From 70b7935fc261cd5e8eaaf1cfbc8078b04db576d2 Mon Sep 17 00:00:00 2001
From: liu <2021943741@qq.com>
Date: 星期六, 07 十一月 2026 14:51:06 +0800
Subject: [PATCH] fix(mes): 自动回填销售订单生产信息
---
src/views/mes/md/item/index.vue | 12 +++
src/views/mes/pro/workorder/modules/form.vue | 2
src/views/mes/pro/workorder/sale-order-fill.ts | 30 ++++++++++
src/api/mes/md/item/index.ts | 8 ++
src/views/mes/pro/workorder/data.ts | 39 +++++++++++-
src/views/mes/md/item/type/components/tree.vue | 31 +++++++++-
6 files changed, 111 insertions(+), 11 deletions(-)
diff --git a/src/api/mes/md/item/index.ts b/src/api/mes/md/item/index.ts
index 4469943..309935c 100644
--- a/src/api/mes/md/item/index.ts
+++ b/src/api/mes/md/item/index.ts
@@ -6,6 +6,7 @@
/** MES 鐗╂枡浜у搧 */
export interface Item {
id?: number; // 鐗╂枡缂栧彿
+ mdmItemId?: number; // MDM 鐗╂枡缂栧彿
code?: string; // 鐗╂枡缂栫爜
name?: string; // 鐗╂枡鍚嶇О
specification?: string; // 瑙勬牸鍨嬪彿
@@ -45,6 +46,13 @@
return requestClient.get<MesMdItemApi.Item>(`/mes/md/item/get?id=${id}`);
}
+/** 鏍规嵁 MDM 鐗╂枡缂栧彿鏌ヨ MES 鐗╂枡浜у搧 */
+export function getItemByMdmItemId(mdmItemId: number) {
+ return requestClient.get<MesMdItemApi.Item>(
+ `/mes/md/item/get-by-mdm-item-id?mdmItemId=${mdmItemId}`,
+ );
+}
+
/** 鏂板鐗╂枡浜у搧 */
export function createItem(data: MesMdItemApi.Item) {
return requestClient.post<number>('/mes/md/item/create', data);
diff --git a/src/views/mes/md/item/index.vue b/src/views/mes/md/item/index.vue
index 901c90c..bb1b68e 100644
--- a/src/views/mes/md/item/index.vue
+++ b/src/views/mes/md/item/index.vue
@@ -76,7 +76,11 @@
/** 瀵煎嚭鐗╂枡 */
async function handleExport() {
- const data = await exportItem(await gridApi.formApi.getValues());
+ const data = await exportItem({
+ ...(await gridApi.formApi.getValues()),
+ itemTypeId: selectedItemTypeId.value,
+ excludeItemTypeCode: "EQUIPMENT",
+ });
downloadFileFromBlobPart({ fileName: "鐗╂枡浜у搧.xls", source: data });
}
@@ -107,6 +111,7 @@
pageSize: page.pageSize,
...formValues,
itemTypeId: selectedItemTypeId.value,
+ excludeItemTypeCode: "EQUIPMENT",
});
},
},
@@ -132,7 +137,10 @@
class="mr-4 h-full w-1/6"
:body-style="{ height: '100%', overflow: 'hidden' }"
>
- <MdItemTypeTree @node-click="handleTypeNodeClick" />
+ <MdItemTypeTree
+ :exclude-codes="['EQUIPMENT']"
+ @node-click="handleTypeNodeClick"
+ />
</Card>
<div class="w-5/6">
<Grid table-title="鐗╂枡浜у搧鍒楄〃">
diff --git a/src/views/mes/md/item/type/components/tree.vue b/src/views/mes/md/item/type/components/tree.vue
index be62a8c..f92ab02 100644
--- a/src/views/mes/md/item/type/components/tree.vue
+++ b/src/views/mes/md/item/type/components/tree.vue
@@ -12,11 +12,13 @@
defineOptions({ name: 'MdItemTypeTree' });
-withDefaults(
+const props = withDefaults(
defineProps<{
+ excludeCodes?: string[];
filterPlaceholder?: string;
}>(),
{
+ excludeCodes: () => [],
filterPlaceholder: '鎼滅储鍒嗙被',
},
);
@@ -32,13 +34,36 @@
const itemTypeList = ref<MesMdItemTypeApi.ItemType[]>([]); // 鐗╂枡鍒嗙被鍒楄〃
const itemTypeTree = ref<any[]>([]); // 鐗╂枡鍒嗙被鏍�
+/** 鎸夊垎绫荤紪鐮佹帓闄ゅ垎绫诲強鍏跺叏閮ㄥ瓙鍒嗙被 */
+function filterExcludedTypes(data: MesMdItemTypeApi.ItemType[]) {
+ const excludedIds = new Set<number>();
+ let changed = true;
+ while (changed) {
+ changed = false;
+ for (const item of data) {
+ if (
+ item.id !== undefined &&
+ (props.excludeCodes.includes(item.code ?? '') ||
+ (item.parentId !== undefined && excludedIds.has(item.parentId))) &&
+ !excludedIds.has(item.id)
+ ) {
+ excludedIds.add(item.id);
+ changed = true;
+ }
+ }
+ }
+ return data.filter(
+ (item) => item.id === undefined || !excludedIds.has(item.id),
+ );
+}
+
/** 鍔犺浇鍒嗙被鏍� */
async function loadTree() {
loading.value = true;
try {
const data = await getItemTypeSimpleList();
- itemTypeList.value = data;
- itemTypeTree.value = handleTree(data, 'id', 'parentId');
+ itemTypeList.value = filterExcludedTypes(data);
+ itemTypeTree.value = handleTree(itemTypeList.value, 'id', 'parentId');
} finally {
loading.value = false;
}
diff --git a/src/views/mes/pro/workorder/data.ts b/src/views/mes/pro/workorder/data.ts
index 1006dd8..73721e3 100644
--- a/src/views/mes/pro/workorder/data.ts
+++ b/src/views/mes/pro/workorder/data.ts
@@ -15,9 +15,11 @@
} from '@vben/constants';
import { getDictOptions } from '@vben/hooks';
-import { Button } from 'ant-design-vue';
+import { Button, message } from 'ant-design-vue';
import { generateAutoCode } from '#/api/mes/md/autocode/record';
+import { getItemByMdmItemId } from '#/api/mes/md/item';
+import { getSaleOrderItemListByOrderId } from '#/api/erp/sale/order';
import CrmCustomerSelect from '#/components/crm-customer-select.vue';
import { getRangePickerDefaultProps } from '#/utils';
import {
@@ -25,6 +27,8 @@
} from '#/views/mes/md/item/components';
import { SrmSupplierSelect } from '#/views/srm/supplier/components';
import { ErpSaleOrderSelect } from '#/views/erp/sale/order/components';
+
+import { summarizeProductionProduct } from './sale-order-fill';
/** 琛ㄥ崟绫诲瀷 */
export type FormType = 'confirm' | 'create' | 'detail' | 'finish' | 'update';
@@ -208,15 +212,40 @@
componentProps: {
disabled: headerReadonly,
placeholder: '璇烽�夋嫨钀ラ攢璁㈠崟锛圗RP閿�鍞鍗曪級',
- // 閫変腑钀ラ攢璁㈠崟鍚庤嚜鍔ㄥ甫鍏ュ鎴�
+ // 閫変腑钀ラ攢璁㈠崟鍚庤嚜鍔ㄥ甫鍏ュ鎴枫�佹潵婧愬崟鍙枫�佷骇鍝佸拰鏁伴噺
onChange: async (item?: ErpSaleOrderApi.SaleOrder) => {
if (!item) {
return;
}
- const values = (await formApi?.getValues()) ?? {};
- if (values.clientId == null && item.customerId) {
- await formApi?.setFieldValue('clientId', item.customerId);
+ await formApi?.setValues({
+ clientId: item.customerId,
+ orderSourceCode: item.no,
+ productId: undefined,
+ quantity: undefined,
+ });
+ if (!item.id) {
+ return;
}
+ const orderItems = await getSaleOrderItemListByOrderId(item.id);
+ const products = summarizeProductionProduct(orderItems ?? []);
+ if (products.length === 0) {
+ message.warning('璇ラ攢鍞鍗曟病鏈夐渶瑕佺敓浜х殑浜у搧鏄庣粏');
+ return;
+ }
+ if (products.length > 1) {
+ message.warning('璇ラ攢鍞鍗曞寘鍚涓敓浜т骇鍝侊紝璇烽�夋嫨鍏蜂綋浜у搧骞跺~鍐欐暟閲�');
+ return;
+ }
+ const [product] = products;
+ const mesItem = await getItemByMdmItemId(product!.mdmProductId);
+ if (!mesItem?.id) {
+ message.warning('閿�鍞鍗曚骇鍝佸皻鏈悓姝ュ埌鐢熶骇鐗╂枡锛岃鍏堝悓姝ヤ骇鍝佷富鏁版嵁');
+ return;
+ }
+ await formApi?.setValues({
+ productId: mesItem.id,
+ quantity: product!.quantity,
+ });
},
},
dependencies: {
diff --git a/src/views/mes/pro/workorder/modules/form.vue b/src/views/mes/pro/workorder/modules/form.vue
index 1b24e67..4a2e9c6 100644
--- a/src/views/mes/pro/workorder/modules/form.vue
+++ b/src/views/mes/pro/workorder/modules/form.vue
@@ -90,7 +90,7 @@
// 浜у搧鍙樻洿鏃讹紝瑙﹀彂宸ュ簭鍔犺浇
if (isCreateMode.value && fieldsChanged.includes('productId')) {
const newProductId = values.productId;
- if (newProductId && newProductId !== currentProductId.value) {
+ if (newProductId !== currentProductId.value) {
currentProductId.value = newProductId;
}
}
diff --git a/src/views/mes/pro/workorder/sale-order-fill.ts b/src/views/mes/pro/workorder/sale-order-fill.ts
new file mode 100644
index 0000000..c07287a
--- /dev/null
+++ b/src/views/mes/pro/workorder/sale-order-fill.ts
@@ -0,0 +1,30 @@
+import type { ErpSaleOrderApi } from '#/api/erp/sale/order';
+
+export interface SaleOrderProductSummary {
+ mdmProductId: number;
+ quantity: number;
+}
+
+/**
+ * 姹囨�婚攢鍞鍗曚腑闇�瑕佺敓浜х殑浜у搧銆�
+ * 鍚屼竴浜у搧鍙瓨鍦ㄥ琛岋紝鐢熶骇宸ュ崟鍙渶瑕佷竴鏉′骇鍝佸強鍚堣鏁伴噺銆�
+ */
+export function summarizeProductionProduct(
+ items: ErpSaleOrderApi.SaleOrderItem[],
+): SaleOrderProductSummary[] {
+ const productionItems = items.filter(
+ (item) => item.needProduction === 1 && item.productId != null,
+ );
+ const quantityByProduct = new Map<number, number>();
+ for (const item of productionItems) {
+ const productId = item.productId!;
+ quantityByProduct.set(
+ productId,
+ (quantityByProduct.get(productId) ?? 0) + Number(item.count ?? 0),
+ );
+ }
+ return [...quantityByProduct.entries()].map(([mdmProductId, quantity]) => ({
+ mdmProductId,
+ quantity,
+ }));
+}
--
Gitblit v1.9.3