diff --git a/yudao-module-common/yudao-module-common-biz/src/main/java/cn/iocoder/yudao/module/common/dal/mysql/moldticketmanagement/MoldTicketManagementMapper.java b/yudao-module-common/yudao-module-common-biz/src/main/java/cn/iocoder/yudao/module/common/dal/mysql/moldticketmanagement/MoldTicketManagementMapper.java index 0c3abd342..466029c6e 100644 --- a/yudao-module-common/yudao-module-common-biz/src/main/java/cn/iocoder/yudao/module/common/dal/mysql/moldticketmanagement/MoldTicketManagementMapper.java +++ b/yudao-module-common/yudao-module-common-biz/src/main/java/cn/iocoder/yudao/module/common/dal/mysql/moldticketmanagement/MoldTicketManagementMapper.java @@ -27,7 +27,7 @@ public interface MoldTicketManagementMapper extends BaseMapperX updateStockOutStatus(@RequestParam("id") Long id, - @RequestParam("status") Integer status, - @RequestParam(name = "status",required = false) Integer bizType) { - stockOutService.updateStockOutStatus(id, status,bizType); + @RequestParam("status") Integer status, + @RequestParam(name = "bizType", required = false) Integer bizType) { + stockOutService.updateStockOutStatus(id, status, bizType); + return success(true); + } + + @PutMapping("/submit") + @Operation(summary = "提交其它出库单审核") + @PreAuthorize("@ss.hasPermission('erp:stock-out:update')") + @RateLimiter(count = 1, timeUnit = TimeUnit.SECONDS) + public CommonResult submitStockOutAudit(@Valid @RequestBody ErpStockOutSubmitReqVO submitReqVO) { + stockOutService.submitStockOutAudit(submitReqVO); + return success(true); + } + + @PutMapping("/audit") + @Operation(summary = "审核其它出库单") + @PreAuthorize("@ss.hasPermission('erp:stock-out:update-status')") + @RateLimiter(count = 1, timeUnit = TimeUnit.SECONDS) + public CommonResult auditStockOut(@Valid @RequestBody ErpStockOutAuditReqVO auditReqVO) { + stockOutService.auditStockOut(auditReqVO); return success(true); } + @GetMapping("/approve-record-list") + @Operation(summary = "获得其它出库单审核记录") + @PreAuthorize("@ss.hasPermission('erp:stock-out:query')") + public CommonResult> getApproveRecordList(@RequestParam("id") Long id) { + return success(buildApproveRecordRespList(stockOutService.getStockOutApproveRecordList(id))); + } @PutMapping("/update-mold-status") @Operation(summary = "更新模具出库单的状态") @PreAuthorize("@ss.hasPermission('erp:stock-out:update-status')") @RateLimiter(count = 1, timeUnit = TimeUnit.SECONDS) public CommonResult updateMoldStatus(@RequestParam("id") Long id, - @RequestParam("status") Integer status) { + @RequestParam("status") Integer status) { stockOutService.updateMoldStatus(id, status); return success(true); } @@ -131,113 +166,111 @@ public class ErpStockOutController { if (stockOut == null) { return success(null); } - List stockOutItemList = stockOutService.getStockOutItemListByOutId(id); - if (Objects.equals(stockOut.getOutType(), "模具出库")) { - Map moldMap = moldBrandService.getMoldVOMap( - convertSet(stockOutItemList, ErpStockOutItemDO::getMoldSetId)); - Map> moldListMap = moldService.getMoldListMapByBrandIds( - convertSet(stockOutItemList, ErpStockOutItemDO::getMoldSetId)); - return success(BeanUtils.toBean(stockOut, ErpStockOutRespVO.class, stockOutVO -> { - stockOutVO.setItems(convertList(stockOutItemList, source -> { - ErpStockOutRespVO.Item item = BeanUtils.toBean(source, ErpStockOutRespVO.Item.class); - item.setMoldSetId(source.getMoldSetId()); - item.setMoldSetName(source.getMoldSetName()); - ErpStockDO stock = stockService.getStock(source.getMoldSetId(), source.getWarehouseId()); - item.setStockCount(stock != null ? stock.getCount() : BigDecimal.ZERO); - item.setMoldList(moldListMap.getOrDefault(source.getMoldSetId(), new ArrayList<>())); - MapUtils.findAndThen(moldMap, source.getMoldSetId(), mold -> item.setMoldSetName(mold.getName()) - .setProductName(mold.getName()) - .setProductBarCode(mold.getCode())); - return item; - })); - stockOutVO.setMoldSetNames(CollUtil.join(stockOutVO.getItems(), "?", ErpStockOutRespVO.Item::getMoldSetName)); - stockOutVO.setProductNames(stockOutVO.getMoldSetNames()); - })); - } else { - Map productMap = productService.getProductVOMap( - convertSet(stockOutItemList, ErpStockOutItemDO::getProductId)); - return success(BeanUtils.toBean(stockOut, ErpStockOutRespVO.class, stockOutVO -> - stockOutVO.setItems(BeanUtils.toBean(stockOutItemList, ErpStockOutRespVO.Item.class, item -> { - ErpStockDO stock = stockService.getStock(item.getProductId(), item.getWarehouseId()); - item.setStockCount(stock != null ? stock.getCount() : BigDecimal.ZERO); - MapUtils.findAndThen(productMap, item.getProductId(), product -> item.setProductName(product.getName()) - .setProductBarCode(product.getBarCode()).setProductUnitName(product.getUnitName())); - })))); - } - + return success(buildStockOutRespVO(stockOut, + stockOutService.getStockOutItemListByOutId(id), + stockOutService.getStockOutApproveRecordList(id))); } @GetMapping("/page") @Operation(summary = "获得其它出库单分页") @PreAuthorize("@ss.hasPermission('erp:stock-out:query')") public CommonResult> getStockOutPage(@Valid ErpStockOutPageReqVO pageReqVO) { - if(StringUtils.isEmpty(pageReqVO.getOutType())){ - List list = new ArrayList<>(); - list.add(StockOutTypeEnum.产品出库.getValue()); - list.add(StockOutTypeEnum.关键件出库.getValue()); - list.add(StockOutTypeEnum.其他出库.getValue()); - list.add(StockOutTypeEnum.原料出库.getValue()); - pageReqVO.setOutTypeList(list); - } - PageResult pageResult = stockOutService.getStockOutPage(pageReqVO); - return success(buildStockOutVOPageResult(pageResult)); + fillPageReqDefault(pageReqVO); + return success(buildStockOutVOPageResult(stockOutService.getStockOutPage(pageReqVO))); } + @GetMapping("/export-excel") @Operation(summary = "导出其它出库单 Excel") @PreAuthorize("@ss.hasPermission('erp:stock-out:export')") @ApiAccessLog(operateType = EXPORT) public void exportStockOutExcel(@Valid ErpStockOutPageReqVO pageReqVO, - HttpServletResponse response) throws IOException { + HttpServletResponse response) throws IOException { + fillPageReqDefault(pageReqVO); pageReqVO.setPageSize(PageParam.PAGE_SIZE_NONE); List list = buildStockOutVOPageResult(stockOutService.getStockOutPage(pageReqVO)).getList(); - // 导出 Excel ExcelUtils.write(response, "其它出库单.xls", "数据", ErpStockOutRespVO.class, list); } + private void fillPageReqDefault(ErpStockOutPageReqVO pageReqVO) { + if (StringUtils.isEmpty(pageReqVO.getOutType())) { + List list = new ArrayList<>(); + list.add(StockOutTypeEnum.产品出库.getValue()); + list.add(StockOutTypeEnum.关键件出库.getValue()); + list.add(StockOutTypeEnum.其他出库.getValue()); + list.add(StockOutTypeEnum.原料出库.getValue()); + pageReqVO.setOutTypeList(list); + } + } + private PageResult buildStockOutVOPageResult(PageResult pageResult) { if (CollUtil.isEmpty(pageResult.getList())) { return PageResult.empty(pageResult.getTotal()); } - List stockOutItemList = stockOutService.getStockOutItemListByOutIds( - convertSet(pageResult.getList(), ErpStockOutDO::getId)); - Map> stockOutItemMap = convertMultiMap(stockOutItemList, ErpStockOutItemDO::getOutId); - Map productMap = productService.getProductVOMap( - convertSet(stockOutItemList, ErpStockOutItemDO::getProductId)); - Map customerMap = customerService.getCustomerMap( - convertSet(pageResult.getList(), ErpStockOutDO::getCustomerId)); - Map userMap = adminUserApi.getUserMap( - convertSet(pageResult.getList(), stockOut -> Long.parseLong(stockOut.getCreator()))); - Map responserMap = adminUserApi.getUserMap( - convertSet(pageResult.getList(), ErpStockOutDO::getResponserId)); - Map moldMap = moldBrandService.getMoldVOMap( - convertSet(stockOutItemList, ErpStockOutItemDO::getMoldSetId)); - Map> moldListMap = moldService.getMoldListMapByBrandIds( - convertSet(stockOutItemList, ErpStockOutItemDO::getMoldSetId)); + List list = convertList(pageResult.getList(), stockOut -> buildStockOutRespVO( + stockOut, stockOutService.getStockOutItemListByOutId(stockOut.getId()), Collections.emptyList())); + return new PageResult<>(list, pageResult.getTotal()); + } - return BeanUtils.toBean(pageResult, ErpStockOutRespVO.class, stockOut -> { - if (Objects.equals(stockOut.getOutType(), "模具出库")) { - List itemDOS = stockOutItemMap.get(stockOut.getId()); - stockOut.setItems(convertList(itemDOS, source -> { - ErpStockOutRespVO.Item item = BeanUtils.toBean(source, ErpStockOutRespVO.Item.class); - item.setMoldSetId(source.getMoldSetId()); - item.setMoldSetName(source.getMoldSetName()); - item.setMoldList(moldListMap.getOrDefault(source.getMoldSetId(), new ArrayList<>())); - MapUtils.findAndThen(moldMap, source.getMoldSetId(), mold -> item.setMoldSetName(mold.getName()) - .setProductName(mold.getName()) - .setProductBarCode(mold.getCode())); - return item; - })); - stockOut.setMoldSetNames(CollUtil.join(stockOut.getItems(), ",", ErpStockOutRespVO.Item::getMoldSetName)); - stockOut.setProductNames(stockOut.getMoldSetNames()); - } else { - stockOut.setItems(BeanUtils.toBean(stockOutItemMap.get(stockOut.getId()), ErpStockOutRespVO.Item.class, - item -> MapUtils.findAndThen(productMap, item.getProductId(), product -> item.setProductName(product.getName()) - .setProductBarCode(product.getBarCode()).setProductUnitName(product.getUnitName())))); - stockOut.setProductNames(CollUtil.join(stockOut.getItems(), ",", ErpStockOutRespVO.Item::getProductName)); - } - MapUtils.findAndThen(customerMap, stockOut.getCustomerId(), customer -> stockOut.setCustomerName(customer.getName())); - MapUtils.findAndThen(userMap, Long.parseLong(stockOut.getCreator()), user -> stockOut.setCreatorName(user.getNickname())); - MapUtils.findAndThen(responserMap, stockOut.getResponserId(), user -> stockOut.setResponserName(user.getNickname())); + private ErpStockOutRespVO buildStockOutRespVO(ErpStockOutDO stockOut, List stockOutItemList, + List approveRecords) { + ErpStockOutRespVO stockOutVO = BeanUtils.toBean(stockOut, ErpStockOutRespVO.class); + Map userMap = adminUserApi.getUserMap(convertListByFlatMap( + Collections.singletonList(stockOut), item -> Stream.of(NumberUtils.parseLong(item.getCreator()), + item.getResponserId(), item.getAuditUserId()))); + MapUtils.findAndThen(userMap, NumberUtils.parseLong(stockOut.getCreator()), user -> stockOutVO.setCreatorName(user.getNickname())); + MapUtils.findAndThen(userMap, stockOut.getResponserId(), user -> stockOutVO.setResponserName(user.getNickname())); + MapUtils.findAndThen(userMap, stockOut.getAuditUserId(), user -> stockOutVO.setAuditUserName(user.getNickname())); + + if (Objects.equals(stockOut.getOutType(), "模具出库")) { + Map moldMap = moldBrandService.getMoldVOMap( + convertSet(stockOutItemList, ErpStockOutItemDO::getMoldSetId)); + Map> moldListMap = moldService.getMoldListMapByBrandIds( + convertSet(stockOutItemList, ErpStockOutItemDO::getMoldSetId)); + stockOutVO.setItems(convertList(stockOutItemList, source -> { + ErpStockOutRespVO.Item item = BeanUtils.toBean(source, ErpStockOutRespVO.Item.class); + ErpStockDO stock = stockService.getStock(source.getMoldSetId(), source.getWarehouseId()); + item.setStockCount(stock != null ? stock.getCount() : BigDecimal.ZERO); + item.setMoldList(moldListMap.getOrDefault(source.getMoldSetId(), new ArrayList<>())); + MapUtils.findAndThen(moldMap, source.getMoldSetId(), mold -> { + item.setMoldSetName(mold.getName()); + item.setProductName(mold.getName()); + item.setProductBarCode(mold.getCode()); + }); + return item; + })); + stockOutVO.setMoldSetNames(CollUtil.join(stockOutVO.getItems(), ",", ErpStockOutRespVO.Item::getMoldSetName)); + stockOutVO.setProductNames(stockOutVO.getMoldSetNames()); + } else { + Map productMap = productService.getProductVOMap( + convertSet(stockOutItemList, ErpStockOutItemDO::getProductId)); + stockOutVO.setItems(BeanUtils.toBean(stockOutItemList, ErpStockOutRespVO.Item.class, item -> { + ErpStockDO stock = stockService.getStock(item.getProductId(), item.getWarehouseId()); + item.setStockCount(stock != null ? stock.getCount() : BigDecimal.ZERO); + MapUtils.findAndThen(productMap, item.getProductId(), product -> { + item.setProductName(product.getName()); + item.setProductBarCode(product.getBarCode()); + item.setProductUnitName(product.getUnitName()); + }); + })); + stockOutVO.setProductNames(CollUtil.join(stockOutVO.getItems(), ",", ErpStockOutRespVO.Item::getProductName)); + } + if (stockOut.getCustomerId() != null) { + Map customerMap = customerService.getCustomerMap(Collections.singleton(stockOut.getCustomerId())); + MapUtils.findAndThen(customerMap, stockOut.getCustomerId(), customer -> stockOutVO.setCustomerName(customer.getName())); + } + stockOutVO.setApproveRecords(buildApproveRecordRespList(approveRecords)); + return stockOutVO; + } + + private List buildApproveRecordRespList(List records) { + if (CollUtil.isEmpty(records)) { + return new ArrayList<>(); + } + Map userMap = adminUserApi.getUserMap(convertListByFlatMap(records, + record -> Stream.of(NumberUtils.parseLong(record.getCreator()), record.getTargetUserId()))); + return BeanUtils.toBean(records, ErpStockOutApproveRecordRespVO.class, record -> { + MapUtils.findAndThen(userMap, NumberUtils.parseLong(record.getCreator()), user -> record.setCreatorName(user.getNickname())); + MapUtils.findAndThen(userMap, record.getTargetUserId(), user -> record.setTargetUserName(user.getNickname())); }); } @@ -248,13 +281,13 @@ public class ErpStockOutController { createReqVO.setOutType(StockOutTypeEnum.领料出库.getValue()); return success(stockOutService.createStockOut(createReqVO)); } + @GetMapping("/pageMesStockOut") @Operation(summary = "获得生产领料出库单分页") @PreAuthorize("@ss.hasPermission('erp:stock-out:query')") public CommonResult> getMesStockOutPage(@Valid ErpStockOutPageReqVO pageReqVO) { pageReqVO.setOutType(StockOutTypeEnum.领料出库.getValue()); - PageResult pageResult = stockOutService.getStockOutPage(pageReqVO); - return success(buildStockOutVOPageResult(pageResult)); + return success(buildStockOutVOPageResult(stockOutService.getStockOutPage(pageReqVO))); } -} \ No newline at end of file +} diff --git a/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/controller/admin/stock/vo/out/ErpStockOutApproveRecordRespVO.java b/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/controller/admin/stock/vo/out/ErpStockOutApproveRecordRespVO.java new file mode 100644 index 000000000..9a080c18f --- /dev/null +++ b/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/controller/admin/stock/vo/out/ErpStockOutApproveRecordRespVO.java @@ -0,0 +1,44 @@ +package cn.iocoder.yudao.module.erp.controller.admin.stock.vo.out; + +import io.swagger.v3.oas.annotations.media.Schema; +import lombok.Data; + +import java.time.LocalDateTime; + +@Schema(description = "管理后台 - ERP 其它出库单审核记录 Response VO") +@Data +public class ErpStockOutApproveRecordRespVO { + + @Schema(description = "编号", example = "1") + private Long id; + + @Schema(description = "出库单编号", example = "1") + private Long stockOutId; + + @Schema(description = "操作类型", example = "SUBMIT") + private String actionType; + + @Schema(description = "变更前状态", example = "0") + private Integer fromStatus; + + @Schema(description = "变更后状态", example = "10") + private Integer toStatus; + + @Schema(description = "目标审核人编号", example = "1") + private Long targetUserId; + + @Schema(description = "目标审核人名称", example = "李四") + private String targetUserName; + + @Schema(description = "备注", example = "请审核") + private String remark; + + @Schema(description = "操作人", example = "1") + private String creator; + + @Schema(description = "操作人名称", example = "张三") + private String creatorName; + + @Schema(description = "创建时间") + private LocalDateTime createTime; +} diff --git a/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/controller/admin/stock/vo/out/ErpStockOutAuditReqVO.java b/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/controller/admin/stock/vo/out/ErpStockOutAuditReqVO.java new file mode 100644 index 000000000..020ffc9c7 --- /dev/null +++ b/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/controller/admin/stock/vo/out/ErpStockOutAuditReqVO.java @@ -0,0 +1,22 @@ +package cn.iocoder.yudao.module.erp.controller.admin.stock.vo.out; + +import io.swagger.v3.oas.annotations.media.Schema; +import lombok.Data; + +import javax.validation.constraints.NotNull; + +@Schema(description = "管理后台 - ERP 其它出库单审核 Request VO") +@Data +public class ErpStockOutAuditReqVO { + + @Schema(description = "出库编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "11756") + @NotNull(message = "出库编号不能为空") + private Long id; + + @Schema(description = "审核结果 20-通过 1-驳回", requiredMode = Schema.RequiredMode.REQUIRED, example = "20") + @NotNull(message = "审核结果不能为空") + private Integer status; + + @Schema(description = "审核备注", example = "审核通过") + private String remark; +} diff --git a/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/controller/admin/stock/vo/out/ErpStockOutPageReqVO.java b/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/controller/admin/stock/vo/out/ErpStockOutPageReqVO.java index 21677e526..f86ccebcb 100644 --- a/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/controller/admin/stock/vo/out/ErpStockOutPageReqVO.java +++ b/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/controller/admin/stock/vo/out/ErpStockOutPageReqVO.java @@ -25,11 +25,14 @@ public class ErpStockOutPageReqVO extends PageParam { @Schema(description = "客户编号", example = "3113") private Long customerId; - @Schema(description = "负责人id", example = "3113") + + @Schema(description = "负责人 id", example = "3113") private Long responserId; - @Schema(description = "出库类型", example = "随便") + + @Schema(description = "出库类型", example = "其他出库") private String outType; - @Schema(description = "出库类型", example = "随便") + + @Schema(description = "出库类型列表", example = "[\"其他出库\",\"产品出库\"]") private List outTypeList; @Schema(description = "出库时间") @@ -40,7 +43,10 @@ public class ErpStockOutPageReqVO extends PageParam { @InEnum(ErpAuditStatus.class) private Integer status; - @Schema(description = "备注", example = "随便") + @Schema(description = "审核人编号", example = "1") + private Long auditUserId; + + @Schema(description = "备注", example = "备注信息") private String remark; @Schema(description = "创建者") @@ -52,6 +58,6 @@ public class ErpStockOutPageReqVO extends PageParam { @Schema(description = "仓库编号", example = "1") private Long warehouseId; - @Schema(description = "id集合导出用") + @Schema(description = "id 集合,导出时使用") private String ids; -} \ No newline at end of file +} diff --git a/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/controller/admin/stock/vo/out/ErpStockOutRespVO.java b/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/controller/admin/stock/vo/out/ErpStockOutRespVO.java index fddfd8ed1..13b0a882f 100644 --- a/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/controller/admin/stock/vo/out/ErpStockOutRespVO.java +++ b/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/controller/admin/stock/vo/out/ErpStockOutRespVO.java @@ -1,8 +1,8 @@ package cn.iocoder.yudao.module.erp.controller.admin.stock.vo.out; import cn.iocoder.yudao.framework.excel.core.annotations.DictFormat; -import cn.iocoder.yudao.module.common.dal.dataobject.mold.MoldDO; import cn.iocoder.yudao.framework.excel.core.convert.DictConvert; +import cn.iocoder.yudao.module.common.dal.dataobject.mold.MoldDO; import com.alibaba.excel.annotation.ExcelIgnoreUnannotated; import com.alibaba.excel.annotation.ExcelProperty; import io.swagger.v3.oas.annotations.media.Schema; @@ -29,14 +29,18 @@ public class ErpStockOutRespVO { @Schema(description = "客户编号", example = "3113") private Long customerId; + @Schema(description = "客户名称", example = "芋道") @ExcelProperty("客户名称") private String customerName; - @Schema(description = "负责人id", example = "3113") + + @Schema(description = "负责人 id", example = "3113") private Long responserId; - @Schema(description = "负责人", example = "3113") + + @Schema(description = "负责人", example = "张三") private String responserName; - @Schema(description = "出库类型", example = "随便") + + @Schema(description = "出库类型", example = "其他出库") private String outType; @Schema(description = "出库时间", requiredMode = Schema.RequiredMode.REQUIRED) @@ -47,7 +51,7 @@ public class ErpStockOutRespVO { @ExcelProperty("合计数量") private BigDecimal totalCount; - @Schema(description = "合计金额,单位:元", requiredMode = Schema.RequiredMode.REQUIRED, example = "24906") + @Schema(description = "合计金额", requiredMode = Schema.RequiredMode.REQUIRED, example = "24906") @ExcelProperty("合计金额") private BigDecimal totalPrice; @@ -56,7 +60,16 @@ public class ErpStockOutRespVO { @DictFormat(AUDIT_STATUS) private Integer status; - @Schema(description = "备注", example = "随便") + @Schema(description = "是否需要审核", example = "true") + private Boolean needAudit; + + @Schema(description = "审核人编号", example = "1888") + private Long auditUserId; + + @Schema(description = "审核人名称", example = "李四") + private String auditUserName; + + @Schema(description = "备注", example = "备注信息") @ExcelProperty("备注") private String remark; @@ -65,6 +78,7 @@ public class ErpStockOutRespVO { @Schema(description = "创建人", example = "芋道") private String creator; + @Schema(description = "创建人名称", example = "芋道") private String creatorName; @@ -75,27 +89,29 @@ public class ErpStockOutRespVO { @Schema(description = "出库项列表", requiredMode = Schema.RequiredMode.REQUIRED) private List items; + @Schema(description = "审核记录") + private List approveRecords; + @Schema(description = "产品信息", requiredMode = Schema.RequiredMode.REQUIRED) @ExcelProperty("产品信息") private String productNames; - @Schema(description = "模具组名字") + @Schema(description = "模具组名称") private String moldSetNames; - @Schema(description = "计划单Code", example = "随便") + @Schema(description = "计划单 Code", example = "PLAN20240601") private String planCode; - @Data public static class Item { @Schema(description = "出库项编号", example = "11756") private Long id; - @Schema(description = "??? ID", example = "1") + @Schema(description = "模具组 ID", example = "1") private Long moldSetId; - @Schema(description = "?????", example = "A?") + @Schema(description = "模具组名称", example = "A组") private String moldSetName; @Schema(description = "仓库编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "3113") @@ -110,13 +126,15 @@ public class ErpStockOutRespVO { @Schema(description = "产品数量", requiredMode = Schema.RequiredMode.REQUIRED, example = "100.00") private BigDecimal count; - @Schema(description = "备注", example = "随便") + @Schema(description = "备注", example = "备注信息") private String remark; - @Schema(description = "产品名称", requiredMode = Schema.RequiredMode.REQUIRED, example = "???") + @Schema(description = "产品名称", requiredMode = Schema.RequiredMode.REQUIRED, example = "巧克力") private String productName; + @Schema(description = "产品条码", requiredMode = Schema.RequiredMode.REQUIRED, example = "A9985") private String productBarCode; + @Schema(description = "产品单位名称", requiredMode = Schema.RequiredMode.REQUIRED, example = "盒") private String productUnitName; @@ -125,7 +143,6 @@ public class ErpStockOutRespVO { @Schema(description = "子模具列表") private List moldList; - } -} \ No newline at end of file +} diff --git a/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/controller/admin/stock/vo/out/ErpStockOutSaveReqVO.java b/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/controller/admin/stock/vo/out/ErpStockOutSaveReqVO.java index e2b817b02..a632a8760 100644 --- a/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/controller/admin/stock/vo/out/ErpStockOutSaveReqVO.java +++ b/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/controller/admin/stock/vo/out/ErpStockOutSaveReqVO.java @@ -14,21 +14,26 @@ import java.util.List; @Data public class ErpStockOutSaveReqVO { - @Schema(description = "出库编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "11756") + @Schema(description = "出库编号", example = "11756") private Long id; @Schema(description = "客户编号", example = "3113") private Long customerId; - @Schema(description = "负责人id", example = "3113") + + @Schema(description = "负责人 id", example = "3113") private Long responserId; - @Schema(description = "出库类型", example = "随便") + + @Schema(description = "出库类型", example = "其他出库") private String outType; @Schema(description = "出库时间", requiredMode = Schema.RequiredMode.REQUIRED) @NotNull(message = "出库时间不能为空") private LocalDateTime outTime; - @Schema(description = "备注", example = "随便") + @Schema(description = "审核人编号", example = "1888") + private Long auditUserId; + + @Schema(description = "备注", example = "备注信息") private String remark; @Schema(description = "附件 URL", example = "https://www.iocoder.cn/1.doc") @@ -39,35 +44,32 @@ public class ErpStockOutSaveReqVO { @Valid private List items; - @Schema(description = "计划单Code", example = "随便") + @Schema(description = "计划单 Code", example = "PLAN20240601") private String planCode; - @Data public static class Item { @Schema(description = "出库项编号", example = "11756") private Long id; - @Schema(description = "模具组id", example = "101") + @Schema(description = "模具组 id", example = "101") private Long moldSetId; @Schema(description = "仓库编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "3113") private Long warehouseId; - @Schema(description = "产品id", example = "3113") + @Schema(description = "产品 id", example = "3113") private Long productId; @Schema(description = "产品单价", example = "100.00") private BigDecimal productPrice; @Schema(description = "产品数量", requiredMode = Schema.RequiredMode.REQUIRED, example = "100.00") -// @NotNull(message = "产品数量不能为空") private BigDecimal count; - @Schema(description = "备注", example = "??") + @Schema(description = "备注", example = "备注信息") private String remark; - } -} \ No newline at end of file +} diff --git a/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/controller/admin/stock/vo/out/ErpStockOutSubmitReqVO.java b/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/controller/admin/stock/vo/out/ErpStockOutSubmitReqVO.java new file mode 100644 index 000000000..3b53f17a4 --- /dev/null +++ b/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/controller/admin/stock/vo/out/ErpStockOutSubmitReqVO.java @@ -0,0 +1,21 @@ +package cn.iocoder.yudao.module.erp.controller.admin.stock.vo.out; + +import io.swagger.v3.oas.annotations.media.Schema; +import lombok.Data; + +import javax.validation.constraints.NotNull; + +@Schema(description = "管理后台 - ERP 其它出库单提交审核 Request VO") +@Data +public class ErpStockOutSubmitReqVO { + + @Schema(description = "出库编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "11756") + @NotNull(message = "出库编号不能为空") + private Long id; + + @Schema(description = "审核人编号", example = "1888") + private Long auditUserId; + + @Schema(description = "提交备注", example = "请审核") + private String remark; +} diff --git a/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/controller/admin/stock/vo/out/StockOutTypeEnum.java b/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/controller/admin/stock/vo/out/StockOutTypeEnum.java index 87843934b..dabcd07e4 100644 --- a/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/controller/admin/stock/vo/out/StockOutTypeEnum.java +++ b/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/controller/admin/stock/vo/out/StockOutTypeEnum.java @@ -15,7 +15,6 @@ public enum StockOutTypeEnum { private final String value; - // 一个可选的方法,用于根据整数值获取对应的枚举实例 public static StockOutTypeEnum fromValue(String value) { for (StockOutTypeEnum status : StockOutTypeEnum.values()) { if (status.getValue().equals(value)) { @@ -24,4 +23,4 @@ public enum StockOutTypeEnum { } throw new IllegalArgumentException("Unknown value: " + value); } -} \ No newline at end of file +} diff --git a/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/dal/dataobject/stock/ErpStockOutApproveRecordDO.java b/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/dal/dataobject/stock/ErpStockOutApproveRecordDO.java new file mode 100644 index 000000000..6a27b56c8 --- /dev/null +++ b/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/dal/dataobject/stock/ErpStockOutApproveRecordDO.java @@ -0,0 +1,39 @@ +package cn.iocoder.yudao.module.erp.dal.dataobject.stock; + +import cn.iocoder.yudao.framework.mybatis.core.dataobject.BaseDO; +import com.baomidou.mybatisplus.annotation.KeySequence; +import com.baomidou.mybatisplus.annotation.TableId; +import com.baomidou.mybatisplus.annotation.TableName; +import lombok.AllArgsConstructor; +import lombok.Builder; +import lombok.Data; +import lombok.EqualsAndHashCode; +import lombok.NoArgsConstructor; +import lombok.ToString; + +@TableName("erp_stock_out_approve_record") +@KeySequence("erp_stock_out_approve_record_seq") +@Data +@EqualsAndHashCode(callSuper = true) +@ToString(callSuper = true) +@Builder +@NoArgsConstructor +@AllArgsConstructor +public class ErpStockOutApproveRecordDO extends BaseDO { + + @TableId + private Long id; + + private Long stockOutId; + + private String actionType; + + private Integer fromStatus; + + private Integer toStatus; + + private Long targetUserId; + + private String remark; + +} diff --git a/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/dal/dataobject/stock/ErpStockOutDO.java b/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/dal/dataobject/stock/ErpStockOutDO.java index bf3edbfeb..51753f700 100644 --- a/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/dal/dataobject/stock/ErpStockOutDO.java +++ b/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/dal/dataobject/stock/ErpStockOutDO.java @@ -66,6 +66,14 @@ public class ErpStockOutDO extends BaseDO { * 枚举 {@link cn.iocoder.yudao.module.erp.enums.ErpAuditStatus} */ private Integer status; + /** + * 是否需要审核 + */ + private Boolean needAudit; + /** + * 审核人编号 + */ + private Long auditUserId; /** * 备注 */ @@ -79,4 +87,4 @@ public class ErpStockOutDO extends BaseDO { * 计划单Code */ private String planCode; -} \ No newline at end of file +} diff --git a/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/dal/mysql/stock/ErpStockOutApproveRecordMapper.java b/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/dal/mysql/stock/ErpStockOutApproveRecordMapper.java new file mode 100644 index 000000000..d7ac920e1 --- /dev/null +++ b/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/dal/mysql/stock/ErpStockOutApproveRecordMapper.java @@ -0,0 +1,23 @@ +package cn.iocoder.yudao.module.erp.dal.mysql.stock; + +import cn.iocoder.yudao.framework.mybatis.core.mapper.BaseMapperX; +import cn.iocoder.yudao.framework.mybatis.core.query.LambdaQueryWrapperX; +import cn.iocoder.yudao.module.erp.dal.dataobject.stock.ErpStockOutApproveRecordDO; +import org.apache.ibatis.annotations.Mapper; + +import java.util.List; + +@Mapper +public interface ErpStockOutApproveRecordMapper extends BaseMapperX { + + default List selectListByStockOutId(Long stockOutId) { + return selectList(new LambdaQueryWrapperX() + .eq(ErpStockOutApproveRecordDO::getStockOutId, stockOutId) + .orderByAsc(ErpStockOutApproveRecordDO::getId)); + } + + default int deleteByStockOutId(Long stockOutId) { + return delete(ErpStockOutApproveRecordDO::getStockOutId, stockOutId); + } + +} diff --git a/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/dal/mysql/stock/ErpStockOutMapper.java b/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/dal/mysql/stock/ErpStockOutMapper.java index aeb99e6d0..1b4ecadfa 100644 --- a/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/dal/mysql/stock/ErpStockOutMapper.java +++ b/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/dal/mysql/stock/ErpStockOutMapper.java @@ -4,8 +4,6 @@ import cn.iocoder.yudao.framework.common.pojo.PageResult; import cn.iocoder.yudao.framework.mybatis.core.mapper.BaseMapperX; import cn.iocoder.yudao.framework.mybatis.core.query.MPJLambdaWrapperX; import cn.iocoder.yudao.module.erp.controller.admin.stock.vo.out.ErpStockOutPageReqVO; -import cn.iocoder.yudao.module.erp.dal.dataobject.product.ErpProductDO; -import cn.iocoder.yudao.module.erp.dal.dataobject.stock.ErpStockInDO; import cn.iocoder.yudao.module.erp.dal.dataobject.stock.ErpStockOutDO; import cn.iocoder.yudao.module.erp.dal.dataobject.stock.ErpStockOutItemDO; import com.alibaba.excel.util.StringUtils; @@ -17,11 +15,6 @@ import java.util.Arrays; import java.util.List; import java.util.stream.Collectors; -/** - * ERP 其它出库单 Mapper - * - * @author 芋道源码 - */ @Mapper public interface ErpStockOutMapper extends BaseMapperX { @@ -36,36 +29,35 @@ public interface ErpStockOutMapper extends BaseMapperX { .eqIfPresent(ErpStockOutDO::getStatus, reqVO.getStatus()) .likeIfPresent(ErpStockOutDO::getRemark, reqVO.getRemark()) .eqIfPresent(ErpStockOutDO::getCreator, reqVO.getCreator()) + .eqIfPresent(ErpStockOutDO::getAuditUserId, reqVO.getAuditUserId()) .orderByDesc(ErpStockOutDO::getId); if (reqVO.getWarehouseId() != null || reqVO.getProductId() != null) { query.leftJoin(ErpStockOutItemDO.class, ErpStockOutItemDO::getOutId, ErpStockOutDO::getId) .eq(reqVO.getWarehouseId() != null, ErpStockOutItemDO::getWarehouseId, reqVO.getWarehouseId()) .eq(reqVO.getProductId() != null, ErpStockOutItemDO::getProductId, reqVO.getProductId()) - .groupBy(ErpStockOutDO::getId); // 避免 1 对多查询,产生相同的 1 + .groupBy(ErpStockOutDO::getId); } - - // 单独处理 ids 条件 if (StringUtils.isNotBlank(reqVO.getIds())) { List idList = Arrays.stream(reqVO.getIds().split(",")) .map(String::trim) .map(Long::valueOf) .collect(Collectors.toList()); - query.in(ErpStockInDO::getId, idList); + query.in(ErpStockOutDO::getId, idList); } - return selectJoinPage(reqVO, ErpStockOutDO.class, query); } default int updateByIdAndStatus(Long id, Integer status, ErpStockOutDO updateObj) { return update(updateObj, new LambdaUpdateWrapper() - .eq(ErpStockOutDO::getId, id).eq(ErpStockOutDO::getStatus, status)); + .eq(ErpStockOutDO::getId, id) + .eq(ErpStockOutDO::getStatus, status)); } default ErpStockOutDO selectByNo(String no) { return selectOne(ErpStockOutDO::getNo, no); } - default List selectByOutType(List outTypes){ - return selectList(new QueryWrapper() - .in("out_type" ,outTypes)); + + default List selectByOutType(List outTypes) { + return selectList(new QueryWrapper().in("out_type", outTypes)); } -} \ No newline at end of file +} diff --git a/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/service/stock/ErpStockOutService.java b/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/service/stock/ErpStockOutService.java index 7c8ff0420..bb9d593d0 100644 --- a/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/service/stock/ErpStockOutService.java +++ b/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/service/stock/ErpStockOutService.java @@ -2,7 +2,10 @@ package cn.iocoder.yudao.module.erp.service.stock; import cn.iocoder.yudao.framework.common.pojo.PageResult; import cn.iocoder.yudao.module.erp.controller.admin.stock.vo.out.ErpStockOutPageReqVO; +import cn.iocoder.yudao.module.erp.controller.admin.stock.vo.out.ErpStockOutAuditReqVO; +import cn.iocoder.yudao.module.erp.controller.admin.stock.vo.out.ErpStockOutSubmitReqVO; import cn.iocoder.yudao.module.erp.controller.admin.stock.vo.out.ErpStockOutSaveReqVO; +import cn.iocoder.yudao.module.erp.dal.dataobject.stock.ErpStockOutApproveRecordDO; import cn.iocoder.yudao.module.erp.dal.dataobject.stock.ErpStockOutDO; import cn.iocoder.yudao.module.erp.dal.dataobject.stock.ErpStockOutItemDO; @@ -40,6 +43,10 @@ public interface ErpStockOutService { */ void updateStockOutStatus(Long id, Integer status, Integer bizType); + void submitStockOutAudit(@Valid ErpStockOutSubmitReqVO submitReqVO); + + void auditStockOut(@Valid ErpStockOutAuditReqVO auditReqVO); + /** * 删除其它出库单 * @@ -80,7 +87,9 @@ public interface ErpStockOutService { * @return 其它出库单项 List */ List getStockOutItemListByOutIds(Collection outIds); + + List getStockOutApproveRecordList(Long stockOutId); List selectByOutType(List outTypes); void updateMoldStatus(Long id, Integer status); -} \ No newline at end of file +} diff --git a/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/service/stock/ErpStockOutServiceImpl.java b/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/service/stock/ErpStockOutServiceImpl.java index e3a4b5553..963cc58f5 100644 --- a/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/service/stock/ErpStockOutServiceImpl.java +++ b/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/service/stock/ErpStockOutServiceImpl.java @@ -3,19 +3,26 @@ package cn.iocoder.yudao.module.erp.service.stock; import cn.hutool.core.collection.CollUtil; import cn.iocoder.yudao.framework.common.pojo.PageResult; import cn.iocoder.yudao.framework.common.util.number.MoneyUtils; +import cn.iocoder.yudao.framework.common.util.number.NumberUtils; import cn.iocoder.yudao.framework.common.util.object.BeanUtils; +import cn.iocoder.yudao.framework.security.core.util.SecurityFrameworkUtils; import cn.iocoder.yudao.module.common.controller.admin.mold.vo.MoldBrandSaveReqVO; import cn.iocoder.yudao.module.common.dal.dataobject.mold.MoldBrandDO; import cn.iocoder.yudao.module.erp.controller.admin.product.vo.product.ErpProductRespVO; +import cn.iocoder.yudao.module.erp.controller.admin.stock.vo.out.ErpStockOutAuditReqVO; import cn.iocoder.yudao.module.erp.controller.admin.stock.vo.out.ErpStockOutPageReqVO; import cn.iocoder.yudao.module.erp.controller.admin.stock.vo.out.ErpStockOutSaveReqVO; +import cn.iocoder.yudao.module.erp.controller.admin.stock.vo.out.ErpStockOutSubmitReqVO; import cn.iocoder.yudao.module.erp.dal.dataobject.product.ErpProductDO; +import cn.iocoder.yudao.module.erp.dal.dataobject.stock.ErpStockOutApproveRecordDO; import cn.iocoder.yudao.module.erp.dal.dataobject.stock.ErpStockOutDO; import cn.iocoder.yudao.module.erp.dal.dataobject.stock.ErpStockOutItemDO; +import cn.iocoder.yudao.module.erp.dal.mysql.stock.ErpStockOutApproveRecordMapper; import cn.iocoder.yudao.module.erp.dal.mysql.stock.ErpStockOutItemMapper; import cn.iocoder.yudao.module.erp.dal.mysql.stock.ErpStockOutMapper; import cn.iocoder.yudao.module.erp.dal.redis.no.ErpNoRedisDAO; import cn.iocoder.yudao.module.erp.enums.ErpAuditStatus; +import cn.iocoder.yudao.module.erp.enums.stock.ErpStockOutApproveActionEnum; import cn.iocoder.yudao.module.erp.enums.stock.ErpStockRecordBizTypeEnum; import cn.iocoder.yudao.module.erp.service.mold.MoldBrandService; import cn.iocoder.yudao.module.erp.service.mold.MoldService; @@ -23,27 +30,27 @@ import cn.iocoder.yudao.module.erp.service.product.ErpProductService; import cn.iocoder.yudao.module.erp.service.sale.ErpCustomerService; import cn.iocoder.yudao.module.erp.service.stock.bo.ErpStockRecordCreateReqBO; import cn.iocoder.yudao.module.infra.api.config.ConfigApi; +import cn.iocoder.yudao.module.system.api.user.AdminUserApi; import org.springframework.stereotype.Service; import org.springframework.transaction.annotation.Transactional; import org.springframework.validation.annotation.Validated; import javax.annotation.Resource; import java.math.BigDecimal; -import java.time.LocalDateTime; -import java.util.*; +import java.util.Collection; +import java.util.Collections; +import java.util.List; +import java.util.Map; +import java.util.Objects; import static cn.iocoder.yudao.framework.common.exception.util.ServiceExceptionUtil.exception; -import static cn.iocoder.yudao.framework.common.util.collection.CollectionUtils.*; -import static cn.iocoder.yudao.framework.web.core.util.WebFrameworkUtils.getLoginUserId; +import static cn.iocoder.yudao.framework.common.util.collection.CollectionUtils.convertList; +import static cn.iocoder.yudao.framework.common.util.collection.CollectionUtils.convertMap; +import static cn.iocoder.yudao.framework.common.util.collection.CollectionUtils.convertSet; +import static cn.iocoder.yudao.framework.common.util.collection.CollectionUtils.diffList; +import static cn.iocoder.yudao.framework.common.util.collection.CollectionUtils.getSumValue; import static cn.iocoder.yudao.module.erp.enums.ErrorCodeConstants.*; -// TODO 芋艿:记录操作日志 - -/** - * ERP 其它出库单 Service 实现类 - * - * @author 芋道源码 - */ @Service @Validated public class ErpStockOutServiceImpl implements ErpStockOutService { @@ -56,10 +63,10 @@ public class ErpStockOutServiceImpl implements ErpStockOutService { private ErpStockOutMapper stockOutMapper; @Resource private ErpStockOutItemMapper stockOutItemMapper; - + @Resource + private ErpStockOutApproveRecordMapper stockOutApproveRecordMapper; @Resource private ErpNoRedisDAO noRedisDAO; - @Resource private ErpProductService productService; @Resource @@ -73,40 +80,44 @@ public class ErpStockOutServiceImpl implements ErpStockOutService { @Resource private ErpStockRecordService stockRecordService; @Resource + private AdminUserApi adminUserApi; + @Resource private ConfigApi configApi; - @Override @Transactional(rollbackFor = Exception.class) public Long createStockOut(ErpStockOutSaveReqVO createReqVO) { - // 1.1 校验出库项的有效性 - List stockOutItems = validateStockOutItems(createReqVO.getItems(),createReqVO.getOutType()); - // 1.2 校验客户 - //customerService.validateCustomer(createReqVO.getCustomerId()); - // 1.3 生成出库单号,并校验唯一性 + List stockOutItems = validateStockOutItems(createReqVO.getItems(), createReqVO.getOutType()); + if (createReqVO.getCustomerId() != null) { + customerService.validateCustomer(createReqVO.getCustomerId()); + } + if (createReqVO.getResponserId() != null) { + adminUserApi.validateUser(createReqVO.getResponserId()); + } + if (createReqVO.getAuditUserId() != null) { + adminUserApi.validateUser(createReqVO.getAuditUserId()); + } String no = noRedisDAO.generate(ErpNoRedisDAO.STOCK_OUT_NO_PREFIX); if (stockOutMapper.selectByNo(no) != null) { throw exception(STOCK_OUT_NO_EXISTS); } - // 2.1 插入出库单 boolean needAudit = needAudit(); - Integer status = needAudit ? ErpAuditStatus.PROCESS.getStatus() : ErpAuditStatus.APPROVE.getStatus(); - ErpStockOutDO stockOut = BeanUtils.toBean(createReqVO, ErpStockOutDO.class, in -> in - .setNo(no).setStatus(status) + Integer status = needAudit ? ErpAuditStatus.DRAFT.getStatus() : ErpAuditStatus.APPROVE.getStatus(); + ErpStockOutDO stockOut = BeanUtils.toBean(createReqVO, ErpStockOutDO.class, out -> out + .setNo(no) + .setNeedAudit(needAudit) + .setStatus(status) .setTotalCount(getSumValue(stockOutItems, ErpStockOutItemDO::getCount, BigDecimal::add)) .setTotalPrice(getSumValue(stockOutItems, ErpStockOutItemDO::getTotalPrice, BigDecimal::add, BigDecimal.ZERO))); stockOutMapper.insert(stockOut); - // 2.2 插入出库单项 - stockOutItems.forEach(o -> o.setOutId(stockOut.getId())); + stockOutItems.forEach(item -> item.setOutId(stockOut.getId())); stockOutItemMapper.insertBatch(stockOutItems); -// for (ErpStockOutItemDO item : stockOutItems) { -// MoldDO moldDO = moldService.getMold(item.getProductId()); -// moldDO.setStatus(ErpAuditStatus.PROCESS.getStatus()); // 未审核 -// moldService.updateMold(BeanUtils.toBean(moldDO, MoldSaveReqVO.class)); -// } + if (!needAudit) { - operateStockOutEffect(stockOut, stockOutItems, true, ErpAuditStatus.APPROVE.getStatus()); + applyStockOutEffect(stockOut, stockOutItems, null); + createApproveRecord(stockOut.getId(), ErpStockOutApproveActionEnum.AUTO_APPROVE, null, + ErpAuditStatus.APPROVE.getStatus(), null, "无需审核,系统自动出库"); } return stockOut.getId(); } @@ -114,141 +125,124 @@ public class ErpStockOutServiceImpl implements ErpStockOutService { @Override @Transactional(rollbackFor = Exception.class) public void updateStockOut(ErpStockOutSaveReqVO updateReqVO) { - // 1.1 校验存在 ErpStockOutDO stockOut = validateStockOutExists(updateReqVO.getId()); if (ErpAuditStatus.APPROVE.getStatus().equals(stockOut.getStatus())) { throw exception(STOCK_OUT_UPDATE_FAIL_APPROVE, stockOut.getNo()); } - // 1.2 校验客户 -// customerService.validateCustomer(updateReqVO.getCustomerId()); - // 1.3 校验出库项的有效性 - List stockOutItems = validateStockOutItems(updateReqVO.getItems(),updateReqVO.getOutType()); - - // 2.1 更新出库单 - ErpStockOutDO updateObj = BeanUtils.toBean(updateReqVO, ErpStockOutDO.class, in -> in + if (ErpAuditStatus.PROCESS.getStatus().equals(stockOut.getStatus())) { + throw exception(STOCK_OUT_UPDATE_FAIL_PROCESS, stockOut.getNo()); + } + if (updateReqVO.getCustomerId() != null) { + customerService.validateCustomer(updateReqVO.getCustomerId()); + } + if (updateReqVO.getResponserId() != null) { + adminUserApi.validateUser(updateReqVO.getResponserId()); + } + if (updateReqVO.getAuditUserId() != null) { + adminUserApi.validateUser(updateReqVO.getAuditUserId()); + } + List stockOutItems = validateStockOutItems(updateReqVO.getItems(), updateReqVO.getOutType()); + boolean needAudit = needAudit(); + ErpStockOutDO updateObj = BeanUtils.toBean(updateReqVO, ErpStockOutDO.class, out -> out + .setNeedAudit(needAudit) .setTotalCount(getSumValue(stockOutItems, ErpStockOutItemDO::getCount, BigDecimal::add)) - .setTotalPrice(getSumValue(stockOutItems, ErpStockOutItemDO::getTotalPrice, BigDecimal::add))); + .setTotalPrice(getSumValue(stockOutItems, ErpStockOutItemDO::getTotalPrice, BigDecimal::add, BigDecimal.ZERO))); stockOutMapper.updateById(updateObj); - // 2.2 更新出库单项 updateStockOutItemList(updateReqVO.getId(), stockOutItems); } @Override @Transactional(rollbackFor = Exception.class) public void updateStockOutStatus(Long id, Integer status, Integer bizType) { - boolean approve = ErpAuditStatus.APPROVE.getStatus().equals(status); ErpStockOutDO stockOut = validateStockOutExists(id); - if (stockOut.getStatus().equals(status)) { - throw exception(approve ? STOCK_OUT_APPROVE_FAIL : STOCK_OUT_PROCESS_FAIL); + boolean approve = ErpAuditStatus.APPROVE.getStatus().equals(status); + if (approve) { + if (!ErpAuditStatus.PROCESS.getStatus().equals(stockOut.getStatus())) { + throw exception(STOCK_OUT_APPROVE_FAIL); + } + } else { + if (!ErpAuditStatus.APPROVE.getStatus().equals(stockOut.getStatus())) { + throw exception(STOCK_OUT_PROCESS_FAIL); + } } - - int updateCount = stockOutMapper.updateByIdAndStatus(id, stockOut.getStatus(), - new ErpStockOutDO().setStatus(status)); + int updateCount = stockOutMapper.updateByIdAndStatus(id, stockOut.getStatus(), new ErpStockOutDO().setStatus(status)); if (updateCount == 0) { throw exception(approve ? STOCK_OUT_APPROVE_FAIL : STOCK_OUT_PROCESS_FAIL); } - List stockOutItems = stockOutItemMapper.selectListByOutId(id); - operateStockOutEffect(stockOut, stockOutItems, approve, status); - } - - private void operateStockOutEffect(ErpStockOutDO stockOut, List stockOutItems, - boolean approve, Integer status) { - stockOutItems.forEach(stockOutItem -> { - BigDecimal count = approve ? stockOutItem.getCount().negate() : stockOutItem.getCount(); - if (Objects.equals(stockOut.getOutType(), "模具出库")) { - MoldBrandDO moldDO = moldBrandService.getMoldBrand(stockOutItem.getMoldSetId()); - stockRecordService.createStockRecord(new ErpStockRecordCreateReqBO( - stockOutItem.getProductId(), moldDO.getId(), stockOutItem.getWarehouseId(), count, - ErpStockRecordBizTypeEnum.OTHER_OUT.getType(), stockOutItem.getOutId(), stockOutItem.getId(), stockOut.getNo(), stockOut.getOutTime())); - } else { - ErpProductRespVO product = productService.getProduct(stockOutItem.getProductId()); - stockRecordService.createStockRecord(new ErpStockRecordCreateReqBO( - stockOutItem.getProductId(), product.getCategoryId(), stockOutItem.getWarehouseId(), count, - ErpStockRecordBizTypeEnum.getTypeByName(stockOut.getOutType(), status), stockOutItem.getOutId(), stockOutItem.getId(), stockOut.getNo(), stockOut.getOutTime())); - } - }); - - if (Objects.equals(stockOut.getOutType(), "模具出库")) { - for (ErpStockOutItemDO item : stockOutItems) { - if (item.getMoldSetId() != null) { - MoldBrandDO moldDO = moldBrandService.getMoldBrand(item.getMoldSetId()); - if (Objects.equals(moldDO.getStatus(), 3)) { - throw exception(STOCK_ALERADY_OUT, moldDO.getCode() + "-" + moldDO.getName()); - } - moldDO.setStatus(3); - moldBrandService.updateMoldBrand(BeanUtils.toBean(moldDO, MoldBrandSaveReqVO.class)); - } - } + if (approve) { + applyStockOutEffect(stockOut, stockOutItems, bizType); + } else { + cancelStockOutEffect(stockOut, stockOutItems, bizType); } } - private boolean needAudit() { - return !AUDIT_CONFIG_DISABLE_VALUE.equals(configApi.getConfigValueByCategoryAndKey(AUDIT_CONFIG_CATEGORY, AUDIT_CONFIG_KEY)); - } - - private List validateStockOutItems(List list,String outType) { - if (Objects.equals(outType, "模具出库")) { - List moldList = moldBrandService.validMoldList( - convertSet(list, ErpStockOutSaveReqVO.Item::getMoldSetId)); - Map moldMap = convertMap(moldList, MoldBrandDO::getId); - return convertList(list, o -> { - MoldBrandDO moldBrand = moldMap.get(o.getMoldSetId()); - return ErpStockOutItemDO.builder() - .id(null) - .moldSetId(moldBrand.getId()) - .moldSetName(moldBrand.getName()) - .warehouseId(o.getWarehouseId()) - .productId(moldBrand.getId()) - .productUnitId(null) - .productPrice(o.getProductPrice()) - .count(o.getCount()) - .totalPrice(MoneyUtils.priceMultiply(o.getProductPrice(), o.getCount())) - .remark(o.getRemark()) - .build(); - }); - } else { - List productList = productService.validProductList( - convertSet(list, ErpStockOutSaveReqVO.Item::getProductId)); - Map productMap = convertMap(productList, ErpProductDO::getId); - return convertList(list, o -> BeanUtils.toBean(o, ErpStockOutItemDO.class, item -> item - .setProductUnitId(productMap.get(item.getProductId()).getUnitId()) - .setTotalPrice(MoneyUtils.priceMultiply(item.getProductPrice(), item.getCount())))); + @Override + @Transactional(rollbackFor = Exception.class) + public void submitStockOutAudit(ErpStockOutSubmitReqVO submitReqVO) { + ErpStockOutDO stockOut = validateStockOutExists(submitReqVO.getId()); + Long loginUserId = SecurityFrameworkUtils.getLoginUserId(); + if (!Objects.equals(NumberUtils.parseLong(stockOut.getCreator()), loginUserId)) { + throw exception(STOCK_OUT_SUBMIT_FAIL_USER); } + if (!ErpAuditStatus.DRAFT.getStatus().equals(stockOut.getStatus()) + && !ErpAuditStatus.UN_APPROVE.getStatus().equals(stockOut.getStatus())) { + throw exception(STOCK_OUT_SUBMIT_FAIL_STATUS); + } + Long auditUserId = submitReqVO.getAuditUserId() != null ? submitReqVO.getAuditUserId() : stockOut.getAuditUserId(); + if (auditUserId == null) { + throw exception(STOCK_OUT_SUBMIT_FAIL_AUDIT_USER_EMPTY); + } + adminUserApi.validateUser(auditUserId); + Integer fromStatus = stockOut.getStatus(); + ErpStockOutDO updateObj = new ErpStockOutDO() + .setAuditUserId(auditUserId) + .setNeedAudit(true) + .setStatus(ErpAuditStatus.PROCESS.getStatus()); + int updateCount = stockOutMapper.updateByIdAndStatus(stockOut.getId(), fromStatus, updateObj); + if (updateCount == 0) { + throw exception(STOCK_OUT_SUBMIT_FAIL_STATUS); + } + createApproveRecord(stockOut.getId(), ErpStockOutApproveActionEnum.SUBMIT, fromStatus, + ErpAuditStatus.PROCESS.getStatus(), auditUserId, submitReqVO.getRemark()); } - private void updateStockOutItemList(Long id, List newList) { - boolean moldStockOut = CollUtil.isNotEmpty(newList) - && newList.stream().anyMatch(item -> item.getMoldSetId() != null); - if (moldStockOut) { - stockOutItemMapper.deleteByOutId(id); - newList.forEach(o -> { - o.setId(null); - o.setOutId(id); - }); - stockOutItemMapper.insertBatch(newList); - return; + @Override + @Transactional(rollbackFor = Exception.class) + public void auditStockOut(ErpStockOutAuditReqVO auditReqVO) { + ErpStockOutDO stockOut = validateStockOutExists(auditReqVO.getId()); + if (!ErpAuditStatus.PROCESS.getStatus().equals(stockOut.getStatus())) { + throw exception(STOCK_OUT_AUDIT_FAIL_STATUS); } - - List oldList = stockOutItemMapper.selectListByOutId(id); - List> diffList = diffList(oldList, newList, - (oldVal, newVal) -> oldVal.getId().equals(newVal.getId())); - if (CollUtil.isNotEmpty(diffList.get(0))) { - diffList.get(0).forEach(o -> o.setOutId(id)); - stockOutItemMapper.insertBatch(diffList.get(0)); + Long loginUserId = SecurityFrameworkUtils.getLoginUserId(); + if (!Objects.equals(stockOut.getAuditUserId(), loginUserId)) { + throw exception(STOCK_OUT_AUDIT_FAIL_USER); } - if (CollUtil.isNotEmpty(diffList.get(1))) { - stockOutItemMapper.updateBatch(diffList.get(1)); + if (!ErpAuditStatus.APPROVE.getStatus().equals(auditReqVO.getStatus()) + && !ErpAuditStatus.UN_APPROVE.getStatus().equals(auditReqVO.getStatus())) { + throw exception(STOCK_OUT_AUDIT_FAIL_RESULT); } - if (CollUtil.isNotEmpty(diffList.get(2))) { - stockOutItemMapper.deleteBatchIds(convertList(diffList.get(2), ErpStockOutItemDO::getId)); + + Integer fromStatus = stockOut.getStatus(); + int updateCount = stockOutMapper.updateByIdAndStatus(stockOut.getId(), fromStatus, + new ErpStockOutDO().setStatus(auditReqVO.getStatus())); + if (updateCount == 0) { + throw exception(STOCK_OUT_AUDIT_FAIL_STATUS); + } + + List stockOutItems = stockOutItemMapper.selectListByOutId(stockOut.getId()); + if (ErpAuditStatus.APPROVE.getStatus().equals(auditReqVO.getStatus())) { + applyStockOutEffect(stockOut, stockOutItems, null); } + Long targetUserId = NumberUtils.parseLong(stockOut.getCreator()); + createApproveRecord(stockOut.getId(), ErpAuditStatus.APPROVE.getStatus().equals(auditReqVO.getStatus()) + ? ErpStockOutApproveActionEnum.APPROVE : ErpStockOutApproveActionEnum.REJECT, + fromStatus, auditReqVO.getStatus(), targetUserId, auditReqVO.getRemark()); } @Override @Transactional(rollbackFor = Exception.class) public void deleteStockOut(List ids) { - // 1. 校验不处于已审批 List stockOuts = stockOutMapper.selectBatchIds(ids); if (CollUtil.isEmpty(stockOuts)) { return; @@ -257,25 +251,17 @@ public class ErpStockOutServiceImpl implements ErpStockOutService { if (ErpAuditStatus.APPROVE.getStatus().equals(stockOut.getStatus())) { throw exception(STOCK_OUT_DELETE_FAIL_APPROVE, stockOut.getNo()); } + if (ErpAuditStatus.PROCESS.getStatus().equals(stockOut.getStatus())) { + throw exception(STOCK_OUT_DELETE_FAIL_PROCESS, stockOut.getNo()); + } }); - - // 2. 遍历删除,并记录操作日志 stockOuts.forEach(stockOut -> { - // 2.1 删除出库单 stockOutMapper.deleteById(stockOut.getId()); - // 2.2 删除出库单项 stockOutItemMapper.deleteByOutId(stockOut.getId()); + stockOutApproveRecordMapper.deleteByStockOutId(stockOut.getId()); }); } - private ErpStockOutDO validateStockOutExists(Long id) { - ErpStockOutDO stockOut = stockOutMapper.selectById(id); - if (stockOut == null) { - throw exception(STOCK_OUT_NOT_EXISTS); - } - return stockOut; - } - @Override public ErpStockOutDO getStockOut(Long id) { return stockOutMapper.selectById(id); @@ -286,8 +272,6 @@ public class ErpStockOutServiceImpl implements ErpStockOutService { return stockOutMapper.selectPage(pageReqVO); } - // ==================== 出库项 ==================== - @Override public List getStockOutItemListByOutId(Long outId) { return stockOutItemMapper.selectListByOutId(outId); @@ -300,9 +284,14 @@ public class ErpStockOutServiceImpl implements ErpStockOutService { } return stockOutItemMapper.selectListByOutIds(outIds); } + + @Override + public List getStockOutApproveRecordList(Long stockOutId) { + return stockOutApproveRecordMapper.selectListByStockOutId(stockOutId); + } + @Override - public - List selectByOutType(List outTypes){ + public List selectByOutType(List outTypes) { return stockOutMapper.selectByOutType(outTypes); } @@ -313,5 +302,125 @@ public class ErpStockOutServiceImpl implements ErpStockOutService { stockOutMapper.updateById(stockOut); } + private ErpStockOutDO validateStockOutExists(Long id) { + ErpStockOutDO stockOut = stockOutMapper.selectById(id); + if (stockOut == null) { + throw exception(STOCK_OUT_NOT_EXISTS); + } + return stockOut; + } + + private void applyStockOutEffect(ErpStockOutDO stockOut, List stockOutItems, Integer bizType) { + operateStockOutEffect(stockOut, stockOutItems, true, bizType); + } + + private void cancelStockOutEffect(ErpStockOutDO stockOut, List stockOutItems, Integer bizType) { + operateStockOutEffect(stockOut, stockOutItems, false, bizType); + } + + private void operateStockOutEffect(ErpStockOutDO stockOut, List stockOutItems, + boolean approve, Integer bizType) { + stockOutItems.forEach(stockOutItem -> { + BigDecimal count = approve ? stockOutItem.getCount().negate() : stockOutItem.getCount(); + if (Objects.equals(stockOut.getOutType(), "模具出库")) { + MoldBrandDO moldDO = moldBrandService.getMoldBrand(stockOutItem.getMoldSetId()); + Integer recordBizType = bizType != null ? bizType + : (approve ? ErpStockRecordBizTypeEnum.OTHER_OUT.getType() + : ErpStockRecordBizTypeEnum.OTHER_OUT_CANCEL.getType()); + stockRecordService.createStockRecord(new ErpStockRecordCreateReqBO( + stockOutItem.getProductId(), moldDO.getId(), stockOutItem.getWarehouseId(), count, + recordBizType, stockOutItem.getOutId(), stockOutItem.getId(), stockOut.getNo(), stockOut.getOutTime())); + if (approve && itemNeedUpdateMoldStatus(moldDO)) { + moldDO.setStatus(3); + moldBrandService.updateMoldBrand(BeanUtils.toBean(moldDO, MoldBrandSaveReqVO.class)); + } + } else { + ErpProductRespVO product = productService.getProduct(stockOutItem.getProductId()); + Integer recordBizType = bizType != null ? bizType + : (approve ? ErpStockRecordBizTypeEnum.getTypeByName(stockOut.getOutType()) + : ErpStockRecordBizTypeEnum.getTypeByName(stockOut.getOutType(), 10)); + stockRecordService.createStockRecord(new ErpStockRecordCreateReqBO( + stockOutItem.getProductId(), product.getCategoryId(), stockOutItem.getWarehouseId(), count, + recordBizType, stockOutItem.getOutId(), stockOutItem.getId(), stockOut.getNo(), stockOut.getOutTime())); + } + }); + } + + private boolean itemNeedUpdateMoldStatus(MoldBrandDO moldDO) { + if (Objects.equals(moldDO.getStatus(), 3)) { + throw exception(STOCK_ALERADY_OUT, moldDO.getCode() + "-" + moldDO.getName()); + } + return true; + } + + private boolean needAudit() { + return !AUDIT_CONFIG_DISABLE_VALUE.equals(configApi.getConfigValueByCategoryAndKey(AUDIT_CONFIG_CATEGORY, AUDIT_CONFIG_KEY)); + } + + private void createApproveRecord(Long stockOutId, ErpStockOutApproveActionEnum action, Integer fromStatus, + Integer toStatus, Long targetUserId, String remark) { + stockOutApproveRecordMapper.insert(ErpStockOutApproveRecordDO.builder() + .stockOutId(stockOutId) + .actionType(action.getActionType()) + .fromStatus(fromStatus) + .toStatus(toStatus) + .targetUserId(targetUserId) + .remark(remark) + .build()); + } + + private List validateStockOutItems(List list, String outType) { + if (Objects.equals(outType, "模具出库")) { + List moldList = moldBrandService.validMoldList(convertSet(list, ErpStockOutSaveReqVO.Item::getMoldSetId)); + Map moldMap = convertMap(moldList, MoldBrandDO::getId); + return convertList(list, item -> { + MoldBrandDO moldBrand = moldMap.get(item.getMoldSetId()); + return ErpStockOutItemDO.builder() + .id(item.getId()) + .moldSetId(moldBrand.getId()) + .moldSetName(moldBrand.getName()) + .warehouseId(item.getWarehouseId()) + .productId(moldBrand.getId()) + .productUnitId(null) + .productPrice(item.getProductPrice()) + .count(item.getCount()) + .totalPrice(MoneyUtils.priceMultiply(item.getProductPrice(), item.getCount())) + .remark(item.getRemark()) + .build(); + }); + } + List productList = productService.validProductList(convertSet(list, ErpStockOutSaveReqVO.Item::getProductId)); + Map productMap = convertMap(productList, ErpProductDO::getId); + return convertList(list, item -> BeanUtils.toBean(item, ErpStockOutItemDO.class, target -> target + .setProductUnitId(productMap.get(target.getProductId()).getUnitId()) + .setTotalPrice(MoneyUtils.priceMultiply(target.getProductPrice(), target.getCount())))); + } + + private void updateStockOutItemList(Long id, List newList) { + boolean moldStockOut = CollUtil.isNotEmpty(newList) + && newList.stream().anyMatch(item -> item.getMoldSetId() != null); + if (moldStockOut) { + stockOutItemMapper.deleteByOutId(id); + newList.forEach(item -> { + item.setId(null); + item.setOutId(id); + }); + stockOutItemMapper.insertBatch(newList); + return; + } + List oldList = stockOutItemMapper.selectListByOutId(id); + List> diffList = diffList(oldList, newList, + (oldVal, newVal) -> oldVal.getId().equals(newVal.getId())); + if (CollUtil.isNotEmpty(diffList.get(0))) { + diffList.get(0).forEach(item -> item.setOutId(id)); + stockOutItemMapper.insertBatch(diffList.get(0)); + } + if (CollUtil.isNotEmpty(diffList.get(1))) { + stockOutItemMapper.updateBatch(diffList.get(1)); + } + if (CollUtil.isNotEmpty(diffList.get(2))) { + stockOutItemMapper.deleteBatchIds(convertList(diffList.get(2), ErpStockOutItemDO::getId)); + } + } } diff --git a/yudao-module-erp/yudao-module-erp-biz/src/main/resources/mapper/mold/MoldOperateQueryMapper.xml b/yudao-module-erp/yudao-module-erp-biz/src/main/resources/mapper/mold/MoldOperateQueryMapper.xml index b4f5bf798..7686ab819 100644 --- a/yudao-module-erp/yudao-module-erp-biz/src/main/resources/mapper/mold/MoldOperateQueryMapper.xml +++ b/yudao-module-erp/yudao-module-erp-biz/src/main/resources/mapper/mold/MoldOperateQueryMapper.xml @@ -13,7 +13,7 @@ ) - ORDER BY operate_time DESC, id DESC + ORDER BY id DESC