| ¶Ô±ÈÐÂÎļþ |
| | |
| | | <template> |
| | | <div class="app-container"> |
| | | <!-- æç´¢è¿æ»¤åº --> |
| | | <el-form :model="searchForm" :inline="true"> |
| | | <el-form-item label="éè´ååå·"> |
| | | <el-input v-model="searchForm.purchaseContractNumber" placeholder="请è¾å
¥" /> |
| | | </el-form-item> |
| | | <el-form-item label="ä¾åºå"> |
| | | <el-input v-model="searchForm.supplierName" placeholder="请è¾å
¥" /> |
| | | </el-form-item> |
| | | <el-form-item> |
| | | <el-button type="primary" @click="search">æç´¢</el-button> |
| | | <el-button @click="resetSearch">éç½®</el-button> |
| | | </el-form-item> |
| | | </el-form> |
| | | |
| | | <!-- è¡¨æ ¼å±ç¤ºåº --> |
| | | <el-table :data="orderList" border v-loading="loading" height="calc(100vh - 12em)"> |
| | | <!-- æ·»å åºå·å --> |
| | | <el-table-column align="center" label="åºå·" type="index" width="60" /> |
| | | <el-table-column prop="purchaseContractNumber" label="éè´ååå·" show-overflow-tooltip /> |
| | | <el-table-column prop="supplierName" label="ä¾åºå" show-overflow-tooltip /> |
| | | <el-table-column label="仿¬¾ç¶æ"> |
| | | <template #default="scope"> |
| | | <el-tag |
| | | :type="getPaymentStatusType(scope.row.paymentStatus)" |
| | | size="small" |
| | | > |
| | | {{ getPaymentStatusText(scope.row.paymentStatus) }} |
| | | </el-tag> |
| | | </template> |
| | | </el-table-column> |
| | | <el-table-column label="æ¶è´§ç¶æ"> |
| | | <template #default="scope"> |
| | | <el-tag |
| | | :type="getReceiptStatusType(scope.row.receiptStatus)" |
| | | size="small" |
| | | > |
| | | {{ getReceiptStatusText(scope.row.receiptStatus) }} |
| | | </el-tag> |
| | | </template> |
| | | </el-table-column> |
| | | <el-table-column prop="receivedQuantity" label="å·²æ¶è´§æ°é"/> |
| | | <el-table-column prop="unreceivedQuantity" label="æªæ¶è´§æ°é"/> |
| | | <el-table-column label="æä½" width="200" fixed="right" align="center"> |
| | | <template #default="scope"> |
| | | <el-button |
| | | type="primary" |
| | | size="small" |
| | | @click="confirmReceipter(scope.row)" |
| | | > |
| | | 确认æ¶è´§ |
| | | </el-button> |
| | | </template> |
| | | </el-table-column> |
| | | </el-table> |
| | | <!-- å¨è¡¨æ ¼ä¸æ¹æ·»å å页 --> |
| | | <pagination |
| | | v-show="total > 0" |
| | | :total="total" |
| | | layout="total, sizes, prev, pager, next, jumper" |
| | | :page="page.current" |
| | | :limit="page.size" |
| | | @pagination="paginationChange" |
| | | /> |
| | | <!-- 确认æ¶è´§å¯¹è¯æ¡ --> |
| | | <el-dialog v-model="receiptDialogVisible" title="确认æ¶è´§" width="70%"> |
| | | <el-form :model="receiptForm" label-width="120px" ref="formRef"> |
| | | <el-form-item label="éè´ååå·"> |
| | | <el-input v-model="receiptForm.purchaseContractNumber" disabled /> |
| | | </el-form-item> |
| | | <el-form-item label="å¼å¸¸åå "> |
| | | <el-input |
| | | v-model="receiptForm.exceptionReason" |
| | | type="textarea" |
| | | placeholder="请è¾å
¥å¼å¸¸åå ï¼ä¸åæ ¼æ¶å¡«åï¼" |
| | | /> |
| | | </el-form-item> |
| | | <el-table |
| | | :data="productList" |
| | | border |
| | | v-loading="loadingProducts" |
| | | @selection-change="handleSelectionChange" |
| | | > |
| | | <el-table-column align="center" type="selection" width="55" /> |
| | | <el-table-column |
| | | align="center" |
| | | label="åºå·" |
| | | type="index" |
| | | width="60" |
| | | /> |
| | | <el-table-column label="产å大类" prop="productCategory" /> |
| | | <el-table-column label="è§æ ¼åå·" prop="specificationModel" /> |
| | | <el-table-column label="åä½" prop="unit" width="70" /> |
| | | <el-table-column label="ä¾åºå" prop="supplierName" width="100" /> |
| | | <el-table-column label="éè´æ°é" prop="quantity" width="100" /> |
| | | <el-table-column label="å¾
å
¥åºæ°é" prop="quantity0" width="100" /> |
| | | <el-table-column label="æ¬æ¬¡å
¥åºæ°é" prop="quantityStock" width="150"> |
| | | <template #default="scope"> |
| | | <el-input-number :step="0.01" :min="0" style="width: 100%" v-model="scope.row.quantityStock" /> |
| | | </template> |
| | | </el-table-column> |
| | | <!-- åæ ¼æä¸åæ ¼--> |
| | | <el-table-column label="æ¯å¦åæ ¼" width="100"> |
| | | <template #default="scope"> |
| | | <el-select v-model="scope.row.isQualified" placeholder="è¯·éæ©"> |
| | | <el-option label="åæ ¼" value="1" /> |
| | | <el-option label="ä¸åæ ¼" value="2" /> |
| | | </el-select> |
| | | </template> |
| | | </el-table-column> |
| | | <el-table-column label="ç¨ç(%)" prop="taxRate" width="120" /> |
| | | <el-table-column |
| | | label="å«ç¨åä»·(å
)" |
| | | prop="taxInclusiveUnitPrice" |
| | | :formatter="formattedNumber" |
| | | width="150" |
| | | /> |
| | | <el-table-column |
| | | label="å«ç¨æ»ä»·(å
)" |
| | | prop="taxInclusiveTotalPrice" |
| | | :formatter="formattedNumber" |
| | | width="150" |
| | | /> |
| | | <el-table-column |
| | | label="ä¸å«ç¨æ»ä»·(å
)" |
| | | prop="taxExclusiveTotalPrice" |
| | | :formatter="formattedNumber" |
| | | width="150" |
| | | /> |
| | | </el-table> |
| | | </el-form> |
| | | <template #footer> |
| | | <el-button @click="receiptDialogVisible = false">åæ¶</el-button> |
| | | <el-button type="primary" @click="submitReceipt">确认æ¶è´§</el-button> |
| | | </template> |
| | | </el-dialog> |
| | | </div> |
| | | </template> |
| | | |
| | | <script setup> |
| | | import {ref, onMounted, getCurrentInstance} from 'vue' |
| | | import { |
| | | getPurchaseOrders, |
| | | confirmReceipt, |
| | | addPurchaseException |
| | | } from '@/api/procurementManagement/transferManagement.js' |
| | | import {selectProductRecordListByPuechaserId, addSutockIn, updateStockIn} from "@/api/inventoryManagement/stockIn.js"; |
| | | import useUserStore from "@/store/modules/user.js"; |
| | | |
| | | |
| | | const userStore = useUserStore() |
| | | const { proxy } = getCurrentInstance() |
| | | |
| | | // æ°æ®å®ä¹ |
| | | const orderList = ref([]) |
| | | const receiptDialogVisible = ref(false) |
| | | const receiptForm = ref({ |
| | | purchaseContractNumber: '', |
| | | exceptionReason: '', |
| | | purchaseLedgerId: '', |
| | | }) |
| | | const operationType = ref('')// æä½ç±»å: 'add' æ 'edit' |
| | | const productList = ref([]);// 产ååè¡¨æ°æ® |
| | | const loadingProducts = ref(false);// 产åå è½½ç¶æ |
| | | const selectedRows = ref([]); |
| | | const loading = ref(false); |
| | | const total = ref(0); // æ»è®°å½æ° |
| | | // æç´¢è¡¨å |
| | | const searchForm = ref({ |
| | | purchaseContractNumber: '', |
| | | supplierName: '', |
| | | }) |
| | | // åé¡µæ°æ® |
| | | const page = reactive({ |
| | | current: 1, |
| | | size: 100, // æ¯é¡µæ¾ç¤ºæ°é |
| | | }); |
| | | |
| | | // å页ååå¤ç |
| | | const paginationChange = (obj) => { |
| | | page.current = obj.page; |
| | | page.size = obj.limit; |
| | | getReceiptOrders(); // éæ°è·åæ°æ® |
| | | }; |
| | | // è·å订åå表 |
| | | const getReceiptOrders = async () => { |
| | | loading.value = true; |
| | | try { |
| | | const response = await getPurchaseOrders({ |
| | | ...searchForm.value, |
| | | current: page.current, |
| | | size: page.size |
| | | }); |
| | | // ä½¿ç¨ Promise.all å¤çææå¼æ¥è¯·æ± |
| | | const processedOrders = await Promise.all(response.data.records.map(async (order) => { |
| | | // çå¾
弿¥è·å产åè®°å½ |
| | | const productRes = await selectProductRecordListByPuechaserId({ |
| | | purchaseContractNumber: order.purchaseContractNumber |
| | | }); |
| | | |
| | | // ç¡®ä¿ productRes.data åå¨ |
| | | if (productRes && productRes.data && Array.isArray(productRes.data)) { |
| | | // è®¡ç®æ»æ°é |
| | | order.totalQuantity = productRes.data.reduce((acc, cur) => acc + (cur.quantity || 0), 0); |
| | | // è®¡ç®æªæ¶è´§æ°é |
| | | order.unreceivedQuantity = productRes.data.reduce((acc, cur) => acc + (cur.quantity0 || 0), 0); |
| | | // 计ç®å·²æ¶è´§æ°é |
| | | order.receivedQuantity = order.totalQuantity - order.unreceivedQuantity; |
| | | |
| | | // ä¿®æ£ç¶æå¤æé»è¾ï¼ä½¿ç¨ === è¿è¡æ¯è¾ï¼ |
| | | if (order.unreceivedQuantity === 0) { |
| | | order.paymentStatus = 1; |
| | | order.receiptStatus = 1; |
| | | } else if (order.receivedQuantity === 0) { |
| | | order.paymentStatus = 3; |
| | | order.receiptStatus = 3; |
| | | } else { |
| | | order.paymentStatus = 2; |
| | | order.receiptStatus = 2; |
| | | } |
| | | } else { |
| | | // å¦ææ²¡æäº§åè®°å½ï¼è®¾ç½®é»è®¤å¼ |
| | | order.totalQuantity = 0; |
| | | order.unreceivedQuantity = 0; |
| | | order.receivedQuantity = 0; |
| | | order.receiptStatus = 3; // æªå
¥åº |
| | | } |
| | | |
| | | return order; |
| | | })); |
| | | |
| | | // æ£ç¡®èµå¼ç» orderList |
| | | orderList.value = processedOrders; |
| | | total.value = response.data.total; |
| | | } catch (error) { |
| | | console.error('è·å订åå表失败:', error); |
| | | proxy.$modal.msgError('è·å订åå表失败'); |
| | | } finally { |
| | | loading.value = false; |
| | | } |
| | | } |
| | | |
| | | // 仿¬¾ç¶ææ¾ç¤ºå¤ç |
| | | const getPaymentStatusText = (status) => { |
| | | const statusMap = { '1': '已仿¬¾', '2': 'é¨å仿¬¾', '3': 'æªä»æ¬¾' } |
| | | return statusMap[status] || 'æªç¥' |
| | | } |
| | | |
| | | const getPaymentStatusType = (status) => { |
| | | const typeMap = { '1': 'success', '2': 'warning', '3': 'danger' } |
| | | return typeMap[status] || 'info' |
| | | } |
| | | |
| | | // æ¶è´§ç¶æå¤ç |
| | | const getReceiptStatusText = (status) => { |
| | | const statusMap = { '1': 'æ¶è´§å®æ', '2': 'é¨åå
¥åº', '3': 'æªå
¥åº' } |
| | | return statusMap[status] || 'æªç¥' |
| | | } |
| | | |
| | | const getReceiptStatusType = (status) => { |
| | | const typeMap = { '1': 'success', '2': 'warning', '3': 'info' } |
| | | return typeMap[status] || 'info' |
| | | } |
| | | const exceedsAddLimit = (product) => { |
| | | const stock = Number(product?.quantityStock ?? 0); |
| | | const waiting = Number(product?.quantity0 ?? 0); |
| | | if (!Number.isFinite(stock) || !Number.isFinite(waiting)) { |
| | | return false; |
| | | } |
| | | return stock > waiting; |
| | | }; |
| | | const exceedsEditLimit = (product) => { |
| | | const stock = Number(product?.quantityStock ?? 0); |
| | | const waiting = Number(product?.quantity0 ?? 0); |
| | | const original = Number(product?.originalQuantityStock ?? 0); |
| | | if (!Number.isFinite(stock) || !Number.isFinite(waiting) || !Number.isFinite(original)) { |
| | | return false; |
| | | } |
| | | return stock > waiting + original; |
| | | }; |
| | | const updatePro = async () => { |
| | | const target = selectedRows.value[0]; |
| | | const stock = Number(target?.quantityStock ?? 0); |
| | | if (!Number.isFinite(stock) || stock <= 0) { |
| | | proxy.$modal.msgWarning('è¯·å¡«åææçå
¥åºæ°é'); |
| | | return; |
| | | } |
| | | if (exceedsEditLimit(target)) { |
| | | proxy.$modal.msgError('æ¬æ¬¡å
¥åºæ°éä¸è½è¶
è¿åå
¥åºæ°éä¸å¾
å
¥åºæ°éä¹å'); |
| | | return; |
| | | } |
| | | const stockInData = { |
| | | id: selectedRows.value[0].recordId, |
| | | quantityStock: Number(selectedRows.value[0].quantityStock),// ä½¿ç¨æ°æ ¼å¼å彿° |
| | | }; |
| | | await updateStockIn(stockInData) |
| | | proxy.$modal.msgSuccess('ä¿®æ¹å
¥åºæå') |
| | | closeDia() |
| | | getReceiptOrders() // å·æ°å表 |
| | | } |
| | | // è¡¨æ ¼éæ©æ°æ® |
| | | const handleSelectionChange = (selection) => { |
| | | // è¿æ»¤æåæ°æ® |
| | | selectedRows.value = selection.filter(item => item.id); |
| | | } |
| | | // æå¼å¼¹æ¡-确认æ¶è´§ |
| | | const confirmReceipter = (row) => { |
| | | receiptForm.value = { |
| | | purchaseContractNumber: row.purchaseContractNumber, |
| | | purchaseLedgerId: row.id, |
| | | exceptionReason: '' |
| | | } |
| | | selectedRows.value = [] |
| | | receiptDialogVisible.value = true |
| | | fetchProductsByContract() |
| | | } |
| | | |
| | | const fetchProductsByContract = async () => |
| | | { |
| | | try { |
| | | loadingProducts.value = true |
| | | // æ ¹æ®ååæ¥è¯¢äº§åè®°å½ |
| | | const productRes = await selectProductRecordListByPuechaserId({ |
| | | purchaseContractNumber: receiptForm.value.purchaseContractNumber |
| | | }); |
| | | console.log('productRes:', productRes) |
| | | operationType.value = 'add' |
| | | if (!productRes.data || productRes.data.length === 0) { |
| | | proxy.$modal.msgWarning('该åå䏿²¡æäº§åè®°å½') |
| | | productList.value = []; |
| | | return |
| | | } |
| | | // å¤çäº§åæ°æ®ï¼æ·»å æ¬æ¬¡å
¥åºæ°éåæ®µ |
| | | productList.value = productRes.data.map(item => ({ |
| | | ...item, |
| | | quantityStock: 0, |
| | | originalQuantityStock: Number(item.quantityStock ?? item.inboundQuantity ?? 0), |
| | | })) |
| | | selectedRows.value = productList.value |
| | | } catch (error) { |
| | | console.error('æ¥è¯¢äº§åè®°å½å¤±è´¥:', error) |
| | | proxy.$modal.msgError('æ¥è¯¢äº§åè®°å½å¤±è´¥') |
| | | productList.value = []; |
| | | } finally { |
| | | loadingProducts.value = false |
| | | } |
| | | } |
| | | |
| | | |
| | | // æäº¤æ¶è´§ç¡®è®¤ |
| | | const submitReceipt = async () => { |
| | | if(operationType.value !== 'add'){ |
| | | await updatePro() |
| | | return |
| | | } |
| | | try { |
| | | await proxy.$refs.formRef.validate() |
| | | // éªè¯å
¥åºæ°é |
| | | const invalidProducts = selectedRows.value.filter((product) => { |
| | | const stock = Number(product?.quantityStock ?? 0); |
| | | if (!Number.isFinite(stock) || stock <= 0) { |
| | | return true; |
| | | } |
| | | return exceedsAddLimit(product); |
| | | }) |
| | | |
| | | if (invalidProducts.length > 0) { |
| | | proxy.$modal.msgError('æ¬æ¬¡å
¥åºæ°éé大äº0ï¼ä¸ä¸è½è¶
è¿å¾
å
¥åºæ°é') |
| | | return |
| | | } |
| | | loading.value = true |
| | | // åå¤æäº¤æ°æ® - ä¿®æ¹ä¸ºå端éè¦çæ ¼å¼ |
| | | const stockInData = { |
| | | // å
¥åºååºæ¬ä¿¡æ¯ |
| | | ...receiptForm.value, |
| | | nickName: userStore.nickName, |
| | | details: selectedRows.value.map(product => ({ |
| | | id: product.id, |
| | | inboundQuantity: Number(product.quantityStock) |
| | | })), |
| | | }; |
| | | //å¦æäº§ååæ ¼ |
| | | if(productList.value.every(product => product.isQualified === '1')){ |
| | | await addSutockIn(stockInData) |
| | | |
| | | proxy.$modal.msgSuccess('确认æ¶è´§,å
¥åºæå') |
| | | }else{ |
| | | stockInData.details.forEach(item => { |
| | | const ProcurementExceptionRecord = { |
| | | purchaseContractNumber: receiptForm.value.purchaseContractNumber, |
| | | purchaseLedgerId: receiptForm.value.purchaseLedgerId, |
| | | exceptionNum: item.inboundQuantity, |
| | | exceptionReason: receiptForm.value.exceptionReason |
| | | } |
| | | addPurchaseException(ProcurementExceptionRecord).then(response => { |
| | | proxy.$modal.msgSuccess('产åä¸åæ ¼ï¼éè´å¼å¸¸è®°å½æå') |
| | | }) |
| | | }) |
| | | } |
| | | closeDia() |
| | | getReceiptOrders() // å·æ°å表 |
| | | |
| | | } catch (error) { |
| | | console.error('æäº¤å¤±è´¥:', error) |
| | | if (!error.errors) { |
| | | proxy.$modal.msgError('æä½å¤±è´¥ï¼è¯·éè¯') |
| | | } |
| | | } finally { |
| | | loading.value = false |
| | | } |
| | | } |
| | | // å
³éå¼¹æ¡ |
| | | const closeDia = () => { |
| | | proxy.$refs.formRef.resetFields() |
| | | receiptDialogVisible.value = false |
| | | } |
| | | // æç´¢åéç½® |
| | | const search = () => { |
| | | getReceiptOrders() |
| | | } |
| | | |
| | | const resetSearch = () => { |
| | | searchForm.value = { |
| | | purchaseContractNumber: '', |
| | | supplierName: '', |
| | | } |
| | | getReceiptOrders() |
| | | } |
| | | |
| | | onMounted(() => { |
| | | getReceiptOrders() |
| | | }) |
| | | </script> |