fix:修改出库单据接口

main
HuangHuiKang 1 week ago
parent 16ebe147af
commit 5d09204f8f

@ -27,7 +27,7 @@ public interface MoldTicketManagementMapper extends BaseMapperX<MoldTicketManage
ticketManagementDOLambdaQueryWrapperX
.eqIfPresent(MoldTicketManagementDO::getTaskId, reqVO.getTaskId())
.eqIfPresent(MoldTicketManagementDO::getPlanId, reqVO.getPlanId())
.eqIfPresent(MoldTicketManagementDO::getPlanNo, reqVO.getPlanNo())
.likeIfPresent(MoldTicketManagementDO::getPlanNo, reqVO.getPlanNo())
.likeIfPresent(MoldTicketManagementDO::getMoldName, reqVO.getMoldName())
.eqIfPresent(MoldTicketManagementDO::getPlanType, reqVO.getPlanType())
.likeIfPresent(MoldTicketManagementDO::getConfigName, reqVO.getConfigName())

@ -128,6 +128,14 @@ public interface ErrorCodeConstants {
ErrorCode STOCK_OUT_APPROVE_FAIL = new ErrorCode(1_030_402_003, "审核失败,只有未审核的出库单才能审核");
ErrorCode STOCK_OUT_NO_EXISTS = new ErrorCode(1_030_402_004, "生成出库单失败,请重新提交");
ErrorCode STOCK_OUT_UPDATE_FAIL_APPROVE = new ErrorCode(1_030_402_005, "其它出库单({})已审核,无法修改");
ErrorCode STOCK_OUT_UPDATE_FAIL_PROCESS = new ErrorCode(1_030_402_006, "其它出库单({})审核中,无法修改");
ErrorCode STOCK_OUT_DELETE_FAIL_PROCESS = new ErrorCode(1_030_402_007, "其它出库单({})审核中,无法删除");
ErrorCode STOCK_OUT_SUBMIT_FAIL_STATUS = new ErrorCode(1_030_402_008, "提交审核失败,只有待提交或已驳回的出库单才能提交审核");
ErrorCode STOCK_OUT_SUBMIT_FAIL_USER = new ErrorCode(1_030_402_009, "提交审核失败,只有创建人才能提交审核");
ErrorCode STOCK_OUT_SUBMIT_FAIL_AUDIT_USER_EMPTY = new ErrorCode(1_030_402_010, "提交审核失败,请选择审核人");
ErrorCode STOCK_OUT_AUDIT_FAIL_STATUS = new ErrorCode(1_030_402_011, "审核失败,只有审核中的出库单才能审核");
ErrorCode STOCK_OUT_AUDIT_FAIL_USER = new ErrorCode(1_030_402_012, "审核失败,当前用户不是指定审核人");
ErrorCode STOCK_OUT_AUDIT_FAIL_RESULT = new ErrorCode(1_030_402_013, "审核失败,审核结果只支持通过或驳回");
// ========== ERP 库存调拨单 1-030-403-000 ==========
ErrorCode STOCK_MOVE_NOT_EXISTS = new ErrorCode(1_030_402_000, "库存调拨单不存在");

@ -0,0 +1,17 @@
package cn.iocoder.yudao.module.erp.enums.stock;
import lombok.Getter;
import lombok.RequiredArgsConstructor;
@RequiredArgsConstructor
@Getter
public enum ErpStockOutApproveActionEnum {
SUBMIT("SUBMIT"),
APPROVE("APPROVE"),
REJECT("REJECT"),
AUTO_APPROVE("AUTO_APPROVE");
private final String actionType;
}

@ -6,18 +6,22 @@ import cn.iocoder.yudao.framework.common.pojo.CommonResult;
import cn.iocoder.yudao.framework.common.pojo.PageParam;
import cn.iocoder.yudao.framework.common.pojo.PageResult;
import cn.iocoder.yudao.framework.common.util.collection.MapUtils;
import cn.iocoder.yudao.framework.common.util.number.NumberUtils;
import cn.iocoder.yudao.framework.common.util.object.BeanUtils;
import cn.iocoder.yudao.framework.excel.core.util.ExcelUtils;
import cn.iocoder.yudao.framework.ratelimiter.core.annotation.RateLimiter;
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.ErpStockOutApproveRecordRespVO;
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.ErpStockOutRespVO;
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.controller.admin.stock.vo.out.StockOutTypeEnum;
import cn.iocoder.yudao.module.erp.dal.dataobject.sale.ErpCustomerDO;
import cn.iocoder.yudao.module.erp.dal.dataobject.stock.ErpStockDO;
import cn.iocoder.yudao.module.erp.dal.dataobject.stock.ErpStockInItemDO;
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.service.mold.MoldBrandService;
@ -34,7 +38,14 @@ import io.swagger.v3.oas.annotations.tags.Tag;
import org.apache.commons.lang3.StringUtils;
import org.springframework.security.access.prepost.PreAuthorize;
import org.springframework.validation.annotation.Validated;
import org.springframework.web.bind.annotation.*;
import org.springframework.web.bind.annotation.DeleteMapping;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.PutMapping;
import org.springframework.web.bind.annotation.RequestBody;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.RestController;
import javax.annotation.Resource;
import javax.servlet.http.HttpServletResponse;
@ -42,15 +53,17 @@ import javax.validation.Valid;
import java.io.IOException;
import java.math.BigDecimal;
import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
import java.util.Map;
import java.util.Objects;
import java.util.concurrent.TimeUnit;
import java.util.stream.Stream;
import static cn.iocoder.yudao.framework.apilog.core.enums.OperateTypeEnum.EXPORT;
import static cn.iocoder.yudao.framework.common.pojo.CommonResult.success;
import static cn.iocoder.yudao.framework.common.util.collection.CollectionUtils.convertList;
import static cn.iocoder.yudao.framework.common.util.collection.CollectionUtils.convertMultiMap;
import static cn.iocoder.yudao.framework.common.util.collection.CollectionUtils.convertListByFlatMap;
import static cn.iocoder.yudao.framework.common.util.collection.CollectionUtils.convertSet;
@Tag(name = "管理后台 - ERP 其它出库单")
@ -67,12 +80,10 @@ public class ErpStockOutController {
private ErpProductService productService;
@Resource
private ErpCustomerService customerService;
@Resource
private MoldBrandService moldBrandService;
@Resource
private MoldService moldService;
@Resource
private AdminUserApi adminUserApi;
@ -96,19 +107,43 @@ public class ErpStockOutController {
@PreAuthorize("@ss.hasPermission('erp:stock-out:update-status')")
@RateLimiter(count = 1, timeUnit = TimeUnit.SECONDS)
public CommonResult<Boolean> 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<Boolean> 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<Boolean> 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<List<ErpStockOutApproveRecordRespVO>> 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<Boolean> 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<ErpStockOutItemDO> stockOutItemList = stockOutService.getStockOutItemListByOutId(id);
if (Objects.equals(stockOut.getOutType(), "模具出库")) {
Map<Long, MoldBrandDO> moldMap = moldBrandService.getMoldVOMap(
convertSet(stockOutItemList, ErpStockOutItemDO::getMoldSetId));
Map<Long, List<cn.iocoder.yudao.module.common.dal.dataobject.mold.MoldDO>> 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<Long, ErpProductRespVO> 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<PageResult<ErpStockOutRespVO>> getStockOutPage(@Valid ErpStockOutPageReqVO pageReqVO) {
if(StringUtils.isEmpty(pageReqVO.getOutType())){
List<String> list = new ArrayList<>();
list.add(StockOutTypeEnum..getValue());
list.add(StockOutTypeEnum..getValue());
list.add(StockOutTypeEnum..getValue());
list.add(StockOutTypeEnum..getValue());
pageReqVO.setOutTypeList(list);
}
PageResult<ErpStockOutDO> 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<ErpStockOutRespVO> 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<String> list = new ArrayList<>();
list.add(StockOutTypeEnum..getValue());
list.add(StockOutTypeEnum..getValue());
list.add(StockOutTypeEnum..getValue());
list.add(StockOutTypeEnum..getValue());
pageReqVO.setOutTypeList(list);
}
}
private PageResult<ErpStockOutRespVO> buildStockOutVOPageResult(PageResult<ErpStockOutDO> pageResult) {
if (CollUtil.isEmpty(pageResult.getList())) {
return PageResult.empty(pageResult.getTotal());
}
List<ErpStockOutItemDO> stockOutItemList = stockOutService.getStockOutItemListByOutIds(
convertSet(pageResult.getList(), ErpStockOutDO::getId));
Map<Long, List<ErpStockOutItemDO>> stockOutItemMap = convertMultiMap(stockOutItemList, ErpStockOutItemDO::getOutId);
Map<Long, ErpProductRespVO> productMap = productService.getProductVOMap(
convertSet(stockOutItemList, ErpStockOutItemDO::getProductId));
Map<Long, ErpCustomerDO> customerMap = customerService.getCustomerMap(
convertSet(pageResult.getList(), ErpStockOutDO::getCustomerId));
Map<Long, AdminUserRespDTO> userMap = adminUserApi.getUserMap(
convertSet(pageResult.getList(), stockOut -> Long.parseLong(stockOut.getCreator())));
Map<Long, AdminUserRespDTO> responserMap = adminUserApi.getUserMap(
convertSet(pageResult.getList(), ErpStockOutDO::getResponserId));
Map<Long, MoldBrandDO> moldMap = moldBrandService.getMoldVOMap(
convertSet(stockOutItemList, ErpStockOutItemDO::getMoldSetId));
Map<Long, List<cn.iocoder.yudao.module.common.dal.dataobject.mold.MoldDO>> moldListMap = moldService.getMoldListMapByBrandIds(
convertSet(stockOutItemList, ErpStockOutItemDO::getMoldSetId));
List<ErpStockOutRespVO> 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<ErpStockOutItemDO> 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<ErpStockOutItemDO> stockOutItemList,
List<ErpStockOutApproveRecordDO> approveRecords) {
ErpStockOutRespVO stockOutVO = BeanUtils.toBean(stockOut, ErpStockOutRespVO.class);
Map<Long, AdminUserRespDTO> 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<Long, MoldBrandDO> moldMap = moldBrandService.getMoldVOMap(
convertSet(stockOutItemList, ErpStockOutItemDO::getMoldSetId));
Map<Long, List<cn.iocoder.yudao.module.common.dal.dataobject.mold.MoldDO>> 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<Long, ErpProductRespVO> 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<Long, ErpCustomerDO> 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<ErpStockOutApproveRecordRespVO> buildApproveRecordRespList(List<ErpStockOutApproveRecordDO> records) {
if (CollUtil.isEmpty(records)) {
return new ArrayList<>();
}
Map<Long, AdminUserRespDTO> 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<PageResult<ErpStockOutRespVO>> getMesStockOutPage(@Valid ErpStockOutPageReqVO pageReqVO) {
pageReqVO.setOutType(StockOutTypeEnum..getValue());
PageResult<ErpStockOutDO> pageResult = stockOutService.getStockOutPage(pageReqVO);
return success(buildStockOutVOPageResult(pageResult));
return success(buildStockOutVOPageResult(stockOutService.getStockOutPage(pageReqVO)));
}
}
}

@ -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;
}

@ -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;
}

@ -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<String> 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;
}
}

@ -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<Item> items;
@Schema(description = "审核记录")
private List<ErpStockOutApproveRecordRespVO> 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<MoldDO> moldList;
}
}
}

@ -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<Item> 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;
}
}
}

@ -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;
}

@ -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);
}
}
}

@ -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;
}

@ -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;
}
}

@ -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<ErpStockOutApproveRecordDO> {
default List<ErpStockOutApproveRecordDO> selectListByStockOutId(Long stockOutId) {
return selectList(new LambdaQueryWrapperX<ErpStockOutApproveRecordDO>()
.eq(ErpStockOutApproveRecordDO::getStockOutId, stockOutId)
.orderByAsc(ErpStockOutApproveRecordDO::getId));
}
default int deleteByStockOutId(Long stockOutId) {
return delete(ErpStockOutApproveRecordDO::getStockOutId, stockOutId);
}
}

@ -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<ErpStockOutDO> {
@ -36,36 +29,35 @@ public interface ErpStockOutMapper extends BaseMapperX<ErpStockOutDO> {
.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<Long> 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<ErpStockOutDO>()
.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<ErpStockOutDO> selectByOutType(List<String> outTypes){
return selectList(new QueryWrapper<ErpStockOutDO>()
.in("out_type" ,outTypes));
default List<ErpStockOutDO> selectByOutType(List<String> outTypes) {
return selectList(new QueryWrapper<ErpStockOutDO>().in("out_type", outTypes));
}
}
}

@ -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<ErpStockOutItemDO> getStockOutItemListByOutIds(Collection<Long> outIds);
List<ErpStockOutApproveRecordDO> getStockOutApproveRecordList(Long stockOutId);
List<ErpStockOutDO> selectByOutType(List<String> outTypes);
void updateMoldStatus(Long id, Integer status);
}
}

@ -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<ErpStockOutItemDO> stockOutItems = validateStockOutItems(createReqVO.getItems(),createReqVO.getOutType());
// 1.2 校验客户
//customerService.validateCustomer(createReqVO.getCustomerId());
// 1.3 生成出库单号,并校验唯一性
List<ErpStockOutItemDO> 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<ErpStockOutItemDO> 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<ErpStockOutItemDO> 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<ErpStockOutItemDO> stockOutItems = stockOutItemMapper.selectListByOutId(id);
operateStockOutEffect(stockOut, stockOutItems, approve, status);
}
private void operateStockOutEffect(ErpStockOutDO stockOut, List<ErpStockOutItemDO> 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<ErpStockOutItemDO> validateStockOutItems(List<ErpStockOutSaveReqVO.Item> list,String outType) {
if (Objects.equals(outType, "模具出库")) {
List<MoldBrandDO> moldList = moldBrandService.validMoldList(
convertSet(list, ErpStockOutSaveReqVO.Item::getMoldSetId));
Map<Long, MoldBrandDO> 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<ErpProductDO> productList = productService.validProductList(
convertSet(list, ErpStockOutSaveReqVO.Item::getProductId));
Map<Long, ErpProductDO> 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<ErpStockOutItemDO> 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<ErpStockOutItemDO> oldList = stockOutItemMapper.selectListByOutId(id);
List<List<ErpStockOutItemDO>> 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<ErpStockOutItemDO> 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<Long> ids) {
// 1. 校验不处于已审批
List<ErpStockOutDO> 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<ErpStockOutItemDO> getStockOutItemListByOutId(Long outId) {
return stockOutItemMapper.selectListByOutId(outId);
@ -300,9 +284,14 @@ public class ErpStockOutServiceImpl implements ErpStockOutService {
}
return stockOutItemMapper.selectListByOutIds(outIds);
}
@Override
public List<ErpStockOutApproveRecordDO> getStockOutApproveRecordList(Long stockOutId) {
return stockOutApproveRecordMapper.selectListByStockOutId(stockOutId);
}
@Override
public
List<ErpStockOutDO> selectByOutType(List<String> outTypes){
public List<ErpStockOutDO> selectByOutType(List<String> 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<ErpStockOutItemDO> stockOutItems, Integer bizType) {
operateStockOutEffect(stockOut, stockOutItems, true, bizType);
}
private void cancelStockOutEffect(ErpStockOutDO stockOut, List<ErpStockOutItemDO> stockOutItems, Integer bizType) {
operateStockOutEffect(stockOut, stockOutItems, false, bizType);
}
private void operateStockOutEffect(ErpStockOutDO stockOut, List<ErpStockOutItemDO> 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<ErpStockOutItemDO> validateStockOutItems(List<ErpStockOutSaveReqVO.Item> list, String outType) {
if (Objects.equals(outType, "模具出库")) {
List<MoldBrandDO> moldList = moldBrandService.validMoldList(convertSet(list, ErpStockOutSaveReqVO.Item::getMoldSetId));
Map<Long, MoldBrandDO> 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<ErpProductDO> productList = productService.validProductList(convertSet(list, ErpStockOutSaveReqVO.Item::getProductId));
Map<Long, ErpProductDO> 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<ErpStockOutItemDO> 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<ErpStockOutItemDO> oldList = stockOutItemMapper.selectListByOutId(id);
List<List<ErpStockOutItemDO>> 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));
}
}
}

@ -13,7 +13,7 @@
</foreach>
)
</if>
ORDER BY operate_time DESC, id DESC
ORDER BY id DESC
</select>
</mapper>

Loading…
Cancel
Save