feat(transaction):优化分账规则管理功能

- 调整分账规则状态枚举值,启用状态为0,禁用状态为1
- 修改适用商品类型字段类型从Integer为Long
- 增加分账规则保存和更新时的商品类型唯一性校验- 优化分账规则更新逻辑,支持明细的增删改操作
- 调整商品分类查询逻辑,支持父子级分类结构展示
- 移除区域ID和手续费承担方式字段注释
- 完善分账规则BO和VO类的字段描述和注解
- 添加分账规则明细Mapper查询方法- 优化分账规则转换逻辑,提升代码可读性
- 增强分账规则服务层的业务校验逻辑
This commit is contained in:
huk 2025-09-27 15:42:02 +08:00
parent 86b14817fd
commit 8d148bd76c
8 changed files with 97 additions and 49 deletions

View File

@ -3,10 +3,12 @@ package com.wzj.soopin.transaction.domain.bo;
import com.alibaba.excel.annotation.ExcelProperty;
import com.wzj.soopin.transaction.domain.po.DivideRule;
import com.wzj.soopin.transaction.enums.DivideRuleStatus;
import io.swagger.v3.oas.annotations.media.Schema;
import jakarta.validation.constraints.NotBlank;
import jakarta.validation.constraints.NotNull;
import lombok.Data;
import lombok.EqualsAndHashCode;
import org.dromara.common.core.domain.BaseBO;
import java.util.ArrayList;
@ -18,6 +20,7 @@ import java.util.List;
* @author wzj
* @date 2023-03-07
*/
@EqualsAndHashCode(callSuper = true)
@Schema(description="分账规则")
@Data
public class DivideRuleBO extends BaseBO<DivideRule> {
@ -47,17 +50,16 @@ public class DivideRuleBO extends BaseBO<DivideRule> {
/**
* 状态
* @see DivideRuleStatus#getCode()
*/
@Schema(description ="状态")
@Schema(description ="状态", implementation = DivideRuleStatus.class)
@ExcelProperty(value ="状态", order = 7)
private Integer status;
/**
* 类型
*/
@Schema(description ="适用订单类型")
@Schema(description ="适用商品类型")
@ExcelProperty(value ="类型", order = 8)
@NotNull(message = "适用订单类型不能为空")
private Integer type;
@NotNull(message = "适用商品类型不能为空")
private Long type;
@Schema(description = "区域id")

View File

@ -43,9 +43,10 @@ public class DivideRuleDetailBO extends BaseBO<DivideRuleDetail> {
/**
* 分账租户类型{@link TenantType}
* 分账租户类型 不可选择商户类型
* @see TenantType#getType()
*/
@Schema(description ="分账租户类型 2->商家,3->代理,4->平台,5->达人")
@Schema(description ="分账租户类型,不可选择商户类型", implementation = TenantType.class)
@ExcelProperty(value ="类型", order = 8)
@NotNull(message = "分账租户类型不能为空")
private Integer type;

View File

@ -4,9 +4,7 @@ package com.wzj.soopin.transaction.domain.po;
import com.alibaba.excel.annotation.ExcelProperty;
import com.baomidou.mybatisplus.annotation.*;
import io.swagger.v3.oas.annotations.media.Schema;
import lombok.Builder;
import lombok.Data;
import lombok.EqualsAndHashCode;
import lombok.*;
import org.apache.ibatis.type.JdbcType;
import org.dromara.common.core.domain.model.BaseAudit;
@ -21,6 +19,8 @@ import org.dromara.common.core.domain.model.BaseAudit;
@Data
@TableName("trans_divide_rule")
@Builder
@AllArgsConstructor
@NoArgsConstructor
public class DivideRule extends BaseAudit {
/**
@ -45,16 +45,12 @@ public class DivideRule extends BaseAudit {
private String name;
@Schema(description = "区域id")
private Long regionId;
// @Schema(description = "区域id")
// private Long regionId;
/**
* 手续费承担方式类型
*/
@Schema(description = "手续费承担方式")
private Integer feeType;
// @Schema(description = "手续费承担方式")
// private Integer feeType;
/**
@ -64,11 +60,11 @@ public class DivideRule extends BaseAudit {
@ExcelProperty(value ="状态", order = 7)
private Integer status;
/**
* 类型
* 适用商品类型
*/
@Schema(description ="适用订单类型")
@Schema(description ="适用商品类型")
@ExcelProperty(value ="类型", order = 8)
private Integer type;
private Long type;
@TableLogic(value = "0", delval = "1")
@TableField(value = "del_flag", fill = FieldFill.INSERT, jdbcType = JdbcType.CHAR)

View File

@ -53,21 +53,19 @@ public class DivideRuleVO extends BaseEntity {
private Integer status;
@Schema(description = "区域id")
private Long regionId;
// @Schema(description = "区域id")
// private Long regionId;
/**
* 手续费承担方式类型
*/
@Schema(description = "手续费承担方式")
private Integer feeType;
// @Schema(description = "手续费承担方式")
// private Integer feeType;
/**
* 类型
*/
@Schema(description ="适用订单类型")
@ExcelProperty(value ="类型", order = 8)
private Integer type;
private Long type;
@Schema(description = "分账规则明细")
@ExcelProperty(value = "分账规则明细", order = 9)

View File

@ -9,11 +9,11 @@ public enum DivideRuleStatus {
/**
* 启用
*/
ON(1, "启用"),
ON(0, "启用"),
/**
* 禁用
*/
OFF(0, "禁用");
OFF(1, "禁用");
private final int code;
private final String message;

View File

@ -4,11 +4,9 @@ import com.wzj.soopin.transaction.domain.po.DivideDetail;
import com.wzj.soopin.transaction.domain.vo.DivideDetailVO;
import org.apache.ibatis.annotations.Mapper;
import org.apache.ibatis.annotations.Param;
import org.apache.ibatis.annotations.Select;
import org.dromara.common.mybatis.core.mapper.BaseMapperPlus;
import java.math.BigDecimal;
import java.util.List;
/**
* 意见反馈Mapper接口

View File

@ -3,8 +3,12 @@ package com.wzj.soopin.transaction.mapper;
import com.wzj.soopin.transaction.domain.po.DivideRuleDetail;
import com.wzj.soopin.transaction.domain.vo.DivideRuleDetailVO;
import org.apache.ibatis.annotations.Mapper;
import org.apache.ibatis.annotations.Param;
import org.apache.ibatis.annotations.Select;
import org.dromara.common.mybatis.core.mapper.BaseMapperPlus;
import java.util.List;
/**
* 意见反馈Mapper接口
*
@ -13,4 +17,6 @@ import org.dromara.common.mybatis.core.mapper.BaseMapperPlus;
@Mapper
public interface DivideRuleDetailMapper extends BaseMapperPlus<DivideRuleDetail, DivideRuleDetailVO> {
@Select("select * from trans_divide_rule_detail where rule_id = #{ruleId} and del_flag = '0' " )
List<DivideRuleDetail> getByRuleId(@Param("ruleId") Long ruleId);
}

View File

@ -4,6 +4,7 @@ import cn.hutool.core.bean.BeanUtil;
import cn.hutool.core.collection.CollUtil;
import cn.hutool.core.lang.Assert;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.wzj.soopin.goods.domain.entity.ProductCategory;
import com.wzj.soopin.goods.domain.vo.ProductCategoryVO;
@ -54,6 +55,7 @@ public class DivideRuleServiceImpl extends ServiceImpl<DivideRuleMapper, DivideR
public boolean save(DivideRuleBO bo) {
DivideRule entity = convert.toPo(bo);
entity.setStatus(DivideRuleStatus.ON.getCode());
Assert.isFalse(this.exists(Wrappers.lambdaQuery(DivideRule.class).eq(DivideRule::getType, bo.getType())), () -> new ServiceException("已存在相同商品类型的分账规则"));
// 保存主分账信息
save(entity);
List<DivideRuleDetailBO> details = bo.getDetails();
@ -69,18 +71,57 @@ public class DivideRuleServiceImpl extends ServiceImpl<DivideRuleMapper, DivideR
@Override
public void update(DivideRuleBO bo) {
Assert.isFalse(this.exists(Wrappers.lambdaQuery(DivideRule.class)
.ne(DivideRule::getId, bo.getId())
.eq(DivideRule::getType, bo.getType())), () -> new ServiceException("已存在相同商品类型的分账规则"));
DivideRule divideRule = this.getById(bo.getId());
Assert.notNull(divideRule, () -> new ServiceException("未找到该分账规则"));
Assert.isTrue(divideRule.getStatus().equals(DivideRuleStatus.OFF.getCode()), () -> new ServiceException("请先停用状态规则"));
List<DivideRuleDetailBO> details = bo.getDetails();
Assert.notEmpty(details, () -> new ServiceException("分账规则详情不能为空"));
checkRule(details.stream().map(detail -> BeanUtil.copyProperties(detail, DivideRuleDetail.class)).toList());
detailMapper.delete(new QueryWrapper<DivideRuleDetail>().lambda().eq(DivideRuleDetail::getRuleId, bo.getId()));
List<DivideRuleDetail> detailEntities = details.stream()
.peek(detailBO -> detailBO.setRuleId(bo.getId()))
.map(detailConvert::toPo)
// Assert.isTrue(divideRule.getStatus().equals(DivideRuleStatus.OFF.getCode()), () -> new ServiceException("请先停用状态规则"));
List<DivideRuleDetailBO> newDetails = bo.getDetails();
Assert.notEmpty(newDetails, () -> new ServiceException("分账规则详情不能为空"));
checkRule(newDetails.stream().map(detail -> BeanUtil.copyProperties(detail, DivideRuleDetail.class)).toList());
this.updateById(BeanUtil.copyProperties(bo, DivideRule.class));
List<DivideRuleDetail> oldDetails = detailMapper.getByRuleId(bo.getId());
// 比较newDetails和oldDetails分类出新增修改删除的list
Map<Long, DivideRuleDetailBO> newDetailMap = newDetails.stream()
.filter(detail -> detail.getId() != null)
.collect(Collectors.toMap(DivideRuleDetailBO::getId, detail -> detail));
List<DivideRuleDetail> toUpdate = oldDetails.stream()
.filter(detail -> newDetailMap.containsKey(detail.getId()))
.map(detail -> {
DivideRuleDetailBO updatedBO = newDetailMap.get(detail.getId());
DivideRuleDetail updatedDetail = BeanUtil.copyProperties(updatedBO, DivideRuleDetail.class);
updatedDetail.setRuleId(bo.getId());
return updatedDetail;
})
.toList();
detailMapper.insertBatch(detailEntities);
List<DivideRuleDetail> toDelete = oldDetails.stream()
.filter(detail -> !newDetailMap.containsKey(detail.getId()))
.toList();
List<DivideRuleDetail> toAdd = newDetails.stream()
.filter(detail -> detail.getId() == null)
.map(detailBO -> {
DivideRuleDetail detail = BeanUtil.copyProperties(detailBO, DivideRuleDetail.class);
detail.setRuleId(bo.getId());
return detail;
})
.toList();
// 执行删除
if (CollUtil.isNotEmpty(toDelete)) {
detailMapper.deleteByIds(toDelete.stream().map(DivideRuleDetail::getId).toList());
}
// 执行更新
if (CollUtil.isNotEmpty(toUpdate)) {
detailMapper.updateBatchById(toUpdate);
}
// 执行新增
if (CollUtil.isNotEmpty(toAdd)) {
detailMapper.insertBatch(toAdd);
}
}
@Override
@ -157,11 +198,17 @@ public class DivideRuleServiceImpl extends ServiceImpl<DivideRuleMapper, DivideR
@Override
public List<ProductCategoryVO> productCategoryWithNoRule() {
List<DivideRule> existRule = this.list();
List<ProductCategory> allProductCategories = productCategoryService.list();
List<Integer> existTypes = existRule.stream().map(item -> item.getType()).toList();
return allProductCategories.stream().filter(item -> item.getParentId() != 0)
.filter(item -> !CollUtil.contains(existTypes, item.getId()))
.map(item -> BeanUtil.copyProperties(item, ProductCategoryVO.class)).toList();
List<Long> existTypes = this.list().stream().map(DivideRule::getType).toList();
return allProductCategories.stream().filter(item -> item.getParentId() == 0)
.map(parent ->{
ProductCategoryVO productCategoryVO = BeanUtil.copyProperties(parent, ProductCategoryVO.class);
productCategoryVO.setChildren(allProductCategories.stream()
.filter(item -> item.getParentId() != 0)
.filter(item -> item.getParentId().equals(parent.getId()))
.filter(item -> !CollUtil.contains(existTypes, item.getId()))
.map(item -> BeanUtil.copyProperties(item, ProductCategoryVO.class)).toList());
return productCategoryVO;
}).toList();
}
}