diff --git a/src/controllers/04-product-controller.ts b/src/controllers/04-product-controller.ts index b73bd3a..6e07f98 100644 --- a/src/controllers/04-product-controller.ts +++ b/src/controllers/04-product-controller.ts @@ -374,6 +374,7 @@ export class ProductController extends Controller { const record = await prisma.product.update({ include: { + productGroup: true, createdBy: true, updatedBy: true, }, @@ -398,6 +399,17 @@ export class ProductController extends Controller { }); } + await prisma.notification.create({ + data: { + title: "สินค้ามีการเปลี่ยนแปลง / Product Updated", + detail: "รหัส / code : " + record.code, + groupReceiver: { + create: [{ name: "sale" }, { name: "head_of_sale" }], + }, + registeredBranchId: record.productGroup.registeredBranchId, + }, + }); + return record; } diff --git a/src/controllers/04-service-controller.ts b/src/controllers/04-service-controller.ts index c48d948..0670295 100644 --- a/src/controllers/04-service-controller.ts +++ b/src/controllers/04-service-controller.ts @@ -473,6 +473,7 @@ export class ServiceController extends Controller { return await tx.service.update({ include: { + productGroup: true, createdBy: true, updatedBy: true, }, @@ -523,6 +524,17 @@ export class ServiceController extends Controller { }); }); + await prisma.notification.create({ + data: { + title: "แพคเกจมีการเปลี่ยนแปลง / Package Updated", + detail: "รหัส / code : " + record.code, + groupReceiver: { + create: [{ name: "sale" }, { name: "head_of_sale" }], + }, + registeredBranchId: record.productGroup.registeredBranchId, + }, + }); + return record; } diff --git a/src/controllers/05-payment-controller.ts b/src/controllers/05-payment-controller.ts index 1177dba..a4b7339 100644 --- a/src/controllers/05-payment-controller.ts +++ b/src/controllers/05-payment-controller.ts @@ -177,55 +177,66 @@ export class QuotationPayment extends Controller { }, }); - await tx.quotation.update({ - where: { id: quotation.id }, - data: { - quotationStatus: - (paymentSum._sum.amount || 0) >= quotation.finalPrice - ? "PaymentSuccess" - : "PaymentInProcess", - requestData: await (async () => { - if ( - body.paymentStatus === "PaymentSuccess" && - (paymentSum._sum.amount || 0) - payment.amount <= 0 - ) { - const lastRequest = await tx.runningNo.upsert({ - where: { - key: `REQUEST_${year}${month}`, - }, - create: { - key: `REQUEST_${year}${month}`, - value: quotation.worker.length, - }, - update: { value: { increment: quotation.worker.length } }, - }); - return { - create: quotation.worker.flatMap((v, i) => { - const productEmployee = quotation.productServiceList.flatMap((item) => - item.worker.findIndex((w) => w.employeeId === v.employeeId) !== -1 - ? { productServiceId: item.id } - : [], - ); + await tx.quotation + .update({ + where: { id: quotation.id }, + data: { + quotationStatus: + (paymentSum._sum.amount || 0) >= quotation.finalPrice + ? "PaymentSuccess" + : "PaymentInProcess", + requestData: await (async () => { + if ( + body.paymentStatus === "PaymentSuccess" && + (paymentSum._sum.amount || 0) - payment.amount <= 0 + ) { + const lastRequest = await tx.runningNo.upsert({ + where: { + key: `REQUEST_${year}${month}`, + }, + create: { + key: `REQUEST_${year}${month}`, + value: quotation.worker.length, + }, + update: { value: { increment: quotation.worker.length } }, + }); + return { + create: quotation.worker.flatMap((v, i) => { + const productEmployee = quotation.productServiceList.flatMap((item) => + item.worker.findIndex((w) => w.employeeId === v.employeeId) !== -1 + ? { productServiceId: item.id } + : [], + ); - if (productEmployee.length <= 0) return []; + if (productEmployee.length <= 0) return []; - return { - code: `TR${year}${month}${(lastRequest.value - quotation.worker.length + i + 1).toString().padStart(6, "0")}`, - employeeId: v.employeeId, - requestWork: { - create: quotation.productServiceList.flatMap((item) => - item.worker.findIndex((w) => w.employeeId === v.employeeId) !== -1 - ? { productServiceId: item.id } - : [], - ), - }, - }; - }), - }; - } - })(), - }, - }); + return { + code: `TR${year}${month}${(lastRequest.value - quotation.worker.length + i + 1).toString().padStart(6, "0")}`, + employeeId: v.employeeId, + requestWork: { + create: quotation.productServiceList.flatMap((item) => + item.worker.findIndex((w) => w.employeeId === v.employeeId) !== -1 + ? { productServiceId: item.id } + : [], + ), + }, + }; + }), + }; + } + })(), + }, + }) + .then(async (res) => { + if (quotation.quotationStatus !== res.quotationStatus) + await tx.notification.create({ + data: { + title: "สถานะใบเสนอราคาเปลี่ยนแปลง / Quotation Status Updated", + detail: "รหัส / code : " + res.code + " " + res.quotationStatus, + receiverId: res.createdByUserId, + }, + }); + }); return payment; }); diff --git a/src/controllers/05-quotation-controller.ts b/src/controllers/05-quotation-controller.ts index 9ae2ae1..bf0f0e5 100644 --- a/src/controllers/05-quotation-controller.ts +++ b/src/controllers/05-quotation-controller.ts @@ -454,7 +454,7 @@ export class QuotationController extends Controller { const { productServiceList: _productServiceList, worker: _worker, ...rest } = body; - return await prisma.$transaction(async (tx) => { + const ret = await prisma.$transaction(async (tx) => { const nonExistEmployee = body.worker.filter((v) => typeof v !== "string"); const lastEmployee = await tx.runningNo.upsert({ where: { @@ -639,6 +639,17 @@ export class QuotationController extends Controller { }, }); }); + + await prisma.notification.create({ + data: { + title: "ใบเสนอราคาใหม่ / New Quotation", + detail: "รหัส / code : " + ret.code, + registeredBranchId: ret.registeredBranchId, + groupReceiver: { create: [{ name: "accountant" }, { name: "head_of_accountant" }] }, + }, + }); + + return ret; } @Put("{quotationId}") @@ -1125,41 +1136,53 @@ export class QuotationActionController extends Controller { }, update: { value: { increment: quotation.worker.length } }, }); - await tx.quotation.update({ - where: { id: quotationId, isDebitNote: false }, - data: { - quotationStatus: QuotationStatus.PaymentSuccess, // NOTE: change back if already complete or canceled - worker: { - createMany: { - data: rearrange - .filter((lhs) => !quotation.worker.find((rhs) => rhs.employeeId === lhs.workerId)) - .map((v, i) => ({ - no: quotation._count.worker + i + 1, - employeeId: v.workerId, - })), + await tx.quotation + .update({ + include: { requestData: true }, + where: { id: quotationId, isDebitNote: false }, + data: { + quotationStatus: QuotationStatus.PaymentSuccess, // NOTE: change back if already complete or canceled + worker: { + createMany: { + data: rearrange + .filter((lhs) => !quotation.worker.find((rhs) => rhs.employeeId === lhs.workerId)) + .map((v, i) => ({ + no: quotation._count.worker + i + 1, + employeeId: v.workerId, + })), + }, }, + requestData: + quotation.quotationStatus === "PaymentInProcess" || + quotation.quotationStatus === "PaymentSuccess" + ? { + create: rearrange + .filter( + (lhs) => + !quotation.worker.find((rhs) => rhs.employeeId === lhs.workerId) && + lhs.productServiceId.length > 0, + ) + .map((v, i) => ({ + code: `TR${year}${month}${(lastRequest.value - quotation._count.worker + i + 1).toString().padStart(6, "0")}`, + employeeId: v.workerId, + requestWork: { + create: v.productServiceId.map((v) => ({ productServiceId: v })), + }, + })), + } + : undefined, }, - requestData: - quotation.quotationStatus === "PaymentInProcess" || - quotation.quotationStatus === "PaymentSuccess" - ? { - create: rearrange - .filter( - (lhs) => - !quotation.worker.find((rhs) => rhs.employeeId === lhs.workerId) && - lhs.productServiceId.length > 0, - ) - .map((v, i) => ({ - code: `TR${year}${month}${(lastRequest.value - quotation._count.worker + i + 1).toString().padStart(6, "0")}`, - employeeId: v.workerId, - requestWork: { - create: v.productServiceId.map((v) => ({ productServiceId: v })), - }, - })), - } - : undefined, - }, - }); + }) + .then(async (ret) => { + await prisma.notification.create({ + data: { + title: "รายการคำขอใหม่ / New Request", + detail: "รหัส / code : " + ret.requestData.map((v) => v.code).join(", "), + registeredBranchId: ret.registeredBranchId, + groupReceiver: { create: { name: "document_checker" } }, + }, + }); + }); }); } } diff --git a/src/controllers/06-request-list-controller.ts b/src/controllers/06-request-list-controller.ts index bbb2e39..8464c03 100644 --- a/src/controllers/06-request-list-controller.ts +++ b/src/controllers/06-request-list-controller.ts @@ -268,14 +268,24 @@ export class RequestDataActionController extends Controller { }), ]); await Promise.all([ - tx.quotation.updateMany({ - where: { - requestData: { - every: { requestDataStatus: RequestDataStatus.Canceled }, + tx.quotation + .updateManyAndReturn({ + where: { + requestData: { + every: { requestDataStatus: RequestDataStatus.Canceled }, + }, }, - }, - data: { quotationStatus: QuotationStatus.Canceled, urgent: false }, - }), + data: { quotationStatus: QuotationStatus.Canceled, urgent: false }, + }) + .then(async (res) => { + await tx.notification.createMany({ + data: res.map((v) => ({ + title: "สถานะใบเสนอราคาเปลี่ยนแปลง / Quotation Status Updated", + detail: "รหัส / code : " + v.code + " Canceled", + receiverId: v.createdByUserId, + })), + }); + }), tx.taskOrder.updateMany({ where: { taskList: { @@ -405,14 +415,25 @@ export class RequestDataActionController extends Controller { data: { taskStatus: TaskStatus.Canceled }, }); await Promise.all([ - tx.quotation.updateMany({ - where: { - requestData: { - every: { requestDataStatus: RequestDataStatus.Canceled }, + tx.quotation + .updateManyAndReturn({ + where: { + quotationStatus: { not: QuotationStatus.Canceled }, + requestData: { + every: { requestDataStatus: RequestDataStatus.Canceled }, + }, }, - }, - data: { quotationStatus: QuotationStatus.Canceled, urgent: false }, - }), + data: { quotationStatus: QuotationStatus.Canceled, urgent: false }, + }) + .then(async (res) => { + await tx.notification.createMany({ + data: res.map((v) => ({ + title: "สถานะใบเสนอราคาเปลี่ยนแปลง / Quotation Status Updated", + detail: "รหัส / code : " + v.code + " Canceled", + receiverId: v.createdByUserId, + })), + }); + }), tx.taskOrder.updateMany({ where: { taskList: { @@ -479,21 +500,31 @@ export class RequestDataActionController extends Controller { where: { id: { in: completed } }, data: { requestDataStatus: RequestDataStatus.Completed }, }); - await tx.quotation.updateMany({ - where: { - quotationStatus: { - notIn: [QuotationStatus.Canceled, QuotationStatus.ProcessComplete], - }, - requestData: { - every: { - requestDataStatus: { - in: [RequestDataStatus.Canceled, RequestDataStatus.Completed], + await tx.quotation + .updateManyAndReturn({ + where: { + quotationStatus: { + notIn: [QuotationStatus.Canceled, QuotationStatus.ProcessComplete], + }, + requestData: { + every: { + requestDataStatus: { + in: [RequestDataStatus.Canceled, RequestDataStatus.Completed], + }, }, }, }, - }, - data: { quotationStatus: QuotationStatus.ProcessComplete, urgent: false }, - }); + data: { quotationStatus: QuotationStatus.ProcessComplete, urgent: false }, + }) + .then(async (res) => { + await tx.notification.createMany({ + data: res.map((v) => ({ + title: "สถานะใบเสนอราคาเปลี่ยนแปลง / Quotation Status Updated", + detail: "รหัส / code : " + v.code + " Completed", + receiverId: v.createdByUserId, + })), + }); + }); // dataRecord.push(record); return data; }); @@ -812,14 +843,25 @@ export class RequestListController extends Controller { data: { taskStatus: TaskStatus.Canceled }, }); await Promise.all([ - tx.quotation.updateMany({ - where: { - requestData: { - every: { requestDataStatus: RequestDataStatus.Canceled }, + tx.quotation + .updateManyAndReturn({ + where: { + quotationStatus: { not: QuotationStatus.Canceled }, + requestData: { + every: { requestDataStatus: RequestDataStatus.Canceled }, + }, }, - }, - data: { quotationStatus: QuotationStatus.Canceled, urgent: false }, - }), + data: { quotationStatus: QuotationStatus.Canceled, urgent: false }, + }) + .then(async (res) => { + await tx.notification.createMany({ + data: res.map((v) => ({ + title: "สถานะใบเสนอราคาเปลี่ยนแปลง / Quotation Status Updated", + detail: "รหัส / code : " + v.code + " Canceled", + receiverId: v.createdByUserId, + })), + }); + }), tx.taskOrder.updateMany({ where: { taskList: { @@ -887,19 +929,32 @@ export class RequestListController extends Controller { where: { id: { in: completed } }, data: { requestDataStatus: RequestDataStatus.Completed }, }); - await tx.quotation.updateMany({ - where: { - quotationStatus: { - notIn: [QuotationStatus.Canceled, QuotationStatus.ProcessComplete], - }, - requestData: { - every: { - requestDataStatus: { in: [RequestDataStatus.Canceled, RequestDataStatus.Completed] }, + await tx.quotation + .updateManyAndReturn({ + where: { + quotationStatus: { + notIn: [QuotationStatus.Canceled, QuotationStatus.ProcessComplete], + }, + requestData: { + every: { + requestDataStatus: { + in: [RequestDataStatus.Canceled, RequestDataStatus.Completed], + }, + }, }, }, - }, - data: { quotationStatus: QuotationStatus.ProcessComplete, urgent: false }, - }); + data: { quotationStatus: QuotationStatus.ProcessComplete, urgent: false }, + }) + .then(async (res) => { + await tx.notification.createMany({ + data: res.map((v) => ({ + title: "สถานะใบเสนอราคาเปลี่ยนแปลง / Quotation Status Updated", + detail: "รหัส / code : " + v.code + " Completed", + receiverId: v.createdByUserId, + })), + }); + }); + return record; }); } diff --git a/src/controllers/07-task-controller.ts b/src/controllers/07-task-controller.ts index a572962..2722c04 100644 --- a/src/controllers/07-task-controller.ts +++ b/src/controllers/07-task-controller.ts @@ -433,88 +433,101 @@ export class TaskController extends Controller { ); } - return await prisma.$transaction(async (tx) => { - await Promise.all( - record.taskList - .filter( - (lhs) => - !body.taskList.find( - (rhs) => lhs.requestWorkId === rhs.requestWorkId && lhs.step === rhs.step, - ), - ) - .map((v) => - tx.task.update({ - where: { id: v.id }, - data: { - requestWorkStep: { update: { workStatus: "Ready" } }, - }, - }), - ), - ); + return await prisma + .$transaction(async (tx) => { + await Promise.all( + record.taskList + .filter( + (lhs) => + !body.taskList.find( + (rhs) => lhs.requestWorkId === rhs.requestWorkId && lhs.step === rhs.step, + ), + ) + .map((v) => + tx.task.update({ + where: { id: v.id }, + data: { + requestWorkStep: { update: { workStatus: "Ready" } }, + }, + }), + ), + ); - await tx.requestWorkStepStatus.updateMany({ - where: { - OR: body.taskList, - workStatus: RequestWorkStatus.Ready, - }, - data: { workStatus: RequestWorkStatus.InProgress }, - }); - - const work = await tx.requestWorkStepStatus.findMany({ - include: { - requestWork: { - include: { - request: { - include: { quotation: true }, - }, - }, + await tx.requestWorkStepStatus.updateMany({ + where: { + OR: body.taskList, + workStatus: RequestWorkStatus.Ready, }, - }, - where: { OR: body.taskList }, - }); + data: { workStatus: RequestWorkStatus.InProgress }, + }); - return await tx.taskOrder.update({ - where: { id: taskOrderId }, - include: { - taskList: { - include: { - requestWorkStep: { - include: { - requestWork: true, + const work = await tx.requestWorkStepStatus.findMany({ + include: { + requestWork: { + include: { + request: { + include: { quotation: true }, }, }, }, }, - institution: true, - registeredBranch: true, - createdBy: true, - }, - data: { - ...body, - urgent: work.some((v) => v.requestWork.request.quotation.urgent), - taskList: { - deleteMany: record?.taskList - .filter( - (lhs) => - !body.taskList.find( - (rhs) => lhs.requestWorkId === rhs.requestWorkId && lhs.step === rhs.step, - ), - ) - .map((v) => ({ id: v.id })), - createMany: { - data: body.taskList.filter( - (lhs) => - !record?.taskList.find( - (rhs) => lhs.requestWorkId === rhs.requestWorkId && lhs.step === rhs.step, - ), - ), - skipDuplicates: true, + where: { OR: body.taskList }, + }); + + return await tx.taskOrder.update({ + where: { id: taskOrderId }, + include: { + taskList: { + include: { + requestWorkStep: { + include: { + requestWork: true, + }, + }, + }, }, + institution: true, + registeredBranch: true, + createdBy: true, }, - taskProduct: { deleteMany: {}, create: body.taskProduct }, - }, + data: { + ...body, + urgent: work.some((v) => v.requestWork.request.quotation.urgent), + taskList: { + deleteMany: record?.taskList + .filter( + (lhs) => + !body.taskList.find( + (rhs) => lhs.requestWorkId === rhs.requestWorkId && lhs.step === rhs.step, + ), + ) + .map((v) => ({ id: v.id })), + createMany: { + data: body.taskList.filter( + (lhs) => + !record?.taskList.find( + (rhs) => lhs.requestWorkId === rhs.requestWorkId && lhs.step === rhs.step, + ), + ), + skipDuplicates: true, + }, + }, + taskProduct: { deleteMany: {}, create: body.taskProduct }, + }, + }); + }) + .then(async (ret) => { + if (body.taskOrderStatus && record.taskOrderStatus !== body.taskOrderStatus) { + await prisma.notification.create({ + data: { + title: "มีการส่งงาน / Task Submitted", + detail: "รหัสใบสั่งงาน / Order : " + record.code, + receiverId: record.createdByUserId, + }, + }); + } + return ret; }); - }); } @Delete("{taskOrderId}") @@ -651,6 +664,13 @@ export class TaskActionController extends Controller { }, data: { userTaskStatus: UserTaskStatus.Submit, submittedAt: new Date() }, }), + prisma.notification.create({ + data: { + title: "มีการส่งงาน / Task Submitted", + detail: "รหัสใบสั่งงาน / Order : " + record.code, + receiverId: record.createdByUserId, + }, + }), ]); } @@ -785,19 +805,31 @@ export class TaskActionController extends Controller { where: { id: { in: completed } }, data: { requestDataStatus: RequestDataStatus.Completed }, }); - await tx.quotation.updateMany({ - where: { - quotationStatus: { - notIn: [QuotationStatus.Canceled, QuotationStatus.ProcessComplete], - }, - requestData: { - every: { - requestDataStatus: { in: [RequestDataStatus.Canceled, RequestDataStatus.Completed] }, + await tx.quotation + .updateManyAndReturn({ + where: { + quotationStatus: { + notIn: [QuotationStatus.Canceled, QuotationStatus.ProcessComplete], + }, + requestData: { + every: { + requestDataStatus: { + in: [RequestDataStatus.Canceled, RequestDataStatus.Completed], + }, + }, }, }, - }, - data: { quotationStatus: QuotationStatus.ProcessComplete, urgent: false }, - }); + data: { quotationStatus: QuotationStatus.ProcessComplete, urgent: false }, + }) + .then(async (res) => { + await tx.notification.createMany({ + data: res.map((v) => ({ + title: "สถานะใบเสนอราคาเปลี่ยนแปลง / Quotation Status Updated", + detail: "รหัส / code : " + v.code + " Completed", + receiverId: v.createdByUserId, + })), + }); + }); }); } } @@ -965,20 +997,37 @@ export class UserTaskController extends Controller { await prisma.$transaction(async (tx) => { const promises = body.taskOrderId.flatMap((taskOrderId) => [ - tx.taskOrder.update({ - where: { id: taskOrderId }, - data: { - taskOrderStatus: TaskOrderStatus.InProgress, - userTask: { - deleteMany: { userId: req.user.sub }, - create: { - userId: req.user.sub, - userTaskStatus: UserTaskStatus.Accept, - acceptedAt: new Date(), + tx.taskOrder + .update({ + where: { id: taskOrderId }, + data: { + taskOrderStatus: TaskOrderStatus.InProgress, + userTask: { + deleteMany: { userId: req.user.sub }, + create: { + userId: req.user.sub, + userTaskStatus: UserTaskStatus.Accept, + acceptedAt: new Date(), + }, }, }, - }, - }), + }) + .then(async (v) => { + await tx.notification.createMany({ + data: [ + { + title: "สถานะใบส่งงานมีการเปลี่ยนแปลง / Order Status Changed", + detail: "รหัสใบสั่งงาน / Order : " + v.code + " InProgress", + receiverId: v.createdByUserId, + }, + { + title: "มีการรับงาน / Task Accepted", + detail: "รหัสใบสั่งงาน / Order : " + v.code, + receiverId: v.createdByUserId, + }, + ], + }); + }), tx.task.updateMany({ where: { taskOrderId: taskOrderId,