workOrderDispatch.ts 5.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179
  1. import service from '/@/utils/request';
  2. import { withAidopTenantParams } from './aidopTenant';
  3. export interface Paged<T> {
  4. total: number;
  5. page: number;
  6. pageSize: number;
  7. list: T[];
  8. }
  9. export interface WorkOrderDispatchRow {
  10. id: number;
  11. domain?: string | null;
  12. workOrd?: string | null;
  13. priority?: string | null;
  14. itemNum?: string | null;
  15. descr?: string | null;
  16. descr1?: string | null;
  17. qtyOrded?: number | null;
  18. materialSituation?: string | null;
  19. ordDate?: string | null;
  20. dueDate?: string | null;
  21. status?: string | null;
  22. lotSerial?: string | null;
  23. prevNbr?: string | null;
  24. nbr?: string | null;
  25. wl?: string | null;
  26. }
  27. export interface WorkOrderReleaseParams {
  28. workOrd: string;
  29. ordDate: string;
  30. lotSerial?: string | null;
  31. /** 登录账号(批量齐套检查等场景使用) */
  32. userAccount: string;
  33. }
  34. /** 物料齐套检查(租户下 p/r 工单批量检查) */
  35. export async function kitCheck(domain: string, userAccount: string): Promise<void> {
  36. await service.post('/api/WorkOrder/dispatch/kitting-check', null, {
  37. params: { domain, userAccount },
  38. timeout: 300000,
  39. });
  40. }
  41. export interface KittingCheckSingleResult {
  42. materialSituation?: string | null;
  43. isKitted?: boolean;
  44. shortageLineCount?: number;
  45. }
  46. /** 单工单齐套检查(替代旧 WorkOrdKittingCheckByNo);缺料属正常结论,由调用方按 isKitted 呈现 */
  47. export async function kittingCheckSingle(
  48. workOrd: string,
  49. domain: string,
  50. userAccount: string
  51. ): Promise<KittingCheckSingleResult> {
  52. const res = await service.post('/api/WorkOrder/dispatch/work-order-kitting-check', null, {
  53. params: { workord: workOrd, domain, userAccount },
  54. timeout: 300000,
  55. });
  56. const body = res.data as (KittingCheckSingleResult & { result?: KittingCheckSingleResult }) | undefined;
  57. return body?.result ?? body ?? {};
  58. }
  59. /** MRP 生成结果 */
  60. export interface MrpGenerateResult {
  61. message?: string;
  62. demandScheduleCount?: number;
  63. prCreatedCount?: number;
  64. shortageItemCount?: number;
  65. }
  66. /** 生成物料需求 */
  67. export async function mrpGenerate(domain: string): Promise<MrpGenerateResult> {
  68. const res = await service.post<MrpGenerateResult>('/api/WorkOrder/material-requirement/generate', null, {
  69. params: { domain },
  70. });
  71. return res.data ?? {};
  72. }
  73. export interface NextLotSerialResult {
  74. lotSerial: string;
  75. }
  76. /** 下一生产批号:本系统接口(租户由认证后 JWT 解析,按 tenant_id + 初始工单取号) */
  77. export function fetchNextLotSerial(payload: { workOrd: string }) {
  78. const params: Record<string, string | number> = {
  79. workOrd: payload.workOrd.trim(),
  80. };
  81. return service
  82. .get<NextLotSerialResult & { result?: NextLotSerialResult }>('/api/WorkOrder/dispatch/next-lot-serial', {
  83. params,
  84. })
  85. .then((res) => {
  86. const body = res.data as NextLotSerialResult & { result?: NextLotSerialResult };
  87. if (body && typeof body.lotSerial === 'string') return { lotSerial: body.lotSerial };
  88. if (body?.result && typeof body.result.lotSerial === 'string') return { lotSerial: body.result.lotSerial };
  89. throw new Error('获取生产批号返回格式异常');
  90. });
  91. }
  92. // ── BOM 上传 ──
  93. export interface BomItemDto {
  94. itemNum: string;
  95. descr: string;
  96. descr1?: string;
  97. um?: string;
  98. qtyRequired: number;
  99. op: number;
  100. salesOrderNo?: string;
  101. parentItemNum?: string;
  102. }
  103. export interface BomCheckResult {
  104. existing: string[];
  105. missing: BomItemDto[];
  106. }
  107. export interface BomUploadResult {
  108. inserted: number;
  109. updated: number;
  110. newItems: number;
  111. total: number;
  112. matchedWorkOrders: number;
  113. unmatched: string[];
  114. }
  115. /** BOM 物料存在性校验 */
  116. export function checkBomMaterials(items: BomItemDto[]) {
  117. return service
  118. .post<BomCheckResult>('/api/WorkOrder/dispatch/bom/check-materials', { items })
  119. .then((r) => r.data);
  120. }
  121. /** BOM 写入工单物料明细(按订单号+父物料号自动匹配未下达工单) */
  122. export function uploadBom(createMissingItems: boolean, items: BomItemDto[]) {
  123. return service
  124. .post<BomUploadResult>('/api/WorkOrder/dispatch/bom/upload', { createMissingItems, items })
  125. .then((r) => r.data);
  126. }
  127. export function fetchWorkOrderDispatchList(params: Record<string, unknown>) {
  128. return service
  129. .get<Paged<WorkOrderDispatchRow>>('/api/WorkOrder/dispatch/list', { params: withAidopTenantParams(params) })
  130. .then((r) => r.data);
  131. }
  132. /** 下达成功后的响应体(统一包装或非统一 JSON) */
  133. export type WorkOrderReleaseResponse = Record<string, unknown>;
  134. /**
  135. * 工单下达:本系统 `POST .../dispatch/release`(含齐套检查与状态落库)。
  136. */
  137. export async function releaseWorkOrder(body: WorkOrderReleaseParams): Promise<WorkOrderReleaseResponse> {
  138. const { userAccount: _ua, ...releaseBody } = body;
  139. const res = await service.post('/api/WorkOrder/dispatch/release', releaseBody, {
  140. headers: { 'X-Silent-Error': '1' },
  141. });
  142. const data = res.data as WorkOrderReleaseResponse | undefined;
  143. if (data == null || typeof data !== 'object') {
  144. throw new Error('工单下达返回异常');
  145. }
  146. if (Object.prototype.hasOwnProperty.call(data, 'code')) {
  147. const code = Number(data.code);
  148. if (!Number.isFinite(code) || code !== 200) {
  149. const msg =
  150. typeof data.message === 'string' && data.message.trim() ? data.message : '工单下达失败';
  151. throw new Error(msg);
  152. }
  153. }
  154. if (typeof data.type === 'string' && data.type && data.type !== 'success') {
  155. const msg =
  156. typeof data.message === 'string' && data.message.trim() ? data.message : '工单下达失败';
  157. throw new Error(msg);
  158. }
  159. return data;
  160. }