|
- "use client";
-
- import { NEXT_PUBLIC_API_URL } from "@/config/api";
- import { clientAuthFetch } from "@/app/utils/clientAuthFetch";
- import {
- exportMultiSheetToXlsx,
- } from "@/app/(main)/chart/_components/exportChartToXlsx";
- import { reportExcelT as tx } from "./reportI18n";
- import type { TFunction } from "i18next";
-
- export interface BomShopSyncReportSummary {
- totalAttempts?: number;
- success?: number;
- skippedUnchanged?: number;
- failed?: number;
- syncDateStart?: string;
- syncDateEnd?: string;
- }
-
- export interface BomShopSyncRow {
- syncLogId?: number;
- syncDateTime?: string;
- bomId?: number;
- bomRoutingCode?: string;
- finishedItemCode?: string;
- finishedItemName?: string;
- m18HeaderCode?: string;
- version?: string;
- m18RecordId?: number;
- syncStatus?: string;
- synced?: boolean;
- m18ApiStatus?: boolean;
- failureReason?: string;
- message?: string;
- }
-
- export interface BomShopSyncMaterialRow {
- syncLogId?: number;
- syncDateTime?: string;
- bomId?: number;
- finishedItemCode?: string;
- m18HeaderCode?: string;
- version?: string;
- syncStatus?: string;
- lineNo?: string;
- materialName?: string;
- udfProductM18Id?: number;
- udfBaseUnit?: string;
- udfQty?: number;
- udfSupplierM18Id?: number;
- udfPurchaseUnitM18Id?: number;
- }
-
- export interface BomShopSyncReportResponse {
- summary?: BomShopSyncReportSummary;
- syncRows?: BomShopSyncRow[];
- materialRows?: BomShopSyncMaterialRow[];
- }
-
- function bomSyncLabels(t?: TFunction) {
- return {
- sheetSync: tx(t, "excel.bomSync.sheetSync", "BOM同步記錄"),
- sheetMaterials: tx(t, "excel.bomSync.sheetMaterials", "BOM物料明細"),
- noData: tx(t, "excel.noData", "(篩選範圍內無資料)"),
- syncTime: tx(t, "excel.bomSync.syncTime", "同步時間"),
- finishedItemCode: tx(t, "excel.bomSync.finishedItemCode", "成品貨號"),
- finishedItemName: tx(t, "excel.bomSync.finishedItemName", "成品名稱"),
- bomRoutingCode: tx(t, "excel.bomSync.bomRoutingCode", "BOM路由編號"),
- version: tx(t, "excel.bomSync.version", "版本"),
- status: tx(t, "excel.bomSync.status", "狀態"),
- failureReason: tx(t, "excel.bomSync.failureReason", "失敗原因"),
- message: tx(t, "excel.bomSync.message", "訊息"),
- lineNo: tx(t, "excel.bomSync.lineNo", "行號"),
- materialName: tx(t, "excel.bomSync.materialName", "物料名稱"),
- uom: tx(t, "excel.bomSync.uom", "單位"),
- qty: tx(t, "excel.bomSync.qty", "用量"),
- statusSuccess: tx(t, "excel.bomSync.statusSuccess", "成功"),
- statusSkipped: tx(t, "excel.bomSync.statusSkipped", "略過(內容未變)"),
- statusFailed: tx(t, "excel.bomSync.statusFailed", "失敗"),
- };
- }
-
- function emptySyncSheetRow(
- L: ReturnType<typeof bomSyncLabels>,
- note?: string,
- ): Record<string, unknown> {
- return {
- [L.syncTime]: note ?? L.noData,
- [L.finishedItemCode]: "",
- [L.finishedItemName]: "",
- [L.bomRoutingCode]: "",
- "M18 BOM Code": "",
- [L.version]: "",
- "M18 Record Id": "",
- [L.status]: "",
- [L.failureReason]: "",
- [L.message]: "",
- "BOM Id": "",
- "Sync Log Id": "",
- };
- }
-
- function emptyMaterialSheetRow(
- L: ReturnType<typeof bomSyncLabels>,
- note?: string,
- ): Record<string, unknown> {
- return {
- [L.syncTime]: note ?? L.noData,
- [L.finishedItemCode]: "",
- "M18 BOM Code": "",
- [L.version]: "",
- [L.status]: "",
- [L.lineNo]: "",
- [L.materialName]: "",
- "M18 Product Id": "",
- [L.uom]: "",
- [L.qty]: "",
- "M18 Supplier Id": "",
- "M18 Purchase Unit Id": "",
- "Sync Log Id": "",
- };
- }
-
- export async function fetchBomShopSyncReportData(
- criteria: Record<string, string>,
- ): Promise<BomShopSyncReportResponse> {
- const queryParams = new URLSearchParams(criteria).toString();
- const url = `${NEXT_PUBLIC_API_URL}/report/bom-shop-sync-history?${queryParams}`;
-
- const response = await clientAuthFetch(url, {
- method: "GET",
- headers: { Accept: "application/json" },
- });
-
- if (response.status === 401 || response.status === 403)
- throw new Error("Unauthorized");
- if (!response.ok)
- throw new Error(`HTTP error! status: ${response.status}`);
-
- return (await response.json()) as BomShopSyncReportResponse;
- }
-
- function syncStatusLabel(
- status: string | undefined,
- L: ReturnType<typeof bomSyncLabels>,
- ): string {
- switch (status) {
- case "SUCCESS":
- return L.statusSuccess;
- case "SKIPPED_UNCHANGED":
- return L.statusSkipped;
- case "FAILED":
- return L.statusFailed;
- default:
- return status ?? "";
- }
- }
-
- function toSyncExcelRow(
- r: BomShopSyncRow,
- L: ReturnType<typeof bomSyncLabels>,
- ): Record<string, unknown> {
- return {
- ...emptySyncSheetRow(L, ""),
- [L.syncTime]: r.syncDateTime ?? "",
- [L.finishedItemCode]: r.finishedItemCode ?? "",
- [L.finishedItemName]: r.finishedItemName ?? "",
- [L.bomRoutingCode]: r.bomRoutingCode ?? "",
- "M18 BOM Code": r.m18HeaderCode ?? "",
- [L.version]: r.version ?? "",
- "M18 Record Id": r.m18RecordId ?? "",
- [L.status]: syncStatusLabel(r.syncStatus, L),
- [L.failureReason]: r.failureReason ?? "",
- [L.message]: r.message ?? "",
- "BOM Id": r.bomId ?? "",
- "Sync Log Id": r.syncLogId ?? "",
- };
- }
-
- function toMaterialExcelRow(
- r: BomShopSyncMaterialRow,
- L: ReturnType<typeof bomSyncLabels>,
- ): Record<string, unknown> {
- return {
- ...emptyMaterialSheetRow(L, ""),
- [L.syncTime]: r.syncDateTime ?? "",
- [L.finishedItemCode]: r.finishedItemCode ?? "",
- "M18 BOM Code": r.m18HeaderCode ?? "",
- [L.version]: r.version ?? "",
- [L.status]: syncStatusLabel(r.syncStatus, L),
- [L.lineNo]: r.lineNo ?? "",
- [L.materialName]: r.materialName ?? "",
- "M18 Product Id": r.udfProductM18Id ?? "",
- [L.uom]: r.udfBaseUnit ?? "",
- [L.qty]: r.udfQty ?? "",
- "M18 Supplier Id": r.udfSupplierM18Id ?? "",
- "M18 Purchase Unit Id": r.udfPurchaseUnitM18Id ?? "",
- "Sync Log Id": r.syncLogId ?? "",
- };
- }
-
- export async function generateBomShopSyncReportExcel(
- criteria: Record<string, string>,
- reportTitle: string = "M18 BOM Shop 同步記錄",
- t?: TFunction,
- ): Promise<void> {
- const L = bomSyncLabels(t);
- const data = await fetchBomShopSyncReportData(criteria);
- const syncRows =
- (data.syncRows ?? []).length > 0
- ? (data.syncRows ?? []).map((r) => toSyncExcelRow(r, L))
- : [emptySyncSheetRow(L)];
- const materialRows =
- (data.materialRows ?? []).length > 0
- ? (data.materialRows ?? []).map((r) => toMaterialExcelRow(r, L))
- : [emptyMaterialSheetRow(L)];
-
- const start = criteria.syncDateStart;
- const end = criteria.syncDateEnd;
- let datePart: string;
- if (start && end && start === end) {
- datePart = start;
- } else if (start || end) {
- datePart = `${start || ""}_to_${end || ""}`;
- } else {
- datePart = new Date().toISOString().slice(0, 10);
- }
- const filename = `${reportTitle}_${datePart.replace(/[^\d\-_/]/g, "")}`;
-
- exportMultiSheetToXlsx(
- [
- { name: L.sheetSync, rows: syncRows },
- { name: L.sheetMaterials, rows: materialRows },
- ],
- filename,
- );
- }
|