revert
Some checks failed
release / release (push) Failing after 8s

This commit is contained in:
Adisak 2025-11-28 17:59:44 +07:00
parent aeecbd8ae9
commit 3aeb893d55

View file

@ -1209,8 +1209,8 @@ export class SalaryPeriodController extends Controller {
* @param {string} id profile Id * @param {string} id profile Id
* @param {string} type NONE-> HAFT-> FULL->1 FULLHAFT->1.5 * @param {string} type NONE-> HAFT-> FULL->1 FULLHAFT->1.5
*/ */
@Post("oldchange/type-multi") @Post("change/type-multi")
async oldchangeTypeMulti( async changeTypeMulti(
@Body() body: { profileId: string[]; type: string; isReserve: boolean; remark?: string | null }, @Body() body: { profileId: string[]; type: string; isReserve: boolean; remark?: string | null },
@Request() req: RequestWithUser, @Request() req: RequestWithUser,
) { ) {
@ -1545,8 +1545,8 @@ export class SalaryPeriodController extends Controller {
} }
//NEW CHANGE TYPE-MULTI //NEW CHANGE TYPE-MULTI
@Post("change/type-multi") @Post("newchange/type-multi")
async changeTypeMulti( async newchangeTypeMulti(
@Body() body: { profileId: string[]; type: string; isReserve: boolean; remark?: string | null }, @Body() body: { profileId: string[]; type: string; isReserve: boolean; remark?: string | null },
@Request() req: RequestWithUser, @Request() req: RequestWithUser,
) { ) {
@ -1572,28 +1572,25 @@ export class SalaryPeriodController extends Controller {
const salaries = await this.salaryRepository.find({ where: { isActive: true } }); const salaries = await this.salaryRepository.find({ where: { isActive: true } });
const salaryRanks = await this.salaryRankRepository.find(); const salaryRanks = await this.salaryRankRepository.find();
// Map lookup
const posTypeMap = new Map(posTypes.map(x => [x.posTypeName, x])); const posTypeMap = new Map(posTypes.map(x => [x.posTypeName, x]));
const posLevelMap = new Map(posLevels.map(x => [`${x.posTypeId}|${x.posLevelName}`, x])); const posLevelMap = new Map(posLevels.map(x => [`${x.posTypeId}|${x.posLevelName}`, x]));
const salaryMap = new Map( const salaryMap = new Map(
salaries.map(x => [`${x.posTypeId}|${x.posLevelId}|${x.isSpecial ? 1 : 0}`, x]), salaries.map(x => [`${x.posTypeId}|${x.posLevelId}|${x.isSpecial ? 1 : 0}`, x]),
); );
const ranksBySalaryId = salaryRanks.reduce((acc, r: any) => { const ranksBySalaryId = salaryRanks.reduce((acc, r: any) => {
if (!acc[r.salaryId]) acc[r.salaryId] = []; if (!acc[r.salaryId]) acc[r.salaryId] = [];
acc[r.salaryId].push(r); acc[r.salaryId].push(r);
return acc; return acc;
}, {} as Record<number, SalaryRanks[]>); }, {} as Record<number, SalaryRanks[]>);
// -----------------------------
// 3) Loop profiles
// -----------------------------
const profilesToSave: SalaryProfile[] = []; const profilesToSave: SalaryProfile[] = [];
const orgNeedRecalc = new Set<string>(); const orgNeedRecalc = new Set<string>();
for (const profile of salaryProfiles) { for (const profile of salaryProfiles) {
const bodyType = body.type?.toUpperCase() ?? profile.type; const bodyType = body.type?.toUpperCase() ?? profile.type;
// --- ตรวจ FULLHAFT → หา APR snapshot2 (เหมือนเดิม) --- // --- ตรวจ FULLHAFT → หา APR snapshot2 ---
if (bodyType === "FULLHAFT" && profile.salaryOrg.salaryPeriod.period === "OCT") { if (bodyType === "FULLHAFT" && profile.salaryOrg.salaryPeriod.period === "OCT") {
const checkPrev = await this.salaryProfileRepository.findOne({ const checkPrev = await this.salaryProfileRepository.findOne({
relations: ["salaryOrg", "salaryOrg.salaryPeriod"], relations: ["salaryOrg", "salaryOrg.salaryPeriod"],
@ -1612,11 +1609,6 @@ export class SalaryPeriodController extends Controller {
} }
} }
// reserve & remark
profile.type = bodyType;
profile.isReserve = bodyType === "FULL" ? body.isReserve : false;
profile.remark = body.remark ?? "";
// --- apply posType/posLevel/salary --- // --- apply posType/posLevel/salary ---
const posType = posTypeMap.get(profile.posType); const posType = posTypeMap.get(profile.posType);
if (!posType) throw new HttpError(404, "ไม่พบประเภทตำแหน่ง"); if (!posType) throw new HttpError(404, "ไม่พบประเภทตำแหน่ง");
@ -1630,13 +1622,11 @@ export class SalaryPeriodController extends Controller {
const salaryId = Number(salaryBase.id); const salaryId = Number(salaryBase.id);
const ranks = ranksBySalaryId[salaryId] ?? []; const ranks = ranksBySalaryId[salaryId] ?? [];
// --- หา rank --- // --- หา rank ตาม amount ก่อน dynamic type adjustment ---
let rank: SalaryRanks | null = null; let rank: SalaryRanks | null = null;
if (profile.amount != null) { if (profile.amount != null) {
const amount = profile.amount; const amount = profile.amount;
// หา rank ที่ใช้ type เดิม (เหมือนเดิม)
const possible = ranks const possible = ranks
.filter((r: any) => r.salary >= amount && !r.isNext) .filter((r: any) => r.salary >= amount && !r.isNext)
.sort((a: any, b: any) => a.salary - b.salary); .sort((a: any, b: any) => a.salary - b.salary);
@ -1648,59 +1638,57 @@ export class SalaryPeriodController extends Controller {
.sort((a: any, b: any) => a.salary - b.salary); .sort((a: any, b: any) => a.salary - b.salary);
rank = next[0] ?? null; rank = next[0] ?? null;
} }
}
// --- FULLHAFT dynamic type adjustment (เหมือนเดิม) --- // --- คำนวณเงินเดือนตาม rank เดิมก่อน dynamic type adjustment ---
if (bodyType === "FULLHAFT" && rank) { const calc = (sp: keyof SalaryRanks, next: keyof SalaryRanks) => ({
const halfSpecial = rank.salaryHalfSpecial ?? 0; amountSpecial: rank?.[sp] ?? 0,
const fullSpecial = rank.salaryFullSpecial ?? 0; amountUse: profile.amount != null && rank?.[next] != null
const fullHalfSpecial = rank.salaryFullHalfSpecial ?? 0; ? Number(rank[next]) - Number(profile.amount)
: 0,
positionSalaryAmount: rank?.[next] ?? 0,
isNext: rank?.isNext ?? 0
});
if (fullHalfSpecial > 0) { // --- FULLHAFT dynamic type adjustment หลังคำนวณเงินเดือน ---
if (fullSpecial === 0) profile.type = "HAFT"; let finalType = bodyType;
else if (halfSpecial === 0) profile.type = "FULL"; if (bodyType === "FULLHAFT" && rank) {
else profile.type = "FULLHAFT"; const halfSpecial = rank.salaryHalfSpecial ?? 0;
} const fullSpecial = rank.salaryFullSpecial ?? 0;
const fullHalfSpecial = rank.salaryFullHalfSpecial ?? 0;
if (fullHalfSpecial > 0) {
if (fullSpecial === 0) finalType = "HAFT";
else if (halfSpecial === 0) finalType = "FULL";
else finalType = "FULLHAFT";
} }
} }
// --- คำนวณเงินเดือน (logic เหมือนเดิม) --- profile.type = finalType;
const calc = (sp: keyof SalaryRanks, next: keyof SalaryRanks) => { profile.isReserve = finalType === "FULL" ? body.isReserve : false;
const amountNext = rank?.[next] ?? 0; profile.remark = body.remark ?? "";
return {
amountSpecial: rank?.[sp] ?? 0,
amountUse: profile.amount != null ? Number(amountNext) - Number(profile.amount) : 0,
positionSalaryAmount: amountNext,
isNext: rank?.isNext ?? 0,
};
};
switch (profile.type) { if (finalType === "NONE") {
case "NONE": profile.amountSpecial = 0;
profile.amountSpecial = 0; profile.amountUse = 0;
profile.amountUse = 0; profile.positionSalaryAmount = profile.amount ?? 0;
profile.positionSalaryAmount = profile.amount ?? 0; } else if (finalType === "PENDING") {
break; profile.amountSpecial = 0;
case "PENDING": profile.amountUse = 0;
profile.amountSpecial = 0; profile.positionSalaryAmount = 0;
profile.amountUse = 0; } else if (finalType === "HAFT") {
profile.positionSalaryAmount = 0; Object.assign(profile, calc("salaryHalfSpecial", "salaryHalf"));
break; } else if (finalType === "FULL") {
case "HAFT": Object.assign(profile, calc("salaryFullSpecial", "salaryFull"));
Object.assign(profile, calc("salaryHalfSpecial", "salaryHalf")); } else if (finalType === "FULLHAFT") {
break; Object.assign(profile, calc("salaryFullHalfSpecial", "salaryFullHalf"));
case "FULL":
Object.assign(profile, calc("salaryFullSpecial", "salaryFull"));
break;
case "FULLHAFT":
Object.assign(profile, calc("salaryFullHalfSpecial", "salaryFullHalf"));
break;
} }
profile.lastUpdateUserId = req.user.sub; profile.lastUpdateUserId = req.user.sub;
profile.lastUpdateFullName = req.user.name; profile.lastUpdateFullName = req.user.name;
profile.lastUpdatedAt = new Date(); profile.lastUpdatedAt = new Date();
// --- log diff (เหมือนเดิม) --- // --- log diff ---
const before = structuredClone(profile); const before = structuredClone(profile);
profilesToSave.push(profile); profilesToSave.push(profile);
setLogDataDiff(req, { before, after: profile }); setLogDataDiff(req, { before, after: profile });
@ -1714,7 +1702,7 @@ export class SalaryPeriodController extends Controller {
await this.salaryProfileRepository.save(profilesToSave); await this.salaryProfileRepository.save(profilesToSave);
// ----------------------------- // -----------------------------
// 5) Recalculate SalaryOrg (คง logic เดิม) // 5) Recalculate SalaryOrg
// ----------------------------- // -----------------------------
for (const orgId of orgNeedRecalc) { for (const orgId of orgNeedRecalc) {
const org = await this.salaryOrgRepository.findOne({ const org = await this.salaryOrgRepository.findOne({
@ -1747,7 +1735,7 @@ export class SalaryPeriodController extends Controller {
org.useAmount = useAmount; org.useAmount = useAmount;
org.remainingAmount = org.sixPercentAmount - useAmount; org.remainingAmount = org.sixPercentAmount - useAmount;
// --- SNAP2 APR recalc (เหมือนเดิม) --- // --- SNAP2 APR recalc ---
const salaryPeriodAPROld = await this.salaryPeriodRepository.findOne({ const salaryPeriodAPROld = await this.salaryPeriodRepository.findOne({
where: { period: "APR", year: org.salaryPeriod.year } where: { period: "APR", year: org.salaryPeriod.year }
}); });
@ -1778,6 +1766,7 @@ export class SalaryPeriodController extends Controller {
/** /**
* API * API
* *