FPSMS-frontend
Nelze vybrat více než 25 témat Téma musí začínat písmenem nebo číslem, může obsahovat pomlčky („-“) a může být dlouhé až 35 znaků.
 
 

217 řádky
7.7 KiB

  1. import dayjs from "dayjs";
  2. import type { TFunction } from "i18next";
  3. import { exportMultiSheetToXlsx } from "@/app/(main)/chart/_components/exportChartToXlsx";
  4. import type {
  5. DrinkProductionQtyJobOrderDetail,
  6. DrinkProductionQtyResponse,
  7. DrinkShipmentQtyResponse,
  8. } from "@/app/api/jo/actions";
  9. export type DrinkViewMode = "actual" | "planned" | "shipment";
  10. const formatDateTime = (value: unknown): string => {
  11. if (value == null || value === "") return "";
  12. if (Array.isArray(value)) {
  13. const [y, m, d, h = 0, min = 0] = value as number[];
  14. if (y == null || m == null || d == null) return "";
  15. return dayjs(new Date(y, m - 1, d, h, min)).format("YYYY-MM-DD HH:mm");
  16. }
  17. const parsed = dayjs(value as string);
  18. return parsed.isValid() ? parsed.format("YYYY-MM-DD HH:mm") : String(value);
  19. };
  20. const formatDate = (value: string | null | undefined): string => {
  21. if (!value) return "";
  22. const parsed = dayjs(value);
  23. return parsed.isValid() ? parsed.format("YYYY-MM-DD") : value;
  24. };
  25. export type ExportDrinkProductionQtyParams = {
  26. data: DrinkProductionQtyResponse[];
  27. shipmentData?: DrinkShipmentQtyResponse[];
  28. viewMode: DrinkViewMode;
  29. selectedDate: string;
  30. statusFilter: string;
  31. t: TFunction;
  32. };
  33. const viewModeLabel = (viewMode: DrinkViewMode, t: TFunction): string => {
  34. switch (viewMode) {
  35. case "planned":
  36. return t("Drink detail mode: planned");
  37. case "shipment":
  38. return t("Drink detail mode: shipment");
  39. case "actual":
  40. return t("Drink detail mode: actual");
  41. default: {
  42. const _exhaustive: never = viewMode;
  43. return _exhaustive;
  44. }
  45. }
  46. };
  47. const formatDoStatus = (status: string | null | undefined, t: TFunction): string => {
  48. if (!status) return "";
  49. switch (status.toLowerCase()) {
  50. case "pending":
  51. return t("Drink do status pending");
  52. case "receiving":
  53. return t("Drink do status receiving");
  54. case "completed":
  55. return t("Drink do status completed");
  56. default:
  57. return t(status, { ns: "do", defaultValue: status });
  58. }
  59. };
  60. export function exportDrinkProductionQtyXlsx({
  61. data,
  62. shipmentData = [],
  63. viewMode,
  64. selectedDate,
  65. statusFilter,
  66. t,
  67. }: ExportDrinkProductionQtyParams): void {
  68. const viewLabel = viewModeLabel(viewMode, t);
  69. const statusFilterLabel = statusFilter
  70. ? t(statusFilter, { ns: "jo", defaultValue: statusFilter })
  71. : t("All");
  72. const exportedAt = dayjs().format("YYYY-MM-DD HH:mm:ss");
  73. if (viewMode === "shipment") {
  74. const doRows: Record<string, unknown>[] = [];
  75. const itemRows = shipmentData.map((item) => {
  76. for (const delivery of item.deliveries ?? []) {
  77. doRows.push({
  78. [t("Export meta: exported at")]: exportedAt,
  79. [t("Drink detail mode label")]: viewLabel,
  80. [t("Date")]: selectedDate,
  81. [t("Item Code")]: item.itemCode ?? "",
  82. [t("Goods Name")]: item.itemName ?? "",
  83. [t("Unit")]: item.uom ?? "",
  84. [t("Delivery Order Code", { ns: "do" })]: delivery.deliveryOrderCode ?? "",
  85. [t("Delivery Order Status", { ns: "do" })]: formatDoStatus(
  86. delivery.deliveryOrderStatus,
  87. t,
  88. ),
  89. [t("Shop Name", { ns: "do" })]:
  90. delivery.shopName || delivery.shopCode || "",
  91. [t("Delivery Date", { ns: "do" })]: formatDate(delivery.deliveryDate),
  92. [t("Shipment Order Qty")]: delivery.orderQty ?? 0,
  93. [t("Shipped Qty")]: delivery.shippedQty ?? 0,
  94. });
  95. }
  96. return {
  97. [t("Export meta: exported at")]: exportedAt,
  98. [t("Drink detail mode label")]: viewLabel,
  99. [t("Date")]: selectedDate,
  100. [t("Item Code")]: item.itemCode ?? "",
  101. [t("Goods Name")]: item.itemName ?? "",
  102. [t("Unit")]: item.uom ?? "",
  103. [t("Shipment Order Qty")]: item.totalOrderQty ?? 0,
  104. [t("Shipped Qty")]: item.totalShippedQty ?? 0,
  105. [t("DO count")]: (item.deliveries ?? []).length,
  106. };
  107. });
  108. const filename = `DrinkProductionQty_shipment_${selectedDate}_${dayjs().format("HHmm")}`;
  109. exportMultiSheetToXlsx(
  110. [
  111. { name: t("Excel sheet: DO detail"), rows: doRows },
  112. { name: t("Excel sheet: item summary"), rows: itemRows },
  113. ],
  114. filename,
  115. );
  116. return;
  117. }
  118. const filterJos = (
  119. jobOrders: DrinkProductionQtyJobOrderDetail[],
  120. ): DrinkProductionQtyJobOrderDetail[] => {
  121. if (!statusFilter) return jobOrders;
  122. return jobOrders.filter((jo) => jo.jobOrderStatus === statusFilter);
  123. };
  124. const joRows: Record<string, unknown>[] = [];
  125. const stepRows: Record<string, unknown>[] = [];
  126. for (const item of data) {
  127. for (const jo of filterJos(item.jobOrders ?? [])) {
  128. joRows.push({
  129. [t("Export meta: exported at")]: exportedAt,
  130. [t("Drink detail mode label")]: viewLabel,
  131. [t("Date")]: selectedDate,
  132. [t("Job Order Status") + ` (${t("Filter")})`]: statusFilterLabel,
  133. [t("Item Code")]: item.itemCode ?? "",
  134. [t("Goods Name")]: item.itemName ?? "",
  135. [t("Unit")]: item.uom ?? "",
  136. [t("Job Order Code")]: jo.jobOrderCode ?? "",
  137. [t("Job Order Status")]: jo.jobOrderStatus
  138. ? t(jo.jobOrderStatus, { ns: "jo", defaultValue: jo.jobOrderStatus })
  139. : "",
  140. [t("Production Date")]: formatDate(jo.productionDate),
  141. [viewMode === "planned"
  142. ? t("Planned Output Qty")
  143. : t("Stock Req. Qty")]: jo.reqQty ?? 0,
  144. [viewMode === "planned"
  145. ? t("Actual Output Qty")
  146. : t("Production Qty")]: jo.productionQty ?? 0,
  147. [t("Assume Time Need")]: jo.assumeTimeNeedMins ?? 0,
  148. [t("Latest Start By")]: formatDateTime(jo.latestStartBy),
  149. [t("Start Time")]: formatDateTime(jo.startTime),
  150. [t("Assume End Time")]: formatDateTime(jo.assumeEndTime),
  151. [t("Actual End Time")]: formatDateTime(jo.actualEndTime),
  152. [t("Process operators")]: jo.processOperators ?? "",
  153. [t("Process handlers")]: jo.processHandlers ?? "",
  154. [t("QC users")]: jo.qcUsers ?? "",
  155. [t("Put away users")]: jo.putAwayUsers ?? "",
  156. });
  157. for (const step of jo.processSteps ?? []) {
  158. stepRows.push({
  159. [t("Export meta: exported at")]: exportedAt,
  160. [t("Drink detail mode label")]: viewLabel,
  161. [t("Date")]: selectedDate,
  162. [t("Item Code")]: step.itemCode ?? item.itemCode ?? "",
  163. [t("Goods Name")]: step.itemName ?? item.itemName ?? "",
  164. [t("Job Order Code")]: step.jobOrderCode ?? jo.jobOrderCode ?? "",
  165. [t("Process seq")]: step.seqNo ?? "",
  166. [t("Process Name")]: step.processName ?? "",
  167. [t("Operator Name & No.")]: step.operatorName ?? "",
  168. [t("Handler")]: step.handlerName ?? "",
  169. [t("Start Time")]: formatDateTime(step.startTime),
  170. [t("End Time")]: formatDateTime(step.endTime),
  171. [t("Status")]: step.status ?? "",
  172. });
  173. }
  174. }
  175. }
  176. const itemRows = data.map((item) => ({
  177. [t("Export meta: exported at")]: exportedAt,
  178. [t("Drink detail mode label")]: viewLabel,
  179. [t("Date")]: selectedDate,
  180. [t("Item Code")]: item.itemCode ?? "",
  181. [t("Goods Name")]: item.itemName ?? "",
  182. [t("Unit")]: item.uom ?? "",
  183. [viewMode === "planned"
  184. ? t("Planned Output Qty")
  185. : t("Stock Req. Qty")]: item.totalReqQty ?? 0,
  186. [viewMode === "planned"
  187. ? t("Actual Output Qty")
  188. : t("Production Qty")]: item.totalQty ?? 0,
  189. [t("JO count")]: filterJos(item.jobOrders ?? []).length,
  190. }));
  191. const modeSlug = viewMode === "planned" ? "planned" : "actual";
  192. const filename = `DrinkProductionQty_${modeSlug}_${selectedDate}_${dayjs().format("HHmm")}`;
  193. exportMultiSheetToXlsx(
  194. [
  195. { name: t("Excel sheet: JO detail"), rows: joRows },
  196. { name: t("Excel sheet: process people"), rows: stepRows },
  197. { name: t("Excel sheet: item summary"), rows: itemRows },
  198. ],
  199. filename,
  200. );
  201. }