"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); }; Object.defineProperty(exports, "__esModule", { value: true }); exports.ShipmentsService = void 0; const common_1 = require("@nestjs/common"); const client_1 = require("@prisma/client"); const prisma_service_1 = require("../prisma/prisma.service"); const name_1 = require("../common/utils/name"); const notifications_service_1 = require("../notifications/notifications.service"); const notification_events_1 = require("../notifications/notification-events"); const STATUS_FLOW = [ client_1.ShipmentStatus.preparing, client_1.ShipmentStatus.ready, client_1.ShipmentStatus.shipped, client_1.ShipmentStatus.delivered, ]; const SHIPMENT_TO_ORDER = { preparing: client_1.OrderStatus.preparing, ready: client_1.OrderStatus.ready_to_ship, shipped: client_1.OrderStatus.shipped, delivered: client_1.OrderStatus.delivered, }; let ShipmentsService = class ShipmentsService { prisma; notifications; constructor(prisma, notifications) { this.prisma = prisma; this.notifications = notifications; } async findAll(status) { const shipments = await this.prisma.shipment.findMany({ where: status ? { status } : undefined, orderBy: { createdAt: 'desc' }, include: { order: { include: { user: true } }, }, }); return shipments.map((s) => this.map(s)); } async findOne(id) { const shipment = await this.prisma.shipment.findUnique({ where: { id }, include: { order: { include: { user: true } } }, }); if (!shipment) throw new common_1.NotFoundException('ارسال یافت نشد'); return this.map(shipment); } async create(adminId, dto) { const order = await this.prisma.order.findUnique({ where: { id: dto.orderId }, include: { shipment: true, user: true }, }); if (!order) throw new common_1.NotFoundException('سفارش یافت نشد'); if (order.shipment) { throw new common_1.ConflictException('برای این سفارش قبلاً ارسال ثبت شده است'); } const status = dto.status ?? client_1.ShipmentStatus.preparing; const shipment = await this.prisma.$transaction(async (tx) => { const created = await tx.shipment.create({ data: { orderId: order.id, carrier: dto.carrier.trim(), trackingNumber: dto.trackingNumber?.trim() || null, meterage: dto.meterage ?? order.totalMeterage, status, shippedAt: status === client_1.ShipmentStatus.shipped ? new Date() : null, deliveredAt: status === client_1.ShipmentStatus.delivered ? new Date() : null, }, include: { order: { include: { user: true } } }, }); const nextOrderStatus = SHIPMENT_TO_ORDER[status]; if (order.status !== nextOrderStatus) { await tx.order.update({ where: { id: order.id }, data: { status: nextOrderStatus }, }); await tx.orderStatusHistory.create({ data: { orderId: order.id, fromStatus: order.status, toStatus: nextOrderStatus, changedBy: `admin:${adminId}`, note: 'ثبت ارسال', }, }); } return created; }); this.notifyOrderStatus(order.id, SHIPMENT_TO_ORDER[status], { carrier: shipment.carrier, trackingNumber: shipment.trackingNumber, }); return this.map(shipment); } async update(id, dto) { await this.ensure(id); const shipment = await this.prisma.shipment.update({ where: { id }, data: { carrier: dto.carrier?.trim(), trackingNumber: dto.trackingNumber === undefined ? undefined : dto.trackingNumber?.trim() || null, meterage: dto.meterage, status: dto.status, }, include: { order: { include: { user: true } } }, }); return this.map(shipment); } async advanceStatus(id, adminId, dto) { const shipment = await this.prisma.shipment.findUnique({ where: { id }, include: { order: { include: { user: true } } }, }); if (!shipment) throw new common_1.NotFoundException('ارسال یافت نشد'); let nextStatus = dto.status; if (!nextStatus) { const idx = STATUS_FLOW.indexOf(shipment.status); if (idx < 0 || idx >= STATUS_FLOW.length - 1) { throw new common_1.BadRequestException('وضعیت ارسال قابل پیشرفت نیست'); } nextStatus = STATUS_FLOW[idx + 1]; } const updated = await this.prisma.$transaction(async (tx) => { const result = await tx.shipment.update({ where: { id }, data: { status: nextStatus, trackingNumber: dto.trackingNumber !== undefined ? dto.trackingNumber.trim() || null : undefined, shippedAt: nextStatus === client_1.ShipmentStatus.shipped ? (shipment.shippedAt ?? new Date()) : shipment.shippedAt, deliveredAt: nextStatus === client_1.ShipmentStatus.delivered ? new Date() : shipment.deliveredAt, }, include: { order: { include: { user: true } } }, }); const nextOrderStatus = SHIPMENT_TO_ORDER[nextStatus]; if (shipment.order.status !== nextOrderStatus) { await tx.order.update({ where: { id: shipment.orderId }, data: { status: nextOrderStatus }, }); await tx.orderStatusHistory.create({ data: { orderId: shipment.orderId, fromStatus: shipment.order.status, toStatus: nextOrderStatus, changedBy: `admin:${adminId}`, note: `وضعیت ارسال: ${nextStatus}`, }, }); } return result; }); this.notifyOrderStatus(shipment.orderId, SHIPMENT_TO_ORDER[nextStatus], { carrier: updated.carrier, trackingNumber: updated.trackingNumber, }); return this.map(updated); } notifyOrderStatus(orderId, status, context) { const event = (0, notification_events_1.eventForStatus)(status); if (event) { this.notifications.dispatchOrderEvent(orderId, event, context); } } async ensure(id) { const shipment = await this.prisma.shipment.findUnique({ where: { id } }); if (!shipment) throw new common_1.NotFoundException('ارسال یافت نشد'); return shipment; } map(s) { return { id: s.id, orderId: s.orderId, orderNumber: s.order.orderNumber, customerName: (0, name_1.joinFullName)(s.order.user.firstName, s.order.user.lastName), carrier: s.carrier, trackingNumber: s.trackingNumber ?? '', meterage: s.meterage, status: s.status, shippedAt: s.shippedAt?.toISOString() ?? null, deliveredAt: s.deliveredAt?.toISOString() ?? null, createdAt: s.createdAt.toISOString(), updatedAt: s.updatedAt.toISOString(), }; } }; exports.ShipmentsService = ShipmentsService; exports.ShipmentsService = ShipmentsService = __decorate([ (0, common_1.Injectable)(), __metadata("design:paramtypes", [prisma_service_1.PrismaService, notifications_service_1.NotificationsService]) ], ShipmentsService); //# sourceMappingURL=shipments.service.js.map