feat(tsoorder): 新增订单类型字典并优化生产订单功能

This commit is contained in:
zxy 2026-04-20 18:07:31 +08:00
parent 3d5ff4a36f
commit 3077a47d15
5 changed files with 154 additions and 108 deletions

View File

@ -16,6 +16,7 @@ import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.StringUtils;
import java.math.BigDecimal;
import java.util.List;
/**
@ -132,6 +133,7 @@ public class ProOrderServiceImpl extends ServiceImpl<ProOrderMapper, ProOrderEnt
for (OrderDetailForm orderItem : orderItems) {
OrderDetailEntity detailEntity = orderDetailService.getById(orderItem.getItemId());
ExampleOrderEntity orderEntity = orderService.getById(detailEntity.getSaleOrdId());
// 判断是全部转生产还是部分转生产
if (detailEntity != null) {
ProSoRelationEntity proSoRelationEntity = new ProSoRelationEntity();
proSoRelationEntity.setProId(proOrder.getId());
@ -148,7 +150,15 @@ public class ProOrderServiceImpl extends ServiceImpl<ProOrderMapper, ProOrderEnt
proSoRelationEntity.setUnit(detailEntity.getUnit());
proSoRelationEntity.setMaterialId(detailEntity.getMaterialId());
proSoRelationService.save(proSoRelationEntity);
// 更新订单明细状态为已转产
detailEntity.setOrdItemStatus("2");
// 默认金额可能为 null
detailEntity.setProduceQty(detailEntity.getProduceQty() == null ? BigDecimal.ZERO : detailEntity.getProduceQty().add(orderItem.getPlanQty()));
orderDetailService.updateById(detailEntity);
}
orderEntity.setProStatus("1");
orderService.updateById(orderEntity);
}
List<OrderLineForm> proLines = orderForm.getProLines();

View File

@ -10,6 +10,8 @@ export const dictMaps = {
paramType: { '1': '温度', '2': '压力', '3': '时间', '4': '速度' },
// 启用状态
enabledStatus: { '1': '启用', '2': '未启用' },
// 订单类型
ordType: { '1': '备库订单', '2': '销售订单' },
};
// 根据映射自动生成下拉选项使用id和fullName字段
@ -33,5 +35,6 @@ export function getLabel(type, value) {
// 快捷导出常用选项
export const paramTypeOptions = dictOptions.paramType;
export const enabledStatusOptions = dictOptions.enabledStatus;
export const ordTypeOptions = dictOptions.ordType;

View File

@ -68,6 +68,16 @@ export default {
if (val) {
this.loadProLineList();
}
},
selectedLineCodes: {
handler() {
if (this.visible && this.proLineList.length > 0) {
this.$nextTick(() => {
this.setDefaultSelection();
});
}
},
deep: true
}
},
methods: {
@ -78,7 +88,7 @@ export default {
data: {
currentPage: this.page.currentPage,
pageSize: this.page.pageSize,
// selectKey: this.search.selectKey,
selectKey: this.search.selectKey,
dataType: 0,
enabledStatus: 1
}
@ -86,24 +96,31 @@ export default {
if (res.code === 200) {
this.proLineList = res.data.list || [];
this.page.total = res.data.pagination ? res.data.pagination.total : 0;
this.$nextTick(() => {
//
setTimeout(() => {
this.setDefaultSelection();
});
}, 100);
}
});
},
setDefaultSelection() {
if (this.selectedLineCodes.length > 0) {
const table = this.$refs.proLineTable;
if (this.selectedLineCodes.length > 0 && this.proLineList.length > 0) {
// JNPF-table使refJNPFTable
const jnpfTable = this.$refs.proLineTable;
const table = jnpfTable ? jnpfTable.$refs.JNPFTable : null;
if (table) {
table.clearSelection();
const defaultSelected = this.proLineList.filter(line =>
this.selectedLineCodes.includes(line.proLineCd)
);
const defaultSelected = this.proLineList.filter(line => {
const lineCode = line.proLineCd || line.lineCode || '';
return this.selectedLineCodes.includes(lineCode);
});
this.selectedLines = [...defaultSelected];
defaultSelected.forEach(line => {
table.toggleRowSelection(line, true);
this.$nextTick(() => {
defaultSelected.forEach(line => {
table.toggleRowSelection(line, true);
});
});
}
}
@ -134,9 +151,9 @@ export default {
const selectedData = this.selectedLines.map(line => ({
lineId: line.id || line.lineId || '',
lineCode: line.lineCode || line.proLineCd || '',
lineName: line.lineName || line.proLineName || '',
remark: line.remark || ""
lineCode: line.proLineCd || line.lineCode || '',
lineName: line.proLineName || line.lineName || '',
remark: ""
}));
this.$emit("confirm", selectedData);

View File

@ -17,19 +17,19 @@
<el-row :gutter="20">
<el-col :span="8">
<el-form-item label="订单编号" prop="orderNo">
<el-input disabled placeholder="" />
<el-input disabled placeholder=""/>
</el-form-item>
</el-col>
<el-col :span="8">
<el-form-item label="订单日期" prop="proDate">
<el-date-picker v-model="baseForm.proDate" type="date" placeholder="选择日期" />
<el-date-picker v-model="baseForm.proDate" type="date" placeholder="选择日期"/>
</el-form-item>
</el-col>
<el-col :span="8">
<el-form-item label="订单状态" prop="orderStatus">
<el-select v-model="baseForm.orderStatus" placeholder="请选择" disabled>
<el-option label="未下发" value="0" />
<el-option label="已下发" value="1" />
<el-option label="未下发" value="0"/>
<el-option label="已下发" value="1"/>
</el-select>
</el-form-item>
</el-col>
@ -37,31 +37,31 @@
<el-row :gutter="20">
<el-col :span="8">
<el-form-item label="产品名称" prop="materialName">
<el-input v-model="baseForm.materialName" disabled placeholder="产品名称" />
<el-input v-model="baseForm.materialName" disabled placeholder="产品名称"/>
</el-form-item>
</el-col>
<el-col :span="8">
<el-form-item label="规格型号" prop="spec">
<el-input v-model="baseForm.spec" disabled placeholder="规格型号" />
<el-input v-model="baseForm.spec" disabled placeholder="规格型号"/>
</el-form-item>
</el-col>
<el-col :span="8">
<el-form-item label="单位" prop="unit">
<el-input v-model="baseForm.unitText" disabled placeholder="单位" />
<el-input v-model="baseForm.unitText" disabled placeholder="单位"/>
</el-form-item>
</el-col>
</el-row>
<el-row :gutter="20">
<el-col :span="8">
<el-form-item label="计划数量" prop="planQty">
<el-input v-model.number="baseForm.planQty" readonly placeholder="计划数量" />
<el-input v-model.number="baseForm.planQty" disabled placeholder="计划数量"/>
</el-form-item>
</el-col>
<el-col :span="8">
<el-form-item label="开始日期" prop="planBgDate">
<el-date-picker
v-model="baseForm.planBgDate"
type="date"
<el-date-picker
v-model="baseForm.planBgDate"
type="date"
placeholder="选择日期"
:picker-options="{ disabledDate: (time) => {
if (this.baseForm.planEndDate) {
@ -74,9 +74,9 @@
</el-col>
<el-col :span="8">
<el-form-item label="结束日期" prop="planEndDate">
<el-date-picker
v-model="baseForm.planEndDate"
type="date"
<el-date-picker
v-model="baseForm.planEndDate"
type="date"
placeholder="选择日期"
:picker-options="{ disabledDate: (time) => {
if (this.baseForm.planBgDate) {
@ -91,32 +91,32 @@
<el-row :gutter="20">
<el-col :span="8">
<el-form-item label="工艺流程" prop="processFlow">
<el-select
v-model="baseForm.processFlow"
filterable
:remote-method="searchProcessFlow"
:loading="processFlowLoading"
placeholder="请选择"
>
<el-option
v-for="item in processFlowList"
:key="item.id"
:label="item.name"
:value="item.id"
/>
</el-select>
<el-select
v-model="baseForm.processFlow"
filterable
:remote-method="searchProcessFlow"
:loading="processFlowLoading"
placeholder="请选择"
>
<el-option
v-for="item in processFlowList"
:key="item.id"
:label="item.name"
:value="item.id"
/>
</el-select>
</el-form-item>
</el-col>
<el-col :span="16">
<el-form-item label="备注" prop="remark">
<el-input v-model="baseForm.remark" type="textarea" :rows="2" placeholder="请输入备注" />
<el-input v-model="baseForm.remark" type="textarea" :rows="2" placeholder="请输入备注"/>
</el-form-item>
</el-col>
</el-row>
<el-row>
<el-col :span="24">
<el-row :gutter="20">
<el-col :span="8">
<el-form-item>
<el-checkbox v-model="baseForm.isAllLine" true-label="0" false-label="1" />
<el-checkbox v-model="baseForm.isAllLine" true-label="0" false-label="1"/>
<span style="margin-left: 5px;">所有产线</span>
</el-form-item>
</el-col>
@ -131,30 +131,30 @@
</div>
<div class="section-body">
<el-table :data="orderList" border :height="200">
<el-table-column prop="itemId" label="序号" align="center" type="index" />
<el-table-column prop="saleOrdNo" label="订单编码" align="center" />
<el-table-column prop="itemId" label="序号" align="center" type="index" width="50"/>
<el-table-column prop="saleOrdNo" label="订单编码" align="center"/>
<el-table-column prop="proStatus" label="生产状态" align="center">
<template slot-scope="scope">
{{ getProStatusText(scope.row.proStatus) }}
</template>
</el-table-column>
<el-table-column prop="ordDate" label="下单日期" align="center" :formatter="jnpf.tableDateFormat1" />
<el-table-column prop="ordQty" label="订单数量" align="center" />
<el-table-column prop="produceQty" label="已转生产数量" align="center" />
<el-table-column prop="remainingQty" label="剩余数量" align="center" />
<el-table-column prop="ordDate" label="下单日期" align="center" :formatter="jnpf.tableDateFormat1"/>
<el-table-column prop="ordQty" label="订单数量" align="center"/>
<el-table-column prop="produceQty" label="已转生产数量" align="center"/>
<el-table-column prop="remainingQty" label="剩余数量" align="center"/>
<el-table-column label="转生产数量" align="center">
<template slot-scope="scope">
<el-input
v-model.number="scope.row.planQty"
<el-input
v-model.number="scope.row.planQty"
:max="scope.row.remainingQty"
@input="handlePlanQtyInput(scope.row)"
placeholder="请输入"
placeholder="请输入"
/>
</template>
</el-table-column>
<el-table-column prop="ordType" label="订单类型" align="center">
<template slot-scope="scope">
{{ scope.row.ordType === '2' ? '销售订单' : '其他' }}
{{ getLabel('ordType', scope.row.ordType) }}
</template>
</el-table-column>
<el-table-column prop="isUrgent" label="是否急单" align="center">
@ -162,9 +162,9 @@
{{ scope.row.isUrgent === '1' ? '是' : '否' }}
</template>
</el-table-column>
<el-table-column prop="materialName" label="产品名称" align="center" />
<el-table-column prop="spec" label="规格型号" align="center" />
<el-table-column prop="custName" label="客户名称" align="center" />
<el-table-column prop="materialName" label="产品名称" align="center"/>
<el-table-column prop="spec" label="规格型号" align="center"/>
<el-table-column prop="custName" label="客户名称" align="center"/>
<el-table-column prop="unit" label="单位" align="center">
<template slot-scope="scope">
{{ getUnitText(scope.row.unit) }}
@ -186,14 +186,13 @@
<i class="el-icon-warning"></i> 产线分配数量不等于计划数量请确认
</div>
<el-table :data="lineList" border :height="200">
<el-table-column prop="index" label="序号" align="center" type="index" />
<el-table-column prop="lineCode" label="产线编码" align="center" />
<el-table-column prop="lineName" label="产线名称" align="center" />
<el-table-column prop="index" label="序号" align="center" type="index"/>
<el-table-column prop="lineCode" label="产线编码" align="center"/>
<el-table-column prop="lineName" label="产线名称" align="center"/>
<el-table-column prop="allocateQty" label="分配数量(*" align="center">
<template slot-scope="scope">
<el-input
v-model="scope.row.allocateQty"
placeholder="分配数量"
<el-input
v-model="scope.row.allocateQty"
style="width: 120px;"
@input="handleAllocateQtyInput(scope.row)"
/>
@ -201,22 +200,22 @@
</el-table-column>
<el-table-column prop="completedQty" label="已完成数量" align="center">
<template slot-scope="scope">
<el-input v-model.number="scope.row.completedQty" placeholder="已完成数量" disabled />
<el-input v-model.number="scope.row.completedQty" placeholder="0" disabled/>
</template>
</el-table-column>
<el-table-column prop="planStartDate" label="计划开工日期" align="center">
<template slot-scope="scope">
<el-date-picker v-model="scope.row.planStartDate" type="date" placeholder="选择日期" />
<el-date-picker v-model="scope.row.planStartDate" type="date" placeholder="选择日期"/>
</template>
</el-table-column>
<el-table-column prop="planEndDate" label="计划完成日期" align="center">
<template slot-scope="scope">
<el-date-picker v-model="scope.row.planEndDate" type="date" placeholder="选择日期" />
<el-date-picker v-model="scope.row.planEndDate" type="date" placeholder="选择日期"/>
</template>
</el-table-column>
<el-table-column prop="remark" label="备注" align="center">
<template slot-scope="scope">
<el-input v-model="scope.row.remark" placeholder="备注" />
<el-input v-model="scope.row.remark" placeholder="备注"/>
</template>
</el-table-column>
<el-table-column label="操作" align="center" width="80">
@ -236,10 +235,10 @@
</div>
<!-- 产线选择弹窗 -->
<ProLineSelect
:visible.sync="lineModalVisible"
<ProLineSelect
:visible.sync="lineModalVisible"
:selected-line-codes="selectedLineCodes"
@confirm="handleProLineConfirm"
@confirm="handleProLineConfirm"
/>
</div>
</template>
@ -248,6 +247,7 @@
import request from "@/utils/request";
import jnpf from "@/utils/jnpf";
import ProLineSelect from "@/views/example/proline/select";
import {getLabel} from "../../common/dict";
export default {
name: "GenerateOrder",
@ -291,6 +291,9 @@ export default {
spec: [
{required: true, message: "请输入规格型号", trigger: "blur"}
],
planQty: [
{required: true, message: "", trigger: "blur"}
],
planBgDate: [
{required: true, message: "请选择开始日期", trigger: "change"}
@ -375,7 +378,7 @@ export default {
if (!keyword) {
this.processFlowList = this.allProcessFlowList;
} else {
this.processFlowList = this.allProcessFlowList.filter(item =>
this.processFlowList = this.allProcessFlowList.filter(item =>
item.name && item.name.toLowerCase().includes(keyword.toLowerCase())
);
}
@ -433,14 +436,17 @@ export default {
},
getProStatusText(status) {
const map = { '0': '正常', '1': '部分转生产', '2': '全部转生产' };
const map = {'0': '正常', '1': '部分转生产', '2': '全部转生产'};
return map[status] || status;
},
getUnitText(unit) {
const map = { '1': '件', '2': '公斤', '3': '吨' };
const map = {'1': '件', '2': '公斤', '3': '吨'};
return map[unit] || unit;
},
getLabel(type, value) {
return getLabel(type, value);
},
formatDate(row, column) {
const date = row[column.prop];
@ -486,7 +492,7 @@ export default {
},
goBack() {
this.$router.push("/example/tsoorder");
this.$router.push({path: "/example/tsoorder", query: {refresh: new Date().getTime()}});
},
save() {
@ -585,7 +591,7 @@ export default {
if (this.lineList.length === 0) {
return true;
}
let hasValidAllocateQty = false;
for (let item of this.lineList) {
const allocateQty = Number(item.allocateQty);
@ -594,12 +600,12 @@ export default {
break;
}
}
if (!hasValidAllocateQty) {
this.$message.error("至少需要有一条产线设置有效的分配数量");
return false;
}
for (let item of this.lineList) {
const allocateQty = Number(item.allocateQty);
if (!isNaN(allocateQty) && allocateQty > 0) {
@ -609,15 +615,15 @@ export default {
return false;
}
}
const totalPlanQty = this.orderList.reduce((sum, item) => sum + Number(item.planQty || 0), 0);
const totalAllocateQty = this.lineList.reduce((sum, item) => sum + Number(item.allocateQty || 0), 0);
if (Math.abs(totalPlanQty - totalAllocateQty) > 0.0001) {
this.$message.warning("产线分配数量不等于计划数量,请确认!");
return false;
}
return true;
},
@ -626,9 +632,9 @@ export default {
itemId: item.itemId,
planQty: item.planQty
}));
const firstItem = this.orderList[0] || {};
const proLines = this.lineList.map(item => ({
lineId: item.id || item.lineId || '',
lineCode: item.lineCode || '',
@ -638,7 +644,7 @@ export default {
planEndDate: item.planEndDate || '',
remark: item.remark || ''
}));
return {
...this.baseForm,
planBgDate: this.baseForm.planBgDate,
@ -773,4 +779,4 @@ export default {
justify-content: center;
gap: 16px;
}
</style>
</style>

View File

@ -73,42 +73,43 @@
<div></div>
<div class="JNPF-common-head-right"></div>
</div>
<JNPF-table v-loading="listLoading" :data="list" border ref="table" height="400" :row-key="row => row.itemId" @selection-change="handleSelectionChange">
<el-table-column type="selection" align="center" :reserve-selection="true" />
<el-table-column prop="saleOrdNo" label="订单编码" align="center" min-width="120" />
<el-table-column prop="ordStatus" label="订单状态" align="center" min-width="100">
<JNPF-table v-loading="listLoading" :data="list" :hasNO="false" border ref="table" height="400" :row-key="row => row.itemId" @selection-change="handleSelectionChange" :index="false">
<el-table-column type="index" label="序号" align="center" width="60" fixed="left" />
<el-table-column type="selection" align="center" :reserve-selection="true" fixed="left" />
<el-table-column prop="saleOrdNo" label="订单编码" align="center" min-width="120" fixed="left"/>
<el-table-column prop="ordStatus" label="订单状态" align="center" min-width="80" fixed="left">
<template slot-scope="scope">
{{ getDictText(scope.row.ordStatus, ordStatusOptions) }}
</template>
</el-table-column>
<el-table-column prop="ordDate" label="下单日期" align="center" min-width="120" :formatter="jnpf.tableDateFormat1"/>
<el-table-column prop="ordDate" label="下单日期" align="center" min-width="90" :formatter="jnpf.tableDateFormat1"/>
<el-table-column prop="custName" label="客户名称" align="center" min-width="150" />
<el-table-column prop="materialName" label="产品名称" align="center" min-width="150" />
<el-table-column prop="spec" label="规格型号" align="center" min-width="120" />
<el-table-column prop="ordQty" label="订单数量" align="center" min-width="100" />
<el-table-column label="已转生产数量" align="center" min-width="120">
<el-table-column prop="spec" label="规格型号" align="center" min-width="100" />
<el-table-column prop="ordQty" label="订单数量" align="center" min-width="95" />
<el-table-column label="已转生产数量" align="center" min-width="95">
<template slot-scope="scope">
{{ Number(scope.row.produceQty) || 0 }}
</template>
</el-table-column>
<el-table-column label="剩余数量" align="center" min-width="100">
<el-table-column label="剩余数量" align="center" min-width="95">
<template slot-scope="scope">
{{ (Number(scope.row.ordQty) || 0) - (Number(scope.row.produceQty) || 0) }}
</template>
</el-table-column>
<el-table-column prop="ordType" label="订单类型" align="center" min-width="100">
<el-table-column prop="ordType" label="订单类型" align="center" min-width="90">
<template slot-scope="scope">
{{ scope.row.ordType == '1' ? '常规' : scope.row.ordType == '2' ? '定制' : scope.row.ordType }}
{{ getLabel('ordType', scope.row.ordType) }}
</template>
</el-table-column>
<el-table-column prop="reqDeliveryDate" label="要求交货日期" align="center" min-width="120" :formatter="jnpf.tableDateFormat1"/>
<el-table-column prop="isUrgent" label="是否急单" align="center" min-width="100">
<el-table-column prop="reqDeliveryDate" label="要求交货日期" align="center" min-width="110" :formatter="jnpf.tableDateFormat1"/>
<el-table-column prop="isUrgent" label="是否急单" align="center" min-width="70">
<template slot-scope="scope">
{{ scope.row.isUrgent == '0' ? '是' : scope.row.isUrgent == '1' ? '否' : '' }}
</template>
</el-table-column>
<el-table-column label="单位" align="center" min-width="80">
<el-table-column label="单位" align="center" min-width="50">
<template slot-scope="scope">
{{ scope.row.unit == '1' ? 'kg' : scope.row.unit == '2' ? 'T' : scope.row.unit }}
</template>
@ -118,12 +119,12 @@
{{ getLabel('proStatus', scope.row.proStatus) }}
</template>
</el-table-column> -->
<el-table-column prop="ordItemStatus" label="生产状态" align="center" min-width="100">
<el-table-column prop="ordItemStatus" label="生产状态" align="center" width="80" fixed="right">
<template slot-scope="scope">
{{ getLabel('orderItemStatus', scope.row.ordItemStatus) }}
</template>
</el-table-column>
<el-table-column label="操作" fixed="right" align="center" width="150">
<el-table-column label="操作" fixed="right" align="center" width="80">
<template slot-scope="scope">
<el-button type="text" @click="handleClose(scope.row)"> </el-button>
</template>
@ -165,7 +166,7 @@ export default {
pageSize: 20,
},
ordItemStatusOptions: [],
ordItemStatusProps: { label: "fullName", value: "enCode" },
ordItemStatusProps: { label: "fullName", value: "id" },
ordStatusOptions: [],
hasSelected: false,
selectedRows: [],
@ -182,6 +183,15 @@ export default {
this.initSearchData();
this.initData();
},
watch: {
'$route.query.refresh': function(newVal) {
if (newVal) {
this.initData();
// refresh
this.$router.replace({ query: {} });
}
}
},
methods: {
initSearchData() {
let date = new Date();
@ -267,30 +277,30 @@ export default {
this.$message.warning("请选择需要转生产的销售订单信息,请确认!");
return;
}
const materialNames = [...new Set(selectedRows.map(row => row.materialName))];
const specs = [...new Set(selectedRows.map(row => row.spec))];
if (materialNames.length > 1) {
this.$message.error("必须选择产品名称和规格型号一致的产品,请确认!");
return;
}
if (specs.length > 1) {
this.$message.error("必须选择产品名称和规格型号一致的产品,请确认!");
return;
}
const saleOrdNos = [...new Set(selectedRows.map(row => row.saleOrdNo))];
const orderIds = selectedRows.map(row => row.itemId);
const params = {
orderIds: orderIds,
materialName: materialNames[0],
spec: specs[0],
saleOrdNo: saleOrdNos.join(', ')
};
this.$router.push({
path: "/example/tsoorder/generate",
query: { data: JSON.stringify(params) }