diff --git a/exthernal-accountingwep-api/src/app.js b/exthernal-accountingwep-api/src/app.js index 48ea973..1dfb6db 100644 --- a/exthernal-accountingwep-api/src/app.js +++ b/exthernal-accountingwep-api/src/app.js @@ -25,7 +25,7 @@ app.use((err, req, res, next) => { next() }) -app.use('/api', router) +app.use('/api/web', router) app.listen(process.env.PORT, () => { console.log(`✅ ${process.env.PJ_NAME} running on port ${process.env.PORT}`) diff --git a/exthernal-accountingwep-api/src/controllers/accountingSetup.js b/exthernal-accountingwep-api/src/controllers/accountingSetup.js index aa7eb32..8e4a3fb 100644 --- a/exthernal-accountingwep-api/src/controllers/accountingSetup.js +++ b/exthernal-accountingwep-api/src/controllers/accountingSetup.js @@ -1,4 +1,4 @@ -import { LoginService } from '../services/loginservice.js' +import { AccountingSetupService } from '../services/accountingSetupService.js' import { sendError } from '../utils/response.js' // import { OftenError } from '../utils/oftenError.js' import { GeneralService } from '../share/generalservice.js'; @@ -9,7 +9,7 @@ export class accountingSetup { constructor() { this.generalService = new GeneralService(); - this.loginService = new LoginService(); + this.AccountingSetupService = new AccountingSetupService(); } async onNavigate(req, res) { @@ -23,18 +23,23 @@ export class accountingSetup { let idx = -1 let result = [] try { - let username = req.body.request.username; - let password = req.body.request.password; + // let username = req.body.request.username; + // let password = req.body.request.password; - result = await this.loginService.verifyLogin(database, username, password); // เช็คกับ db กลาง ส่ง jwttoken ออกมา + result = await this.AccountingSetupService.getAccountingSetup(database); // เช็คกับ db กลาง ส่ง jwttoken ออกมา // this.generalService.devhint(1, 'accountingSetup.js', 'Login success'); } catch (error) { idx = 1; } finally { if (idx === 1) return sendError('เกิดข้อผิดพลาดไม่คาดคิดเกิดขึ้น', 'Unexpected error'); if (!result) return sendError('ชื่อผู้ใช้หรือรหัสผ่านไม่ถูกต้อง', 'Invalid credentials'); - if(result) { return result } - return null + // แยกกลุ่ม income / expense + let income = result.filter(item => item.dtltblcod === 'ACTCAT_INC').map(({ dtltblcod, ...rest }) => rest); + + let expense = result.filter(item => item.dtltblcod === 'ACTCAT_EXP').map(({ dtltblcod, ...rest }) => rest); + + let arydiy = { income , expense }; + return arydiy } } } diff --git a/exthernal-accountingwep-api/src/routes/route.js b/exthernal-accountingwep-api/src/routes/route.js index dc61da5..e2bfc80 100644 --- a/exthernal-accountingwep-api/src/routes/route.js +++ b/exthernal-accountingwep-api/src/routes/route.js @@ -1,19 +1,15 @@ import express from 'express' -// import { loginController } from '../controllers/logincontroller.js' +import { accountingSetup } from '../controllers/accountingSetup.js' // import { authMiddleware } from '../middlewares/auth.js' // import { sendResponse } from '../utils/response.js' const router = express.Router() -// const controller_login_post = new loginController() +const controller_accountingSetup_post = new accountingSetup() -// =================================================== -// 🔹 LOGIN ปกติ -// =================================================== -// router.post('/login', async (req, res) => { -// const data = await controller_login_post.onNavigate(req, res) -// if (data) -// return sendResponse(res, 200, 'เข้าสู่ระบบสำเร็จ', 'Login success', data) -// }) +router.post('/accountingSetup', async (req, res) => { + const result = await controller_accountingSetup_post.onNavigate(req, res) + if (result) return res.json(result) +}) // // =================================================== // // 🔹 BIOMETRIC LOGIN diff --git a/exthernal-accountingwep-api/src/services/accountingSetupService.js b/exthernal-accountingwep-api/src/services/accountingSetupService.js new file mode 100644 index 0000000..a3aba89 --- /dev/null +++ b/exthernal-accountingwep-api/src/services/accountingSetupService.js @@ -0,0 +1,27 @@ +import { GeneralService } from '../share/generalservice.js' + +export class AccountingSetupService { + constructor() { + this.generalService = new GeneralService() + } + async getAccountingSetup(database) { + const sql = ` + SELECT + dtlnam, + dtlcod, + dtltblcod + FROM ${database}.dtlmst + WHERE dtltblcod IN ('ACTTYP', 'ACTCAT_INC', 'ACTCAT_EXP'); + ` + const params = [] + const result = await this.generalService.executeQueryParam(database, sql, params); + return result + } +} + + + // SELECT + // acttyp, + // dtlname + // FROM ${database}.actmst + // LEFT JOIN ${database}.dtlmst ON dtltblcod = 'acttyp' and acttyp = dtlcod \ No newline at end of file diff --git a/exthernal-accountingwep-api/src/services/loginservice.js b/exthernal-accountingwep-api/src/services/loginservice.js deleted file mode 100644 index 8f355f5..0000000 --- a/exthernal-accountingwep-api/src/services/loginservice.js +++ /dev/null @@ -1,106 +0,0 @@ -import bcrypt from 'bcrypt' -import { GeneralService } from '../share/generalservice.js' -import { generateToken } from '../utils/token.js' - -export class LoginService { - constructor() { - this.generalService = new GeneralService() - } - async verifyLogin(database, username, password) { - this.generalService.devhint(2, 'loginservice.js', `verifyLogin() start for username=${username}`) - - let user = null - let token = null - - let sql = ` - SELECT usrseq, usrnam, usrorg, usrrol, usrpwd, usrthinam, usrthilstnam - FROM nuttakit.usrmst - WHERE usrnam = $1 - ` - let params = [username] - const rows = await this.generalService.executeQueryParam(database, sql, params) - this.generalService.devhint(3, 'loginservice.js', `query done, found=${rows.length}`) - - if (rows.length === 0) { - this.generalService.devhint(2, 'loginservice.js', 'no user found') - return null - } - - user = rows[0] - const match = await bcrypt.compare(password, user.usrpwd) - if (match === false) { - this.generalService.devhint(2, 'loginservice.js', 'password mismatch') - return null - } - - token = generateToken({ - id: user.usrseq, - name: user.usrnam, - realname: user.usrthinam, - lastname: user.usrthilstnam, - role: user.usrrol, - organization: user.usrorg - }) - this.generalService.devhint(2, 'loginservice.js', 'token generated successfully') - - - delete user.usrseq - delete user.usrnam - delete user.usrrol - delete user.usrpwd - delete user.usrorg - return { - token, - ...user - } - } - - async loginWithBiometric(database, biometric_id) { - this.generalService.devhint(2, 'loginservice.js', `loginWithBiometric() start for biometric_id=${biometric_id}`) - - let sql = '' - let params = [] - - sql = ` - SELECT usrid, usrnam, usrrol - FROM ${database}.usrmst - WHERE biometric_id = $1 - ` - params = [biometric_id] - const rows = await this.generalService.executeQueryParam(database, sql, params) - if (rows.length === 0) { - this.generalService.devhint(2, 'loginservice.js', 'no biometric found') - return null - } - - const user = rows[0] - const token = generateToken({ - id: user.usrid, - name: user.usrnam, - role: user.usrrol, - organization: database - }) - - this.generalService.devhint(2, 'loginservice.js', 'biometric token generated') - return { token, user } - } - - async registerBiometric(database, usrid, biometric_id) { - this.generalService.devhint(2, 'loginservice.js', `registerBiometric() start user=${usrid}`) - - - let sql = '' - let params = [] - - sql = ` - UPDATE ${database}.usrmst - SET biometric_id = $1 - WHERE usrid = $2 - ` - params = [biometric_id, usrid] - await this.generalService.executeQueryParam(database, sql, params) - - this.generalService.devhint(2, 'loginservice.js', 'biometric registered') - return { message: 'Biometric registered successfully' } - } -} diff --git a/exthernal-accountingwep-api/src/services/otpservice.js b/exthernal-accountingwep-api/src/services/otpservice.js deleted file mode 100644 index 4ce4834..0000000 --- a/exthernal-accountingwep-api/src/services/otpservice.js +++ /dev/null @@ -1,17 +0,0 @@ -import { generateOTP } from '../utils/otp.js' -import { sendMockOtpMail } from '../utils/mailer.js' -import { saveOtp, verifyOtp, removeOtp } from '../utils/redis.js' -import { sendError } from '../utils/response.js' - -export class OtpService { - async sendOtp(email) { - try { - const otp = generateOTP() - await saveOtp(email, otp) - await sendMockOtpMail(email, otp) - return { email, otp} - } catch (error) { - return sendError('ไม่สามารถส่ง OTP ได้', 'Failed to send OTP') - } - } -} diff --git a/exthernal-accountingwep-api/src/services/otpverifyservice.js b/exthernal-accountingwep-api/src/services/otpverifyservice.js deleted file mode 100644 index 7bf59f6..0000000 --- a/exthernal-accountingwep-api/src/services/otpverifyservice.js +++ /dev/null @@ -1,29 +0,0 @@ -import Redis from 'ioredis'; -import crypto from 'crypto'; -import { sendError } from '../utils/response.js'; -import { GeneralService } from '../share/generalservice.js'; - -export class OTPVerifyService { - constructor() { - this.redis = new Redis(); - this.generalService = new GeneralService(); - } - - async verifyOtp(email, otp) { - const storedOtp = await this.redis.get(`otp:${email}`); - if (!storedOtp || storedOtp !== otp) { - throw sendError('รหัส OTP ไม่ถูกต้องหรือหมดอายุ', 'Invalid OTP'); - } - - await this.redis.del(`otp:${email}`); - - const resetToken = crypto.randomBytes(32).toString('hex'); - await this.redis.set(`reset:${email}`, resetToken, 'EX', 600); // TTL 10 นาที - - this.generalService.devhint(1, 'otpverifyservice.js', `OTP Verified → Reset Token issued (${email})`); - - return { - resetToken:resetToken - }; - } -} diff --git a/exthernal-accountingwep-api/src/services/registerservice.js b/exthernal-accountingwep-api/src/services/registerservice.js deleted file mode 100644 index 2b93131..0000000 --- a/exthernal-accountingwep-api/src/services/registerservice.js +++ /dev/null @@ -1,88 +0,0 @@ -import Redis from 'ioredis'; -import bcrypt from 'bcrypt'; -import crypto from 'crypto'; -import nodemailer from 'nodemailer'; -import { GeneralService } from '../share/generalservice.js'; -import { sendError } from '../utils/response.js'; - -export class RegisterService { - - constructor() { - this.redis = new Redis(); - this.generalService = new GeneralService(); - } - - async requestRegistration(database, email, fname, lname, password) { - let result = []; - try { - let sql = ` - SELECT usrseq FROM ${database}.usrmst WHERE usrnam = $1 - `; - let param = [email]; - const userCheck = await this.generalService.executeQueryParam(database, sql, param); - - if (userCheck.length > 0) { - this.generalService.devhint(1, 'registerservice.js', `❌ Duplicate email (${email})`); - throw sendError('อีเมลนี้ถูกใช้แล้ว', 'Email already registered'); - } - - const hashedPwd = await bcrypt.hash(password, 10); - const token = crypto.randomBytes(32).toString('hex'); - - - const payload = JSON.stringify({ fname, lname, hashedPwd, token, database }); - await this.redis.set(`verify:${email}`, payload, 'EX', 86400); // 24h - - - const verifyUrl = `http://localhost:1012/login/verify-email?token=${token}&email=${encodeURIComponent(email)}&organization=${database}`; - await this.sendVerifyEmail(email, verifyUrl); - - this.generalService.devhint(2, 'registerservice.js', `✅ Verify link sent to ${email}`); - - result = { - code: '200', - message_th: 'ส่งลิงก์ยืนยันอีเมลแล้ว', - data: {} - }; - } catch (error) { - this.generalService.devhint(1, 'registerservice.js', '❌ Registration Error', error.message); - throw error; - } - return result; - } - - async sendVerifyEmail(email, verifyUrl) { - try { - const transporter = nodemailer.createTransport({ - service: 'gmail', - auth: { - user: process.env.SMTP_USER, - pass: process.env.SMTP_PASS, - }, - }); - - const html = ` -
-

ยืนยันการสมัครสมาชิก

-

กรุณากดยืนยันภายใน 24 ชั่วโมง เพื่อเปิดใช้งานบัญชีของคุณ

- ยืนยันอีเมล -

หากคุณไม่ได้สมัคร โปรดละเว้นอีเมลนี้

-
- `; - - await transporter.sendMail({ - from: `"System" <${process.env.SMTP_USER}>`, - to: email, - subject: '📩 ยืนยันอีเมลสำหรับสมัครสมาชิก', - html, - }); - - this.generalService.devhint(2, 'registerservice.js', `📤 Verification email sent (${email})`); - } catch (error) { - this.generalService.devhint(1, 'registerservice.js', '❌ Email Send Failed', error.message); - throw sendError('ไม่สามารถส่งอีเมลได้', 'Email send failed'); - } - } -} diff --git a/exthernal-accountingwep-api/src/services/resetpasswordservice.js b/exthernal-accountingwep-api/src/services/resetpasswordservice.js deleted file mode 100644 index bfaecfd..0000000 --- a/exthernal-accountingwep-api/src/services/resetpasswordservice.js +++ /dev/null @@ -1,38 +0,0 @@ -import Redis from 'ioredis'; -import bcrypt from 'bcrypt'; -import { sendError } from '../utils/response.js'; -import { GeneralService } from '../share/generalservice.js'; - -export class ResetPasswordService { - constructor() { - this.redis = new Redis(); - this.generalService = new GeneralService(); - } - - async resetPassword(email, token, newPassword) { - let database = ''; - - const storedToken = await this.redis.get(`reset:${email}`); - if (!storedToken || storedToken !== token) { - throw sendError('Token ไม่ถูกต้องหรือหมดอายุ', 'Invalid or expired token'); - } - - await this.redis.del(`reset:${email}`); - - // อัปเดตรหัสผ่านในฐานข้อมูลจริง - const hashedPwd = await bcrypt.hash(newPassword, 10); - let sql = ` - UPDATE usrmst SET usrpwd = $1 WHERE usrnam = $2 - ` - let param = [hashedPwd, email]; - await this.generalService.executeQueryParam(database, sql, param); - - this.generalService.devhint(1, 'resetpasswordservice.js', `Password reset successful (${email})`); - - return { - code: '200', - message: 'successful', - message_th: 'รีเซ็ตรหัสผ่านสำเร็จ' - }; - } -} diff --git a/exthernal-accountingwep-api/src/services/userservice.js b/exthernal-accountingwep-api/src/services/userservice.js deleted file mode 100644 index d2fbcc9..0000000 --- a/exthernal-accountingwep-api/src/services/userservice.js +++ /dev/null @@ -1,16 +0,0 @@ -import { executeQueryParam } from '../share/generalservice.js' - -export class userservice { - constructor() { - this.generalService = new GeneralService() - } - async createUser(database, usrnam, usreml) { - const sql = ` - SELECT * FROM ${database}.usrmst - WHERE usrnam = $1 OR usreml = $2 - ` - const params = [usrnam, usreml] - const result = await executeQueryParam(sql, database, params) - return result - } -} diff --git a/exthernal-accountingwep-api/src/services/verifyemailservice.js b/exthernal-accountingwep-api/src/services/verifyemailservice.js deleted file mode 100644 index 02a05f5..0000000 --- a/exthernal-accountingwep-api/src/services/verifyemailservice.js +++ /dev/null @@ -1,66 +0,0 @@ -import Redis from 'ioredis'; -import { GeneralService } from '../share/generalservice.js'; -import { sendError } from '../utils/response.js'; - -export class VerifyEmailService { - constructor() { - this.redis = new Redis(); - this.generalService = new GeneralService(); - } - - async verifyAndCreate({ email, token, schema = 'nuttakit' }) { - // ✅ STEP 1: โหลด payload จาก Redis - const key = `verify:${email}`; - const stored = await this.redis.get(key); - if (!stored) { - throw sendError('ลิงก์หมดอายุหรือไม่ถูกต้อง', 'Verification link expired or invalid', 400); - } - - let parsed; - try { - parsed = JSON.parse(stored); - } catch (ex) { - await this.redis.del(key).catch(() => {}); - throw sendError('ข้อมูลการยืนยันไม่ถูกต้อง', 'Invalid verify payload', 400); - } - - // ✅ STEP 2: ตรวจสอบ token - if (parsed.token !== token) { - throw sendError('Token ไม่ถูกต้อง', 'Invalid token', 400); - } - - // ✅ STEP 3: ตรวจสอบว่าอีเมลนี้เคยถูกสร้างใน schema แล้วหรือยัง - const checkSql = ` - SELECT usrseq FROM \${database}.usrmst WHERE usrnam = $1 - `; - const checkResult = await this.generalService.executeQueryParam(schema, checkSql, [email]); - - if (checkResult && checkResult.length > 0) { - await this.redis.del(key).catch(() => {}); - throw sendError('อีเมลนี้ถูกใช้แล้วในองค์กรนี้', 'Email already registered in this organization', 400); - } - - // ✅ STEP 4: Insert ข้อมูลลงในตารางจริง - const insertSql = ` - INSERT INTO ${database}.usrmst (usrnam, usrthinam, usrthilstnam, usrpwd, usrrol) - VALUES ($1, $2, $3, $4, 'U') - `; - const params = [email, parsed.fname, parsed.lname, parsed.hashedPwd]; - await this.generalService.executeQueryParam(schema, insertSql, params); - - // ✅ STEP 5: ลบ Redis Key (เคลียร์ payload) - await this.redis.del(key).catch(() => {}); - - this.generalService.devhint(2, 'verifyemailservice.js', `✅ Account verified (${email})`); - - // ✅ STEP 6: ส่งผลลัพธ์กลับ - return { - code: '200', - message_th: 'ยืนยันอีเมลสำเร็จ บัญชีถูกสร้างแล้ว', - data: { - email, - schema, - }, - }; - } -}