优化出入库功能,新增对未完全入库和出库商品的检查,更新相关API接口以支持审批人字段的统一命名
| | |
| | | item.operateQuantity = String(Math.max(0, n)); |
| | | }; |
| | | |
| | | const hasEditableInboundItems = computed(() => { |
| | | if (!recordList.value?.length) return false; |
| | | return recordList.value.some(item => !isFullyStocked(item)); |
| | | }); |
| | | |
| | | const formatCell = (item, row, idx) => { |
| | | if (row.key === "index") { |
| | | const v = item.index; |
| | |
| | | modal.msgError("缺少订单信息,请重新扫码"); |
| | | return; |
| | | } |
| | | if (!hasEditableInboundItems.value) { |
| | | modal.msgError("该产品已经全部入库"); |
| | | return; |
| | | } |
| | | const salesLedgerProductList = buildSalesLedgerProductList(recordList.value); |
| | | if (!hasAnyPositiveStockedQty(salesLedgerProductList)) { |
| | | modal.msgError("请至少填写一行大于 0 的入库数量"); |
| | |
| | | return; |
| | | } |
| | | const runApi = currentSubmitConfig.runApi; |
| | | const inboundApproveUserIds = stockApproverNodes.value.map(node => node.userId).join(","); |
| | | const approveUserIds = stockApproverNodes.value.map(node => node.userId).join(","); |
| | | const payload = currentSubmitConfig.payloadBuilder( |
| | | salesLedgerProductList, |
| | | inboundApproveUserIds |
| | | approveUserIds |
| | | ); |
| | | try { |
| | | submitLoading.value = true; |
| | |
| | | |
| | | type SubmitConfig = { |
| | | runApi: (data: any) => Promise<any>; |
| | | payloadBuilder: (list: AnyRow[], inboundApproveUserIds: string) => any; |
| | | payloadBuilder: (list: AnyRow[], approveUserIds: string) => any; |
| | | }; |
| | | |
| | | export function createSubmitConfig(scanLedgerIdRef: AnyRef<string | number | null>) { |
| | | const cfg: Record<string, SubmitConfig> = { |
| | | [`${CONTRACT_KIND.sales}-${QUALITY_TYPE.qualified}`]: { |
| | | runApi: scanInboundSales, |
| | | payloadBuilder: (list: AnyRow[], inboundApproveUserIds: string) => ({ |
| | | payloadBuilder: (list: AnyRow[], approveUserIds: string) => ({ |
| | | salesLedgerId: scanLedgerIdRef.value, |
| | | salesLedgerProductList: list, |
| | | inboundApproveUserIds, |
| | | approveUserIds, |
| | | }), |
| | | }, |
| | | [`${CONTRACT_KIND.sales}-${QUALITY_TYPE.unqualified}`]: { |
| | | runApi: scanInboundSalesUnqualified, |
| | | payloadBuilder: (list: AnyRow[], inboundApproveUserIds: string) => ({ |
| | | payloadBuilder: (list: AnyRow[], approveUserIds: string) => ({ |
| | | salesLedgerId: scanLedgerIdRef.value, |
| | | salesLedgerProductList: list, |
| | | inboundApproveUserIds, |
| | | approveUserIds, |
| | | }), |
| | | }, |
| | | [`${CONTRACT_KIND.purchase}-${QUALITY_TYPE.qualified}`]: { |
| | | runApi: scanInboundPurchase, |
| | | payloadBuilder: (list: AnyRow[], inboundApproveUserIds: string) => ({ |
| | | payloadBuilder: (list: AnyRow[], approveUserIds: string) => ({ |
| | | purchaseLedgerId: scanLedgerIdRef.value, |
| | | salesLedgerProductList: list, |
| | | inboundApproveUserIds, |
| | | approveUserIds, |
| | | }), |
| | | }, |
| | | [`${CONTRACT_KIND.purchase}-${QUALITY_TYPE.unqualified}`]: { |
| | | runApi: scanInboundPurchaseUnqualified, |
| | | payloadBuilder: (list: AnyRow[], inboundApproveUserIds: string) => ({ |
| | | payloadBuilder: (list: AnyRow[], approveUserIds: string) => ({ |
| | | purchaseLedgerId: scanLedgerIdRef.value, |
| | | salesLedgerProductList: list, |
| | | inboundApproveUserIds, |
| | | approveUserIds, |
| | | }), |
| | | }, |
| | | }; |
| | |
| | | |
| | | </view> |
| | | |
| | | <view |
| | | |
| | | <view v-if="!isFullyOutbound(item)" |
| | | class="stocked-qty-block"> |
| | | |
| | | <view class="kv-row stocked-qty-row"> |
| | |
| | | |
| | | }; |
| | | |
| | | const parseUnqualifiedInboundQty = item => { |
| | | return ( |
| | | parseOptionalNumber( |
| | | item?.unqualifiedStockedQuantity ?? |
| | | item?.unQualifiedStockedQuantity ?? |
| | | item?.unqualifiedStockedQty ?? |
| | | item?.unqualifiedInboundQuantity |
| | | ) ?? 0 |
| | | ); |
| | | }; |
| | | |
| | | const parseUnqualifiedOutboundQty = item => { |
| | | return ( |
| | | parseOptionalNumber( |
| | | item?.unqualifiedShippedQuantity ?? |
| | | item?.unQualifiedShippedQuantity ?? |
| | | item?.unqualifiedShippedQty ?? |
| | | item?.unqualifiedOutboundQuantity |
| | | ) ?? 0 |
| | | ); |
| | | }; |
| | | |
| | | const isFullyOutbound = item => { |
| | | if (type.value === QUALITY_TYPE.unqualified) { |
| | | return parseUnqualifiedInboundQty(item) - parseUnqualifiedOutboundQty(item) <= 0; |
| | | } |
| | | const remaining = parseOptionalNumber(item?.remainingShippedQuantity); |
| | | if (remaining !== null) return remaining <= 0; |
| | | const fallback = parseOptionalNumber(defaultStockedQuantityFromRow(item, "outbound")); |
| | | return fallback !== null ? fallback <= 0 : false; |
| | | }; |
| | | |
| | | const hasEditableOutboundItems = computed(() => { |
| | | if (!recordList.value?.length) return false; |
| | | return recordList.value.some(item => !isFullyOutbound(item)); |
| | | }); |
| | | |
| | | |
| | | |
| | | const formatCell = (item, row, idx) => { |
| | |
| | | return; |
| | | |
| | | } |
| | | if (!hasEditableOutboundItems.value) { |
| | | modal.msgError("该产品已经全部出库"); |
| | | return; |
| | | } |
| | | |
| | | const salesLedgerProductList = buildSalesLedgerProductList(recordList.value); |
| | | |