| | |
| | | /** MES ç©æäº§å */ |
| | | export interface Item { |
| | | id?: number; // ç©æç¼å· |
| | | mdmItemId?: number; // MDM ç©æç¼å· |
| | | code?: string; // ç©æç¼ç |
| | | name?: string; // ç©æåç§° |
| | | specification?: string; // è§æ ¼åå· |
| | |
| | | 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); |
| | |
| | | |
| | | /** 导åºç©æ */ |
| | | 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 }); |
| | | } |
| | | |
| | |
| | | pageSize: page.pageSize, |
| | | ...formValues, |
| | | itemTypeId: selectedItemTypeId.value, |
| | | excludeItemTypeCode: "EQUIPMENT", |
| | | }); |
| | | }, |
| | | }, |
| | |
| | | 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="ç©æäº§åå表"> |
| | |
| | | |
| | | defineOptions({ name: 'MdItemTypeTree' }); |
| | | |
| | | withDefaults( |
| | | const props = withDefaults( |
| | | defineProps<{ |
| | | excludeCodes?: string[]; |
| | | filterPlaceholder?: string; |
| | | }>(), |
| | | { |
| | | excludeCodes: () => [], |
| | | filterPlaceholder: 'æç´¢åç±»', |
| | | }, |
| | | ); |
| | |
| | | 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; |
| | | } |
| | |
| | | } 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 { |
| | |
| | | } 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'; |
| | |
| | | componentProps: { |
| | | disabled: headerReadonly, |
| | | placeholder: 'è¯·éæ©è¥é订åï¼ERPéå®è®¢åï¼', |
| | | // éä¸è¥é订ååèªå¨å¸¦å
¥å®¢æ· |
| | | // éä¸è¥é订ååèªå¨å¸¦å
¥å®¢æ·ãæ¥æºåå·ã产ååæ°é |
| | | 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: { |
| | |
| | | // 产ååæ´æ¶ï¼è§¦åå·¥åºå è½½ |
| | | if (isCreateMode.value && fieldsChanged.includes('productId')) { |
| | | const newProductId = values.productId; |
| | | if (newProductId && newProductId !== currentProductId.value) { |
| | | if (newProductId !== currentProductId.value) { |
| | | currentProductId.value = newProductId; |
| | | } |
| | | } |
| ¶Ô±ÈÐÂÎļþ |
| | |
| | | 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, |
| | | })); |
| | | } |