diff --git a/Dockerfile b/Dockerfile index 951bb52..7b7967d 100644 --- a/Dockerfile +++ b/Dockerfile @@ -4,7 +4,8 @@ ENV PNPM_HOME="/pnpm" ENV PATH="$PNPM_HOME:$PATH" RUN corepack enable -RUN apt-get update && apt-get install -y openssl +RUN apt-get update && apt-get install -y openssl fontconfig +RUN fc-cache -f -v RUN pnpm i -g prisma prisma-kysely WORKDIR /app diff --git a/prisma/migrations/20250513084929_add/migration.sql b/prisma/migrations/20250513084929_add/migration.sql new file mode 100644 index 0000000..f982e5b --- /dev/null +++ b/prisma/migrations/20250513084929_add/migration.sql @@ -0,0 +1,3 @@ +-- AlterTable +ALTER TABLE "QuotationWorker" ADD COLUMN "createdAt" TIMESTAMP(3) NOT NULL DEFAULT CURRENT_TIMESTAMP, +ADD COLUMN "updatedAt" TIMESTAMP(3) NOT NULL DEFAULT CURRENT_TIMESTAMP; diff --git a/prisma/schema.prisma b/prisma/schema.prisma index 73be520..47f82d6 100644 --- a/prisma/schema.prisma +++ b/prisma/schema.prisma @@ -1410,6 +1410,9 @@ model QuotationWorker { employeeId String quotation Quotation @relation(fields: [quotationId], references: [id], onDelete: Cascade) quotationId String + + createdAt DateTime @default(now()) + updatedAt DateTime @default(now()) @updatedAt } model QuotationProductServiceList { diff --git a/src/controllers/07-task-controller.ts b/src/controllers/07-task-controller.ts index 5e9977c..e806797 100644 --- a/src/controllers/07-task-controller.ts +++ b/src/controllers/07-task-controller.ts @@ -606,7 +606,28 @@ export class TaskActionController extends Controller { return await prisma.$transaction(async (tx) => { const promises = body.map(async (v) => { const record = await tx.task.findFirst({ - include: { requestWorkStep: true }, + include: { + requestWorkStep: { + include: { + requestWork: { + include: { + request: { + include: { + quotation: true, + employee: true, + }, + }, + productService: { + include: { + product: true, + }, + }, + }, + }, + }, + }, + taskOrder: true, + }, where: { step: v.step, requestWorkId: v.requestWorkId, @@ -624,6 +645,24 @@ export class TaskActionController extends Controller { data: { userTaskStatus: UserTaskStatus.Restart }, }); } + + if (v.taskStatus === TaskStatus.Failed) { + const taskCode = record.taskOrder.code; + const taskName = record.taskOrder.taskName; + const productCode = record.requestWorkStep.requestWork.productService.product.code; + const productName = record.requestWorkStep.requestWork.productService.product.name; + const employeeName = `${record.requestWorkStep.requestWork.request.employee.namePrefix}.${record.requestWorkStep.requestWork.request.employee.firstNameEN} ${record.requestWorkStep.requestWork.request.employee.lastNameEN}`; + + await tx.notification.create({ + data: { + title: "ใบรายการคำขอที่จัดการเกิดปัญหา / Task Failed", + detail: `ใบรายการคำขอรหัส ${taskCode}: ${taskName} รหัสสินค้า ${productCode}: ${productName} ของลูกจ้าง ${employeeName} เกิดข้อผิดพลาด`, + groupReceiver: { create: { name: "document_checker" } }, + registeredBranchId: record.taskOrder.registeredBranchId, + }, + }); + } + return await tx.task.update({ where: { id: record.id }, data: { diff --git a/src/services/schedule.ts b/src/services/schedule.ts index bd12bf8..dd0591e 100644 --- a/src/services/schedule.ts +++ b/src/services/schedule.ts @@ -2,6 +2,7 @@ import dayjs from "dayjs"; import { CronJob } from "cron"; import prisma from "../db"; +import { Prisma } from "@prisma/client"; const jobs = [ CronJob.from({ @@ -38,6 +39,162 @@ const jobs = [ .catch((e) => console.error("[ERR]: Update expired quotation status, FAILED.", e)); }, }), + CronJob.from({ + cronTime: "0 0 0 * * *", + runOnInit: true, + onTick: async () => { + const employeeExpireData = await prisma.employee.findMany({ + include: { + employeePassport: { + orderBy: { + expireDate: "desc", + }, + take: 1, + }, + customerBranch: { + include: { + customer: true, + }, + }, + quotationWorker: { + include: { + quotation: true, + }, + orderBy: { + createdAt: "desc", + }, + take: 1, + }, + }, + where: { + employeePassport: { + some: { + expireDate: dayjs().add(90, "day").toDate(), + }, + }, + }, + }); + + await Promise.all( + employeeExpireData.map(async (record) => { + const fullName = `${record.namePrefix}.${record.firstNameEN} ${record.lastNameEN}`; + const expireDate = `${dayjs(record.employeePassport[0].expireDate).format("DD/MM")}/${dayjs(record.employeePassport[0].expireDate).year() + 543}`; + const textDetail = `ลูกจ้างรหัส / code : ${record.code} ชื่อ : ${fullName} หนังสือเดินทางจะหมดอายุในวันที่ ${expireDate}`; + const duplicateText = await prisma.notification.findFirst({ + where: { + detail: textDetail, + }, + }); + + const dataNotification: Prisma.NotificationCreateArgs["data"] = { + title: "หนังสือเดินทางลูกจ้างหมดอายุ / Employee Passport Expire", + detail: textDetail, + }; + + if (record.quotationWorker && record.quotationWorker.length > 0) { + dataNotification.receiverId = record.quotationWorker[0].quotation.updatedByUserId; + dataNotification.registeredBranchId = + record.quotationWorker[0].quotation.registeredBranchId; + } else { + (dataNotification.groupReceiver = { + create: [{ name: "sale" }, { name: "head_of_sale" }], + }), + (dataNotification.registeredBranchId = + record.customerBranch.customer.registeredBranchId); + } + + if (!duplicateText) { + await prisma.notification + .create({ + data: dataNotification, + }) + .then(() => console.log("[INFO]: Create notification employee passport expired, OK.")) + .catch((e) => + console.error("[ERR]: Create notification employee passport expired, FAILED.", e), + ); + } + }), + ); + }, + }), + CronJob.from({ + cronTime: "0 0 0 * * *", + runOnInit: true, + onTick: async () => { + const employeeVisaData = await prisma.employee.findMany({ + include: { + employeeVisa: { + orderBy: { + expireDate: "desc", + }, + take: 1, + }, + customerBranch: { + include: { + customer: true, + }, + }, + quotationWorker: { + include: { + quotation: true, + }, + orderBy: { + createdAt: "desc", + }, + take: 1, + }, + }, + where: { + employeeVisa: { + some: { + expireDate: dayjs().add(90, "day").toDate(), + }, + }, + }, + }); + + await Promise.all( + employeeVisaData.map(async (record) => { + const fullName = `${record.namePrefix}.${record.firstNameEN} ${record.lastNameEN}`; + const expireDate = `${dayjs(record.employeeVisa[0].expireDate).format("DD/MM")}/${dayjs(record.employeeVisa[0].expireDate).year() + 543}`; + const textDetail = `ลูกจ้างรหัส / code : ${record.code} ชื่อ : ${fullName} ข้อมูลการตรวจลงตราจะหมดอายุในวันที่ ${expireDate}`; + const duplicateText = await prisma.notification.findFirst({ + where: { + detail: textDetail, + }, + }); + + const dataNotification: Prisma.NotificationCreateArgs["data"] = { + title: "ข้อมูลการตรวจลงตราลูกจ้างหมดอายุ / Employee Visa Expire", + detail: textDetail, + }; + + if (record.quotationWorker && record.quotationWorker.length > 0) { + dataNotification.receiverId = record.quotationWorker[0].quotation.updatedByUserId; + dataNotification.registeredBranchId = + record.quotationWorker[0].quotation.registeredBranchId; + } else { + (dataNotification.groupReceiver = { + create: [{ name: "sale" }, { name: "head_of_sale" }], + }), + (dataNotification.registeredBranchId = + record.customerBranch.customer.registeredBranchId); + } + + if (!duplicateText) { + await prisma.notification + .create({ + data: dataNotification, + }) + .then(() => console.log("[INFO]: Create notification employee visa expired, OK.")) + .catch((e) => + console.error("[ERR]: Create notification employee visa expired, FAILED.", e), + ); + } + }), + ); + }, + }), ]; export function initSchedule() {