From a4ded59a4784abc853e734f6d38316af2c656716 Mon Sep 17 00:00:00 2001
From: gongchunyi <deslre0381@gmail.com>
Date: 星期四, 02 七月 2026 15:43:17 +0800
Subject: [PATCH] Merge branch 'dev_NEW_pro' of http://114.132.189.42:9002/r/product-inventory-management into dev_NEW_pro
---
src/views/procurementManagement/procurementLedger/index.vue | 4
src/views/salesManagement/returnOrder/components/formDia.vue | 81 +++++++++++--------
src/api/procurementManagement/procurementLedger.js | 8 ++
src/views/salesManagement/returnOrder/components/detailDia.vue | 8 -
src/views/financialManagement/receivable/receipt.vue | 71 ++++++++++++++++-
src/views/procurementManagement/purchaseReturnOrder/New.vue | 6
src/views/financialManagement/receivable/outputInvoice.vue | 12 +-
src/views/salesManagement/returnOrder/index.vue | 22 +++++
8 files changed, 156 insertions(+), 56 deletions(-)
diff --git a/src/api/procurementManagement/procurementLedger.js b/src/api/procurementManagement/procurementLedger.js
index 88f4ce0..c389582 100644
--- a/src/api/procurementManagement/procurementLedger.js
+++ b/src/api/procurementManagement/procurementLedger.js
@@ -9,6 +9,14 @@
params: query,
});
}
+// 閲囪喘閫�璐у彲閫夐噰璐彴璐�
+export function purchaseReturnableList(query) {
+ return request({
+ url: "/purchase/ledger/returnableList",
+ method: "get",
+ params: query,
+ });
+}
// 鏌ヨ鍚堝悓鍙�
export function getSalesNo(query) {
return request({
diff --git a/src/views/financialManagement/receivable/outputInvoice.vue b/src/views/financialManagement/receivable/outputInvoice.vue
index e5c8bf8..effb0af 100644
--- a/src/views/financialManagement/receivable/outputInvoice.vue
+++ b/src/views/financialManagement/receivable/outputInvoice.vue
@@ -93,7 +93,7 @@
@confirm="submitForm"
@cancel="closeDialog"
>
- <el-form :model="form" :rules="rules" ref="formRef" label-width="120px">
+ <el-form :model="form" :rules="rules" ref="formRef" label-width="100px">
<el-row v-if="isView" :gutter="20">
<el-col :span="12">
<el-form-item label="鐘舵��">
@@ -178,7 +178,7 @@
</el-col>
</el-row>
<el-row :gutter="20">
- <el-col :span="8">
+ <el-col :span="10">
<el-form-item label="閲戦(涓嶅惈绋�)" prop="amount">
<el-input-number
v-model="form.amount"
@@ -190,14 +190,14 @@
/>
</el-form-item>
</el-col>
- <el-col :span="8">
+ <el-col :span="7">
<el-form-item label="绋庨">
- <el-input v-model="form.taxAmount" disabled />
+ <el-input v-model="form.taxAmount" style="width: 100%;" disabled />
</el-form-item>
</el-col>
- <el-col :span="8">
+ <el-col :span="7">
<el-form-item label="浠风◣鍚堣">
- <el-input v-model="form.totalAmount" disabled />
+ <el-input v-model="form.totalAmount" style="width: 100%;" disabled />
</el-form-item>
</el-col>
</el-row>
diff --git a/src/views/financialManagement/receivable/receipt.vue b/src/views/financialManagement/receivable/receipt.vue
index 467a368..29194e7 100644
--- a/src/views/financialManagement/receivable/receipt.vue
+++ b/src/views/financialManagement/receivable/receipt.vue
@@ -171,10 +171,10 @@
prop="amount">
<el-input-number v-model="form.amount"
:min="0"
+ :max="collectionAmountInputMax"
:precision="2"
style="width: 100%;"
- :disabled="isView"
- placeholder="鏍规嵁鍏宠仈鍗曟嵁鑷姩姹囨�伙紝鍙慨鏀�" />
+ :disabled="isView" />
</el-form-item>
</el-col>
</el-row>
@@ -368,6 +368,7 @@
const isEdit = ref(false);
const isView = ref(false);
const currentId = ref(null);
+ const originalReceiptAmount = ref(0);
const submitLoading = ref(false);
const customerList = ref([]);
@@ -406,6 +407,46 @@
},
});
+ const maxCollectionAmount = computed(() => {
+ const selected = form.stockOutRecordIds || [];
+ const editAmount = isEdit.value ? Number(originalReceiptAmount.value) || 0 : 0;
+ if (!selected.length) return isEdit.value ? editAmount : undefined;
+ const selectedValueSet = new Set(selected.map(id => String(id)));
+ const selectedOptions = outboundBatchOptions.value.filter(
+ opt => opt.amountLimitAvailable && selectedValueSet.has(String(opt.value))
+ );
+ if (selectedOptions.length !== selectedValueSet.size) {
+ return isEdit.value ? Number(editAmount.toFixed(2)) : undefined;
+ }
+ const sum = selectedOptions.reduce(
+ (acc, opt) => acc + (Number(opt.outboundAmount) || 0),
+ 0
+ );
+ return Number((sum + editAmount).toFixed(2));
+ });
+
+ const collectionAmountInputMax = computed(
+ () => maxCollectionAmount.value ?? Number.MAX_SAFE_INTEGER
+ );
+
+ const validateCollectionAmount = (rule, value, callback) => {
+ if (value === undefined || value === null || value === "") {
+ callback();
+ return;
+ }
+ const amount = Number(value);
+ if (Number.isNaN(amount)) {
+ callback(new Error("璇疯緭鍏ユ敹娆鹃噾棰�"));
+ return;
+ }
+ const max = maxCollectionAmount.value;
+ if (max !== undefined && amount - max > 0.000001) {
+ callback(new Error(`鏀舵閲戦涓嶈兘瓒呰繃${max.toFixed(2)}`));
+ return;
+ }
+ callback();
+ };
+
const rules = {
customerId: [{ required: true, message: "璇烽�夋嫨瀹㈡埛", trigger: "change" }],
stockOutRecordIds: [
@@ -420,7 +461,10 @@
receiptDate: [
{ required: true, message: "璇烽�夋嫨鏀舵鏃ユ湡", trigger: "change" },
],
- amount: [{ required: true, message: "璇疯緭鍏ユ敹娆鹃噾棰�", trigger: "blur" }],
+ amount: [
+ { required: true, message: "璇疯緭鍏ユ敹娆鹃噾棰�", trigger: "blur" },
+ { validator: validateCollectionAmount, trigger: ["blur", "change"] },
+ ],
receiptMethod: [
{ required: true, message: "璇烽�夋嫨鏀舵鏂瑰紡", trigger: "change" },
],
@@ -480,7 +524,12 @@
return list.map((item, index) => {
if (typeof item === "string" || typeof item === "number") {
const text = String(item);
- return { label: text, value: text, outboundAmount: 0 };
+ return {
+ label: text,
+ value: text,
+ outboundAmount: 0,
+ amountLimitAvailable: false,
+ };
}
const label =
item.outboundBatches ??
@@ -490,10 +539,15 @@
item.label ??
`鍑哄簱鍗�${index + 1}`;
const value = item.id ?? item.stockOutRecordId ?? label;
+ const outboundAmount = Number(item.outboundAmount) || 0;
+ const amountReceived = Number(item.amountReceived) || 0;
+ const availableAmount = outboundAmount - amountReceived;
return {
label: String(label),
value,
- outboundAmount: (Number(item.outboundAmount)-Number(item.amountReceived)) || 0,
+ outboundAmount:
+ availableAmount > 0 ? Number(availableAmount.toFixed(2)) : 0,
+ amountLimitAvailable: true,
};
});
};
@@ -541,6 +595,7 @@
label: String(id),
value: id,
outboundAmount: 0,
+ amountLimitAvailable: false,
});
});
};
@@ -643,6 +698,7 @@
outboundSelectVisible.value = false;
syncCollectionAmount();
formRef.value?.validateField("stockOutRecordIds");
+ formRef.value?.validateField("amount");
};
const handleOutboundDialogClosed = () => {
@@ -713,6 +769,7 @@
outboundSelectVisible.value = false;
isView.value = false;
isEdit.value = false;
+ originalReceiptAmount.value = 0;
};
const handleExport = () => {
@@ -772,6 +829,7 @@
isEdit.value = false;
isView.value = false;
dialogTitle.value = "鏂板鏀舵";
+ originalReceiptAmount.value = 0;
Object.assign(form, {
receiptCode: "",
customerId: "",
@@ -794,13 +852,16 @@
currentId.value = row.id;
dialogTitle.value = "缂栬緫鏀舵";
fillFormFromRow(row);
+ originalReceiptAmount.value = Number(form.amount || 0);
dialogVisible.value = true;
+ loadOutboundBatches(form.customerId, true);
};
const view = row => {
isView.value = true;
isEdit.value = false;
dialogTitle.value = "鏌ョ湅鏀舵";
+ originalReceiptAmount.value = 0;
fillFormFromRow(row);
dialogVisible.value = true;
};
diff --git a/src/views/procurementManagement/procurementLedger/index.vue b/src/views/procurementManagement/procurementLedger/index.vue
index ed7e5d9..6d9cae6 100644
--- a/src/views/procurementManagement/procurementLedger/index.vue
+++ b/src/views/procurementManagement/procurementLedger/index.vue
@@ -219,7 +219,7 @@
<el-button link
type="primary"
@click="openForm('edit', scope.row)"
- :disabled="scope.row.stockInStatus === '瀹屽叏鍏ュ簱'">缂栬緫
+ :disabled="scope.row.approvalStatus === 3">缂栬緫
</el-button>
<el-button link
type="primary"
@@ -1747,7 +1747,7 @@
return;
}
const ids = selectedRows.value.map((item) => item.id);
-
+
ElMessageBox.confirm("纭鎵归噺鐢熸垚鏁版嵁锛�", "鎵归噺鐢熸垚", {
confirmButtonText: "纭",
cancelButtonText: "鍙栨秷",
diff --git a/src/views/procurementManagement/purchaseReturnOrder/New.vue b/src/views/procurementManagement/purchaseReturnOrder/New.vue
index 9474b11..f4771d3 100644
--- a/src/views/procurementManagement/purchaseReturnOrder/New.vue
+++ b/src/views/procurementManagement/purchaseReturnOrder/New.vue
@@ -420,7 +420,7 @@
<script setup>
import {ref, computed, getCurrentInstance, watch, defineAsyncComponent} from "vue";
import {createPurchaseReturnOrder} from "@/api/procurementManagement/purchase_return_order.js";
-import {getOptions, purchaseList} from "@/api/procurementManagement/procurementLedger.js";
+import {getOptions, purchaseReturnableList} from "@/api/procurementManagement/procurementLedger.js";
import {userListNoPageByTenantId} from "@/api/system/user.js";
const ProductList = defineAsyncComponent(() => import("@/views/procurementManagement/purchaseReturnOrder/ProductList.vue"));
const props = defineProps({
@@ -674,7 +674,7 @@
const fetchPurchaseLedgerOptions = () => {
purchaseLedgerOptions.value = []
if (formState.value.supplierId) {
- purchaseList({supplierId: formState.value.supplierId,approvalStatus:3}).then((res) => {
+ purchaseReturnableList({ supplierId: formState.value.supplierId }).then((res) => {
purchaseLedgerOptions.value = res.rows;
});
}
@@ -805,4 +805,4 @@
}
-</style>
\ No newline at end of file
+</style>
diff --git a/src/views/salesManagement/returnOrder/components/detailDia.vue b/src/views/salesManagement/returnOrder/components/detailDia.vue
index ecc663f..60b485b 100644
--- a/src/views/salesManagement/returnOrder/components/detailDia.vue
+++ b/src/views/salesManagement/returnOrder/components/detailDia.vue
@@ -21,9 +21,6 @@
<div style="padding-top: 20px">
<span class="descriptions">浜у搧鍒楄〃</span>
<PIMTable :isShowPagination="false" rowKey="id" :column="tableColumn" :tableData="tableData">
- <template #totalReturnNum="{ row }">
- {{ calcAlreadyReturned(row) }}
- </template>
</PIMTable>
</div>
</div>
@@ -252,8 +249,9 @@
{align: "center", label: "瑙勬牸鍨嬪彿", prop: "model"},
{align: "center", label: "鍗曚綅", prop: "unit", width: 80},
{align: "center", label: "鎬绘暟閲�", prop: "stockOutNum", width: 120},
- {align: "center", label: "宸查��璐ф暟閲�", prop: "totalReturnNum", width: 120, dataType: "slot", slot: "totalReturnNum"},
+ {align: "center", label: "宸查��璐ф暟閲�", prop: "totalReturnNum", width: 120},
{align: "center", label: "鏈��璐ф暟閲�", prop: "unQuantity", width: 120},
+ {align: "center", label: "寰呭鐞嗛��璐ф暟閲�", prop: "pendingReturnNum", width: 120},
{align: "center", label: "閫�璐ф暟閲�", prop: "returnQuantity", width: 120},
{align: "center", label: "閫�璐т骇鍝佸崟浠�", prop: "price", width: 120},
{align: "center", label: "閫�璐т骇鍝侀噾棰�", prop: "amount", width: 120},
@@ -284,7 +282,7 @@
try {
const res = await returnManagementGetById({ returnManagementId: row.id });
detail.value = res?.data ?? res ?? {};
-
+
if (detail.value.shippingId) {
const productRes = await returnManagementGetByShippingId({ shippingId: detail.value.shippingId });
if (productRes.code === 200) {
diff --git a/src/views/salesManagement/returnOrder/components/formDia.vue b/src/views/salesManagement/returnOrder/components/formDia.vue
index 81d9487..40c98dc 100644
--- a/src/views/salesManagement/returnOrder/components/formDia.vue
+++ b/src/views/salesManagement/returnOrder/components/formDia.vue
@@ -82,32 +82,29 @@
<el-button type="primary" @click="openProductSelection" :disabled="!form.shippingId">娣诲姞浜у搧</el-button>
</div>
<PIMTable :isShowPagination="false" rowKey="id" :column="tableColumn" :tableData="tableData">
- <template #totalReturnNum="{ row }">
- {{ calcAlreadyReturned(row) }}
- </template>
<template #returnQuantity="{ row }">
- <el-input
- v-model="row.returnQuantity"
- style="width:100px"
- placeholder="璇疯緭鍏�"
+ <el-input
+ v-model="row.returnQuantity"
+ style="width:100px"
+ placeholder="璇疯緭鍏�"
type="number"
@input="(val) => handleReturnQuantityChange(val, row)"
/>
</template>
<template #price="{ row }">
- <el-input
- v-model="row.price"
- style="width:100px"
- placeholder="璇疯緭鍏�"
+ <el-input
+ v-model="row.price"
+ style="width:100px"
+ placeholder="璇疯緭鍏�"
type="number"
@input="(val) => handlePriceChange(val, row)"
/>
</template>
<template #amount="{ row }">
- <el-input
- v-model="row.amount"
- style="width:100px"
- placeholder="鑷姩璁$畻"
+ <el-input
+ v-model="row.amount"
+ style="width:100px"
+ placeholder="鑷姩璁$畻"
type="number"
disabled
/>
@@ -119,10 +116,10 @@
</el-select>
</template>
<template #remark="{ row }">
- <el-input
- v-model="row.remark"
- style="width:130px"
- placeholder="璇疯緭鍏�"
+ <el-input
+ v-model="row.remark"
+ style="width:130px"
+ placeholder="璇疯緭鍏�"
/>
</template>
<template #action="{ index }">
@@ -140,9 +137,9 @@
</el-dialog>
<el-dialog v-model="productSelectionVisible" title="閫夋嫨浜у搧" width="70%" append-to-body>
- <el-table
- :data="availableProducts"
- style="width: 100%"
+ <el-table
+ :data="availableProducts"
+ style="width: 100%"
@selection-change="handleSelectionChange"
ref="productTableRef"
row-key="id"
@@ -154,11 +151,9 @@
<el-table-column align="center" prop="specificationModel" label="瑙勬牸鍨嬪彿" />
<el-table-column align="center" prop="unit" label="鍗曚綅" />
<el-table-column align="center" prop="stockOutNum" label="鎬绘暟閲�" />
+ <el-table-column align="center" label="宸查��璐ф暟閲�" prop="totalReturnNum"></el-table-column>
<el-table-column align="center" prop="unQuantity" label="鏈��璐ф暟閲�" />
- <el-table-column align="center" label="宸查��璐ф暟閲�">
- <template #default="{ row }">{{ calcAlreadyReturned(row) }}</template>
- </el-table-column>
-
+ <el-table-column align="center" prop="pendingReturnNum" label="寰呭鐞嗛��璐ф暟閲�" />
</el-table>
<template #footer>
<div class="dialog-footer">
@@ -226,7 +221,8 @@
{align: "center", label: "瑙勬牸鍨嬪彿", prop: "specificationModel" },
{align: "center", label: "鍗曚綅", prop: "unit", width: 80 },
{align: "center", label: "鎬绘暟閲�", prop: "stockOutNum", width: 120 },
- {align: "center", label: "宸查��璐ф暟閲�", prop: "totalReturnNum", width: 120, dataType: "slot", slot: "totalReturnNum" },
+ {align: "center", label: "宸查��璐ф暟閲�", prop: "totalReturnNum", width: 120 },
+ {align: "center", label: "寰呭鐞嗛��璐ф暟閲�", prop: "pendingReturnNum", width: 120 },
{align: "center", label: "鏈��璐ф暟閲�", prop: "unQuantity", width: 120 },
{align: "center", label: "閫�璐ф暟閲�", prop: "returnQuantity", dataType: "slot", slot: "returnQuantity", width: 120 },
{align: "center", label: "閫�璐т骇鍝佸崟浠�", prop: "price", dataType: "slot", slot: "price", width: 120 },
@@ -559,6 +555,18 @@
proxy.resetForm("formRef");
dialogFormVisible.value = false;
emit('close');
+ data.form = {
+ returnNoCheckbox: true,
+ returnNo: "",
+ customerId: "",
+ shippingId: "",
+ projectId: "",
+ maker: "",
+ makeTime: "",
+ status: 0,
+ returnReason: "",
+ refundAmount: "",
+ }
};
const initCustomers = async () => {
@@ -601,7 +609,7 @@
form.value.shippingId = "";
outboundOptions.value = [];
}
-
+
// Find customer name for getSalesLedger if it requires name
const customer = customerNameOptions.value.find(c => c.id === val);
if (!customer) return;
@@ -609,7 +617,7 @@
// Assuming getSalesLedger takes customerName. If it takes ID, adjust accordingly.
// Previous code used customerName. Let's try passing customerName.
getSalesLedger({
- customerName: customer.label,
+ customerName: customer.label,
}).then(res => {
if(res.code === 200){
outboundOptions.value = res.data.map(item => ({
@@ -626,7 +634,7 @@
if(res.code === 200){
// If backend returns project info, set it
if (res.data.projectId) form.value.projectId = res.data.projectId;
-
+
availableProducts.value = mergeShippingProductLists(res.data);
if (clearTable) tableData.value = [];
}
@@ -634,9 +642,12 @@
const handleReturnQuantityChange = (val, row) => {
if (val === "" || val === null) return;
- const max = row.unQuantity === undefined || row.unQuantity === null ? Infinity : Number(row.unQuantity || 0);
+ const unQuantity = row.unQuantity === undefined || row.unQuantity === null ? Infinity : Number(row.unQuantity || 0);//鏈��璐ф暟閲�
+ const pendingReturnNum = row.pendingReturnNum === undefined || row.pendingReturnNum === null ? Infinity : Number(row.pendingReturnNum || 0);//寰呭鐞嗛��璐ф暟閲�
+ //鏈�澶ч��璐ф暟閲忥紝濡傛灉涓虹紪杈戠姸鎬佸姞涓婂緟澶勭悊閫�璐ф暟閲�
+ const max = operationType.value === 'edit' ? unQuantity + pendingReturnNum : unQuantity
const current = Number(val);
-
+
if (current > max) {
proxy.$nextTick(() => {
row.returnQuantity = max;
@@ -702,7 +713,7 @@
// Removed checkSelectable to allow toggling existing items
const confirmProductSelection = () => {
const newTableData = [];
-
+
selectedProducts.value.forEach(product => {
const existing = tableData.value.find(item => item.id === product.id);
if (existing) {
@@ -710,7 +721,7 @@
} else {
newTableData.push({
...product,
- returnSaleLedgerProductId: product.id,
+ returnSaleLedgerProductId: product.id,
productModelId: product.productModelId,
returnQuantity: 0,
num: 0,
@@ -728,7 +739,7 @@
});
}
});
-
+
tableData.value = newTableData;
productSelectionVisible.value = false;
};
diff --git a/src/views/salesManagement/returnOrder/index.vue b/src/views/salesManagement/returnOrder/index.vue
index 0a8257b..e190901 100644
--- a/src/views/salesManagement/returnOrder/index.vue
+++ b/src/views/salesManagement/returnOrder/index.vue
@@ -38,6 +38,9 @@
<template #status="{ row }">
<el-tag :type="getStatusType(row.status)">{{ getStatusText(row.status) }}</el-tag>
</template>
+ <template #stockInApprovalStatus="{ row }">
+ <el-tag :type="getStockInApprovalStatusType(row.stockInApprovalStatus)">{{ getStockInApprovalStatusText(row.stockInApprovalStatus) }}</el-tag>
+ </template>
</PIMTable>
</div>
<form-dia ref="formDia" @close="handleQuery" />
@@ -114,6 +117,7 @@
const defaultColumns = [
{ label: "閫�璐у崟鍙�", prop: "returnNo", minWidth: 160 },
{ label: "鍗曟嵁鐘舵��", prop: "status", minWidth: 90, dataType: "slot", slot: "status" },
+ { label: "鍏ュ簱瀹℃壒鐘舵��", prop: "stockInApprovalStatus", minWidth: 120, dataType: "slot", slot: "stockInApprovalStatus" },
{ label: "鍒跺崟鏃堕棿", prop: "makeTime", minWidth: 170 },
{ label: "瀹㈡埛鍚嶇О", prop: "customerName", minWidth: 220 },
{ label: "閿�鍞崟鍙�", prop: "salesContractNo", minWidth: 160 },
@@ -207,6 +211,24 @@
return statusMap[status] || "鏈煡";
};
+const getStockInApprovalStatusType = (status) => {
+ const statusMap = {
+ 0: "",
+ 1: "success",
+ 2: "warning"
+ };
+ return statusMap[status] || "info";
+};
+
+const getStockInApprovalStatusText = (status) => {
+ const statusMap = {
+ 0: "鏈鎵�",
+ 1: "宸插鎵�",
+ 2: "瀹℃壒涓�"
+ };
+ return statusMap[status] || "鏈煡";
+};
+
onMounted(() => {
getList();
});
--
Gitblit v1.9.3