"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.DashboardService = void 0; const common_1 = require("@nestjs/common"); const prisma_service_1 = require("../prisma/prisma.service"); const order_status_1 = require("../common/utils/order-status"); const orders_service_1 = require("../orders/orders.service"); let DashboardService = class DashboardService { prisma; ordersService; constructor(prisma, ordersService) { this.prisma = prisma; this.ordersService = ordersService; } async getDashboard() { const now = new Date(); const startOfToday = new Date(now); startOfToday.setHours(0, 0, 0, 0); const startOfYesterday = new Date(startOfToday); startOfYesterday.setDate(startOfYesterday.getDate() - 1); const startOfMonth = new Date(now.getFullYear(), now.getMonth(), 1); const startOfChart = new Date(startOfToday); startOfChart.setDate(startOfChart.getDate() - 27); const [newOrders, pendingReview, pendingCheck, finalApproval, todayOrders, yesterdayOrders, monthOrders, chartOrders, recentOrders, checks, notifications, messages,] = await Promise.all([ this.prisma.order.count({ where: { createdAt: { gte: startOfToday } }, }), this.prisma.order.count({ where: { status: { in: order_status_1.ADMIN_STATUS_MAP.pending_review } }, }), this.prisma.order.count({ where: { status: { in: order_status_1.ADMIN_STATUS_MAP.pending_check } }, }), this.prisma.order.count({ where: { status: { in: order_status_1.ADMIN_STATUS_MAP.final_approval } }, }), this.prisma.order.findMany({ where: { createdAt: { gte: startOfToday } }, select: { finalAmount: true, totalAmount: true }, }), this.prisma.order.findMany({ where: { createdAt: { gte: startOfYesterday, lt: startOfToday }, }, select: { finalAmount: true, totalAmount: true }, }), this.prisma.order.findMany({ where: { createdAt: { gte: startOfMonth } }, select: { finalAmount: true, totalAmount: true }, }), this.prisma.order.findMany({ where: { createdAt: { gte: startOfChart } }, select: { createdAt: true, finalAmount: true, totalAmount: true, }, }), this.prisma.order.findMany({ orderBy: { createdAt: 'desc' }, take: 5, include: { items: true, checks: { orderBy: { row: 'asc' } }, cashReceipt: true, statusHistory: { orderBy: { changedAt: 'asc' } }, shipment: true, user: true, company: true, }, }), this.prisma.check.findMany({ where: { status: { not: 'rejected' }, dueDate: { gte: startOfToday, lte: new Date(startOfToday.getTime() + 30 * 24 * 60 * 60 * 1000), }, }, select: { dueDate: true, amount: true }, }), this.prisma.adminNotification.findMany({ orderBy: { sentAt: 'desc' }, take: 20, }), this.prisma.internalMessage.findMany({ orderBy: { sentAt: 'desc' }, take: 20, }), ]); const sumAmounts = (rows) => rows.reduce((s, o) => s + (o.finalAmount ?? o.totalAmount ?? 0), 0); const todaySales = sumAmounts(todayOrders); const yesterdaySales = sumAmounts(yesterdayOrders); const monthSales = sumAmounts(monthOrders); const todaySalesGrowth = yesterdaySales > 0 ? Math.round(((todaySales - yesterdaySales) / yesterdaySales) * 100) : todaySales > 0 ? 100 : 0; const salesByDay = Array.from({ length: 28 }, () => 0); for (const order of chartOrders) { const dayIndex = Math.floor((order.createdAt.getTime() - startOfChart.getTime()) / (24 * 60 * 60 * 1000)); if (dayIndex >= 0 && dayIndex < 28) { salesByDay[dayIndex] += order.finalAmount ?? order.totalAmount ?? 0; } } const maxSale = Math.max(...salesByDay, 1); const salesChartData = salesByDay.map((v) => Number((v / maxSale).toFixed(3))); const checkDeadlines = this.buildCheckDeadlines(checks, startOfToday); return { stats: { newOrders, pendingReview, pendingCheck, finalApproval, todaySales, todaySalesGrowth, monthSales, }, recentOrders: recentOrders.map((o) => this.ordersService.mapOrder(o, true)), salesChartData, chartAxisLabels: ['۱', '۷', '۱۴', '۲۱', '۲۸'], checkDeadlines, notifications: notifications.map((n) => ({ id: n.id, title: n.title, body: n.body, tone: n.tone, link: n.link, isRead: n.isRead, sentAt: n.sentAt.toISOString(), })), messages: messages.map((m) => ({ id: m.id, senderName: m.senderName, subject: m.subject, preview: m.preview, isRead: m.isRead, sentAt: m.sentAt.toISOString(), })), }; } async getReports() { const orders = await this.prisma.order.findMany({ select: { companyName: true, status: true, totalMeterage: true, finalAmount: true, totalAmount: true, }, }); const byCompany = new Map(); const byStatus = new Map(); for (const order of orders) { const company = byCompany.get(order.companyName) ?? { companyName: order.companyName, orderCount: 0, totalAmount: 0, meterage: 0, }; company.orderCount += 1; company.totalAmount += order.finalAmount ?? order.totalAmount ?? 0; company.meterage += order.totalMeterage; byCompany.set(order.companyName, company); const label = order_status_1.ORDER_STATUS_LABELS[order.status] ?? (0, order_status_1.toAdminStatus)(order.status); byStatus.set(label, (byStatus.get(label) ?? 0) + 1); } return { reportSalesByCompany: Array.from(byCompany.values()).sort((a, b) => b.totalAmount - a.totalAmount), reportOrdersByStatus: Array.from(byStatus.entries()).map(([status, count]) => ({ status, count })), }; } buildCheckDeadlines(checks, startOfToday) { const buckets = [ { id: 'cd-today', label: 'امروز', tone: 'danger', days: 0 }, { id: 'cd-3', label: '۳ روز آینده', tone: 'warning', days: 3 }, { id: 'cd-7', label: '۷ روز آینده', tone: 'warning', days: 7 }, { id: 'cd-30', label: '۳۰ روز آینده', tone: 'neutral', days: 30, }, ]; return buckets.map((bucket) => { const end = new Date(startOfToday); end.setDate(end.getDate() + bucket.days); end.setHours(23, 59, 59, 999); const matched = checks.filter((c) => { const d = new Date(c.dueDate); d.setHours(0, 0, 0, 0); if (bucket.days === 0) { return d.getTime() === startOfToday.getTime(); } return d >= startOfToday && d <= end; }); return { id: bucket.id, label: bucket.label, tone: bucket.tone, count: matched.length, amount: matched.reduce((s, c) => s + c.amount, 0), }; }); } }; exports.DashboardService = DashboardService; exports.DashboardService = DashboardService = __decorate([ (0, common_1.Injectable)(), __metadata("design:paramtypes", [prisma_service_1.PrismaService, orders_service_1.OrdersService]) ], DashboardService); //# sourceMappingURL=dashboard.service.js.map