mirror of
https://gitee.com/huangge1199_admin/vue-pro.git
synced 2024-11-22 15:21:53 +08:00
✨ ERP:完善 ERP 销售出库单的保存
This commit is contained in:
parent
09e4763c79
commit
0694bc8684
@ -291,7 +291,7 @@ public class CollectionUtils {
|
||||
return getSumValue(from, valueFunc, accumulator, null);
|
||||
}
|
||||
|
||||
public static <T, V extends Comparable<? super V>> V getSumValue(List<T> from, Function<T, V> valueFunc,
|
||||
public static <T, V extends Comparable<? super V>> V getSumValue(Collection<T> from, Function<T, V> valueFunc,
|
||||
BinaryOperator<V> accumulator, V defaultValue) {
|
||||
if (CollUtil.isEmpty(from)) {
|
||||
return defaultValue;
|
||||
|
@ -24,6 +24,17 @@ public interface ErrorCodeConstants {
|
||||
ErrorCode SALE_ORDER_APPROVE_FAIL = new ErrorCode(1_020_201_003, "审核失败,只有未审核的销售订单才能审核");
|
||||
ErrorCode SALE_ORDER_NO_EXISTS = new ErrorCode(1_020_201_004, "生成销售单号失败,请重新提交");
|
||||
ErrorCode SALE_ORDER_UPDATE_FAIL_APPROVE = new ErrorCode(1_020_201_005, "销售订单({})已审核,无法修改");
|
||||
ErrorCode SALE_ORDER_NOT_APPROVE = new ErrorCode(1_020_201_006, "销售订单未审核,无法操作");
|
||||
ErrorCode SALE_ORDER_ITEM_OUT_FAIL_PRODUCT_EXCEED = new ErrorCode(1_020_201_007, "销售订单项({})超过最大允许出库数量({})");
|
||||
ErrorCode SALE_ORDER_PROCESS_FAIL_EXISTS_OUT = new ErrorCode(1_020_201_002, "反审核失败,已存在对应的销售出库单");
|
||||
|
||||
// ========== ERP 销售出库(1-030-202-000) ==========
|
||||
ErrorCode SALE_OUT_NOT_EXISTS = new ErrorCode(1_020_202_000, "销售出库单不存在");
|
||||
ErrorCode SALE_OUT_DELETE_FAIL_APPROVE = new ErrorCode(1_020_202_001, "销售出库单({})已审核,无法删除");
|
||||
ErrorCode SALE_OUT_PROCESS_FAIL = new ErrorCode(1_020_202_002, "反审核失败,只有已审核的出库单才能反审核");
|
||||
ErrorCode SALE_OUT_APPROVE_FAIL = new ErrorCode(1_020_202_003, "审核失败,只有未审核的出库单才能审核");
|
||||
ErrorCode SALE_OUT_NO_EXISTS = new ErrorCode(1_020_202_004, "生成出库单失败,请重新提交");
|
||||
ErrorCode SALE_OUT_UPDATE_FAIL_APPROVE = new ErrorCode(1_020_202_005, "销售出库单({})已审核,无法修改");
|
||||
|
||||
// ========== ERP 仓库 1-030-400-000 ==========
|
||||
ErrorCode WAREHOUSE_NOT_EXISTS = new ErrorCode(1_030_400_000, "仓库不存在");
|
||||
|
@ -90,10 +90,10 @@ public class ErpSaleOrderRespVO {
|
||||
@ExcelProperty("产品信息")
|
||||
private String productNames;
|
||||
|
||||
// ========== 销售入库 ==========
|
||||
// ========== 销售出库 ==========
|
||||
|
||||
@Schema(description = "销售入库数量", requiredMode = Schema.RequiredMode.REQUIRED, example = "100.00")
|
||||
private BigDecimal inCount;
|
||||
@Schema(description = "销售出库数量", requiredMode = Schema.RequiredMode.REQUIRED, example = "100.00")
|
||||
private BigDecimal outCount;
|
||||
|
||||
// ========== 销售退货(出库)) ==========
|
||||
|
||||
@ -128,6 +128,16 @@ public class ErpSaleOrderRespVO {
|
||||
@Schema(description = "备注", example = "随便")
|
||||
private String remark;
|
||||
|
||||
// ========== 销售出库 ==========
|
||||
|
||||
@Schema(description = "销售出库数量", requiredMode = Schema.RequiredMode.REQUIRED, example = "100.00")
|
||||
private BigDecimal outCount;
|
||||
|
||||
// ========== 销售退货(出库)) ==========
|
||||
|
||||
@Schema(description = "销售退货数量", requiredMode = Schema.RequiredMode.REQUIRED, example = "100.00")
|
||||
private BigDecimal returnCount;
|
||||
|
||||
// ========== 关联字段 ==========
|
||||
|
||||
@Schema(description = "产品名称", requiredMode = Schema.RequiredMode.REQUIRED, example = "巧克力")
|
||||
|
@ -47,7 +47,7 @@ public class ErpSaleOutRespVO {
|
||||
@Schema(description = "销售订单编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "17386")
|
||||
private Long orderId;
|
||||
@Schema(description = "销售订单号", requiredMode = Schema.RequiredMode.REQUIRED, example = "XS001")
|
||||
private Long orderNo;
|
||||
private String orderNo;
|
||||
|
||||
@Schema(description = "合计数量", requiredMode = Schema.RequiredMode.REQUIRED, example = "15663")
|
||||
@ExcelProperty("合计数量")
|
||||
|
@ -106,11 +106,11 @@ public class ErpSaleOrderDO extends BaseDO {
|
||||
*/
|
||||
private String remark;
|
||||
|
||||
// ========== 销售入库 ==========
|
||||
// ========== 销售出库 ==========
|
||||
/**
|
||||
* 销售入库数量
|
||||
* 销售出库数量
|
||||
*/
|
||||
private BigDecimal inCount;
|
||||
private BigDecimal outCount;
|
||||
|
||||
// ========== 销售退货(出库)) ==========
|
||||
/**
|
||||
|
@ -78,11 +78,11 @@ public class ErpSaleOrderItemDO extends BaseDO {
|
||||
*/
|
||||
private String remark;
|
||||
|
||||
// ========== 销售入库 ==========
|
||||
// ========== 销售出库 ==========
|
||||
/**
|
||||
* 销售入库数量
|
||||
* 销售出库数量
|
||||
*/
|
||||
private BigDecimal inCount;
|
||||
private BigDecimal outCount;
|
||||
|
||||
// ========== 销售退货(出库)) ==========
|
||||
/**
|
||||
|
@ -74,7 +74,7 @@ public class ErpSaleOutDO extends BaseDO {
|
||||
*
|
||||
* 冗余 {@link ErpSaleOrderDO#getNo()}
|
||||
*/
|
||||
private Long orderNo;
|
||||
private String orderNo;
|
||||
|
||||
/**
|
||||
* 合计数量
|
||||
|
@ -30,13 +30,13 @@ public interface ErpSaleOrderMapper extends BaseMapperX<ErpSaleOrderDO> {
|
||||
.likeIfPresent(ErpSaleOrderDO::getRemark, reqVO.getRemark())
|
||||
.eqIfPresent(ErpSaleOrderDO::getCreator, reqVO.getCreator())
|
||||
.orderByDesc(ErpSaleOrderDO::getId);
|
||||
// 入库状态。为什么需要 t. 的原因,是因为联表查询时,需要指定表名,不然会报 in_count 错误
|
||||
// 入库状态。为什么需要 t. 的原因,是因为联表查询时,需要指定表名,不然会报 out_count 错误
|
||||
if (Objects.equals(reqVO.getInStatus(), ErpSaleOrderPageReqVO.IN_STATUS_NONE)) {
|
||||
query.eq(ErpSaleOrderDO::getInCount, 0);
|
||||
query.eq(ErpSaleOrderDO::getOutCount, 0);
|
||||
} else if (Objects.equals(reqVO.getInStatus(), ErpSaleOrderPageReqVO.IN_STATUS_PART)) {
|
||||
query.gt(ErpSaleOrderDO::getInCount, 0).apply("t.in_count < t.total_count");
|
||||
query.gt(ErpSaleOrderDO::getOutCount, 0).apply("t.out_count < t.total_count");
|
||||
} else if (Objects.equals(reqVO.getInStatus(), ErpSaleOrderPageReqVO.IN_STATUS_ALL)) {
|
||||
query.apply("t.in_count = t.total_count");
|
||||
query.apply("t.out_count = t.total_count");
|
||||
}
|
||||
// 退货状态
|
||||
if (Objects.equals(reqVO.getReturnStatus(), ErpSaleOrderPageReqVO.RETURN_STATUS_NONE)) {
|
||||
@ -49,7 +49,7 @@ public interface ErpSaleOrderMapper extends BaseMapperX<ErpSaleOrderDO> {
|
||||
// 可出库
|
||||
if (Boolean.TRUE.equals(reqVO.getOutEnable())) {
|
||||
query.eq(ErpSaleOrderDO::getStatus, ErpAuditStatus.APPROVE.getStatus())
|
||||
.apply("t.in_count < t.total_count");
|
||||
.apply("t.out_count < t.total_count");
|
||||
}
|
||||
if (reqVO.getProductId() != null) {
|
||||
query.leftJoin(ErpSaleOrderItemDO.class, ErpSaleOrderItemDO::getOrderId, ErpSaleOrderDO::getId)
|
||||
|
@ -1,11 +1,18 @@
|
||||
package cn.iocoder.yudao.module.erp.dal.mysql.sale;
|
||||
|
||||
import cn.hutool.core.collection.CollUtil;
|
||||
import cn.iocoder.yudao.framework.mybatis.core.mapper.BaseMapperX;
|
||||
import cn.iocoder.yudao.module.erp.dal.dataobject.sale.ErpSaleOutItemDO;
|
||||
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
|
||||
import org.apache.ibatis.annotations.Mapper;
|
||||
|
||||
import java.math.BigDecimal;
|
||||
import java.util.Collection;
|
||||
import java.util.Collections;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
import static cn.iocoder.yudao.framework.common.util.collection.CollectionUtils.convertMap;
|
||||
|
||||
/**
|
||||
* ERP 销售出库项 Mapper
|
||||
@ -27,4 +34,23 @@ public interface ErpSaleOutItemMapper extends BaseMapperX<ErpSaleOutItemDO> {
|
||||
return delete(ErpSaleOutItemDO::getOutId, orderId);
|
||||
}
|
||||
|
||||
/**
|
||||
* 基于销售订单编号,查询每个销售订单项的出库数量之和
|
||||
*
|
||||
* @param outIds 出库订单项编号数组
|
||||
* @return key:销售订单项编号;value:出库数量之和
|
||||
*/
|
||||
default Map<Long, BigDecimal> selectOrderItemCountSumMapByOutIds(Collection<Long> outIds) {
|
||||
if (CollUtil.isEmpty(outIds)) {
|
||||
return Collections.emptyMap();
|
||||
}
|
||||
// SQL sum 查询
|
||||
List<Map<String, Object>> result = selectMaps(new QueryWrapper<ErpSaleOutItemDO>()
|
||||
.select("order_item_id, SUM(count) AS sumCount")
|
||||
.groupBy("order_item_id")
|
||||
.in("out_id", outIds));
|
||||
// 获得数量
|
||||
return convertMap(result, obj -> (Long) obj.get("order_item_id"), obj -> (BigDecimal) obj.get("sumCount"));
|
||||
}
|
||||
|
||||
}
|
@ -11,6 +11,7 @@ import com.baomidou.mybatisplus.core.conditions.update.LambdaUpdateWrapper;
|
||||
import org.apache.ibatis.annotations.Mapper;
|
||||
|
||||
import java.math.BigDecimal;
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* ERP 销售出库 Mapper
|
||||
@ -54,4 +55,8 @@ public interface ErpSaleOutMapper extends BaseMapperX<ErpSaleOutDO> {
|
||||
return selectOne(ErpSaleOutDO::getNo, no);
|
||||
}
|
||||
|
||||
default List<ErpSaleOutDO> selectListByOrderId(Long orderId) {
|
||||
return selectList(ErpSaleOutDO::getOrderId, orderId);
|
||||
}
|
||||
|
||||
}
|
@ -42,6 +42,10 @@ public class ErpNoRedisDAO {
|
||||
* 销售订单 {@link cn.iocoder.yudao.module.erp.dal.dataobject.sale.ErpSaleOrderDO}
|
||||
*/
|
||||
public static final String SALE_ORDER_NO_PREFIX = "XSDD";
|
||||
/**
|
||||
* 销售出库 {@link cn.iocoder.yudao.module.erp.dal.dataobject.sale.ErpSaleOutDO}
|
||||
*/
|
||||
public static final String SALE_OUT_NO_PREFIX = "XSCK";
|
||||
|
||||
@Resource
|
||||
private StringRedisTemplate stringRedisTemplate;
|
||||
|
@ -7,8 +7,10 @@ import cn.iocoder.yudao.module.erp.dal.dataobject.sale.ErpSaleOrderDO;
|
||||
import cn.iocoder.yudao.module.erp.dal.dataobject.sale.ErpSaleOrderItemDO;
|
||||
import jakarta.validation.Valid;
|
||||
|
||||
import java.math.BigDecimal;
|
||||
import java.util.Collection;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
/**
|
||||
* ERP 销售订单 Service 接口
|
||||
@ -40,6 +42,14 @@ public interface ErpSaleOrderService {
|
||||
*/
|
||||
void updateSaleOrderStatus(Long id, Integer status);
|
||||
|
||||
/**
|
||||
* 更新销售订单的出库数量
|
||||
*
|
||||
* @param id 编号
|
||||
* @param returnCountMap 出库数量 Map:key 销售订单项编号;value 出库数量
|
||||
*/
|
||||
void updateSaleOrderOutCount(Long id, Map<Long, BigDecimal> returnCountMap);
|
||||
|
||||
/**
|
||||
* 删除销售订单
|
||||
*
|
||||
@ -55,6 +65,14 @@ public interface ErpSaleOrderService {
|
||||
*/
|
||||
ErpSaleOrderDO getSaleOrder(Long id);
|
||||
|
||||
/**
|
||||
* 校验销售订单,已经审核通过
|
||||
*
|
||||
* @param id 编号
|
||||
* @return 销售订单
|
||||
*/
|
||||
ErpSaleOrderDO validateSaleOrder(Long id);
|
||||
|
||||
/**
|
||||
* 获得销售订单分页
|
||||
*
|
||||
|
@ -1,6 +1,7 @@
|
||||
package cn.iocoder.yudao.module.erp.service.sale;
|
||||
|
||||
import cn.hutool.core.collection.CollUtil;
|
||||
import cn.hutool.core.util.ObjectUtil;
|
||||
import cn.iocoder.yudao.framework.common.pojo.PageResult;
|
||||
import cn.iocoder.yudao.framework.common.util.number.MoneyUtils;
|
||||
import cn.iocoder.yudao.framework.common.util.object.BeanUtils;
|
||||
@ -15,6 +16,7 @@ import cn.iocoder.yudao.module.erp.dal.redis.no.ErpNoRedisDAO;
|
||||
import cn.iocoder.yudao.module.erp.enums.ErpAuditStatus;
|
||||
import cn.iocoder.yudao.module.erp.service.finance.ErpAccountService;
|
||||
import cn.iocoder.yudao.module.erp.service.product.ErpProductService;
|
||||
import cn.iocoder.yudao.module.system.api.user.AdminUserApi;
|
||||
import jakarta.annotation.Resource;
|
||||
import org.springframework.stereotype.Service;
|
||||
import org.springframework.transaction.annotation.Transactional;
|
||||
@ -56,6 +58,9 @@ public class ErpSaleOrderServiceImpl implements ErpSaleOrderService {
|
||||
@Resource
|
||||
private ErpAccountService accountService;
|
||||
|
||||
@Resource
|
||||
private AdminUserApi adminUserApi;
|
||||
|
||||
@Override
|
||||
@Transactional(rollbackFor = Exception.class)
|
||||
public Long createSaleOrder(ErpSaleOrderSaveReqVO createReqVO) {
|
||||
@ -67,7 +72,11 @@ public class ErpSaleOrderServiceImpl implements ErpSaleOrderService {
|
||||
if (createReqVO.getAccountId() != null) {
|
||||
accountService.validateAccount(createReqVO.getAccountId());
|
||||
}
|
||||
// 1.4 生成调拨单号,并校验唯一性
|
||||
// 1.4 校验销售人员
|
||||
if (createReqVO.getSaleUserId() != null) {
|
||||
adminUserApi.validateUser(createReqVO.getSaleUserId());
|
||||
}
|
||||
// 1.5 生成调拨单号,并校验唯一性
|
||||
String no = noRedisDAO.generate(ErpNoRedisDAO.SALE_ORDER_NO_PREFIX);
|
||||
if (saleOrderMapper.selectByNo(no) != null) {
|
||||
throw exception(SALE_ORDER_NO_EXISTS);
|
||||
@ -98,7 +107,11 @@ public class ErpSaleOrderServiceImpl implements ErpSaleOrderService {
|
||||
if (updateReqVO.getAccountId() != null) {
|
||||
accountService.validateAccount(updateReqVO.getAccountId());
|
||||
}
|
||||
// 1.4 校验订单项的有效性
|
||||
// 1.4 校验销售人员
|
||||
if (updateReqVO.getSaleUserId() != null) {
|
||||
adminUserApi.validateUser(updateReqVO.getSaleUserId());
|
||||
}
|
||||
// 1.5 校验订单项的有效性
|
||||
List<ErpSaleOrderItemDO> saleOrderItems = validateSaleOrderItems(updateReqVO.getItems());
|
||||
|
||||
// 2.1 更新订单
|
||||
@ -132,7 +145,11 @@ public class ErpSaleOrderServiceImpl implements ErpSaleOrderService {
|
||||
if (saleOrder.getStatus().equals(status)) {
|
||||
throw exception(approve ? SALE_ORDER_APPROVE_FAIL : SALE_ORDER_PROCESS_FAIL);
|
||||
}
|
||||
// TODO @芋艿:需要校验是不是有入库、有退货
|
||||
// 1.3 存在销售出库单,无法反审核
|
||||
if (!approve && saleOrder.getOutCount().compareTo(BigDecimal.ZERO) > 0) {
|
||||
throw exception(SALE_ORDER_PROCESS_FAIL_EXISTS_OUT);
|
||||
}
|
||||
// TODO @芋艿:需要校验是不是有有退货
|
||||
|
||||
// 2. 更新状态
|
||||
int updateCount = saleOrderMapper.updateByIdAndStatus(id, saleOrder.getStatus(),
|
||||
@ -142,6 +159,26 @@ public class ErpSaleOrderServiceImpl implements ErpSaleOrderService {
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void updateSaleOrderOutCount(Long id, Map<Long, BigDecimal> returnCountMap) {
|
||||
List<ErpSaleOrderItemDO> orderItems = saleOrderItemMapper.selectListByOrderId(id);
|
||||
// 1. 更新每个销售订单项
|
||||
orderItems.forEach(item -> {
|
||||
BigDecimal outCount = returnCountMap.getOrDefault(item.getId(), BigDecimal.ZERO);
|
||||
if (item.getOutCount().equals(outCount)) {
|
||||
return;
|
||||
}
|
||||
if (outCount.compareTo(item.getCount()) > 0) {
|
||||
throw exception(SALE_ORDER_ITEM_OUT_FAIL_PRODUCT_EXCEED,
|
||||
productService.getProduct(item.getProductId()).getName(), item.getCount());
|
||||
}
|
||||
saleOrderItemMapper.updateById(new ErpSaleOrderItemDO().setId(item.getId()).setOutCount(outCount));
|
||||
});
|
||||
// 2. 更新销售订单
|
||||
BigDecimal totalOutCount = getSumValue(returnCountMap.values(), value -> value, BigDecimal::add, BigDecimal.ZERO);
|
||||
saleOrderMapper.updateById(new ErpSaleOrderDO().setId(id).setOutCount(totalOutCount));
|
||||
}
|
||||
|
||||
private List<ErpSaleOrderItemDO> validateSaleOrderItems(List<ErpSaleOrderSaveReqVO.Item> list) {
|
||||
// 1. 校验产品存在
|
||||
List<ErpProductDO> productList = productService.validProductList(
|
||||
@ -214,6 +251,15 @@ public class ErpSaleOrderServiceImpl implements ErpSaleOrderService {
|
||||
return saleOrderMapper.selectById(id);
|
||||
}
|
||||
|
||||
@Override
|
||||
public ErpSaleOrderDO validateSaleOrder(Long id) {
|
||||
ErpSaleOrderDO saleOrder = validateSaleOrderExists(id);
|
||||
if (ObjectUtil.notEqual(saleOrder.getStatus(), ErpAuditStatus.APPROVE.getStatus())) {
|
||||
throw exception(SALE_ORDER_NOT_APPROVE);
|
||||
}
|
||||
return saleOrder;
|
||||
}
|
||||
|
||||
@Override
|
||||
public PageResult<ErpSaleOrderDO> getSaleOrderPage(ErpSaleOrderPageReqVO pageReqVO) {
|
||||
return saleOrderMapper.selectPage(pageReqVO);
|
||||
|
@ -1,12 +1,14 @@
|
||||
package cn.iocoder.yudao.module.erp.service.sale;
|
||||
|
||||
import cn.hutool.core.collection.CollUtil;
|
||||
import cn.hutool.core.util.ObjectUtil;
|
||||
import cn.iocoder.yudao.framework.common.pojo.PageResult;
|
||||
import cn.iocoder.yudao.framework.common.util.number.MoneyUtils;
|
||||
import cn.iocoder.yudao.framework.common.util.object.BeanUtils;
|
||||
import cn.iocoder.yudao.module.erp.controller.admin.sale.vo.out.ErpSaleOutPageReqVO;
|
||||
import cn.iocoder.yudao.module.erp.controller.admin.sale.vo.out.ErpSaleOutSaveReqVO;
|
||||
import cn.iocoder.yudao.module.erp.dal.dataobject.product.ErpProductDO;
|
||||
import cn.iocoder.yudao.module.erp.dal.dataobject.sale.ErpSaleOrderDO;
|
||||
import cn.iocoder.yudao.module.erp.dal.dataobject.sale.ErpSaleOutDO;
|
||||
import cn.iocoder.yudao.module.erp.dal.dataobject.sale.ErpSaleOutItemDO;
|
||||
import cn.iocoder.yudao.module.erp.dal.mysql.sale.ErpSaleOutItemMapper;
|
||||
@ -15,7 +17,9 @@ import cn.iocoder.yudao.module.erp.dal.redis.no.ErpNoRedisDAO;
|
||||
import cn.iocoder.yudao.module.erp.enums.ErpAuditStatus;
|
||||
import cn.iocoder.yudao.module.erp.service.finance.ErpAccountService;
|
||||
import cn.iocoder.yudao.module.erp.service.product.ErpProductService;
|
||||
import cn.iocoder.yudao.module.system.api.user.AdminUserApi;
|
||||
import jakarta.annotation.Resource;
|
||||
import org.springframework.context.annotation.Lazy;
|
||||
import org.springframework.stereotype.Service;
|
||||
import org.springframework.transaction.annotation.Transactional;
|
||||
import org.springframework.validation.annotation.Validated;
|
||||
@ -52,33 +56,45 @@ public class ErpSaleOutServiceImpl implements ErpSaleOutService {
|
||||
@Resource
|
||||
private ErpProductService productService;
|
||||
@Resource
|
||||
private ErpCustomerService customerService;
|
||||
@Lazy // 延迟加载,避免循环依赖
|
||||
private ErpSaleOrderService saleOrderService;
|
||||
@Resource
|
||||
private ErpAccountService accountService;
|
||||
|
||||
@Resource
|
||||
private AdminUserApi adminUserApi;
|
||||
|
||||
@Override
|
||||
@Transactional(rollbackFor = Exception.class)
|
||||
public Long createSaleOut(ErpSaleOutSaveReqVO createReqVO) {
|
||||
// 1.1 校验订单项的有效性
|
||||
// 1.1 校验销售订单已审核
|
||||
ErpSaleOrderDO saleOrder = saleOrderService.validateSaleOrder(createReqVO.getOrderId());
|
||||
// 1.2 校验订单项的有效性
|
||||
List<ErpSaleOutItemDO> saleOutItems = validateSaleOutItems(createReqVO.getItems());
|
||||
// 1.2 校验客户 TODO 芋艿:需要在瞅瞅
|
||||
// customerService.validateCustomer(createReqVO.getCustomerId());
|
||||
// 1.3 校验结算账户
|
||||
accountService.validateAccount(createReqVO.getAccountId());
|
||||
// 1.4 生成调拨单号,并校验唯一性
|
||||
String no = noRedisDAO.generate(ErpNoRedisDAO.SALE_ORDER_NO_PREFIX);
|
||||
// 1.4 校验销售人员
|
||||
if (createReqVO.getSaleUserId() != null) {
|
||||
adminUserApi.validateUser(createReqVO.getSaleUserId());
|
||||
}
|
||||
// 1.5 生成调拨单号,并校验唯一性
|
||||
String no = noRedisDAO.generate(ErpNoRedisDAO.SALE_OUT_NO_PREFIX);
|
||||
if (saleOutMapper.selectByNo(no) != null) {
|
||||
throw exception(SALE_ORDER_NO_EXISTS);
|
||||
throw exception(SALE_OUT_NO_EXISTS);
|
||||
}
|
||||
|
||||
// 2.1 插入订单
|
||||
ErpSaleOutDO saleOut = BeanUtils.toBean(createReqVO, ErpSaleOutDO.class, in -> in
|
||||
.setNo(no).setStatus(ErpAuditStatus.PROCESS.getStatus()));
|
||||
.setNo(no).setStatus(ErpAuditStatus.PROCESS.getStatus()))
|
||||
.setOrderNo(saleOrder.getNo()).setCustomerId(saleOrder.getCustomerId());
|
||||
calculateTotalPrice(saleOut, saleOutItems);
|
||||
saleOutMapper.insert(saleOut);
|
||||
// 2.2 插入订单项
|
||||
saleOutItems.forEach(o -> o.setOutId(saleOut.getId()));
|
||||
saleOutItemMapper.insertBatch(saleOutItems);
|
||||
|
||||
// 3. 更新销售订单的出库数量
|
||||
updateSaleOrderOutCount(createReqVO.getOrderId());
|
||||
return saleOut.getId();
|
||||
}
|
||||
|
||||
@ -88,21 +104,33 @@ public class ErpSaleOutServiceImpl implements ErpSaleOutService {
|
||||
// 1.1 校验存在
|
||||
ErpSaleOutDO saleOut = validateSaleOutExists(updateReqVO.getId());
|
||||
if (ErpAuditStatus.APPROVE.getStatus().equals(saleOut.getStatus())) {
|
||||
throw exception(SALE_ORDER_UPDATE_FAIL_APPROVE, saleOut.getNo());
|
||||
throw exception(SALE_OUT_UPDATE_FAIL_APPROVE, saleOut.getNo());
|
||||
}
|
||||
// 1.2 校验客户 TODO 芋艿:需要在瞅瞅
|
||||
// customerService.validateCustomer(updateReqVO.getCustomerId());
|
||||
// 1.2 校验销售订单已审核
|
||||
ErpSaleOrderDO saleOrder = saleOrderService.validateSaleOrder(updateReqVO.getOrderId());
|
||||
// 1.3 校验结算账户
|
||||
accountService.validateAccount(updateReqVO.getAccountId());
|
||||
// 1.4 校验订单项的有效性
|
||||
// 1.4 校验销售人员
|
||||
if (updateReqVO.getSaleUserId() != null) {
|
||||
adminUserApi.validateUser(updateReqVO.getSaleUserId());
|
||||
}
|
||||
// 1.5 校验订单项的有效性
|
||||
List<ErpSaleOutItemDO> saleOutItems = validateSaleOutItems(updateReqVO.getItems());
|
||||
|
||||
// 2.1 更新订单
|
||||
ErpSaleOutDO updateObj = BeanUtils.toBean(updateReqVO, ErpSaleOutDO.class);
|
||||
ErpSaleOutDO updateObj = BeanUtils.toBean(updateReqVO, ErpSaleOutDO.class)
|
||||
.setOrderNo(saleOrder.getNo()).setCustomerId(saleOrder.getCustomerId());
|
||||
calculateTotalPrice(updateObj, saleOutItems);
|
||||
saleOutMapper.updateById(updateObj);
|
||||
// 2.2 更新订单项
|
||||
updateSaleOutItemList(updateReqVO.getId(), saleOutItems);
|
||||
|
||||
// 3.1 更新销售订单的出库数量
|
||||
updateSaleOrderOutCount(updateObj.getOrderId());
|
||||
// 3.2 注意:如果销售订单编号变更了,需要更新“老”销售订单的出库数量
|
||||
if (ObjectUtil.notEqual(saleOut.getOrderId(), updateObj.getOrderId())) {
|
||||
updateSaleOrderOutCount(saleOut.getOrderId());
|
||||
}
|
||||
}
|
||||
|
||||
private void calculateTotalPrice(ErpSaleOutDO saleOut, List<ErpSaleOutItemDO> saleOutItems) {
|
||||
@ -118,6 +146,16 @@ public class ErpSaleOutServiceImpl implements ErpSaleOutService {
|
||||
saleOut.setTotalPrice(saleOut.getTotalPrice().subtract(saleOut.getDiscountPrice()));
|
||||
}
|
||||
|
||||
private void updateSaleOrderOutCount(Long orderId) {
|
||||
// 1.1 查询销售订单对应的销售出库单列表
|
||||
List<ErpSaleOutDO> saleOuts = saleOutMapper.selectListByOrderId(orderId);
|
||||
// 1.2 查询对应的销售订单项的出库数量
|
||||
Map<Long, BigDecimal> returnCountMap = saleOutItemMapper.selectOrderItemCountSumMapByOutIds(
|
||||
convertList(saleOuts, ErpSaleOutDO::getId));
|
||||
// 2. 更新销售订单的出库数量
|
||||
saleOrderService.updateSaleOrderOutCount(orderId, returnCountMap);
|
||||
}
|
||||
|
||||
@Override
|
||||
@Transactional(rollbackFor = Exception.class)
|
||||
public void updateSaleOutStatus(Long id, Integer status) {
|
||||
@ -126,15 +164,14 @@ public class ErpSaleOutServiceImpl implements ErpSaleOutService {
|
||||
ErpSaleOutDO saleOut = validateSaleOutExists(id);
|
||||
// 1.2 校验状态
|
||||
if (saleOut.getStatus().equals(status)) {
|
||||
throw exception(approve ? SALE_ORDER_APPROVE_FAIL : SALE_ORDER_PROCESS_FAIL);
|
||||
throw exception(approve ? SALE_OUT_APPROVE_FAIL : SALE_OUT_PROCESS_FAIL);
|
||||
}
|
||||
// TODO @芋艿:需要校验是不是有入库、有退货
|
||||
|
||||
// 2. 更新状态
|
||||
int updateCount = saleOutMapper.updateByIdAndStatus(id, saleOut.getStatus(),
|
||||
new ErpSaleOutDO().setStatus(status));
|
||||
if (updateCount == 0) {
|
||||
throw exception(approve ? SALE_ORDER_APPROVE_FAIL : SALE_ORDER_PROCESS_FAIL);
|
||||
throw exception(approve ? SALE_OUT_APPROVE_FAIL : SALE_OUT_PROCESS_FAIL);
|
||||
}
|
||||
}
|
||||
|
||||
@ -184,7 +221,7 @@ public class ErpSaleOutServiceImpl implements ErpSaleOutService {
|
||||
}
|
||||
saleOuts.forEach(saleOut -> {
|
||||
if (ErpAuditStatus.APPROVE.getStatus().equals(saleOut.getStatus())) {
|
||||
throw exception(SALE_ORDER_DELETE_FAIL_APPROVE, saleOut.getNo());
|
||||
throw exception(SALE_OUT_DELETE_FAIL_APPROVE, saleOut.getNo());
|
||||
}
|
||||
});
|
||||
|
||||
@ -194,13 +231,17 @@ public class ErpSaleOutServiceImpl implements ErpSaleOutService {
|
||||
saleOutMapper.deleteById(saleOut.getId());
|
||||
// 2.2 删除订单项
|
||||
saleOutItemMapper.deleteByOutId(saleOut.getId());
|
||||
|
||||
// 2.3 更新销售订单的出库数量
|
||||
updateSaleOrderOutCount(saleOut.getOrderId());
|
||||
});
|
||||
|
||||
}
|
||||
|
||||
private ErpSaleOutDO validateSaleOutExists(Long id) {
|
||||
ErpSaleOutDO saleOut = saleOutMapper.selectById(id);
|
||||
if (saleOut == null) {
|
||||
throw exception(SALE_ORDER_NOT_EXISTS);
|
||||
throw exception(SALE_OUT_NOT_EXISTS);
|
||||
}
|
||||
return saleOut;
|
||||
}
|
||||
|
@ -4,6 +4,7 @@ import cn.iocoder.yudao.framework.common.util.collection.CollectionUtils;
|
||||
import cn.iocoder.yudao.module.system.api.user.dto.AdminUserRespDTO;
|
||||
|
||||
import java.util.Collection;
|
||||
import java.util.Collections;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
@ -65,6 +66,17 @@ public interface AdminUserApi {
|
||||
return CollectionUtils.convertMap(users, AdminUserRespDTO::getId);
|
||||
}
|
||||
|
||||
/**
|
||||
* 校验用户是否有效。如下情况,视为无效:
|
||||
* 1. 用户编号不存在
|
||||
* 2. 用户被禁用
|
||||
*
|
||||
* @param id 用户编号
|
||||
*/
|
||||
default void validateUser(Long id) {
|
||||
validateUserList(Collections.singleton(id));
|
||||
}
|
||||
|
||||
/**
|
||||
* 校验用户们是否有效。如下情况,视为无效:
|
||||
* 1. 用户编号不存在
|
||||
|
Loading…
Reference in New Issue
Block a user