diff --git a/hw-modules/hw-mes/src/main/java/com/hw/mes/controller/MesProductOrderController.java b/hw-modules/hw-mes/src/main/java/com/hw/mes/controller/MesProductOrderController.java index e210d3b7..016717a1 100644 --- a/hw-modules/hw-mes/src/main/java/com/hw/mes/controller/MesProductOrderController.java +++ b/hw-modules/hw-mes/src/main/java/com/hw/mes/controller/MesProductOrderController.java @@ -234,4 +234,15 @@ public class MesProductOrderController extends BaseController { return R.fail(e.getMessage()); } } + + /** + * 批量新增生产工单 + */ + @RequiresPermissions("mes:productOrder:add") + @Log(title = "生产工单", businessType = BusinessType.INSERT) + @PostMapping("/batchAddProductOrder") + public AjaxResult batchAddProductOrder(@RequestBody List mesProductOrders) { + return toAjax(mesProductOrderService.batchAddProductOrder(mesProductOrders)); + } + } diff --git a/hw-modules/hw-mes/src/main/java/com/hw/mes/domain/MesSaleOrder.java b/hw-modules/hw-mes/src/main/java/com/hw/mes/domain/MesSaleOrder.java index 31cbfa45..25750530 100644 --- a/hw-modules/hw-mes/src/main/java/com/hw/mes/domain/MesSaleOrder.java +++ b/hw-modules/hw-mes/src/main/java/com/hw/mes/domain/MesSaleOrder.java @@ -213,7 +213,18 @@ public class MesSaleOrder extends BaseEntity { @Excel(name = "项目名称") private String projectName;//项目名称 + /** + * 下达任务标识(1=是;0=否) + */ + private String isTaskFlag; + public String getIsTaskFlag() { + return isTaskFlag; + } + + public void setIsTaskFlag(String isTaskFlag) { + this.isTaskFlag = isTaskFlag; + } public String getMaterialModel() { return materialModel; diff --git a/hw-modules/hw-mes/src/main/java/com/hw/mes/service/IMesProductOrderService.java b/hw-modules/hw-mes/src/main/java/com/hw/mes/service/IMesProductOrderService.java index 4564e9d0..d3df4ca6 100644 --- a/hw-modules/hw-mes/src/main/java/com/hw/mes/service/IMesProductOrderService.java +++ b/hw-modules/hw-mes/src/main/java/com/hw/mes/service/IMesProductOrderService.java @@ -143,4 +143,11 @@ public interface IMesProductOrderService *生产工单超时统计 */ public void productOrderOverTimeAlarm(); + + /** + * 批量新增生产工单 + * @param mesProductOrders + * @return + */ + int batchAddProductOrder(List mesProductOrders); } diff --git a/hw-modules/hw-mes/src/main/java/com/hw/mes/service/impl/MesProductOrderServiceImpl.java b/hw-modules/hw-mes/src/main/java/com/hw/mes/service/impl/MesProductOrderServiceImpl.java index 96dbb82e..dbacf356 100644 --- a/hw-modules/hw-mes/src/main/java/com/hw/mes/service/impl/MesProductOrderServiceImpl.java +++ b/hw-modules/hw-mes/src/main/java/com/hw/mes/service/impl/MesProductOrderServiceImpl.java @@ -28,6 +28,7 @@ import org.springframework.stereotype.Service; import com.hw.mes.mapper.MesProductOrderMapper; import com.hw.mes.domain.MesProductOrder; import com.hw.mes.service.IMesProductOrderService; +import org.springframework.transaction.annotation.Transactional; import javax.annotation.Resource; @@ -669,6 +670,22 @@ public class MesProductOrderServiceImpl implements IMesProductOrderService { } + /** + * 批量新增生产工单 + * @param mesProductOrders + * @return + */ + @Override + @Transactional(rollbackFor = Exception.class) + public int batchAddProductOrder(List mesProductOrders) { + for (MesProductOrder mesProductOrder : mesProductOrders) { + mesProductOrder.setOrderCode(this.getOrderCode()); + mesProductOrder.setCreateBy(SecurityUtils.getLoginUser().getUsername()); + this.insertMesProductOrder(mesProductOrder); + } + return 1; + } + private static SysPointRouter getSysPointRouter(Long productOrderId, String nickName, Date currentDate) { SysPointRouter sysPointRouter = new SysPointRouter(); diff --git a/hw-modules/hw-mes/src/main/resources/mapper/mes/MesSaleOrderMapper.xml b/hw-modules/hw-mes/src/main/resources/mapper/mes/MesSaleOrderMapper.xml index e797844c..57469140 100644 --- a/hw-modules/hw-mes/src/main/resources/mapper/mes/MesSaleOrderMapper.xml +++ b/hw-modules/hw-mes/src/main/resources/mapper/mes/MesSaleOrderMapper.xml @@ -41,6 +41,7 @@ + @@ -258,10 +259,14 @@ mso.complete_date, mso.sale_order_classfication, mso.create_time, - mpi.project_name + mpi.project_name, + IF(mpo.sale_order_id > 0, '1', '0') isTaskFlag from mes_sale_order mso left join mes_base_material_info mbmi on ((mso.material_id = mbmi.erp_id and (mso.sale_order_classfication='1' or mso.sale_order_classfication='3')) or (mso.material_id = mbmi.material_id and mso.sale_order_classfication='2')) left join mes_project_info mpi on mso.tond_base=mpi.erp_id + left join (select sale_order_id + from mes_product_order + group by sale_order_id) mpo on mpo.sale_order_id = mso.sale_order_id mso.is_flag = '1' and mso.saleorder_code like concat('%', #{saleorderCode}, diff --git a/hw-ui/src/api/mes/productOrder.js b/hw-ui/src/api/mes/productOrder.js index 078f4ca7..ab2a0d87 100644 --- a/hw-ui/src/api/mes/productOrder.js +++ b/hw-ui/src/api/mes/productOrder.js @@ -151,3 +151,12 @@ export function getStockTotalWithRawOutstocks(query) { params: query }) } + +// 批量新增生产工单 +export function batchAddProductOrder(data) { + return request({ + url: '/mes/productOrder/batchAddProductOrder', + method: 'post', + data: data + }) +} diff --git a/hw-ui/src/views/mes/productOrder/addBatchSaleOrder.vue b/hw-ui/src/views/mes/productOrder/addBatchSaleOrder.vue new file mode 100644 index 00000000..615a0dff --- /dev/null +++ b/hw-ui/src/views/mes/productOrder/addBatchSaleOrder.vue @@ -0,0 +1,306 @@ + + + + diff --git a/hw-ui/src/views/mes/productOrder/index.vue b/hw-ui/src/views/mes/productOrder/index.vue index 46ac3738..f9b13efa 100644 --- a/hw-ui/src/views/mes/productOrder/index.vue +++ b/hw-ui/src/views/mes/productOrder/index.vue @@ -126,6 +126,17 @@ + 批量销售新增 + + + @@ -136,7 +147,7 @@ - + + + + + + {{ dict.label }} + + + + + 选择销售订单 + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + @@ -632,8 +756,15 @@ import { delProductOrder, addProductOrder, updateProductOrder, - getMaterialUsages, getStockTotalWithRawOutstocks, - getOrderCode, productOrderLockInventory, productOrderPublish, productOrderPause,productOrderContinue,productOrderRecall + getMaterialUsages, + getStockTotalWithRawOutstocks, + getOrderCode, + productOrderLockInventory, + productOrderPublish, + productOrderPause, + productOrderContinue, + productOrderRecall, + batchAddProductOrder } from "@/api/mes/productOrder"; import addSaleOrder from '@//views/mes/productOrder/addSaleOrder.vue'; import {getMaterialVisionList} from "@//api/mes/materialBom"; @@ -642,6 +773,7 @@ import add_ProductOrder from '@//views/mes/productOrder/addProductOrder.vue'; import router from "@//router"; import {parseTime} from "@/utils/ruoyi"; import selectMaterial from "@/views/mes/materialinfo/selectMaterial.vue"; +import addBatchSaleOrder from '@//views/mes/productOrder/addBatchSaleOrder.vue'; export default { name: "ProductOrder", @@ -650,6 +782,7 @@ export default { 'add-SaleOrder': addSaleOrder, 'select-material': selectMaterial, 'add-product-order': add_ProductOrder, + 'add-batch-sale-order': addBatchSaleOrder, }, data() { return { @@ -899,7 +1032,17 @@ export default { PAUSE: '4', //暂停 RECALLED: '5',//已撤回 DELETED: '9',//已删除 - } + }, + // 批量销售新增相关 + batchSaleOpen: false, + batchSaleOrderOpen: false, // 新增: 控制批量选择弹窗 + batchSaleForm: { + batchSaleType: '' + }, + batchSaleOrders: [], + // 新增: 批量选择生产物料弹窗控制和当前行索引 + batchSaleProduceMaterialOpen: false, + currentBatchSaleRowIndex: null, }; }, activated() { @@ -1430,6 +1573,119 @@ export default { } return ''; }, + handleBatchSaleAdd() { + this.batchSaleForm.batchSaleType = ''; + this.batchSaleOrders = []; + this.batchSaleOpen = true; + // 新增: 重置生产物料弹窗状态 + this.batchSaleProduceMaterialOpen = false; + this.currentBatchSaleRowIndex = null; + }, + openBatchSaleOrderDialog() { + this.batchSaleOrderOpen = true; + + }, + // 新增: 批量选择弹窗确定 + handleBatchSaleOrderSelect() { + const rows = this.$refs.batchSaleOrderRef.selectedRows || []; + + this.batchSaleOrders = rows.map(row => ({ + saleOrderId: row.saleOrderId, + saleorderCode: row.saleorderCode, + saleorderLinenumber: row.saleorderLinenumber, + saleAmount: row.orderAmount, + planBeginTime: row.beginDate == null ? null : row.beginDate + " 00:00:00", + planEndTime: row.endDate == null ? null : row.endDate + " 00:00:00", + planDeliveryDate: row.planDeliveryDate == null ? null : row.planDeliveryDate + " 00:00:00", + saleOrderFlag: '1', + materialId: row.materialId, + materialCode: row.materialCode, + materialName: row.materialName, + planAmount: 1, + dispatchType: '2', + saleType: this.batchSaleForm.batchSaleType, + materialBomList: [] + })); + + rows.forEach((row, index) => { + getMaterialVisionList(row.materialId).then(response => { + if (response.data && response.data.length !== 0) { + this.$set(this.batchSaleOrders[index], 'materialBomList', response.data); + this.batchSaleOrders[index].materialBomId = response.data[0].materialBomId; + } else { + this.$modal.msgError(row.materialName + "物料未维护BOM信息!"); + this.$set(this.batchSaleOrders[index], 'materialBomList', []); + } + }).catch(error => { + console.error('获取BOM信息失败:', error); + this.$set(this.batchSaleOrders[index], 'materialBomList', []); + }); + }); + + console.log("batchSaleOrders",this.batchSaleOrders) + this.$refs.batchSaleOrderRef.clearSelection(); + this.batchSaleOrderOpen = false; + }, + submitBatchSaleForm() { + // 校验每行必填项 + const requiredFields = [ + { key: 'planAmount', label: '计划数量' }, + { key: 'planDeliveryDate', label: '计划交货日期' }, + // 新增: 生产物料必填(对内生产时) + ...(this.batchSaleForm.batchSaleType === this.MES_SALE_TYPE.MES_SALE_TYPE_INTERNAL ? [ + { key: 'produceMaterialName', label: '生产物料' }, + { key: 'materialBomId', label: '物料BOM' }, + ] : []), + ]; + for (let i = 0; i < this.batchSaleOrders.length; i++) { + const row = this.batchSaleOrders[i]; + for (const field of requiredFields) { + if (!row[field.key]) { + this.$message.error(`第${i + 1}行【${row.saleorderCode || ''}】的\"${field.label}\"不能为空!`); + return; + } + } + // 计划数量校验 + if (Number(row.planAmount) < 1 || Number(row.planAmount) > Number(row.orderAmount)) { + this.$message.error(`第${i + 1}行【${row.saleorderCode || ''}】的"计划数量"需为1~销售数量之间的整数!`); + return; + } + // 时间校验 + if (row.planEndTime && row.planBeginTime && row.planEndTime <= row.planBeginTime) { + this.$message.error(`第${i + 1}行【${row.saleorderCode || ''}】的"计划结束时间"需大于"计划开始时间"!`); + return; + } + if (row.planDeliveryDate && row.planEndTime && row.planDeliveryDate <= row.planEndTime) { + this.$message.error(`第${i + 1}行【${row.saleorderCode || ''}】的"计划交付时间"需大于"计划结束时间"!`); + return; + } + } + this.submitLoading = true; + batchAddProductOrder(this.batchSaleOrders).then(() => { + this.$message.success('批量新增成功!'); + this.batchSaleOpen = false; + this.getList(); + }).catch(() => { + this.$message.error('批量新增失败,请检查数据!'); + }).finally(() => { + this.submitLoading = false; + }); + }, + // 新增: 打开批量选择生产物料弹窗 + openBatchSaleProduceMaterialDialog(rowIndex) { + this.currentBatchSaleRowIndex = rowIndex; + this.batchSaleProduceMaterialOpen = true; + }, + // 新增: 批量选择生产物料弹窗确认 + submitBatchSaleProduceMaterialForm() { + const selectedRow = this.$refs.batchSaleProduceMaterialRef.selectedRow; + if (selectedRow) { + const idx = this.currentBatchSaleRowIndex; + this.$set(this.batchSaleOrders[idx], 'produceMaterialId', selectedRow.materialId); + this.$set(this.batchSaleOrders[idx], 'produceMaterialName', selectedRow.materialName); + } + this.batchSaleProduceMaterialOpen = false; + }, } };