-Expense
Some checks failed
Build Docker Image / Build Docker Image (push) Successful in 3m43s
Build Docker Image / Restart Docker Compose (push) Has been cancelled

-Search
This commit is contained in:
x2Skyz
2025-11-25 15:12:38 +07:00
parent 9771fa1360
commit 76d48f895f
6 changed files with 257 additions and 91 deletions

View File

@@ -1,21 +1,112 @@
import { GeneralService } from '../share/generalservice.js'
import { GeneralService } from '../share/generalservice.js';
import { connection } from '../config/db.js'; // ต้อง import connection เพื่อทำ Transaction
import { sendError } from '../utils/response.js';
export class BudgetExpenseService {
constructor() {
this.generalService = new GeneralService()
this.generalService = new GeneralService();
}
// อันนี้ใช้ GeneralService ได้เพราะเป็น Query เดียวจบ
async getBudgetExpense(database, name) {
const sql = `
SELECT
trnseq,
trnprjnam
SELECT trnseq, trnprjnam
FROM ${database}.trnmst
WHERE trnprjnam = $1
`
const params = [name]
`;
const params = [name];
const result = await this.generalService.executeQueryParam(database, sql, params);
return result
return result;
}
// ฟังก์ชันอนุมัติและตัดงบ (Transaction)
async approveBudgetExpense(database, projectSeq, expenseList, user) {
// ⚠️ จำเป็นต้องใช้ client โดยตรงเพื่อคุม Transaction (GeneralService ปกติจะใช้ pool ซึ่งอาจเปลี่ยน connection ระหว่างทางได้)
const client = await connection.connect();
try {
await client.query('BEGIN'); // เริ่ม Transaction
let totalApprovedAmount = 0;
// Format วันที่: YYYYMMDD
const currentDate = new Date().toISOString().slice(0, 10).replace(/-/g, '');
// 1. วนลูปตัดงบและบันทึก Transaction
for (const expense of expenseList) {
// expense: { bdgcod: '33', amount: 5000 }
// [Check 2] เช็คก่อนว่ามีรหัสงบประมาณนี้จริงหรือไม่
const checkBdgSql = `SELECT bdgseq FROM ${database}.bdgmst WHERE bdgcod = $1`;
const checkBdgRes = await client.query(checkBdgSql, [expense.bdgcod]);
if (checkBdgRes.rows.length === 0) {
return sendError(`ไม่พบรหัสงบประมาณ: ${expense.bdgcod} ในระบบ`, `Cannot Find Budget Code ${expense.bdgcod} in System`);
}
// 1.1 หา trnseq ล่าสุด
const seqRes = await client.query(`SELECT COALESCE(MAX(trnseq), 0) + 1 as nextseq FROM ${database}.trnmst`);
const nextTrnSeq = seqRes.rows[0].nextseq;
// 1.2 หาชื่อโครงการ
const prjRes = await client.query(`SELECT prjnam FROM ${database}.prjmst WHERE prjseq = $1`, [projectSeq]);
if (prjRes.rows.length === 0) throw new Error(`Project ${projectSeq} not found`);
const projectName = prjRes.rows[0].prjnam;
// แปลงยอดเงินเป็นทศนิยม 2 ตำแหน่งให้ชัวร์ก่อนบันทึก
const expenseAmount = Number(expense.amount).toFixed(2);
// 1.3 Insert ลง trnmst (บันทึกยอดที่ตัดในรายการนี้)
const sqlTrn = `
INSERT INTO ${database}.trnmst
(trnseq, trnprjnam, trnprjseq, trnexpbdg, trnbdgcod, trncomstt, trnacpdtm)
VALUES ($1, $2, $3, $4, $5, 'BAP', $6)
`;
await client.query(sqlTrn, [
nextTrnSeq,
projectName,
projectSeq,
expenseAmount, //ใช้ค่าที่ format แล้ว
expense.bdgcod,
currentDate
]);
// 1.4 ตัดเงินจากงบประมาณ (bdgmst)
// Postgres จะจัดการลบเลขทศนิยมให้เอง แต่ส่งค่าที่ถูกต้องไปจะดีที่สุด
const sqlUpdateBdg = `
UPDATE ${database}.bdgmst
SET bdgttl = bdgttl - $1,
bdgedtdtm = $2
WHERE bdgcod = $3
`;
await client.query(sqlUpdateBdg, [expenseAmount, currentDate, expense.bdgcod]);
// สะสมยอดรวม (ระวังเรื่องทศนิยมใน JS)
totalApprovedAmount += Number(expense.amount);
}
// 2. อัปเดต Project Master (prjmst)
// Format ยอดรวมให้เป็นทศนิยม 2 ตำแหน่งเป๊ะๆ ก่อนบันทึก (เช่น 45000.00)
const formattedTotal = totalApprovedAmount.toFixed(2);
const sqlUpdatePrj = `
UPDATE ${database}.prjmst
SET prjacpbdg = $1,
prjcomstt = 'BAP',
prjacpdtm = $2
WHERE prjseq = $3
`;
await client.query(sqlUpdatePrj, [formattedTotal, currentDate, projectSeq]);
await client.query('COMMIT'); // ยืนยัน (ทุกอย่างจะถูกบันทึกพร้อมกันเมื่อถึงบรรทัดนี้)
return { status: true, total: totalApprovedAmount };
} catch (error) {
await client.query('ROLLBACK'); // ยกเลิกทั้งหมด (ถ้ามี error ข้อมูลจะกลับไปเหมือนเดิมทุกประการ)
console.error('Transaction Error:', error);
throw error;
} finally {
client.release(); // คืน Connection กลับสู่ Pool
}
}
}

View File

@@ -1,26 +1,46 @@
import { GeneralService } from '../share/generalservice.js'
import { GeneralService } from '../share/generalservice.js';
export class ProjectSearchService {
constructor() {
this.generalService = new GeneralService()
this.generalService = new GeneralService();
}
// 🟢 ฟังก์ชันเดิม (Simple Search) - คืนสภาพเดิมเพื่อไม่ให้กระทบ Service อื่น
// ใช้สำหรับค้นหาข้อมูลในตาราง prjmst อย่างเดียว
async getProjectSearch(database, column, condition) {
const selectCol = column || '*';
const sql = `
SELECT
${column}
SELECT ${selectCol}
FROM ${database}.prjmst
WHERE 1=1
`
const params = []
const result = await this.generalService.executeQueryConditions(database, sql, condition);
return result
`;
return await this.generalService.executeQueryConditions(database, sql, condition);
}
}
// bdgseq,
// bdgnam,
// bdgcod,
// bdgttl,
// bdgedtdtm
// ดึงข้อมูล: ลำดับ, รหัส, ชื่อโครงการ, ผู้รับผิดชอบ, งบขอ, หมวดงบ, งบอนุมัติ, สถานะ
async getProjectDetailSearch(database, column, condition) {
const selectCol = column || `
prjseq,
prjnam,
usrnam,
prjwntbdg,
bdgnam,
prjacpbdg,
prjcomstt,
prjacpdtm
`;
const sql = `
SELECT ${selectCol}
FROM ${database}.prjmst p
LEFT JOIN ${database}.usrmst u ON prjusrseq = usrseq
LEFT JOIN ${database}.bdgmst b ON prjbdgcod = bdgcod
WHERE 1=1
`;
const result = await this.generalService.executeQueryConditions(database, sql, condition);
return result;
}
}