225 lines
7.1 KiB
TypeScript
225 lines
7.1 KiB
TypeScript
|
|
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();
|
||
|
|
}
|
||
|
|
}
|
||
|
|
|
||
|
|
}
|