cronjob ส่งข้อมูลผู้เกษียณไปให้ระบบพ้นราชการ #2330
All checks were successful
Build & Deploy on Dev / build (push) Successful in 1m17s
All checks were successful
Build & Deploy on Dev / build (push) Successful in 1m17s
This commit is contained in:
parent
e6c3e80a3d
commit
93d4857ea1
4 changed files with 175 additions and 12 deletions
133
src/services/RetirementService.ts
Normal file
133
src/services/RetirementService.ts
Normal file
|
|
@ -0,0 +1,133 @@
|
|||
import { AppDataSource } from "../database/data-source";
|
||||
import { Profile } from "../entities/Profile";
|
||||
import { PostRetireToExprofile } from "../controllers/ExRetirementController";
|
||||
import { Between, MoreThanOrEqual } from "typeorm";
|
||||
|
||||
const BATCH_SIZE = 100;
|
||||
const CONCURRENT_PER_BATCH = 10; // ส่ง parallel ทีละ 10 คนในแต่ละ batch
|
||||
|
||||
export class RetirementService {
|
||||
private profileRepository = AppDataSource.getRepository(Profile);
|
||||
|
||||
/**
|
||||
* Cronjob สำหรับส่งข้อมูลผู้เกษียณไปยังระบบพ้นราชการ (Exprofile)
|
||||
* ทำงานเวลา 04:30:00 ของทุกวันที่ 1 ตุลาคม
|
||||
*
|
||||
* รายละเอียด:
|
||||
* - Query profiles ที่ leaveDate = วันที่ 1 ตุลาคมของปีนั้น และ leaveType = "RETIRE"
|
||||
* - Batch ทีละ 100 records
|
||||
* - Concurrent ทีละ 10 คน (parallel) ในแต่ละ batch
|
||||
* - ถ้า fail ให้ log error แล้วทำคนต่อไป
|
||||
*/
|
||||
async cronjobPostRetireToExprofile(): Promise<{
|
||||
success: number;
|
||||
failed: number;
|
||||
failedProfiles: Array<{ id: string; name: string; error: string }>;
|
||||
}> {
|
||||
const result = {
|
||||
success: 0,
|
||||
failed: 0,
|
||||
failedProfiles: [] as Array<{ id: string; name: string; error: string }>,
|
||||
};
|
||||
|
||||
try {
|
||||
|
||||
// หาวันที่ 1 ตุลาคมของปีปัจจุบัน
|
||||
const now = new Date();
|
||||
const currentYear = now.getFullYear();
|
||||
|
||||
// สร้างวันที่ 1 ตุลาคมของปีปัจจุบัน (เวลา 00:00:00)
|
||||
const startDate = new Date(currentYear, 9, 1, 0, 0, 0); // Month 9 = October (0-indexed)
|
||||
const endDate = new Date(currentYear, 9, 1, 23, 59, 59);
|
||||
|
||||
// Query profiles ที่ leaveDate อยู่ในวันที่ 1 ตุลาคม และ leaveType = "RETIRE"
|
||||
const profiles = await this.profileRepository.find({
|
||||
where: [
|
||||
{ leaveDate: Between(startDate, endDate), leaveType: "RETIRE" as any },
|
||||
{ leaveDate: MoreThanOrEqual(startDate), leaveType: "RETIRE" as any },
|
||||
],
|
||||
relations: ["posLevel", "posType"],
|
||||
});
|
||||
|
||||
// Filter เอาเฉพาะวันที่ 1 ตุลาคมเท่านั้น
|
||||
const filteredProfiles = profiles.filter(p => {
|
||||
if (!p.leaveDate) return false;
|
||||
const leaveDate = new Date(p.leaveDate);
|
||||
return (
|
||||
leaveDate.getFullYear() === currentYear &&
|
||||
leaveDate.getMonth() === 9 && // October
|
||||
leaveDate.getDate() === 1
|
||||
);
|
||||
});
|
||||
|
||||
if (filteredProfiles.length === 0) {
|
||||
return result;
|
||||
}
|
||||
|
||||
// แบ่ง batch ทีละ 100 records
|
||||
for (let i = 0; i < filteredProfiles.length; i += BATCH_SIZE) {
|
||||
const batch = filteredProfiles.slice(i, i + BATCH_SIZE);
|
||||
|
||||
// แบ่งเป็น chunk เล็กๆ ทีละ CONCURRENT_PER_BATCH เพื่อส่ง parallel
|
||||
for (let j = 0; j < batch.length; j += CONCURRENT_PER_BATCH) {
|
||||
const chunk = batch.slice(j, j + CONCURRENT_PER_BATCH);
|
||||
|
||||
// ส่ง parallel ในแต่ละ chunk
|
||||
await Promise.all(
|
||||
chunk.map(async (profile) => {
|
||||
try {
|
||||
await this.postSingleProfileToExprofile(profile);
|
||||
result.success++;
|
||||
} catch (error: any) {
|
||||
result.failed++;
|
||||
const errorInfo = {
|
||||
id: profile.id,
|
||||
name: `${profile.prefix}${profile.firstName} ${profile.lastName}`,
|
||||
error: error.message || String(error),
|
||||
};
|
||||
result.failedProfiles.push(errorInfo);
|
||||
}
|
||||
})
|
||||
);
|
||||
}
|
||||
}
|
||||
|
||||
} catch (error: any) {
|
||||
throw error;
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
/**
|
||||
* ส่งข้อมูล profile ไปยัง Exprofile
|
||||
*/
|
||||
private async postSingleProfileToExprofile(profile: Profile): Promise<void> {
|
||||
if (!profile.leaveDate) {
|
||||
return;
|
||||
}
|
||||
|
||||
if (!profile.citizenId) {
|
||||
return;
|
||||
}
|
||||
|
||||
const retireYear = profile.leaveDate.getFullYear();
|
||||
const retireDate = new Date(profile.leaveDate);
|
||||
|
||||
// ส่งไปยัง Exprofile
|
||||
PostRetireToExprofile(
|
||||
null,
|
||||
profile.citizenId,
|
||||
profile.prefix || "",
|
||||
profile.firstName || "",
|
||||
profile.lastName || "",
|
||||
retireYear.toString(),
|
||||
profile.position || "",
|
||||
profile.posType?.posTypeName || "",
|
||||
profile.posLevel?.posLevelName || "",
|
||||
retireDate,
|
||||
profile.org || "",
|
||||
profile.leaveReason || "เกษียณอายุราชการ"
|
||||
);
|
||||
}
|
||||
}
|
||||
Loading…
Add table
Add a link
Reference in a new issue