diff --git a/src/app.ts b/src/app.ts index 6efbcf9..b0180b1 100644 --- a/src/app.ts +++ b/src/app.ts @@ -8,6 +8,7 @@ import * as cron from "node-cron"; import error from "./middlewares/error"; import { AppDataSource } from "./database/data-source"; import { RegisterRoutes } from "./routes"; +import { SalaryPeriodController } from "./controllers/SalaryPeriodController"; async function main() { await AppDataSource.initialize(); @@ -25,11 +26,20 @@ async function main() { app.use("/api-docs", swaggerUi.serve, swaggerUi.setup(swaggerDocument)); RegisterRoutes(app); - + app.use(error); const APP_HOST = process.env.APP_HOST || "0.0.0.0"; const APP_PORT = +(process.env.APP_PORT || 3000); + const cronTime = "0 1 * * *"; // ตั้งเวลาทุกวันเวลา 01:00:00 + cron.schedule(cronTime, async () => { + try { + const salaryPeriod = new SalaryPeriodController(); + await salaryPeriod.CronjobSalaryPeriod(); + } catch (error) { + console.error("Error executing function from controller:", error); + } + }); app.listen( APP_PORT, APP_HOST, diff --git a/src/controllers/PosLevelController.ts b/src/controllers/PosLevelController.ts index 1f51b5a..51cd00a 100644 --- a/src/controllers/PosLevelController.ts +++ b/src/controllers/PosLevelController.ts @@ -66,7 +66,7 @@ export class PosLevelController extends Controller { if (!chkPosTypeId) { throw new HttpError( HttpStatusCode.NOT_FOUND, - "ไม่พบข้อมูล posTypeId ไอดีนี้ : " + requestBody.posTypeId, + "ไม่พบข้อมูลประเภทตำแหน่งนี้" ); } @@ -122,7 +122,7 @@ export class PosLevelController extends Controller { ) { const posLevel = await this.posLevelRepository.findOne({ where: { id } }); if (!posLevel) { - throw new HttpError(HttpStatusCode.NOT_FOUND, "ไม่พบข้อมูลไอดีนี้"); + throw new HttpError(HttpStatusCode.NOT_FOUND, "ไม่พบข้อมูลระดับตำแหน่งนี้"); } const chkPosTypeId = await this.posTypeRepository.findOne({ @@ -133,7 +133,7 @@ export class PosLevelController extends Controller { if (!chkPosTypeId) { throw new HttpError( HttpStatusCode.NOT_FOUND, - "ไม่พบข้อมูล posTypeId ไอดีนี้ : " + requestBody.posTypeId, + "ไม่พบข้อมูลระดับตำแหน่งนี้" ); } @@ -180,7 +180,7 @@ export class PosLevelController extends Controller { async deleteLevel(@Path() id: string) { const delPosLevel = await this.posLevelRepository.findOne({ where: { id } }); if (!delPosLevel) { - throw new HttpError(HttpStatusCode.NOT_FOUND, "ไม่พบข้อมูลไอดีนี้"); + throw new HttpError(HttpStatusCode.NOT_FOUND, "ไม่พบข้อมูลระดับตำแหน่งนี้"); } // try { await this.posLevelRepository.remove(delPosLevel); @@ -217,7 +217,7 @@ export class PosLevelController extends Controller { where: { id: id }, }); if (!getPosType) { - throw new HttpError(HttpStatusCode.NOT_FOUND, "ไม่พบข้อมูลไอดีนี้"); + throw new HttpError(HttpStatusCode.NOT_FOUND, "ไม่พบข้อมูลประเภทตำแหน่งนี้"); } const mapPosLevel = { diff --git a/src/controllers/PosTypeController.ts b/src/controllers/PosTypeController.ts index 72ce810..4004641 100644 --- a/src/controllers/PosTypeController.ts +++ b/src/controllers/PosTypeController.ts @@ -98,7 +98,7 @@ export class PosTypeController extends Controller { ) { const posType = await this.posTypeRepository.findOne({ where: { id } }); if (!posType) { - throw new HttpError(HttpStatusCode.NOT_FOUND, "ไม่พบข้อมูลไอดีนี้"); + throw new HttpError(HttpStatusCode.NOT_FOUND, "ไม่พบข้อมูลประเภทตำแหน่งนี้"); } const chkPosTypeName = await this.posTypeRepository.findOne({ where: { @@ -134,13 +134,13 @@ export class PosTypeController extends Controller { async deleteType(@Path() id: string) { const delPosType = await this.posTypeRepository.findOne({ where: { id } }); if (!delPosType) { - throw new HttpError(HttpStatusCode.NOT_FOUND, "ไม่พบข้อมูลไอดีนี้"); + throw new HttpError(HttpStatusCode.NOT_FOUND, "ไม่พบข้อมูลประเภทตำแหน่งนี้"); } const IdExitsInLevel = await this.posLevelRepository.find({ where: { posTypeId: id }, }); if (IdExitsInLevel.length > 0) { - throw new HttpError(HttpStatusCode.NOT_FOUND, "ไม่สามารถลบได้ เนื่องจาก id ผูกกับ posLevel"); + throw new HttpError(HttpStatusCode.NOT_FOUND, "ไม่สามารถลบข้อมูลระดับตำแหน่งนี้"); } // try { @@ -182,7 +182,7 @@ export class PosTypeController extends Controller { where: { id: id }, }); if (!getPosType) { - throw new HttpError(HttpStatusCode.NOT_FOUND, "ไม่พบข้อมูลไอดีนี้"); + throw new HttpError(HttpStatusCode.NOT_FOUND, "ไม่พบข้อมูลประเภทต"); } const mapGetPosType = { diff --git a/src/controllers/ReportController.ts b/src/controllers/ReportController.ts index 5646cac..2ed861f 100644 --- a/src/controllers/ReportController.ts +++ b/src/controllers/ReportController.ts @@ -53,7 +53,7 @@ export class ReportController extends Controller { where: { id: id } }); if (!salarys) { - throw new HttpError(HttpStatusCode.NOT_FOUND, "ไม่พบข้อมูลไอดี"); + throw new HttpError(HttpStatusCode.NOT_FOUND, "ไม่พบข้อมูลผังเงินเดือนนี้"); } const posType = await this.poTypeRepository.findOne({ where: { id: salarys.posTypeId }, diff --git a/src/controllers/SalaryController.ts b/src/controllers/SalaryController.ts index 237d605..a4842eb 100644 --- a/src/controllers/SalaryController.ts +++ b/src/controllers/SalaryController.ts @@ -132,7 +132,7 @@ export class Salary extends Controller { where: { id: id }, }); if (!chk_Salary) { - throw new HttpError(HttpStatusCode.NOT_FOUND, "ไม่พบข้อมูลไอดี"); + throw new HttpError(HttpStatusCode.NOT_FOUND, "ไม่พบข้อมูลผังเงินเดือนนี้"); } if (chk_Salary.isActive && !requestBody.isActive) { @@ -205,7 +205,7 @@ export class Salary extends Controller { where: { id: id }, }); if (!chk_Salary) { - throw new HttpError(HttpStatusCode.NOT_FOUND, "ไม่พบข้อมูลไอดี"); + throw new HttpError(HttpStatusCode.NOT_FOUND, "ไม่พบข้อมูลผังเงินเดือนนี้"); } if (chk_Salary.isActive) { throw new HttpError( @@ -259,7 +259,7 @@ export class Salary extends Controller { ], }); if (!salary) { - throw new HttpError(HttpStatusCode.NOT_FOUND, "ไม่พบข้อมูลไอดี"); + throw new HttpError(HttpStatusCode.NOT_FOUND, "ไม่พบข้อมูลผังเงินเดือนนี้"); } return new HttpSuccess(salary); // } catch (error: any) { @@ -354,7 +354,7 @@ export class Salary extends Controller { }); if (!salary) { - throw new HttpError(HttpStatusCode.NOT_FOUND, "ไม่พบข้อมูลเงินเดือนจากไอดีนี้ : " + body.id); + throw new HttpError(HttpStatusCode.NOT_FOUND, "ไม่พบข้อมูลผังเงินเดือนนี้"); } const salaryRank = await this.salaryRankRepository.find({ diff --git a/src/controllers/SalaryPeriodController.ts b/src/controllers/SalaryPeriodController.ts index 22e1e62..92140f8 100644 --- a/src/controllers/SalaryPeriodController.ts +++ b/src/controllers/SalaryPeriodController.ts @@ -27,6 +27,8 @@ import { PosType } from "../entities/PosType"; import { PosLevel } from "../entities/PosLevel"; import { Salarys } from "../entities/Salarys"; import { SalaryRanks } from "../entities/SalaryRanks"; +import CallAPI from "../interfaces/call-api"; +import { Int32 } from "typeorm/browser"; @Route("api/v1/salary/period") @Tags("Salary") @@ -478,7 +480,8 @@ export class SalaryPeriodController extends Controller { ); } - const salaryProfile = Object.assign(new SalaryProfile(), requestBody); + let salaryProfile: any = Object.assign(new SalaryProfile(), requestBody); + delete salaryProfile.id; salaryProfile.type = salaryProfile.type.toUpperCase(); //Type & Level const type = await this.posTypeRepository.findOne({ @@ -555,7 +558,9 @@ export class SalaryPeriodController extends Controller { : salaryRanks.salaryFullHalf - salaryProfile.amount; salaryProfile.positionSalaryAmount = salaryRanks == null ? 0 : salaryRanks.salaryFullHalf; } else { - throw new HttpError(HttpStatusCode.NOT_FOUND, "ประเภทการเลื่อนขึ้นเงินเดือนไม่ถูกต้อง"); + salaryProfile.amountSpecial = 0; + salaryProfile.amountUse = 0; + salaryProfile.positionSalaryAmount = 0; } salaryProfile.salaryOrgId = salaryOrg.id; @@ -625,7 +630,7 @@ export class SalaryPeriodController extends Controller { where: { id: id }, }); if (!chk_SalaryPeriod) { - throw new HttpError(HttpStatusCode.NOT_FOUND, "ไม่พบข้อมูลไอดี"); + throw new HttpError(HttpStatusCode.NOT_FOUND, "ไม่พบข้อมูลรอบผังเงินเดือนนี้"); } const chk_toUpper = ["SPECIAL", "APR", "OCT"]; @@ -669,7 +674,7 @@ export class SalaryPeriodController extends Controller { where: { id: id }, }); if (!SalaryPeriod) { - throw new HttpError(HttpStatusCode.NOT_FOUND, "ไม่พบข้อมูลไอดี"); + throw new HttpError(HttpStatusCode.NOT_FOUND, "ไม่พบข้อมูลรอบผังเงินเดือนนี้"); } const SalaryOrg = await this.salaryOrgRepository.findOne({ where: { salaryPeriodId: SalaryPeriod.id }, @@ -704,7 +709,7 @@ export class SalaryPeriodController extends Controller { ], }); if (!salaryPeriod) { - throw new HttpError(HttpStatusCode.NOT_FOUND, "ไม่พบข้อมูลไอดี"); + throw new HttpError(HttpStatusCode.NOT_FOUND, "ไม่พบข้อมูลรอบผังเงินเดือนนี้"); } return new HttpSuccess(salaryPeriod); } @@ -751,13 +756,13 @@ export class SalaryPeriodController extends Controller { * @summary snapshot salary * */ - @Get("snapshot/{snaphot}/{salaryPeriodId}") + @Get("snapshot/{snapshot}/{salaryPeriodId}") async SnapshotSalary( - @Path() snaphot: string, + @Path() snapshot: string, salaryPeriodId: string, @Request() request: { user: Record }, ) { - snaphot = snaphot.toLocaleUpperCase(); + snapshot = snapshot.toLocaleUpperCase(); const salaryPeriod = await this.salaryPeriodRepository.findOne({ where: { id: salaryPeriodId }, }); @@ -766,17 +771,38 @@ export class SalaryPeriodController extends Controller { } const salaryOrg = await this.salaryOrgRepository.find({ - where: { salaryPeriodId: salaryPeriod.id, snapshot: snaphot }, + where: { salaryPeriodId: salaryPeriod.id, snapshot: snapshot }, }); const salaryProfile = await this.salaryProfileRepository.find({ where: { salaryOrgId: In(salaryOrg.map((x) => x.id)) }, }); - await this.salaryOrgRepository.remove(salaryOrg); await this.salaryProfileRepository.remove(salaryProfile); + await this.salaryOrgRepository.remove(salaryOrg); - let orgs: any; - let orgProfiles: any; - let revisionId: any; + let orgs = await new CallAPI().GetData(request, "org/active/root/id"); + let total = 1000; + let _orgProfiles = await new CallAPI().PostData(request, "org/profile/salary/gen", { + page: 1, + pageSize: 1000, + keyword: "", + }); + let orgProfiles = _orgProfiles.data; + total = _orgProfiles.total; + if (total > 1000) { + const page = Math.ceil(total / 1000); + for (let index = 2; index <= page; index++) { + await new CallAPI() + .PostData(request, "org/profile/salary/gen", { + page: index, + pageSize: 1000, + keyword: "", + }) + .then((x) => { + Array.prototype.push.apply(orgProfiles, x.data); + }); + } + } + let revisionId = await new CallAPI().GetData(request, "org/revision/latest"); salaryPeriod.revisionId = revisionId; await this.salaryPeriodRepository.save(salaryPeriod); @@ -784,11 +810,12 @@ export class SalaryPeriodController extends Controller { await Promise.all( orgs.map(async (rootId: string) => { let salaryOrgNew = Object.assign(new SalaryOrg()); + delete salaryOrgNew.id; salaryOrgNew.salaryPeriodId = salaryPeriod.id; salaryOrgNew.status = "PENDING"; salaryOrgNew.rootId = rootId; salaryOrgNew.revisionId = salaryPeriod.revisionId; - salaryOrgNew.snapshot = snaphot; + salaryOrgNew.snapshot = snapshot; salaryOrgNew.group = "GROUP1"; salaryOrgNew.createdUserId = request.user.sub; salaryOrgNew.createdFullName = request.user.name; @@ -802,9 +829,9 @@ export class SalaryPeriodController extends Controller { ); let salaryProfileOld: SalaryProfile[] = []; - if (snaphot == "SNAP2") { + if (snapshot == "SNAP2") { const salaryOrgOld = await this.salaryOrgRepository.findOne({ - where: { salaryPeriodId: salaryPeriod.id, snapshot: snaphot }, + where: { salaryPeriodId: salaryPeriod.id, snapshot: "SNAP1" }, relations: ["salaryProfiles"], }); if (salaryOrgOld != null) salaryProfileOld = salaryOrgOld.salaryProfiles; @@ -827,13 +854,14 @@ export class SalaryPeriodController extends Controller { where: { salaryPeriodId: salaryPeriod.id, rootId: profile.rootId, - snapshot: snaphot, + snapshot: snapshot, group: group, }, }); if (salaryOrgNew != null) { let salaryProfileNew = Object.assign(new SalaryProfile(), profile); + delete profile.id; salaryProfileNew.salaryOrgId = salaryOrgNew.id; salaryProfileNew.revisionId = salaryPeriod.revisionId; salaryProfileNew.createdUserId = request.user.sub; @@ -841,7 +869,7 @@ export class SalaryPeriodController extends Controller { salaryProfileNew.lastUpdateUserId = request.user.sub; salaryProfileNew.lastUpdateFullName = request.user.name; - if (snaphot == "SNAP2") { + if (snapshot == "SNAP2") { const salaryOld = salaryProfileOld.find( (x) => x.citizenId == salaryProfileNew.citizenId, ); @@ -857,7 +885,7 @@ export class SalaryPeriodController extends Controller { ); const salaryOrgNew = await this.salaryOrgRepository.find({ - where: { salaryPeriodId: salaryPeriod.id, snapshot: snaphot }, + where: { salaryPeriodId: salaryPeriod.id, snapshot: snapshot }, relations: ["salaryProfiles"], }); await Promise.all( @@ -871,4 +899,46 @@ export class SalaryPeriodController extends Controller { return new HttpSuccess(); } + + /** + * Cronjob SalaryPeriod + */ + async CronjobSalaryPeriod() { + const current = new Date(); + let salaryPeriod: any; + // console.log(current.getDate(), current.getMonth() , current.getFullYear()) + if (current.getDate() == 1 && current.getMonth() == 2) { + salaryPeriod = await this.salaryPeriodRepository.findOne({ + where: { + year: current.getFullYear(), + period: "MAR", + isActive: true, + }, + }); + } else if (current.getDate() == 1 && current.getMonth() == 3) { + salaryPeriod = await this.salaryPeriodRepository.findOne({ + where: { + year: current.getFullYear(), + period: "APR", + isActive: true, + }, + }); + } else if (current.getDate() == 1 && current.getMonth() == 8) { + salaryPeriod = await this.salaryPeriodRepository.findOne({ + where: { + year: current.getFullYear(), + period: "SEP", + isActive: true, + }, + }); + } else if (current.getDate() == 1 && current.getMonth() == 9) { + salaryPeriod = await this.salaryPeriodRepository.findOne({ + where: { + year: current.getFullYear(), + period: "OCT", + isActive: true, + }, + }); + } + } } diff --git a/src/controllers/SalaryRankController.ts b/src/controllers/SalaryRankController.ts index eb878db..0de9663 100644 --- a/src/controllers/SalaryRankController.ts +++ b/src/controllers/SalaryRankController.ts @@ -52,7 +52,7 @@ export class SalaryRanksController extends Controller { if (!checkSalary) { throw new HttpError( HttpStatusCode.NOT_FOUND, - "ไม่พบข้อมูลไอดีนี้ : " + requestBody.salaryId, + "ไม่พบข้อมูลผังเงินเดือนนี้" ); } const salaryRank = Object.assign(new SalaryRanks(), requestBody); @@ -84,7 +84,7 @@ export class SalaryRanksController extends Controller { // try { const salaryRank = await this.salaryRankRepository.findOne({ where: { id: id } }); if (!salaryRank) { - throw new HttpError(HttpStatusCode.NOT_FOUND, "ไม่พบข้อมูลไอดีนี้"); + throw new HttpError(HttpStatusCode.NOT_FOUND, "ไม่พบข้อมูลระดับผังเงินเดือนนี้"); } salaryRank.lastUpdateUserId = request.user.sub; salaryRank.lastUpdateFullName = request.user.name; @@ -110,7 +110,7 @@ export class SalaryRanksController extends Controller { where: { id }, }); if (!delSalaryRanks) { - throw new HttpError(HttpStatusCode.NOT_FOUND, "ไม่พบข้อมูลตำแหน่งตามไอดีนี้"); + throw new HttpError(HttpStatusCode.NOT_FOUND, "ไม่พบข้อมูลระดับผังเงินเดือนนี้"); } await this.salaryRankRepository.delete({ id: id }); return new HttpSuccess(); diff --git a/src/entities/SalaryOrg.ts b/src/entities/SalaryOrg.ts index fbb960f..eebc772 100644 --- a/src/entities/SalaryOrg.ts +++ b/src/entities/SalaryOrg.ts @@ -37,11 +37,13 @@ export class SalaryOrg extends EntityBase { snapshot: string; @Column({ + default: 0, comment: "จำนวนคนทั้งหมด", }) total: number; @Column({ + default: 0, comment: "15%ของจำนวนคน(จำนวนเต็ม)", }) fifteenPercent: number; diff --git a/src/entities/SalaryProfile.ts b/src/entities/SalaryProfile.ts index 41bfcdb..f93f68e 100644 --- a/src/entities/SalaryProfile.ts +++ b/src/entities/SalaryProfile.ts @@ -289,16 +289,16 @@ export class CreateSalaryProfile { citizenId: string; @Column() - posMasterNoPrefix: string; + posMasterNoPrefix: string | null; @Column() posMasterNo: number; @Column() - posMasterNoSuffix: string; + posMasterNoSuffix: string | null; @Column() - orgShortName: string; + orgShortName: string | null; @Column() position: string; @@ -309,36 +309,54 @@ export class CreateSalaryProfile { @Column() posLevel: string; + @Column() + posExecutive: string | null; + @Column() amount: number; @Column("uuid") - rootId: string; + rootId: string | null; @Column() - root: string; + root: string | null; @Column("uuid") - child1Id: string; + child1Id: string | null; @Column() - child1: string; + child1: string | null; @Column("uuid") - child2Id: string; + child2Id: string | null; @Column() - child2: string; + child2: string | null; @Column("uuid") - child3Id: string; + child3Id: string | null; @Column() - child3: string; + child3: string | null; @Column("uuid") - child4Id: string; + child4Id: string | null; @Column() - child4: string; + child4: string | null; + + @Column() + isResult: boolean; + + @Column() + isDuration: boolean; + + @Column() + isPunish: boolean; + + @Column() + isRetired: boolean; + + @Column() + isRetired2: boolean; } diff --git a/src/interfaces/call-api.ts b/src/interfaces/call-api.ts index 49473f0..8608230 100644 --- a/src/interfaces/call-api.ts +++ b/src/interfaces/call-api.ts @@ -1,24 +1,51 @@ -import { Controller, Request, Get, Post, Put, Delete, Patch, Route, Security, Tags, Path } from "tsoa"; -import axios from 'axios'; +import { + Controller, + Request, + Get, + Post, + Put, + Delete, + Patch, + Route, + Security, + Tags, + Path, +} from "tsoa"; +import axios from "axios"; class CallAPI { - //Get - public async GetData(request: any, @Path() path: any) { - const token = request.headers.authorization; - const url = process.env.ORG_API+path; - try { - const response = await axios.get(url, { - headers: { - Authorization: `Bearer ${token}`, - 'Content-Type': 'application/json' - } - }); - return response.data; - } catch (error) { - throw error; - } + //Get + public async GetData(request: any, @Path() path: any) { + const token = request.headers.authorization; + const url = process.env.API + path; + try { + const response = await axios.get(url, { + headers: { + Authorization: `Bearer ${token}`, + "Content-Type": "application/json", + }, + }); + return response.data.result; + } catch (error) { + throw error; } - + } + //Post + public async PostData(request: any, @Path() path: any, sendData: any) { + const token = request.headers.authorization; + const url = process.env.API + path; + try { + const response = await axios.post(url, sendData, { + headers: { + Authorization: `Bearer ${token}`, + "Content-Type": "application/json", + }, + }); + return response.data.result; + } catch (error) { + throw error; + } + } } -export default CallAPI; \ No newline at end of file +export default CallAPI; diff --git a/src/migration/1709105846886-update_table_salaryProfile_add_revision3.ts b/src/migration/1709105846886-update_table_salaryProfile_add_revision3.ts new file mode 100644 index 0000000..cffaf25 --- /dev/null +++ b/src/migration/1709105846886-update_table_salaryProfile_add_revision3.ts @@ -0,0 +1,16 @@ +import { MigrationInterface, QueryRunner } from "typeorm"; + +export class UpdateTableSalaryProfileAddRevision31709105846886 implements MigrationInterface { + name = 'UpdateTableSalaryProfileAddRevision31709105846886' + + public async up(queryRunner: QueryRunner): Promise { + await queryRunner.query(`ALTER TABLE \`salaryOrg\` CHANGE \`total\` \`total\` int NOT NULL COMMENT 'จำนวนคนทั้งหมด' DEFAULT '0'`); + await queryRunner.query(`ALTER TABLE \`salaryOrg\` CHANGE \`fifteenPercent\` \`fifteenPercent\` int NOT NULL COMMENT '15%ของจำนวนคน(จำนวนเต็ม)' DEFAULT '0'`); + } + + public async down(queryRunner: QueryRunner): Promise { + await queryRunner.query(`ALTER TABLE \`salaryOrg\` CHANGE \`fifteenPercent\` \`fifteenPercent\` int NOT NULL COMMENT '15%ของจำนวนคน(จำนวนเต็ม)'`); + await queryRunner.query(`ALTER TABLE \`salaryOrg\` CHANGE \`total\` \`total\` int NOT NULL COMMENT 'จำนวนคนทั้งหมด'`); + } + +}