From f85e557d1c7c613576e0ef517554668f2caf6f66 Mon Sep 17 00:00:00 2001 From: chenhao <852066789@qq.com> Date: Wed, 20 Aug 2025 14:46:24 +0800 Subject: [PATCH] =?UTF-8?q?feat(customer):=20=E5=AE=A2=E6=88=B7=E7=BC=96?= =?UTF-8?q?=E7=A0=81=E8=87=AA=E5=8A=A8=E7=94=9F=E6=88=90=E5=B9=B6=E4=BC=98?= =?UTF-8?q?=E5=8C=96=E7=9B=B8=E5=85=B3=E5=8A=9F=E8=83=BD?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit -客户编码改为自动生成,无需手动输入 - 添加生成客户编码的逻辑和接口 - 修改客户信息保存逻辑,支持自动生成编码 - 优化客户信息编辑界面,使编码字段只读 --- .../templates/inventory/execution/edit.html | 8 +- .../templates/inventory/outer/edit.html | 183 +++++++++++------- .../templates/inventory/outer/outer.html | 6 +- .../templates/system/customer/add.html | 4 +- .../templates/system/customer/edit.html | 2 +- .../controller/InventoryOuterController.java | 9 +- .../ruoyi/sip/domain/InventoryDelivery.java | 1 + .../flowable/listener/ProcessListener.java | 58 +++++- .../flowable/service/TodoCommonTemplate.java | 5 + .../ruoyi/sip/mapper/CustomerInfoMapper.java | 2 + .../ruoyi/sip/mapper/InventoryInfoMapper.java | 1 + .../service/IOmsInventoryInnerService.java | 4 +- .../service/impl/CustomerInfoServiceImpl.java | 61 +++++- .../impl/ExecutionTrackServiceImpl.java | 14 +- .../impl/InventoryDeliveryServiceImpl.java | 43 ++-- .../impl/InventoryInfoServiceImpl.java | 8 + .../impl/OmsInventoryInnerServiceImpl.java | 34 +++- .../impl/ProjectOrderInfoServiceImpl.java | 15 +- .../mapper/inventory/InventoryInfoMapper.xml | 8 + .../mapper/manage/CustomerInfoMapper.xml | 8 + 20 files changed, 358 insertions(+), 116 deletions(-) diff --git a/ruoyi-admin/src/main/resources/templates/inventory/execution/edit.html b/ruoyi-admin/src/main/resources/templates/inventory/execution/edit.html index 50be29d6..2906ef9f 100644 --- a/ruoyi-admin/src/main/resources/templates/inventory/execution/edit.html +++ b/ruoyi-admin/src/main/resources/templates/inventory/execution/edit.html @@ -519,7 +519,7 @@ formatter: function (value, row, index) { var actions = []; let disabled = Number(row.quantity) <= Number(row.generatedQuantity) + Number(row.confirmQuantity) - actions.push(`出库`); return actions.join(''); } @@ -555,7 +555,7 @@ function initWarehouseTable(data) { }, { field: 'availableCount', - title: '实时用库存' + title: '实时库存' }, { field: 'confirmQuantity', @@ -762,12 +762,12 @@ function initWarehouseTable(data) { var actions = []; if (row.outerStatus === '1' || row.outerStatus === '4') { actions.push(`撤销`); - actions.push(`确认出库`); + actions.push(`确认出库`); } else { // actions.push('查看详情'); - actions.push(`查看详情`); + actions.push(`查看详情`); } return actions.join(''); } diff --git a/ruoyi-admin/src/main/resources/templates/inventory/outer/edit.html b/ruoyi-admin/src/main/resources/templates/inventory/outer/edit.html index bdf9ee95..23fef6ae 100644 --- a/ruoyi-admin/src/main/resources/templates/inventory/outer/edit.html +++ b/ruoyi-admin/src/main/resources/templates/inventory/outer/edit.html @@ -110,6 +110,7 @@
+ @@ -172,6 +173,75 @@ var productPrefix = ctx + "inventory/info"; var deliveryPrefix = ctx + "inventory/delivery"; const showReturnFlag = [[${deliveryList}]] && [[${deliveryList.size()}]]>0; + + let productSnData = []; + let productSnOptions = { + id: 'bootstrap-table', + url: productPrefix + "/list", + modalName: "出库单", + + onCheck: (row, $ele) => { + updateTotal() + }, + onUncheck: (row, $ele) => { + if (productSnData.length > 0) { + $('#bootstrap-table').bootstrapTable('checkAll'); + $.modal.msgError("导入数据不允许取消勾选") + return + } + updateTotal() + }, + onCheckAll: (rowsAfter, rowsBefore) => { + updateTotal() + }, + onUncheckAll: (rowsAfter, rowsBefore) => { + if (productSnData.length > 0) { + $('#bootstrap-table').bootstrapTable('checkAll'); + $.modal.msgError("导入数据不允许取消勾选") + return + } + updateTotal() + }, + onLoadSuccess: (data) => { + $('#bootstrap-table').bootstrapTable('checkAll'); + }, + showSearch: false, + showRefresh: false, + showToggle: false, + showColumns: false, + rememberSelected: true, + formId: "query-product-sn", + columns: [{ + field: 'state', + checkbox: true + }, + { + field: 'id', + title: '', + visible: false + }, + { + field: 'productSn', + title: 'SN码' + }, + { + field: 'productCode', + title: '产品编码' + }, + { + field: 'model', + title: '产品型号' + }, + { + field: 'productDesc', + title: '描述' + }, + { + field: 'warehouseName', + title: '仓库' + }] + }; + $("#form-outer-edit").validate({ focusCleanup: true }); @@ -197,6 +267,7 @@ let data = new FormData() data.append('file', file) data.append('productCode', $('[name="productCode"]').val()) + data.append('quantity', Number($('#deliveryQuantity').val())) var xhr = new XMLHttpRequest(); // 创建XMLHttpRequest对象 xhr.open('POST', prefix + '/importData', true); // 设置请求类型和URL // 当请求完成时执行的回调函数 @@ -204,7 +275,17 @@ let data = JSON.parse(res.currentTarget.response) if (data.code === 0) { $.modal.msgSuccess('上传成功'); - $.table.search('query-product-sn', 'bootstrap-table') + productSnData = data.data; + $.table.refreshOptions($.extend(productSnOptions, { + url: '', + data: productSnData, + pagination: false + }), 'bootstrap-table') + setTimeout(() => { + $('#bootstrap-table').bootstrapTable('checkAll'); + }, 200); + $('#bootstrap-table').before(`
已选:${productSnData.length}(台)
`); + // $.table.search('query-product-sn', 'bootstrap-table') } else { top.layer.alert(data.msg || '导入失败', { icon: 2, @@ -272,61 +353,10 @@ } } - function initProductSnTable() { - var options = { - id: 'bootstrap-table', - url: productPrefix + "/list", - modalName: "出库单", - onCheck: (row, $ele) => { - updateTotal() - }, - onUncheck: (row, $ele) => { - updateTotal() - }, - onCheckAll: (rowsAfter, rowsBefore) => { - updateTotal() - }, - onUncheckAll: (rowsAfter, rowsBefore) => { - updateTotal() - }, - showSearch: false, - showRefresh: false, - showToggle: false, - showColumns: false, - rememberSelected: true, - formId: "query-product-sn", - columns: [{ - field: 'state', - checkbox: true - }, - { - field: 'id', - title: '', - visible: false - }, - { - field: 'productSn', - title: 'SN码' - }, - { - field: 'productCode', - title: '产品编码' - }, - { - field: 'model', - title: '产品型号' - }, - { - field: 'productDesc', - title: '描述' - }, - { - field: 'warehouseName', - title: '仓库' - }] - }; - $.table.init(options); + function initProductSnTable() { + + $.table.init(productSnOptions); $('#bootstrap-table').before('
已选:0(台)
'); } @@ -335,7 +365,7 @@ if ($tableCount.length > 0) { // 延迟100毫秒,等待表格渲染完成 setTimeout(function () { - $tableCount.text($.table.selectColumns("productSn").length); + $tableCount.text(productSnData.length > 0 ? productSnData.length : $.table.selectColumns("productSn").length); }, 100) } } @@ -398,7 +428,7 @@ formatter: function (value, row, index) { var actions = []; let disabled = Number(row.quantity) <= Number(row.deliveryGenerateQuantity) + Number(row.deliveryConfirmQuantity) - actions.push(`发货`); + actions.push(`发货`); return actions.join(''); } }] @@ -412,12 +442,18 @@ let width = 1000, height = 700 parent.$('.layui-layer-btn').css('display', 'none') parent.$('.layui-layer-setwin').css('display', 'none') + $('#deliveryQuantity').val(quantity) $('[name="warehouseId"]').val(warehouseId) $('[name="productCode"]').val(productCode) $('[name="inventoryStatus"]').val(0) $('#query-product-sn [name="outerCode"]').val('') - $.table.search('query-product-sn', 'bootstrap-table') - + productSnData = [] + $.table.refreshOptions($.extend(productSnOptions, { + url: productPrefix + "/list", + pagination: true, + pageSize: quantity + }), 'bootstrap-table') + $('#bootstrap-table').before('
已选:0(台)
'); $('#table-select-count').text(0); let index = layer.open({ id: 'generate_delivery', @@ -432,15 +468,25 @@ $.modal.msgError('物流单号必填') return; } - var arrays = $.table.selectColumns("productSn"); - if (arrays.length != quantity) { - $.modal.msgError(`产品选中数量应与发货数量一致,应发货数量为[${quantity}]`) - return + let arrays = [] + if (productSnData.length <= 0) { + arrays = $.table.selectColumns("productSn"); + if (arrays.length != quantity) { + $.modal.msgError(`产品选中数量应与发货数量一致,应发货数量为[${quantity}]`) + return + } + } else { + if (productSnData.length != quantity) { + $.modal.msgError(`产品选中数量应与发货数量一致,应发货数量为[${quantity}]`) + return + } } + //保存数据 let data = { productSnList: arrays, logisticsCode: $('#logisticsCode').val(), + productCode: productCode, quantity: quantity, warehouseId: warehouseId, logisticsCompany: $('#logisticsCompany').val(), @@ -448,6 +494,7 @@ deliveryTime: $('#deliveryTime').val(), deliveryTimeType: $('#deliveryTimeType').val(), outerCode: $('[name="outerCode"]').val(), + productSnDataList: productSnData, } var config = { url: deliveryPrefix + "/add", @@ -460,18 +507,22 @@ $.modal.disable(); }, success: function (result) { + if (result.code != 0) { + $.modal.closeLoading(); + $.modal.enable(); + $.modal.msgError(result.msg) + return + } if (typeof callback == "function") { callback(result); } refreshTable() $.modal.closeLoading(); $.modal.enable(); + layer.close(index); } }; $.ajax(config) - - layer.close(index); - }, end: function () { parent.$('.layui-layer-btn').css('display', '') diff --git a/ruoyi-admin/src/main/resources/templates/inventory/outer/outer.html b/ruoyi-admin/src/main/resources/templates/inventory/outer/outer.html index 02d15485..96d0a8e9 100644 --- a/ruoyi-admin/src/main/resources/templates/inventory/outer/outer.html +++ b/ruoyi-admin/src/main/resources/templates/inventory/outer/outer.html @@ -129,7 +129,7 @@ actions.push('编辑 '); } else { actions.push('退回 '); - actions.push('确认接收'); + actions.push('确认接收'); } return actions.join(''); } @@ -140,11 +140,11 @@ function received(id) { - $.modal.confirm("确认要确认接收吗?", function () { + // $.modal.confirm("确认要确认接收吗?", function () { $.operate.post(prefix + "/status", {"id": id, "outerStatus": '3'},()=>{ // $.table.refresh() }); - }) + // }) } function refundable(id,orderCode) { diff --git a/ruoyi-admin/src/main/resources/templates/system/customer/add.html b/ruoyi-admin/src/main/resources/templates/system/customer/add.html index 40efa9d7..363c198f 100644 --- a/ruoyi-admin/src/main/resources/templates/system/customer/add.html +++ b/ruoyi-admin/src/main/resources/templates/system/customer/add.html @@ -9,9 +9,9 @@
- +
- +
diff --git a/ruoyi-admin/src/main/resources/templates/system/customer/edit.html b/ruoyi-admin/src/main/resources/templates/system/customer/edit.html index e0d4d442..7a8c5fbc 100644 --- a/ruoyi-admin/src/main/resources/templates/system/customer/edit.html +++ b/ruoyi-admin/src/main/resources/templates/system/customer/edit.html @@ -12,7 +12,7 @@
- +
diff --git a/ruoyi-sip/src/main/java/com/ruoyi/sip/controller/InventoryOuterController.java b/ruoyi-sip/src/main/java/com/ruoyi/sip/controller/InventoryOuterController.java index 95cbcce6..9afe29a3 100644 --- a/ruoyi-sip/src/main/java/com/ruoyi/sip/controller/InventoryOuterController.java +++ b/ruoyi-sip/src/main/java/com/ruoyi/sip/controller/InventoryOuterController.java @@ -171,7 +171,7 @@ public class InventoryOuterController extends BaseController @PostMapping("/importData") @ResponseBody - public AjaxResult importTemplate(@RequestPart("file") MultipartFile file, @RequestParam(value = "productCode") String productCode) { + public AjaxResult importTemplate(@RequestPart("file") MultipartFile file, @RequestParam(value = "productCode") String productCode,@RequestParam(value = "quantity") Long quantity) { ExcelUtil util = new ExcelUtil(InventoryInfoExcelDto.class); try (InputStream inputStream = file.getInputStream()) { @@ -179,7 +179,10 @@ public class InventoryOuterController extends BaseController if (CollUtil.isEmpty(inventoryInfoExcelDtoList)){ return AjaxResult.error("导入数据为空"); } - innerService.importByOuter(inventoryInfoExcelDtoList, productCode); + if (inventoryInfoExcelDtoList.size()!=quantity.intValue()){ + return AjaxResult.error("导入数据应等于发货数量"); + } + return AjaxResult.success(innerService.getInventoryInfoList(inventoryInfoExcelDtoList, productCode)); } catch (IOException e) { throw new ServiceException("读取excel错误,请联系管理员"); @@ -187,8 +190,6 @@ public class InventoryOuterController extends BaseController return AjaxResult.error(e.getMessage()); } - - return AjaxResult.success(); } diff --git a/ruoyi-sip/src/main/java/com/ruoyi/sip/domain/InventoryDelivery.java b/ruoyi-sip/src/main/java/com/ruoyi/sip/domain/InventoryDelivery.java index 66e2fec4..2d70e405 100644 --- a/ruoyi-sip/src/main/java/com/ruoyi/sip/domain/InventoryDelivery.java +++ b/ruoyi-sip/src/main/java/com/ruoyi/sip/domain/InventoryDelivery.java @@ -73,6 +73,7 @@ public class InventoryDelivery extends BaseEntity private String deliveryStatus; private List productSnList; + private List productSnDataList; diff --git a/ruoyi-sip/src/main/java/com/ruoyi/sip/flowable/listener/ProcessListener.java b/ruoyi-sip/src/main/java/com/ruoyi/sip/flowable/listener/ProcessListener.java index 00d6c80f..bd9e497f 100644 --- a/ruoyi-sip/src/main/java/com/ruoyi/sip/flowable/listener/ProcessListener.java +++ b/ruoyi-sip/src/main/java/com/ruoyi/sip/flowable/listener/ProcessListener.java @@ -18,10 +18,15 @@ import com.ruoyi.sip.flowable.service.TodoService; import com.ruoyi.system.service.ISysUserService; import lombok.SneakyThrows; import org.apache.commons.lang3.ObjectUtils; +import org.flowable.common.engine.api.delegate.Expression; import org.flowable.common.engine.api.delegate.event.FlowableEngineEntityEvent; +import org.flowable.common.engine.impl.el.ExpressionManager; +import org.flowable.common.engine.impl.el.JuelExpression; +import org.flowable.engine.RepositoryService; import org.flowable.engine.RuntimeService; import org.flowable.engine.TaskService; import org.flowable.engine.delegate.event.AbstractFlowableEngineEventListener; +import org.flowable.engine.delegate.event.FlowableMultiInstanceActivityCompletedEvent; import org.flowable.engine.delegate.event.FlowableMultiInstanceActivityEvent; import org.flowable.engine.delegate.event.FlowableProcessStartedEvent; import org.flowable.engine.delegate.event.impl.FlowableEntityWithVariablesEventImpl; @@ -35,6 +40,7 @@ import org.slf4j.LoggerFactory; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.stereotype.Component; +import javax.annotation.Resource; import java.lang.reflect.Method; import java.util.*; import java.util.stream.Collectors; @@ -88,6 +94,53 @@ public class ProcessListener extends AbstractFlowableEngineEventListener { super.multiInstanceActivityStarted(event); } + @SneakyThrows + @Override + protected void multiInstanceActivityCompletedWithCondition(FlowableMultiInstanceActivityCompletedEvent event) { + if ("userTask".equals(event.getActivityType())) { + log.info("多实例任务完成 start--------"); + String processInstanceId = event.getProcessInstanceId(); + ProcessInstance processInstance = runtimeService.createProcessInstanceQuery().processInstanceId(processInstanceId).singleResult(); + + { + List todos = todoService.selectTodoListByProcessInstanceId(new Todo().setProcessInstanceId(processInstanceId)); + if (ObjectUtils.isNotEmpty(todos)) { + String ids = todos.stream().map(Todo::getTodoId).map(String::valueOf).collect(Collectors.joining(",")); + todoService.deleteTodoByIds(ids); + log.error("待办任务删除成功 {}", ids); + } + // 处理业务回调 - 添加默认回调逻辑 + Instance instance = processConfig.getInstance(); + String processDefinitionId = processInstance.getProcessDefinitionKey(); + + try { + Method method1 = BeanUtils.findMethod(instance.getClass(), + "get" + processDefinitionId.substring(0, 1).toUpperCase() + processDefinitionId.substring(1)); + if (method1 != null) { + // 默认多实例回调 + TodoCommonTemplate todoExecuteInstance = todoService.getTodoExecuteInstance( + new Todo().setProcessKey(processDefinitionId)); + if (todoExecuteInstance != null) { + Method multiInstanceCallbackMethod = BeanUtils.findMethod( + todoExecuteInstance.getClass(), "multiInstanceApproveCallback", String.class,ProcessInstance.class); + if (multiInstanceCallbackMethod != null) { + multiInstanceCallbackMethod.invoke(todoExecuteInstance, event.getActivityName(),processInstance); + log.error("默认多实例回调执行成功"); + } + } + } + + } catch (Exception e) { + log.error("多实例回调执行异常", e); + } + + } + + } + + super.multiInstanceActivityCompletedWithCondition(event); + } + @Override protected void taskCreated(FlowableEngineEntityEvent event) { @@ -127,11 +180,10 @@ public class ProcessListener extends AbstractFlowableEngineEventListener { if(!"noTodo".equals(taskEntity.getCategory())) { List todos = todoService.selectTodoListByProcessInstanceId(new Todo().setProcessInstanceId(taskEntity.getProcessInstanceId())); if (ObjectUtils.isNotEmpty(todos)) { - String ids = todos.stream().map(Todo::getTodoId).map(String::valueOf).collect(Collectors.joining(",")); Integer btn = null; - todoService.deleteTodoByIds(ids); - log.error("待办任务删除成功 {}", ids); Todo todo = todos.stream().filter(d -> d.getTaskId().equals(taskEntity.getId())).findFirst().get(); + todoService.deleteTodoByIds(String.valueOf(todo.getTodoId())); + log.error("待办任务删除成功 {}", todo.getId()); if (event instanceof FlowableEntityWithVariablesEventImpl) { Map variables = ((FlowableEntityWithVariablesEventImpl) event).getVariables(); log.error("variables {}", ObjectUtils.isNotEmpty(variables) ? JSON.toJSONString(variables) : "无数据"); diff --git a/ruoyi-sip/src/main/java/com/ruoyi/sip/flowable/service/TodoCommonTemplate.java b/ruoyi-sip/src/main/java/com/ruoyi/sip/flowable/service/TodoCommonTemplate.java index c6567b32..8cf738f3 100644 --- a/ruoyi-sip/src/main/java/com/ruoyi/sip/flowable/service/TodoCommonTemplate.java +++ b/ruoyi-sip/src/main/java/com/ruoyi/sip/flowable/service/TodoCommonTemplate.java @@ -2,6 +2,7 @@ package com.ruoyi.sip.flowable.service; import com.ruoyi.sip.flowable.domain.Todo; +import org.flowable.engine.runtime.ProcessInstance; /** * 流程相关接口模板定义 @@ -39,6 +40,10 @@ public interface TodoCommonTemplate { //默认实现 return true; } + default boolean multiInstanceApproveCallback(String activityName,ProcessInstance processInstance) { + //默认实现 + return true; + } } diff --git a/ruoyi-sip/src/main/java/com/ruoyi/sip/mapper/CustomerInfoMapper.java b/ruoyi-sip/src/main/java/com/ruoyi/sip/mapper/CustomerInfoMapper.java index 63764fc8..24b986c3 100644 --- a/ruoyi-sip/src/main/java/com/ruoyi/sip/mapper/CustomerInfoMapper.java +++ b/ruoyi-sip/src/main/java/com/ruoyi/sip/mapper/CustomerInfoMapper.java @@ -61,4 +61,6 @@ public interface CustomerInfoMapper */ public int deleteCustomerInfoByIds(String[] ids); public int selectCountByCode(CustomerInfo customerInfo); + + int selectMaxByPrefix(String province); } diff --git a/ruoyi-sip/src/main/java/com/ruoyi/sip/mapper/InventoryInfoMapper.java b/ruoyi-sip/src/main/java/com/ruoyi/sip/mapper/InventoryInfoMapper.java index f24f23f8..17b22ec6 100644 --- a/ruoyi-sip/src/main/java/com/ruoyi/sip/mapper/InventoryInfoMapper.java +++ b/ruoyi-sip/src/main/java/com/ruoyi/sip/mapper/InventoryInfoMapper.java @@ -70,4 +70,5 @@ public interface InventoryInfoMapper List countBySn(List productSnList); void deleteInventoryInfoByInnerIds(String[] idArray); + List listInventoryInfoByInnerIds(String[] idArray); } diff --git a/ruoyi-sip/src/main/java/com/ruoyi/sip/service/IOmsInventoryInnerService.java b/ruoyi-sip/src/main/java/com/ruoyi/sip/service/IOmsInventoryInnerService.java index 03a51082..23fc5bbf 100644 --- a/ruoyi-sip/src/main/java/com/ruoyi/sip/service/IOmsInventoryInnerService.java +++ b/ruoyi-sip/src/main/java/com/ruoyi/sip/service/IOmsInventoryInnerService.java @@ -2,6 +2,7 @@ package com.ruoyi.sip.service; import java.util.List; +import com.ruoyi.sip.domain.InventoryInfo; import com.ruoyi.sip.domain.OmsInventoryInner; import com.ruoyi.sip.dto.inventory.InventoryInfoExcelDto; @@ -62,5 +63,6 @@ public interface IOmsInventoryInnerService public int deleteOmsInventoryInnerById(Long id); - void importByOuter(List inventoryInfoExcelDtoList, String productCode); + void importByOuter(List inventoryInfoList,String productCode); + List getInventoryInfoList(List inventoryInfoExcelDtoList, String productCode); } diff --git a/ruoyi-sip/src/main/java/com/ruoyi/sip/service/impl/CustomerInfoServiceImpl.java b/ruoyi-sip/src/main/java/com/ruoyi/sip/service/impl/CustomerInfoServiceImpl.java index 57142baa..e5637c04 100644 --- a/ruoyi-sip/src/main/java/com/ruoyi/sip/service/impl/CustomerInfoServiceImpl.java +++ b/ruoyi-sip/src/main/java/com/ruoyi/sip/service/impl/CustomerInfoServiceImpl.java @@ -2,10 +2,14 @@ package com.ruoyi.sip.service.impl; import java.util.List; +import cn.hutool.core.collection.CollUtil; import com.ruoyi.common.exception.ServiceException; import com.ruoyi.common.utils.ShiroUtils; +import com.ruoyi.common.utils.StringUtils; +import com.ruoyi.sip.domain.Cnarea; import com.ruoyi.sip.domain.CustomerInfo; import com.ruoyi.sip.mapper.CustomerInfoMapper; +import com.ruoyi.sip.service.ICnareaService; import com.ruoyi.sip.service.ICustomerInfoService; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.stereotype.Service; @@ -23,7 +27,8 @@ public class CustomerInfoServiceImpl implements ICustomerInfoService { @Autowired private CustomerInfoMapper customerInfoMapper; - + @Autowired + private ICnareaService cnareaService; /** * 查询客户信息 * @@ -58,6 +63,7 @@ public class CustomerInfoServiceImpl implements ICustomerInfoService public int insertCustomerInfo(CustomerInfo customerInfo) { customerInfo.setCreateBy(ShiroUtils.getUserId().toString()); + customerInfo.setCustomerCode(generateCode(customerInfo.getProvince())); int i = customerInfoMapper.selectCountByCode(customerInfo); if (i > 0){ throw new ServiceException("客户编码已存在"); @@ -65,6 +71,28 @@ public class CustomerInfoServiceImpl implements ICustomerInfoService return customerInfoMapper.insertCustomerInfo(customerInfo); } + private String generateCode(String province) { + if (StringUtils.isEmpty(province)) { + throw new ServiceException("客户所属省为空,无法生成客户编码"); + } + Cnarea cnarea = new Cnarea(); + cnarea.setName(province); + cnarea.setLevel("1"); + List cnareas = cnareaService.queryAll(cnarea); + if (CollUtil.isEmpty(cnareas)) { + throw new ServiceException("省市未配置,生成订单编号出错,请联系管理员"); + } + String shortCode = cnareas.get(0).getShortCode(); + StringBuilder result = new StringBuilder(); + result.append("CU-"); + result.append(shortCode); + result.append("-"); + int count = customerInfoMapper.selectMaxByPrefix(result.toString()); + // 生成顺序编码,不足四位补零 + String sequence = String.format("%04d", count + 1); + result.append(sequence); + return result.toString(); + } /** * 修改客户信息 * @@ -75,10 +103,35 @@ public class CustomerInfoServiceImpl implements ICustomerInfoService public int updateCustomerInfo(CustomerInfo customerInfo) { customerInfo.setUpdateBy(ShiroUtils.getUserId().toString()); - int i = customerInfoMapper.selectCountByCode(customerInfo); - if (i > 0){ - throw new ServiceException("客户编码已存在"); + + // 检查客户编码是否已存在(排除当前记录) +// CustomerInfo queryParam = new CustomerInfo(); +// queryParam.setCustomerCode(customerInfo.getCustomerCode()); +// List customerInfoList = customerInfoMapper.selectCustomerInfoList(queryParam); +// +// if (CollUtil.isNotEmpty(customerInfoList)) { +// CustomerInfo existInfo = customerInfoList.get(0); +// // 如果编码已存在且不是当前正在更新的记录,则抛出异常 +// if (!existInfo.getId().equals(customerInfo.getId())) { +// throw new ServiceException("客户编码已存在"); +// } +// } + + // 如果省份发生变化,需要重新生成客户编码 + CustomerInfo oldCustomerInfo = customerInfoMapper.selectCustomerInfoById(customerInfo.getId()); + if (oldCustomerInfo != null && !oldCustomerInfo.getProvince().equals(customerInfo.getProvince())) { + String newCustomerCode = generateCode(customerInfo.getProvince()); + customerInfo.setCustomerCode(newCustomerCode); + + // 检查新生成的编码是否已存在 + CustomerInfo codeCheckParam = new CustomerInfo(); + codeCheckParam.setCustomerCode(newCustomerCode); + int count = customerInfoMapper.selectCountByCode(codeCheckParam); + if (count > 0) { + throw new ServiceException("客户编码已存在"); + } } + return customerInfoMapper.updateCustomerInfo(customerInfo); } diff --git a/ruoyi-sip/src/main/java/com/ruoyi/sip/service/impl/ExecutionTrackServiceImpl.java b/ruoyi-sip/src/main/java/com/ruoyi/sip/service/impl/ExecutionTrackServiceImpl.java index cab94a73..2cec2278 100644 --- a/ruoyi-sip/src/main/java/com/ruoyi/sip/service/impl/ExecutionTrackServiceImpl.java +++ b/ruoyi-sip/src/main/java/com/ruoyi/sip/service/impl/ExecutionTrackServiceImpl.java @@ -2,6 +2,7 @@ package com.ruoyi.sip.service.impl; import cn.hutool.core.collection.CollUtil; +import com.ruoyi.common.exception.ServiceException; import com.ruoyi.sip.domain.*; import com.ruoyi.sip.dto.inventory.ProductDetail; import com.ruoyi.sip.dto.inventory.ProductWarehouseInfo; @@ -182,9 +183,15 @@ public class ExecutionTrackServiceImpl implements IExecutionTrackService { } // 如果仍有未满足的需求,尝试使用默认仓库 if (remainingQuantity > 0) { + List productInfoList = productInfoService.selectProductInfoByCodeList(Collections.singletonList(productCode)); + if (CollUtil.isEmpty(productInfoList)) { + throw new ServiceException("产品编码对应产品未找到"); + } + ProductInfo productInfo = productInfoList.get(0); List currentVendors = inventoryAuthService.currentVendor(); - if (CollUtil.isNotEmpty(currentVendors)) { - VendorInfo defaultVendor = currentVendors.get(0); + boolean vendorAuthFlag = currentVendors.stream().anyMatch(item -> item.getVendorCode().equals(productInfo.getVendorCode())); + if (CollUtil.isNotEmpty(currentVendors) && vendorAuthFlag) { + VendorInfo defaultVendor = currentVendors.stream().filter(item -> item.getVendorCode().equals(productInfo.getVendorCode())).findFirst().orElseThrow(() -> new ServiceException("制造商未授权")); // 检查默认仓库是否已经在列表中 boolean defaultVendorInList = productWarehouseInfoList.stream() @@ -196,8 +203,7 @@ public class ExecutionTrackServiceImpl implements IExecutionTrackService { defaultWarehouseInfo.setWarehouseId(defaultVendor.getWarehouseId()); defaultWarehouseInfo.setWarehouseName(defaultVendor.getWarehouseName()); // 这里假设默认仓库有足够库存,实际应用中可能需要查询具体库存 - List productInfos = productInfoService.selectProductInfoByCodeList(Collections.singletonList(productCode)); - defaultWarehouseInfo.setAvailableCount(productInfos.get(0).getAvailableCount() == null ? 0L : productInfos.get(0).getAvailableCount()); + defaultWarehouseInfo.setAvailableCount(productInfo.getAvailableCount() == null ? 0L : productInfo.getAvailableCount()); defaultWarehouseInfo.setConfirmQuantity((long) remainingQuantity); defaultWarehouseInfo.setDefaultWarehouse(true); productWarehouseInfoList.add(defaultWarehouseInfo); diff --git a/ruoyi-sip/src/main/java/com/ruoyi/sip/service/impl/InventoryDeliveryServiceImpl.java b/ruoyi-sip/src/main/java/com/ruoyi/sip/service/impl/InventoryDeliveryServiceImpl.java index d765ab32..a6835e6e 100644 --- a/ruoyi-sip/src/main/java/com/ruoyi/sip/service/impl/InventoryDeliveryServiceImpl.java +++ b/ruoyi-sip/src/main/java/com/ruoyi/sip/service/impl/InventoryDeliveryServiceImpl.java @@ -35,6 +35,8 @@ public class InventoryDeliveryServiceImpl implements IInventoryDeliveryService { private InventoryDeliveryMapper inventoryDeliveryMapper; @Autowired private IInventoryInfoService inventoryInfoService; + @Autowired + private IOmsInventoryInnerService omsInventoryInnerService; @Resource private InventoryOuterMapper inventoryOuterMapper; @Autowired @@ -74,27 +76,42 @@ public class InventoryDeliveryServiceImpl implements IInventoryDeliveryService { */ @Override public int insertInventoryDelivery(InventoryDelivery inventoryDelivery) { - inventoryDelivery.setCreateTime(DateUtils.getNowDate()); + + Date nowDate = DateUtils.getNowDate(); + inventoryDelivery.setCreateTime(nowDate); String currentUserId = ShiroUtils.getUserId().toString(); inventoryDelivery.setCreateBy(currentUserId); - inventoryDelivery.setCreateTime(DateUtils.getNowDate()); + inventoryDelivery.setCreateTime(nowDate); inventoryDelivery.setUpdateBy(currentUserId); - inventoryDelivery.setUpdateTime(DateUtils.getNowDate()); + inventoryDelivery.setUpdateTime(nowDate); inventoryDelivery.setDeliveryStatus(InventoryDelivery.DeliveryStatusEnum.WAIT_DELIVERY.getCode()); //处理库存 List productSnList = inventoryDelivery.getProductSnList(); - if (CollUtil.isEmpty(productSnList)) { + List productSnDataList = inventoryDelivery.getProductSnDataList(); + if (CollUtil.isEmpty(productSnList) && CollUtil.isEmpty(productSnDataList)) { throw new ServiceException("发货清单为空,保存失败"); } - List inventoryInfoList = productSnList.stream().map(item -> { - InventoryInfo info = new InventoryInfo(); - info.setProductSn(item); - info.setOuterCode(inventoryDelivery.getOuterCode()); - info.setInventoryStatus(InventoryInfo.InventoryStatusEnum.OUTER.getCode()); - info.setUpdateBy(currentUserId); - return info; - }).collect(Collectors.toList()); - inventoryInfoService.saveBatch(inventoryInfoList); + + if (CollUtil.isEmpty(productSnDataList)) { + List inventoryInfoList = productSnList.stream().map(item -> { + InventoryInfo info = new InventoryInfo(); + info.setProductSn(item); + info.setOuterCode(inventoryDelivery.getOuterCode()); + info.setInventoryStatus(InventoryInfo.InventoryStatusEnum.OUTER.getCode()); + info.setUpdateBy(currentUserId); + info.setUpdateTime(nowDate); + return info; + }).collect(Collectors.toList()); + inventoryInfoService.saveBatch(inventoryInfoList); + }else{ + for (InventoryInfo inventoryInfo : productSnDataList) { + inventoryInfo.setInventoryStatus(InventoryInfo.InventoryStatusEnum.OUTER.getCode()); + inventoryInfo.setOuterCode(inventoryDelivery.getOuterCode()); + inventoryInfo.setUpdateBy(currentUserId); + inventoryInfo.setUpdateTime(nowDate); + } + omsInventoryInnerService.importByOuter(productSnDataList,inventoryDelivery.getProductCode()); + } return inventoryDeliveryMapper.insertInventoryDelivery(inventoryDelivery); } diff --git a/ruoyi-sip/src/main/java/com/ruoyi/sip/service/impl/InventoryInfoServiceImpl.java b/ruoyi-sip/src/main/java/com/ruoyi/sip/service/impl/InventoryInfoServiceImpl.java index b24922e3..4db06cb9 100644 --- a/ruoyi-sip/src/main/java/com/ruoyi/sip/service/impl/InventoryInfoServiceImpl.java +++ b/ruoyi-sip/src/main/java/com/ruoyi/sip/service/impl/InventoryInfoServiceImpl.java @@ -20,6 +20,7 @@ import com.ruoyi.sip.vo.DeliveryInfoVo; import liquibase.pro.packaged.O; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.stereotype.Service; +import org.springframework.transaction.annotation.Transactional; import java.util.Collections; import java.util.List; @@ -34,6 +35,7 @@ import java.util.stream.Collectors; * @date 2025-08-07 */ @Service +@Transactional(rollbackFor = Exception.class) public class InventoryInfoServiceImpl implements IInventoryInfoService { @Autowired private InventoryInfoMapper inventoryInfoMapper; @@ -186,6 +188,12 @@ public class InventoryInfoServiceImpl implements IInventoryInfoService { @Override public void deleteInventoryInfoByInnerIds(String[] idArray) { + List inventoryInfos = inventoryInfoMapper.listInventoryInfoByInnerIds(idArray); + Map> listMap = inventoryInfos.stream().collect(Collectors.groupingBy(InventoryInfo::getProductCode)); + for (Map.Entry> entry : listMap.entrySet()) { + //此处删除 应该只有一个productCode + productInfoService.updateAvailableCount((long) -entry.getValue().size(),entry.getKey()); + } inventoryInfoMapper.deleteInventoryInfoByInnerIds(idArray); } diff --git a/ruoyi-sip/src/main/java/com/ruoyi/sip/service/impl/OmsInventoryInnerServiceImpl.java b/ruoyi-sip/src/main/java/com/ruoyi/sip/service/impl/OmsInventoryInnerServiceImpl.java index 356aa2a7..3131f45a 100644 --- a/ruoyi-sip/src/main/java/com/ruoyi/sip/service/impl/OmsInventoryInnerServiceImpl.java +++ b/ruoyi-sip/src/main/java/com/ruoyi/sip/service/impl/OmsInventoryInnerServiceImpl.java @@ -175,7 +175,19 @@ public class OmsInventoryInnerServiceImpl implements IOmsInventoryInnerService { } @Override - public void importByOuter(List inventoryInfoExcelDtoList, String productCode) { + public void importByOuter(List inventoryInfoList,String productCode) { + List productInfos = productInfoService.selectProductInfoByCodeList(Collections.singletonList(productCode)); + OmsInventoryInner omsInventoryInner = new OmsInventoryInner(); + omsInventoryInner.setVendorCode(productInfos.get(0).getVendorCode()); + omsInventoryInner.setProductCode(productCode); + omsInventoryInner.setWarehouseId(inventoryInfoList.get(0).getWarehouseId()); + omsInventoryInner.setInventoryInfoList(inventoryInfoList); + this.insertOmsInventoryInner(omsInventoryInner); + + } + + @Override + public List getInventoryInfoList(List inventoryInfoExcelDtoList, String productCode) { long count = inventoryInfoExcelDtoList.stream().filter(item -> !item.getProductCode().equals(productCode)).count(); if (count > 0){ throw new ServiceException("导入清单的产品与出库单不符"); @@ -184,6 +196,10 @@ public class OmsInventoryInnerServiceImpl implements IOmsInventoryInnerService { if (warehouseNameList.size() > 1){ throw new ServiceException("导入清单只能有一个仓库"); } + List productInfos = productInfoService.selectProductInfoByCodeList(Collections.singletonList(productCode)); + if (CollUtil.isEmpty(productInfos)){ + throw new ServiceException("产品编码对应产品未找到"); + } List warehouseInfoList = warehouseInfoService.listByNameList(warehouseNameList); Map warehouseInfoMap = warehouseInfoList.stream().collect(Collectors.toMap(OmsWarehouseInfo::getWarehouseName, Function.identity(), (v1, v2) -> v1)); List inventoryInfoList = inventoryInfoExcelDtoList.stream().map(item -> { @@ -191,23 +207,23 @@ public class OmsInventoryInnerServiceImpl implements IOmsInventoryInnerService { info.setInventoryStatus(InventoryInfo.InventoryStatusEnum.INNER.getCode()); info.setProductSn(item.getProductSn()); info.setProductCode(productCode); + info.setModel(productInfos.get(0).getModel()); + info.setProductDesc(productInfos.get(0).getDescription()); info.setInnerPrice(item.getInnerPrice()); OmsWarehouseInfo omsWarehouseInfo = warehouseInfoMap.get(item.getWarehouseName()); if (omsWarehouseInfo == null){ throw new ServiceException("仓库未找到,导入失败"); } info.setWarehouseId(omsWarehouseInfo.getId()); + info.setWarehouseName(omsWarehouseInfo.getWarehouseName()); return info; }).collect(Collectors.toList()); - List productInfos = productInfoService.selectProductInfoByCodeList(Collections.singletonList(productCode)); - OmsInventoryInner omsInventoryInner = new OmsInventoryInner(); - omsInventoryInner.setVendorCode(productInfos.get(0).getVendorCode()); - omsInventoryInner.setProductCode(productCode); - omsInventoryInner.setWarehouseId(warehouseInfoList.get(0).getId()); - omsInventoryInner.setInventoryInfoList(inventoryInfoList); - this.insertOmsInventoryInner(omsInventoryInner); - + List repeatSnList = inventoryInfoService.checkUnq(inventoryInfoList.stream().map(InventoryInfo::getProductSn).collect(Collectors.toList())); + if (CollUtil.isNotEmpty(repeatSnList)) { + throw new ServiceException(StrUtil.format("SN码[{}]已存在,导入失败", repeatSnList)); + } + return inventoryInfoList; } diff --git a/ruoyi-sip/src/main/java/com/ruoyi/sip/service/impl/ProjectOrderInfoServiceImpl.java b/ruoyi-sip/src/main/java/com/ruoyi/sip/service/impl/ProjectOrderInfoServiceImpl.java index b38b08e2..b2786a53 100644 --- a/ruoyi-sip/src/main/java/com/ruoyi/sip/service/impl/ProjectOrderInfoServiceImpl.java +++ b/ruoyi-sip/src/main/java/com/ruoyi/sip/service/impl/ProjectOrderInfoServiceImpl.java @@ -1033,14 +1033,25 @@ public class ProjectOrderInfoServiceImpl implements IProjectOrderInfoService, To // 审批通过处理 if ("产品经理".equals(taskName)) { handleProductManagerApproval(businessKey); - } else if ("公司领导".equals(taskName)) { - handleCompanyLeaderApproval(businessKey); } } return TodoCommonTemplate.super.todoApproveCallback(todo); } + @Override + public boolean multiInstanceApproveCallback(String activityName,ProcessInstance processInstance) { + String flowBusinessKey = processInstance.getBusinessKey(); + String[] split = flowBusinessKey.split("#"); + String businessKey = split.length > 1 ? split[1] : split[0]; + Map processVariables = processInstance.getProcessVariables(); + Integer approveBtn = (Integer) processVariables.get("approveBtn"); + if ("公司领导".equals(activityName) && approveBtn == 1) { + handleCompanyLeaderApproval(businessKey); + } + + return TodoCommonTemplate.super.multiInstanceApproveCallback(activityName,processInstance); + } /** * 处理订单驳回 diff --git a/ruoyi-sip/src/main/resources/mapper/inventory/InventoryInfoMapper.xml b/ruoyi-sip/src/main/resources/mapper/inventory/InventoryInfoMapper.xml index 5251babe..f50c074a 100644 --- a/ruoyi-sip/src/main/resources/mapper/inventory/InventoryInfoMapper.xml +++ b/ruoyi-sip/src/main/resources/mapper/inventory/InventoryInfoMapper.xml @@ -73,6 +73,14 @@ PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" #{item} + diff --git a/ruoyi-sip/src/main/resources/mapper/manage/CustomerInfoMapper.xml b/ruoyi-sip/src/main/resources/mapper/manage/CustomerInfoMapper.xml index cc51c103..818cf2e1 100644 --- a/ruoyi-sip/src/main/resources/mapper/manage/CustomerInfoMapper.xml +++ b/ruoyi-sip/src/main/resources/mapper/manage/CustomerInfoMapper.xml @@ -67,6 +67,14 @@ PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" select count(1) from customer_info where customer_code = #{customerCode} and status=0 and id != #{id} + insert into customer_info