FPSMS-frontend
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 

47 lines
1.5 KiB

  1. export type StockQtyRoundMode = "CEILING" | "FLOOR";
  2. export type StockQtyRoundSource = "CREATE" | "QC";
  3. export type StockQtyRoundChoice = {
  4. mode: StockQtyRoundMode;
  5. before: number;
  6. after: number;
  7. };
  8. /** FP-MTMS Version Checklist | Functions Ref. No. 56 | v1.0.3 | 2026-09-10 */
  9. export function previewPoBatchStockQty(
  10. orderM18Qty: number,
  11. orderStockQty: number,
  12. batchM18Qty: number,
  13. ): number {
  14. if (!Number.isFinite(orderM18Qty) || orderM18Qty === 0) {
  15. return Number(batchM18Qty.toFixed(2));
  16. }
  17. return Number(((batchM18Qty * orderStockQty) / orderM18Qty).toFixed(2));
  18. }
  19. export function isNotIntegerQty(qty: number): boolean {
  20. if (!Number.isFinite(qty)) return false;
  21. return Math.abs(qty - Math.round(qty)) > 1e-9;
  22. }
  23. /**
  24. * FP-MTMS Version Checklist | Functions Ref. No. 56 | v1.0.3 | 2026-09-10
  25. * PO 收貨/品檢:pending 或 escalated 且庫存數量非整數時需選擇 CEILING / FLOOR
  26. */
  27. export function needsPoQcStockQtyRound(
  28. purchaseOrderLineId: number | null | undefined,
  29. status: string | null | undefined,
  30. acceptedQty: number | null | undefined,
  31. ): boolean {
  32. if (!purchaseOrderLineId) return false;
  33. const silStatus = (status ?? "").toLowerCase().trim();
  34. if (silStatus !== "pending" && silStatus !== "escalated") return false;
  35. return isNotIntegerQty(Number(acceptedQty ?? 0));
  36. }
  37. /** FP-MTMS Version Checklist | Functions Ref. No. 56 | v1.0.3 | 2026-09-10 */
  38. export function roundStockQty(before: number, mode: StockQtyRoundMode): number {
  39. if (mode === "CEILING") return Math.ceil(before);
  40. return Math.floor(before);
  41. }