Commit 64146d205b0ede74e0d0326b9e5792ec9f48595d
1 parent
11cc1364
批量入库出库
Showing
9 changed files
with
485 additions
and
2 deletions
urbanops-module-garden/src/main/java/com/zteits/urbanops/module/garden/controller/admin/costfee/vo/MaterialInventoryInImport.java
0 → 100644
| 1 | +package com.zteits.urbanops.module.garden.controller.admin.costfee.vo; | ||
| 2 | + | ||
| 3 | +import cn.idev.excel.annotation.ExcelProperty; | ||
| 4 | +import com.fasterxml.jackson.annotation.JsonFormat; | ||
| 5 | +import jakarta.validation.constraints.NotEmpty; | ||
| 6 | +import jakarta.validation.constraints.NotNull; | ||
| 7 | +import jakarta.validation.constraints.Positive; | ||
| 8 | +import lombok.AllArgsConstructor; | ||
| 9 | +import lombok.Builder; | ||
| 10 | +import lombok.Data; | ||
| 11 | +import lombok.NoArgsConstructor; | ||
| 12 | + | ||
| 13 | +import java.math.BigDecimal; | ||
| 14 | +import java.time.LocalDate; | ||
| 15 | + | ||
| 16 | +/** | ||
| 17 | + * @Classname MaterialInventoryInImport | ||
| 18 | + * @Description 物料批量入库 | ||
| 19 | + * @Date 2026/1/15 22:22 | ||
| 20 | + * @Created by wangqian | ||
| 21 | + */ | ||
| 22 | +@Data | ||
| 23 | +@Builder | ||
| 24 | +@AllArgsConstructor | ||
| 25 | +@NoArgsConstructor | ||
| 26 | +public class MaterialInventoryInImport { | ||
| 27 | + | ||
| 28 | + | ||
| 29 | + @ExcelProperty(index = 1) | ||
| 30 | + @NotEmpty(message = "物料名称不能为空") | ||
| 31 | + private String materialName; | ||
| 32 | + | ||
| 33 | + @NotEmpty(message = "耗材类型不能为空") | ||
| 34 | + @ExcelProperty(index = 2) | ||
| 35 | + private String materialTypeName; | ||
| 36 | + | ||
| 37 | + @NotEmpty(message = "类别名称不能为空") | ||
| 38 | + @ExcelProperty(index = 3) | ||
| 39 | + private String typeName; | ||
| 40 | + | ||
| 41 | + | ||
| 42 | + @NotEmpty(message = "类别明细不能为空") | ||
| 43 | + @ExcelProperty(index = 4) | ||
| 44 | + private String typeDetailName; | ||
| 45 | + | ||
| 46 | + @NotEmpty(message = "物料规格不能为空") | ||
| 47 | + @ExcelProperty(index = 5) | ||
| 48 | + private String specifications; | ||
| 49 | + | ||
| 50 | + @NotEmpty(message = "物料单位不能为空") | ||
| 51 | + @ExcelProperty(index = 6) | ||
| 52 | + private String unitName; | ||
| 53 | + | ||
| 54 | + @NotNull(message = "单价不能为空") | ||
| 55 | + @ExcelProperty(index = 7) | ||
| 56 | + private BigDecimal materialPrice; | ||
| 57 | + | ||
| 58 | + @NotNull(message = "入库数量不能为空") | ||
| 59 | + @ExcelProperty(index = 8) | ||
| 60 | + @Positive(message = "数量必须为正整数") | ||
| 61 | + private Long inInventoryNum; | ||
| 62 | + | ||
| 63 | + @NotNull(message = "采购日期不能为空") | ||
| 64 | + @ExcelProperty(index = 9) | ||
| 65 | + @JsonFormat(pattern = "yyyy-MM-dd") | ||
| 66 | + private LocalDate buyDate; | ||
| 67 | + | ||
| 68 | + @NotEmpty(message = "供应商名称不能为空") | ||
| 69 | + @ExcelProperty(index = 10) | ||
| 70 | + private String supplierName; | ||
| 71 | + | ||
| 72 | + @NotEmpty(message = "联系人不能为空") | ||
| 73 | + @ExcelProperty(index = 11) | ||
| 74 | + private String contactsName; | ||
| 75 | + | ||
| 76 | + @NotEmpty(message = "联系电话不能为空") | ||
| 77 | + @ExcelProperty(index = 12) | ||
| 78 | + private String contactsPhone; | ||
| 79 | + | ||
| 80 | + @NotEmpty(message = "归属公司不能为空") | ||
| 81 | + @ExcelProperty(index = 13) | ||
| 82 | + private String belongCompanyName; | ||
| 83 | +} |
urbanops-module-garden/src/main/java/com/zteits/urbanops/module/garden/controller/admin/costfee/vo/MaterialInventoryOutImport.java
0 → 100644
| 1 | +package com.zteits.urbanops.module.garden.controller.admin.costfee.vo; | ||
| 2 | + | ||
| 3 | +import cn.idev.excel.annotation.ExcelProperty; | ||
| 4 | +import com.fasterxml.jackson.annotation.JsonFormat; | ||
| 5 | +import io.swagger.v3.oas.annotations.media.Schema; | ||
| 6 | +import jakarta.validation.constraints.NotEmpty; | ||
| 7 | +import jakarta.validation.constraints.NotNull; | ||
| 8 | +import jakarta.validation.constraints.Positive; | ||
| 9 | +import lombok.AllArgsConstructor; | ||
| 10 | +import lombok.Builder; | ||
| 11 | +import lombok.Data; | ||
| 12 | +import lombok.NoArgsConstructor; | ||
| 13 | + | ||
| 14 | +import java.math.BigDecimal; | ||
| 15 | +import java.time.LocalDate; | ||
| 16 | +import java.time.LocalDateTime; | ||
| 17 | + | ||
| 18 | +/** | ||
| 19 | + * @Classname MaterialInventoryOutImport | ||
| 20 | + * @Description 物料批量出库 | ||
| 21 | + * @Date 2026/1/15 22:22 | ||
| 22 | + * @Created by wangqian | ||
| 23 | + */ | ||
| 24 | +@Data | ||
| 25 | +@Builder | ||
| 26 | +@AllArgsConstructor | ||
| 27 | +@NoArgsConstructor | ||
| 28 | +public class MaterialInventoryOutImport { | ||
| 29 | + | ||
| 30 | + | ||
| 31 | + | ||
| 32 | + @ExcelProperty(index = 1) | ||
| 33 | + @NotEmpty(message = "物料名称不能为空") | ||
| 34 | + private String materialName; | ||
| 35 | + | ||
| 36 | + @NotEmpty(message = "耗材类型不能为空") | ||
| 37 | + @ExcelProperty(index = 2) | ||
| 38 | + private String materialTypeName; | ||
| 39 | + | ||
| 40 | + @NotEmpty(message = "类别名称不能为空") | ||
| 41 | + @ExcelProperty(index = 3) | ||
| 42 | + private String typeName; | ||
| 43 | + | ||
| 44 | + @NotEmpty(message = "类别明细不能为空") | ||
| 45 | + @ExcelProperty(index = 4) | ||
| 46 | + private String typeDetailName; | ||
| 47 | + | ||
| 48 | + @NotEmpty(message = "物料规格不能为空") | ||
| 49 | + @ExcelProperty(index = 5) | ||
| 50 | + private String specifications; | ||
| 51 | + | ||
| 52 | + @NotEmpty(message = "物料单位不能为空") | ||
| 53 | + @ExcelProperty(index = 6) | ||
| 54 | + private String unitName; | ||
| 55 | + | ||
| 56 | + @ExcelProperty(index = 7) | ||
| 57 | + @NotNull(message = "出库数量不能为空") | ||
| 58 | + @Positive(message = "数量必须为正整数") | ||
| 59 | + private Long outInventoryNum; | ||
| 60 | + | ||
| 61 | + @NotNull(message = "出库日期不能为空") | ||
| 62 | + @ExcelProperty(index = 8) | ||
| 63 | + @JsonFormat(pattern = "yyyy-MM-dd") | ||
| 64 | + private LocalDate outDate; | ||
| 65 | + | ||
| 66 | + @NotEmpty(message = "归属公司不能为空") | ||
| 67 | + @ExcelProperty(index = 9) | ||
| 68 | + private String belongCompanyName; | ||
| 69 | +} |
urbanops-module-garden/src/main/java/com/zteits/urbanops/module/garden/enums/TemplateEnum.java
| @@ -60,6 +60,20 @@ public enum TemplateEnum { | @@ -60,6 +60,20 @@ public enum TemplateEnum { | ||
| 60 | 2, | 60 | 2, |
| 61 | RentalMechanicalCostImport.class, | 61 | RentalMechanicalCostImport.class, |
| 62 | true // 新增默认值 | 62 | true // 新增默认值 |
| 63 | + ), | ||
| 64 | + MATERIAL_INVENTORY_IN( | ||
| 65 | + "materialInventory_in", | ||
| 66 | + "物料入库模板.xlsx", | ||
| 67 | + 1, | ||
| 68 | + MaterialInventoryInImport.class, | ||
| 69 | + true // 新增默认值 | ||
| 70 | + ), | ||
| 71 | + MATERIAL_INVENTORY_OUT( | ||
| 72 | + "materialInventory_out", | ||
| 73 | + "物料出库模板.xlsx", | ||
| 74 | + 1, | ||
| 75 | + MaterialInventoryOutImport.class, | ||
| 76 | + true // 新增默认值 | ||
| 63 | ); | 77 | ); |
| 64 | 78 | ||
| 65 | // 模板编码(前端传递的标识) | 79 | // 模板编码(前端传递的标识) |
urbanops-module-garden/src/main/java/com/zteits/urbanops/module/garden/service/costfee/CostFeeServiceImpl.java
| @@ -5,12 +5,16 @@ import com.fasterxml.jackson.databind.ObjectMapper; | @@ -5,12 +5,16 @@ import com.fasterxml.jackson.databind.ObjectMapper; | ||
| 5 | import com.zteits.urbanops.module.garden.controller.admin.costfee.CostFeeController; | 5 | import com.zteits.urbanops.module.garden.controller.admin.costfee.CostFeeController; |
| 6 | import com.zteits.urbanops.module.garden.controller.admin.costfee.vo.*; | 6 | import com.zteits.urbanops.module.garden.controller.admin.costfee.vo.*; |
| 7 | import com.zteits.urbanops.module.garden.dal.dataobject.departmentcost.DepartmentCostDO; | 7 | import com.zteits.urbanops.module.garden.dal.dataobject.departmentcost.DepartmentCostDO; |
| 8 | +import com.zteits.urbanops.module.garden.dal.dataobject.material.MaterialDO; | ||
| 9 | +import com.zteits.urbanops.module.garden.dal.dataobject.materialinventoryin.MaterialInventoryInDO; | ||
| 10 | +import com.zteits.urbanops.module.garden.dal.dataobject.materialinventoryout.MaterialInventoryOutDO; | ||
| 8 | import com.zteits.urbanops.module.garden.dal.dataobject.mechanicalcost.MechanicalCostDO; | 11 | import com.zteits.urbanops.module.garden.dal.dataobject.mechanicalcost.MechanicalCostDO; |
| 9 | import com.zteits.urbanops.module.garden.dal.dataobject.personalcost.PersonalCostDO; | 12 | import com.zteits.urbanops.module.garden.dal.dataobject.personalcost.PersonalCostDO; |
| 10 | import com.zteits.urbanops.module.garden.dal.dataobject.rentalmechanicalcost.RentalMechanicalCostDO; | 13 | import com.zteits.urbanops.module.garden.dal.dataobject.rentalmechanicalcost.RentalMechanicalCostDO; |
| 11 | import com.zteits.urbanops.module.garden.dal.dataobject.wasterecord.WasteRecordDO; | 14 | import com.zteits.urbanops.module.garden.dal.dataobject.wasterecord.WasteRecordDO; |
| 12 | import com.zteits.urbanops.module.garden.dal.dataobject.waterfee.WaterFeeDO; | 15 | import com.zteits.urbanops.module.garden.dal.dataobject.waterfee.WaterFeeDO; |
| 13 | import com.zteits.urbanops.module.garden.dal.mysql.departmentcost.DepartmentCostMapper; | 16 | import com.zteits.urbanops.module.garden.dal.mysql.departmentcost.DepartmentCostMapper; |
| 17 | +import com.zteits.urbanops.module.garden.dal.mysql.material.MaterialMapper; | ||
| 14 | import com.zteits.urbanops.module.garden.dal.mysql.mechanicalcost.MechanicalCostMapper; | 18 | import com.zteits.urbanops.module.garden.dal.mysql.mechanicalcost.MechanicalCostMapper; |
| 15 | import com.zteits.urbanops.module.garden.dal.mysql.personalcost.PersonalCostMapper; | 19 | import com.zteits.urbanops.module.garden.dal.mysql.personalcost.PersonalCostMapper; |
| 16 | import com.zteits.urbanops.module.garden.dal.mysql.rentalmechanicalcost.RentalMechanicalCostMapper; | 20 | import com.zteits.urbanops.module.garden.dal.mysql.rentalmechanicalcost.RentalMechanicalCostMapper; |
| @@ -19,6 +23,9 @@ import com.zteits.urbanops.module.garden.dal.mysql.waterfee.WaterFeeMapper; | @@ -19,6 +23,9 @@ import com.zteits.urbanops.module.garden.dal.mysql.waterfee.WaterFeeMapper; | ||
| 19 | import com.zteits.urbanops.module.garden.enums.AssignTasksConstants; | 23 | import com.zteits.urbanops.module.garden.enums.AssignTasksConstants; |
| 20 | import com.zteits.urbanops.module.garden.enums.CostFeeConstants; | 24 | import com.zteits.urbanops.module.garden.enums.CostFeeConstants; |
| 21 | import com.zteits.urbanops.module.garden.enums.TemplateEnum; | 25 | import com.zteits.urbanops.module.garden.enums.TemplateEnum; |
| 26 | +import com.zteits.urbanops.module.garden.service.material.MaterialService; | ||
| 27 | +import com.zteits.urbanops.module.garden.service.materialinventoryin.MaterialInventoryInService; | ||
| 28 | +import com.zteits.urbanops.module.garden.service.materialinventoryout.MaterialInventoryOutService; | ||
| 22 | import com.zteits.urbanops.module.system.api.dept.DeptApi; | 29 | import com.zteits.urbanops.module.system.api.dept.DeptApi; |
| 23 | import com.zteits.urbanops.module.system.api.dept.dto.DeptRespDTO; | 30 | import com.zteits.urbanops.module.system.api.dept.dto.DeptRespDTO; |
| 24 | import jakarta.annotation.Resource; | 31 | import jakarta.annotation.Resource; |
| @@ -84,6 +91,12 @@ public class CostFeeServiceImpl implements CostFeeService { | @@ -84,6 +91,12 @@ public class CostFeeServiceImpl implements CostFeeService { | ||
| 84 | private RentalMechanicalCostMapper rentalMechanicalCostMapper; | 91 | private RentalMechanicalCostMapper rentalMechanicalCostMapper; |
| 85 | @Autowired | 92 | @Autowired |
| 86 | private WasteRecordMapper wasteRecordMapper; | 93 | private WasteRecordMapper wasteRecordMapper; |
| 94 | + @Resource | ||
| 95 | + private MaterialMapper materialMapper; | ||
| 96 | + @Resource | ||
| 97 | + private MaterialInventoryInService materialInventoryInService; | ||
| 98 | + @Resource | ||
| 99 | + private MaterialInventoryOutService materialInventoryOutService; | ||
| 87 | 100 | ||
| 88 | 101 | ||
| 89 | @Override | 102 | @Override |
| @@ -412,6 +425,73 @@ public class CostFeeServiceImpl implements CostFeeService { | @@ -412,6 +425,73 @@ public class CostFeeServiceImpl implements CostFeeService { | ||
| 412 | } | 425 | } |
| 413 | 426 | ||
| 414 | log.info("成功插入 {} 园林废弃物费用数据", dataList.size()); | 427 | log.info("成功插入 {} 园林废弃物费用数据", dataList.size()); |
| 428 | + } else if (MaterialInventoryInImport.class.isAssignableFrom(importClass)) { | ||
| 429 | + List<MaterialInventoryInImport> feeList = (List<MaterialInventoryInImport>)dataList; | ||
| 430 | + List<MaterialInventoryInDO> saveFeeList = new ArrayList<>(CollectionUtils.isEmpty(feeList) ? 0 : feeList.size()); | ||
| 431 | + if (!CollectionUtils.isEmpty(feeList)) { | ||
| 432 | + Map<String, MaterialDO> materialMap = getMaterialAllMap(); | ||
| 433 | + for (MaterialInventoryInImport importObj : feeList) { | ||
| 434 | + MaterialInventoryInDO inventoryDO = new MaterialInventoryInDO(); | ||
| 435 | + BeanUtils.copyProperties(importObj, inventoryDO); | ||
| 436 | + //时间 | ||
| 437 | + inventoryDO.setBuyDate(importObj.getBuyDate().atStartOfDay()); | ||
| 438 | + String checkKey = importObj.getMaterialName() + "|" + | ||
| 439 | + importObj.getMaterialTypeName() + "|" + | ||
| 440 | + importObj.getTypeName() + "|" + | ||
| 441 | + importObj.getTypeDetailName() + "|" + | ||
| 442 | + importObj.getSpecifications() + "|" + | ||
| 443 | + importObj.getUnitName(); | ||
| 444 | + MaterialDO materialDO = materialMap.get(checkKey); | ||
| 445 | + if (materialDO != null) { | ||
| 446 | + inventoryDO.setMaterialId(materialDO.getMaterialId()); | ||
| 447 | + inventoryDO.setMaterialTypeId(materialDO.getMaterialTypeId()); | ||
| 448 | + inventoryDO.setTypeId(materialDO.getTypeId()); | ||
| 449 | + inventoryDO.setTypeDetailId(materialDO.getTypeDetailId()); | ||
| 450 | + inventoryDO.setUnitId(materialDO.getUnitId()); | ||
| 451 | + inventoryDO.setBelongCompanyId(nameToCompanyIdMap.get(inventoryDO.getBelongCompanyName())); | ||
| 452 | + } | ||
| 453 | + saveFeeList.add(inventoryDO); | ||
| 454 | + } | ||
| 455 | + } | ||
| 456 | + //入库 | ||
| 457 | + if (!saveFeeList.isEmpty()) { | ||
| 458 | + materialInventoryInService.batchCreateMaterialInventoryIn(saveFeeList); | ||
| 459 | + } | ||
| 460 | + log.info("成功插入 {} 物料入库数据", dataList.size()); | ||
| 461 | + } else if (MaterialInventoryOutImport.class.isAssignableFrom(importClass)) { | ||
| 462 | + | ||
| 463 | + List<MaterialInventoryOutImport> feeList = (List<MaterialInventoryOutImport>)dataList; | ||
| 464 | + List<MaterialInventoryOutDO> saveFeeList = new ArrayList<>(CollectionUtils.isEmpty(feeList) ? 0 : feeList.size()); | ||
| 465 | + if (!CollectionUtils.isEmpty(feeList)) { | ||
| 466 | + Map<String, MaterialDO> materialMap = getMaterialAllMap(); | ||
| 467 | + for (MaterialInventoryOutImport importObj : feeList) { | ||
| 468 | + MaterialInventoryOutDO inventoryDO = new MaterialInventoryOutDO(); | ||
| 469 | + BeanUtils.copyProperties(importObj, inventoryDO); | ||
| 470 | + //时间 | ||
| 471 | + inventoryDO.setOutDate(importObj.getOutDate().atStartOfDay()); | ||
| 472 | + String checkKey = importObj.getMaterialName() + "|" + | ||
| 473 | + importObj.getMaterialTypeName() + "|" + | ||
| 474 | + importObj.getTypeName() + "|" + | ||
| 475 | + importObj.getTypeDetailName() + "|" + | ||
| 476 | + importObj.getSpecifications() + "|" + | ||
| 477 | + importObj.getUnitName(); | ||
| 478 | + MaterialDO materialDO = materialMap.get(checkKey); | ||
| 479 | + if (materialDO != null) { | ||
| 480 | + inventoryDO.setMaterialId(materialDO.getMaterialId()); | ||
| 481 | + inventoryDO.setMaterialTypeId(materialDO.getMaterialTypeId()); | ||
| 482 | + inventoryDO.setTypeId(materialDO.getTypeId()); | ||
| 483 | + inventoryDO.setTypeDetailId(materialDO.getTypeDetailId()); | ||
| 484 | + inventoryDO.setUnitId(materialDO.getUnitId()); | ||
| 485 | + inventoryDO.setBelongCompanyId(nameToCompanyIdMap.get(inventoryDO.getBelongCompanyName())); | ||
| 486 | + } | ||
| 487 | + saveFeeList.add(inventoryDO); | ||
| 488 | + } | ||
| 489 | + } | ||
| 490 | + //出库 | ||
| 491 | + if (!saveFeeList.isEmpty()) { | ||
| 492 | + materialInventoryOutService.batchCreateMaterialInventoryOut(saveFeeList); | ||
| 493 | + } | ||
| 494 | + log.info("成功插入 {} 物料出库数据", dataList.size()); | ||
| 415 | } | 495 | } |
| 416 | 496 | ||
| 417 | } | 497 | } |
| @@ -776,9 +856,112 @@ public class CostFeeServiceImpl implements CostFeeService { | @@ -776,9 +856,112 @@ public class CostFeeServiceImpl implements CostFeeService { | ||
| 776 | throw exception0(BAD_REQUEST.getCode(), String.format("第%d条数据校验失败:%s", rowNum, ex.getMessage()), ex); | 856 | throw exception0(BAD_REQUEST.getCode(), String.format("第%d条数据校验失败:%s", rowNum, ex.getMessage()), ex); |
| 777 | } | 857 | } |
| 778 | } | 858 | } |
| 859 | + } else if (MaterialInventoryInImport.class.isAssignableFrom(importClass)) { | ||
| 860 | + //物料入库 | ||
| 861 | + List<MaterialInventoryInImport> importList = (List<MaterialInventoryInImport>) dataList; | ||
| 862 | + | ||
| 863 | + // 2. 遍历,逐个创建 | ||
| 864 | + for (int i = 0; i < importList.size(); i++) { | ||
| 865 | + int rowNum = i + 1; // 第i条数据 → 第rowNum行(对应Excel导入的行号逻辑) | ||
| 866 | + MaterialInventoryInImport importBean = importList.get(i); | ||
| 867 | + | ||
| 868 | + try { | ||
| 869 | + // 2.1 执行校验(替换原 ValidationUtils,直接用 Validator 校验,确保抛出 ConstraintViolationException) | ||
| 870 | + Set<ConstraintViolation<MaterialInventoryInImport>> violations = validator.validate(importBean); | ||
| 871 | + if (!violations.isEmpty()) { | ||
| 872 | + for (ConstraintViolation<MaterialInventoryInImport> violation : violations) { | ||
| 873 | + //errorMsg.append(violation.getMessage()).append(";"); | ||
| 874 | + throw exception0(BAD_REQUEST.getCode() ,String.format( | ||
| 875 | + "第[{}]条数据:"+violation.getMessage() | ||
| 876 | + ), rowNum); | ||
| 877 | + } | ||
| 878 | + } | ||
| 879 | + | ||
| 880 | + Long companyId = nameToCompanyIdMap.get(importBean.getBelongCompanyName()); | ||
| 881 | + //单位校验 | ||
| 882 | + validatecompany(rowNum, importBean.getBelongCompanyName(), companyId, belongCompanyId); | ||
| 883 | + } catch (ConstraintViolationException ex) { | ||
| 884 | + // 5. 包装异常,明确行号 + 真实校验错误( | ||
| 885 | + throw exception0(BAD_REQUEST.getCode(), String.format("第%d条数据校验失败:%s", rowNum, ex.getMessage()), ex); | ||
| 886 | + } | ||
| 887 | + } | ||
| 888 | + // 业务校验,检查物料信息是否正确 | ||
| 889 | + validateMaterialIn(importList); | ||
| 890 | + | ||
| 891 | + } else if (MaterialInventoryOutImport.class.isAssignableFrom(importClass)) { | ||
| 892 | + //物料出库 | ||
| 893 | + List<MaterialInventoryOutImport> importList = (List<MaterialInventoryOutImport>) dataList; | ||
| 894 | + // 2. 遍历,逐个创建 | ||
| 895 | + for (int i = 0; i < importList.size(); i++) { | ||
| 896 | + int rowNum = i + 1; // 第i条数据 → 第rowNum行(对应Excel导入的行号逻辑) | ||
| 897 | + MaterialInventoryOutImport importBean = importList.get(i); | ||
| 898 | + | ||
| 899 | + try { | ||
| 900 | + // 2.1 执行校验(替换原 ValidationUtils,直接用 Validator 校验,确保抛出 ConstraintViolationException) | ||
| 901 | + Set<ConstraintViolation<MaterialInventoryOutImport>> violations = validator.validate(importBean); | ||
| 902 | + if (!violations.isEmpty()) { | ||
| 903 | + for (ConstraintViolation<MaterialInventoryOutImport> violation : violations) { | ||
| 904 | + //errorMsg.append(violation.getMessage()).append(";"); | ||
| 905 | + throw exception0(BAD_REQUEST.getCode() ,String.format( | ||
| 906 | + "第[{}]条数据:"+violation.getMessage() | ||
| 907 | + ), rowNum); | ||
| 908 | + } | ||
| 909 | + } | ||
| 910 | + | ||
| 911 | + Long companyId = nameToCompanyIdMap.get(importBean.getBelongCompanyName()); | ||
| 912 | + //单位校验 | ||
| 913 | + validatecompany(rowNum, importBean.getBelongCompanyName(), companyId, belongCompanyId); | ||
| 914 | + } catch (ConstraintViolationException ex) { | ||
| 915 | + // 5. 包装异常,明确行号 + 真实校验错误( | ||
| 916 | + throw exception0(BAD_REQUEST.getCode(), String.format("第%d条数据校验失败:%s", rowNum, ex.getMessage()), ex); | ||
| 917 | + } | ||
| 918 | + } | ||
| 919 | + // 业务校验,检查物料信息是否正确 | ||
| 920 | + validateMaterialOut(importList); | ||
| 921 | + } | ||
| 922 | + } | ||
| 923 | + | ||
| 924 | + private void validateMaterialIn(List<MaterialInventoryInImport> importList) { | ||
| 925 | + Set<String> materialSet = getMaterialAllSet(); | ||
| 926 | + for (int i = 0; i < importList.size() ; i++) { | ||
| 927 | + int rowNum = i + 1; | ||
| 928 | + MaterialInventoryInImport importBean = importList.get(i); | ||
| 929 | + String checkKey = importBean.getMaterialName() + "|" + | ||
| 930 | + importBean.getMaterialTypeName() + "|" + | ||
| 931 | + importBean.getTypeName() + "|" + | ||
| 932 | + importBean.getTypeDetailName() + "|" + | ||
| 933 | + importBean.getSpecifications() + "|" + | ||
| 934 | + importBean.getUnitName(); | ||
| 935 | + | ||
| 936 | + if (materialSet.contains(checkKey) == false) { | ||
| 937 | + throw exception0(BAD_REQUEST.getCode(), String.format( | ||
| 938 | + "第%d条数据:导入的物料信息有误", | ||
| 939 | + rowNum | ||
| 940 | + )); | ||
| 941 | + } | ||
| 779 | } | 942 | } |
| 780 | } | 943 | } |
| 781 | 944 | ||
| 945 | + private void validateMaterialOut(List<MaterialInventoryOutImport> importList) { | ||
| 946 | + Set<String> materialSet = getMaterialAllSet(); | ||
| 947 | + for (int i = 0; i < importList.size() ; i++) { | ||
| 948 | + int rowNum = i + 1; | ||
| 949 | + MaterialInventoryOutImport importBean = importList.get(i); | ||
| 950 | + String checkKey = importBean.getMaterialName() + "|" + | ||
| 951 | + importBean.getMaterialTypeName() + "|" + | ||
| 952 | + importBean.getTypeName() + "|" + | ||
| 953 | + importBean.getTypeDetailName() + "|" + | ||
| 954 | + importBean.getSpecifications() + "|" + | ||
| 955 | + importBean.getUnitName(); | ||
| 956 | + | ||
| 957 | + if (materialSet.contains(checkKey) == false) { | ||
| 958 | + throw exception0(BAD_REQUEST.getCode(), String.format( | ||
| 959 | + "第%d条数据:%s信息有误", | ||
| 960 | + rowNum, checkKey | ||
| 961 | + )); | ||
| 962 | + } | ||
| 963 | + } | ||
| 964 | + } | ||
| 782 | private void validatecompany(int rowNum, String companyName, Long companyId, Long belongCompanyId){ | 965 | private void validatecompany(int rowNum, String companyName, Long companyId, Long belongCompanyId){ |
| 783 | // 校验数组长度是否一致 | 966 | // 校验数组长度是否一致 |
| 784 | if (companyId == null) { | 967 | if (companyId == null) { |
| @@ -998,4 +1181,52 @@ public class CostFeeServiceImpl implements CostFeeService { | @@ -998,4 +1181,52 @@ public class CostFeeServiceImpl implements CostFeeService { | ||
| 998 | 1181 | ||
| 999 | return list; | 1182 | return list; |
| 1000 | } | 1183 | } |
| 1184 | + | ||
| 1185 | + /** | ||
| 1186 | + * @Author wangqian | ||
| 1187 | + * @Description 获取物料详情 | ||
| 1188 | + * @Date 2026/1/16 9:22 | ||
| 1189 | + */ | ||
| 1190 | + private Set<String> getMaterialAllSet() { | ||
| 1191 | + List<MaterialDO> material = materialMapper.selectList(); | ||
| 1192 | + Set<String> materialKeySet = material.stream() | ||
| 1193 | + // 第一步:将MaterialDO转换为拼接key(处理空值) | ||
| 1194 | + .map(CostFeeServiceImpl::buildMaterialKey) | ||
| 1195 | + // 第三步:收集为Set(HashSet,自动去重) | ||
| 1196 | + .collect(Collectors.toCollection(HashSet::new)); | ||
| 1197 | + | ||
| 1198 | + return materialKeySet; | ||
| 1199 | + } | ||
| 1200 | + private Map<String, MaterialDO> getMaterialAllMap() { | ||
| 1201 | + List<MaterialDO> material = materialMapper.selectList(); | ||
| 1202 | + Map<String, MaterialDO> materialMap = material.stream() | ||
| 1203 | + // 转换为Map:key=拼接字符串,value=MaterialDO | ||
| 1204 | + .collect(Collectors.toMap( | ||
| 1205 | + // 第一个参数:生成Map的key(调用抽离的拼接方法) | ||
| 1206 | + CostFeeServiceImpl::buildMaterialKey, | ||
| 1207 | + // 第二个参数:生成Map的value(直接用当前MaterialDO对象) | ||
| 1208 | + m -> m, | ||
| 1209 | + // 第三个参数:重复key的合并规则(避免DuplicateKeyException) | ||
| 1210 | + // 规则1:保留第一个出现的对象(推荐,避免覆盖) | ||
| 1211 | + (existingValue, newValue) -> existingValue | ||
| 1212 | + | ||
| 1213 | + )); | ||
| 1214 | + return materialMap; | ||
| 1215 | + } | ||
| 1216 | + /** | ||
| 1217 | + * 抽离key拼接方法(复用性高,与checkKey规则完全一致) | ||
| 1218 | + * @param materialDO 物料对象 | ||
| 1219 | + * @return 拼接后的key(格式:A|B|C|D|E|F) | ||
| 1220 | + */ | ||
| 1221 | + private static String buildMaterialKey(MaterialDO materialDO) { | ||
| 1222 | + // 空值处理:字段为null时用空字符串替代,避免key中出现null | ||
| 1223 | + String materialName = materialDO.getMaterialName() == null ? "" : materialDO.getMaterialName(); | ||
| 1224 | + String materialTypeName = materialDO.getMaterialTypeName() == null ? "" : materialDO.getMaterialTypeName(); | ||
| 1225 | + String typeName = materialDO.getTypeName() == null ? "" : materialDO.getTypeName(); | ||
| 1226 | + String typeDetailName = materialDO.getTypeDetailName() == null ? "" : materialDO.getTypeDetailName(); | ||
| 1227 | + String specifications = materialDO.getSpecifications() == null ? "" : materialDO.getSpecifications(); | ||
| 1228 | + String unitName = materialDO.getUnitName() == null ? "" : materialDO.getUnitName(); | ||
| 1229 | + | ||
| 1230 | + return materialName + "|" + materialTypeName + "|" + typeName + "|" + typeDetailName + "|" + specifications + "|" + unitName; | ||
| 1231 | + } | ||
| 1001 | } | 1232 | } |
urbanops-module-garden/src/main/java/com/zteits/urbanops/module/garden/service/materialinventory/MaterialInventoryServiceImpl.java
| @@ -107,6 +107,9 @@ public class MaterialInventoryServiceImpl implements MaterialInventoryService { | @@ -107,6 +107,9 @@ public class MaterialInventoryServiceImpl implements MaterialInventoryService { | ||
| 107 | LambdaQueryWrapper<MaterialInventoryDO> queryWrapper = Wrappers.lambdaQuery(); | 107 | LambdaQueryWrapper<MaterialInventoryDO> queryWrapper = Wrappers.lambdaQuery(); |
| 108 | queryWrapper.eq(MaterialInventoryDO::getBelongCompanyId, materialInventory.getBelongCompanyId()); | 108 | queryWrapper.eq(MaterialInventoryDO::getBelongCompanyId, materialInventory.getBelongCompanyId()); |
| 109 | queryWrapper.eq(MaterialInventoryDO::getMaterialId, materialInventory.getMaterialId()); | 109 | queryWrapper.eq(MaterialInventoryDO::getMaterialId, materialInventory.getMaterialId()); |
| 110 | + queryWrapper.eq(MaterialInventoryDO::getMaterialTypeId, materialInventory.getMaterialTypeId()); | ||
| 111 | + queryWrapper.eq(MaterialInventoryDO::getTypeDetailId, materialInventory.getTypeDetailId()); | ||
| 112 | + queryWrapper.eq(MaterialInventoryDO::getTypeId, materialInventory.getTypeId()); | ||
| 110 | MaterialInventoryDO object = materialInventoryMapper.selectOne(queryWrapper); | 113 | MaterialInventoryDO object = materialInventoryMapper.selectOne(queryWrapper); |
| 111 | if(object != null){ | 114 | if(object != null){ |
| 112 | object.setInventoryTotalNum(object.getInventoryTotalNum()+ materialInventory.getCurrentNum()); | 115 | object.setInventoryTotalNum(object.getInventoryTotalNum()+ materialInventory.getCurrentNum()); |
urbanops-module-garden/src/main/java/com/zteits/urbanops/module/garden/service/materialinventoryin/MaterialInventoryInService.java
| @@ -58,5 +58,13 @@ public interface MaterialInventoryInService { | @@ -58,5 +58,13 @@ public interface MaterialInventoryInService { | ||
| 58 | * @return 物料入库分页 | 58 | * @return 物料入库分页 |
| 59 | */ | 59 | */ |
| 60 | PageResult<MaterialInventoryInDO> getMaterialInventoryInPage(MaterialInventoryInPageReqVO pageReqVO); | 60 | PageResult<MaterialInventoryInDO> getMaterialInventoryInPage(MaterialInventoryInPageReqVO pageReqVO); |
| 61 | + /** | ||
| 62 | + * @Author wangqian | ||
| 63 | + * @Description 批量入库 | ||
| 64 | + * @Date 2026/1/16 20:25 | ||
| 65 | + * @Param createReqVO | ||
| 66 | + * @Return void | ||
| 67 | + */ | ||
| 68 | + void batchCreateMaterialInventoryIn(List<MaterialInventoryInDO> list); | ||
| 61 | 69 | ||
| 62 | -} | ||
| 63 | \ No newline at end of file | 70 | \ No newline at end of file |
| 71 | +} |
urbanops-module-garden/src/main/java/com/zteits/urbanops/module/garden/service/materialinventoryin/MaterialInventoryInServiceImpl.java
| @@ -8,6 +8,7 @@ import com.zteits.urbanops.module.garden.dal.mysql.material.MaterialMapper; | @@ -8,6 +8,7 @@ import com.zteits.urbanops.module.garden.dal.mysql.material.MaterialMapper; | ||
| 8 | import com.zteits.urbanops.module.garden.service.materialinventory.MaterialInventoryService; | 8 | import com.zteits.urbanops.module.garden.service.materialinventory.MaterialInventoryService; |
| 9 | import com.zteits.urbanops.module.system.api.dept.DeptApi; | 9 | import com.zteits.urbanops.module.system.api.dept.DeptApi; |
| 10 | import com.zteits.urbanops.module.system.api.dept.dto.DeptRespDTO; | 10 | import com.zteits.urbanops.module.system.api.dept.dto.DeptRespDTO; |
| 11 | +import org.apache.commons.collections4.CollectionUtils; | ||
| 11 | import org.springframework.stereotype.Service; | 12 | import org.springframework.stereotype.Service; |
| 12 | import jakarta.annotation.Resource; | 13 | import jakarta.annotation.Resource; |
| 13 | import org.springframework.validation.annotation.Validated; | 14 | import org.springframework.validation.annotation.Validated; |
| @@ -187,4 +188,38 @@ public class MaterialInventoryInServiceImpl implements MaterialInventoryInServic | @@ -187,4 +188,38 @@ public class MaterialInventoryInServiceImpl implements MaterialInventoryInServic | ||
| 187 | return materialInventoryInMapper.selectPage(pageReqVO); | 188 | return materialInventoryInMapper.selectPage(pageReqVO); |
| 188 | } | 189 | } |
| 189 | 190 | ||
| 191 | + | ||
| 192 | + @Transactional | ||
| 193 | + @Override | ||
| 194 | + public void batchCreateMaterialInventoryIn(List<MaterialInventoryInDO> list) { | ||
| 195 | + if (CollectionUtils.isEmpty(list)) { | ||
| 196 | + return; | ||
| 197 | + } | ||
| 198 | + for (MaterialInventoryInDO in : list) { | ||
| 199 | + in.setInventoryInNo(System.currentTimeMillis()+ RandomUtil.randomInt(10, 100000)+""); | ||
| 200 | + in.setDeptId(getLoginUserDeptId()); | ||
| 201 | + materialInventoryInMapper.insert(in); | ||
| 202 | + | ||
| 203 | + //更新库存 | ||
| 204 | + MaterialInventoryDO inventory = new MaterialInventoryDO(); | ||
| 205 | + inventory.setMaterialId(in.getMaterialId()); | ||
| 206 | + inventory.setMaterialName(in.getMaterialName()); | ||
| 207 | + inventory.setMaterialTypeId(in.getMaterialTypeId()); | ||
| 208 | + inventory.setMaterialTypeName(in.getMaterialTypeName()); | ||
| 209 | + inventory.setTypeId(in.getTypeId()); | ||
| 210 | + inventory.setTypeName(in.getTypeName()); | ||
| 211 | + inventory.setTypeDetailId(in.getTypeDetailId()); | ||
| 212 | + inventory.setTypeDetailName(in.getTypeDetailName()); | ||
| 213 | + inventory.setSpecifications(in.getSpecifications()); | ||
| 214 | + inventory.setBelongCompanyId(in.getBelongCompanyId()); | ||
| 215 | + inventory.setBelongCompanyName(in.getBelongCompanyName()); | ||
| 216 | + inventory.setUnitId(in.getUnitId()); | ||
| 217 | + inventory.setUnitName(in.getUnitName()); | ||
| 218 | + inventory.setCurrentNum(in.getInInventoryNum()); | ||
| 219 | + inventory.setOutTotalNum(0L); | ||
| 220 | + inventory.setInventoryTotalNum(in.getInInventoryNum()); | ||
| 221 | + inventory.setDeptId(getLoginUserDeptId()); | ||
| 222 | + materialInventoryService.insertMaterialInventory(inventory); | ||
| 223 | + } | ||
| 224 | + } | ||
| 190 | } | 225 | } |
urbanops-module-garden/src/main/java/com/zteits/urbanops/module/garden/service/materialinventoryout/MaterialInventoryOutService.java
| @@ -59,4 +59,13 @@ public interface MaterialInventoryOutService { | @@ -59,4 +59,13 @@ public interface MaterialInventoryOutService { | ||
| 59 | */ | 59 | */ |
| 60 | PageResult<MaterialInventoryOutDO> getMaterialInventoryOutPage(MaterialInventoryOutPageReqVO pageReqVO); | 60 | PageResult<MaterialInventoryOutDO> getMaterialInventoryOutPage(MaterialInventoryOutPageReqVO pageReqVO); |
| 61 | 61 | ||
| 62 | -} | ||
| 63 | \ No newline at end of file | 62 | \ No newline at end of file |
| 63 | + /** | ||
| 64 | + * @Author wangqian | ||
| 65 | + * @Description 批量出库 | ||
| 66 | + * @Date 2026/1/16 21:40 | ||
| 67 | + * @Param list | ||
| 68 | + * @Return void | ||
| 69 | + */ | ||
| 70 | + void batchCreateMaterialInventoryOut(List<MaterialInventoryOutDO> list); | ||
| 71 | + | ||
| 72 | +} |
urbanops-module-garden/src/main/java/com/zteits/urbanops/module/garden/service/materialinventoryout/MaterialInventoryOutServiceImpl.java
| @@ -14,7 +14,9 @@ import com.zteits.urbanops.module.garden.service.materialinventory.MaterialInven | @@ -14,7 +14,9 @@ import com.zteits.urbanops.module.garden.service.materialinventory.MaterialInven | ||
| 14 | import com.zteits.urbanops.module.system.api.dept.DeptApi; | 14 | import com.zteits.urbanops.module.system.api.dept.DeptApi; |
| 15 | import com.zteits.urbanops.module.system.api.dept.dto.DeptRespDTO; | 15 | import com.zteits.urbanops.module.system.api.dept.dto.DeptRespDTO; |
| 16 | import jakarta.annotation.Resource; | 16 | import jakarta.annotation.Resource; |
| 17 | +import org.apache.commons.collections4.CollectionUtils; | ||
| 17 | import org.springframework.stereotype.Service; | 18 | import org.springframework.stereotype.Service; |
| 19 | +import org.springframework.transaction.annotation.Transactional; | ||
| 18 | import org.springframework.validation.annotation.Validated; | 20 | import org.springframework.validation.annotation.Validated; |
| 19 | 21 | ||
| 20 | import java.util.List; | 22 | import java.util.List; |
| @@ -154,4 +156,33 @@ public class MaterialInventoryOutServiceImpl implements MaterialInventoryOutServ | @@ -154,4 +156,33 @@ public class MaterialInventoryOutServiceImpl implements MaterialInventoryOutServ | ||
| 154 | return materialInventoryOutMapper.selectPage(pageReqVO); | 156 | return materialInventoryOutMapper.selectPage(pageReqVO); |
| 155 | } | 157 | } |
| 156 | 158 | ||
| 159 | + | ||
| 160 | + @Override | ||
| 161 | + @Transactional | ||
| 162 | + public void batchCreateMaterialInventoryOut(List<MaterialInventoryOutDO> list) { | ||
| 163 | + if (CollectionUtils.isEmpty(list)) { | ||
| 164 | + return; | ||
| 165 | + } | ||
| 166 | + for (MaterialInventoryOutDO out : list) { | ||
| 167 | + MaterialInventoryDO materialInventory = materialInventoryService.selectMaterialInventoryByMaterialId(out.getMaterialId(), out.getBelongCompanyId()); | ||
| 168 | + if(null == materialInventory){ | ||
| 169 | + throw exception0(BAD_REQUEST.getCode(),out.getMaterialName()+"没有库存"); | ||
| 170 | + } | ||
| 171 | + | ||
| 172 | + //当前库存不足,无法出库 | ||
| 173 | + if(materialInventory.getCurrentNum() < out.getOutInventoryNum()){ | ||
| 174 | + throw exception0(BAD_REQUEST.getCode(),"当前库存不足,无法出库"); | ||
| 175 | + } | ||
| 176 | + DeptRespDTO deptRespDTO = deptApi.getDept(getCompanyId()); | ||
| 177 | + if(null == deptRespDTO){ | ||
| 178 | + throw exception0(BAD_REQUEST.getCode(), "无效参数-登录人所属单位为空"); | ||
| 179 | + } | ||
| 180 | + out.setInventoryOutNo(System.currentTimeMillis()+ RandomUtil.randomInt(10, 100000)+""); | ||
| 181 | + materialInventoryOutMapper.insert(out); | ||
| 182 | + | ||
| 183 | + //更新库存 | ||
| 184 | + materialInventoryService.updateInVentoryByMaterialId(materialInventory, out.getOutInventoryNum()); | ||
| 185 | + } | ||
| 186 | + | ||
| 187 | + } | ||
| 157 | } | 188 | } |