diff --git a/package.json b/package.json index 7462ca4..b4a9e4f 100644 --- a/package.json +++ b/package.json @@ -37,6 +37,7 @@ "@tsoa/runtime": "^6.5.1", "@types/morgan": "^1.9.9", "cors": "^2.8.5", + "cron": "^3.1.9", "dotenv": "^16.4.5", "express": "^4.21.1", "fast-jwt": "^4.0.5", diff --git a/pnpm-lock.yaml b/pnpm-lock.yaml index b94756e..8dd836b 100644 --- a/pnpm-lock.yaml +++ b/pnpm-lock.yaml @@ -29,6 +29,9 @@ importers: cors: specifier: ^2.8.5 version: 2.8.5 + cron: + specifier: ^3.1.9 + version: 3.1.9 dotenv: specifier: ^16.4.5 version: 16.4.5 @@ -429,6 +432,9 @@ packages: '@types/koa@2.15.0': resolution: {integrity: sha512-7QFsywoE5URbuVnG3loe03QXuGajrnotr3gQkXcEBShORai23MePfFYdhz90FEtBBpkyIYQbVD+evKtloCgX3g==} + '@types/luxon@3.4.2': + resolution: {integrity: sha512-TifLZlFudklWlMBfhubvgqTXRzLDI5pCbGa4P8a3wPyUQSW+1xQ5eDsreP9DWHX3tjq1ke96uYG/nwundroWcA==} + '@types/mime@1.3.5': resolution: {integrity: sha512-/pyBZWSLD2n0dcHE3hq8s8ZvcETHtEuF+3E7XVt0Ig2nvsVQXdghHVcEkIWjy9A0wKfTn97a/PSDYohKIlnP/w==} @@ -777,6 +783,9 @@ packages: create-require@1.1.1: resolution: {integrity: sha512-dcKFX3jn0MpIaXjisoRvexIJVEKzaq7z2rZKxf+MSr9TkdmHmsU4m2lcLojrj/FHl8mk5VxMmYA+ftRkP/3oKQ==} + cron@3.1.9: + resolution: {integrity: sha512-eNZu+YhLRHLxNJNqZgYuy8mXhzMV0XXmOSh+Ls2j1yTeQLCQ04ya7oNpujxwl4lEyck1fcVa1aRVZ+T4tAC7SA==} + cross-spawn@7.0.3: resolution: {integrity: sha512-iRDPJKUPVEND7dHPO8rkbOnPpyDygcDFtWjpeWNCgy8WP2rXcxXL8TskReQl6OrB2G7+UJrags1q15Fudc7G6w==} engines: {node: '>= 8'} @@ -1523,6 +1532,10 @@ packages: resolution: {integrity: sha512-Jo6dJ04CmSjuznwJSS3pUeWmd/H0ffTlkXXgwZi+eq1UCmqQwCh+eLsYOYCwY991i2Fah4h1BEMCx4qThGbsiA==} engines: {node: '>=10'} + luxon@3.5.0: + resolution: {integrity: sha512-rh+Zjr6DNfUYR3bPwJEnuwDdqMbxZW7LOQfUN4B54+Cl+0o5zaU9RJ6bcidfDtC1cWCZXQ+nvX8bf6bAji37QQ==} + engines: {node: '>=12'} + make-dir@3.1.0: resolution: {integrity: sha512-g3FeP20LNwhALb/6Cz6Dd4F2ngze0jz7tbzrD2wAV+o9FeNHe4rL+yK2md0J/fiSf1sa1ADhXqi5+oVwOM/eGw==} engines: {node: '>=8'} @@ -3070,6 +3083,8 @@ snapshots: '@types/koa-compose': 3.2.8 '@types/node': 20.17.6 + '@types/luxon@3.4.2': {} + '@types/mime@1.3.5': {} '@types/mime@4.0.0': @@ -3486,6 +3501,11 @@ snapshots: create-require@1.1.1: {} + cron@3.1.9: + dependencies: + '@types/luxon': 3.4.2 + luxon: 3.5.0 + cross-spawn@7.0.3: dependencies: path-key: 3.1.1 @@ -4348,6 +4368,8 @@ snapshots: dependencies: yallist: 4.0.0 + luxon@3.5.0: {} + make-dir@3.1.0: dependencies: semver: 6.3.1 diff --git a/prisma/schema.prisma b/prisma/schema.prisma index 6b2db61..5432747 100644 --- a/prisma/schema.prisma +++ b/prisma/schema.prisma @@ -1166,6 +1166,7 @@ enum QuotationStatus { PaymentSuccess ProcessComplete Canceled + Expired } enum PayCondition { diff --git a/src/app.ts b/src/app.ts index f429970..bf4756a 100644 --- a/src/app.ts +++ b/src/app.ts @@ -7,6 +7,7 @@ import { RegisterRoutes } from "./routes"; import { initThailandAreaDatabase } from "./utils/thailand-area"; import { initFirstAdmin } from "./utils/database"; import { apiReference } from "@scalar/express-api-reference"; +import { initSchedule } from "./services/schedule"; const APP_HOST = process.env.APP_HOST || "0.0.0.0"; const APP_PORT = +(process.env.APP_PORT || 3000); @@ -17,6 +18,8 @@ const APP_PORT = +(process.env.APP_PORT || 3000); await initThailandAreaDatabase(); await initFirstAdmin(); + initSchedule(); + const originalSend = app.response.json; app.response.json = function (body: unknown) { diff --git a/src/services/schedule.ts b/src/services/schedule.ts new file mode 100644 index 0000000..933fe2c --- /dev/null +++ b/src/services/schedule.ts @@ -0,0 +1,25 @@ +import { CronJob } from "cron"; + +import prisma from "../db"; + +const jobs = [ + CronJob.from({ + cronTime: "0 0 0 * * *", + runOnInit: true, + onTick: async () => { + await prisma.quotation + .updateMany({ + where: { + dueDate: { lte: new Date() }, + }, + data: { quotationStatus: "Expired" }, + }) + .then(() => console.log("[INFO]: Update expired quotation status, OK.")) + .catch((e) => console.error(e)); + }, + }), +]; + +export function initSchedule() { + for (const job of jobs) job.start(); +}