feat: 添加商品归还审批模块

新增商品归还审批模块,包括审批列表查询、新增、修改、删除功能。涉及实体类、服务类、控制器及MyBatis映射文件等。模块支持审批状态管理及订单关联查询。
This commit is contained in:
dzq 2025-04-06 11:00:31 +08:00
parent 8a908fc26a
commit f93e2ec039
14 changed files with 517 additions and 1 deletions

View File

@ -0,0 +1,68 @@
package com.agileboot.admin.controller.shop;
import com.agileboot.admin.customize.aop.accessLog.AccessLog;
import com.agileboot.common.core.base.BaseController;
import com.agileboot.common.core.dto.ResponseDTO;
import com.agileboot.common.core.page.PageDTO;
import com.agileboot.common.enums.common.BusinessTypeEnum;
import com.agileboot.domain.common.command.BulkOperationCommand;
import com.agileboot.domain.shop.approval.ReturnApprovalApplicationService;
import com.agileboot.domain.shop.approval.command.AddReturnApprovalCommand;
import com.agileboot.domain.shop.approval.command.UpdateReturnApprovalCommand;
import com.agileboot.domain.shop.approval.db.ReturnApprovalEntity;
import com.agileboot.domain.shop.approval.dto.ReturnApprovalDTO;
import com.agileboot.domain.shop.approval.query.SearchReturnApprovalQuery;
import io.swagger.v3.oas.annotations.Operation;
import java.util.List;
import javax.validation.constraints.NotNull;
import lombok.RequiredArgsConstructor;
import org.springframework.validation.annotation.Validated;
import org.springframework.web.bind.annotation.DeleteMapping;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PathVariable;
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.RestController;
@RestController
@RequestMapping("/shop/returnApproval")
@RequiredArgsConstructor
@Validated
public class ReturnApprovalController extends BaseController {
private final ReturnApprovalApplicationService approvalApplicationService;
@Operation(summary = "退货审批列表")
@GetMapping
public ResponseDTO<PageDTO<ReturnApprovalDTO>> list(SearchReturnApprovalQuery<ReturnApprovalEntity> query) {
PageDTO<ReturnApprovalDTO> page = approvalApplicationService.getApprovalList(query);
return ResponseDTO.ok(page);
}
@Operation(summary = "新增退货审批")
@AccessLog(title = "退货审批管理", businessType = BusinessTypeEnum.ADD)
@PostMapping
public ResponseDTO<Void> add(@Validated @RequestBody AddReturnApprovalCommand command) {
approvalApplicationService.addApproval(command);
return ResponseDTO.ok();
}
@Operation(summary = "修改退货审批")
@AccessLog(title = "退货审批管理", businessType = BusinessTypeEnum.MODIFY)
@PutMapping("/{approvalId}")
public ResponseDTO<Void> edit(@PathVariable Long approvalId, @Validated @RequestBody UpdateReturnApprovalCommand command) {
command.setApprovalId(approvalId);
approvalApplicationService.updateApproval(command);
return ResponseDTO.ok();
}
@Operation(summary = "删除退货审批")
@AccessLog(title = "退货审批管理", businessType = BusinessTypeEnum.DELETE)
@DeleteMapping("/{approvalIds}")
public ResponseDTO<Void> remove(@PathVariable @NotNull List<Long> approvalIds) {
approvalApplicationService.deleteApproval(new BulkOperationCommand<>(approvalIds));
return ResponseDTO.ok();
}
}

View File

@ -0,0 +1,54 @@
package com.agileboot.domain.shop.approval;
import com.agileboot.common.core.page.PageDTO;
import com.agileboot.domain.common.command.BulkOperationCommand;
import com.agileboot.domain.shop.approval.command.AddReturnApprovalCommand;
import com.agileboot.domain.shop.approval.command.UpdateReturnApprovalCommand;
import com.agileboot.domain.shop.approval.db.ReturnApprovalEntity;
import com.agileboot.domain.shop.approval.db.ReturnApprovalService;
import com.agileboot.domain.shop.approval.dto.ReturnApprovalDTO;
import com.agileboot.domain.shop.approval.model.ReturnApprovalModel;
import com.agileboot.domain.shop.approval.model.ReturnApprovalModelFactory;
import com.agileboot.domain.shop.approval.query.SearchReturnApprovalQuery;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import java.util.List;
import java.util.stream.Collectors;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Service;
@Service
@Slf4j
@RequiredArgsConstructor
public class ReturnApprovalApplicationService {
private final ReturnApprovalService approvalService;
private final ReturnApprovalModelFactory modelFactory;
public PageDTO<ReturnApprovalDTO> getApprovalList(SearchReturnApprovalQuery<ReturnApprovalEntity> query) {
Page<ReturnApprovalEntity> page = approvalService.getApprovalList(query);
List<ReturnApprovalDTO> dtoList = page.getRecords().stream()
.map(ReturnApprovalDTO::new)
.collect(Collectors.toList());
return new PageDTO<>(dtoList, page.getTotal());
}
public void addApproval(AddReturnApprovalCommand command) {
ReturnApprovalModel model = modelFactory.create();
model.loadAddCommand(command);
model.insert();
}
public void updateApproval(UpdateReturnApprovalCommand command) {
ReturnApprovalModel model = modelFactory.loadById(command.getApprovalId());
model.loadUpdateCommand(command);
model.updateById();
}
public void deleteApproval(BulkOperationCommand<Long> command) {
for (Long approvalId : command.getIds()) {
ReturnApprovalModel model = modelFactory.loadById(approvalId);
model.deleteById();
}
}
}

View File

@ -0,0 +1,11 @@
package com.agileboot.domain.shop.approval.command;
import com.agileboot.domain.shop.approval.db.ReturnApprovalEntity;
import lombok.Data;
import lombok.EqualsAndHashCode;
@EqualsAndHashCode(callSuper = true)
@Data
public class AddReturnApprovalCommand extends ReturnApprovalEntity {
}

View File

@ -0,0 +1,16 @@
package com.agileboot.domain.shop.approval.command;
import javax.validation.constraints.NotNull;
import javax.validation.constraints.PositiveOrZero;
import lombok.Data;
import lombok.EqualsAndHashCode;
@EqualsAndHashCode(callSuper = true)
@Data
public class UpdateReturnApprovalCommand extends AddReturnApprovalCommand {
@NotNull
@PositiveOrZero
private Long approvalId;
}

View File

@ -0,0 +1,81 @@
package com.agileboot.domain.shop.approval.db;
import com.agileboot.common.core.base.BaseEntity;
import com.baomidou.mybatisplus.annotation.IdType;
import com.baomidou.mybatisplus.annotation.TableField;
import com.baomidou.mybatisplus.annotation.TableId;
import com.baomidou.mybatisplus.annotation.TableName;
import java.io.Serializable;
import java.math.BigDecimal;
import io.swagger.annotations.ApiModel;
import io.swagger.annotations.ApiModelProperty;
import lombok.Getter;
import lombok.Setter;
/**
* <p>
* 商品归还审批表
* </p>
*
* @author valarchie
* @since 2025-04-03
*/
@Getter
@Setter
@TableName("return_approval")
@ApiModel(value = "ReturnApprovalEntity对象", description = "商品归还审批表")
public class ReturnApprovalEntity extends BaseEntity<ReturnApprovalEntity> {
private static final long serialVersionUID = 1L;
@ApiModelProperty("审批编号")
@TableId(value = "approval_id", type = IdType.AUTO)
private Long approvalId;
@ApiModelProperty("关联订单ID")
@TableField("order_id")
private Long orderId;
@ApiModelProperty("关联商品ID")
@TableField("goods_id")
private Long goodsId;
@ApiModelProperty("归还数量")
@TableField("return_quantity")
private Integer returnQuantity;
@ApiModelProperty("商品单价")
@TableField("goods_price")
private BigDecimal goodsPrice;
@ApiModelProperty("退还金额")
@TableField("return_amount")
private BigDecimal returnAmount;
@ApiModelProperty("归还图片路径数组")
@TableField("return_images")
private String returnImages;
@ApiModelProperty("审核图片路径数组")
@TableField("audit_images")
private String auditImages;
@ApiModelProperty("归还说明")
@TableField("return_remark")
private String returnRemark;
@ApiModelProperty("审核说明")
@TableField("audit_remark")
private String auditRemark;
@ApiModelProperty("审批状态(1待审核 2已通过 3已驳回)")
@TableField("`status`")
private Integer status;
@Override
public Serializable pkVal() {
return this.approvalId;
}
}

View File

@ -0,0 +1,43 @@
package com.agileboot.domain.shop.approval.db;
import com.baomidou.mybatisplus.core.conditions.Wrapper;
import com.baomidou.mybatisplus.core.mapper.BaseMapper;
import com.baomidou.mybatisplus.core.toolkit.Constants;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import java.util.List;
import org.apache.ibatis.annotations.Param;
import org.apache.ibatis.annotations.Select;
/**
* <p>
* 商品归还审批表 Mapper 接口
* </p>
*
* @author valarchie
* @since 2025-04-03
*/
public interface ReturnApprovalMapper extends BaseMapper<ReturnApprovalEntity> {
@Select("SELECT approval_id, order_id, goods_id, return_quantity, goods_price, return_amount, return_images, audit_images, return_remark, audit_remark, status " +
"FROM return_approval " +
"${ew.customSqlSegment}")
Page<ReturnApprovalEntity> getApprovalList(
Page<ReturnApprovalEntity> page,
@Param(Constants.WRAPPER) Wrapper<ReturnApprovalEntity> queryWrapper
);
@Select("SELECT * " +
"FROM return_approval " +
"WHERE status = #{status} " +
"ORDER BY create_time DESC " +
"LIMIT 1")
ReturnApprovalEntity selectFirstByStatus(@Param("status") Integer status);
@Select("SELECT * " +
"FROM return_approval " +
"WHERE status = #{status} " +
"ORDER BY create_time DESC")
List<ReturnApprovalEntity> selectAllByStatus(@Param("status") Integer status);
@Select("SELECT * FROM return_approval WHERE order_id = #{orderId} LIMIT 1")
ReturnApprovalEntity selectByOrderId(@Param("orderId") Long orderId);
}

View File

@ -0,0 +1,24 @@
package com.agileboot.domain.shop.approval.db;
import com.agileboot.common.core.page.AbstractPageQuery;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.IService;
import java.util.List;
/**
* <p>
* 商品归还审批表 服务类
* </p>
*
* @author valarchie
* @since 2025-04-03
*/
public interface ReturnApprovalService extends IService<ReturnApprovalEntity> {
Page<ReturnApprovalEntity> getApprovalList(AbstractPageQuery<ReturnApprovalEntity> query);
List<ReturnApprovalEntity> selectAll();
ReturnApprovalEntity getByOrderId(Long orderId);
}

View File

@ -0,0 +1,41 @@
package com.agileboot.domain.shop.approval.db;
import com.agileboot.common.core.page.AbstractPageQuery;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import org.springframework.stereotype.Service;
import java.util.List;
/**
* <p>
* 商品归还审批表 服务实现类
* </p>
*
* @author valarchie
* @since 2025-04-03
*/
@Service
public class ReturnApprovalServiceImpl extends ServiceImpl<ReturnApprovalMapper, ReturnApprovalEntity> implements ReturnApprovalService {
@Override
public Page<ReturnApprovalEntity> getApprovalList(AbstractPageQuery<ReturnApprovalEntity> query) {
return this.page(query.toPage(), query.toQueryWrapper());
}
@Override
public List<ReturnApprovalEntity> selectAll() {
LambdaQueryWrapper<ReturnApprovalEntity> wrapper = new LambdaQueryWrapper<>();
wrapper.orderByDesc(ReturnApprovalEntity::getCreateTime);
return this.list(wrapper);
}
@Override
public ReturnApprovalEntity getByOrderId(Long orderId) {
LambdaQueryWrapper<ReturnApprovalEntity> wrapper = new LambdaQueryWrapper<>();
wrapper.eq(ReturnApprovalEntity::getOrderId, orderId)
.last("LIMIT 1");
return this.getOne(wrapper);
}
}

View File

@ -0,0 +1,67 @@
package com.agileboot.domain.shop.approval.dto;
import cn.hutool.core.bean.BeanUtil;
import com.agileboot.common.annotation.ExcelColumn;
import com.agileboot.common.annotation.ExcelSheet;
import com.agileboot.domain.common.cache.CacheCenter;
import com.agileboot.domain.shop.approval.db.ReturnApprovalEntity;
import com.agileboot.domain.system.user.db.SysUserEntity;
import lombok.Data;
import java.math.BigDecimal;
@ExcelSheet(name = "商品归还审批列表")
@Data
public class ReturnApprovalDTO {
public ReturnApprovalDTO(ReturnApprovalEntity entity) {
if (entity != null) {
BeanUtil.copyProperties(entity, this);
this.statusStr = convertStatus(entity.getStatus());
}
}
private String convertStatus(Integer status) {
if (status == null) return "-";
switch (status) {
case 1: return "待审核";
case 2: return "已通过";
case 3: return "已驳回";
default: return "未知状态";
}
}
@ExcelColumn(name = "审批编号")
private Long approvalId;
@ExcelColumn(name = "关联订单ID")
private Long orderId;
@ExcelColumn(name = "关联商品ID")
private Long goodsId;
@ExcelColumn(name = "归还数量")
private Integer returnQuantity;
@ExcelColumn(name = "商品单价")
private BigDecimal goodsPrice;
@ExcelColumn(name = "退还金额")
private BigDecimal returnAmount;
@ExcelColumn(name = "归还图片")
private String returnImages;
@ExcelColumn(name = "审核图片")
private String auditImages;
@ExcelColumn(name = "归还说明")
private String returnRemark;
@ExcelColumn(name = "审核说明")
private String auditRemark;
@ExcelColumn(name = "审批状态")
private String statusStr;
}

View File

@ -0,0 +1,39 @@
package com.agileboot.domain.shop.approval.model;
import cn.hutool.core.bean.BeanUtil;
import com.agileboot.domain.shop.approval.command.AddReturnApprovalCommand;
import com.agileboot.domain.shop.approval.command.UpdateReturnApprovalCommand;
import com.agileboot.domain.shop.approval.db.ReturnApprovalEntity;
import com.agileboot.domain.shop.approval.db.ReturnApprovalService;
import lombok.Data;
import lombok.EqualsAndHashCode;
@EqualsAndHashCode(callSuper = true)
@Data
public class ReturnApprovalModel extends ReturnApprovalEntity {
private ReturnApprovalService approvalService;
public ReturnApprovalModel(ReturnApprovalEntity entity, ReturnApprovalService approvalService) {
this(approvalService);
if (entity != null) {
BeanUtil.copyProperties(entity, this);
}
}
public ReturnApprovalModel(ReturnApprovalService approvalService) {
this.approvalService = approvalService;
}
public void loadAddCommand(AddReturnApprovalCommand command) {
if (command != null) {
BeanUtil.copyProperties(command, this, "approvalId");
}
}
public void loadUpdateCommand(UpdateReturnApprovalCommand command) {
if (command != null) {
loadAddCommand(command);
}
}
}

View File

@ -0,0 +1,27 @@
package com.agileboot.domain.shop.approval.model;
import com.agileboot.common.exception.ApiException;
import com.agileboot.common.exception.error.ErrorCode;
import com.agileboot.domain.shop.approval.db.ReturnApprovalEntity;
import com.agileboot.domain.shop.approval.db.ReturnApprovalService;
import lombok.RequiredArgsConstructor;
import org.springframework.stereotype.Component;
@Component
@RequiredArgsConstructor
public class ReturnApprovalModelFactory {
private final ReturnApprovalService approvalService;
public ReturnApprovalModel loadById(Long approvalId) {
ReturnApprovalEntity entity = approvalService.getById(approvalId);
if (entity == null) {
throw new ApiException(ErrorCode.Business.COMMON_OBJECT_NOT_FOUND, approvalId, "审批");
}
return new ReturnApprovalModel(entity, approvalService);
}
public ReturnApprovalModel create() {
return new ReturnApprovalModel(approvalService);
}
}

View File

@ -0,0 +1,40 @@
package com.agileboot.domain.shop.approval.query;
import cn.hutool.core.util.StrUtil;
import com.agileboot.common.core.page.AbstractPageQuery;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import java.util.Date;
import lombok.Data;
import lombok.EqualsAndHashCode;
@EqualsAndHashCode(callSuper = true)
@Data
public class SearchReturnApprovalQuery<T> extends AbstractPageQuery<T> {
private Long approvalId;
private Long orderId;
private Long goodsId;
private Integer status;
private String returnRemark;
private String auditRemark;
private Date startTime;
private Date endTime;
@Override
public QueryWrapper<T> addQueryCondition() {
QueryWrapper<T> queryWrapper = new QueryWrapper<>();
queryWrapper
.eq(approvalId != null, "approval_id", approvalId)
.eq(orderId != null, "order_id", orderId)
.eq(goodsId != null, "goods_id", goodsId)
.eq(status != null, "status", status)
.like(StrUtil.isNotEmpty(returnRemark), "return_remark", returnRemark)
.like(StrUtil.isNotEmpty(auditRemark), "audit_remark", auditRemark)
.between(startTime != null && endTime != null, "create_time", startTime, endTime);
this.timeRangeColumn = "create_time";
return queryWrapper;
}
}

View File

@ -0,0 +1,5 @@
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
<mapper namespace="com.agileboot.domain.shop.approval.db.ReturnApprovalMapper">
</mapper>

View File

@ -61,7 +61,7 @@ public class CodeGenerator {
//生成的类 放在orm子模块下的/target/generated-code目录底下 //生成的类 放在orm子模块下的/target/generated-code目录底下
.module("/agileboot-orm/target/generated-code") .module("/agileboot-orm/target/generated-code")
.parentPackage("com.agileboot") .parentPackage("com.agileboot")
.tableName("sys_user_qy_user") .tableName("return_approval")
// 决定是否继承基类 // 决定是否继承基类
.isExtendsFromBaseEntity(true) .isExtendsFromBaseEntity(true)
.build(); .build();