diff --git a/src/controllers/CommandController.ts b/src/controllers/CommandController.ts index 905c77ea..d31bfa65 100644 --- a/src/controllers/CommandController.ts +++ b/src/controllers/CommandController.ts @@ -27,6 +27,7 @@ import { OrgRevision } from "../entities/OrgRevision"; import { CommandSendCC } from "../entities/CommandSendCC"; import { CommandSalary } from "../entities/CommandSalary"; import { CommandRecive } from "../entities/CommandRecive"; +import { CommandOperator } from "../entities/CommandOperator"; import HttpStatus from "../interfaces/http-status"; import Extension from "../interfaces/extension"; import { ProfileEmployee } from "../entities/ProfileEmployee"; @@ -112,6 +113,7 @@ export class CommandController extends Controller { private commandSendCCRepository = AppDataSource.getRepository(CommandSendCC); private commandSalaryRepository = AppDataSource.getRepository(CommandSalary); private commandReciveRepository = AppDataSource.getRepository(CommandRecive); + private commandOperatorRepository = AppDataSource.getRepository(CommandOperator); private profileRepository = AppDataSource.getRepository(Profile); private profileEmployeeRepository = AppDataSource.getRepository(ProfileEmployee); private orgRevisionRepo = AppDataSource.getRepository(OrgRevision); @@ -2408,6 +2410,7 @@ export class CommandController extends Controller { }, @Request() request: RequestWithUser, ) { + const now = new Date(); let command = new Command(); let commandCode: string = ""; let _null: any = null; @@ -2466,12 +2469,86 @@ export class CommandController extends Controller { : _null), (command.createdUserId = request.user.sub); command.createdFullName = request.user.name; - command.createdAt = new Date(); + command.createdAt = now; command.lastUpdateUserId = request.user.sub; command.lastUpdateFullName = request.user.name; - command.lastUpdatedAt = new Date(); + command.lastUpdatedAt = now; await this.commandRepository.save(command); } + // insert commandOperator + if (request.user.sub) { + const profile = await this.profileRepository.findOne({ + where: { keycloak: request.user.sub }, + relations: { + posLevel: true, + posType: true, + current_holders: { + orgRevision: true, + orgRoot: true, + orgChild1: true, + orgChild2: true, + orgChild3: true, + orgChild4: true, + }, + }, + }); + if (profile) { + const currentHolder = profile!.current_holders?.find( + x => + x.orgRevision?.orgRevisionIsDraft === false && + x.orgRevision?.orgRevisionIsCurrent === true, + ); + + const posNo = + currentHolder != null && currentHolder.orgChild4 != null + ? `${currentHolder.orgChild4.orgChild4ShortName} ${currentHolder.posMasterNo}` + : currentHolder != null && currentHolder.orgChild3 != null + ? `${currentHolder.orgChild3.orgChild3ShortName} ${currentHolder.posMasterNo}` + : currentHolder != null && currentHolder.orgChild2 != null + ? `${currentHolder.orgChild2.orgChild2ShortName} ${currentHolder.posMasterNo}` + : currentHolder != null && currentHolder.orgChild1 != null + ? `${currentHolder.orgChild1.orgChild1ShortName} ${currentHolder.posMasterNo}` + : currentHolder != null && currentHolder?.orgRoot != null + ? `${currentHolder.orgRoot.orgRootShortName} ${currentHolder.posMasterNo}` + : null; + + const position = await this.positionRepository.findOne({ + where: { + positionIsSelected: true, + posMaster: { + orgRevisionId: currentHolder?.orgRevisionId, + current_holderId: profile!.id, + }, + }, + order: { createdAt: "DESC" }, + relations: { posExecutive: true }, + }); + const operator = Object.assign( + new CommandOperator(), + { + profileId: profile?.id, + prefix: profile?.prefix, + firstName: profile?.firstName, + lastName: profile?.lastName, + posNo: posNo, + posType: profile?.posType?.posTypeName ?? null, + posLevel: profile?.posLevel?.posLevelName ?? null, + position: position?.positionName ?? null, + positionExecutive: position?.posExecutive?.posExecutiveName ?? null, + roleName: "เจ้าหน้าที่ดำเนินการ", + orderNo: 1, + commandId: command.id, + createUserId: request.user.sub, + createdFullName: request.user.name, + createdAt: now, + lastUpdateUserId: request.user.sub, + lastUpdateFullName: request.user.name, + lastUpdatedAt: now, + } + ); + await this.commandOperatorRepository.save(operator); + } + } const path = commandTypePath(commandCode); if (path == null) throw new HttpError(HttpStatusCode.NOT_FOUND, "ไม่พบประเภทคำสั่งนี้ในระบบ"); @@ -2537,10 +2614,10 @@ export class CommandController extends Controller { commandRecive.commandId = command.id; commandRecive.createdUserId = request.user.sub; commandRecive.createdFullName = request.user.name; - commandRecive.createdAt = new Date(); + commandRecive.createdAt = now; commandRecive.lastUpdateUserId = request.user.sub; commandRecive.lastUpdateFullName = request.user.name; - commandRecive.lastUpdatedAt = new Date(); + commandRecive.lastUpdatedAt = now; if (commandCode == "C-PM-40") { const posMasterAct = await this.posMasterActRepository.findOne({ @@ -2635,10 +2712,10 @@ export class CommandController extends Controller { commandSend.commandId = command.id; commandSend.createdUserId = request.user.sub; commandSend.createdFullName = request.user.name; - commandSend.createdAt = new Date(); + commandSend.createdAt = now; commandSend.lastUpdateUserId = request.user.sub; commandSend.lastUpdateFullName = request.user.name; - commandSend.lastUpdatedAt = new Date(); + commandSend.lastUpdatedAt = now; await this.commandSendRepository.save(commandSend); if (commandSend && commandSend.id) { let _ccName = new Array("EMAIL", "INBOX"); @@ -2649,10 +2726,10 @@ export class CommandController extends Controller { name: _ccName[i], createdUserId: request.user.sub, createdFullName: request.user.name, - createdAt: new Date(), + createdAt: now, lastUpdateUserId: request.user.sub, lastUpdateFullName: request.user.name, - lastUpdatedAt: new Date(), + lastUpdatedAt: now, }); } await this.commandSendCCRepository.save(_dataSendCC); @@ -2692,10 +2769,10 @@ export class CommandController extends Controller { commandSend.commandId = command.id; commandSend.createdUserId = request.user.sub; commandSend.createdFullName = request.user.name; - commandSend.createdAt = new Date(); + commandSend.createdAt = now; commandSend.lastUpdateUserId = request.user.sub; commandSend.lastUpdateFullName = request.user.name; - commandSend.lastUpdatedAt = new Date(); + commandSend.lastUpdatedAt = now; await this.commandSendRepository.save(commandSend); if (commandSend && commandSend.id) { let _ccName = new Array("EMAIL", "INBOX"); @@ -2706,10 +2783,10 @@ export class CommandController extends Controller { name: _ccName[i], createdUserId: request.user.sub, createdFullName: request.user.name, - createdAt: new Date(), + createdAt: now, lastUpdateUserId: request.user.sub, lastUpdateFullName: request.user.name, - lastUpdatedAt: new Date(), + lastUpdatedAt: now, }); } await this.commandSendCCRepository.save(_dataSendCC); @@ -2749,10 +2826,10 @@ export class CommandController extends Controller { commandSend.commandId = command.id; commandSend.createdUserId = request.user.sub; commandSend.createdFullName = request.user.name; - commandSend.createdAt = new Date(); + commandSend.createdAt = now; commandSend.lastUpdateUserId = request.user.sub; commandSend.lastUpdateFullName = request.user.name; - commandSend.lastUpdatedAt = new Date(); + commandSend.lastUpdatedAt = now; await this.commandSendRepository.save(commandSend); if (commandSend && commandSend.id) { let _ccName = new Array("EMAIL", "INBOX"); @@ -2763,10 +2840,10 @@ export class CommandController extends Controller { name: _ccName[i], createdUserId: request.user.sub, createdFullName: request.user.name, - createdAt: new Date(), + createdAt: now, lastUpdateUserId: request.user.sub, lastUpdateFullName: request.user.name, - lastUpdatedAt: new Date(), + lastUpdatedAt: now, }); } await this.commandSendCCRepository.save(_dataSendCC); @@ -2931,10 +3008,10 @@ export class CommandController extends Controller { commandSend.commandId = command.id; commandSend.createdUserId = request.user.sub; commandSend.createdFullName = request.user.name; - commandSend.createdAt = new Date(); + commandSend.createdAt = now; commandSend.lastUpdateUserId = request.user.sub; commandSend.lastUpdateFullName = request.user.name; - commandSend.lastUpdatedAt = new Date(); + commandSend.lastUpdatedAt = now; await this.commandSendRepository.save(commandSend); if (commandSend && commandSend.id) { let _ccName = new Array("EMAIL", "INBOX"); @@ -2945,10 +3022,10 @@ export class CommandController extends Controller { name: _ccName[i], createdUserId: request.user.sub, createdFullName: request.user.name, - createdAt: new Date(), + createdAt: now, lastUpdateUserId: request.user.sub, lastUpdateFullName: request.user.name, - lastUpdatedAt: new Date(), + lastUpdatedAt: now, }); } await this.commandSendCCRepository.save(_dataSendCC); @@ -2992,10 +3069,10 @@ export class CommandController extends Controller { commandSend.commandId = command.id; commandSend.createdUserId = request.user.sub; commandSend.createdFullName = request.user.name; - commandSend.createdAt = new Date(); + commandSend.createdAt = now; commandSend.lastUpdateUserId = request.user.sub; commandSend.lastUpdateFullName = request.user.name; - commandSend.lastUpdatedAt = new Date(); + commandSend.lastUpdatedAt = now; await this.commandSendRepository.save(commandSend); if (commandSend && commandSend.id) { let _ccName = new Array("EMAIL", "INBOX"); @@ -3006,10 +3083,10 @@ export class CommandController extends Controller { name: _ccName[i], createdUserId: request.user.sub, createdFullName: request.user.name, - createdAt: new Date(), + createdAt: now, lastUpdateUserId: request.user.sub, lastUpdateFullName: request.user.name, - lastUpdatedAt: new Date(), + lastUpdatedAt: now, }); } await this.commandSendCCRepository.save(_dataSendCC); @@ -3051,10 +3128,10 @@ export class CommandController extends Controller { commandSend.commandId = command.id; commandSend.createdUserId = request.user.sub; commandSend.createdFullName = request.user.name; - commandSend.createdAt = new Date(); + commandSend.createdAt = now; commandSend.lastUpdateUserId = request.user.sub; commandSend.lastUpdateFullName = request.user.name; - commandSend.lastUpdatedAt = new Date(); + commandSend.lastUpdatedAt = now; await this.commandSendRepository.save(commandSend); if (commandSend && commandSend.id) { let _ccName = new Array("EMAIL", "INBOX"); @@ -3065,10 +3142,10 @@ export class CommandController extends Controller { name: _ccName[i], createdUserId: request.user.sub, createdFullName: request.user.name, - createdAt: new Date(), + createdAt: now, lastUpdateUserId: request.user.sub, lastUpdateFullName: request.user.name, - lastUpdatedAt: new Date(), + lastUpdatedAt: now, }); } await this.commandSendCCRepository.save(_dataSendCC); diff --git a/src/controllers/CommandOperatorController.ts b/src/controllers/CommandOperatorController.ts new file mode 100644 index 00000000..f1cac92a --- /dev/null +++ b/src/controllers/CommandOperatorController.ts @@ -0,0 +1,224 @@ +import { + Controller, + Post, + Delete, + Route, + Security, + Tags, + Body, + Path, + Request, + Response, + Get +} from "tsoa"; +import { LessThan, MoreThan } from "typeorm"; +import { AppDataSource } from "../database/data-source"; +import HttpSuccess from "../interfaces/http-success"; +import HttpStatusCode from "../interfaces/http-status"; +import HttpError from "../interfaces/http-error"; +import { Command } from "../entities/Command"; +import { CommandOperator, CreateCommandOperatorDto } from "../entities/CommandOperator"; +import { RequestWithUser } from "../middlewares/user"; + +@Route("api/v1/org/commandOperator") +@Tags("CommandOperator") +@Security("bearerAuth") +@Response( + HttpStatusCode.INTERNAL_SERVER_ERROR, + "เกิดข้อผิดพลาด ไม่สามารถแสดงรายการได้ กรุณาลองใหม่ในภายหลัง", +) +export class CommandOperatorController extends Controller { + private commandRepo = AppDataSource.getRepository(Command); + private commandOperatorRepo = AppDataSource.getRepository(CommandOperator); + + /** + * API รายชื่อเจ้าหน้าที่ดำเนินการที่คำสั่ง + * @summary API รายชื่อเจ้าหน้าที่ดำเนินการที่คำสั่ง + * @param commandId คีย์คำสั่ง + */ + @Get("{commandId}") + async getCommandOperatorByCommandId( + @Path() commandId: string + ) { + const command = await this.commandRepo.findOne({ + where: { id: commandId }, + select: { id: true }, + }); + if (!command) { + throw new HttpError(HttpStatusCode.NOT_FOUND, "ไม่พบข้อมูลคำสั่งนี้"); + } + const commandOperators = await this.commandOperatorRepo.find({ + where: { commandId: command.id }, + order: { orderNo: "ASC" }, + }); + return new HttpSuccess(commandOperators); + } + + /** + * API สลับลำดับเจ้าหน้าที่ดำเนินการ (UP / DOWN) + * @summary API สลับลำดับเจ้าหน้าที่ดำเนินการ (UP / DOWN) + * @param direction สลับขึ้นหรือลง (UP / DOWN) + * @param operatorId คีย์เจ้าหน้าที่ดำเนินการ + */ + @Get("swap/{direction}/{operatorId}") + async swapCommandOperator( + @Path() direction: string, + @Path() operatorId: string, + ) { + const source = await this.commandOperatorRepo.findOne({ + where: { id: operatorId }, + }); + + if (!source) { + throw new HttpError(HttpStatusCode.NOT_FOUND, "ไม่พบข้อมูลเจ้าหน้าที่"); + } + + const sourceOrder = source.orderNo; + const isUp = direction.trim().toUpperCase() === "UP"; + + let dest: CommandOperator | null; + + if (isUp) { + dest = await this.commandOperatorRepo.findOne({ + where: { + commandId: source.commandId, + orderNo: LessThan(sourceOrder), + }, + order: { orderNo: "DESC" }, + }); + } else { + dest = await this.commandOperatorRepo.findOne({ + where: { + commandId: source.commandId, + orderNo: MoreThan(sourceOrder), + }, + order: { orderNo: "ASC" }, + }); + } + + // ถ้าไม่มีตัวให้สลับ (บนสุด / ล่างสุด) + if (!dest) { + return new HttpSuccess(); + } + + // swap + const temp = source.orderNo; + source.orderNo = dest.orderNo; + dest.orderNo = temp; + + await Promise.all([ + this.commandOperatorRepo.save(source), + this.commandOperatorRepo.save(dest), + ]); + + return new HttpSuccess(); + } + + /** + * API เพิ่มเจ้าหน้าที่ดำเนินการที่คำสั่ง + * @summary API เพิ่มเจ้าหน้าที่ดำเนินการที่คำสั่ง + * @param commandId คีย์คำสั่ง + */ + @Post("{commandId}") + async createCommandOperators( + @Path() commandId: string, + @Request() request: RequestWithUser, + @Body() body: CreateCommandOperatorDto, + ) { + const command = await this.commandRepo.findOne({ + where: { id: commandId }, + select: { id: true }, + }); + + if (!command) { + throw new HttpError(HttpStatusCode.NOT_FOUND, "ไม่พบข้อมูลคำสั่งนี้"); + } + const lastOrderNo = await this.commandOperatorRepo.findOne({ + where: { commandId: commandId }, + order: { orderNo: "DESC" }, + select: { orderNo: true }, + }); + const nextOrderNo = (lastOrderNo?.orderNo ?? 1) + 1; + + const now = new Date(); + const operator = Object.assign( + new CommandOperator(), + { + ...body, + commandId: command.id, + orderNo: nextOrderNo, + createdUserId: request.user.sub, + createdFullName: request.user.name, + createdAt: now, + lastUpdateUserId: request.user.sub, + lastUpdateFullName: request.user.name, + lastUpdatedAt: now, + } + ); + await this.commandOperatorRepo.save(operator); + return new HttpSuccess(); + } + + /** + * API ลบเจ้าหน้าที่ดำเนินการที่คำสั่ง + * @summary API ลบเจ้าหน้าที่ดำเนินการที่คำสั่ง + * @param commandId คีย์คำสั่ง + * @param operatorId คีย์เจ้าหน้าที่ดำเนินการ + */ + @Delete("{commandId}/{operatorId}") + public async deleteCommandOperator( + @Path() commandId: string, + @Path() operatorId: string, + ) { + const queryRunner = AppDataSource.createQueryRunner(); + await queryRunner.connect(); + await queryRunner.startTransaction(); + + try { + // 1. หา operator + const operator = await queryRunner.manager.findOne(CommandOperator, { + where: { + id: operatorId, + commandId: commandId, + }, + }); + + if (!operator) { + throw new HttpError(HttpStatusCode.NOT_FOUND, "ไม่พบเจ้าหน้าที่ดำเนินการ"); + } + + // 2. ห้ามลบ orderNo = 1 + if (operator.orderNo === 1) { + throw new HttpError( + HttpStatusCode.BAD_REQUEST, + "ไม่สามารถลบเจ้าหน้าที่ลำดับที่ 1 ได้" + ); + } + + const removedOrderNo = operator.orderNo; + + // 3. ลบ + await queryRunner.manager.remove(operator); + + // 4. re orderNumber ตัวที่เหลือ + await queryRunner.manager + .createQueryBuilder() + .update(CommandOperator) + .set({ + orderNo: () => "orderNo - 1", + }) + .where("commandId = :commandId", { commandId }) + .andWhere("orderNo > :removedOrderNo", { removedOrderNo }) + .execute(); + + await queryRunner.commitTransaction(); + return new HttpSuccess(true); + } catch (error) { + await queryRunner.rollbackTransaction(); + throw error; + } finally { + await queryRunner.release(); + } + } + +} diff --git a/src/entities/CommandOperator.ts b/src/entities/CommandOperator.ts index 02b452b2..f2d42a6b 100644 --- a/src/entities/CommandOperator.ts +++ b/src/entities/CommandOperator.ts @@ -84,6 +84,13 @@ export class CommandOperator extends EntityBase { }) roleName: string; + @Column({ + nullable: true, + comment: "ลำดับบทบาทของเจ้าหน้าที่ดำเนินการ", + default: null, + }) + orderNo: number; + @Column({ length: 40, comment: "คีย์นอก(FK)ของตาราง command", @@ -95,3 +102,16 @@ export class CommandOperator extends EntityBase { command: Command; } + +export class CreateCommandOperatorDto { + profileId: string; + prefix?: string; + firstName?: string; + lastName?: string; + posNo?: string; + posType?: string; + posLevel?: string; + position?: string; + positionExecutive?: string; + roleName: string; +} \ No newline at end of file diff --git a/src/migration/1770089334925-update_table_commandOperator_add_column_orderNo.ts b/src/migration/1770089334925-update_table_commandOperator_add_column_orderNo.ts new file mode 100644 index 00000000..11990b5b --- /dev/null +++ b/src/migration/1770089334925-update_table_commandOperator_add_column_orderNo.ts @@ -0,0 +1,14 @@ +import { MigrationInterface, QueryRunner } from "typeorm"; + +export class UpdateTableCommandOperatorAddColumnOrderNo1770089334925 implements MigrationInterface { + name = 'UpdateTableCommandOperatorAddColumnOrderNo1770089334925' + + public async up(queryRunner: QueryRunner): Promise { + await queryRunner.query(`ALTER TABLE \`commandOperator\` ADD \`orderNo\` int NULL COMMENT 'ลำดับบทบาทของเจ้าหน้าที่ดำเนินการ'`); + } + + public async down(queryRunner: QueryRunner): Promise { + await queryRunner.query(`ALTER TABLE \`commandOperator\` DROP COLUMN \`orderNo\``); + } + +}