|
- 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<string, unknown>[] = [];
- 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<string, unknown>[] = [];
- const stepRows: Record<string, unknown>[] = [];
-
- 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,
- );
- }
|