Files
fabric_trade_server/dist/orders/cash-invoice-scheduler.service.js
T
mohmdsdgandCursor d4aaa8e997 Rebuild order flow: settle after pricing, notifications, and invoice expiry.
Hide prices until admin sends the invoice, enforce status transitions, add customer/admin SMS+in-app notifications, schedule cash invoice reminders, and ship updated dist/prisma-client/deploy-bundle for git-pull deploys.

Co-authored-by: Cursor <cursoragent@cursor.com>
2026-08-09 12:00:13 +03:30

118 lines
5.3 KiB
JavaScript

"use strict";
var __decorate = (this && this.__decorate) || function (decorators, target, key, desc) {
var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;
if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc);
else for (var i = decorators.length - 1; i >= 0; i--) if (d = decorators[i]) r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r;
return c > 3 && r && Object.defineProperty(target, key, r), r;
};
var __metadata = (this && this.__metadata) || function (k, v) {
if (typeof Reflect === "object" && typeof Reflect.metadata === "function") return Reflect.metadata(k, v);
};
var CashInvoiceSchedulerService_1;
Object.defineProperty(exports, "__esModule", { value: true });
exports.CashInvoiceSchedulerService = void 0;
const common_1 = require("@nestjs/common");
const schedule_1 = require("@nestjs/schedule");
const client_1 = require("@prisma/client");
const prisma_service_1 = require("../prisma/prisma.service");
const notifications_service_1 = require("../notifications/notifications.service");
const PAYABLE_STATUSES = [
client_1.OrderStatus.awaiting_cash_payment,
client_1.OrderStatus.cash_invoice_issued,
];
const REMINDER_WINDOW_MS = 60 * 60 * 1000;
let CashInvoiceSchedulerService = CashInvoiceSchedulerService_1 = class CashInvoiceSchedulerService {
prisma;
notifications;
logger = new common_1.Logger(CashInvoiceSchedulerService_1.name);
constructor(prisma, notifications) {
this.prisma = prisma;
this.notifications = notifications;
}
async handleCashInvoices() {
await this.sendReminders();
await this.expireOverdueInvoices();
}
async sendReminders() {
const now = new Date();
const soon = new Date(now.getTime() + REMINDER_WINDOW_MS);
try {
const orders = await this.prisma.order.findMany({
where: {
status: { in: PAYABLE_STATUSES },
cashReminderSentAt: null,
cashInvoiceExpiresAt: { gt: now, lte: soon },
},
select: { id: true, finalAmount: true },
});
for (const order of orders) {
await this.prisma.order.update({
where: { id: order.id },
data: { cashReminderSentAt: now },
});
await this.notifications.notifyOrderEvent(order.id, 'cash_invoice_reminder', { amount: order.finalAmount });
}
return orders.length;
}
catch (err) {
this.logger.error('sendReminders failed', err instanceof Error ? err.stack : err);
return 0;
}
}
async expireOverdueInvoices() {
const now = new Date();
try {
const orders = await this.prisma.order.findMany({
where: {
status: { in: PAYABLE_STATUSES },
cashInvoiceExpiresAt: { lt: now },
},
select: { id: true, orderNumber: true, status: true },
});
for (const order of orders) {
await this.prisma.$transaction([
this.prisma.order.update({
where: { id: order.id },
data: { status: client_1.OrderStatus.expired },
}),
this.prisma.orderStatusHistory.create({
data: {
orderId: order.id,
fromStatus: order.status,
toStatus: client_1.OrderStatus.expired,
changedBy: 'system',
note: 'پایان مهلت پرداخت فاکتور نقدی',
},
}),
]);
await this.notifications.notifyOrderEvent(order.id, 'cash_invoice_expired');
this.notifications.dispatchAdmin({
title: 'فاکتور نقدی منقضی شد',
body: `مهلت پرداخت سفارش ${order.orderNumber} به پایان رسید و سفارش منقضی شد.`,
link: '/orders',
});
}
if (orders.length) {
this.logger.log(`${orders.length} فاکتور نقدی منقضی شد`);
}
return orders.length;
}
catch (err) {
this.logger.error('expireOverdueInvoices failed', err instanceof Error ? err.stack : err);
return 0;
}
}
};
exports.CashInvoiceSchedulerService = CashInvoiceSchedulerService;
__decorate([
(0, schedule_1.Cron)(schedule_1.CronExpression.EVERY_10_MINUTES),
__metadata("design:type", Function),
__metadata("design:paramtypes", []),
__metadata("design:returntype", Promise)
], CashInvoiceSchedulerService.prototype, "handleCashInvoices", null);
exports.CashInvoiceSchedulerService = CashInvoiceSchedulerService = CashInvoiceSchedulerService_1 = __decorate([
(0, common_1.Injectable)(),
__metadata("design:paramtypes", [prisma_service_1.PrismaService,
notifications_service_1.NotificationsService])
], CashInvoiceSchedulerService);
//# sourceMappingURL=cash-invoice-scheduler.service.js.map