feat(wms): 优化采购订单和入库单功能

-移除不必要的字段和功能
- 增加物料选择和验证逻辑
- 优化分包计算和验证
- 改进错误提示和用户交互
master
zangch@mesnac.com 4 months ago
parent 4a981e5ce9
commit d31642860f

@ -133,16 +133,16 @@
<el-table-column label="已分包数量" align="center" prop="printedNum" />
<el-table-column label="物料规格" align="center" prop="materialSpe"/>
<el-table-column label="计量单位名称" align="center" prop="unitName"/>
<el-table-column label="是否有条码" align="center" prop="codeYesNo">
<template #default="scope">
<dict-tag :options="wms_barcode_if" :value="scope.row.codeYesNo"/>
</template>
</el-table-column>
<!-- <el-table-column label="是否有条码" align="center" prop="codeYesNo">-->
<!-- <template #default="scope">-->
<!-- <dict-tag :options="wms_barcode_if" :value="scope.row.codeYesNo"/>-->
<!-- </template>-->
<!-- </el-table-column>-->
<!-- <el-table-column label="物料大类" align="center" prop="materialCategoryName">-->
<!-- </el-table-column>-->
<el-table-column label="操作" fixed="right" width="200">
<template #default="scope">
<el-button size="small" @click="childrenTableUpdate( scope.row)" v-if="auditStatusLoad && partntTableSelectCell.instockType !== '6'">
<el-button size="small" @click="childrenTableUpdate( scope.row)" v-if="auditStatusLoad && partntTableSelectCell.instockType !== '6' && isRowPrintable(scope.row)">
打印
</el-button>
<el-button
@ -163,15 +163,15 @@
<el-dialog v-model="dialogVisible" :title="dialogTitle" width="80%">
<el-card shadow="never">
<el-form :model="dialogForm" :inline="true" label-width="120px" :disabled="isView" ref="dialogFormRef" :rules="dialogFormRules">
<el-form-item label="物料大类" prop="materialCategoryId">
<el-select v-model="dialogForm.materialCategoryId" placeholder="请选择物料大类" @change="setMaterialList">
<el-option v-for="item in mategoryOptions"
:key="item.materialCategoryId"
:label="item.materialCategoryName"
:value="item.materialCategoryId"
/>
</el-select>
</el-form-item>
<!-- <el-form-item label="物料大类" prop="materialCategoryId">-->
<!-- <el-select v-model="dialogForm.materialCategoryId" placeholder="请选择物料大类" @change="setMaterialList">-->
<!-- <el-option v-for="item in mategoryOptions"-->
<!-- :key="item.materialCategoryId"-->
<!-- :label="item.materialCategoryName"-->
<!-- :value="item.materialCategoryId"-->
<!-- />-->
<!-- </el-select>-->
<!-- </el-form-item>-->
<el-form-item label="工单类型" prop="instockType">
<el-select v-model="dialogForm.instockType" placeholder="请选择工单类型">
<el-option
@ -275,10 +275,10 @@
</template>
</el-table-column>
<el-table-column label="物料单位" prop="materialUnit">
<el-table-column label="物料单位" prop="unitName">
<template #default="scope">
<el-select
v-model="scope.row.materialUnit"
v-model="scope.row.unitName"
placeholder="选择物料"
style="width: 240px"
:disabled="true"
@ -418,15 +418,15 @@
<el-dialog v-model="parentTableInfoVisible" title="修改父表格" width="40%">
<el-form :model="parentTableInfoForm" label-width="120px">
<el-form-item label="物料大类" prop="materialCategoryId">
<el-select v-model="parentTableInfoForm.materialCategoryId" placeholder="请选择物料大类" :disabled="true">
<el-option v-for="item in mategoryOptions"
:key="item.materialCategoryId"
:label="item.materialCategoryName"
:value="item.materialCategoryId"
/>
</el-select>
</el-form-item>
<!-- <el-form-item label="物料大类" prop="materialCategoryId">-->
<!-- <el-select v-model="parentTableInfoForm.materialCategoryId" placeholder="请选择物料大类" :disabled="true">-->
<!-- <el-option v-for="item in mategoryOptions"-->
<!-- :key="item.materialCategoryId"-->
<!-- :label="item.materialCategoryName"-->
<!-- :value="item.materialCategoryId"-->
<!-- />-->
<!-- </el-select>-->
<!-- </el-form-item>-->
<el-form-item label="工单类型" prop="instockType">
<el-select v-model="parentTableInfoForm.instockType" placeholder="请选择工单类型">
<el-option
@ -525,15 +525,15 @@
<el-form-item label="入库数量" prop="instockQty">
<el-input v-model="childrenTableInfoForm.instockQty" placeholder="请输入入库数量" :disabled="true"/>
</el-form-item>
<el-form-item label="有无条码" prop="codeYesNo">
<el-radio-group v-model="childrenTableInfoForm.codeYesNo" :disabled="true">
<el-radio
v-for="dict in wms_barcode_if"
:key="dict.value"
:value="dict.value"
>{{dict.label}}</el-radio>
</el-radio-group>
</el-form-item>
<!-- <el-form-item label="有无条码" prop="codeYesNo">-->
<!-- <el-radio-group v-model="childrenTableInfoForm.codeYesNo" :disabled="true">-->
<!-- <el-radio-->
<!-- v-for="dict in wms_barcode_if"-->
<!-- :key="dict.value"-->
<!-- :value="dict.value"-->
<!-- >{{dict.label}}</el-radio>-->
<!-- </el-radio-group>-->
<!-- </el-form-item>-->
<el-form-item>
@ -545,7 +545,7 @@
<el-input v-model="childrenTableInfoForm.printedNum" placeholder="" :disabled="true"/>
</el-form-item>
<el-form-item label="分包数量" prop="splitPackageCount">
<el-input-number v-model="childrenTableInfoForm.splitPackageCount" :min="1" :max="remainingQty" placeholder="请输入分包数量" @change="onSplitPackageCountChange" />
<el-input-number v-model="childrenTableInfoForm.splitPackageCount" :min="1" :max="instockQty" placeholder="请输入分包数量" @change="onSplitPackageCountChange" />
</el-form-item>
<!-- 当分包数量大于1时显示分包模式选择和每包数量配置 -->
@ -564,7 +564,8 @@
<span class="package-qty">{{qty}}</span>
</div>
<div class="total-qty-info">
<span>总计{{averageTotal}} / {{remainingQty}}</span>
<span :class="{'error-text': averageTotal !== instockQty}">总计{{averageTotal}} / {{instockQty}}</span>
<span v-if="averageTotal !== instockQty" class="error-text"> - </span>
</div>
</div>
</el-form-item>
@ -577,7 +578,7 @@
<el-input-number
v-model="packageQtyList[index]"
:min="1"
:max="remainingQty"
:max="instockQty"
placeholder="请输入数量"
@change="validateTotalQty"
size="small"
@ -585,7 +586,8 @@
/>
</div>
<div class="total-qty-info">
<span :class="{'error-text': totalPackageQty > remainingQty}">总计{{totalPackageQty}} / {{remainingQty}}</span>
<span :class="{'error-text': totalPackageQty !== instockQty}">总计{{totalPackageQty}} / {{instockQty}}</span>
<span v-if="totalPackageQty !== instockQty" class="error-text"> - </span>
</div>
</div>
</el-form-item>
@ -783,23 +785,30 @@ listUser({ pageNum: 1, pageSize: 99999 }).then(e => {
})
/** 提交按钮 */
const submitForm = async() => {
if (!childrenTableInfoForm.value.instockQty || !childrenTableInfoForm.value.printedNum) {
if (!childrenTableInfoForm.value.instockQty || childrenTableInfoForm.value.printedNum === undefined) {
ElMessage.error('物料数据未加载完成,请重试')
return
}
//
if (Number(childrenTableInfoForm.value.printedNum) > 0) {
ElMessage.error('该入库单已经打印过,不允许重复打印')
return
}
const split = Number(childrenTableInfoForm.value.splitPackageCount) || 1
const copies = Number(childrenTableInfoForm.value.printCopies) || 1
const remaining = remainingQty.value
const totalInstockQty = instockQty.value // 使
if (split > 1) {
//
// 使packageQtyList
let finalPackageList = []
if (packageMode.value === 'average') {
// 使
finalPackageList = averagePackageList.value
const total = averageTotal.value
if (total > remaining) {
ElMessage.error('平均分包总计不能超过剩余物料量')
if (total !== totalInstockQty) {
ElMessage.error(`分包数量大于1时必须一次性分配完所有入库数量 ${totalInstockQty},当前总计:${total}`)
return
}
if (total <= 0) {
@ -810,8 +819,8 @@ const submitForm = async() => {
// 使
finalPackageList = packageQtyList.value
const total = totalPackageQty.value
if (total > remaining) {
ElMessage.error('每包数量总计不能超过剩余物料量')
if (total !== totalInstockQty) {
ElMessage.error(`分包数量大于1时每包数量总计必须等于入库数量 ${totalInstockQty},当前总计:${total}`)
return
}
if (total <= 0) {
@ -825,13 +834,12 @@ const submitForm = async() => {
}
}
//
//
childrenTableInfoForm.value.packageQtyList = finalPackageList
childrenTableInfoForm.value.packageMode = packageMode.value //
} else {
//
if (split > remaining) {
ElMessage.error('分包数量不能超过剩余物料量')
//
if (split > totalInstockQty) {
ElMessage.error('分包数量不能超过入库数量')
return
}
if (copies < 1) {
@ -1137,9 +1145,11 @@ const parentTableInfoSubmit = () =>{
//
const childrenTableUpdate = async (e) => {
const detail = (await getInstockDetail(e.instockDetailId)).data
const remaining = Number(detail.instockQty) - Number(detail.printedNum || 0)
if(remaining < 1){
ElMessage.error('无剩余数量可打印')
const printed = Number(detail.printedNum || 0)
//
if(printed > 0){
ElMessage.error('该入库单已经打印过,不允许重复打印')
return
}
@ -1282,7 +1292,7 @@ const handleAssociatePurchaseOrder = async () => {
});
dialogtable.value = res.data.map(item => ({
poDId: item.poDId, //
materialId: item.materialCode, //
// materialId: item.materialId,
materialCode: item.materialCode,
materialName: item.materialName,
materialSpe: item.materialSpe,
@ -1337,18 +1347,25 @@ const validateQty = (row, val) => {
}
//
if (row.deliveryQty !== undefined && intVal > row.deliveryQty) {
row.instockQty = row.deliveryQty;
ElMessage.warning(`入库数量不能大于交付数量 ${row.deliveryQty}`);
} else {
row.instockQty = Math.max(0, intVal);
}
// if (row.deliveryQty !== undefined && intVal > row.deliveryQty) {
// row.instockQty = row.deliveryQty;
// ElMessage.warning(` ${row.deliveryQty}`);
// } else {
// row.instockQty = Math.max(0, intVal);
// }
};
const remainingQty = computed(() => {
// remainingQty
// instockQty
const instock = Number(childrenTableInfoForm.value.instockQty) || 0
const printed = Number(childrenTableInfoForm.value.printedNum) || 0
return Math.max(0, instock - printed) // Math.max
return Math.max(0, instock - printed) //
})
//
const instockQty = computed(() => {
return Number(childrenTableInfoForm.value.instockQty) || 0
})
//
@ -1388,12 +1405,14 @@ const onSplitPackageCountChange = (count) => {
//
const calculateAveragePackage = (count) => {
const remaining = remainingQty.value
if (remaining > 0 && count > 0) {
const avgQty = Math.floor(remaining / count)
const remainder = remaining % count
const totalQty = instockQty.value // 使
if (totalQty > 0 && count > 0) {
const avgQty = Math.floor(totalQty / count)
const remainder = totalQty % count
averagePackageList.value = []
for (let i = 0; i < count; i++) {
// avgQty + 1 avgQty
averagePackageList.value[i] = avgQty + (i < remainder ? 1 : 0)
}
}
@ -1411,10 +1430,15 @@ const onPackageModeChange = (mode) => {
//
const validateTotalQty = () => {
const total = totalPackageQty.value
const remaining = remainingQty.value
const totalQty = instockQty.value // 使
if (total > remaining) {
ElMessage.warning(`每包数量总计不能超过剩余数量 ${remaining}`)
if (total > totalQty) {
ElMessage.warning(`每包数量总计不能超过入库数量 ${totalQty}`)
}
// 1
if (childrenTableInfoForm.value.splitPackageCount > 1 && total !== totalQty) {
ElMessage.warning(`分包数量大于1时每包数量总计必须等于入库数量 ${totalQty}`)
}
}
@ -1428,6 +1452,17 @@ const isAddDisabled = computed(() => {
return dialogForm.value.instockType === '1';
});
//
const isRowPrintable = (row) => {
const printed = Number(row.printedNum || 0)
//
if (printed > 0) {
return false
}
return true
}
</script>
<style scoped>
.demo-form-inline .el-input {

@ -10,11 +10,11 @@
<el-option v-for="dict in wms_po_status" :key="dict.value" :label="dict.label" :value="dict.value"/>
</el-select>
</el-form-item>
<el-form-item label="订单类型" prop="poType">
<el-select v-model="queryForm.poType" placeholder="请选择订单类型" clearable>
<el-option v-for="dict in wms_po_type" :key="dict.value" :label="dict.label" :value="dict.value"/>
</el-select>
</el-form-item>
<!-- <el-form-item label="订单类型" prop="poType">-->
<!-- <el-select v-model="queryForm.poType" placeholder="请选择订单类型" clearable>-->
<!-- <el-option v-for="dict in wms_po_type" :key="dict.value" :label="dict.label" :value="dict.value"/>-->
<!-- </el-select>-->
<!-- </el-form-item>-->
<!-- <el-form-item label="物料大类" prop="materialCategoryId">-->
<!-- <el-select v-model="queryForm.materialCategoryId" placeholder="请选择物料大类" clearable>-->
<!-- <el-option v-for="item in mategoryOptions"-->
@ -24,11 +24,11 @@
<!-- />-->
<!-- </el-select>-->
<!-- </el-form-item>-->
<el-form-item label="审核状态" prop="auditStatus">
<el-select v-model="queryForm.auditStatus" placeholder="请选择审核状态" clearable>
<el-option v-for="dict in wms_audit_status" :key="dict.value" :label="dict.label" :value="dict.value"/>
</el-select>
</el-form-item>
<!-- <el-form-item label="审核状态" prop="auditStatus">-->
<!-- <el-select v-model="queryForm.auditStatus" placeholder="请选择审核状态" clearable>-->
<!-- <el-option v-for="dict in wms_audit_status" :key="dict.value" :label="dict.label" :value="dict.value"/>-->
<!-- </el-select>-->
<!-- </el-form-item>-->
<el-form-item>
<el-button :loading="parentTableLoad" type="primary" @click="query"></el-button>
<el-button @click="reset"></el-button>
@ -70,10 +70,10 @@
</el-table-column>
<el-table-column label="计划交货日期" align="center" prop="planDeliveryDate" width="180">
<template #default="scope">
<span>{{ parseTime(scope.row.planDeliveryDate, '{y}-{m}-{d} {h}:{i}:{s}') }}</span>
<span>{{ parseTime(scope.row.planDeliveryDate, '{y}-{m}-{d} ') }}</span>
</template>
</el-table-column>
<el-table-column label="供应商" align="center" prop="supplierCode"/>
<el-table-column label="供应商" align="center" prop="supplierName"/>
<el-table-column label="订单类型" align="center" prop="poType">
<template #default="scope">
<dict-tag :options="wms_po_type" :value="scope.row.poType"/>
@ -269,6 +269,7 @@
<el-input
v-model="scope.row.materialCode"
placeholder="请点击检索物料"
readonly
@click="handleMaterialAdd('material', scope.$index)">
<template #append>
<el-icon class="el-input__icon">
@ -297,10 +298,10 @@
</template>
</el-table-column>
<el-table-column label="物料单位" prop="materialUnit">
<el-table-column label="物料单位" prop="unitName">
<template #default="scope">
<el-select
v-model="scope.row.materialUnit"
v-model="scope.row.unitName"
placeholder="选择物料"
style="width: 240px"
:disabled="true"
@ -315,10 +316,10 @@
</template>
</el-table-column>
<el-table-column label="物料规格" prop="materialSpec">
<el-table-column label="物料规格" prop="materialSpe">
<template #default="scope">
<el-select
v-model="scope.row.materialSpec"
v-model="scope.row.materialSpe"
placeholder="选择物料"
style="width: 240px"
:disabled="true"
@ -342,11 +343,11 @@
<el-input v-model="scope.row.purchaseQty" placeholder="请输入采购数量" style="width: 240px"/>
</template>
</el-table-column>
<!-- <el-table-column label="送货数量" prop="deliveryQty" readonly>
<el-table-column label="送货数量" prop="deliveryQty" readonly>
<template #default="scope">
<el-input v-model="scope.row.deliveryQty" placeholder="请输入送货数量" style="width: 240px"/>
<el-input v-model="scope.row.deliveryQty" placeholder="送货数量不可编辑" style="width: 240px" disabled/>
</template>
</el-table-column> -->
</el-table-column>
<el-table-column label="操作" fixed="right" width="200">
<template #default="scope">
<el-button
@ -372,6 +373,14 @@
<el-dialog v-model="parentTableInfoVisible" title="修改父表格" width="40%">
<el-form :model="parentTableInfoForm" label-width="120px">
<el-form-item label="计划日期" prop="supplierId">
<el-date-picker clearable
v-model="parentTableInfoForm.planDeliveryDate"
type="date"
value-format="YYYY-MM-DD"
placeholder="请选择计划交货日期">
</el-date-picker>
</el-form-item>
<el-form-item label="供应商" prop="supplierId">
<el-select v-model="parentTableInfoForm.supplierId" placeholder="请选择供应商">
<el-option
@ -382,6 +391,10 @@
></el-option>
</el-select>
</el-form-item>
<el-form-item label="备注" prop="remark">
<el-input v-model="parentTableInfoForm.remark" placeholder="请输入备注" />
</el-form-item>
<!-- <el-form-item label="订单类型" prop="poType">-->
<!-- <el-select v-model="parentTableInfoForm.poType" placeholder="请选择订单类型">-->
<!-- <el-option-->
@ -686,6 +699,7 @@ const parentTableAdd = () => {
//
const parentTableUpdate = async (e) => {
getListSelect();
let id = ref(null)
if (e) {
id.value = e.poId
@ -743,22 +757,98 @@ const setMaterialList = (materialCategoryId) => {
//
const addDialogTableCell = () => {
dialogtable.value.push({})
//
for (let i = 0; i < dialogtable.value.length; i++) {
const row = dialogtable.value[i];
if (!row.materialId || !row.materialCode) {
ElMessage({
type: 'warning',
message: `${i + 1}行必须先选择物料!`,
});
return;
}
}
//
dialogtable.value.push({});
}
//
const dialogSubmit = () => {
//
if (!dialogForm.value.supplierId) {
ElMessage({
type: 'warning',
message: '请选择供应商!',
});
return;
}
//
if (!dialogtable.value || dialogtable.value.length === 0) {
ElMessage({
type: 'warning',
message: '请至少添加一行采购明细!',
});
return;
}
//
for (let i = 0; i < dialogtable.value.length; i++) {
const row = dialogtable.value[i];
//
if (!row.materialId || !row.materialCode) {
ElMessage({
type: 'warning',
message: `${i + 1}行必须选择物料!`,
});
return;
}
//
if (!row.purchaseQty || row.purchaseQty <= 0) {
ElMessage({
type: 'warning',
message: `${i + 1}行采购数量必须大于0`,
});
return;
}
//
// if (!row.taxPrice || row.taxPrice <= 0) {
// ElMessage({
// type: 'warning',
// message: `${i + 1}0`,
// });
// return;
// }
}
//
addWmsPurchaseOrder(dialogForm.value).then(e => {
addWmsPurchaseOrderDetail(dialogtable.value.map(item => {
return {...item, poNo: e.data.poNo}
}
)
).then(v => {
ElMessage({
type: 'success',
message: '采购订单创建成功!',
});
dialogVisible.value = false
getParentTable()
}).catch(error => {
ElMessage({
type: 'error',
message: '采购订单明细保存失败:' + (error.message || '未知错误'),
});
})
}).catch(error => {
ElMessage({
type: 'error',
message: '采购订单保存失败:' + (error.message || '未知错误'),
});
})
}
@ -843,30 +933,83 @@ const handleSelection = (row) => {
const submitMaterialForm = () => {
if (!selectedMaterial.value) {
//
selectedMaterial.value = materialSelectRef.value.tableRef.store.states.currentRow.value;
if (materialSelectRef.value && materialSelectRef.value.tableRef && materialSelectRef.value.tableRef.store.states.currentRow.value) {
selectedMaterial.value = materialSelectRef.value.tableRef.store.states.currentRow.value;
}
}
if (!selectedMaterial.value) {
ElMessage({
type: 'warning',
message: '请选择一个物料!',
});
return;
}
//
if (!selectedMaterial.value.materialId || !selectedMaterial.value.materialCode) {
ElMessage({
type: 'error',
message: '选中的物料信息不完整,请重新选择!',
});
return;
}
if (selectedMaterial.value) {
if (selectType.value === 'material') {
//
if (currentRowIndex.value >= 0 && dialogtable.value[currentRowIndex.value]) {
//
if (currentRowIndex.value < 0 || currentRowIndex.value >= dialogtable.value.length) {
ElMessage({
type: 'error',
message: '无效的行索引!',
});
return;
}
// 使
for (let i = 0; i < dialogtable.value.length; i++) {
if (i !== currentRowIndex.value && dialogtable.value[i].materialId === selectedMaterial.value.materialId) {
ElMessage({
type: 'warning',
message: `该物料已在第${i + 1}行中使用,请选择其他物料!`,
});
return;
}
}
//
if (dialogtable.value[currentRowIndex.value]) {
dialogtable.value[currentRowIndex.value].materialId = selectedMaterial.value.materialId;
dialogtable.value[currentRowIndex.value].materialName = selectedMaterial.value.materialName;
dialogtable.value[currentRowIndex.value].materialCode = selectedMaterial.value.materialCode;
dialogtable.value[currentRowIndex.value].unitName = selectedMaterial.value.materialUnit;
dialogtable.value[currentRowIndex.value].materialSpe = selectedMaterial.value.materialSpec;
//
ElMessage({
type: 'success',
message: '物料选择成功!',
});
}
}
}
//
selectedMaterial.value = null;
currentRowIndex.value = -1;
materialOpen.value = false;
};
/** 新增按钮操作 */
const handleMaterialAdd = (type, index) => {
//
if (index < 0 || index >= dialogtable.value.length) {
ElMessage({
type: 'error',
message: '行索引无效!',
});
return;
}
selectType.value = type;
currentRowIndex.value = index; //
materialOpen.value = true;

Loading…
Cancel
Save