import dayjs from "dayjs"; import type { TFunction } from "i18next"; import { exportMultiSheetToXlsx } from "@/app/(main)/chart/_components/exportChartToXlsx"; import type { DrinkProductionQtyJobOrderDetail, DrinkProductionQtyResponse, DrinkShipmentQtyResponse, } from "@/app/api/jo/actions"; export type DrinkViewMode = "actual" | "planned" | "shipment"; const formatDateTime = (value: unknown): string => { if (value == null || value === "") return ""; if (Array.isArray(value)) { const [y, m, d, h = 0, min = 0] = value as number[]; if (y == null || m == null || d == null) return ""; return dayjs(new Date(y, m - 1, d, h, min)).format("YYYY-MM-DD HH:mm"); } const parsed = dayjs(value as string); return parsed.isValid() ? parsed.format("YYYY-MM-DD HH:mm") : String(value); }; const formatDate = (value: string | null | undefined): string => { if (!value) return ""; const parsed = dayjs(value); return parsed.isValid() ? parsed.format("YYYY-MM-DD") : value; }; export type ExportDrinkProductionQtyParams = { data: DrinkProductionQtyResponse[]; shipmentData?: DrinkShipmentQtyResponse[]; viewMode: DrinkViewMode; selectedDate: string; statusFilter: string; t: TFunction; }; const viewModeLabel = (viewMode: DrinkViewMode, t: TFunction): string => { switch (viewMode) { case "planned": return t("Drink detail mode: planned"); case "shipment": return t("Drink detail mode: shipment"); case "actual": return t("Drink detail mode: actual"); default: { const _exhaustive: never = viewMode; return _exhaustive; } } }; const formatDoStatus = (status: string | null | undefined, t: TFunction): string => { if (!status) return ""; switch (status.toLowerCase()) { case "pending": return t("Drink do status pending"); case "receiving": return t("Drink do status receiving"); case "completed": return t("Drink do status completed"); default: return t(status, { ns: "do", defaultValue: status }); } }; export function exportDrinkProductionQtyXlsx({ data, shipmentData = [], viewMode, selectedDate, statusFilter, t, }: ExportDrinkProductionQtyParams): void { const viewLabel = viewModeLabel(viewMode, t); const statusFilterLabel = statusFilter ? t(statusFilter, { ns: "jo", defaultValue: statusFilter }) : t("All"); const exportedAt = dayjs().format("YYYY-MM-DD HH:mm:ss"); if (viewMode === "shipment") { const doRows: Record[] = []; const itemRows = shipmentData.map((item) => { for (const delivery of item.deliveries ?? []) { doRows.push({ [t("Export meta: exported at")]: exportedAt, [t("Drink detail mode label")]: viewLabel, [t("Date")]: selectedDate, [t("Item Code")]: item.itemCode ?? "", [t("Goods Name")]: item.itemName ?? "", [t("Unit")]: item.uom ?? "", [t("Delivery Order Code", { ns: "do" })]: delivery.deliveryOrderCode ?? "", [t("Delivery Order Status", { ns: "do" })]: formatDoStatus( delivery.deliveryOrderStatus, t, ), [t("Shop Name", { ns: "do" })]: delivery.shopName || delivery.shopCode || "", [t("Delivery Date", { ns: "do" })]: formatDate(delivery.deliveryDate), [t("Shipment Order Qty")]: delivery.orderQty ?? 0, [t("Shipped Qty")]: delivery.shippedQty ?? 0, }); } return { [t("Export meta: exported at")]: exportedAt, [t("Drink detail mode label")]: viewLabel, [t("Date")]: selectedDate, [t("Item Code")]: item.itemCode ?? "", [t("Goods Name")]: item.itemName ?? "", [t("Unit")]: item.uom ?? "", [t("Shipment Order Qty")]: item.totalOrderQty ?? 0, [t("Shipped Qty")]: item.totalShippedQty ?? 0, [t("DO count")]: (item.deliveries ?? []).length, }; }); const filename = `DrinkProductionQty_shipment_${selectedDate}_${dayjs().format("HHmm")}`; exportMultiSheetToXlsx( [ { name: t("Excel sheet: DO detail"), rows: doRows }, { name: t("Excel sheet: item summary"), rows: itemRows }, ], filename, ); return; } const filterJos = ( jobOrders: DrinkProductionQtyJobOrderDetail[], ): DrinkProductionQtyJobOrderDetail[] => { if (!statusFilter) return jobOrders; return jobOrders.filter((jo) => jo.jobOrderStatus === statusFilter); }; const joRows: Record[] = []; const stepRows: Record[] = []; for (const item of data) { for (const jo of filterJos(item.jobOrders ?? [])) { joRows.push({ [t("Export meta: exported at")]: exportedAt, [t("Drink detail mode label")]: viewLabel, [t("Date")]: selectedDate, [t("Job Order Status") + ` (${t("Filter")})`]: statusFilterLabel, [t("Item Code")]: item.itemCode ?? "", [t("Goods Name")]: item.itemName ?? "", [t("Unit")]: item.uom ?? "", [t("Job Order Code")]: jo.jobOrderCode ?? "", [t("Job Order Status")]: jo.jobOrderStatus ? t(jo.jobOrderStatus, { ns: "jo", defaultValue: jo.jobOrderStatus }) : "", [t("Production Date")]: formatDate(jo.productionDate), [viewMode === "planned" ? t("Planned Output Qty") : t("Stock Req. Qty")]: jo.reqQty ?? 0, [viewMode === "planned" ? t("Actual Output Qty") : t("Production Qty")]: jo.productionQty ?? 0, [t("Assume Time Need")]: jo.assumeTimeNeedMins ?? 0, [t("Latest Start By")]: formatDateTime(jo.latestStartBy), [t("Start Time")]: formatDateTime(jo.startTime), [t("Assume End Time")]: formatDateTime(jo.assumeEndTime), [t("Actual End Time")]: formatDateTime(jo.actualEndTime), [t("Process operators")]: jo.processOperators ?? "", [t("Process handlers")]: jo.processHandlers ?? "", [t("QC users")]: jo.qcUsers ?? "", [t("Put away users")]: jo.putAwayUsers ?? "", }); for (const step of jo.processSteps ?? []) { stepRows.push({ [t("Export meta: exported at")]: exportedAt, [t("Drink detail mode label")]: viewLabel, [t("Date")]: selectedDate, [t("Item Code")]: step.itemCode ?? item.itemCode ?? "", [t("Goods Name")]: step.itemName ?? item.itemName ?? "", [t("Job Order Code")]: step.jobOrderCode ?? jo.jobOrderCode ?? "", [t("Process seq")]: step.seqNo ?? "", [t("Process Name")]: step.processName ?? "", [t("Operator Name & No.")]: step.operatorName ?? "", [t("Handler")]: step.handlerName ?? "", [t("Start Time")]: formatDateTime(step.startTime), [t("End Time")]: formatDateTime(step.endTime), [t("Status")]: step.status ?? "", }); } } } const itemRows = data.map((item) => ({ [t("Export meta: exported at")]: exportedAt, [t("Drink detail mode label")]: viewLabel, [t("Date")]: selectedDate, [t("Item Code")]: item.itemCode ?? "", [t("Goods Name")]: item.itemName ?? "", [t("Unit")]: item.uom ?? "", [viewMode === "planned" ? t("Planned Output Qty") : t("Stock Req. Qty")]: item.totalReqQty ?? 0, [viewMode === "planned" ? t("Actual Output Qty") : t("Production Qty")]: item.totalQty ?? 0, [t("JO count")]: filterJos(item.jobOrders ?? []).length, })); const modeSlug = viewMode === "planned" ? "planned" : "actual"; const filename = `DrinkProductionQty_${modeSlug}_${selectedDate}_${dayjs().format("HHmm")}`; exportMultiSheetToXlsx( [ { name: t("Excel sheet: JO detail"), rows: joRows }, { name: t("Excel sheet: process people"), rows: stepRows }, { name: t("Excel sheet: item summary"), rows: itemRows }, ], filename, ); }