diff --git a/src/controllers/ProfileSalaryTempController.ts b/src/controllers/ProfileSalaryTempController.ts index 40c0003c..6ea1713c 100644 --- a/src/controllers/ProfileSalaryTempController.ts +++ b/src/controllers/ProfileSalaryTempController.ts @@ -38,6 +38,17 @@ import { import { ProfileSalaryBackup } from "../entities/ProfileSalaryBackup"; import { ProfileActposition } from "../entities/ProfileActposition"; import { ProfileAssistance } from "../entities/ProfileAssistance"; + +const SALARY_COMMAND_CODES = { + ACT_POSITION: "17", // รักษาการ + ASSISTANCE: "18", // ช่วยราชการ +} as const; + +class ConfirmDoneSalaryDto { + profileId: string; + type: "OFFICER" | "EMPLOYEE"; +} + @Route("api/v1/org/profile/salaryTemp") @Tags("ProfileSalaryTemp") @Security("bearerAuth") @@ -1013,7 +1024,10 @@ export class ProfileSalaryTempController extends Controller { if (!salary) { throw new HttpError(HttpStatus.BAD_REQUEST, "ไม่พบ profile ดังกล่าว"); } - return new HttpSuccess({ salaryNew: salary, salaryOld: salary.profileSalary }); + return new HttpSuccess({ + salaryNew: salary, + salaryOld: salary.profileSalary, + }); } /** @@ -1242,7 +1256,9 @@ export class ProfileSalaryTempController extends Controller { profile.statusCheckEdit = "PENDING"; await this.profileRepo.save(profile); } else { - const profile = await this.profileEmployeeRepo.findOneBy({ id: body.profileId }); + const profile = await this.profileEmployeeRepo.findOneBy({ + id: body.profileId, + }); if (!profile) { throw new HttpError(HttpStatus.BAD_REQUEST, "ไม่พบ profile ดังกล่าว"); } @@ -1271,7 +1287,9 @@ export class ProfileSalaryTempController extends Controller { profile.statusCheckEdit = "EDITED"; await this.profileRepo.save(profile); } else { - const profile = await this.profileEmployeeRepo.findOneBy({ id: body.profileId }); + const profile = await this.profileEmployeeRepo.findOneBy({ + id: body.profileId, + }); if (!profile) { throw new HttpError(HttpStatus.BAD_REQUEST, "ไม่พบ profile ดังกล่าว"); } @@ -1290,7 +1308,7 @@ export class ProfileSalaryTempController extends Controller { @Post("confirm-done") public async confirmDoneSalary( @Request() req: RequestWithUser, - @Body() body: { profileId: string; type: string }, + @Body() body: ConfirmDoneSalaryDto, ) { const queryRunner = AppDataSource.createQueryRunner(); await queryRunner.connect(); @@ -1303,8 +1321,12 @@ export class ProfileSalaryTempController extends Controller { * 1. Load Profile * ========================= */ const profile = isOfficer - ? await queryRunner.manager.findOne(Profile, { where: { id: body.profileId } }) - : await queryRunner.manager.findOne(ProfileEmployee, { where: { id: body.profileId } }); + ? await queryRunner.manager.findOne(Profile, { + where: { id: body.profileId }, + }) + : await queryRunner.manager.findOne(ProfileEmployee, { + where: { id: body.profileId }, + }); if (!profile) { throw new HttpError(HttpStatus.BAD_REQUEST, "ไม่พบข้อมูล profile"); @@ -1325,24 +1347,26 @@ export class ProfileSalaryTempController extends Controller { } /* ========================= - * 3. Split Update / Insert + * 3. สำรองข้อมูล Temp ไว้ restore ภายหลัง * ========================= */ - // const toUpdate = salaryTemps.filter((t) => t.salaryId && t.isEdit && !t.isDelete); - const backupTemp = salaryTemps; + const originalTempRows = salaryTemps; // เก็บไว้ restore หลัง insert ProfileSalary เสร็จ const toInsert = salaryTemps.filter((t) => !t.isDelete); - // delete profile salary temp + /* ========================= + * 4. ลบข้อมูล ProfileSalaryTemp และ ProfileSalary ปัจจุบัน + * ========================= */ await queryRunner.manager.delete(ProfileSalaryTemp, { ...(isOfficer ? { profileId: body.profileId } : { profileEmployeeId: body.profileId }), }); - // add insert to profile salary backup + // backup profile salary before delete const profileSalaryBeforeDelete = await queryRunner.manager.find(ProfileSalary, { where: { ...(isOfficer ? { profileId: body.profileId } : { profileEmployeeId: body.profileId }), }, }); + // insert ProfileSalary backup to ProfileSalaryBackup if (profileSalaryBeforeDelete.length > 0) { const backupRows = profileSalaryBeforeDelete.map(({ id, ...salary }) => queryRunner.manager.create(ProfileSalaryBackup, { @@ -1358,21 +1382,6 @@ export class ProfileSalaryTempController extends Controller { ...(isOfficer ? { profileId: body.profileId } : { profileEmployeeId: body.profileId }), }); - /* ========================= - * 4. UPDATE - * ========================= */ - // for (const temp of toUpdate) { - // const { id, salaryId, isDelete, isEdit, ...data } = temp; - // await queryRunner.manager.update( - // ProfileSalary, - // { id: salaryId }, - // { - // ...data, - // ...metaUpdate, - // }, - // ); - // } - /* ========================= * 5. INSERT (bulk) * ========================= */ @@ -1387,12 +1396,22 @@ export class ProfileSalaryTempController extends Controller { lastUpdatedAt: dateNow, }; - const salaryRows = toInsert.filter((x) => !["17", "18"].includes(x.commandCode)); - // ส่งไปรักษาการ - const actPositionRows = toInsert.filter((x) => x.commandCode === "17"); - // ส่งไปช่วยราชการ - const assistanceRows = toInsert.filter((x) => x.commandCode === "18"); + // แยกข้อมูลตามประเภทการ insert + const { salaryRows, actPositionRows, assistanceRows } = toInsert.reduce<{ + salaryRows: ProfileSalaryTemp[]; + actPositionRows: ProfileSalaryTemp[]; + assistanceRows: ProfileSalaryTemp[]; + }>( + (acc, x) => { + if (x.commandCode === SALARY_COMMAND_CODES.ACT_POSITION) acc.actPositionRows.push(x); + else if (x.commandCode === SALARY_COMMAND_CODES.ASSISTANCE) acc.assistanceRows.push(x); + else acc.salaryRows.push(x); + return acc; + }, + { salaryRows: [], actPositionRows: [], assistanceRows: [] }, + ); + // Insert ProfileSalary if (salaryRows.length) { await queryRunner.manager.insert( ProfileSalary, @@ -1403,14 +1422,15 @@ export class ProfileSalaryTempController extends Controller { ); } - if (actPositionRows.length > 0) { + // Insert ProfileActposition + if (actPositionRows.length) { await queryRunner.manager.insert( ProfileActposition, actPositionRows.map((x) => ({ profileId: x.profileId, profileEmployeeId: x.profileEmployeeId, dateStart: x.commandDateAffect, - dateEnd: x.commandDateAffect, + dateEnd: null, posNo: x.posNo, position: x.positionName, commandId: x.commandId, @@ -1423,7 +1443,8 @@ export class ProfileSalaryTempController extends Controller { ); } - if (assistanceRows.length > 0) { + // Insert ProfileAssistance + if (assistanceRows.length) { await queryRunner.manager.insert( ProfileAssistance, assistanceRows.map((x) => ({ @@ -1431,7 +1452,7 @@ export class ProfileSalaryTempController extends Controller { profileEmployeeId: x.profileEmployeeId, agency: x.orgRoot, dateStart: x.commandDateAffect, - dateEnd: x.commandDateAffect, + dateEnd: null, commandId: x.commandId, commandNo: x.commandNo, commandName: x.commandName, @@ -1445,14 +1466,17 @@ export class ProfileSalaryTempController extends Controller { } } - // insert profile salary temp new - if (backupTemp.length > 0) { - const insertBackupTemp = toInsert.map(({ id, ...data }) => ({ - ...data, - salaryId: null, - })); - - await queryRunner.manager.insert(ProfileSalaryTemp, insertBackupTemp); + /* ========================= + * Restore ProfileSalaryTemp (หลังจาก ProfileSalary insert เรียบร้อยแล้ว) + * ========================= */ + if (originalTempRows.length > 0) { + await queryRunner.manager.insert( + ProfileSalaryTemp, + originalTempRows.map(({ id, ...data }) => ({ + ...data, + salaryId: null, + })), + ); } await queryRunner.commitTransaction(); @@ -1547,7 +1571,9 @@ export class ProfileSalaryTempController extends Controller { salaryId: string, @Request() req: RequestWithUser, ) { - const source_item = await this.salaryRepo.findOne({ where: { id: salaryId } }); + const source_item = await this.salaryRepo.findOne({ + where: { id: salaryId }, + }); // if (source_item) { //await new permission().PermissionOrgUserGet(req,"SYS_REGISTRY_OFFICER",source_item.profileId,); //ไม่แน่ใจOFFปิดไว้ก่อน // } @@ -1555,7 +1581,10 @@ export class ProfileSalaryTempController extends Controller { const sourceOrder = source_item.order; if (direction.trim().toUpperCase() == "UP") { const dest_item = await this.salaryRepo.findOne({ - where: { profileId: source_item.profileId, order: LessThan(sourceOrder) }, + where: { + profileId: source_item.profileId, + order: LessThan(sourceOrder), + }, order: { order: "DESC" }, }); if (dest_item == null) return new HttpSuccess(); @@ -1567,7 +1596,10 @@ export class ProfileSalaryTempController extends Controller { await Promise.all([this.salaryRepo.save(source_item), this.salaryRepo.save(dest_item)]); } else { const dest_item = await this.salaryRepo.findOne({ - where: { profileId: source_item.profileId, order: MoreThan(sourceOrder) }, + where: { + profileId: source_item.profileId, + order: MoreThan(sourceOrder), + }, order: { order: "ASC" }, }); if (dest_item == null) return new HttpSuccess(); @@ -1598,7 +1630,9 @@ export class ProfileSalaryTempController extends Controller { profile = await this.profileRepo.findOneBy({ id: profileId }); if (!profile) { - profileEmployee = await this.profileEmployeeRepo.findOneBy({ id: profileId }); + profileEmployee = await this.profileEmployeeRepo.findOneBy({ + id: profileId, + }); if (!profileEmployee) { throw new HttpError(HttpStatus.NOT_FOUND, "ไม่พบข้อมูล"); } diff --git a/src/entities/ProfileActposition.ts b/src/entities/ProfileActposition.ts index 4d20c0d8..bde07e30 100644 --- a/src/entities/ProfileActposition.ts +++ b/src/entities/ProfileActposition.ts @@ -29,7 +29,7 @@ export class ProfileActposition extends EntityBase { comment: "วันที่สิ้นสุด", default: null, }) - dateEnd: Date; + dateEnd: Date | null; @Column({ nullable: true, diff --git a/src/entities/ProfileAssistance.ts b/src/entities/ProfileAssistance.ts index 568552c0..ad01f585 100644 --- a/src/entities/ProfileAssistance.ts +++ b/src/entities/ProfileAssistance.ts @@ -43,7 +43,7 @@ export class ProfileAssistance extends EntityBase { comment: "วันสิ้นสุดการช่วยราชการ", default: null, }) - dateEnd: Date; + dateEnd: Date | null; @Column({ nullable: true,