fix:修改出库单据接口

main
HuangHuiKang 1 week ago
parent 16ebe147af
commit 5d09204f8f

@ -27,7 +27,7 @@ public interface MoldTicketManagementMapper extends BaseMapperX<MoldTicketManage
ticketManagementDOLambdaQueryWrapperX ticketManagementDOLambdaQueryWrapperX
.eqIfPresent(MoldTicketManagementDO::getTaskId, reqVO.getTaskId()) .eqIfPresent(MoldTicketManagementDO::getTaskId, reqVO.getTaskId())
.eqIfPresent(MoldTicketManagementDO::getPlanId, reqVO.getPlanId()) .eqIfPresent(MoldTicketManagementDO::getPlanId, reqVO.getPlanId())
.eqIfPresent(MoldTicketManagementDO::getPlanNo, reqVO.getPlanNo()) .likeIfPresent(MoldTicketManagementDO::getPlanNo, reqVO.getPlanNo())
.likeIfPresent(MoldTicketManagementDO::getMoldName, reqVO.getMoldName()) .likeIfPresent(MoldTicketManagementDO::getMoldName, reqVO.getMoldName())
.eqIfPresent(MoldTicketManagementDO::getPlanType, reqVO.getPlanType()) .eqIfPresent(MoldTicketManagementDO::getPlanType, reqVO.getPlanType())
.likeIfPresent(MoldTicketManagementDO::getConfigName, reqVO.getConfigName()) .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_APPROVE_FAIL = new ErrorCode(1_030_402_003, "审核失败,只有未审核的出库单才能审核");
ErrorCode STOCK_OUT_NO_EXISTS = new ErrorCode(1_030_402_004, "生成出库单失败,请重新提交"); 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_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 ========== // ========== ERP 库存调拨单 1-030-403-000 ==========
ErrorCode STOCK_MOVE_NOT_EXISTS = new ErrorCode(1_030_402_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.PageParam;
import cn.iocoder.yudao.framework.common.pojo.PageResult; import cn.iocoder.yudao.framework.common.pojo.PageResult;
import cn.iocoder.yudao.framework.common.util.collection.MapUtils; 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.common.util.object.BeanUtils;
import cn.iocoder.yudao.framework.excel.core.util.ExcelUtils; import cn.iocoder.yudao.framework.excel.core.util.ExcelUtils;
import cn.iocoder.yudao.framework.ratelimiter.core.annotation.RateLimiter; import cn.iocoder.yudao.framework.ratelimiter.core.annotation.RateLimiter;
import cn.iocoder.yudao.module.common.dal.dataobject.mold.MoldBrandDO; 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.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.ErpStockOutPageReqVO;
import cn.iocoder.yudao.module.erp.controller.admin.stock.vo.out.ErpStockOutRespVO; 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.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.controller.admin.stock.vo.out.StockOutTypeEnum;
import cn.iocoder.yudao.module.erp.dal.dataobject.sale.ErpCustomerDO; 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.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.ErpStockOutDO;
import cn.iocoder.yudao.module.erp.dal.dataobject.stock.ErpStockOutItemDO; import cn.iocoder.yudao.module.erp.dal.dataobject.stock.ErpStockOutItemDO;
import cn.iocoder.yudao.module.erp.service.mold.MoldBrandService; 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.apache.commons.lang3.StringUtils;
import org.springframework.security.access.prepost.PreAuthorize; import org.springframework.security.access.prepost.PreAuthorize;
import org.springframework.validation.annotation.Validated; 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.annotation.Resource;
import javax.servlet.http.HttpServletResponse; import javax.servlet.http.HttpServletResponse;
@ -42,15 +53,17 @@ import javax.validation.Valid;
import java.io.IOException; import java.io.IOException;
import java.math.BigDecimal; import java.math.BigDecimal;
import java.util.ArrayList; import java.util.ArrayList;
import java.util.Collections;
import java.util.List; import java.util.List;
import java.util.Map; import java.util.Map;
import java.util.Objects; import java.util.Objects;
import java.util.concurrent.TimeUnit; 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.apilog.core.enums.OperateTypeEnum.EXPORT;
import static cn.iocoder.yudao.framework.common.pojo.CommonResult.success; 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.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; import static cn.iocoder.yudao.framework.common.util.collection.CollectionUtils.convertSet;
@Tag(name = "管理后台 - ERP 其它出库单") @Tag(name = "管理后台 - ERP 其它出库单")
@ -67,12 +80,10 @@ public class ErpStockOutController {
private ErpProductService productService; private ErpProductService productService;
@Resource @Resource
private ErpCustomerService customerService; private ErpCustomerService customerService;
@Resource @Resource
private MoldBrandService moldBrandService; private MoldBrandService moldBrandService;
@Resource @Resource
private MoldService moldService; private MoldService moldService;
@Resource @Resource
private AdminUserApi adminUserApi; private AdminUserApi adminUserApi;
@ -96,19 +107,43 @@ public class ErpStockOutController {
@PreAuthorize("@ss.hasPermission('erp:stock-out:update-status')") @PreAuthorize("@ss.hasPermission('erp:stock-out:update-status')")
@RateLimiter(count = 1, timeUnit = TimeUnit.SECONDS) @RateLimiter(count = 1, timeUnit = TimeUnit.SECONDS)
public CommonResult<Boolean> updateStockOutStatus(@RequestParam("id") Long id, public CommonResult<Boolean> updateStockOutStatus(@RequestParam("id") Long id,
@RequestParam("status") Integer status, @RequestParam("status") Integer status,
@RequestParam(name = "status",required = false) Integer bizType) { @RequestParam(name = "bizType", required = false) Integer bizType) {
stockOutService.updateStockOutStatus(id, status,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); 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") @PutMapping("/update-mold-status")
@Operation(summary = "更新模具出库单的状态") @Operation(summary = "更新模具出库单的状态")
@PreAuthorize("@ss.hasPermission('erp:stock-out:update-status')") @PreAuthorize("@ss.hasPermission('erp:stock-out:update-status')")
@RateLimiter(count = 1, timeUnit = TimeUnit.SECONDS) @RateLimiter(count = 1, timeUnit = TimeUnit.SECONDS)
public CommonResult<Boolean> updateMoldStatus(@RequestParam("id") Long id, public CommonResult<Boolean> updateMoldStatus(@RequestParam("id") Long id,
@RequestParam("status") Integer status) { @RequestParam("status") Integer status) {
stockOutService.updateMoldStatus(id, status); stockOutService.updateMoldStatus(id, status);
return success(true); return success(true);
} }
@ -131,113 +166,111 @@ public class ErpStockOutController {
if (stockOut == null) { if (stockOut == null) {
return success(null); return success(null);
} }
List<ErpStockOutItemDO> stockOutItemList = stockOutService.getStockOutItemListByOutId(id); return success(buildStockOutRespVO(stockOut,
if (Objects.equals(stockOut.getOutType(), "模具出库")) { stockOutService.getStockOutItemListByOutId(id),
Map<Long, MoldBrandDO> moldMap = moldBrandService.getMoldVOMap( stockOutService.getStockOutApproveRecordList(id)));
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()));
}))));
}
} }
@GetMapping("/page") @GetMapping("/page")
@Operation(summary = "获得其它出库单分页") @Operation(summary = "获得其它出库单分页")
@PreAuthorize("@ss.hasPermission('erp:stock-out:query')") @PreAuthorize("@ss.hasPermission('erp:stock-out:query')")
public CommonResult<PageResult<ErpStockOutRespVO>> getStockOutPage(@Valid ErpStockOutPageReqVO pageReqVO) { public CommonResult<PageResult<ErpStockOutRespVO>> getStockOutPage(@Valid ErpStockOutPageReqVO pageReqVO) {
if(StringUtils.isEmpty(pageReqVO.getOutType())){ fillPageReqDefault(pageReqVO);
List<String> list = new ArrayList<>(); return success(buildStockOutVOPageResult(stockOutService.getStockOutPage(pageReqVO)));
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));
} }
@GetMapping("/export-excel") @GetMapping("/export-excel")
@Operation(summary = "导出其它出库单 Excel") @Operation(summary = "导出其它出库单 Excel")
@PreAuthorize("@ss.hasPermission('erp:stock-out:export')") @PreAuthorize("@ss.hasPermission('erp:stock-out:export')")
@ApiAccessLog(operateType = EXPORT) @ApiAccessLog(operateType = EXPORT)
public void exportStockOutExcel(@Valid ErpStockOutPageReqVO pageReqVO, public void exportStockOutExcel(@Valid ErpStockOutPageReqVO pageReqVO,
HttpServletResponse response) throws IOException { HttpServletResponse response) throws IOException {
fillPageReqDefault(pageReqVO);
pageReqVO.setPageSize(PageParam.PAGE_SIZE_NONE); pageReqVO.setPageSize(PageParam.PAGE_SIZE_NONE);
List<ErpStockOutRespVO> list = buildStockOutVOPageResult(stockOutService.getStockOutPage(pageReqVO)).getList(); List<ErpStockOutRespVO> list = buildStockOutVOPageResult(stockOutService.getStockOutPage(pageReqVO)).getList();
// 导出 Excel
ExcelUtils.write(response, "其它出库单.xls", "数据", ErpStockOutRespVO.class, list); 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) { private PageResult<ErpStockOutRespVO> buildStockOutVOPageResult(PageResult<ErpStockOutDO> pageResult) {
if (CollUtil.isEmpty(pageResult.getList())) { if (CollUtil.isEmpty(pageResult.getList())) {
return PageResult.empty(pageResult.getTotal()); return PageResult.empty(pageResult.getTotal());
} }
List<ErpStockOutItemDO> stockOutItemList = stockOutService.getStockOutItemListByOutIds( List<ErpStockOutRespVO> list = convertList(pageResult.getList(), stockOut -> buildStockOutRespVO(
convertSet(pageResult.getList(), ErpStockOutDO::getId)); stockOut, stockOutService.getStockOutItemListByOutId(stockOut.getId()), Collections.emptyList()));
Map<Long, List<ErpStockOutItemDO>> stockOutItemMap = convertMultiMap(stockOutItemList, ErpStockOutItemDO::getOutId); return new PageResult<>(list, pageResult.getTotal());
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));
return BeanUtils.toBean(pageResult, ErpStockOutRespVO.class, stockOut -> { private ErpStockOutRespVO buildStockOutRespVO(ErpStockOutDO stockOut, List<ErpStockOutItemDO> stockOutItemList,
if (Objects.equals(stockOut.getOutType(), "模具出库")) { List<ErpStockOutApproveRecordDO> approveRecords) {
List<ErpStockOutItemDO> itemDOS = stockOutItemMap.get(stockOut.getId()); ErpStockOutRespVO stockOutVO = BeanUtils.toBean(stockOut, ErpStockOutRespVO.class);
stockOut.setItems(convertList(itemDOS, source -> { Map<Long, AdminUserRespDTO> userMap = adminUserApi.getUserMap(convertListByFlatMap(
ErpStockOutRespVO.Item item = BeanUtils.toBean(source, ErpStockOutRespVO.Item.class); Collections.singletonList(stockOut), item -> Stream.of(NumberUtils.parseLong(item.getCreator()),
item.setMoldSetId(source.getMoldSetId()); item.getResponserId(), item.getAuditUserId())));
item.setMoldSetName(source.getMoldSetName()); MapUtils.findAndThen(userMap, NumberUtils.parseLong(stockOut.getCreator()), user -> stockOutVO.setCreatorName(user.getNickname()));
item.setMoldList(moldListMap.getOrDefault(source.getMoldSetId(), new ArrayList<>())); MapUtils.findAndThen(userMap, stockOut.getResponserId(), user -> stockOutVO.setResponserName(user.getNickname()));
MapUtils.findAndThen(moldMap, source.getMoldSetId(), mold -> item.setMoldSetName(mold.getName()) MapUtils.findAndThen(userMap, stockOut.getAuditUserId(), user -> stockOutVO.setAuditUserName(user.getNickname()));
.setProductName(mold.getName())
.setProductBarCode(mold.getCode())); if (Objects.equals(stockOut.getOutType(), "模具出库")) {
return item; Map<Long, MoldBrandDO> moldMap = moldBrandService.getMoldVOMap(
})); convertSet(stockOutItemList, ErpStockOutItemDO::getMoldSetId));
stockOut.setMoldSetNames(CollUtil.join(stockOut.getItems(), ",", ErpStockOutRespVO.Item::getMoldSetName)); Map<Long, List<cn.iocoder.yudao.module.common.dal.dataobject.mold.MoldDO>> moldListMap = moldService.getMoldListMapByBrandIds(
stockOut.setProductNames(stockOut.getMoldSetNames()); convertSet(stockOutItemList, ErpStockOutItemDO::getMoldSetId));
} else { stockOutVO.setItems(convertList(stockOutItemList, source -> {
stockOut.setItems(BeanUtils.toBean(stockOutItemMap.get(stockOut.getId()), ErpStockOutRespVO.Item.class, ErpStockOutRespVO.Item item = BeanUtils.toBean(source, ErpStockOutRespVO.Item.class);
item -> MapUtils.findAndThen(productMap, item.getProductId(), product -> item.setProductName(product.getName()) ErpStockDO stock = stockService.getStock(source.getMoldSetId(), source.getWarehouseId());
.setProductBarCode(product.getBarCode()).setProductUnitName(product.getUnitName())))); item.setStockCount(stock != null ? stock.getCount() : BigDecimal.ZERO);
stockOut.setProductNames(CollUtil.join(stockOut.getItems(), ",", ErpStockOutRespVO.Item::getProductName)); item.setMoldList(moldListMap.getOrDefault(source.getMoldSetId(), new ArrayList<>()));
} MapUtils.findAndThen(moldMap, source.getMoldSetId(), mold -> {
MapUtils.findAndThen(customerMap, stockOut.getCustomerId(), customer -> stockOut.setCustomerName(customer.getName())); item.setMoldSetName(mold.getName());
MapUtils.findAndThen(userMap, Long.parseLong(stockOut.getCreator()), user -> stockOut.setCreatorName(user.getNickname())); item.setProductName(mold.getName());
MapUtils.findAndThen(responserMap, stockOut.getResponserId(), user -> stockOut.setResponserName(user.getNickname())); 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()); createReqVO.setOutType(StockOutTypeEnum..getValue());
return success(stockOutService.createStockOut(createReqVO)); return success(stockOutService.createStockOut(createReqVO));
} }
@GetMapping("/pageMesStockOut") @GetMapping("/pageMesStockOut")
@Operation(summary = "获得生产领料出库单分页") @Operation(summary = "获得生产领料出库单分页")
@PreAuthorize("@ss.hasPermission('erp:stock-out:query')") @PreAuthorize("@ss.hasPermission('erp:stock-out:query')")
public CommonResult<PageResult<ErpStockOutRespVO>> getMesStockOutPage(@Valid ErpStockOutPageReqVO pageReqVO) { public CommonResult<PageResult<ErpStockOutRespVO>> getMesStockOutPage(@Valid ErpStockOutPageReqVO pageReqVO) {
pageReqVO.setOutType(StockOutTypeEnum..getValue()); pageReqVO.setOutType(StockOutTypeEnum..getValue());
PageResult<ErpStockOutDO> pageResult = stockOutService.getStockOutPage(pageReqVO); return success(buildStockOutVOPageResult(stockOutService.getStockOutPage(pageReqVO)));
return success(buildStockOutVOPageResult(pageResult));
} }
} }

@ -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") @Schema(description = "客户编号", example = "3113")
private Long customerId; private Long customerId;
@Schema(description = "负责人id", example = "3113")
@Schema(description = "负责人 id", example = "3113")
private Long responserId; private Long responserId;
@Schema(description = "出库类型", example = "随便")
@Schema(description = "出库类型", example = "其他出库")
private String outType; private String outType;
@Schema(description = "出库类型", example = "随便")
@Schema(description = "出库类型列表", example = "[\"其他出库\",\"产品出库\"]")
private List<String> outTypeList; private List<String> outTypeList;
@Schema(description = "出库时间") @Schema(description = "出库时间")
@ -40,7 +43,10 @@ public class ErpStockOutPageReqVO extends PageParam {
@InEnum(ErpAuditStatus.class) @InEnum(ErpAuditStatus.class)
private Integer status; private Integer status;
@Schema(description = "备注", example = "随便") @Schema(description = "审核人编号", example = "1")
private Long auditUserId;
@Schema(description = "备注", example = "备注信息")
private String remark; private String remark;
@Schema(description = "创建者") @Schema(description = "创建者")
@ -52,6 +58,6 @@ public class ErpStockOutPageReqVO extends PageParam {
@Schema(description = "仓库编号", example = "1") @Schema(description = "仓库编号", example = "1")
private Long warehouseId; private Long warehouseId;
@Schema(description = "id集合导出用") @Schema(description = "id 集合导出时使用")
private String ids; private String ids;
} }

@ -1,8 +1,8 @@
package cn.iocoder.yudao.module.erp.controller.admin.stock.vo.out; package cn.iocoder.yudao.module.erp.controller.admin.stock.vo.out;
import cn.iocoder.yudao.framework.excel.core.annotations.DictFormat; 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.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.ExcelIgnoreUnannotated;
import com.alibaba.excel.annotation.ExcelProperty; import com.alibaba.excel.annotation.ExcelProperty;
import io.swagger.v3.oas.annotations.media.Schema; import io.swagger.v3.oas.annotations.media.Schema;
@ -29,14 +29,18 @@ public class ErpStockOutRespVO {
@Schema(description = "客户编号", example = "3113") @Schema(description = "客户编号", example = "3113")
private Long customerId; private Long customerId;
@Schema(description = "客户名称", example = "芋道") @Schema(description = "客户名称", example = "芋道")
@ExcelProperty("客户名称") @ExcelProperty("客户名称")
private String customerName; private String customerName;
@Schema(description = "负责人id", example = "3113")
@Schema(description = "负责人 id", example = "3113")
private Long responserId; private Long responserId;
@Schema(description = "负责人", example = "3113")
@Schema(description = "负责人", example = "张三")
private String responserName; private String responserName;
@Schema(description = "出库类型", example = "随便")
@Schema(description = "出库类型", example = "其他出库")
private String outType; private String outType;
@Schema(description = "出库时间", requiredMode = Schema.RequiredMode.REQUIRED) @Schema(description = "出库时间", requiredMode = Schema.RequiredMode.REQUIRED)
@ -47,7 +51,7 @@ public class ErpStockOutRespVO {
@ExcelProperty("合计数量") @ExcelProperty("合计数量")
private BigDecimal totalCount; private BigDecimal totalCount;
@Schema(description = "合计金额,单位:元", requiredMode = Schema.RequiredMode.REQUIRED, example = "24906") @Schema(description = "合计金额", requiredMode = Schema.RequiredMode.REQUIRED, example = "24906")
@ExcelProperty("合计金额") @ExcelProperty("合计金额")
private BigDecimal totalPrice; private BigDecimal totalPrice;
@ -56,7 +60,16 @@ public class ErpStockOutRespVO {
@DictFormat(AUDIT_STATUS) @DictFormat(AUDIT_STATUS)
private Integer 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("备注") @ExcelProperty("备注")
private String remark; private String remark;
@ -65,6 +78,7 @@ public class ErpStockOutRespVO {
@Schema(description = "创建人", example = "芋道") @Schema(description = "创建人", example = "芋道")
private String creator; private String creator;
@Schema(description = "创建人名称", example = "芋道") @Schema(description = "创建人名称", example = "芋道")
private String creatorName; private String creatorName;
@ -75,27 +89,29 @@ public class ErpStockOutRespVO {
@Schema(description = "出库项列表", requiredMode = Schema.RequiredMode.REQUIRED) @Schema(description = "出库项列表", requiredMode = Schema.RequiredMode.REQUIRED)
private List<Item> items; private List<Item> items;
@Schema(description = "审核记录")
private List<ErpStockOutApproveRecordRespVO> approveRecords;
@Schema(description = "产品信息", requiredMode = Schema.RequiredMode.REQUIRED) @Schema(description = "产品信息", requiredMode = Schema.RequiredMode.REQUIRED)
@ExcelProperty("产品信息") @ExcelProperty("产品信息")
private String productNames; private String productNames;
@Schema(description = "模具组名") @Schema(description = "模具组名")
private String moldSetNames; private String moldSetNames;
@Schema(description = "计划单Code", example = "随便") @Schema(description = "计划单 Code", example = "PLAN20240601")
private String planCode; private String planCode;
@Data @Data
public static class Item { public static class Item {
@Schema(description = "出库项编号", example = "11756") @Schema(description = "出库项编号", example = "11756")
private Long id; private Long id;
@Schema(description = "??? ID", example = "1") @Schema(description = "模具组 ID", example = "1")
private Long moldSetId; private Long moldSetId;
@Schema(description = "?????", example = "A?") @Schema(description = "模具组名称", example = "A组")
private String moldSetName; private String moldSetName;
@Schema(description = "仓库编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "3113") @Schema(description = "仓库编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "3113")
@ -110,13 +126,15 @@ public class ErpStockOutRespVO {
@Schema(description = "产品数量", requiredMode = Schema.RequiredMode.REQUIRED, example = "100.00") @Schema(description = "产品数量", requiredMode = Schema.RequiredMode.REQUIRED, example = "100.00")
private BigDecimal count; private BigDecimal count;
@Schema(description = "备注", example = "随便") @Schema(description = "备注", example = "备注信息")
private String remark; private String remark;
@Schema(description = "产品名称", requiredMode = Schema.RequiredMode.REQUIRED, example = "???") @Schema(description = "产品名称", requiredMode = Schema.RequiredMode.REQUIRED, example = "巧克力")
private String productName; private String productName;
@Schema(description = "产品条码", requiredMode = Schema.RequiredMode.REQUIRED, example = "A9985") @Schema(description = "产品条码", requiredMode = Schema.RequiredMode.REQUIRED, example = "A9985")
private String productBarCode; private String productBarCode;
@Schema(description = "产品单位名称", requiredMode = Schema.RequiredMode.REQUIRED, example = "盒") @Schema(description = "产品单位名称", requiredMode = Schema.RequiredMode.REQUIRED, example = "盒")
private String productUnitName; private String productUnitName;
@ -125,7 +143,6 @@ public class ErpStockOutRespVO {
@Schema(description = "子模具列表") @Schema(description = "子模具列表")
private List<MoldDO> moldList; private List<MoldDO> moldList;
} }
} }

@ -14,21 +14,26 @@ import java.util.List;
@Data @Data
public class ErpStockOutSaveReqVO { public class ErpStockOutSaveReqVO {
@Schema(description = "出库编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "11756") @Schema(description = "出库编号", example = "11756")
private Long id; private Long id;
@Schema(description = "客户编号", example = "3113") @Schema(description = "客户编号", example = "3113")
private Long customerId; private Long customerId;
@Schema(description = "负责人id", example = "3113")
@Schema(description = "负责人 id", example = "3113")
private Long responserId; private Long responserId;
@Schema(description = "出库类型", example = "随便")
@Schema(description = "出库类型", example = "其他出库")
private String outType; private String outType;
@Schema(description = "出库时间", requiredMode = Schema.RequiredMode.REQUIRED) @Schema(description = "出库时间", requiredMode = Schema.RequiredMode.REQUIRED)
@NotNull(message = "出库时间不能为空") @NotNull(message = "出库时间不能为空")
private LocalDateTime outTime; private LocalDateTime outTime;
@Schema(description = "备注", example = "随便") @Schema(description = "审核人编号", example = "1888")
private Long auditUserId;
@Schema(description = "备注", example = "备注信息")
private String remark; private String remark;
@Schema(description = "附件 URL", example = "https://www.iocoder.cn/1.doc") @Schema(description = "附件 URL", example = "https://www.iocoder.cn/1.doc")
@ -39,35 +44,32 @@ public class ErpStockOutSaveReqVO {
@Valid @Valid
private List<Item> items; private List<Item> items;
@Schema(description = "计划单Code", example = "随便") @Schema(description = "计划单 Code", example = "PLAN20240601")
private String planCode; private String planCode;
@Data @Data
public static class Item { public static class Item {
@Schema(description = "出库项编号", example = "11756") @Schema(description = "出库项编号", example = "11756")
private Long id; private Long id;
@Schema(description = "模具组id", example = "101") @Schema(description = "模具组 id", example = "101")
private Long moldSetId; private Long moldSetId;
@Schema(description = "仓库编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "3113") @Schema(description = "仓库编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "3113")
private Long warehouseId; private Long warehouseId;
@Schema(description = "产品id", example = "3113") @Schema(description = "产品 id", example = "3113")
private Long productId; private Long productId;
@Schema(description = "产品单价", example = "100.00") @Schema(description = "产品单价", example = "100.00")
private BigDecimal productPrice; private BigDecimal productPrice;
@Schema(description = "产品数量", requiredMode = Schema.RequiredMode.REQUIRED, example = "100.00") @Schema(description = "产品数量", requiredMode = Schema.RequiredMode.REQUIRED, example = "100.00")
// @NotNull(message = "产品数量不能为空")
private BigDecimal count; private BigDecimal count;
@Schema(description = "备注", example = "??") @Schema(description = "备注", example = "备注信息")
private String remark; 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; private final String value;
// 一个可选的方法,用于根据整数值获取对应的枚举实例
public static StockOutTypeEnum fromValue(String value) { public static StockOutTypeEnum fromValue(String value) {
for (StockOutTypeEnum status : StockOutTypeEnum.values()) { for (StockOutTypeEnum status : StockOutTypeEnum.values()) {
if (status.getValue().equals(value)) { if (status.getValue().equals(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} * {@link cn.iocoder.yudao.module.erp.enums.ErpAuditStatus}
*/ */
private Integer status; private Integer status;
/**
*
*/
private Boolean needAudit;
/**
*
*/
private Long auditUserId;
/** /**
* *
*/ */

@ -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.mapper.BaseMapperX;
import cn.iocoder.yudao.framework.mybatis.core.query.MPJLambdaWrapperX; 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.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.ErpStockOutDO;
import cn.iocoder.yudao.module.erp.dal.dataobject.stock.ErpStockOutItemDO; import cn.iocoder.yudao.module.erp.dal.dataobject.stock.ErpStockOutItemDO;
import com.alibaba.excel.util.StringUtils; import com.alibaba.excel.util.StringUtils;
@ -17,11 +15,6 @@ import java.util.Arrays;
import java.util.List; import java.util.List;
import java.util.stream.Collectors; import java.util.stream.Collectors;
/**
* ERP Mapper
*
* @author
*/
@Mapper @Mapper
public interface ErpStockOutMapper extends BaseMapperX<ErpStockOutDO> { public interface ErpStockOutMapper extends BaseMapperX<ErpStockOutDO> {
@ -36,36 +29,35 @@ public interface ErpStockOutMapper extends BaseMapperX<ErpStockOutDO> {
.eqIfPresent(ErpStockOutDO::getStatus, reqVO.getStatus()) .eqIfPresent(ErpStockOutDO::getStatus, reqVO.getStatus())
.likeIfPresent(ErpStockOutDO::getRemark, reqVO.getRemark()) .likeIfPresent(ErpStockOutDO::getRemark, reqVO.getRemark())
.eqIfPresent(ErpStockOutDO::getCreator, reqVO.getCreator()) .eqIfPresent(ErpStockOutDO::getCreator, reqVO.getCreator())
.eqIfPresent(ErpStockOutDO::getAuditUserId, reqVO.getAuditUserId())
.orderByDesc(ErpStockOutDO::getId); .orderByDesc(ErpStockOutDO::getId);
if (reqVO.getWarehouseId() != null || reqVO.getProductId() != null) { if (reqVO.getWarehouseId() != null || reqVO.getProductId() != null) {
query.leftJoin(ErpStockOutItemDO.class, ErpStockOutItemDO::getOutId, ErpStockOutDO::getId) query.leftJoin(ErpStockOutItemDO.class, ErpStockOutItemDO::getOutId, ErpStockOutDO::getId)
.eq(reqVO.getWarehouseId() != null, ErpStockOutItemDO::getWarehouseId, reqVO.getWarehouseId()) .eq(reqVO.getWarehouseId() != null, ErpStockOutItemDO::getWarehouseId, reqVO.getWarehouseId())
.eq(reqVO.getProductId() != null, ErpStockOutItemDO::getProductId, reqVO.getProductId()) .eq(reqVO.getProductId() != null, ErpStockOutItemDO::getProductId, reqVO.getProductId())
.groupBy(ErpStockOutDO::getId); // 避免 1 对多查询,产生相同的 1 .groupBy(ErpStockOutDO::getId);
} }
// 单独处理 ids 条件
if (StringUtils.isNotBlank(reqVO.getIds())) { if (StringUtils.isNotBlank(reqVO.getIds())) {
List<Long> idList = Arrays.stream(reqVO.getIds().split(",")) List<Long> idList = Arrays.stream(reqVO.getIds().split(","))
.map(String::trim) .map(String::trim)
.map(Long::valueOf) .map(Long::valueOf)
.collect(Collectors.toList()); .collect(Collectors.toList());
query.in(ErpStockInDO::getId, idList); query.in(ErpStockOutDO::getId, idList);
} }
return selectJoinPage(reqVO, ErpStockOutDO.class, query); return selectJoinPage(reqVO, ErpStockOutDO.class, query);
} }
default int updateByIdAndStatus(Long id, Integer status, ErpStockOutDO updateObj) { default int updateByIdAndStatus(Long id, Integer status, ErpStockOutDO updateObj) {
return update(updateObj, new LambdaUpdateWrapper<ErpStockOutDO>() 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) { default ErpStockOutDO selectByNo(String no) {
return selectOne(ErpStockOutDO::getNo, no); return selectOne(ErpStockOutDO::getNo, no);
} }
default List<ErpStockOutDO> selectByOutType(List<String> outTypes){
return selectList(new QueryWrapper<ErpStockOutDO>() default List<ErpStockOutDO> selectByOutType(List<String> outTypes) {
.in("out_type" ,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.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.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.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.ErpStockOutDO;
import cn.iocoder.yudao.module.erp.dal.dataobject.stock.ErpStockOutItemDO; 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 updateStockOutStatus(Long id, Integer status, Integer bizType);
void submitStockOutAudit(@Valid ErpStockOutSubmitReqVO submitReqVO);
void auditStockOut(@Valid ErpStockOutAuditReqVO auditReqVO);
/** /**
* *
* *
@ -80,6 +87,8 @@ public interface ErpStockOutService {
* @return List * @return List
*/ */
List<ErpStockOutItemDO> getStockOutItemListByOutIds(Collection<Long> outIds); List<ErpStockOutItemDO> getStockOutItemListByOutIds(Collection<Long> outIds);
List<ErpStockOutApproveRecordDO> getStockOutApproveRecordList(Long stockOutId);
List<ErpStockOutDO> selectByOutType(List<String> outTypes); List<ErpStockOutDO> selectByOutType(List<String> outTypes);
void updateMoldStatus(Long id, Integer status); 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.hutool.core.collection.CollUtil;
import cn.iocoder.yudao.framework.common.pojo.PageResult; 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.MoneyUtils;
import cn.iocoder.yudao.framework.common.util.number.NumberUtils;
import cn.iocoder.yudao.framework.common.util.object.BeanUtils; 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.controller.admin.mold.vo.MoldBrandSaveReqVO;
import cn.iocoder.yudao.module.common.dal.dataobject.mold.MoldBrandDO; 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.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.ErpStockOutPageReqVO;
import cn.iocoder.yudao.module.erp.controller.admin.stock.vo.out.ErpStockOutSaveReqVO; 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.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.ErpStockOutDO;
import cn.iocoder.yudao.module.erp.dal.dataobject.stock.ErpStockOutItemDO; 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.ErpStockOutItemMapper;
import cn.iocoder.yudao.module.erp.dal.mysql.stock.ErpStockOutMapper; 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.dal.redis.no.ErpNoRedisDAO;
import cn.iocoder.yudao.module.erp.enums.ErpAuditStatus; 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.enums.stock.ErpStockRecordBizTypeEnum;
import cn.iocoder.yudao.module.erp.service.mold.MoldBrandService; import cn.iocoder.yudao.module.erp.service.mold.MoldBrandService;
import cn.iocoder.yudao.module.erp.service.mold.MoldService; 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.sale.ErpCustomerService;
import cn.iocoder.yudao.module.erp.service.stock.bo.ErpStockRecordCreateReqBO; import cn.iocoder.yudao.module.erp.service.stock.bo.ErpStockRecordCreateReqBO;
import cn.iocoder.yudao.module.infra.api.config.ConfigApi; 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.stereotype.Service;
import org.springframework.transaction.annotation.Transactional; import org.springframework.transaction.annotation.Transactional;
import org.springframework.validation.annotation.Validated; import org.springframework.validation.annotation.Validated;
import javax.annotation.Resource; import javax.annotation.Resource;
import java.math.BigDecimal; import java.math.BigDecimal;
import java.time.LocalDateTime; import java.util.Collection;
import java.util.*; 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.exception.util.ServiceExceptionUtil.exception;
import static cn.iocoder.yudao.framework.common.util.collection.CollectionUtils.*; import static cn.iocoder.yudao.framework.common.util.collection.CollectionUtils.convertList;
import static cn.iocoder.yudao.framework.web.core.util.WebFrameworkUtils.getLoginUserId; 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.*; import static cn.iocoder.yudao.module.erp.enums.ErrorCodeConstants.*;
// TODO 芋艿:记录操作日志
/**
* ERP Service
*
* @author
*/
@Service @Service
@Validated @Validated
public class ErpStockOutServiceImpl implements ErpStockOutService { public class ErpStockOutServiceImpl implements ErpStockOutService {
@ -56,10 +63,10 @@ public class ErpStockOutServiceImpl implements ErpStockOutService {
private ErpStockOutMapper stockOutMapper; private ErpStockOutMapper stockOutMapper;
@Resource @Resource
private ErpStockOutItemMapper stockOutItemMapper; private ErpStockOutItemMapper stockOutItemMapper;
@Resource
private ErpStockOutApproveRecordMapper stockOutApproveRecordMapper;
@Resource @Resource
private ErpNoRedisDAO noRedisDAO; private ErpNoRedisDAO noRedisDAO;
@Resource @Resource
private ErpProductService productService; private ErpProductService productService;
@Resource @Resource
@ -73,40 +80,44 @@ public class ErpStockOutServiceImpl implements ErpStockOutService {
@Resource @Resource
private ErpStockRecordService stockRecordService; private ErpStockRecordService stockRecordService;
@Resource @Resource
private AdminUserApi adminUserApi;
@Resource
private ConfigApi configApi; private ConfigApi configApi;
@Override @Override
@Transactional(rollbackFor = Exception.class) @Transactional(rollbackFor = Exception.class)
public Long createStockOut(ErpStockOutSaveReqVO createReqVO) { public Long createStockOut(ErpStockOutSaveReqVO createReqVO) {
// 1.1 校验出库项的有效性 List<ErpStockOutItemDO> stockOutItems = validateStockOutItems(createReqVO.getItems(), createReqVO.getOutType());
List<ErpStockOutItemDO> stockOutItems = validateStockOutItems(createReqVO.getItems(),createReqVO.getOutType()); if (createReqVO.getCustomerId() != null) {
// 1.2 校验客户 customerService.validateCustomer(createReqVO.getCustomerId());
//customerService.validateCustomer(createReqVO.getCustomerId()); }
// 1.3 生成出库单号,并校验唯一性 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); String no = noRedisDAO.generate(ErpNoRedisDAO.STOCK_OUT_NO_PREFIX);
if (stockOutMapper.selectByNo(no) != null) { if (stockOutMapper.selectByNo(no) != null) {
throw exception(STOCK_OUT_NO_EXISTS); throw exception(STOCK_OUT_NO_EXISTS);
} }
// 2.1 插入出库单
boolean needAudit = needAudit(); boolean needAudit = needAudit();
Integer status = needAudit ? ErpAuditStatus.PROCESS.getStatus() : ErpAuditStatus.APPROVE.getStatus(); Integer status = needAudit ? ErpAuditStatus.DRAFT.getStatus() : ErpAuditStatus.APPROVE.getStatus();
ErpStockOutDO stockOut = BeanUtils.toBean(createReqVO, ErpStockOutDO.class, in -> in ErpStockOutDO stockOut = BeanUtils.toBean(createReqVO, ErpStockOutDO.class, out -> out
.setNo(no).setStatus(status) .setNo(no)
.setNeedAudit(needAudit)
.setStatus(status)
.setTotalCount(getSumValue(stockOutItems, ErpStockOutItemDO::getCount, BigDecimal::add)) .setTotalCount(getSumValue(stockOutItems, ErpStockOutItemDO::getCount, BigDecimal::add))
.setTotalPrice(getSumValue(stockOutItems, ErpStockOutItemDO::getTotalPrice, BigDecimal::add, BigDecimal.ZERO))); .setTotalPrice(getSumValue(stockOutItems, ErpStockOutItemDO::getTotalPrice, BigDecimal::add, BigDecimal.ZERO)));
stockOutMapper.insert(stockOut); stockOutMapper.insert(stockOut);
// 2.2 插入出库单项 stockOutItems.forEach(item -> item.setOutId(stockOut.getId()));
stockOutItems.forEach(o -> o.setOutId(stockOut.getId()));
stockOutItemMapper.insertBatch(stockOutItems); 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) { 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(); return stockOut.getId();
} }
@ -114,141 +125,124 @@ public class ErpStockOutServiceImpl implements ErpStockOutService {
@Override @Override
@Transactional(rollbackFor = Exception.class) @Transactional(rollbackFor = Exception.class)
public void updateStockOut(ErpStockOutSaveReqVO updateReqVO) { public void updateStockOut(ErpStockOutSaveReqVO updateReqVO) {
// 1.1 校验存在
ErpStockOutDO stockOut = validateStockOutExists(updateReqVO.getId()); ErpStockOutDO stockOut = validateStockOutExists(updateReqVO.getId());
if (ErpAuditStatus.APPROVE.getStatus().equals(stockOut.getStatus())) { if (ErpAuditStatus.APPROVE.getStatus().equals(stockOut.getStatus())) {
throw exception(STOCK_OUT_UPDATE_FAIL_APPROVE, stockOut.getNo()); throw exception(STOCK_OUT_UPDATE_FAIL_APPROVE, stockOut.getNo());
} }
// 1.2 校验客户 if (ErpAuditStatus.PROCESS.getStatus().equals(stockOut.getStatus())) {
// customerService.validateCustomer(updateReqVO.getCustomerId()); throw exception(STOCK_OUT_UPDATE_FAIL_PROCESS, stockOut.getNo());
// 1.3 校验出库项的有效性 }
List<ErpStockOutItemDO> stockOutItems = validateStockOutItems(updateReqVO.getItems(),updateReqVO.getOutType()); if (updateReqVO.getCustomerId() != null) {
customerService.validateCustomer(updateReqVO.getCustomerId());
// 2.1 更新出库单 }
ErpStockOutDO updateObj = BeanUtils.toBean(updateReqVO, ErpStockOutDO.class, in -> in 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)) .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); stockOutMapper.updateById(updateObj);
// 2.2 更新出库单项
updateStockOutItemList(updateReqVO.getId(), stockOutItems); updateStockOutItemList(updateReqVO.getId(), stockOutItems);
} }
@Override @Override
@Transactional(rollbackFor = Exception.class) @Transactional(rollbackFor = Exception.class)
public void updateStockOutStatus(Long id, Integer status, Integer bizType) { public void updateStockOutStatus(Long id, Integer status, Integer bizType) {
boolean approve = ErpAuditStatus.APPROVE.getStatus().equals(status);
ErpStockOutDO stockOut = validateStockOutExists(id); ErpStockOutDO stockOut = validateStockOutExists(id);
if (stockOut.getStatus().equals(status)) { boolean approve = ErpAuditStatus.APPROVE.getStatus().equals(status);
throw exception(approve ? STOCK_OUT_APPROVE_FAIL : STOCK_OUT_PROCESS_FAIL); 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) { if (updateCount == 0) {
throw exception(approve ? STOCK_OUT_APPROVE_FAIL : STOCK_OUT_PROCESS_FAIL); throw exception(approve ? STOCK_OUT_APPROVE_FAIL : STOCK_OUT_PROCESS_FAIL);
} }
List<ErpStockOutItemDO> stockOutItems = stockOutItemMapper.selectListByOutId(id); List<ErpStockOutItemDO> stockOutItems = stockOutItemMapper.selectListByOutId(id);
operateStockOutEffect(stockOut, stockOutItems, approve, status); if (approve) {
} applyStockOutEffect(stockOut, stockOutItems, bizType);
} else {
private void operateStockOutEffect(ErpStockOutDO stockOut, List<ErpStockOutItemDO> stockOutItems, cancelStockOutEffect(stockOut, stockOutItems, bizType);
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));
}
}
} }
} }
private boolean needAudit() { @Override
return !AUDIT_CONFIG_DISABLE_VALUE.equals(configApi.getConfigValueByCategoryAndKey(AUDIT_CONFIG_CATEGORY, AUDIT_CONFIG_KEY)); @Transactional(rollbackFor = Exception.class)
} public void submitStockOutAudit(ErpStockOutSubmitReqVO submitReqVO) {
ErpStockOutDO stockOut = validateStockOutExists(submitReqVO.getId());
private List<ErpStockOutItemDO> validateStockOutItems(List<ErpStockOutSaveReqVO.Item> list,String outType) { Long loginUserId = SecurityFrameworkUtils.getLoginUserId();
if (Objects.equals(outType, "模具出库")) { if (!Objects.equals(NumberUtils.parseLong(stockOut.getCreator()), loginUserId)) {
List<MoldBrandDO> moldList = moldBrandService.validMoldList( throw exception(STOCK_OUT_SUBMIT_FAIL_USER);
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()))));
} }
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) { @Override
boolean moldStockOut = CollUtil.isNotEmpty(newList) @Transactional(rollbackFor = Exception.class)
&& newList.stream().anyMatch(item -> item.getMoldSetId() != null); public void auditStockOut(ErpStockOutAuditReqVO auditReqVO) {
if (moldStockOut) { ErpStockOutDO stockOut = validateStockOutExists(auditReqVO.getId());
stockOutItemMapper.deleteByOutId(id); if (!ErpAuditStatus.PROCESS.getStatus().equals(stockOut.getStatus())) {
newList.forEach(o -> { throw exception(STOCK_OUT_AUDIT_FAIL_STATUS);
o.setId(null);
o.setOutId(id);
});
stockOutItemMapper.insertBatch(newList);
return;
} }
Long loginUserId = SecurityFrameworkUtils.getLoginUserId();
List<ErpStockOutItemDO> oldList = stockOutItemMapper.selectListByOutId(id); if (!Objects.equals(stockOut.getAuditUserId(), loginUserId)) {
List<List<ErpStockOutItemDO>> diffList = diffList(oldList, newList, throw exception(STOCK_OUT_AUDIT_FAIL_USER);
(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));
} }
if (CollUtil.isNotEmpty(diffList.get(1))) { if (!ErpAuditStatus.APPROVE.getStatus().equals(auditReqVO.getStatus())
stockOutItemMapper.updateBatch(diffList.get(1)); && !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 @Override
@Transactional(rollbackFor = Exception.class) @Transactional(rollbackFor = Exception.class)
public void deleteStockOut(List<Long> ids) { public void deleteStockOut(List<Long> ids) {
// 1. 校验不处于已审批
List<ErpStockOutDO> stockOuts = stockOutMapper.selectBatchIds(ids); List<ErpStockOutDO> stockOuts = stockOutMapper.selectBatchIds(ids);
if (CollUtil.isEmpty(stockOuts)) { if (CollUtil.isEmpty(stockOuts)) {
return; return;
@ -257,25 +251,17 @@ public class ErpStockOutServiceImpl implements ErpStockOutService {
if (ErpAuditStatus.APPROVE.getStatus().equals(stockOut.getStatus())) { if (ErpAuditStatus.APPROVE.getStatus().equals(stockOut.getStatus())) {
throw exception(STOCK_OUT_DELETE_FAIL_APPROVE, stockOut.getNo()); 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 -> { stockOuts.forEach(stockOut -> {
// 2.1 删除出库单
stockOutMapper.deleteById(stockOut.getId()); stockOutMapper.deleteById(stockOut.getId());
// 2.2 删除出库单项
stockOutItemMapper.deleteByOutId(stockOut.getId()); 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 @Override
public ErpStockOutDO getStockOut(Long id) { public ErpStockOutDO getStockOut(Long id) {
return stockOutMapper.selectById(id); return stockOutMapper.selectById(id);
@ -286,8 +272,6 @@ public class ErpStockOutServiceImpl implements ErpStockOutService {
return stockOutMapper.selectPage(pageReqVO); return stockOutMapper.selectPage(pageReqVO);
} }
// ==================== 出库项 ====================
@Override @Override
public List<ErpStockOutItemDO> getStockOutItemListByOutId(Long outId) { public List<ErpStockOutItemDO> getStockOutItemListByOutId(Long outId) {
return stockOutItemMapper.selectListByOutId(outId); return stockOutItemMapper.selectListByOutId(outId);
@ -300,9 +284,14 @@ public class ErpStockOutServiceImpl implements ErpStockOutService {
} }
return stockOutItemMapper.selectListByOutIds(outIds); return stockOutItemMapper.selectListByOutIds(outIds);
} }
@Override
public List<ErpStockOutApproveRecordDO> getStockOutApproveRecordList(Long stockOutId) {
return stockOutApproveRecordMapper.selectListByStockOutId(stockOutId);
}
@Override @Override
public public List<ErpStockOutDO> selectByOutType(List<String> outTypes) {
List<ErpStockOutDO> selectByOutType(List<String> outTypes){
return stockOutMapper.selectByOutType(outTypes); return stockOutMapper.selectByOutType(outTypes);
} }
@ -313,5 +302,125 @@ public class ErpStockOutServiceImpl implements ErpStockOutService {
stockOutMapper.updateById(stockOut); 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> </foreach>
) )
</if> </if>
ORDER BY operate_time DESC, id DESC ORDER BY id DESC
</select> </select>
</mapper> </mapper>

Loading…
Cancel
Save