From 4bd97c4baf020b2c311b4bcc39222b7f4de37981 Mon Sep 17 00:00:00 2001 From: dhb52 Date: Mon, 15 Jan 2024 17:41:21 +0800 Subject: [PATCH 001/119] =?UTF-8?q?wip:=20=E6=A0=B9=E6=8D=AEcode=20review?= =?UTF-8?q?=E4=BC=98=E5=8C=96=E4=BB=A3=E7=A0=81?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../module/crm/enums/ErrorCodeConstants.java | 3 + .../enums/message/CrmContactStatusEnum.java | 39 ------------- .../CrmBacklogController.java} | 18 +++--- .../vo/CrmTodayCustomerPageReqVO.java | 9 +-- .../dal/mysql/customer/CrmCustomerMapper.java | 55 +++++++------------ ...ageService.java => CrmBacklogService.java} | 12 ++-- ...ceImpl.java => CrmBacklogServiceImpl.java} | 9 ++- 7 files changed, 50 insertions(+), 95 deletions(-) delete mode 100644 yudao-module-crm/yudao-module-crm-api/src/main/java/cn/iocoder/yudao/module/crm/enums/message/CrmContactStatusEnum.java rename yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/controller/admin/{message/CrmMessageController.java => backlog/CrmBacklogController.java} (71%) rename yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/controller/admin/{message => backlog}/vo/CrmTodayCustomerPageReqVO.java (65%) rename yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/service/message/{CrmMessageService.java => CrmBacklogService.java} (60%) rename yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/service/message/{CrmMessageServiceImpl.java => CrmBacklogServiceImpl.java} (80%) diff --git a/yudao-module-crm/yudao-module-crm-api/src/main/java/cn/iocoder/yudao/module/crm/enums/ErrorCodeConstants.java b/yudao-module-crm/yudao-module-crm-api/src/main/java/cn/iocoder/yudao/module/crm/enums/ErrorCodeConstants.java index 6200f3845..4543fe856 100644 --- a/yudao-module-crm/yudao-module-crm-api/src/main/java/cn/iocoder/yudao/module/crm/enums/ErrorCodeConstants.java +++ b/yudao-module-crm/yudao-module-crm-api/src/main/java/cn/iocoder/yudao/module/crm/enums/ErrorCodeConstants.java @@ -84,4 +84,7 @@ public interface ErrorCodeConstants { // ========== 跟进记录 1_020_013_000 ========== ErrorCode FOLLOW_UP_RECORD_NOT_EXISTS = new ErrorCode(1_020_013_000, "跟进记录不存在"); + // ========== 待办消息 1_020_014_000 ========== + ErrorCode BACKLOG_CONTACT_STATUS_ERROR = new ErrorCode(1_020_014_000, "客户联系状态有误"); + } diff --git a/yudao-module-crm/yudao-module-crm-api/src/main/java/cn/iocoder/yudao/module/crm/enums/message/CrmContactStatusEnum.java b/yudao-module-crm/yudao-module-crm-api/src/main/java/cn/iocoder/yudao/module/crm/enums/message/CrmContactStatusEnum.java deleted file mode 100644 index 6ca5f52dc..000000000 --- a/yudao-module-crm/yudao-module-crm-api/src/main/java/cn/iocoder/yudao/module/crm/enums/message/CrmContactStatusEnum.java +++ /dev/null @@ -1,39 +0,0 @@ -package cn.iocoder.yudao.module.crm.enums.message; - -import cn.iocoder.yudao.framework.common.core.IntArrayValuable; -import lombok.Getter; -import lombok.RequiredArgsConstructor; - -import java.util.Arrays; - -/** - * CRM 联系状态 - * - * @author dhb52 - */ -@RequiredArgsConstructor -@Getter -public enum CrmContactStatusEnum implements IntArrayValuable { - - NEEDED_TODAY(1, "今日需联系"), - EXPIRED(2, "已逾期"), - ALREADY_CONTACT(3, "已联系"), - ; - - public static final int[] ARRAYS = Arrays.stream(values()).mapToInt(CrmContactStatusEnum::getType).toArray(); - - /** - * 状态 - */ - private final Integer type; - /** - * 状态名 - */ - private final String name; - - @Override - public int[] array() { - return ARRAYS; - } - -} diff --git a/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/controller/admin/message/CrmMessageController.java b/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/controller/admin/backlog/CrmBacklogController.java similarity index 71% rename from yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/controller/admin/message/CrmMessageController.java rename to yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/controller/admin/backlog/CrmBacklogController.java index 32a0eb6ca..9b8841e2e 100644 --- a/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/controller/admin/message/CrmMessageController.java +++ b/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/controller/admin/backlog/CrmBacklogController.java @@ -1,12 +1,12 @@ -package cn.iocoder.yudao.module.crm.controller.admin.message; +package cn.iocoder.yudao.module.crm.controller.admin.backlog; import cn.iocoder.yudao.framework.common.pojo.CommonResult; import cn.iocoder.yudao.framework.common.pojo.PageResult; import cn.iocoder.yudao.framework.common.util.object.BeanUtils; import cn.iocoder.yudao.module.crm.controller.admin.customer.vo.CrmCustomerRespVO; -import cn.iocoder.yudao.module.crm.controller.admin.message.vo.CrmTodayCustomerPageReqVO; +import cn.iocoder.yudao.module.crm.controller.admin.backlog.vo.CrmTodayCustomerPageReqVO; import cn.iocoder.yudao.module.crm.dal.dataobject.customer.CrmCustomerDO; -import cn.iocoder.yudao.module.crm.service.message.CrmMessageService; +import cn.iocoder.yudao.module.crm.service.message.CrmBacklogService; import io.swagger.v3.oas.annotations.Operation; import io.swagger.v3.oas.annotations.tags.Tag; import jakarta.annotation.Resource; @@ -20,19 +20,19 @@ import org.springframework.web.bind.annotation.RestController; import static cn.iocoder.yudao.framework.common.pojo.CommonResult.success; import static cn.iocoder.yudao.framework.security.core.util.SecurityFrameworkUtils.getLoginUserId; -@Tag(name = "管理后台 - CRM消息") +@Tag(name = "管理后台 - CRM待办消息") @RestController -@RequestMapping("/crm/message") +@RequestMapping("/crm/backlog") @Validated -public class CrmMessageController { +public class CrmBacklogController { @Resource - private CrmMessageService crmMessageService; + private CrmBacklogService crmMessageService; // TODO 芋艿:未来可能合并到 CrmCustomerController - @GetMapping("/todayCustomer") // TODO @dbh52:【优先级低】url 使用中划线,项目规范。然后叫 today-customer-page,通过 page 体现出它是个分页接口 + @GetMapping("/today-customer-page") @Operation(summary = "今日需联系客户") - @PreAuthorize("@ss.hasPermission('crm:message:todayCustomer')") + @PreAuthorize("@ss.hasPermission('crm:customer:query')") public CommonResult> getTodayCustomerPage(@Valid CrmTodayCustomerPageReqVO pageReqVO) { PageResult pageResult = crmMessageService.getTodayCustomerPage(pageReqVO, getLoginUserId()); return success(BeanUtils.toBean(pageResult, CrmCustomerRespVO.class)); diff --git a/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/controller/admin/message/vo/CrmTodayCustomerPageReqVO.java b/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/controller/admin/backlog/vo/CrmTodayCustomerPageReqVO.java similarity index 65% rename from yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/controller/admin/message/vo/CrmTodayCustomerPageReqVO.java rename to yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/controller/admin/backlog/vo/CrmTodayCustomerPageReqVO.java index f47dfb468..e054792a9 100644 --- a/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/controller/admin/message/vo/CrmTodayCustomerPageReqVO.java +++ b/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/controller/admin/backlog/vo/CrmTodayCustomerPageReqVO.java @@ -1,9 +1,8 @@ -package cn.iocoder.yudao.module.crm.controller.admin.message.vo; +package cn.iocoder.yudao.module.crm.controller.admin.backlog.vo; import cn.iocoder.yudao.framework.common.pojo.PageParam; import cn.iocoder.yudao.framework.common.validation.InEnum; import cn.iocoder.yudao.module.crm.enums.common.CrmSceneTypeEnum; -import cn.iocoder.yudao.module.crm.enums.message.CrmContactStatusEnum; import io.swagger.v3.oas.annotations.media.Schema; import lombok.Data; import lombok.EqualsAndHashCode; @@ -15,10 +14,12 @@ import lombok.ToString; @ToString(callSuper = true) public class CrmTodayCustomerPageReqVO extends PageParam { - // TODO @dbh52:CrmContactStatusEnum 可以直接枚举三个 Integer;一般来说,枚举类尽量给数据模型用,这样枚举类少,更聚焦;这里的枚举,更多是专门给这个接口用的哈 + public static final int CONTACT_TODAY = 1; + public static final int CONTACT_EXPIRED = 2; + public static final int CONTACT_ALREADY = 3; + @Schema(description = "联系状态", example = "1") - @InEnum(CrmContactStatusEnum.class) private Integer contactStatus; @Schema(description = "场景类型", example = "1") diff --git a/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/dal/mysql/customer/CrmCustomerMapper.java b/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/dal/mysql/customer/CrmCustomerMapper.java index 125249d14..925bc8bf3 100644 --- a/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/dal/mysql/customer/CrmCustomerMapper.java +++ b/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/dal/mysql/customer/CrmCustomerMapper.java @@ -4,20 +4,26 @@ import cn.iocoder.yudao.framework.common.pojo.PageResult; import cn.iocoder.yudao.framework.mybatis.core.mapper.BaseMapperX; import cn.iocoder.yudao.framework.mybatis.core.query.LambdaQueryWrapperX; import cn.iocoder.yudao.framework.mybatis.core.query.MPJLambdaWrapperX; +import cn.iocoder.yudao.module.crm.controller.admin.backlog.vo.CrmTodayCustomerPageReqVO; import cn.iocoder.yudao.module.crm.controller.admin.customer.vo.CrmCustomerPageReqVO; -import cn.iocoder.yudao.module.crm.controller.admin.message.vo.CrmTodayCustomerPageReqVO; import cn.iocoder.yudao.module.crm.dal.dataobject.customer.CrmCustomerDO; import cn.iocoder.yudao.module.crm.dal.dataobject.followup.CrmFollowUpRecordDO; import cn.iocoder.yudao.module.crm.enums.common.CrmBizTypeEnum; -import cn.iocoder.yudao.module.crm.enums.message.CrmContactStatusEnum; import cn.iocoder.yudao.module.crm.util.CrmQueryWrapperUtils; import com.baomidou.mybatisplus.core.conditions.update.LambdaUpdateWrapper; import org.apache.ibatis.annotations.Mapper; import org.springframework.lang.Nullable; import java.time.LocalDate; +import java.time.LocalDateTime; +import java.time.LocalTime; +import java.time.temporal.TemporalUnit; import java.util.Collection; import java.util.List; +import java.util.concurrent.TimeUnit; + +import static cn.iocoder.yudao.framework.common.exception.util.ServiceExceptionUtil.exception; +import static cn.iocoder.yudao.module.crm.enums.ErrorCodeConstants.BACKLOG_CONTACT_STATUS_ERROR; /** * 客户 Mapper @@ -80,41 +86,22 @@ public interface CrmCustomerMapper extends BaseMapperX { CrmQueryWrapperUtils.appendPermissionCondition(query, CrmBizTypeEnum.CRM_CUSTOMER.getType(), CrmCustomerDO::getId, userId, pageReqVO.getSceneType(), null); - query.selectAll(CrmCustomerDO.class) - .leftJoin(CrmFollowUpRecordDO.class, CrmFollowUpRecordDO::getBizId, CrmCustomerDO::getId) - .eq(CrmFollowUpRecordDO::getType, CrmBizTypeEnum.CRM_CUSTOMER.getType()); + query.selectAll(CrmCustomerDO.class); // 拼接自身的查询条件 - // TODO @dbh52:这里不仅仅要获得 today、tomorrow。而是 today 要获取今天的 00:00:00 这种; - LocalDate today = LocalDate.now(); - LocalDate tomorrow = today.plusDays(1); - LocalDate yesterday = today.minusDays(1); - if (pageReqVO.getContactStatus().equals(CrmContactStatusEnum.NEEDED_TODAY.getType())) { - // 今天需联系: - // 1.【客户】的【下一次联系时间】 是【今天】 - // 2. 无法找到【今天】创建的【跟进】记录 - query.between(CrmCustomerDO::getContactNextTime, today, tomorrow) - // TODO @dbh52:是不是查询 CrmCustomerDO::contactLastTime < today?因为今天联系过,应该会更新该字段,减少链表查询; - .between(CrmFollowUpRecordDO::getCreateTime, today, tomorrow) - .isNull(CrmFollowUpRecordDO::getId); - } else if (pageReqVO.getContactStatus().equals(CrmContactStatusEnum.EXPIRED.getType())) { - // 已逾期: - // 1. 【客户】的【下一次联系时间】 <= 【昨天】 - // 2. 无法找到【今天】创建的【跟进】记录 - // TODO @dbh52:是不是 contactNextTime 在当前时间之前,且 contactLastTime < contactNextTime?说白了,就是下次联系时间超过当前时间,且最后联系时间没去联系; - query.le(CrmCustomerDO::getContactNextTime, yesterday) - .between(CrmFollowUpRecordDO::getCreateTime, today, tomorrow) - .isNull(CrmFollowUpRecordDO::getId); - } else if (pageReqVO.getContactStatus().equals(CrmContactStatusEnum.ALREADY_CONTACT.getType())) { - // 已联系: - // 1.【客户】的【下一次联系时间】 是【今天】 - // 2. 找到【今天】创建的【跟进】记录 - query.between(CrmCustomerDO::getContactNextTime, today, tomorrow) - // TODO @dbh52:contactLastTime 是今天 - .between(CrmFollowUpRecordDO::getCreateTime, today, tomorrow) - .isNotNull(CrmFollowUpRecordDO::getId); + LocalDateTime beginOfToday = LocalDateTime.now().toLocalDate().atTime(LocalTime.MIN); + LocalDateTime endOfToday = LocalDateTime.now().toLocalDate().atTime(LocalTime.MAX); + if (pageReqVO.getContactStatus().equals(CrmTodayCustomerPageReqVO.CONTACT_TODAY)) { + // 今天需联系 + query.between(CrmCustomerDO::getContactNextTime, beginOfToday, endOfToday); + } else if (pageReqVO.getContactStatus().equals(CrmTodayCustomerPageReqVO.CONTACT_EXPIRED)) { + // 已逾期 + query.lt(CrmCustomerDO::getContactNextTime, beginOfToday); + } else if (pageReqVO.getContactStatus().equals(CrmTodayCustomerPageReqVO.CONTACT_ALREADY)) { + // 已联系 + query.between(CrmCustomerDO::getContactLastTime, beginOfToday, endOfToday); } else { - // TODO: 参数错误,是不是要兜一下底;直接抛出异常就好啦; + throw exception(BACKLOG_CONTACT_STATUS_ERROR); } return selectJoinPage(pageReqVO, CrmCustomerDO.class, query); diff --git a/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/service/message/CrmMessageService.java b/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/service/message/CrmBacklogService.java similarity index 60% rename from yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/service/message/CrmMessageService.java rename to yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/service/message/CrmBacklogService.java index c0bdb42e8..f13514c25 100644 --- a/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/service/message/CrmMessageService.java +++ b/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/service/message/CrmBacklogService.java @@ -1,22 +1,22 @@ package cn.iocoder.yudao.module.crm.service.message; import cn.iocoder.yudao.framework.common.pojo.PageResult; -import cn.iocoder.yudao.module.crm.controller.admin.message.vo.CrmTodayCustomerPageReqVO; +import cn.iocoder.yudao.module.crm.controller.admin.backlog.vo.CrmTodayCustomerPageReqVO; import cn.iocoder.yudao.module.crm.dal.dataobject.customer.CrmCustomerDO; import jakarta.validation.Valid; /** - * CRM 代办消息 Service 接口 + * CRM 待办消息 Service 接口 * * @author dhb52 */ -public interface CrmMessageService { +public interface CrmBacklogService { /** - * TODO @dbh52:注释要写下 + * 根据【联系状态】、【场景类型】筛选客户分页 * - * @param pageReqVO - * @return + * @param pageReqVO 分页查询 + * @return 分页数据 */ PageResult getTodayCustomerPage(@Valid CrmTodayCustomerPageReqVO pageReqVO, Long userId); diff --git a/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/service/message/CrmMessageServiceImpl.java b/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/service/message/CrmBacklogServiceImpl.java similarity index 80% rename from yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/service/message/CrmMessageServiceImpl.java rename to yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/service/message/CrmBacklogServiceImpl.java index 523a64671..ff2560f09 100644 --- a/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/service/message/CrmMessageServiceImpl.java +++ b/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/service/message/CrmBacklogServiceImpl.java @@ -1,17 +1,20 @@ package cn.iocoder.yudao.module.crm.service.message; import cn.iocoder.yudao.framework.common.pojo.PageResult; -import cn.iocoder.yudao.module.crm.controller.admin.message.vo.CrmTodayCustomerPageReqVO; +import cn.iocoder.yudao.module.crm.controller.admin.backlog.vo.CrmTodayCustomerPageReqVO; import cn.iocoder.yudao.module.crm.dal.dataobject.customer.CrmCustomerDO; import cn.iocoder.yudao.module.crm.dal.mysql.customer.CrmCustomerMapper; import jakarta.annotation.Resource; import org.springframework.stereotype.Component; import org.springframework.validation.annotation.Validated; -// TODO @dbh52:注释要写下 +/** + * 待办消息 Service 实现类 + */ + @Component @Validated -public class CrmMessageServiceImpl implements CrmMessageService { +public class CrmBacklogServiceImpl implements CrmBacklogService { @Resource private CrmCustomerMapper customerMapper; From 08e23a7dc4b40897c4da67e83f53ab9ba65e61ed Mon Sep 17 00:00:00 2001 From: dhb52 Date: Mon, 15 Jan 2024 22:47:46 +0800 Subject: [PATCH 002/119] wip: style-fix --- .../yudao/module/crm/enums/ErrorCodeConstants.java | 2 +- .../crm/dal/mysql/customer/CrmCustomerMapper.java | 12 ++++-------- 2 files changed, 5 insertions(+), 9 deletions(-) diff --git a/yudao-module-crm/yudao-module-crm-api/src/main/java/cn/iocoder/yudao/module/crm/enums/ErrorCodeConstants.java b/yudao-module-crm/yudao-module-crm-api/src/main/java/cn/iocoder/yudao/module/crm/enums/ErrorCodeConstants.java index 4543fe856..f2ad2d6f9 100644 --- a/yudao-module-crm/yudao-module-crm-api/src/main/java/cn/iocoder/yudao/module/crm/enums/ErrorCodeConstants.java +++ b/yudao-module-crm/yudao-module-crm-api/src/main/java/cn/iocoder/yudao/module/crm/enums/ErrorCodeConstants.java @@ -85,6 +85,6 @@ public interface ErrorCodeConstants { ErrorCode FOLLOW_UP_RECORD_NOT_EXISTS = new ErrorCode(1_020_013_000, "跟进记录不存在"); // ========== 待办消息 1_020_014_000 ========== - ErrorCode BACKLOG_CONTACT_STATUS_ERROR = new ErrorCode(1_020_014_000, "客户联系状态有误"); + ErrorCode BACKLOG_CONTACT_STATUS_INVALID = new ErrorCode(1_020_014_000, "客户联系状态有误"); } diff --git a/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/dal/mysql/customer/CrmCustomerMapper.java b/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/dal/mysql/customer/CrmCustomerMapper.java index 925bc8bf3..1c70b8267 100644 --- a/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/dal/mysql/customer/CrmCustomerMapper.java +++ b/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/dal/mysql/customer/CrmCustomerMapper.java @@ -7,23 +7,19 @@ import cn.iocoder.yudao.framework.mybatis.core.query.MPJLambdaWrapperX; import cn.iocoder.yudao.module.crm.controller.admin.backlog.vo.CrmTodayCustomerPageReqVO; import cn.iocoder.yudao.module.crm.controller.admin.customer.vo.CrmCustomerPageReqVO; import cn.iocoder.yudao.module.crm.dal.dataobject.customer.CrmCustomerDO; -import cn.iocoder.yudao.module.crm.dal.dataobject.followup.CrmFollowUpRecordDO; import cn.iocoder.yudao.module.crm.enums.common.CrmBizTypeEnum; import cn.iocoder.yudao.module.crm.util.CrmQueryWrapperUtils; import com.baomidou.mybatisplus.core.conditions.update.LambdaUpdateWrapper; import org.apache.ibatis.annotations.Mapper; import org.springframework.lang.Nullable; -import java.time.LocalDate; import java.time.LocalDateTime; import java.time.LocalTime; -import java.time.temporal.TemporalUnit; import java.util.Collection; import java.util.List; -import java.util.concurrent.TimeUnit; import static cn.iocoder.yudao.framework.common.exception.util.ServiceExceptionUtil.exception; -import static cn.iocoder.yudao.module.crm.enums.ErrorCodeConstants.BACKLOG_CONTACT_STATUS_ERROR; +import static cn.iocoder.yudao.module.crm.enums.ErrorCodeConstants.BACKLOG_CONTACT_STATUS_INVALID; /** * 客户 Mapper @@ -89,8 +85,8 @@ public interface CrmCustomerMapper extends BaseMapperX { query.selectAll(CrmCustomerDO.class); // 拼接自身的查询条件 - LocalDateTime beginOfToday = LocalDateTime.now().toLocalDate().atTime(LocalTime.MIN); - LocalDateTime endOfToday = LocalDateTime.now().toLocalDate().atTime(LocalTime.MAX); + LocalDateTime beginOfToday = LocalDateTime.now().toLocalDate().atTime(LocalTime.MIN); + LocalDateTime endOfToday = LocalDateTime.now().toLocalDate().atTime(LocalTime.MAX); if (pageReqVO.getContactStatus().equals(CrmTodayCustomerPageReqVO.CONTACT_TODAY)) { // 今天需联系 query.between(CrmCustomerDO::getContactNextTime, beginOfToday, endOfToday); @@ -101,7 +97,7 @@ public interface CrmCustomerMapper extends BaseMapperX { // 已联系 query.between(CrmCustomerDO::getContactLastTime, beginOfToday, endOfToday); } else { - throw exception(BACKLOG_CONTACT_STATUS_ERROR); + throw exception(BACKLOG_CONTACT_STATUS_INVALID); } return selectJoinPage(pageReqVO, CrmCustomerDO.class, query); From 5105c6d16fd63f79543ca9324e599ae6bf802b5b Mon Sep 17 00:00:00 2001 From: dhb52 Date: Tue, 16 Jan 2024 11:06:01 +0800 Subject: [PATCH 003/119] wip: LocalDate.now().atTime --- .../module/crm/dal/mysql/customer/CrmCustomerMapper.java | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/dal/mysql/customer/CrmCustomerMapper.java b/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/dal/mysql/customer/CrmCustomerMapper.java index 1c70b8267..e28883c8c 100644 --- a/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/dal/mysql/customer/CrmCustomerMapper.java +++ b/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/dal/mysql/customer/CrmCustomerMapper.java @@ -13,6 +13,7 @@ import com.baomidou.mybatisplus.core.conditions.update.LambdaUpdateWrapper; import org.apache.ibatis.annotations.Mapper; import org.springframework.lang.Nullable; +import java.time.LocalDate; import java.time.LocalDateTime; import java.time.LocalTime; import java.util.Collection; @@ -85,8 +86,8 @@ public interface CrmCustomerMapper extends BaseMapperX { query.selectAll(CrmCustomerDO.class); // 拼接自身的查询条件 - LocalDateTime beginOfToday = LocalDateTime.now().toLocalDate().atTime(LocalTime.MIN); - LocalDateTime endOfToday = LocalDateTime.now().toLocalDate().atTime(LocalTime.MAX); + LocalDateTime beginOfToday = LocalDate.now().atTime(LocalTime.MIN); + LocalDateTime endOfToday = LocalDate.now().atTime(LocalTime.MAX); if (pageReqVO.getContactStatus().equals(CrmTodayCustomerPageReqVO.CONTACT_TODAY)) { // 今天需联系 query.between(CrmCustomerDO::getContactNextTime, beginOfToday, endOfToday); From ba4f9207e20bf6555e307acb9a0f8e67527ec6f3 Mon Sep 17 00:00:00 2001 From: min Date: Sat, 20 Jan 2024 13:55:05 +0800 Subject: [PATCH 004/119] =?UTF-8?q?CRM=EF=BC=9A=E3=80=90=E7=BA=BF=E7=B4=A2?= =?UTF-8?q?=E3=80=91=E4=BD=BF=E7=94=A8=E5=B7=A5=E5=85=B7=E7=B1=BB=E6=9B=BF?= =?UTF-8?q?=E6=8D=A2stream=E6=93=8D=E4=BD=9C?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../crm/service/clue/CrmClueServiceImpl.java | 21 +++++++------------ 1 file changed, 8 insertions(+), 13 deletions(-) diff --git a/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/service/clue/CrmClueServiceImpl.java b/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/service/clue/CrmClueServiceImpl.java index 4a6ff9575..506424697 100644 --- a/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/service/clue/CrmClueServiceImpl.java +++ b/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/service/clue/CrmClueServiceImpl.java @@ -3,7 +3,9 @@ package cn.iocoder.yudao.module.crm.service.clue; import cn.hutool.core.collection.CollUtil; import cn.hutool.core.collection.ListUtil; import cn.hutool.core.util.ObjectUtil; +import cn.hutool.core.util.StrUtil; import cn.iocoder.yudao.framework.common.pojo.PageResult; +import cn.iocoder.yudao.framework.common.util.collection.CollectionUtils; import cn.iocoder.yudao.framework.common.util.object.BeanUtils; import cn.iocoder.yudao.module.crm.controller.admin.clue.vo.CrmCluePageReqVO; import cn.iocoder.yudao.module.crm.controller.admin.clue.vo.CrmClueSaveReqVO; @@ -25,11 +27,7 @@ import org.springframework.stereotype.Service; import org.springframework.transaction.annotation.Transactional; import org.springframework.validation.annotation.Validated; -import java.util.Collection; -import java.util.List; -import java.util.Objects; -import java.util.Set; -import java.util.stream.Collectors; +import java.util.*; import static cn.iocoder.yudao.framework.common.exception.util.ServiceExceptionUtil.exception; import static cn.iocoder.yudao.framework.common.util.collection.CollectionUtils.convertSet; @@ -145,19 +143,16 @@ public class CrmClueServiceImpl implements CrmClueService { List clues = getClueList(clueIds, userId); if (CollUtil.isEmpty(clues) || ObjectUtil.notEqual(clues.size(), clueIds.size())) { clueIds.removeAll(convertSet(clues, CrmClueDO::getId)); - // TODO @min:可以使用 StrUtil.join(",", clueIds) 简化这种常见操作 - throw exception(CLUE_ANY_CLUE_NOT_EXISTS, clueIds.stream().map(String::valueOf).collect(Collectors.joining(","))); + throw exception(CLUE_ANY_CLUE_NOT_EXISTS, StrUtil.join(",", clueIds)); } // 过滤出未转化的客户 - // TODO @min:1)存在已经转化的,直接提示哈。避免操作的用户,以为都转化成功了;2)常见的过滤逻辑,可以使用 CollectionUtils.filterList() - List unTransformClues = clues.stream() - .filter(clue -> ObjectUtil.notEqual(Boolean.TRUE, clue.getTransformStatus())).toList(); - // 传入的线索中包含已经转化的情况,抛出业务异常 + List unTransformClues = CollectionUtils.filterList(clues, + clue -> ObjectUtil.notEqual(Boolean.TRUE, clue.getTransformStatus())); + // 存在已经转化的,直接提示哈。避免操作的用户,以为都转化成功了 if (ObjectUtil.notEqual(clues.size(), unTransformClues.size())) { - // TODO @min:可以使用 StrUtil.join(",", clueIds) 简化这种常见操作 clueIds.removeAll(convertSet(unTransformClues, CrmClueDO::getId)); - throw exception(CLUE_ANY_CLUE_ALREADY_TRANSLATED, clueIds.stream().map(String::valueOf).collect(Collectors.joining(","))); + throw exception(CLUE_ANY_CLUE_ALREADY_TRANSLATED, StrUtil.join(",", clueIds)); } // 遍历线索(未转化的线索),创建对应的客户 From 7914423c66b8f1960d7c4bbf014e9db5399c2fb7 Mon Sep 17 00:00:00 2001 From: puhui999 Date: Sat, 20 Jan 2024 14:56:31 +0800 Subject: [PATCH 005/119] =?UTF-8?q?CRM:=20=E5=AE=8C=E5=96=84=E8=B7=9F?= =?UTF-8?q?=E8=BF=9B=20TODO?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../convert/business/CrmBusinessConvert.java | 9 ++ .../convert/contact/CrmContactConvert.java | 8 ++ .../service/business/CrmBusinessService.java | 4 +- .../business/CrmBusinessServiceImpl.java | 6 +- .../bo/CrmBusinessUpdateFollowUpReqBO.java | 38 ------- .../crm/service/clue/CrmClueService.java | 4 +- .../crm/service/clue/CrmClueServiceImpl.java | 6 +- .../service/contact/CrmContactService.java | 4 +- .../contact/CrmContactServiceImpl.java | 6 +- .../bo/CrmContactUpdateFollowUpReqBO.java | 38 ------- .../service/contract/CrmContractService.java | 4 +- .../contract/CrmContractServiceImpl.java | 6 +- .../bo/CrmContractUpdateFollowUpReqBO.java | 38 ------- .../service/customer/CrmCustomerService.java | 4 +- .../customer/CrmCustomerServiceImpl.java | 6 +- .../bo/CrmCustomerUpdateFollowUpReqBO.java | 33 ------ .../CrmFollowUpRecordServiceImpl.java | 104 ++++++++++++++---- .../bo/CrmUpdateFollowUpReqBO.java} | 15 ++- .../handle/CrmBusinessFollowUpHandler.java | 38 ------- .../handle/CrmClueFollowUpHandler.java | 37 ------- .../handle/CrmContactFollowUpHandler.java | 38 ------- .../handle/CrmContractFollowUpHandler.java | 37 ------- .../handle/CrmCustomerFollowUpHandler.java | 37 ------- .../followup/handle/CrmFollowUpHandler.java | 23 ---- .../comment/ProductCommentConvert.java | 4 + .../ProductCommentServiceImplTest.java | 11 +- 26 files changed, 143 insertions(+), 415 deletions(-) delete mode 100644 yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/service/business/bo/CrmBusinessUpdateFollowUpReqBO.java delete mode 100644 yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/service/contact/bo/CrmContactUpdateFollowUpReqBO.java delete mode 100644 yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/service/contract/bo/CrmContractUpdateFollowUpReqBO.java delete mode 100644 yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/service/customer/bo/CrmCustomerUpdateFollowUpReqBO.java rename yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/service/{clue/bo/CrmClueUpdateFollowUpReqBO.java => followup/bo/CrmUpdateFollowUpReqBO.java} (67%) delete mode 100644 yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/service/followup/handle/CrmBusinessFollowUpHandler.java delete mode 100644 yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/service/followup/handle/CrmClueFollowUpHandler.java delete mode 100644 yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/service/followup/handle/CrmContactFollowUpHandler.java delete mode 100644 yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/service/followup/handle/CrmContractFollowUpHandler.java delete mode 100644 yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/service/followup/handle/CrmCustomerFollowUpHandler.java delete mode 100644 yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/service/followup/handle/CrmFollowUpHandler.java diff --git a/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/convert/business/CrmBusinessConvert.java b/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/convert/business/CrmBusinessConvert.java index 63c8ab7d6..56bba541e 100644 --- a/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/convert/business/CrmBusinessConvert.java +++ b/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/convert/business/CrmBusinessConvert.java @@ -1,6 +1,7 @@ package cn.iocoder.yudao.module.crm.convert.business; import cn.iocoder.yudao.framework.common.pojo.PageResult; +import cn.iocoder.yudao.framework.common.util.collection.CollectionUtils; import cn.iocoder.yudao.framework.common.util.object.BeanUtils; import cn.iocoder.yudao.module.crm.controller.admin.business.vo.business.CrmBusinessRespVO; import cn.iocoder.yudao.module.crm.controller.admin.business.vo.business.CrmBusinessTransferReqVO; @@ -8,6 +9,7 @@ import cn.iocoder.yudao.module.crm.dal.dataobject.business.CrmBusinessDO; import cn.iocoder.yudao.module.crm.dal.dataobject.business.CrmBusinessStatusDO; import cn.iocoder.yudao.module.crm.dal.dataobject.business.CrmBusinessStatusTypeDO; import cn.iocoder.yudao.module.crm.dal.dataobject.customer.CrmCustomerDO; +import cn.iocoder.yudao.module.crm.service.followup.bo.CrmUpdateFollowUpReqBO; import cn.iocoder.yudao.module.crm.service.permission.bo.CrmPermissionTransferReqBO; import org.mapstruct.Mapper; import org.mapstruct.Mapping; @@ -45,4 +47,11 @@ public interface CrmBusinessConvert { return voPageResult; } + @Mapping(target = "id", source = "reqBO.bizId") + CrmBusinessDO convert(CrmUpdateFollowUpReqBO reqBO); + + default List convertList(List updateFollowUpReqBOList) { + return CollectionUtils.convertList(updateFollowUpReqBOList, INSTANCE::convert); + } + } diff --git a/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/convert/contact/CrmContactConvert.java b/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/convert/contact/CrmContactConvert.java index 363fd4f60..1d32331bb 100644 --- a/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/convert/contact/CrmContactConvert.java +++ b/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/convert/contact/CrmContactConvert.java @@ -8,6 +8,7 @@ import cn.iocoder.yudao.module.crm.controller.admin.contact.vo.CrmContactRespVO; import cn.iocoder.yudao.module.crm.controller.admin.contact.vo.CrmContactTransferReqVO; import cn.iocoder.yudao.module.crm.dal.dataobject.contact.CrmContactDO; import cn.iocoder.yudao.module.crm.dal.dataobject.customer.CrmCustomerDO; +import cn.iocoder.yudao.module.crm.service.followup.bo.CrmUpdateFollowUpReqBO; import cn.iocoder.yudao.module.crm.service.permission.bo.CrmPermissionTransferReqBO; import cn.iocoder.yudao.module.system.api.user.dto.AdminUserRespDTO; import org.mapstruct.Mapper; @@ -66,4 +67,11 @@ public interface CrmContactConvert { findAndThen(userMap, Long.parseLong(contactRespVO.getCreator()), user -> contactRespVO.setCreatorName(user.getNickname())); } + @Mapping(target = "id", source = "reqBO.bizId") + CrmContactDO convert(CrmUpdateFollowUpReqBO reqBO); + + default List convertList(List updateFollowUpReqBOList) { + return CollectionUtils.convertList(updateFollowUpReqBOList, INSTANCE::convert); + } + } diff --git a/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/service/business/CrmBusinessService.java b/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/service/business/CrmBusinessService.java index 8dae99eb8..fde5551c1 100644 --- a/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/service/business/CrmBusinessService.java +++ b/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/service/business/CrmBusinessService.java @@ -7,7 +7,7 @@ import cn.iocoder.yudao.module.crm.controller.admin.business.vo.business.CrmBusi import cn.iocoder.yudao.module.crm.dal.dataobject.business.CrmBusinessDO; import cn.iocoder.yudao.module.crm.dal.dataobject.contact.CrmContactDO; import cn.iocoder.yudao.module.crm.dal.dataobject.customer.CrmCustomerDO; -import cn.iocoder.yudao.module.crm.service.business.bo.CrmBusinessUpdateFollowUpReqBO; +import cn.iocoder.yudao.module.crm.service.followup.bo.CrmUpdateFollowUpReqBO; import jakarta.validation.Valid; import java.util.Collection; @@ -41,7 +41,7 @@ public interface CrmBusinessService { * * @param updateFollowUpReqBOList 跟进信息 */ - void updateContactFollowUpBatch(List updateFollowUpReqBOList); + void updateBusinessFollowUpBatch(List updateFollowUpReqBOList); /** * 删除商机 diff --git a/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/service/business/CrmBusinessServiceImpl.java b/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/service/business/CrmBusinessServiceImpl.java index a4d08f315..58c0851b5 100644 --- a/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/service/business/CrmBusinessServiceImpl.java +++ b/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/service/business/CrmBusinessServiceImpl.java @@ -21,8 +21,8 @@ import cn.iocoder.yudao.module.crm.dal.mysql.contract.CrmContractMapper; import cn.iocoder.yudao.module.crm.enums.common.CrmBizTypeEnum; import cn.iocoder.yudao.module.crm.enums.permission.CrmPermissionLevelEnum; import cn.iocoder.yudao.module.crm.framework.permission.core.annotations.CrmPermission; -import cn.iocoder.yudao.module.crm.service.business.bo.CrmBusinessUpdateFollowUpReqBO; import cn.iocoder.yudao.module.crm.service.contact.CrmContactBusinessService; +import cn.iocoder.yudao.module.crm.service.followup.bo.CrmUpdateFollowUpReqBO; import cn.iocoder.yudao.module.crm.service.permission.CrmPermissionService; import cn.iocoder.yudao.module.crm.service.permission.bo.CrmPermissionCreateReqBO; import com.mzt.logapi.context.LogRecordContext; @@ -172,8 +172,8 @@ public class CrmBusinessServiceImpl implements CrmBusinessService { } @Override - public void updateContactFollowUpBatch(List updateFollowUpReqBOList) { - businessMapper.updateBatch(BeanUtils.toBean(updateFollowUpReqBOList, CrmBusinessDO.class)); + public void updateBusinessFollowUpBatch(List updateFollowUpReqBOList) { + businessMapper.updateBatch(CrmBusinessConvert.INSTANCE.convertList(updateFollowUpReqBOList)); } @Override diff --git a/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/service/business/bo/CrmBusinessUpdateFollowUpReqBO.java b/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/service/business/bo/CrmBusinessUpdateFollowUpReqBO.java deleted file mode 100644 index ccf8d0a0a..000000000 --- a/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/service/business/bo/CrmBusinessUpdateFollowUpReqBO.java +++ /dev/null @@ -1,38 +0,0 @@ -package cn.iocoder.yudao.module.crm.service.business.bo; - -import com.mzt.logapi.starter.annotation.DiffLogField; -import io.swagger.v3.oas.annotations.media.Schema; -import jakarta.validation.constraints.NotNull; -import lombok.Data; - -import java.time.LocalDateTime; - -// TODO @puhui999:是不是搞个通用的 ReqBO 就好了 -/** - * 商机跟进信息 Update Req BO - * - * @author HUIHUI - */ -@Data -public class CrmBusinessUpdateFollowUpReqBO { - - @Schema(description = "商机编号", example = "3167") - @NotNull(message = "商机编号不能为空") - private Long id; - - @Schema(description = "最后跟进时间") - @DiffLogField(name = "最后跟进时间") - @NotNull(message = "最后跟进时间不能为空") - private LocalDateTime contactLastTime; - - @Schema(description = "下次联系时间") - @DiffLogField(name = "下次联系时间") - @NotNull(message = "下次联系时间不能为空") - private LocalDateTime contactNextTime; - - @Schema(description = "最后更进内容") - @DiffLogField(name = "最后更进内容") - @NotNull(message = "最后更进内容不能为空") - private String contactLastContent; - -} diff --git a/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/service/clue/CrmClueService.java b/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/service/clue/CrmClueService.java index 47ece94e2..6efffa96a 100644 --- a/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/service/clue/CrmClueService.java +++ b/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/service/clue/CrmClueService.java @@ -6,7 +6,7 @@ import cn.iocoder.yudao.module.crm.controller.admin.clue.vo.CrmClueSaveReqVO; import cn.iocoder.yudao.module.crm.controller.admin.clue.vo.CrmClueTransferReqVO; import cn.iocoder.yudao.module.crm.controller.admin.clue.vo.CrmClueTransformReqVO; import cn.iocoder.yudao.module.crm.dal.dataobject.clue.CrmClueDO; -import cn.iocoder.yudao.module.crm.service.clue.bo.CrmClueUpdateFollowUpReqBO; +import cn.iocoder.yudao.module.crm.service.followup.bo.CrmUpdateFollowUpReqBO; import jakarta.validation.Valid; import java.util.Collection; @@ -39,7 +39,7 @@ public interface CrmClueService { * * @param clueUpdateFollowUpReqBO 信息 */ - void updateClueFollowUp(CrmClueUpdateFollowUpReqBO clueUpdateFollowUpReqBO); + void updateClueFollowUp(CrmUpdateFollowUpReqBO clueUpdateFollowUpReqBO); /** * 删除线索 diff --git a/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/service/clue/CrmClueServiceImpl.java b/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/service/clue/CrmClueServiceImpl.java index 4a6ff9575..9bec56064 100644 --- a/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/service/clue/CrmClueServiceImpl.java +++ b/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/service/clue/CrmClueServiceImpl.java @@ -16,8 +16,8 @@ import cn.iocoder.yudao.module.crm.dal.mysql.clue.CrmClueMapper; import cn.iocoder.yudao.module.crm.enums.common.CrmBizTypeEnum; import cn.iocoder.yudao.module.crm.enums.permission.CrmPermissionLevelEnum; import cn.iocoder.yudao.module.crm.framework.permission.core.annotations.CrmPermission; -import cn.iocoder.yudao.module.crm.service.clue.bo.CrmClueUpdateFollowUpReqBO; import cn.iocoder.yudao.module.crm.service.customer.CrmCustomerService; +import cn.iocoder.yudao.module.crm.service.followup.bo.CrmUpdateFollowUpReqBO; import cn.iocoder.yudao.module.crm.service.permission.CrmPermissionService; import cn.iocoder.yudao.module.system.api.user.AdminUserApi; import jakarta.annotation.Resource; @@ -84,8 +84,8 @@ public class CrmClueServiceImpl implements CrmClueService { } @Override - public void updateClueFollowUp(CrmClueUpdateFollowUpReqBO clueUpdateFollowUpReqBO) { - clueMapper.updateById(BeanUtils.toBean(clueUpdateFollowUpReqBO, CrmClueDO.class)); + public void updateClueFollowUp(CrmUpdateFollowUpReqBO clueUpdateFollowUpReqBO) { + clueMapper.updateById(BeanUtils.toBean(clueUpdateFollowUpReqBO, CrmClueDO.class).setId(clueUpdateFollowUpReqBO.getBizId())); } @Override diff --git a/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/service/contact/CrmContactService.java b/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/service/contact/CrmContactService.java index 5962db9a8..a43ed2e65 100644 --- a/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/service/contact/CrmContactService.java +++ b/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/service/contact/CrmContactService.java @@ -6,7 +6,7 @@ import cn.iocoder.yudao.module.crm.controller.admin.contact.vo.CrmContactSaveReq import cn.iocoder.yudao.module.crm.controller.admin.contact.vo.CrmContactTransferReqVO; import cn.iocoder.yudao.module.crm.dal.dataobject.contact.CrmContactDO; import cn.iocoder.yudao.module.crm.dal.dataobject.customer.CrmCustomerDO; -import cn.iocoder.yudao.module.crm.service.contact.bo.CrmContactUpdateFollowUpReqBO; +import cn.iocoder.yudao.module.crm.service.followup.bo.CrmUpdateFollowUpReqBO; import jakarta.validation.Valid; import java.util.Collection; @@ -63,7 +63,7 @@ public interface CrmContactService { * * @param updateFollowUpReqBOList 跟进信息 */ - void updateContactFollowUpBatch(List updateFollowUpReqBOList); + void updateContactFollowUpBatch(List updateFollowUpReqBOList); /** * 获得联系人 diff --git a/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/service/contact/CrmContactServiceImpl.java b/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/service/contact/CrmContactServiceImpl.java index 7b6f83e04..52f2d6cf7 100644 --- a/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/service/contact/CrmContactServiceImpl.java +++ b/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/service/contact/CrmContactServiceImpl.java @@ -15,9 +15,9 @@ import cn.iocoder.yudao.module.crm.enums.common.CrmBizTypeEnum; import cn.iocoder.yudao.module.crm.enums.permission.CrmPermissionLevelEnum; import cn.iocoder.yudao.module.crm.framework.permission.core.annotations.CrmPermission; import cn.iocoder.yudao.module.crm.service.business.CrmBusinessService; -import cn.iocoder.yudao.module.crm.service.contact.bo.CrmContactUpdateFollowUpReqBO; import cn.iocoder.yudao.module.crm.service.contract.CrmContractService; import cn.iocoder.yudao.module.crm.service.customer.CrmCustomerService; +import cn.iocoder.yudao.module.crm.service.followup.bo.CrmUpdateFollowUpReqBO; import cn.iocoder.yudao.module.crm.service.permission.CrmPermissionService; import cn.iocoder.yudao.module.crm.service.permission.bo.CrmPermissionCreateReqBO; import cn.iocoder.yudao.module.system.api.user.AdminUserApi; @@ -195,8 +195,8 @@ public class CrmContactServiceImpl implements CrmContactService { } @Override - public void updateContactFollowUpBatch(List updateFollowUpReqBOList) { - contactMapper.updateBatch(BeanUtils.toBean(updateFollowUpReqBOList, CrmContactDO.class)); + public void updateContactFollowUpBatch(List updateFollowUpReqBOList) { + contactMapper.updateBatch(CrmContactConvert.INSTANCE.convertList(updateFollowUpReqBOList)); } //======================= 查询相关 ======================= diff --git a/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/service/contact/bo/CrmContactUpdateFollowUpReqBO.java b/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/service/contact/bo/CrmContactUpdateFollowUpReqBO.java deleted file mode 100644 index 40604353e..000000000 --- a/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/service/contact/bo/CrmContactUpdateFollowUpReqBO.java +++ /dev/null @@ -1,38 +0,0 @@ -package cn.iocoder.yudao.module.crm.service.contact.bo; - -import com.mzt.logapi.starter.annotation.DiffLogField; -import io.swagger.v3.oas.annotations.media.Schema; -import jakarta.validation.constraints.NotNull; -import lombok.Data; - -import java.time.LocalDateTime; - -// TODO @puhui999:是不是搞个通用的 ReqBO 就好了 -/** - * 联系人跟进信息 Update Req BO - * - * @author HUIHUI - */ -@Data -public class CrmContactUpdateFollowUpReqBO { - - @Schema(description = "联系人编号", example = "3167") - @NotNull(message = "联系人编号不能为空") - private Long id; - - @Schema(description = "最后跟进时间") - @DiffLogField(name = "最后跟进时间") - @NotNull(message = "最后跟进时间不能为空") - private LocalDateTime contactLastTime; - - @Schema(description = "下次联系时间") - @DiffLogField(name = "下次联系时间") - @NotNull(message = "下次联系时间不能为空") - private LocalDateTime contactNextTime; - - @Schema(description = "最后更进内容") - @DiffLogField(name = "最后更进内容") - @NotNull(message = "最后更进内容不能为空") - private String contactLastContent; - -} diff --git a/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/service/contract/CrmContractService.java b/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/service/contract/CrmContractService.java index 26a9256f2..ec52d85c0 100644 --- a/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/service/contract/CrmContractService.java +++ b/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/service/contract/CrmContractService.java @@ -6,7 +6,7 @@ import cn.iocoder.yudao.module.crm.controller.admin.contract.vo.CrmContractSaveR import cn.iocoder.yudao.module.crm.controller.admin.contract.vo.CrmContractTransferReqVO; import cn.iocoder.yudao.module.crm.dal.dataobject.contract.CrmContractDO; import cn.iocoder.yudao.module.crm.dal.dataobject.customer.CrmCustomerDO; -import cn.iocoder.yudao.module.crm.service.contract.bo.CrmContractUpdateFollowUpReqBO; +import cn.iocoder.yudao.module.crm.service.followup.bo.CrmUpdateFollowUpReqBO; import jakarta.validation.Valid; import java.util.Collection; @@ -55,7 +55,7 @@ public interface CrmContractService { * * @param contractUpdateFollowUpReqBO 信息 */ - void updateContractFollowUp(CrmContractUpdateFollowUpReqBO contractUpdateFollowUpReqBO); + void updateContractFollowUp(CrmUpdateFollowUpReqBO contractUpdateFollowUpReqBO); /** * 获得合同 diff --git a/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/service/contract/CrmContractServiceImpl.java b/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/service/contract/CrmContractServiceImpl.java index b9142dd35..dc921e952 100644 --- a/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/service/contract/CrmContractServiceImpl.java +++ b/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/service/contract/CrmContractServiceImpl.java @@ -13,7 +13,7 @@ import cn.iocoder.yudao.module.crm.dal.mysql.contract.CrmContractMapper; import cn.iocoder.yudao.module.crm.enums.common.CrmBizTypeEnum; import cn.iocoder.yudao.module.crm.enums.permission.CrmPermissionLevelEnum; import cn.iocoder.yudao.module.crm.framework.permission.core.annotations.CrmPermission; -import cn.iocoder.yudao.module.crm.service.contract.bo.CrmContractUpdateFollowUpReqBO; +import cn.iocoder.yudao.module.crm.service.followup.bo.CrmUpdateFollowUpReqBO; import cn.iocoder.yudao.module.crm.service.permission.CrmPermissionService; import cn.iocoder.yudao.module.crm.service.permission.bo.CrmPermissionCreateReqBO; import com.mzt.logapi.context.LogRecordContext; @@ -137,8 +137,8 @@ public class CrmContractServiceImpl implements CrmContractService { } @Override - public void updateContractFollowUp(CrmContractUpdateFollowUpReqBO contractUpdateFollowUpReqBO) { - contractMapper.updateById(BeanUtils.toBean(contractUpdateFollowUpReqBO, CrmContractDO.class)); + public void updateContractFollowUp(CrmUpdateFollowUpReqBO contractUpdateFollowUpReqBO) { + contractMapper.updateById(BeanUtils.toBean(contractUpdateFollowUpReqBO, CrmContractDO.class).setId(contractUpdateFollowUpReqBO.getBizId())); } //======================= 查询相关 ======================= diff --git a/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/service/contract/bo/CrmContractUpdateFollowUpReqBO.java b/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/service/contract/bo/CrmContractUpdateFollowUpReqBO.java deleted file mode 100644 index 57c1f5f50..000000000 --- a/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/service/contract/bo/CrmContractUpdateFollowUpReqBO.java +++ /dev/null @@ -1,38 +0,0 @@ -package cn.iocoder.yudao.module.crm.service.contract.bo; - -import com.mzt.logapi.starter.annotation.DiffLogField; -import io.swagger.v3.oas.annotations.media.Schema; -import jakarta.validation.constraints.NotNull; -import lombok.Data; - -import java.time.LocalDateTime; - -// TODO @puhui999:是不是搞个通用的 ReqBO 就好了 -/** - * 合同跟进信息 Update Req BO - * - * @author HUIHUI - */ -@Data -public class CrmContractUpdateFollowUpReqBO { - - @Schema(description = "合同编号", example = "3167") - @NotNull(message = "合同编号不能为空") - private Long id; - - @Schema(description = "最后跟进时间") - @DiffLogField(name = "最后跟进时间") - @NotNull(message = "最后跟进时间不能为空") - private LocalDateTime contactLastTime; - - @Schema(description = "下次联系时间") - @DiffLogField(name = "下次联系时间") - @NotNull(message = "下次联系时间不能为空") - private LocalDateTime contactNextTime; - - @Schema(description = "最后更进内容") - @DiffLogField(name = "最后更进内容") - @NotNull(message = "最后更进内容不能为空") - private String contactLastContent; - -} diff --git a/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/service/customer/CrmCustomerService.java b/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/service/customer/CrmCustomerService.java index d40b08118..8cd2448b7 100644 --- a/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/service/customer/CrmCustomerService.java +++ b/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/service/customer/CrmCustomerService.java @@ -6,7 +6,7 @@ import cn.iocoder.yudao.module.crm.controller.admin.customer.vo.CrmCustomerPageR import cn.iocoder.yudao.module.crm.controller.admin.customer.vo.CrmCustomerSaveReqVO; import cn.iocoder.yudao.module.crm.controller.admin.customer.vo.CrmCustomerTransferReqVO; import cn.iocoder.yudao.module.crm.dal.dataobject.customer.CrmCustomerDO; -import cn.iocoder.yudao.module.crm.service.customer.bo.CrmCustomerUpdateFollowUpReqBO; +import cn.iocoder.yudao.module.crm.service.followup.bo.CrmUpdateFollowUpReqBO; import jakarta.validation.Valid; import java.util.Collection; @@ -96,7 +96,7 @@ public interface CrmCustomerService { * * @param customerUpdateFollowUpReqBO 请求 */ - void updateCustomerFollowUp(CrmCustomerUpdateFollowUpReqBO customerUpdateFollowUpReqBO); + void updateCustomerFollowUp(CrmUpdateFollowUpReqBO customerUpdateFollowUpReqBO); // ==================== 公海相关操作 ==================== diff --git a/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/service/customer/CrmCustomerServiceImpl.java b/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/service/customer/CrmCustomerServiceImpl.java index a88b230e3..5c1f5134a 100644 --- a/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/service/customer/CrmCustomerServiceImpl.java +++ b/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/service/customer/CrmCustomerServiceImpl.java @@ -21,7 +21,7 @@ import cn.iocoder.yudao.module.crm.framework.permission.core.util.CrmPermissionU import cn.iocoder.yudao.module.crm.service.business.CrmBusinessService; import cn.iocoder.yudao.module.crm.service.contact.CrmContactService; import cn.iocoder.yudao.module.crm.service.contract.CrmContractService; -import cn.iocoder.yudao.module.crm.service.customer.bo.CrmCustomerUpdateFollowUpReqBO; +import cn.iocoder.yudao.module.crm.service.followup.bo.CrmUpdateFollowUpReqBO; import cn.iocoder.yudao.module.crm.service.permission.CrmPermissionService; import cn.iocoder.yudao.module.crm.service.permission.bo.CrmPermissionCreateReqBO; import cn.iocoder.yudao.module.system.api.user.AdminUserApi; @@ -205,8 +205,8 @@ public class CrmCustomerServiceImpl implements CrmCustomerService { } @Override - public void updateCustomerFollowUp(CrmCustomerUpdateFollowUpReqBO customerUpdateFollowUpReqBO) { - customerMapper.updateById(BeanUtils.toBean(customerUpdateFollowUpReqBO, CrmCustomerDO.class)); + public void updateCustomerFollowUp(CrmUpdateFollowUpReqBO customerUpdateFollowUpReqBO) { + customerMapper.updateById(BeanUtils.toBean(customerUpdateFollowUpReqBO, CrmCustomerDO.class).setId(customerUpdateFollowUpReqBO.getBizId())); } // ==================== 公海相关操作 ==================== diff --git a/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/service/customer/bo/CrmCustomerUpdateFollowUpReqBO.java b/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/service/customer/bo/CrmCustomerUpdateFollowUpReqBO.java deleted file mode 100644 index 2ba7fbb05..000000000 --- a/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/service/customer/bo/CrmCustomerUpdateFollowUpReqBO.java +++ /dev/null @@ -1,33 +0,0 @@ -package cn.iocoder.yudao.module.crm.service.customer.bo; - -import com.mzt.logapi.starter.annotation.DiffLogField; -import io.swagger.v3.oas.annotations.media.Schema; -import lombok.Data; - -import java.time.LocalDateTime; - -// TODO @puhui999:是不是搞个通用的 ReqBO 就好了 -/** - * 跟进信息 Update Req BO - * - * @author HUIHUI - */ -@Data -public class CrmCustomerUpdateFollowUpReqBO { - - @Schema(description = "主键", example = "3167") - private Long id; - - @Schema(description = "最后跟进时间") - @DiffLogField(name = "最后跟进时间") - private LocalDateTime contactLastTime; - - @Schema(description = "下次联系时间") - @DiffLogField(name = "下次联系时间") - private LocalDateTime contactNextTime; - - @Schema(description = "最后更进内容") - @DiffLogField(name = "最后更进内容") - private String contactLastContent; - -} diff --git a/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/service/followup/CrmFollowUpRecordServiceImpl.java b/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/service/followup/CrmFollowUpRecordServiceImpl.java index f1c98e7d7..d812ce048 100644 --- a/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/service/followup/CrmFollowUpRecordServiceImpl.java +++ b/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/service/followup/CrmFollowUpRecordServiceImpl.java @@ -9,19 +9,22 @@ import cn.iocoder.yudao.module.crm.controller.admin.followup.vo.CrmFollowUpRecor import cn.iocoder.yudao.module.crm.dal.dataobject.followup.CrmFollowUpRecordDO; import cn.iocoder.yudao.module.crm.dal.dataobject.permission.CrmPermissionDO; import cn.iocoder.yudao.module.crm.dal.mysql.followup.CrmFollowUpRecordMapper; +import cn.iocoder.yudao.module.crm.enums.common.CrmBizTypeEnum; import cn.iocoder.yudao.module.crm.enums.permission.CrmPermissionLevelEnum; import cn.iocoder.yudao.module.crm.framework.permission.core.annotations.CrmPermission; import cn.iocoder.yudao.module.crm.service.business.CrmBusinessService; -import cn.iocoder.yudao.module.crm.service.business.bo.CrmBusinessUpdateFollowUpReqBO; +import cn.iocoder.yudao.module.crm.service.clue.CrmClueService; import cn.iocoder.yudao.module.crm.service.contact.CrmContactService; -import cn.iocoder.yudao.module.crm.service.contact.bo.CrmContactUpdateFollowUpReqBO; -import cn.iocoder.yudao.module.crm.service.followup.handle.CrmFollowUpHandler; +import cn.iocoder.yudao.module.crm.service.contract.CrmContractService; +import cn.iocoder.yudao.module.crm.service.customer.CrmCustomerService; +import cn.iocoder.yudao.module.crm.service.followup.bo.CrmUpdateFollowUpReqBO; import cn.iocoder.yudao.module.crm.service.permission.CrmPermissionService; import jakarta.annotation.Resource; import org.springframework.stereotype.Service; import org.springframework.validation.annotation.Validated; import java.time.LocalDateTime; +import java.util.Collections; import java.util.List; import static cn.iocoder.yudao.framework.common.exception.util.ServiceExceptionUtil.exception; @@ -45,11 +48,15 @@ public class CrmFollowUpRecordServiceImpl implements CrmFollowUpRecordService { @Resource private CrmPermissionService permissionService; @Resource - private List followUpHandlers; - @Resource private CrmBusinessService businessService; @Resource + private CrmClueService clueService; + @Resource private CrmContactService contactService; + @Resource + private CrmContractService contractService; + @Resource + private CrmCustomerService customerService; @Override @CrmPermission(bizTypeValue = "#createReqVO.bizType", bizId = "#createReqVO.bizId", level = CrmPermissionLevelEnum.WRITE) @@ -60,29 +67,88 @@ public class CrmFollowUpRecordServiceImpl implements CrmFollowUpRecordService { LocalDateTime now = LocalDateTime.now(); // 2. 更新 bizId 对应的记录; - followUpHandlers.forEach(handler -> handler.execute(followUpRecord, now)); + updateBizTypeFollowUp(followUpRecord, now); // 3.1 更新 contactIds 对应的记录 if (CollUtil.isNotEmpty(createReqVO.getContactIds())) { - // TODO @puhui999:可以用链式设置哈 - contactService.updateContactFollowUpBatch(convertList(createReqVO.getContactIds(), contactId -> { - CrmContactUpdateFollowUpReqBO crmContactUpdateFollowUpReqBO = new CrmContactUpdateFollowUpReqBO(); - crmContactUpdateFollowUpReqBO.setId(contactId).setContactNextTime(followUpRecord.getNextTime()) - .setContactLastTime(now).setContactLastContent(followUpRecord.getContent()); - return crmContactUpdateFollowUpReqBO; - })); + contactService.updateContactFollowUpBatch(convertList(createReqVO.getContactIds(), contactId -> + new CrmUpdateFollowUpReqBO().setBizId(contactId).setContactNextTime(followUpRecord.getNextTime()) + .setContactLastTime(now).setContactLastContent(followUpRecord.getContent()))); } // 3.2 需要更新 businessIds、contactIds 对应的记录 if (CollUtil.isNotEmpty(createReqVO.getBusinessIds())) { - businessService.updateContactFollowUpBatch(convertList(createReqVO.getBusinessIds(), businessId -> { - CrmBusinessUpdateFollowUpReqBO crmBusinessUpdateFollowUpReqBO = new CrmBusinessUpdateFollowUpReqBO(); - crmBusinessUpdateFollowUpReqBO.setId(businessId).setContactNextTime(followUpRecord.getNextTime()) - .setContactLastTime(now).setContactLastContent(followUpRecord.getContent()); - return crmBusinessUpdateFollowUpReqBO; - })); + businessService.updateBusinessFollowUpBatch(convertList(createReqVO.getBusinessIds(), businessId -> + new CrmUpdateFollowUpReqBO().setBizId(businessId).setContactNextTime(followUpRecord.getNextTime()) + .setContactLastTime(now).setContactLastContent(followUpRecord.getContent()))); } return followUpRecord.getId(); } + /** + * 执行更新 + * + * @param followUpRecord 跟进记录 + * @param now 跟进时间 + */ + private void updateBizTypeFollowUp(CrmFollowUpRecordDO followUpRecord, LocalDateTime now) { + updateBusinessFollowUp(followUpRecord, now); + updateClueFollowUp(followUpRecord, now); + updateContactFollowUp(followUpRecord, now); + updateContractFollowUp(followUpRecord, now); + updateCustomerFollowUp(followUpRecord, now); + } + + private void updateBusinessFollowUp(CrmFollowUpRecordDO followUpRecord, LocalDateTime now) { + if (ObjUtil.notEqual(CrmBizTypeEnum.CRM_BUSINESS.getType(), followUpRecord.getBizType())) { + return; + } + + // 更新商机跟进信息 + businessService.updateBusinessFollowUpBatch(Collections.singletonList(new CrmUpdateFollowUpReqBO() + .setBizId(followUpRecord.getBizId()).setContactNextTime(followUpRecord.getNextTime()).setContactLastTime(now) + .setContactLastContent(followUpRecord.getContent()))); + } + + private void updateClueFollowUp(CrmFollowUpRecordDO followUpRecord, LocalDateTime now) { + if (ObjUtil.notEqual(CrmBizTypeEnum.CRM_LEADS.getType(), followUpRecord.getBizType())) { + return; + } + + // 更新线索跟进信息 + clueService.updateClueFollowUp(new CrmUpdateFollowUpReqBO().setBizId(followUpRecord.getBizId()).setContactLastTime(now) + .setContactNextTime(followUpRecord.getNextTime()).setContactLastContent(followUpRecord.getContent())); + } + + private void updateContactFollowUp(CrmFollowUpRecordDO followUpRecord, LocalDateTime now) { + if (ObjUtil.notEqual(CrmBizTypeEnum.CRM_CONTACT.getType(), followUpRecord.getBizType())) { + return; + } + + // 更新联系人跟进信息 + contactService.updateContactFollowUpBatch(Collections.singletonList(new CrmUpdateFollowUpReqBO() + .setBizId(followUpRecord.getBizId()).setContactNextTime(followUpRecord.getNextTime()).setContactLastTime(now) + .setContactLastContent(followUpRecord.getContent()))); + } + + private void updateContractFollowUp(CrmFollowUpRecordDO followUpRecord, LocalDateTime now) { + if (ObjUtil.notEqual(CrmBizTypeEnum.CRM_CONTRACT.getType(), followUpRecord.getBizType())) { + return; + } + + // 更新合同跟进信息 + contractService.updateContractFollowUp(new CrmUpdateFollowUpReqBO().setBizId(followUpRecord.getBizId()).setContactLastTime(now) + .setContactNextTime(followUpRecord.getNextTime()).setContactLastContent(followUpRecord.getContent())); + } + + private void updateCustomerFollowUp(CrmFollowUpRecordDO followUpRecord, LocalDateTime now) { + if (ObjUtil.notEqual(CrmBizTypeEnum.CRM_CUSTOMER.getType(), followUpRecord.getBizType())) { + return; + } + + // 更新客户跟进信息 + customerService.updateCustomerFollowUp(new CrmUpdateFollowUpReqBO().setBizId(followUpRecord.getBizId()).setContactLastTime(now) + .setContactNextTime(followUpRecord.getNextTime()).setContactLastContent(followUpRecord.getContent())); + } + @Override public void deleteFollowUpRecord(Long id, Long userId) { // 校验存在 diff --git a/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/service/clue/bo/CrmClueUpdateFollowUpReqBO.java b/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/service/followup/bo/CrmUpdateFollowUpReqBO.java similarity index 67% rename from yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/service/clue/bo/CrmClueUpdateFollowUpReqBO.java rename to yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/service/followup/bo/CrmUpdateFollowUpReqBO.java index d4697acc2..6ddf71c7d 100644 --- a/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/service/clue/bo/CrmClueUpdateFollowUpReqBO.java +++ b/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/service/followup/bo/CrmUpdateFollowUpReqBO.java @@ -1,4 +1,4 @@ -package cn.iocoder.yudao.module.crm.service.clue.bo; +package cn.iocoder.yudao.module.crm.service.followup.bo; import com.mzt.logapi.starter.annotation.DiffLogField; import io.swagger.v3.oas.annotations.media.Schema; @@ -7,18 +7,18 @@ import lombok.Data; import java.time.LocalDateTime; -// TODO @puhui999:是不是搞个通用的 ReqBO 就好了 + /** - * 线索跟进信息 Update Req BO + * 跟进信息 Update Req BO * * @author HUIHUI */ @Data -public class CrmClueUpdateFollowUpReqBO { +public class CrmUpdateFollowUpReqBO { - @Schema(description = "线索编号", example = "3167") - @NotNull(message = "线索编号不能为空") - private Long id; + @Schema(description = "数据编号", example = "3167") + @NotNull(message = "数据编号不能为空") + private Long bizId; @Schema(description = "最后跟进时间") @DiffLogField(name = "最后跟进时间") @@ -27,7 +27,6 @@ public class CrmClueUpdateFollowUpReqBO { @Schema(description = "下次联系时间") @DiffLogField(name = "下次联系时间") - @NotNull(message = "下次联系时间不能为空") private LocalDateTime contactNextTime; @Schema(description = "最后更进内容") diff --git a/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/service/followup/handle/CrmBusinessFollowUpHandler.java b/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/service/followup/handle/CrmBusinessFollowUpHandler.java deleted file mode 100644 index ffba7fb7e..000000000 --- a/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/service/followup/handle/CrmBusinessFollowUpHandler.java +++ /dev/null @@ -1,38 +0,0 @@ -package cn.iocoder.yudao.module.crm.service.followup.handle; - -import cn.hutool.core.util.ObjUtil; -import cn.iocoder.yudao.module.crm.dal.dataobject.followup.CrmFollowUpRecordDO; -import cn.iocoder.yudao.module.crm.enums.common.CrmBizTypeEnum; -import cn.iocoder.yudao.module.crm.service.business.CrmBusinessService; -import cn.iocoder.yudao.module.crm.service.business.bo.CrmBusinessUpdateFollowUpReqBO; -import jakarta.annotation.Resource; -import org.springframework.stereotype.Component; - -import java.time.LocalDateTime; -import java.util.Collections; - -/** - * CRM 商机的 {@link CrmFollowUpHandler} 实现类 - * - * @author HUIHUI - */ -@Component -public class CrmBusinessFollowUpHandler implements CrmFollowUpHandler { - - @Resource - private CrmBusinessService businessService; - - @Override - public void execute(CrmFollowUpRecordDO followUpRecord, LocalDateTime now) { - if (ObjUtil.notEqual(CrmBizTypeEnum.CRM_BUSINESS.getType(), followUpRecord.getBizType())) { - return; - } - - // 更新商机跟进信息 - CrmBusinessUpdateFollowUpReqBO businessUpdateFollowUpReqBO = new CrmBusinessUpdateFollowUpReqBO(); - businessUpdateFollowUpReqBO.setId(followUpRecord.getBizId()).setContactNextTime(followUpRecord.getNextTime()) - .setContactLastTime(now).setContactLastContent(followUpRecord.getContent()); - businessService.updateContactFollowUpBatch(Collections.singletonList(businessUpdateFollowUpReqBO)); - } - -} diff --git a/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/service/followup/handle/CrmClueFollowUpHandler.java b/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/service/followup/handle/CrmClueFollowUpHandler.java deleted file mode 100644 index ade2b2aaa..000000000 --- a/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/service/followup/handle/CrmClueFollowUpHandler.java +++ /dev/null @@ -1,37 +0,0 @@ -package cn.iocoder.yudao.module.crm.service.followup.handle; - -import cn.hutool.core.util.ObjUtil; -import cn.iocoder.yudao.module.crm.dal.dataobject.followup.CrmFollowUpRecordDO; -import cn.iocoder.yudao.module.crm.enums.common.CrmBizTypeEnum; -import cn.iocoder.yudao.module.crm.service.clue.CrmClueService; -import cn.iocoder.yudao.module.crm.service.clue.bo.CrmClueUpdateFollowUpReqBO; -import jakarta.annotation.Resource; -import org.springframework.stereotype.Component; - -import java.time.LocalDateTime; - -/** - * CRM 线索的 {@link CrmFollowUpHandler} 实现类 - * - * @author HUIHUI - */ -@Component -public class CrmClueFollowUpHandler implements CrmFollowUpHandler { - - @Resource - private CrmClueService clueService; - - @Override - public void execute(CrmFollowUpRecordDO followUpRecord, LocalDateTime now) { - if (ObjUtil.notEqual(CrmBizTypeEnum.CRM_LEADS.getType(), followUpRecord.getBizType())) { - return; - } - - // 更新线索跟进信息 - CrmClueUpdateFollowUpReqBO clueUpdateFollowUpReqBO = new CrmClueUpdateFollowUpReqBO(); - clueUpdateFollowUpReqBO.setId(followUpRecord.getBizId()).setContactNextTime(followUpRecord.getNextTime()) - .setContactLastTime(now).setContactLastContent(followUpRecord.getContent()); - clueService.updateClueFollowUp(clueUpdateFollowUpReqBO); - } - -} diff --git a/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/service/followup/handle/CrmContactFollowUpHandler.java b/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/service/followup/handle/CrmContactFollowUpHandler.java deleted file mode 100644 index f38942111..000000000 --- a/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/service/followup/handle/CrmContactFollowUpHandler.java +++ /dev/null @@ -1,38 +0,0 @@ -package cn.iocoder.yudao.module.crm.service.followup.handle; - -import cn.hutool.core.util.ObjUtil; -import cn.iocoder.yudao.module.crm.dal.dataobject.followup.CrmFollowUpRecordDO; -import cn.iocoder.yudao.module.crm.enums.common.CrmBizTypeEnum; -import cn.iocoder.yudao.module.crm.service.contact.CrmContactService; -import cn.iocoder.yudao.module.crm.service.contact.bo.CrmContactUpdateFollowUpReqBO; -import jakarta.annotation.Resource; -import org.springframework.stereotype.Component; - -import java.time.LocalDateTime; -import java.util.Collections; - -/** - * CRM 联系人的 {@link CrmFollowUpHandler} 实现类 - * - * @author HUIHUI - */ -@Component -public class CrmContactFollowUpHandler implements CrmFollowUpHandler { - - @Resource - private CrmContactService contactService; - - @Override - public void execute(CrmFollowUpRecordDO followUpRecord, LocalDateTime now) { - if (ObjUtil.notEqual(CrmBizTypeEnum.CRM_CONTACT.getType(), followUpRecord.getBizType())) { - return; - } - - // 更新联系人跟进信息 - CrmContactUpdateFollowUpReqBO contactUpdateFollowUpReqBO = new CrmContactUpdateFollowUpReqBO(); - contactUpdateFollowUpReqBO.setId(followUpRecord.getBizId()).setContactNextTime(followUpRecord.getNextTime()) - .setContactLastTime(now).setContactLastContent(followUpRecord.getContent()); - contactService.updateContactFollowUpBatch(Collections.singletonList(contactUpdateFollowUpReqBO)); - } - -} diff --git a/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/service/followup/handle/CrmContractFollowUpHandler.java b/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/service/followup/handle/CrmContractFollowUpHandler.java deleted file mode 100644 index 269015fd0..000000000 --- a/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/service/followup/handle/CrmContractFollowUpHandler.java +++ /dev/null @@ -1,37 +0,0 @@ -package cn.iocoder.yudao.module.crm.service.followup.handle; - -import cn.hutool.core.util.ObjUtil; -import cn.iocoder.yudao.module.crm.dal.dataobject.followup.CrmFollowUpRecordDO; -import cn.iocoder.yudao.module.crm.enums.common.CrmBizTypeEnum; -import cn.iocoder.yudao.module.crm.service.contract.CrmContractService; -import cn.iocoder.yudao.module.crm.service.contract.bo.CrmContractUpdateFollowUpReqBO; -import jakarta.annotation.Resource; -import org.springframework.stereotype.Component; - -import java.time.LocalDateTime; - -/** - * CRM 合同的 {@link CrmFollowUpHandler} 实现类 - * - * @author HUIHUI - */ -@Component -public class CrmContractFollowUpHandler implements CrmFollowUpHandler { - - @Resource - private CrmContractService contractService; - - @Override - public void execute(CrmFollowUpRecordDO followUpRecord, LocalDateTime now) { - if (ObjUtil.notEqual(CrmBizTypeEnum.CRM_CONTRACT.getType(), followUpRecord.getBizType())) { - return; - } - - // 更新合同跟进信息 - CrmContractUpdateFollowUpReqBO contractUpdateFollowUpReqBO = new CrmContractUpdateFollowUpReqBO(); - contractUpdateFollowUpReqBO.setId(followUpRecord.getBizId()).setContactNextTime(followUpRecord.getNextTime()) - .setContactLastTime(now).setContactLastContent(followUpRecord.getContent()); - contractService.updateContractFollowUp(contractUpdateFollowUpReqBO); - } - -} diff --git a/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/service/followup/handle/CrmCustomerFollowUpHandler.java b/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/service/followup/handle/CrmCustomerFollowUpHandler.java deleted file mode 100644 index 0e0931555..000000000 --- a/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/service/followup/handle/CrmCustomerFollowUpHandler.java +++ /dev/null @@ -1,37 +0,0 @@ -package cn.iocoder.yudao.module.crm.service.followup.handle; - -import cn.hutool.core.util.ObjUtil; -import cn.iocoder.yudao.module.crm.dal.dataobject.followup.CrmFollowUpRecordDO; -import cn.iocoder.yudao.module.crm.enums.common.CrmBizTypeEnum; -import cn.iocoder.yudao.module.crm.service.customer.CrmCustomerService; -import cn.iocoder.yudao.module.crm.service.customer.bo.CrmCustomerUpdateFollowUpReqBO; -import jakarta.annotation.Resource; -import org.springframework.stereotype.Component; - -import java.time.LocalDateTime; - -/** - * CRM 客户的 {@link CrmFollowUpHandler} 实现类 - * - * @author HUIHUI - */ -@Component -public class CrmCustomerFollowUpHandler implements CrmFollowUpHandler { - - @Resource - private CrmCustomerService customerService; - - @Override - public void execute(CrmFollowUpRecordDO followUpRecord, LocalDateTime now) { - if (ObjUtil.notEqual(CrmBizTypeEnum.CRM_CUSTOMER.getType(), followUpRecord.getBizType())) { - return; - } - - // 更新客户跟进信息 - CrmCustomerUpdateFollowUpReqBO customerUpdateFollowUpReqBO = new CrmCustomerUpdateFollowUpReqBO(); - customerUpdateFollowUpReqBO.setId(followUpRecord.getBizId()).setContactNextTime(followUpRecord.getNextTime()) - .setContactLastTime(now).setContactLastContent(followUpRecord.getContent()); - customerService.updateCustomerFollowUp(customerUpdateFollowUpReqBO); - } - -} diff --git a/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/service/followup/handle/CrmFollowUpHandler.java b/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/service/followup/handle/CrmFollowUpHandler.java deleted file mode 100644 index 82bcec835..000000000 --- a/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/service/followup/handle/CrmFollowUpHandler.java +++ /dev/null @@ -1,23 +0,0 @@ -package cn.iocoder.yudao.module.crm.service.followup.handle; - -import cn.iocoder.yudao.module.crm.dal.dataobject.followup.CrmFollowUpRecordDO; - -import java.time.LocalDateTime; - -/** - * CRM 跟进信息处理器 handler 接口 - * - * @author HUIHUI - */ -public interface CrmFollowUpHandler { - - // TODO @puhui999:需要考虑,下次联系时间为空; - /** - * 执行更新 - * - * @param followUpRecord 跟进记录 - * @param now 跟进时间 - */ - void execute(CrmFollowUpRecordDO followUpRecord, LocalDateTime now); - -} diff --git a/yudao-module-mall/yudao-module-product-biz/src/main/java/cn/iocoder/yudao/module/product/convert/comment/ProductCommentConvert.java b/yudao-module-mall/yudao-module-product-biz/src/main/java/cn/iocoder/yudao/module/product/convert/comment/ProductCommentConvert.java index 7a3a3c011..27cb92637 100644 --- a/yudao-module-mall/yudao-module-product-biz/src/main/java/cn/iocoder/yudao/module/product/convert/comment/ProductCommentConvert.java +++ b/yudao-module-mall/yudao-module-product-biz/src/main/java/cn/iocoder/yudao/module/product/convert/comment/ProductCommentConvert.java @@ -1,9 +1,11 @@ package cn.iocoder.yudao.module.product.convert.comment; +import cn.iocoder.yudao.framework.common.pojo.PageResult; import cn.iocoder.yudao.framework.common.util.object.BeanUtils; import cn.iocoder.yudao.module.member.api.user.dto.MemberUserRespDTO; import cn.iocoder.yudao.module.product.api.comment.dto.ProductCommentCreateReqDTO; import cn.iocoder.yudao.module.product.controller.admin.comment.vo.ProductCommentCreateReqVO; +import cn.iocoder.yudao.module.product.controller.admin.comment.vo.ProductCommentRespVO; import cn.iocoder.yudao.module.product.dal.dataobject.comment.ProductCommentDO; import cn.iocoder.yudao.module.product.dal.dataobject.sku.ProductSkuDO; import cn.iocoder.yudao.module.product.dal.dataobject.spu.ProductSpuDO; @@ -59,4 +61,6 @@ public interface ProductCommentConvert { return divide.intValue(); } + PageResult convertPage(PageResult productCommentDOPageResult); + } diff --git a/yudao-module-mall/yudao-module-product-biz/src/test/java/cn/iocoder/yudao/module/product/service/comment/ProductCommentServiceImplTest.java b/yudao-module-mall/yudao-module-product-biz/src/test/java/cn/iocoder/yudao/module/product/service/comment/ProductCommentServiceImplTest.java index 83ec2c456..50ff0af56 100644 --- a/yudao-module-mall/yudao-module-product-biz/src/test/java/cn/iocoder/yudao/module/product/service/comment/ProductCommentServiceImplTest.java +++ b/yudao-module-mall/yudao-module-product-biz/src/test/java/cn/iocoder/yudao/module/product/service/comment/ProductCommentServiceImplTest.java @@ -9,20 +9,19 @@ import cn.iocoder.yudao.module.product.controller.admin.comment.vo.ProductCommen import cn.iocoder.yudao.module.product.controller.admin.comment.vo.ProductCommentRespVO; import cn.iocoder.yudao.module.product.controller.admin.comment.vo.ProductCommentUpdateVisibleReqVO; import cn.iocoder.yudao.module.product.controller.app.comment.vo.AppCommentPageReqVO; -import cn.iocoder.yudao.module.product.controller.app.comment.vo.AppCommentStatisticsRespVO; import cn.iocoder.yudao.module.product.convert.comment.ProductCommentConvert; import cn.iocoder.yudao.module.product.dal.dataobject.comment.ProductCommentDO; import cn.iocoder.yudao.module.product.dal.mysql.comment.ProductCommentMapper; import cn.iocoder.yudao.module.product.enums.comment.ProductCommentScoresEnum; import cn.iocoder.yudao.module.product.service.sku.ProductSkuService; import cn.iocoder.yudao.module.product.service.spu.ProductSpuService; +import jakarta.annotation.Resource; import org.junit.jupiter.api.Disabled; import org.junit.jupiter.api.Test; import org.springframework.boot.test.mock.mockito.MockBean; import org.springframework.context.annotation.Import; import org.springframework.context.annotation.Lazy; -import jakarta.annotation.Resource; import java.time.LocalDateTime; import java.util.Date; @@ -148,10 +147,10 @@ public class ProductCommentServiceImplTest extends BaseDbUnitTest { assertEquals(2, result3.getTotal()); // 测试分页 tab count - AppCommentStatisticsRespVO tabsCount = productCommentService.getCommentStatistics(spuId, Boolean.TRUE); - assertEquals(4, tabsCount.getGoodCount()); - assertEquals(2, tabsCount.getMediocreCount()); - assertEquals(0, tabsCount.getNegativeCount()); + //AppCommentStatisticsRespVO tabsCount = productCommentService.getCommentStatistics(spuId, Boolean.TRUE); + //assertEquals(4, tabsCount.getGoodCount()); + //assertEquals(2, tabsCount.getMediocreCount()); + //assertEquals(0, tabsCount.getNegativeCount()); } From 4ce9271ecedf39e1f06e0213bd8bfb4c396b0c2c Mon Sep 17 00:00:00 2001 From: min Date: Sat, 20 Jan 2024 15:08:45 +0800 Subject: [PATCH 006/119] =?UTF-8?q?CRM=EF=BC=9A=E3=80=90=E7=BA=BF=E7=B4=A2?= =?UTF-8?q?=E3=80=91=E5=88=9B=E5=BB=BA=E3=80=81=E5=88=A0=E9=99=A4=E7=BA=BF?= =?UTF-8?q?=E7=B4=A2=E6=97=B6=E5=90=8C=E6=97=B6=E5=88=9B=E5=BB=BA=E3=80=81?= =?UTF-8?q?=E5=88=A0=E9=99=A4=E6=95=B0=E6=8D=AE=E6=9D=83=E9=99=90?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../crm/service/clue/CrmClueServiceImpl.java | 42 ++++++++++++++----- 1 file changed, 31 insertions(+), 11 deletions(-) diff --git a/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/service/clue/CrmClueServiceImpl.java b/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/service/clue/CrmClueServiceImpl.java index 506424697..d311be78e 100644 --- a/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/service/clue/CrmClueServiceImpl.java +++ b/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/service/clue/CrmClueServiceImpl.java @@ -21,16 +21,21 @@ import cn.iocoder.yudao.module.crm.framework.permission.core.annotations.CrmPerm import cn.iocoder.yudao.module.crm.service.clue.bo.CrmClueUpdateFollowUpReqBO; import cn.iocoder.yudao.module.crm.service.customer.CrmCustomerService; import cn.iocoder.yudao.module.crm.service.permission.CrmPermissionService; +import cn.iocoder.yudao.module.crm.service.permission.bo.CrmPermissionCreateReqBO; import cn.iocoder.yudao.module.system.api.user.AdminUserApi; import jakarta.annotation.Resource; import org.springframework.stereotype.Service; import org.springframework.transaction.annotation.Transactional; import org.springframework.validation.annotation.Validated; -import java.util.*; +import java.util.Collection; +import java.util.List; +import java.util.Objects; +import java.util.Set; import static cn.iocoder.yudao.framework.common.exception.util.ServiceExceptionUtil.exception; import static cn.iocoder.yudao.framework.common.util.collection.CollectionUtils.convertSet; +import static cn.iocoder.yudao.framework.security.core.util.SecurityFrameworkUtils.getLoginUserId; import static cn.iocoder.yudao.module.crm.enums.ErrorCodeConstants.*; import static cn.iocoder.yudao.module.system.enums.ErrorCodeConstants.USER_NOT_EXISTS; @@ -56,15 +61,24 @@ public class CrmClueServiceImpl implements CrmClueService { private AdminUserApi adminUserApi; @Override - // TODO @min:补充相关几个方法的操作日志; + @Transactional(rollbackFor = Exception.class) public Long createClue(CrmClueSaveReqVO createReqVO) { - // 校验关联数据 + // 1. 校验关联数据 validateRelationDataExists(createReqVO); - // 插入 + // 2. 插入 CrmClueDO clue = BeanUtils.toBean(createReqVO, CrmClueDO.class); clueMapper.insert(clue); - // 返回 + + // 3. 创建数据权限 + CrmPermissionCreateReqBO createReqBO = new CrmPermissionCreateReqBO() + .setBizType(CrmBizTypeEnum.CRM_LEADS.getType()) + .setBizId(clue.getId()) + // 设置当前操作的人为负责人 + .setUserId(getLoginUserId()) + .setLevel(CrmPermissionLevelEnum.OWNER.getLevel()); + crmPermissionService.createPermission(createReqBO); + return clue.getId(); } @@ -87,20 +101,26 @@ public class CrmClueServiceImpl implements CrmClueService { } @Override + @Transactional(rollbackFor = Exception.class) @CrmPermission(bizType = CrmBizTypeEnum.CRM_LEADS, bizId = "#id", level = CrmPermissionLevelEnum.OWNER) public void deleteClue(Long id) { - // 校验存在 - validateClueExists(id); - // 删除 + // 1. 校验存在 + CrmClueDO clue = validateClueExists(id); + + // 2. 删除 clueMapper.deleteById(id); - // 删除数据权限 + + // 3. 删除数据权限 crmPermissionService.deletePermission(CrmBizTypeEnum.CRM_LEADS.getType(), id); + } - private void validateClueExists(Long id) { - if (clueMapper.selectById(id) == null) { + private CrmClueDO validateClueExists(Long id) { + CrmClueDO crmClueDO = clueMapper.selectById(id); + if (crmClueDO == null) { throw exception(CLUE_NOT_EXISTS); } + return crmClueDO; } @Override From 604611e1d2c3035db1457e11c7749571b1b91f33 Mon Sep 17 00:00:00 2001 From: min Date: Sat, 20 Jan 2024 15:38:55 +0800 Subject: [PATCH 007/119] =?UTF-8?q?CRM=EF=BC=9A=E3=80=90=E7=BA=BF=E7=B4=A2?= =?UTF-8?q?=E3=80=91=E8=A1=A5=E5=85=85=E7=9B=B8=E5=85=B3=E6=97=A5=E5=BF=97?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../module/crm/enums/LogRecordConstants.java | 6 ++++ .../crm/service/clue/CrmClueServiceImpl.java | 31 ++++++++++++++++--- 2 files changed, 33 insertions(+), 4 deletions(-) diff --git a/yudao-module-crm/yudao-module-crm-api/src/main/java/cn/iocoder/yudao/module/crm/enums/LogRecordConstants.java b/yudao-module-crm/yudao-module-crm-api/src/main/java/cn/iocoder/yudao/module/crm/enums/LogRecordConstants.java index 223994725..198886e68 100644 --- a/yudao-module-crm/yudao-module-crm-api/src/main/java/cn/iocoder/yudao/module/crm/enums/LogRecordConstants.java +++ b/yudao-module-crm/yudao-module-crm-api/src/main/java/cn/iocoder/yudao/module/crm/enums/LogRecordConstants.java @@ -11,6 +11,12 @@ public interface LogRecordConstants { // ======================= CRM_LEADS 线索 ======================= String CRM_LEADS_TYPE = "CRM 线索"; + String CRM_LEADS_CREATE_SUB_TYPE = "创建线索"; + String CRM_LEADS_CREATE_SUCCESS = "创建了线索{{#clue.name}}"; + String CRM_LEADS_UPDATE_SUB_TYPE = "更新线索"; + String CRM_LEADS_UPDATE_SUCCESS = "更新了线索【{{#clueName}}】: {_DIFF{#updateReqVO}}"; + String CRM_LEADS_DELETE_SUB_TYPE = "删除线索"; + String CRM_LEADS_DELETE_SUCCESS = "删除了线索【{{#clueName}}】"; // ======================= CRM_CUSTOMER 客户 ======================= diff --git a/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/service/clue/CrmClueServiceImpl.java b/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/service/clue/CrmClueServiceImpl.java index d311be78e..0d2be4ba9 100644 --- a/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/service/clue/CrmClueServiceImpl.java +++ b/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/service/clue/CrmClueServiceImpl.java @@ -2,6 +2,7 @@ package cn.iocoder.yudao.module.crm.service.clue; import cn.hutool.core.collection.CollUtil; import cn.hutool.core.collection.ListUtil; +import cn.hutool.core.lang.Assert; import cn.hutool.core.util.ObjectUtil; import cn.hutool.core.util.StrUtil; import cn.iocoder.yudao.framework.common.pojo.PageResult; @@ -23,6 +24,9 @@ import cn.iocoder.yudao.module.crm.service.customer.CrmCustomerService; import cn.iocoder.yudao.module.crm.service.permission.CrmPermissionService; import cn.iocoder.yudao.module.crm.service.permission.bo.CrmPermissionCreateReqBO; import cn.iocoder.yudao.module.system.api.user.AdminUserApi; +import com.mzt.logapi.context.LogRecordContext; +import com.mzt.logapi.service.impl.DiffParseFunction; +import com.mzt.logapi.starter.annotation.LogRecord; import jakarta.annotation.Resource; import org.springframework.stereotype.Service; import org.springframework.transaction.annotation.Transactional; @@ -37,6 +41,7 @@ import static cn.iocoder.yudao.framework.common.exception.util.ServiceExceptionU import static cn.iocoder.yudao.framework.common.util.collection.CollectionUtils.convertSet; import static cn.iocoder.yudao.framework.security.core.util.SecurityFrameworkUtils.getLoginUserId; import static cn.iocoder.yudao.module.crm.enums.ErrorCodeConstants.*; +import static cn.iocoder.yudao.module.crm.enums.LogRecordConstants.*; import static cn.iocoder.yudao.module.system.enums.ErrorCodeConstants.USER_NOT_EXISTS; /** @@ -62,6 +67,9 @@ public class CrmClueServiceImpl implements CrmClueService { @Override @Transactional(rollbackFor = Exception.class) + @LogRecord(type = CRM_LEADS_TYPE, subType = CRM_LEADS_CREATE_SUB_TYPE, bizNo = "{{#clue.id}}", + success = CRM_LEADS_CREATE_SUCCESS) + // TODO @min:补充相关几个方法的操作日志; public Long createClue(CrmClueSaveReqVO createReqVO) { // 1. 校验关联数据 validateRelationDataExists(createReqVO); @@ -79,20 +87,31 @@ public class CrmClueServiceImpl implements CrmClueService { .setLevel(CrmPermissionLevelEnum.OWNER.getLevel()); crmPermissionService.createPermission(createReqBO); + // 4. 记录操作日志上下文 + LogRecordContext.putVariable("clue", clue); return clue.getId(); } @Override + @Transactional(rollbackFor = Exception.class) + @LogRecord(type = CRM_LEADS_TYPE, subType = CRM_LEADS_UPDATE_SUB_TYPE, bizNo = "{{#updateReqVO.id}}", + success = CRM_LEADS_UPDATE_SUCCESS) @CrmPermission(bizType = CrmBizTypeEnum.CRM_LEADS, bizId = "#updateReqVO.id", level = CrmPermissionLevelEnum.WRITE) public void updateClue(CrmClueSaveReqVO updateReqVO) { - // 校验线索是否存在 - validateClueExists(updateReqVO.getId()); - // 校验关联数据 + Assert.notNull(updateReqVO.getId(), "线索编号不能为空"); + // 1. 校验线索是否存在 + CrmClueDO oldClue = validateClueExists(updateReqVO.getId()); + // 2. 校验关联数据 validateRelationDataExists(updateReqVO); - // 更新 + // 3. 更新 CrmClueDO updateObj = BeanUtils.toBean(updateReqVO, CrmClueDO.class); clueMapper.updateById(updateObj); + + // 3. 记录操作日志上下文 + LogRecordContext.putVariable(DiffParseFunction.OLD_OBJECT, BeanUtils.toBean(oldClue, CrmCustomerSaveReqVO.class)); + LogRecordContext.putVariable("clueName", oldClue.getName()); + } @Override @@ -102,6 +121,8 @@ public class CrmClueServiceImpl implements CrmClueService { @Override @Transactional(rollbackFor = Exception.class) + @LogRecord(type = CRM_LEADS_TYPE, subType = CRM_LEADS_DELETE_SUB_TYPE, bizNo = "{{#id}}", + success = CRM_LEADS_DELETE_SUCCESS) @CrmPermission(bizType = CrmBizTypeEnum.CRM_LEADS, bizId = "#id", level = CrmPermissionLevelEnum.OWNER) public void deleteClue(Long id) { // 1. 校验存在 @@ -113,6 +134,8 @@ public class CrmClueServiceImpl implements CrmClueService { // 3. 删除数据权限 crmPermissionService.deletePermission(CrmBizTypeEnum.CRM_LEADS.getType(), id); + // 4. 记录操作日志上下文 + LogRecordContext.putVariable("clueName", clue.getName()); } private CrmClueDO validateClueExists(Long id) { From 8920b9787de127049e56865c82fc61a2fc4f95fb Mon Sep 17 00:00:00 2001 From: puhui999 Date: Sat, 20 Jan 2024 18:42:06 +0800 Subject: [PATCH 008/119] =?UTF-8?q?fix:=20CRM=20selectBatchIds=20=E6=9D=83?= =?UTF-8?q?=E9=99=90=E6=9F=A5=E8=AF=A2=20ids=20=E7=AD=9B=E9=80=89=E4=B8=8D?= =?UTF-8?q?=E7=94=9F=E6=95=88=E7=9A=84=20bug?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../module/crm/dal/mysql/business/CrmBusinessMapper.java | 1 + .../yudao/module/crm/dal/mysql/clue/CrmClueMapper.java | 1 + .../module/crm/dal/mysql/contact/CrmContactMapper.java | 1 + .../module/crm/dal/mysql/contract/CrmContractMapper.java | 7 ++++--- .../module/crm/dal/mysql/customer/CrmCustomerMapper.java | 1 + .../crm/dal/mysql/receivable/CrmReceivableMapper.java | 1 + .../crm/dal/mysql/receivable/CrmReceivablePlanMapper.java | 1 + .../yudao/module/crm/util/CrmQueryWrapperUtils.java | 3 +-- 8 files changed, 11 insertions(+), 5 deletions(-) diff --git a/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/dal/mysql/business/CrmBusinessMapper.java b/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/dal/mysql/business/CrmBusinessMapper.java index d01352007..8f900b03b 100644 --- a/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/dal/mysql/business/CrmBusinessMapper.java +++ b/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/dal/mysql/business/CrmBusinessMapper.java @@ -58,6 +58,7 @@ public interface CrmBusinessMapper extends BaseMapperX { MPJLambdaWrapperX query = new MPJLambdaWrapperX<>(); // 拼接数据权限的查询条件 CrmQueryWrapperUtils.appendPermissionCondition(query, CrmBizTypeEnum.CRM_BUSINESS.getType(), ids, userId); + query.selectAll(CrmBusinessDO.class).in(CrmBusinessDO::getId, ids).orderByDesc(CrmBusinessDO::getId); return selectJoinList(CrmBusinessDO.class, query); } diff --git a/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/dal/mysql/clue/CrmClueMapper.java b/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/dal/mysql/clue/CrmClueMapper.java index 2253e69f6..c9007f78e 100644 --- a/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/dal/mysql/clue/CrmClueMapper.java +++ b/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/dal/mysql/clue/CrmClueMapper.java @@ -45,6 +45,7 @@ public interface CrmClueMapper extends BaseMapperX { MPJLambdaWrapperX query = new MPJLambdaWrapperX<>(); // 拼接数据权限的查询条件 CrmQueryWrapperUtils.appendPermissionCondition(query, CrmBizTypeEnum.CRM_LEADS.getType(), ids, userId); + query.selectAll(CrmClueDO.class).in(CrmClueDO::getId, ids).orderByDesc(CrmClueDO::getId); return selectJoinList(CrmClueDO.class, query); } diff --git a/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/dal/mysql/contact/CrmContactMapper.java b/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/dal/mysql/contact/CrmContactMapper.java index 8b2fb76bd..c4c194f6c 100644 --- a/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/dal/mysql/contact/CrmContactMapper.java +++ b/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/dal/mysql/contact/CrmContactMapper.java @@ -67,6 +67,7 @@ public interface CrmContactMapper extends BaseMapperX { MPJLambdaWrapperX query = new MPJLambdaWrapperX<>(); // 拼接数据权限的查询条件 CrmQueryWrapperUtils.appendPermissionCondition(query, CrmBizTypeEnum.CRM_CONTACT.getType(), ids, userId); + query.selectAll(CrmContactDO.class).in(CrmContactDO::getId, ids).orderByDesc(CrmContactDO::getId); return selectJoinList(CrmContactDO.class, query); } diff --git a/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/dal/mysql/contract/CrmContractMapper.java b/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/dal/mysql/contract/CrmContractMapper.java index eb21a3d5b..b0b2cbe70 100644 --- a/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/dal/mysql/contract/CrmContractMapper.java +++ b/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/dal/mysql/contract/CrmContractMapper.java @@ -54,10 +54,11 @@ public interface CrmContractMapper extends BaseMapperX { } default List selectBatchIds(Collection ids, Long userId) { - MPJLambdaWrapperX mpjLambdaWrapperX = new MPJLambdaWrapperX<>(); + MPJLambdaWrapperX query = new MPJLambdaWrapperX<>(); // 构建数据权限连表条件 - CrmQueryWrapperUtils.appendPermissionCondition(mpjLambdaWrapperX, CrmBizTypeEnum.CRM_CONTACT.getType(), ids, userId); - return selectJoinList(CrmContractDO.class, mpjLambdaWrapperX); + CrmQueryWrapperUtils.appendPermissionCondition(query, CrmBizTypeEnum.CRM_CONTACT.getType(), ids, userId); + query.selectAll(CrmContractDO.class).in(CrmContractDO::getId, ids).orderByDesc(CrmContractDO::getId); + return selectJoinList(CrmContractDO.class, query); } default Long selectCountByContactId(Long contactId) { diff --git a/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/dal/mysql/customer/CrmCustomerMapper.java b/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/dal/mysql/customer/CrmCustomerMapper.java index 125249d14..342f61d34 100644 --- a/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/dal/mysql/customer/CrmCustomerMapper.java +++ b/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/dal/mysql/customer/CrmCustomerMapper.java @@ -64,6 +64,7 @@ public interface CrmCustomerMapper extends BaseMapperX { MPJLambdaWrapperX query = new MPJLambdaWrapperX<>(); // 拼接数据权限的查询条件 CrmQueryWrapperUtils.appendPermissionCondition(query, CrmBizTypeEnum.CRM_CUSTOMER.getType(), ids, userId); + query.selectAll(CrmCustomerDO.class).in(CrmCustomerDO::getId, ids).orderByDesc(CrmCustomerDO::getId); return selectJoinList(CrmCustomerDO.class, query); } diff --git a/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/dal/mysql/receivable/CrmReceivableMapper.java b/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/dal/mysql/receivable/CrmReceivableMapper.java index a20da86a6..2f461e3eb 100644 --- a/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/dal/mysql/receivable/CrmReceivableMapper.java +++ b/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/dal/mysql/receivable/CrmReceivableMapper.java @@ -53,6 +53,7 @@ public interface CrmReceivableMapper extends BaseMapperX { MPJLambdaWrapperX query = new MPJLambdaWrapperX<>(); // 拼接数据权限的查询条件 CrmQueryWrapperUtils.appendPermissionCondition(query, CrmBizTypeEnum.CRM_RECEIVABLE.getType(), ids, userId); + query.selectAll(CrmReceivableDO.class).in(CrmReceivableDO::getId, ids).orderByDesc(CrmReceivableDO::getId); return selectJoinList(CrmReceivableDO.class, query); } diff --git a/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/dal/mysql/receivable/CrmReceivablePlanMapper.java b/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/dal/mysql/receivable/CrmReceivablePlanMapper.java index ed578f1fd..5bdf0a10f 100644 --- a/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/dal/mysql/receivable/CrmReceivablePlanMapper.java +++ b/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/dal/mysql/receivable/CrmReceivablePlanMapper.java @@ -52,6 +52,7 @@ public interface CrmReceivablePlanMapper extends BaseMapperX query = new MPJLambdaWrapperX<>(); // 拼接数据权限的查询条件 CrmQueryWrapperUtils.appendPermissionCondition(query, CrmBizTypeEnum.CRM_RECEIVABLE_PLAN.getType(), ids, userId); + query.selectAll(CrmReceivablePlanDO.class).in(CrmReceivablePlanDO::getId, ids).orderByDesc(CrmReceivablePlanDO::getId); return selectJoinList(CrmReceivablePlanDO.class, query); } diff --git a/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/util/CrmQueryWrapperUtils.java b/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/util/CrmQueryWrapperUtils.java index dc849622e..cfd2f8c1b 100644 --- a/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/util/CrmQueryWrapperUtils.java +++ b/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/util/CrmQueryWrapperUtils.java @@ -84,10 +84,9 @@ public class CrmQueryWrapperUtils { if (CrmPermissionUtils.isCrmAdmin()) {// 管理员不需要数据权限 return; } - query.innerJoin(CrmPermissionDO.class, on -> on.eq(CrmPermissionDO::getBizType, bizType).in(CrmPermissionDO::getBizId, bizIds) - .in(CollUtil.isNotEmpty(bizIds), CrmPermissionDO::getUserId, userId)); + .eq(CollUtil.isNotEmpty(bizIds), CrmPermissionDO::getUserId, userId)); } /** From 16fd1a96392c3f298fbc6ba9459423233749e327 Mon Sep 17 00:00:00 2001 From: YunaiV Date: Sat, 20 Jan 2024 18:46:51 +0800 Subject: [PATCH 009/119] =?UTF-8?q?=F0=9F=90=9B=20oracle=20limit=20?= =?UTF-8?q?=E6=9F=A5=E8=AF=A2=E4=B8=8D=E6=AD=A3=E7=A1=AE?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../yudao/framework/mybatis/core/query/QueryWrapperX.java | 2 +- .../system/controller/admin/notice/vo/NoticeSaveReqVO.java | 3 +-- 2 files changed, 2 insertions(+), 3 deletions(-) diff --git a/yudao-framework/yudao-spring-boot-starter-mybatis/src/main/java/cn/iocoder/yudao/framework/mybatis/core/query/QueryWrapperX.java b/yudao-framework/yudao-spring-boot-starter-mybatis/src/main/java/cn/iocoder/yudao/framework/mybatis/core/query/QueryWrapperX.java index 9661b7363..eec4172f1 100644 --- a/yudao-framework/yudao-spring-boot-starter-mybatis/src/main/java/cn/iocoder/yudao/framework/mybatis/core/query/QueryWrapperX.java +++ b/yudao-framework/yudao-spring-boot-starter-mybatis/src/main/java/cn/iocoder/yudao/framework/mybatis/core/query/QueryWrapperX.java @@ -151,7 +151,7 @@ public class QueryWrapperX extends QueryWrapper { switch (SqlConstants.DB_TYPE) { case ORACLE: case ORACLE_12C: - super.eq("ROWNUM", n); + super.le("ROWNUM", n); break; case SQL_SERVER: case SQL_SERVER2005: diff --git a/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/controller/admin/notice/vo/NoticeSaveReqVO.java b/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/controller/admin/notice/vo/NoticeSaveReqVO.java index d3d3e61ce..78794ed71 100644 --- a/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/controller/admin/notice/vo/NoticeSaveReqVO.java +++ b/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/controller/admin/notice/vo/NoticeSaveReqVO.java @@ -11,8 +11,7 @@ import jakarta.validation.constraints.Size; @Data public class NoticeSaveReqVO { - @Schema(description = "岗位公告编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "1024") - @NotNull(message = "岗位公告编号不能为空") + @Schema(description = "岗位公告编号", example = "1024") private Long id; @Schema(description = "公告标题", requiredMode = Schema.RequiredMode.REQUIRED, example = "小博主") From 39ae547b9d9730e9dcd9960a7a426bf87fc44b15 Mon Sep 17 00:00:00 2001 From: YunaiV Date: Sat, 20 Jan 2024 18:55:28 +0800 Subject: [PATCH 010/119] =?UTF-8?q?=F0=9F=93=96=20CRM=EF=BC=9Acode=20revie?= =?UTF-8?q?w=20=E7=BA=BF=E7=B4=A2=E9=80=BB=E8=BE=91?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../crm/service/clue/CrmClueServiceImpl.java | 18 +++++++----------- 1 file changed, 7 insertions(+), 11 deletions(-) diff --git a/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/service/clue/CrmClueServiceImpl.java b/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/service/clue/CrmClueServiceImpl.java index 0d2be4ba9..0185c3206 100644 --- a/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/service/clue/CrmClueServiceImpl.java +++ b/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/service/clue/CrmClueServiceImpl.java @@ -69,7 +69,6 @@ public class CrmClueServiceImpl implements CrmClueService { @Transactional(rollbackFor = Exception.class) @LogRecord(type = CRM_LEADS_TYPE, subType = CRM_LEADS_CREATE_SUB_TYPE, bizNo = "{{#clue.id}}", success = CRM_LEADS_CREATE_SUCCESS) - // TODO @min:补充相关几个方法的操作日志; public Long createClue(CrmClueSaveReqVO createReqVO) { // 1. 校验关联数据 validateRelationDataExists(createReqVO); @@ -111,7 +110,6 @@ public class CrmClueServiceImpl implements CrmClueService { // 3. 记录操作日志上下文 LogRecordContext.putVariable(DiffParseFunction.OLD_OBJECT, BeanUtils.toBean(oldClue, CrmCustomerSaveReqVO.class)); LogRecordContext.putVariable("clueName", oldClue.getName()); - } @Override @@ -189,23 +187,21 @@ public class CrmClueServiceImpl implements CrmClueService { throw exception(CLUE_ANY_CLUE_NOT_EXISTS, StrUtil.join(",", clueIds)); } - // 过滤出未转化的客户 - List unTransformClues = CollectionUtils.filterList(clues, - clue -> ObjectUtil.notEqual(Boolean.TRUE, clue.getTransformStatus())); // 存在已经转化的,直接提示哈。避免操作的用户,以为都转化成功了 - if (ObjectUtil.notEqual(clues.size(), unTransformClues.size())) { - clueIds.removeAll(convertSet(unTransformClues, CrmClueDO::getId)); - throw exception(CLUE_ANY_CLUE_ALREADY_TRANSLATED, StrUtil.join(",", clueIds)); + List translatedClues = CollectionUtils.filterList(clues, + clue -> ObjectUtil.equal(Boolean.TRUE, clue.getTransformStatus())); + if (CollUtil.isNotEmpty(translatedClues)) { + throw exception(CLUE_ANY_CLUE_ALREADY_TRANSLATED, StrUtil.join(",", convertSet(translatedClues, CrmClueDO::getId))); } // 遍历线索(未转化的线索),创建对应的客户 - unTransformClues.forEach(clue -> { + reqVO.getIds().forEach(id -> { // 1. 创建客户 - CrmCustomerSaveReqVO customerSaveReqVO = BeanUtils.toBean(clue, CrmCustomerSaveReqVO.class).setId(null); + CrmCustomerSaveReqVO customerSaveReqVO = BeanUtils.toBean(id, CrmCustomerSaveReqVO.class).setId(null); Long customerId = customerService.createCustomer(customerSaveReqVO, userId); // TODO @puhui999:如果有跟进记录,需要一起转过去;提问:艿艿这里是复制线索所有的跟进吗?还是直接把线索相关的跟进 bizType、bizId 全改为关联客户? // 2. 更新线索 - clueMapper.updateById(new CrmClueDO().setId(clue.getId()) + clueMapper.updateById(new CrmClueDO().setId(id) .setTransformStatus(Boolean.TRUE).setCustomerId(customerId)); }); } From c6c8dddfec8d6266630f4800e41771901e582f28 Mon Sep 17 00:00:00 2001 From: YunaiV Date: Sat, 20 Jan 2024 19:05:16 +0800 Subject: [PATCH 011/119] =?UTF-8?q?=F0=9F=93=96=20CRM=EF=BC=9Acode=20revie?= =?UTF-8?q?w=20=E8=B7=9F=E8=BF=9B=E8=AE=B0=E5=BD=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../module/crm/convert/business/CrmBusinessConvert.java | 4 ++-- .../yudao/module/crm/convert/contact/CrmContactConvert.java | 4 ++-- .../crm/service/followup/CrmFollowUpRecordServiceImpl.java | 1 + .../crm/service/followup/bo/CrmUpdateFollowUpReqBO.java | 1 - .../product/convert/comment/ProductCommentConvert.java | 4 ---- .../service/comment/ProductCommentServiceImplTest.java | 5 +++-- 6 files changed, 8 insertions(+), 11 deletions(-) diff --git a/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/convert/business/CrmBusinessConvert.java b/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/convert/business/CrmBusinessConvert.java index 56bba541e..d7f990043 100644 --- a/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/convert/business/CrmBusinessConvert.java +++ b/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/convert/business/CrmBusinessConvert.java @@ -50,8 +50,8 @@ public interface CrmBusinessConvert { @Mapping(target = "id", source = "reqBO.bizId") CrmBusinessDO convert(CrmUpdateFollowUpReqBO reqBO); - default List convertList(List updateFollowUpReqBOList) { - return CollectionUtils.convertList(updateFollowUpReqBOList, INSTANCE::convert); + default List convertList(List list) { + return CollectionUtils.convertList(list, INSTANCE::convert); } } diff --git a/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/convert/contact/CrmContactConvert.java b/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/convert/contact/CrmContactConvert.java index 1d32331bb..5fd2afa67 100644 --- a/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/convert/contact/CrmContactConvert.java +++ b/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/convert/contact/CrmContactConvert.java @@ -70,8 +70,8 @@ public interface CrmContactConvert { @Mapping(target = "id", source = "reqBO.bizId") CrmContactDO convert(CrmUpdateFollowUpReqBO reqBO); - default List convertList(List updateFollowUpReqBOList) { - return CollectionUtils.convertList(updateFollowUpReqBOList, INSTANCE::convert); + default List convertList(List list) { + return CollectionUtils.convertList(list, INSTANCE::convert); } } diff --git a/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/service/followup/CrmFollowUpRecordServiceImpl.java b/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/service/followup/CrmFollowUpRecordServiceImpl.java index d812ce048..a2da1ee3e 100644 --- a/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/service/followup/CrmFollowUpRecordServiceImpl.java +++ b/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/service/followup/CrmFollowUpRecordServiceImpl.java @@ -66,6 +66,7 @@ public class CrmFollowUpRecordServiceImpl implements CrmFollowUpRecordService { crmFollowUpRecordMapper.insert(followUpRecord); LocalDateTime now = LocalDateTime.now(); + // TODO @puhui999:感觉可以这里基于 type 做 102 到 104 这种判断;然后,每个类型的调用封装一个小方法,之后调用这些小方法;再之后,74-76、80-82 也是等价的处理; // 2. 更新 bizId 对应的记录; updateBizTypeFollowUp(followUpRecord, now); // 3.1 更新 contactIds 对应的记录 diff --git a/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/service/followup/bo/CrmUpdateFollowUpReqBO.java b/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/service/followup/bo/CrmUpdateFollowUpReqBO.java index 6ddf71c7d..74e789436 100644 --- a/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/service/followup/bo/CrmUpdateFollowUpReqBO.java +++ b/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/service/followup/bo/CrmUpdateFollowUpReqBO.java @@ -7,7 +7,6 @@ import lombok.Data; import java.time.LocalDateTime; - /** * 跟进信息 Update Req BO * diff --git a/yudao-module-mall/yudao-module-product-biz/src/main/java/cn/iocoder/yudao/module/product/convert/comment/ProductCommentConvert.java b/yudao-module-mall/yudao-module-product-biz/src/main/java/cn/iocoder/yudao/module/product/convert/comment/ProductCommentConvert.java index 27cb92637..7a3a3c011 100644 --- a/yudao-module-mall/yudao-module-product-biz/src/main/java/cn/iocoder/yudao/module/product/convert/comment/ProductCommentConvert.java +++ b/yudao-module-mall/yudao-module-product-biz/src/main/java/cn/iocoder/yudao/module/product/convert/comment/ProductCommentConvert.java @@ -1,11 +1,9 @@ package cn.iocoder.yudao.module.product.convert.comment; -import cn.iocoder.yudao.framework.common.pojo.PageResult; import cn.iocoder.yudao.framework.common.util.object.BeanUtils; import cn.iocoder.yudao.module.member.api.user.dto.MemberUserRespDTO; import cn.iocoder.yudao.module.product.api.comment.dto.ProductCommentCreateReqDTO; import cn.iocoder.yudao.module.product.controller.admin.comment.vo.ProductCommentCreateReqVO; -import cn.iocoder.yudao.module.product.controller.admin.comment.vo.ProductCommentRespVO; import cn.iocoder.yudao.module.product.dal.dataobject.comment.ProductCommentDO; import cn.iocoder.yudao.module.product.dal.dataobject.sku.ProductSkuDO; import cn.iocoder.yudao.module.product.dal.dataobject.spu.ProductSpuDO; @@ -61,6 +59,4 @@ public interface ProductCommentConvert { return divide.intValue(); } - PageResult convertPage(PageResult productCommentDOPageResult); - } diff --git a/yudao-module-mall/yudao-module-product-biz/src/test/java/cn/iocoder/yudao/module/product/service/comment/ProductCommentServiceImplTest.java b/yudao-module-mall/yudao-module-product-biz/src/test/java/cn/iocoder/yudao/module/product/service/comment/ProductCommentServiceImplTest.java index 50ff0af56..1b92e21f2 100644 --- a/yudao-module-mall/yudao-module-product-biz/src/test/java/cn/iocoder/yudao/module/product/service/comment/ProductCommentServiceImplTest.java +++ b/yudao-module-mall/yudao-module-product-biz/src/test/java/cn/iocoder/yudao/module/product/service/comment/ProductCommentServiceImplTest.java @@ -3,13 +3,13 @@ package cn.iocoder.yudao.module.product.service.comment; import cn.hutool.core.date.DateUtil; import cn.hutool.core.util.RandomUtil; import cn.iocoder.yudao.framework.common.pojo.PageResult; +import cn.iocoder.yudao.framework.common.util.object.BeanUtils; import cn.iocoder.yudao.framework.test.core.ut.BaseDbUnitTest; import cn.iocoder.yudao.module.product.controller.admin.comment.vo.ProductCommentPageReqVO; import cn.iocoder.yudao.module.product.controller.admin.comment.vo.ProductCommentReplyReqVO; import cn.iocoder.yudao.module.product.controller.admin.comment.vo.ProductCommentRespVO; import cn.iocoder.yudao.module.product.controller.admin.comment.vo.ProductCommentUpdateVisibleReqVO; import cn.iocoder.yudao.module.product.controller.app.comment.vo.AppCommentPageReqVO; -import cn.iocoder.yudao.module.product.convert.comment.ProductCommentConvert; import cn.iocoder.yudao.module.product.dal.dataobject.comment.ProductCommentDO; import cn.iocoder.yudao.module.product.dal.mysql.comment.ProductCommentMapper; import cn.iocoder.yudao.module.product.enums.comment.ProductCommentScoresEnum; @@ -128,7 +128,8 @@ public class ProductCommentServiceImplTest extends BaseDbUnitTest { productCommentPageReqVO.setReplyStatus(Boolean.TRUE); PageResult commentPage = productCommentService.getCommentPage(productCommentPageReqVO); - PageResult result = ProductCommentConvert.INSTANCE.convertPage(productCommentMapper.selectPage(productCommentPageReqVO)); + PageResult result = BeanUtils.toBean(productCommentMapper.selectPage(productCommentPageReqVO), + ProductCommentRespVO.class); assertEquals(result.getTotal(), commentPage.getTotal()); PageResult all = productCommentService.getCommentPage(new ProductCommentPageReqVO()); From d293fdd474fe661f96ed3a1f9768a6f2a412c3d9 Mon Sep 17 00:00:00 2001 From: puhui999 Date: Sat, 20 Jan 2024 22:49:47 +0800 Subject: [PATCH 012/119] =?UTF-8?q?fix:=20=E4=BF=AE=E5=A4=8D=20CRM=20?= =?UTF-8?q?=E7=9A=84=E4=B8=80=E4=BA=9B=20bug?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../admin/followup/vo/CrmFollowUpRecordRespVO.java | 5 +++++ .../followup/vo/CrmFollowUpRecordSaveReqVO.java | 6 +++++- .../admin/permission/CrmPermissionController.java | 8 +++++++- .../convert/permission/CrmPermissionConvert.java | 5 ++--- .../dataobject/followup/CrmFollowUpRecordDO.java | 14 ++++++++++++++ .../dal/mysql/permission/CrmPermissionMapper.java | 5 +++++ .../permission/CrmPermissionServiceImpl.java | 5 ++++- 7 files changed, 42 insertions(+), 6 deletions(-) diff --git a/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/controller/admin/followup/vo/CrmFollowUpRecordRespVO.java b/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/controller/admin/followup/vo/CrmFollowUpRecordRespVO.java index 8d4b145b6..83bfd9edc 100644 --- a/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/controller/admin/followup/vo/CrmFollowUpRecordRespVO.java +++ b/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/controller/admin/followup/vo/CrmFollowUpRecordRespVO.java @@ -44,6 +44,11 @@ public class CrmFollowUpRecordRespVO { @Schema(description = "关联的联系人名称数组") private List contactNames; + @Schema(description = "图片") + private List picUrls; + @Schema(description = "附件") + private List fileUrls; + @Schema(description = "创建时间", requiredMode = Schema.RequiredMode.REQUIRED) private LocalDateTime createTime; diff --git a/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/controller/admin/followup/vo/CrmFollowUpRecordSaveReqVO.java b/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/controller/admin/followup/vo/CrmFollowUpRecordSaveReqVO.java index b6d0e13c7..c4d53859b 100644 --- a/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/controller/admin/followup/vo/CrmFollowUpRecordSaveReqVO.java +++ b/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/controller/admin/followup/vo/CrmFollowUpRecordSaveReqVO.java @@ -37,8 +37,12 @@ public class CrmFollowUpRecordSaveReqVO { @Schema(description = "关联的商机编号数组") private List businessIds; - @Schema(description = "关联的联系人编号数组") private List contactIds; + @Schema(description = "图片") + private List picUrls; + @Schema(description = "附件") + private List fileUrls; + } \ No newline at end of file diff --git a/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/controller/admin/permission/CrmPermissionController.java b/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/controller/admin/permission/CrmPermissionController.java index 5dc3807f5..fe2aa261a 100644 --- a/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/controller/admin/permission/CrmPermissionController.java +++ b/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/controller/admin/permission/CrmPermissionController.java @@ -28,6 +28,7 @@ import org.springframework.validation.annotation.Validated; import org.springframework.web.bind.annotation.*; import java.util.*; +import java.util.stream.Stream; import static cn.iocoder.yudao.framework.common.pojo.CommonResult.success; import static cn.iocoder.yudao.framework.common.util.collection.CollectionUtils.convertSet; @@ -103,7 +104,12 @@ public class CrmPermissionController { // 拼接数据 List userList = adminUserApi.getUserList(convertSet(permission, CrmPermissionDO::getUserId)); Map deptMap = deptApi.getDeptMap(convertSet(userList, AdminUserRespDTO::getDeptId)); - Set postIds = CollectionUtils.convertSetByFlatMap(userList, AdminUserRespDTO::getPostIds, Collection::stream); + Set postIds = CollectionUtils.convertSetByFlatMap(userList, AdminUserRespDTO::getPostIds, item -> { + if (item == null) { + return Stream.empty(); + } + return item.stream(); + }); Map postMap = postApi.getPostMap(postIds); return success(CrmPermissionConvert.INSTANCE.convert(permission, userList, deptMap, postMap)); } diff --git a/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/convert/permission/CrmPermissionConvert.java b/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/convert/permission/CrmPermissionConvert.java index 5b81e67ad..d3b7ea4f0 100644 --- a/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/convert/permission/CrmPermissionConvert.java +++ b/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/convert/permission/CrmPermissionConvert.java @@ -1,6 +1,5 @@ package cn.iocoder.yudao.module.crm.convert.permission; -import cn.hutool.core.collection.CollUtil; import cn.iocoder.yudao.framework.common.util.collection.CollectionUtils; import cn.iocoder.yudao.framework.common.util.collection.MapUtils; import cn.iocoder.yudao.module.crm.controller.admin.permission.vo.CrmPermissionCreateReqVO; @@ -49,11 +48,11 @@ public interface CrmPermissionConvert { findAndThen(userMap, item.getUserId(), user -> { item.setNickname(user.getNickname()); findAndThen(deptMap, user.getDeptId(), deptRespDTO -> item.setDeptName(deptRespDTO.getName())); - List postRespList = MapUtils.getList(Multimaps.forMap(postMap), user.getPostIds()); - if (CollUtil.isEmpty(postRespList)) { + if (user.getPostIds() == null) { item.setPostNames(Collections.emptySet()); return; } + List postRespList = MapUtils.getList(Multimaps.forMap(postMap), user.getPostIds()); item.setPostNames(CollectionUtils.convertSet(postRespList, PostRespDTO::getName)); }); return item; diff --git a/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/dal/dataobject/followup/CrmFollowUpRecordDO.java b/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/dal/dataobject/followup/CrmFollowUpRecordDO.java index 896ad0297..1287fbc98 100644 --- a/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/dal/dataobject/followup/CrmFollowUpRecordDO.java +++ b/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/dal/dataobject/followup/CrmFollowUpRecordDO.java @@ -2,6 +2,7 @@ package cn.iocoder.yudao.module.crm.dal.dataobject.followup; import cn.iocoder.yudao.framework.mybatis.core.dataobject.BaseDO; import cn.iocoder.yudao.framework.mybatis.core.type.LongListTypeHandler; +import cn.iocoder.yudao.framework.mybatis.core.type.StringListTypeHandler; import cn.iocoder.yudao.module.crm.dal.dataobject.business.CrmBusinessDO; import cn.iocoder.yudao.module.crm.dal.dataobject.contact.CrmContactDO; import cn.iocoder.yudao.module.crm.enums.DictTypeConstants; @@ -66,6 +67,18 @@ public class CrmFollowUpRecordDO extends BaseDO { */ private LocalDateTime nextTime; + /** + * 图片 + */ + @TableField(typeHandler = StringListTypeHandler.class) + private List picUrls; + + /** + * 附件 + */ + @TableField(typeHandler = StringListTypeHandler.class) + private List fileUrls; + /** * 关联的商机编号数组 * @@ -81,4 +94,5 @@ public class CrmFollowUpRecordDO extends BaseDO { @TableField(typeHandler = LongListTypeHandler.class) private List contactIds; + } diff --git a/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/dal/mysql/permission/CrmPermissionMapper.java b/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/dal/mysql/permission/CrmPermissionMapper.java index 71c0368ca..bf8507383 100644 --- a/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/dal/mysql/permission/CrmPermissionMapper.java +++ b/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/dal/mysql/permission/CrmPermissionMapper.java @@ -53,6 +53,11 @@ public interface CrmPermissionMapper extends BaseMapperX { .eq(CrmPermissionDO::getId, id).eq(CrmPermissionDO::getUserId, userId)); } + default CrmPermissionDO selectByBizIdAndUserId(Long id, Long userId) { + return selectOne(new LambdaQueryWrapperX() + .eq(CrmPermissionDO::getBizId, id).eq(CrmPermissionDO::getUserId, userId)); + } + default int deletePermission(Integer bizType, Long bizId) { return delete(new LambdaQueryWrapperX() .eq(CrmPermissionDO::getBizType, bizType) diff --git a/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/service/permission/CrmPermissionServiceImpl.java b/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/service/permission/CrmPermissionServiceImpl.java index e8a74d49f..f135da993 100644 --- a/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/service/permission/CrmPermissionServiceImpl.java +++ b/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/service/permission/CrmPermissionServiceImpl.java @@ -167,7 +167,10 @@ public class CrmPermissionServiceImpl implements CrmPermissionService { throw exception(CRM_PERMISSION_DELETE_FAIL); } // 校验操作人是否为负责人 - CrmPermissionDO permission = permissionMapper.selectByIdAndUserId(permissions.get(0).getBizId(), userId); + CrmPermissionDO permission = permissionMapper.selectByBizIdAndUserId(permissions.getFirst().getBizId(), userId); + if (permission == null) { + throw exception(CRM_PERMISSION_DELETE_DENIED); + } if (!CrmPermissionLevelEnum.isOwner(permission.getLevel())) { throw exception(CRM_PERMISSION_DELETE_DENIED); } From 227a4f126ab2f85b5b8666d3447ff6149fa361f4 Mon Sep 17 00:00:00 2001 From: puhui999 Date: Sat, 20 Jan 2024 23:07:15 +0800 Subject: [PATCH 013/119] =?UTF-8?q?CRM:=20=E5=AE=8C=E5=96=84=E8=B7=9F?= =?UTF-8?q?=E8=BF=9B=20TODO?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../CrmFollowUpRecordServiceImpl.java | 94 ++++--------------- 1 file changed, 20 insertions(+), 74 deletions(-) diff --git a/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/service/followup/CrmFollowUpRecordServiceImpl.java b/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/service/followup/CrmFollowUpRecordServiceImpl.java index a2da1ee3e..612772a1d 100644 --- a/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/service/followup/CrmFollowUpRecordServiceImpl.java +++ b/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/service/followup/CrmFollowUpRecordServiceImpl.java @@ -66,90 +66,36 @@ public class CrmFollowUpRecordServiceImpl implements CrmFollowUpRecordService { crmFollowUpRecordMapper.insert(followUpRecord); LocalDateTime now = LocalDateTime.now(); - // TODO @puhui999:感觉可以这里基于 type 做 102 到 104 这种判断;然后,每个类型的调用封装一个小方法,之后调用这些小方法;再之后,74-76、80-82 也是等价的处理; + CrmUpdateFollowUpReqBO updateFollowUpReqBO = new CrmUpdateFollowUpReqBO().setBizId(followUpRecord.getBizId()) + .setContactLastTime(now).setContactNextTime(followUpRecord.getNextTime()).setContactLastContent(followUpRecord.getContent()); // 2. 更新 bizId 对应的记录; - updateBizTypeFollowUp(followUpRecord, now); + if (ObjUtil.notEqual(CrmBizTypeEnum.CRM_BUSINESS.getType(), followUpRecord.getBizType())) { // 更新商机跟进信息 + businessService.updateBusinessFollowUpBatch(Collections.singletonList(updateFollowUpReqBO)); + } + if (ObjUtil.notEqual(CrmBizTypeEnum.CRM_LEADS.getType(), followUpRecord.getBizType())) { // 更新线索跟进信息 + clueService.updateClueFollowUp(updateFollowUpReqBO); + } + if (ObjUtil.notEqual(CrmBizTypeEnum.CRM_CONTACT.getType(), followUpRecord.getBizType())) { // 更新联系人跟进信息 + contactService.updateContactFollowUpBatch(Collections.singletonList(updateFollowUpReqBO)); + } + if (ObjUtil.notEqual(CrmBizTypeEnum.CRM_CONTRACT.getType(), followUpRecord.getBizType())) { // 更新合同跟进信息 + contractService.updateContractFollowUp(updateFollowUpReqBO); + } + if (ObjUtil.notEqual(CrmBizTypeEnum.CRM_CUSTOMER.getType(), followUpRecord.getBizType())) { // 更新客户跟进信息 + customerService.updateCustomerFollowUp(updateFollowUpReqBO); + } + // 3.1 更新 contactIds 对应的记录 if (CollUtil.isNotEmpty(createReqVO.getContactIds())) { - contactService.updateContactFollowUpBatch(convertList(createReqVO.getContactIds(), contactId -> - new CrmUpdateFollowUpReqBO().setBizId(contactId).setContactNextTime(followUpRecord.getNextTime()) - .setContactLastTime(now).setContactLastContent(followUpRecord.getContent()))); + contactService.updateContactFollowUpBatch(convertList(createReqVO.getContactIds(), updateFollowUpReqBO::setBizId)); } // 3.2 需要更新 businessIds、contactIds 对应的记录 if (CollUtil.isNotEmpty(createReqVO.getBusinessIds())) { - businessService.updateBusinessFollowUpBatch(convertList(createReqVO.getBusinessIds(), businessId -> - new CrmUpdateFollowUpReqBO().setBizId(businessId).setContactNextTime(followUpRecord.getNextTime()) - .setContactLastTime(now).setContactLastContent(followUpRecord.getContent()))); + businessService.updateBusinessFollowUpBatch(convertList(createReqVO.getBusinessIds(), updateFollowUpReqBO::setBizId)); } return followUpRecord.getId(); } - /** - * 执行更新 - * - * @param followUpRecord 跟进记录 - * @param now 跟进时间 - */ - private void updateBizTypeFollowUp(CrmFollowUpRecordDO followUpRecord, LocalDateTime now) { - updateBusinessFollowUp(followUpRecord, now); - updateClueFollowUp(followUpRecord, now); - updateContactFollowUp(followUpRecord, now); - updateContractFollowUp(followUpRecord, now); - updateCustomerFollowUp(followUpRecord, now); - } - - private void updateBusinessFollowUp(CrmFollowUpRecordDO followUpRecord, LocalDateTime now) { - if (ObjUtil.notEqual(CrmBizTypeEnum.CRM_BUSINESS.getType(), followUpRecord.getBizType())) { - return; - } - - // 更新商机跟进信息 - businessService.updateBusinessFollowUpBatch(Collections.singletonList(new CrmUpdateFollowUpReqBO() - .setBizId(followUpRecord.getBizId()).setContactNextTime(followUpRecord.getNextTime()).setContactLastTime(now) - .setContactLastContent(followUpRecord.getContent()))); - } - - private void updateClueFollowUp(CrmFollowUpRecordDO followUpRecord, LocalDateTime now) { - if (ObjUtil.notEqual(CrmBizTypeEnum.CRM_LEADS.getType(), followUpRecord.getBizType())) { - return; - } - - // 更新线索跟进信息 - clueService.updateClueFollowUp(new CrmUpdateFollowUpReqBO().setBizId(followUpRecord.getBizId()).setContactLastTime(now) - .setContactNextTime(followUpRecord.getNextTime()).setContactLastContent(followUpRecord.getContent())); - } - - private void updateContactFollowUp(CrmFollowUpRecordDO followUpRecord, LocalDateTime now) { - if (ObjUtil.notEqual(CrmBizTypeEnum.CRM_CONTACT.getType(), followUpRecord.getBizType())) { - return; - } - - // 更新联系人跟进信息 - contactService.updateContactFollowUpBatch(Collections.singletonList(new CrmUpdateFollowUpReqBO() - .setBizId(followUpRecord.getBizId()).setContactNextTime(followUpRecord.getNextTime()).setContactLastTime(now) - .setContactLastContent(followUpRecord.getContent()))); - } - - private void updateContractFollowUp(CrmFollowUpRecordDO followUpRecord, LocalDateTime now) { - if (ObjUtil.notEqual(CrmBizTypeEnum.CRM_CONTRACT.getType(), followUpRecord.getBizType())) { - return; - } - - // 更新合同跟进信息 - contractService.updateContractFollowUp(new CrmUpdateFollowUpReqBO().setBizId(followUpRecord.getBizId()).setContactLastTime(now) - .setContactNextTime(followUpRecord.getNextTime()).setContactLastContent(followUpRecord.getContent())); - } - - private void updateCustomerFollowUp(CrmFollowUpRecordDO followUpRecord, LocalDateTime now) { - if (ObjUtil.notEqual(CrmBizTypeEnum.CRM_CUSTOMER.getType(), followUpRecord.getBizType())) { - return; - } - - // 更新客户跟进信息 - customerService.updateCustomerFollowUp(new CrmUpdateFollowUpReqBO().setBizId(followUpRecord.getBizId()).setContactLastTime(now) - .setContactNextTime(followUpRecord.getNextTime()).setContactLastContent(followUpRecord.getContent())); - } - @Override public void deleteFollowUpRecord(Long id, Long userId) { // 校验存在 From 23ef3c8ae00076fa711ab4daed8c96064b605f0c Mon Sep 17 00:00:00 2001 From: YunaiV Date: Mon, 22 Jan 2024 08:53:59 +0800 Subject: [PATCH 014/119] =?UTF-8?q?=F0=9F=93=96=20CRM=EF=BC=9Acode=20revie?= =?UTF-8?q?w=20=E8=B7=9F=E8=BF=9B=E8=AE=B0=E5=BD=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../admin/customer/CrmCustomerController.java | 1 + .../admin/permission/CrmPermissionController.java | 8 ++------ .../crm/convert/permission/CrmPermissionConvert.java | 8 +++++--- .../dal/dataobject/followup/CrmFollowUpRecordDO.java | 1 - .../crm/dal/mysql/business/CrmBusinessMapper.java | 1 + .../yudao/module/crm/dal/mysql/clue/CrmClueMapper.java | 1 + .../module/crm/dal/mysql/contact/CrmContactMapper.java | 1 + .../crm/dal/mysql/contract/CrmContractMapper.java | 1 + .../crm/dal/mysql/customer/CrmCustomerMapper.java | 1 + .../crm/dal/mysql/permission/CrmPermissionMapper.java | 10 +++++----- .../crm/dal/mysql/receivable/CrmReceivableMapper.java | 1 + .../dal/mysql/receivable/CrmReceivablePlanMapper.java | 1 + .../service/followup/CrmFollowUpRecordServiceImpl.java | 1 - .../promotion/dal/dataobject/coupon/CouponDO.java | 3 +++ .../dal/dataobject/coupon/CouponTemplateDO.java | 4 ++++ 15 files changed, 27 insertions(+), 16 deletions(-) diff --git a/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/controller/admin/customer/CrmCustomerController.java b/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/controller/admin/customer/CrmCustomerController.java index 0ea42cad6..a7b0a3730 100644 --- a/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/controller/admin/customer/CrmCustomerController.java +++ b/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/controller/admin/customer/CrmCustomerController.java @@ -182,6 +182,7 @@ public class CrmCustomerController { return success(true); } + // TODO @puhui999:要不搞个通用的 CrmOperateLogController,之后所有业务都调用它? @GetMapping("/operate-log-page") @Operation(summary = "获得客户操作日志") @Parameter(name = "id", description = "客户编号", required = true) diff --git a/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/controller/admin/permission/CrmPermissionController.java b/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/controller/admin/permission/CrmPermissionController.java index fe2aa261a..8bc9a6d93 100644 --- a/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/controller/admin/permission/CrmPermissionController.java +++ b/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/controller/admin/permission/CrmPermissionController.java @@ -104,12 +104,8 @@ public class CrmPermissionController { // 拼接数据 List userList = adminUserApi.getUserList(convertSet(permission, CrmPermissionDO::getUserId)); Map deptMap = deptApi.getDeptMap(convertSet(userList, AdminUserRespDTO::getDeptId)); - Set postIds = CollectionUtils.convertSetByFlatMap(userList, AdminUserRespDTO::getPostIds, item -> { - if (item == null) { - return Stream.empty(); - } - return item.stream(); - }); + Set postIds = CollectionUtils.convertSetByFlatMap(userList, AdminUserRespDTO::getPostIds, + item -> item != null ? item.stream() : Stream.empty()); Map postMap = postApi.getPostMap(postIds); return success(CrmPermissionConvert.INSTANCE.convert(permission, userList, deptMap, postMap)); } diff --git a/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/convert/permission/CrmPermissionConvert.java b/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/convert/permission/CrmPermissionConvert.java index d3b7ea4f0..6979a055e 100644 --- a/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/convert/permission/CrmPermissionConvert.java +++ b/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/convert/permission/CrmPermissionConvert.java @@ -1,5 +1,6 @@ package cn.iocoder.yudao.module.crm.convert.permission; +import cn.hutool.core.collection.CollUtil; import cn.iocoder.yudao.framework.common.util.collection.CollectionUtils; import cn.iocoder.yudao.framework.common.util.collection.MapUtils; import cn.iocoder.yudao.module.crm.controller.admin.permission.vo.CrmPermissionCreateReqVO; @@ -48,12 +49,12 @@ public interface CrmPermissionConvert { findAndThen(userMap, item.getUserId(), user -> { item.setNickname(user.getNickname()); findAndThen(deptMap, user.getDeptId(), deptRespDTO -> item.setDeptName(deptRespDTO.getName())); - if (user.getPostIds() == null) { + if (CollUtil.isEmpty(user.getPostIds())) { item.setPostNames(Collections.emptySet()); return; } - List postRespList = MapUtils.getList(Multimaps.forMap(postMap), user.getPostIds()); - item.setPostNames(CollectionUtils.convertSet(postRespList, PostRespDTO::getName)); + List postList = MapUtils.getList(Multimaps.forMap(postMap), user.getPostIds()); + item.setPostNames(CollectionUtils.convertSet(postList, PostRespDTO::getName)); }); return item; }); @@ -64,6 +65,7 @@ public interface CrmPermissionConvert { id -> new CrmPermissionDO().setId(id).setLevel(updateReqVO.getLevel())); } + // TODO @puhui999:搞成 BeanUtils List convertList(List list); } diff --git a/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/dal/dataobject/followup/CrmFollowUpRecordDO.java b/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/dal/dataobject/followup/CrmFollowUpRecordDO.java index 1287fbc98..a01d47af9 100644 --- a/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/dal/dataobject/followup/CrmFollowUpRecordDO.java +++ b/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/dal/dataobject/followup/CrmFollowUpRecordDO.java @@ -72,7 +72,6 @@ public class CrmFollowUpRecordDO extends BaseDO { */ @TableField(typeHandler = StringListTypeHandler.class) private List picUrls; - /** * 附件 */ diff --git a/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/dal/mysql/business/CrmBusinessMapper.java b/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/dal/mysql/business/CrmBusinessMapper.java index 8f900b03b..d7438484f 100644 --- a/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/dal/mysql/business/CrmBusinessMapper.java +++ b/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/dal/mysql/business/CrmBusinessMapper.java @@ -58,6 +58,7 @@ public interface CrmBusinessMapper extends BaseMapperX { MPJLambdaWrapperX query = new MPJLambdaWrapperX<>(); // 拼接数据权限的查询条件 CrmQueryWrapperUtils.appendPermissionCondition(query, CrmBizTypeEnum.CRM_BUSINESS.getType(), ids, userId); + // 拼接自身的查询条件 query.selectAll(CrmBusinessDO.class).in(CrmBusinessDO::getId, ids).orderByDesc(CrmBusinessDO::getId); return selectJoinList(CrmBusinessDO.class, query); } diff --git a/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/dal/mysql/clue/CrmClueMapper.java b/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/dal/mysql/clue/CrmClueMapper.java index c9007f78e..ec21cbe93 100644 --- a/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/dal/mysql/clue/CrmClueMapper.java +++ b/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/dal/mysql/clue/CrmClueMapper.java @@ -46,6 +46,7 @@ public interface CrmClueMapper extends BaseMapperX { // 拼接数据权限的查询条件 CrmQueryWrapperUtils.appendPermissionCondition(query, CrmBizTypeEnum.CRM_LEADS.getType(), ids, userId); query.selectAll(CrmClueDO.class).in(CrmClueDO::getId, ids).orderByDesc(CrmClueDO::getId); + // 拼接自身的查询条件 return selectJoinList(CrmClueDO.class, query); } diff --git a/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/dal/mysql/contact/CrmContactMapper.java b/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/dal/mysql/contact/CrmContactMapper.java index c4c194f6c..c35df47d3 100644 --- a/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/dal/mysql/contact/CrmContactMapper.java +++ b/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/dal/mysql/contact/CrmContactMapper.java @@ -67,6 +67,7 @@ public interface CrmContactMapper extends BaseMapperX { MPJLambdaWrapperX query = new MPJLambdaWrapperX<>(); // 拼接数据权限的查询条件 CrmQueryWrapperUtils.appendPermissionCondition(query, CrmBizTypeEnum.CRM_CONTACT.getType(), ids, userId); + // 拼接自身的查询条件 query.selectAll(CrmContactDO.class).in(CrmContactDO::getId, ids).orderByDesc(CrmContactDO::getId); return selectJoinList(CrmContactDO.class, query); } diff --git a/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/dal/mysql/contract/CrmContractMapper.java b/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/dal/mysql/contract/CrmContractMapper.java index b0b2cbe70..2e7bafdcf 100644 --- a/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/dal/mysql/contract/CrmContractMapper.java +++ b/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/dal/mysql/contract/CrmContractMapper.java @@ -57,6 +57,7 @@ public interface CrmContractMapper extends BaseMapperX { MPJLambdaWrapperX query = new MPJLambdaWrapperX<>(); // 构建数据权限连表条件 CrmQueryWrapperUtils.appendPermissionCondition(query, CrmBizTypeEnum.CRM_CONTACT.getType(), ids, userId); + // 拼接自身的查询条件 query.selectAll(CrmContractDO.class).in(CrmContractDO::getId, ids).orderByDesc(CrmContractDO::getId); return selectJoinList(CrmContractDO.class, query); } diff --git a/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/dal/mysql/customer/CrmCustomerMapper.java b/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/dal/mysql/customer/CrmCustomerMapper.java index 342f61d34..2e5b2d212 100644 --- a/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/dal/mysql/customer/CrmCustomerMapper.java +++ b/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/dal/mysql/customer/CrmCustomerMapper.java @@ -64,6 +64,7 @@ public interface CrmCustomerMapper extends BaseMapperX { MPJLambdaWrapperX query = new MPJLambdaWrapperX<>(); // 拼接数据权限的查询条件 CrmQueryWrapperUtils.appendPermissionCondition(query, CrmBizTypeEnum.CRM_CUSTOMER.getType(), ids, userId); + // 拼接自身的查询条件 query.selectAll(CrmCustomerDO.class).in(CrmCustomerDO::getId, ids).orderByDesc(CrmCustomerDO::getId); return selectJoinList(CrmCustomerDO.class, query); } diff --git a/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/dal/mysql/permission/CrmPermissionMapper.java b/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/dal/mysql/permission/CrmPermissionMapper.java index bf8507383..26f212e5e 100644 --- a/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/dal/mysql/permission/CrmPermissionMapper.java +++ b/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/dal/mysql/permission/CrmPermissionMapper.java @@ -49,13 +49,13 @@ public interface CrmPermissionMapper extends BaseMapperX { } default CrmPermissionDO selectByIdAndUserId(Long id, Long userId) { - return selectOne(new LambdaQueryWrapperX() - .eq(CrmPermissionDO::getId, id).eq(CrmPermissionDO::getUserId, userId)); + return selectOne(CrmPermissionDO::getId, id, + CrmPermissionDO::getUserId, userId); } - default CrmPermissionDO selectByBizIdAndUserId(Long id, Long userId) { - return selectOne(new LambdaQueryWrapperX() - .eq(CrmPermissionDO::getBizId, id).eq(CrmPermissionDO::getUserId, userId)); + default CrmPermissionDO selectByBizIdAndUserId(Long bizId, Long userId) { + return selectOne(CrmPermissionDO::getBizId, bizId, + CrmPermissionDO::getUserId, userId); } default int deletePermission(Integer bizType, Long bizId) { diff --git a/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/dal/mysql/receivable/CrmReceivableMapper.java b/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/dal/mysql/receivable/CrmReceivableMapper.java index 2f461e3eb..3ad8009f0 100644 --- a/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/dal/mysql/receivable/CrmReceivableMapper.java +++ b/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/dal/mysql/receivable/CrmReceivableMapper.java @@ -53,6 +53,7 @@ public interface CrmReceivableMapper extends BaseMapperX { MPJLambdaWrapperX query = new MPJLambdaWrapperX<>(); // 拼接数据权限的查询条件 CrmQueryWrapperUtils.appendPermissionCondition(query, CrmBizTypeEnum.CRM_RECEIVABLE.getType(), ids, userId); + // 拼接自身的查询条件 query.selectAll(CrmReceivableDO.class).in(CrmReceivableDO::getId, ids).orderByDesc(CrmReceivableDO::getId); return selectJoinList(CrmReceivableDO.class, query); } diff --git a/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/dal/mysql/receivable/CrmReceivablePlanMapper.java b/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/dal/mysql/receivable/CrmReceivablePlanMapper.java index 5bdf0a10f..eb6587174 100644 --- a/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/dal/mysql/receivable/CrmReceivablePlanMapper.java +++ b/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/dal/mysql/receivable/CrmReceivablePlanMapper.java @@ -52,6 +52,7 @@ public interface CrmReceivablePlanMapper extends BaseMapperX query = new MPJLambdaWrapperX<>(); // 拼接数据权限的查询条件 CrmQueryWrapperUtils.appendPermissionCondition(query, CrmBizTypeEnum.CRM_RECEIVABLE_PLAN.getType(), ids, userId); + // 拼接自身的查询条件 query.selectAll(CrmReceivablePlanDO.class).in(CrmReceivablePlanDO::getId, ids).orderByDesc(CrmReceivablePlanDO::getId); return selectJoinList(CrmReceivablePlanDO.class, query); } diff --git a/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/service/followup/CrmFollowUpRecordServiceImpl.java b/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/service/followup/CrmFollowUpRecordServiceImpl.java index 612772a1d..670fdacfc 100644 --- a/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/service/followup/CrmFollowUpRecordServiceImpl.java +++ b/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/service/followup/CrmFollowUpRecordServiceImpl.java @@ -126,7 +126,6 @@ public class CrmFollowUpRecordServiceImpl implements CrmFollowUpRecordService { return crmFollowUpRecordMapper.selectById(id); } - @Override @CrmPermission(bizTypeValue = "#pageReqVO.bizType", bizId = "#pageReqVO.bizId", level = CrmPermissionLevelEnum.READ) public PageResult getFollowUpRecordPage(CrmFollowUpRecordPageReqVO pageReqVO) { diff --git a/yudao-module-mall/yudao-module-promotion-biz/src/main/java/cn/iocoder/yudao/module/promotion/dal/dataobject/coupon/CouponDO.java b/yudao-module-mall/yudao-module-promotion-biz/src/main/java/cn/iocoder/yudao/module/promotion/dal/dataobject/coupon/CouponDO.java index b98615093..31cef2e78 100644 --- a/yudao-module-mall/yudao-module-promotion-biz/src/main/java/cn/iocoder/yudao/module/promotion/dal/dataobject/coupon/CouponDO.java +++ b/yudao-module-mall/yudao-module-promotion-biz/src/main/java/cn/iocoder/yudao/module/promotion/dal/dataobject/coupon/CouponDO.java @@ -48,8 +48,11 @@ public class CouponDO extends BaseDO { * * 枚举 {@link CouponStatusEnum} */ + // TODO 芋艿:已作废? private Integer status; + // TODO 芋艿:发放 adminid? + // ========== 基本信息 END ========== // ========== 领取情况 BEGIN ========== diff --git a/yudao-module-mall/yudao-module-promotion-biz/src/main/java/cn/iocoder/yudao/module/promotion/dal/dataobject/coupon/CouponTemplateDO.java b/yudao-module-mall/yudao-module-promotion-biz/src/main/java/cn/iocoder/yudao/module/promotion/dal/dataobject/coupon/CouponTemplateDO.java index 6cab9c58c..ad4ebab9b 100644 --- a/yudao-module-mall/yudao-module-promotion-biz/src/main/java/cn/iocoder/yudao/module/promotion/dal/dataobject/coupon/CouponTemplateDO.java +++ b/yudao-module-mall/yudao-module-promotion-biz/src/main/java/cn/iocoder/yudao/module/promotion/dal/dataobject/coupon/CouponTemplateDO.java @@ -45,6 +45,7 @@ public class CouponTemplateDO extends BaseDO { * * 枚举 {@link CommonStatusEnum} */ + // TODO 芋艿:要不要改成 3 个状态?? private Integer status; // ========== 基本信息 END ========== @@ -159,4 +160,7 @@ public class CouponTemplateDO extends BaseDO { private Integer useCount; // ========== 统计信息 END ========== + // TODO 芋艿:领取开始时间、领取结束时间 + + // TODO 芋艿:要不要加描述 } From 5622ba8acf82e0a9246317ede1b58c7119fe7fc7 Mon Sep 17 00:00:00 2001 From: kyle <573984425@qq.com> Date: Mon, 22 Jan 2024 11:21:17 +0800 Subject: [PATCH 015/119] =?UTF-8?q?review:=20=E7=AC=AC=E4=B8=80=E6=AC=A1?= =?UTF-8?q?=E4=BF=AE=E6=AD=A3=E5=90=88=E5=B9=B6?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../task/BpmProcessInstanceController.java | 21 --- .../BpmProcessInstanceCopyController.java | 44 ++++++ .../instance/BpmProcessInstanceCCReqVO.java | 47 ------ .../BpmProcessInstanceCopyCreateReqVO.java | 25 ++++ ...=> BpmProcessInstanceCopyMyPageReqVO.java} | 3 +- ...BpmProcessInstanceCopyPageItemRespVO.java} | 16 +-- .../vo/task}/BpmProcessInstanceCopyVO.java | 8 +- .../cc/BpmProcessInstanceCopyConvert.java | 51 +++---- .../cc/BpmProcessInstanceCopyDO.java | 20 ++- .../cc/BpmProcessInstanceCopyMapper.java | 7 +- .../candidate/BpmCandidateSourceInfo.java | 9 +- .../cc/BpmProcessInstanceCopyService.java | 53 ------- .../bpm/service/task/BpmTaskService.java | 21 ++- .../bpm/service/task/BpmTaskServiceImpl.java | 35 ++++- .../cc/BpmProcessInstanceCopyService.java | 40 ++++++ .../cc/BpmProcessInstanceCopyServiceImpl.java | 136 ++++++++++-------- .../cc/dto/BpmDelegateExecutionDTO.java | 2 +- .../yudao/module/bpm/util/FlowableUtils.java | 40 +----- .../cc/BpmProcessInstanceCopyServiceTest.java | 1 + 19 files changed, 287 insertions(+), 292 deletions(-) create mode 100644 yudao-module-bpm/yudao-module-bpm-biz/src/main/java/cn/iocoder/yudao/module/bpm/controller/admin/task/BpmProcessInstanceCopyController.java delete mode 100644 yudao-module-bpm/yudao-module-bpm-biz/src/main/java/cn/iocoder/yudao/module/bpm/controller/admin/task/vo/instance/BpmProcessInstanceCCReqVO.java create mode 100644 yudao-module-bpm/yudao-module-bpm-biz/src/main/java/cn/iocoder/yudao/module/bpm/controller/admin/task/vo/instance/BpmProcessInstanceCopyCreateReqVO.java rename yudao-module-bpm/yudao-module-bpm-biz/src/main/java/cn/iocoder/yudao/module/bpm/controller/admin/task/vo/instance/{BpmProcessInstanceCCMyPageReqVO.java => BpmProcessInstanceCopyMyPageReqVO.java} (81%) rename yudao-module-bpm/yudao-module-bpm-biz/src/main/java/cn/iocoder/yudao/module/bpm/controller/admin/task/vo/instance/{BpmProcessInstanceCCPageItemRespVO.java => BpmProcessInstanceCopyPageItemRespVO.java} (80%) rename yudao-module-bpm/yudao-module-bpm-biz/src/main/java/cn/iocoder/yudao/module/bpm/{service/cc => controller/admin/task/vo/task}/BpmProcessInstanceCopyVO.java (88%) delete mode 100644 yudao-module-bpm/yudao-module-bpm-biz/src/main/java/cn/iocoder/yudao/module/bpm/service/cc/BpmProcessInstanceCopyService.java create mode 100644 yudao-module-bpm/yudao-module-bpm-biz/src/main/java/cn/iocoder/yudao/module/bpm/service/task/cc/BpmProcessInstanceCopyService.java rename yudao-module-bpm/yudao-module-bpm-biz/src/main/java/cn/iocoder/yudao/module/bpm/service/{ => task}/cc/BpmProcessInstanceCopyServiceImpl.java (54%) rename yudao-module-bpm/yudao-module-bpm-biz/src/main/java/cn/iocoder/yudao/module/bpm/service/{ => task}/cc/dto/BpmDelegateExecutionDTO.java (99%) diff --git a/yudao-module-bpm/yudao-module-bpm-biz/src/main/java/cn/iocoder/yudao/module/bpm/controller/admin/task/BpmProcessInstanceController.java b/yudao-module-bpm/yudao-module-bpm-biz/src/main/java/cn/iocoder/yudao/module/bpm/controller/admin/task/BpmProcessInstanceController.java index 0cba2b35f..9d1301a27 100644 --- a/yudao-module-bpm/yudao-module-bpm-biz/src/main/java/cn/iocoder/yudao/module/bpm/controller/admin/task/BpmProcessInstanceController.java +++ b/yudao-module-bpm/yudao-module-bpm-biz/src/main/java/cn/iocoder/yudao/module/bpm/controller/admin/task/BpmProcessInstanceController.java @@ -3,7 +3,6 @@ package cn.iocoder.yudao.module.bpm.controller.admin.task; import cn.iocoder.yudao.framework.common.pojo.CommonResult; import cn.iocoder.yudao.framework.common.pojo.PageResult; import cn.iocoder.yudao.module.bpm.controller.admin.task.vo.instance.*; -import cn.iocoder.yudao.module.bpm.service.cc.BpmProcessInstanceCopyService; import cn.iocoder.yudao.module.bpm.service.task.BpmProcessInstanceService; import io.swagger.v3.oas.annotations.Operation; import io.swagger.v3.oas.annotations.Parameter; @@ -26,9 +25,6 @@ public class BpmProcessInstanceController { @Resource private BpmProcessInstanceService processInstanceService; - @Resource - private BpmProcessInstanceCopyService processInstanceCopyService; - @GetMapping("/my-page") @Operation(summary = "获得我的实例分页列表", description = "在【我的流程】菜单中,进行调用") @PreAuthorize("@ss.hasPermission('bpm:process-instance:query')") @@ -60,21 +56,4 @@ public class BpmProcessInstanceController { return success(true); } - // TODO @kyle:抄送要不单独 controller? - - @PostMapping("/cc/create") - @Operation(summary = "抄送流程") - @PreAuthorize("@ss.hasPermission('bpm:process-instance-cc:create')") - public CommonResult createProcessInstanceCC(@Valid @RequestBody BpmProcessInstanceCCReqVO createReqVO) { - return success(processInstanceCopyService.ccProcessInstance(getLoginUserId(), createReqVO)); - } - - @GetMapping("/cc/my-page") - @Operation(summary = "获得抄送流程分页列表") - @PreAuthorize("@ss.hasPermission('bpm:process-instance-cc:query')") - public CommonResult> getProcessInstanceCCPage( - @Valid BpmProcessInstanceCCMyPageReqVO pageReqVO) { - return success(processInstanceCopyService.getMyProcessInstanceCCPage(getLoginUserId(), pageReqVO)); - } - } diff --git a/yudao-module-bpm/yudao-module-bpm-biz/src/main/java/cn/iocoder/yudao/module/bpm/controller/admin/task/BpmProcessInstanceCopyController.java b/yudao-module-bpm/yudao-module-bpm-biz/src/main/java/cn/iocoder/yudao/module/bpm/controller/admin/task/BpmProcessInstanceCopyController.java new file mode 100644 index 000000000..0ff980756 --- /dev/null +++ b/yudao-module-bpm/yudao-module-bpm-biz/src/main/java/cn/iocoder/yudao/module/bpm/controller/admin/task/BpmProcessInstanceCopyController.java @@ -0,0 +1,44 @@ +package cn.iocoder.yudao.module.bpm.controller.admin.task; + +import cn.iocoder.yudao.framework.common.pojo.CommonResult; +import cn.iocoder.yudao.framework.common.pojo.PageResult; +import cn.iocoder.yudao.module.bpm.controller.admin.task.vo.instance.BpmProcessInstanceCopyCreateReqVO; +import cn.iocoder.yudao.module.bpm.controller.admin.task.vo.instance.BpmProcessInstanceCopyMyPageReqVO; +import cn.iocoder.yudao.module.bpm.controller.admin.task.vo.instance.BpmProcessInstanceCopyPageItemRespVO; +import cn.iocoder.yudao.module.bpm.service.task.cc.BpmProcessInstanceCopyService; +import io.swagger.v3.oas.annotations.Operation; +import io.swagger.v3.oas.annotations.tags.Tag; +import jakarta.annotation.Resource; +import jakarta.validation.Valid; +import org.springframework.security.access.prepost.PreAuthorize; +import org.springframework.validation.annotation.Validated; +import org.springframework.web.bind.annotation.*; + +import static cn.iocoder.yudao.framework.common.pojo.CommonResult.success; +import static cn.iocoder.yudao.framework.security.core.util.SecurityFrameworkUtils.getLoginUserId; + +@Tag(name = "管理后台 - 流程实例") // 流程实例,通过流程定义创建的一次“申请” +@RestController +@RequestMapping("/bpm/process-instance/cc") +@Validated +public class BpmProcessInstanceCopyController { + + @Resource + private BpmProcessInstanceCopyService processInstanceCopyService; + + @PostMapping("/create") + @Operation(summary = "抄送流程") + @PreAuthorize("@ss.hasPermission('bpm:process-instance-cc:create')") + public CommonResult createProcessInstanceCC(@Valid @RequestBody BpmProcessInstanceCopyCreateReqVO createReqVO) { + return success(processInstanceCopyService.createProcessInstanceCopy(getLoginUserId(), createReqVO)); + } + + @GetMapping("/my-page") + @Operation(summary = "获得抄送流程分页列表") + @PreAuthorize("@ss.hasPermission('bpm:process-instance-cc:query')") + public CommonResult> getProcessInstanceCCPage( + @Valid BpmProcessInstanceCopyMyPageReqVO pageReqVO) { + return success(processInstanceCopyService.getMyProcessInstanceCopyPage(getLoginUserId(), pageReqVO)); + } + +} diff --git a/yudao-module-bpm/yudao-module-bpm-biz/src/main/java/cn/iocoder/yudao/module/bpm/controller/admin/task/vo/instance/BpmProcessInstanceCCReqVO.java b/yudao-module-bpm/yudao-module-bpm-biz/src/main/java/cn/iocoder/yudao/module/bpm/controller/admin/task/vo/instance/BpmProcessInstanceCCReqVO.java deleted file mode 100644 index a07fd1514..000000000 --- a/yudao-module-bpm/yudao-module-bpm-biz/src/main/java/cn/iocoder/yudao/module/bpm/controller/admin/task/vo/instance/BpmProcessInstanceCCReqVO.java +++ /dev/null @@ -1,47 +0,0 @@ -package cn.iocoder.yudao.module.bpm.controller.admin.task.vo.instance; - -import cn.iocoder.yudao.module.bpm.controller.admin.candidate.vo.BpmTaskCandidateRuleVO; -import io.swagger.v3.oas.annotations.media.Schema; -import jakarta.validation.constraints.NotBlank; -import jakarta.validation.constraints.NotEmpty; -import jakarta.validation.constraints.NotNull; -import lombok.Data; -import lombok.EqualsAndHashCode; -import lombok.ToString; - -// TODO @kyle:这个 VO 可以改成 BpmProcessInstanceCopyCreateReqVO -@Schema(description = "管理后台 - 流程实例的抄送 Request VO") -@Data -@EqualsAndHashCode(callSuper = true) -@ToString(callSuper = true) -public class BpmProcessInstanceCCReqVO extends BpmTaskCandidateRuleVO { - - @Schema(description = "任务编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "1024") - @NotEmpty(message = "任务编号不能为空") - private String taskKey; - - @Schema(description = "任务名称", requiredMode = Schema.RequiredMode.REQUIRED, example = "1024") - @NotEmpty(message = "任务名称不能为空") - private String taskName; - - @Schema(description = "流程实例的编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "1024") - @NotEmpty(message = "流程实例的编号不能为空") - private String processInstanceKey; - - @Schema(description = "发起流程的用户的编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "1024") - @NotNull(message = "发起流程的用户的编号不能为空") - private Long startUserId; - - @Schema(description = "任务实例名称", requiredMode = Schema.RequiredMode.REQUIRED, example = "1024") - @NotEmpty(message = "任务实例名称不能为空") - private String processInstanceName; - - @Schema(description = "抄送原因", requiredMode = Schema.RequiredMode.REQUIRED, example = "请帮忙审查下!") - @NotBlank(message = "抄送原因不能为空") - private String reason; - - // TODO @kyle:看了下字段有点多,尽量不传递可推导的字段; - // 需要传递:taskId(任务编号)、reason、userIds(被抄送的人) - // 不需要传递:taskKey、taskName、processInstanceKey、startUserId、processInstanceName 因为这些可以后端查询到 - -} diff --git a/yudao-module-bpm/yudao-module-bpm-biz/src/main/java/cn/iocoder/yudao/module/bpm/controller/admin/task/vo/instance/BpmProcessInstanceCopyCreateReqVO.java b/yudao-module-bpm/yudao-module-bpm-biz/src/main/java/cn/iocoder/yudao/module/bpm/controller/admin/task/vo/instance/BpmProcessInstanceCopyCreateReqVO.java new file mode 100644 index 000000000..5847d2a1c --- /dev/null +++ b/yudao-module-bpm/yudao-module-bpm-biz/src/main/java/cn/iocoder/yudao/module/bpm/controller/admin/task/vo/instance/BpmProcessInstanceCopyCreateReqVO.java @@ -0,0 +1,25 @@ +package cn.iocoder.yudao.module.bpm.controller.admin.task.vo.instance; + +import cn.iocoder.yudao.module.bpm.controller.admin.candidate.vo.BpmTaskCandidateRuleVO; +import io.swagger.v3.oas.annotations.media.Schema; +import jakarta.validation.constraints.NotBlank; +import jakarta.validation.constraints.NotEmpty; +import lombok.Data; +import lombok.EqualsAndHashCode; +import lombok.ToString; + +@Schema(description = "管理后台 - 流程实例抄送的创建 Request VO") +@Data +@EqualsAndHashCode(callSuper = true) +@ToString(callSuper = true) +public class BpmProcessInstanceCopyCreateReqVO extends BpmTaskCandidateRuleVO { + + @Schema(description = "任务编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "1024") + @NotEmpty(message = "任务编号不能为空") + private String taskId; + + @Schema(description = "抄送原因", requiredMode = Schema.RequiredMode.REQUIRED, example = "请帮忙审查下!") + @NotBlank(message = "抄送原因不能为空") + private String reason; + +} diff --git a/yudao-module-bpm/yudao-module-bpm-biz/src/main/java/cn/iocoder/yudao/module/bpm/controller/admin/task/vo/instance/BpmProcessInstanceCCMyPageReqVO.java b/yudao-module-bpm/yudao-module-bpm-biz/src/main/java/cn/iocoder/yudao/module/bpm/controller/admin/task/vo/instance/BpmProcessInstanceCopyMyPageReqVO.java similarity index 81% rename from yudao-module-bpm/yudao-module-bpm-biz/src/main/java/cn/iocoder/yudao/module/bpm/controller/admin/task/vo/instance/BpmProcessInstanceCCMyPageReqVO.java rename to yudao-module-bpm/yudao-module-bpm-biz/src/main/java/cn/iocoder/yudao/module/bpm/controller/admin/task/vo/instance/BpmProcessInstanceCopyMyPageReqVO.java index 928ea8d97..7b4effadd 100644 --- a/yudao-module-bpm/yudao-module-bpm-biz/src/main/java/cn/iocoder/yudao/module/bpm/controller/admin/task/vo/instance/BpmProcessInstanceCCMyPageReqVO.java +++ b/yudao-module-bpm/yudao-module-bpm-biz/src/main/java/cn/iocoder/yudao/module/bpm/controller/admin/task/vo/instance/BpmProcessInstanceCopyMyPageReqVO.java @@ -11,12 +11,11 @@ import java.time.LocalDateTime; import static cn.iocoder.yudao.framework.common.util.date.DateUtils.FORMAT_YEAR_MONTH_DAY_HOUR_MINUTE_SECOND; -// TODO @kyle:建议改成 BpmProcessInstanceCopyMyPageReqVO;cc 缩写不容易理解,所以改成 copy,虽然会长一点,但是可读性更重要; @Schema(description = "管理后台 - 流程实例抄送的分页 Request VO") @Data @EqualsAndHashCode(callSuper = true) @ToString(callSuper = true) -public class BpmProcessInstanceCCMyPageReqVO extends PageParam { +public class BpmProcessInstanceCopyMyPageReqVO extends PageParam { @Schema(description = "流程名称", example = "芋道") private String processInstanceName; diff --git a/yudao-module-bpm/yudao-module-bpm-biz/src/main/java/cn/iocoder/yudao/module/bpm/controller/admin/task/vo/instance/BpmProcessInstanceCCPageItemRespVO.java b/yudao-module-bpm/yudao-module-bpm-biz/src/main/java/cn/iocoder/yudao/module/bpm/controller/admin/task/vo/instance/BpmProcessInstanceCopyPageItemRespVO.java similarity index 80% rename from yudao-module-bpm/yudao-module-bpm-biz/src/main/java/cn/iocoder/yudao/module/bpm/controller/admin/task/vo/instance/BpmProcessInstanceCCPageItemRespVO.java rename to yudao-module-bpm/yudao-module-bpm-biz/src/main/java/cn/iocoder/yudao/module/bpm/controller/admin/task/vo/instance/BpmProcessInstanceCopyPageItemRespVO.java index 176350c24..ee23e4c0b 100644 --- a/yudao-module-bpm/yudao-module-bpm-biz/src/main/java/cn/iocoder/yudao/module/bpm/controller/admin/task/vo/instance/BpmProcessInstanceCCPageItemRespVO.java +++ b/yudao-module-bpm/yudao-module-bpm-biz/src/main/java/cn/iocoder/yudao/module/bpm/controller/admin/task/vo/instance/BpmProcessInstanceCopyPageItemRespVO.java @@ -7,35 +7,23 @@ import java.time.LocalDateTime; @Schema(description = "管理后台 - 流程实例抄送的分页 Item Response VO") @Data -public class BpmProcessInstanceCCPageItemRespVO { +public class BpmProcessInstanceCopyPageItemRespVO { - // TODO @kyle:如果已经写了 swagger 注解,可以不用写 java 注释哈; - /** - * 编号 - */ @Schema(description = "抄送主键") private Long id; - /** - * 发起人Id - */ @Schema(description = "发起人Id") private Long startUserId; @Schema(description = "发起人别名") private String startUserNickname; - /** - * 流程主键 - */ @Schema(description = "流程实例的主键") private String processInstanceId; @Schema(description = "流程实例的名称") private String processInstanceName; - /** - * 任务主键 - */ + @Schema(description = "发起抄送的任务编号") private String taskId; diff --git a/yudao-module-bpm/yudao-module-bpm-biz/src/main/java/cn/iocoder/yudao/module/bpm/service/cc/BpmProcessInstanceCopyVO.java b/yudao-module-bpm/yudao-module-bpm-biz/src/main/java/cn/iocoder/yudao/module/bpm/controller/admin/task/vo/task/BpmProcessInstanceCopyVO.java similarity index 88% rename from yudao-module-bpm/yudao-module-bpm-biz/src/main/java/cn/iocoder/yudao/module/bpm/service/cc/BpmProcessInstanceCopyVO.java rename to yudao-module-bpm/yudao-module-bpm-biz/src/main/java/cn/iocoder/yudao/module/bpm/controller/admin/task/vo/task/BpmProcessInstanceCopyVO.java index 881ec6fd3..4be3d0bbe 100644 --- a/yudao-module-bpm/yudao-module-bpm-biz/src/main/java/cn/iocoder/yudao/module/bpm/service/cc/BpmProcessInstanceCopyVO.java +++ b/yudao-module-bpm/yudao-module-bpm-biz/src/main/java/cn/iocoder/yudao/module/bpm/controller/admin/task/vo/task/BpmProcessInstanceCopyVO.java @@ -1,16 +1,12 @@ -package cn.iocoder.yudao.module.bpm.service.cc; +package cn.iocoder.yudao.module.bpm.controller.admin.task.vo.task; import io.swagger.v3.oas.annotations.media.Schema; import lombok.Data; import java.time.LocalDateTime; -// TODO @kyle:看看是不是要删除 /** - * 流程抄送视图对象 wf_copy - * - * @author ruoyi - * @date 2022-05-19 + * 流程抄送视图对象 */ @Data public class BpmProcessInstanceCopyVO { diff --git a/yudao-module-bpm/yudao-module-bpm-biz/src/main/java/cn/iocoder/yudao/module/bpm/convert/cc/BpmProcessInstanceCopyConvert.java b/yudao-module-bpm/yudao-module-bpm-biz/src/main/java/cn/iocoder/yudao/module/bpm/convert/cc/BpmProcessInstanceCopyConvert.java index 3be0c131f..7bfd8cd62 100644 --- a/yudao-module-bpm/yudao-module-bpm-biz/src/main/java/cn/iocoder/yudao/module/bpm/convert/cc/BpmProcessInstanceCopyConvert.java +++ b/yudao-module-bpm/yudao-module-bpm-biz/src/main/java/cn/iocoder/yudao/module/bpm/convert/cc/BpmProcessInstanceCopyConvert.java @@ -2,18 +2,18 @@ package cn.iocoder.yudao.module.bpm.convert.cc; import cn.iocoder.yudao.framework.common.pojo.PageResult; import cn.iocoder.yudao.framework.common.util.collection.MapUtils; -import cn.iocoder.yudao.module.bpm.controller.admin.task.vo.instance.BpmProcessInstanceCCPageItemRespVO; +import cn.iocoder.yudao.framework.common.util.object.BeanUtils; +import cn.iocoder.yudao.module.bpm.controller.admin.task.vo.instance.BpmProcessInstanceCopyPageItemRespVO; +import cn.iocoder.yudao.module.bpm.controller.admin.task.vo.task.BpmProcessInstanceCopyVO; import cn.iocoder.yudao.module.bpm.dal.dataobject.cc.BpmProcessInstanceCopyDO; -import cn.iocoder.yudao.module.bpm.service.cc.BpmProcessInstanceCopyVO; import org.mapstruct.Mapper; import org.mapstruct.factory.Mappers; import java.util.List; import java.util.Map; -// TODO kyle:类注释不太对 /** - * 动态表单 Convert + * 流程抄送 Convert * * @author 芋艿 */ @@ -22,39 +22,24 @@ public interface BpmProcessInstanceCopyConvert { BpmProcessInstanceCopyConvert INSTANCE = Mappers.getMapper(BpmProcessInstanceCopyConvert.class); - // TODO @kyle:可以使用 BeanUtils copy 替代这些简单的哈; - BpmProcessInstanceCopyDO copy(BpmProcessInstanceCopyDO bean); - BpmProcessInstanceCopyVO convert(BpmProcessInstanceCopyDO bean); - List convertList(List list); + List convertList(List list); - // TODO @kyle:/* taskId */ 这种注释一般不用写,可以一眼看明白的;避免变量看着略微不清晰哈 - default PageResult convertPage(PageResult page - , Map taskMap - , Map processInstaneMap - , Map userMap + default PageResult convertPage(PageResult page + , Map taskMap + , Map processInstaneMap + , Map userMap ) { - List list = convertList(page.getList()); - for (BpmProcessInstanceCCPageItemRespVO vo : list) { - MapUtils.findAndThen(userMap, Long.valueOf(vo.getCreator()), - vo::setCreatorNickname); - MapUtils.findAndThen(userMap, vo.getStartUserId(), - vo::setStartUserNickname); - MapUtils.findAndThen(taskMap, vo.getTaskId(), - vo::setTaskName); - MapUtils.findAndThen(processInstaneMap, vo.getProcessInstanceId(), - vo::setProcessInstanceName); - } - // TODO @kyle:可以精简成下面的哈; -// List list2 = BeanUtils.toBean(page.getList(), -// BpmProcessInstanceCCPageItemRespVO.class, -// copy -> { -// MapUtils.findAndThen(userMap, Long.valueOf(copy.getCreator()), copy::setCreatorNickname); -// MapUtils.findAndThen(userMap, copy.getStartUserId(), copy::setStartUserNickname); -// MapUtils.findAndThen(taskMap, copy.getTaskId(), copy::setTaskName); -// MapUtils.findAndThen(processInstaneMap, copy.getProcessInstanceId(), copy::setProcessInstanceName); -// }); + List list = convertList(page.getList()); + List list2 = BeanUtils.toBean(page.getList(), + BpmProcessInstanceCopyPageItemRespVO.class, + copy -> { + MapUtils.findAndThen(userMap, Long.valueOf(copy.getCreator()), copy::setCreatorNickname); + MapUtils.findAndThen(userMap, copy.getStartUserId(), copy::setStartUserNickname); + MapUtils.findAndThen(taskMap, copy.getTaskId(), copy::setTaskName); + MapUtils.findAndThen(processInstaneMap, copy.getProcessInstanceId(), copy::setProcessInstanceName); + }); return new PageResult<>(list, page.getTotal()); } diff --git a/yudao-module-bpm/yudao-module-bpm-biz/src/main/java/cn/iocoder/yudao/module/bpm/dal/dataobject/cc/BpmProcessInstanceCopyDO.java b/yudao-module-bpm/yudao-module-bpm-biz/src/main/java/cn/iocoder/yudao/module/bpm/dal/dataobject/cc/BpmProcessInstanceCopyDO.java index 3bd287409..c9192e103 100644 --- a/yudao-module-bpm/yudao-module-bpm-biz/src/main/java/cn/iocoder/yudao/module/bpm/dal/dataobject/cc/BpmProcessInstanceCopyDO.java +++ b/yudao-module-bpm/yudao-module-bpm-biz/src/main/java/cn/iocoder/yudao/module/bpm/dal/dataobject/cc/BpmProcessInstanceCopyDO.java @@ -9,7 +9,7 @@ import lombok.*; * 流程抄送 DO * * @author kyle - * @date 2022-05-19 TODO @kyle:@date 不是标准 java doc,可以使用 @since 替代,然后日期是不是不对 + * @since 2024-01-22 */ @TableName(value = "bpm_process_instance_copy", autoResultMap = true) @Data @@ -26,34 +26,43 @@ public class BpmProcessInstanceCopyDO extends BaseDO { @TableId private Long id; - // TODO @kyle:字段如果是关联或者冗余,要写下注释。以 processInstanceId 举例子。 /** * 发起人 Id + *

+ * 关联 system_users 的 id 属性 */ private Long startUserId; /** * 流程名 + *

+ * 冗余字段 */ private String processInstanceName; /** * 流程实例的编号 - * + *

* 关联 ProcessInstance 的 id 属性 */ private String processInstanceId; /** * 任务主键 + *

+ * 关联 task 的 id 属性 */ private String taskId; /** * 任务名称 + *

+ * 冗余字段 */ private String taskName; /** * 用户编号 + *

+ * 关联 system_users 的 id 属性 */ private Long userId; @@ -62,10 +71,11 @@ public class BpmProcessInstanceCopyDO extends BaseDO { */ private String reason; - // TODO @kyle:这个字段,可以用 category 简化点 /** * 流程分类 + *

+ * 冗余字段 */ - private String processDefinitionCategory; + private String category; } diff --git a/yudao-module-bpm/yudao-module-bpm-biz/src/main/java/cn/iocoder/yudao/module/bpm/dal/mysql/cc/BpmProcessInstanceCopyMapper.java b/yudao-module-bpm/yudao-module-bpm-biz/src/main/java/cn/iocoder/yudao/module/bpm/dal/mysql/cc/BpmProcessInstanceCopyMapper.java index 3b8848428..de6fa14f5 100644 --- a/yudao-module-bpm/yudao-module-bpm-biz/src/main/java/cn/iocoder/yudao/module/bpm/dal/mysql/cc/BpmProcessInstanceCopyMapper.java +++ b/yudao-module-bpm/yudao-module-bpm-biz/src/main/java/cn/iocoder/yudao/module/bpm/dal/mysql/cc/BpmProcessInstanceCopyMapper.java @@ -3,13 +3,14 @@ package cn.iocoder.yudao.module.bpm.dal.mysql.cc; import cn.iocoder.yudao.framework.common.pojo.PageResult; import cn.iocoder.yudao.framework.mybatis.core.mapper.BaseMapperX; import cn.iocoder.yudao.framework.mybatis.core.query.LambdaQueryWrapperX; -import cn.iocoder.yudao.module.bpm.controller.admin.task.vo.instance.BpmProcessInstanceCCMyPageReqVO; +import cn.iocoder.yudao.module.bpm.controller.admin.task.vo.instance.BpmProcessInstanceCopyMyPageReqVO; import cn.iocoder.yudao.module.bpm.dal.dataobject.cc.BpmProcessInstanceCopyDO; import org.apache.ibatis.annotations.Mapper; @Mapper -public interface BpmProcessInstanceCopyMapper extends BaseMapperX { // TODO @kyle:方法和类之间要空行下; - default PageResult selectPage(Long loginUserId, BpmProcessInstanceCCMyPageReqVO reqVO){ +public interface BpmProcessInstanceCopyMapper extends BaseMapperX { + + default PageResult selectPage(Long loginUserId, BpmProcessInstanceCopyMyPageReqVO reqVO) { return selectPage(reqVO, new LambdaQueryWrapperX() .eqIfPresent(BpmProcessInstanceCopyDO::getUserId, loginUserId) .eqIfPresent(BpmProcessInstanceCopyDO::getProcessInstanceId, reqVO.getProcessInstanceId()) diff --git a/yudao-module-bpm/yudao-module-bpm-biz/src/main/java/cn/iocoder/yudao/module/bpm/service/candidate/BpmCandidateSourceInfo.java b/yudao-module-bpm/yudao-module-bpm-biz/src/main/java/cn/iocoder/yudao/module/bpm/service/candidate/BpmCandidateSourceInfo.java index 8582ad9a0..0c5f099d6 100644 --- a/yudao-module-bpm/yudao-module-bpm-biz/src/main/java/cn/iocoder/yudao/module/bpm/service/candidate/BpmCandidateSourceInfo.java +++ b/yudao-module-bpm/yudao-module-bpm-biz/src/main/java/cn/iocoder/yudao/module/bpm/service/candidate/BpmCandidateSourceInfo.java @@ -2,12 +2,12 @@ package cn.iocoder.yudao.module.bpm.service.candidate; import cn.iocoder.yudao.module.bpm.controller.admin.candidate.vo.BpmTaskCandidateRuleVO; import io.swagger.v3.oas.annotations.media.Schema; +import jakarta.validation.constraints.NotEmpty; +import jakarta.validation.constraints.NotNull; import lombok.AllArgsConstructor; import lombok.Data; import lombok.NoArgsConstructor; -import jakarta.validation.constraints.NotEmpty; -import jakarta.validation.constraints.NotNull; import java.util.HashSet; import java.util.Set; @@ -18,11 +18,6 @@ import java.util.Set; @NoArgsConstructor @Data public class BpmCandidateSourceInfo { - - @Schema(description = "流程id") - @NotNull - private String processInstanceId; - @Schema(description = "当前任务ID") @NotNull private String taskId; diff --git a/yudao-module-bpm/yudao-module-bpm-biz/src/main/java/cn/iocoder/yudao/module/bpm/service/cc/BpmProcessInstanceCopyService.java b/yudao-module-bpm/yudao-module-bpm-biz/src/main/java/cn/iocoder/yudao/module/bpm/service/cc/BpmProcessInstanceCopyService.java deleted file mode 100644 index 799656fde..000000000 --- a/yudao-module-bpm/yudao-module-bpm-biz/src/main/java/cn/iocoder/yudao/module/bpm/service/cc/BpmProcessInstanceCopyService.java +++ /dev/null @@ -1,53 +0,0 @@ -package cn.iocoder.yudao.module.bpm.service.cc; - -import cn.iocoder.yudao.framework.common.pojo.PageResult; -import cn.iocoder.yudao.module.bpm.controller.admin.task.vo.instance.BpmProcessInstanceCCMyPageReqVO; -import cn.iocoder.yudao.module.bpm.controller.admin.task.vo.instance.BpmProcessInstanceCCPageItemRespVO; -import cn.iocoder.yudao.module.bpm.controller.admin.task.vo.instance.BpmProcessInstanceCCReqVO; -import cn.iocoder.yudao.module.bpm.service.candidate.BpmCandidateSourceInfo; - -// TODO @kyle:这个 Service 要不挪到 task 包下;保持统一,task 下有流程、任务、抄送等; -// TODO @kyle:中文和英文之间,有个空格,会更清晰点;例如说;流程抄送 Service 接口;中文写作习惯~ -/** - * 流程抄送Service接口 - * - * 现在是在审批的时候进行流程抄送 - */ -public interface BpmProcessInstanceCopyService { - - // TODO @kyle:无用的方法,可以去掉哈;另外,考虑到避免过多的 VO,这里就可以返回 BpmProcessInstanceCopyDO - /** - * 查询流程抄送 - * - * @param copyId 流程抄送主键 - * @return 流程抄送 - */ - BpmProcessInstanceCopyVO queryById(Long copyId); - - // TODO 芋艿:这块要 review 下;思考下~~ - /** - * 抄送 - * @param sourceInfo 抄送源信息,方便抄送处理 - * @return - */ - boolean makeCopy(BpmCandidateSourceInfo sourceInfo); - - // TODO @kyle:可以方法名改成 createProcessInstanceCopy;现在项目一般新增都用 create 为主; - /** - * 流程实例的抄送 - * - * @param userId 当前登录用户 - * @param createReqVO 创建的抄送请求 - * @return 是否抄送成功,抄送成功则返回true TODO @kyle:这里可以不用返回哈;目前一般是失败,就抛出业务异常; - */ - boolean ccProcessInstance(Long userId, BpmProcessInstanceCCReqVO createReqVO); - - /** - * 抄送的流程 - * @param loginUserId 登录用户id - * @param pageReqVO 分页请求 - * @return 抄送的分页结果 - */ - PageResult getMyProcessInstanceCCPage(Long loginUserId, - BpmProcessInstanceCCMyPageReqVO pageReqVO); -} diff --git a/yudao-module-bpm/yudao-module-bpm-biz/src/main/java/cn/iocoder/yudao/module/bpm/service/task/BpmTaskService.java b/yudao-module-bpm/yudao-module-bpm-biz/src/main/java/cn/iocoder/yudao/module/bpm/service/task/BpmTaskService.java index 6c3837179..05925a858 100644 --- a/yudao-module-bpm/yudao-module-bpm-biz/src/main/java/cn/iocoder/yudao/module/bpm/service/task/BpmTaskService.java +++ b/yudao-module-bpm/yudao-module-bpm-biz/src/main/java/cn/iocoder/yudao/module/bpm/service/task/BpmTaskService.java @@ -4,11 +4,13 @@ import cn.iocoder.yudao.framework.common.pojo.PageResult; import cn.iocoder.yudao.framework.common.util.collection.CollectionUtils; import cn.iocoder.yudao.module.bpm.controller.admin.task.vo.task.*; import cn.iocoder.yudao.module.bpm.dal.dataobject.task.BpmTaskExtDO; +import jakarta.validation.Valid; import org.flowable.task.api.Task; -import jakarta.validation.Valid; +import java.util.Collection; import java.util.List; import java.util.Map; +import java.util.Set; /** * 流程任务实例 Service 接口 @@ -132,6 +134,8 @@ public interface BpmTaskService { */ void updateTaskExtAssign(Task task); + Task getTask(String id); + /** * 获取当前任务的可回退的流程集合 * @@ -181,4 +185,19 @@ public interface BpmTaskService { */ List getChildrenTaskList(String parentId); + /** + * 通过任务id查询任务名 + * + * @param taskIds 任务id + * @return 对应的映射关系 + */ + Map getTaskNameByTaskIds(Collection taskIds); + + /** + * 通过流程实例id获取到流程实例名 + * + * @param processInstaneIds 流程实例Id + * @return 对应的映射关系 + */ + Map getProcessInstanceNameByProcessInstanceIds(Set processInstaneIds); } diff --git a/yudao-module-bpm/yudao-module-bpm-biz/src/main/java/cn/iocoder/yudao/module/bpm/service/task/BpmTaskServiceImpl.java b/yudao-module-bpm/yudao-module-bpm-biz/src/main/java/cn/iocoder/yudao/module/bpm/service/task/BpmTaskServiceImpl.java index 27a4c7763..eaebccb93 100644 --- a/yudao-module-bpm/yudao-module-bpm-biz/src/main/java/cn/iocoder/yudao/module/bpm/service/task/BpmTaskServiceImpl.java +++ b/yudao-module-bpm/yudao-module-bpm-biz/src/main/java/cn/iocoder/yudao/module/bpm/service/task/BpmTaskServiceImpl.java @@ -19,14 +19,15 @@ import cn.iocoder.yudao.module.bpm.enums.task.BpmCommentTypeEnum; import cn.iocoder.yudao.module.bpm.enums.task.BpmProcessInstanceDeleteReasonEnum; import cn.iocoder.yudao.module.bpm.enums.task.BpmProcessInstanceResultEnum; import cn.iocoder.yudao.module.bpm.enums.task.BpmTaskAddSignTypeEnum; -import cn.iocoder.yudao.module.bpm.service.candidate.BpmCandidateSourceInfo; -import cn.iocoder.yudao.module.bpm.service.cc.BpmProcessInstanceCopyService; import cn.iocoder.yudao.module.bpm.service.definition.BpmModelService; import cn.iocoder.yudao.module.bpm.service.message.BpmMessageService; +import cn.iocoder.yudao.module.bpm.service.task.cc.BpmProcessInstanceCopyService; import cn.iocoder.yudao.module.system.api.dept.DeptApi; import cn.iocoder.yudao.module.system.api.dept.dto.DeptRespDTO; import cn.iocoder.yudao.module.system.api.user.AdminUserApi; import cn.iocoder.yudao.module.system.api.user.dto.AdminUserRespDTO; +import jakarta.annotation.Resource; +import jakarta.validation.Valid; import lombok.extern.slf4j.Slf4j; import org.flowable.bpmn.model.BpmnModel; import org.flowable.bpmn.model.FlowElement; @@ -51,8 +52,6 @@ import org.springframework.transaction.support.TransactionSynchronization; import org.springframework.transaction.support.TransactionSynchronizationManager; import org.springframework.util.Assert; -import jakarta.annotation.Resource; -import jakarta.validation.Valid; import java.time.LocalDateTime; import java.util.*; import java.util.stream.Stream; @@ -558,7 +557,8 @@ public class BpmTaskServiceImpl implements BpmTaskService { return task; } - private Task getTask(String id) { + @Override + public Task getTask(String id) { return taskService.createTaskQuery().taskId(id).singleResult(); } @@ -971,4 +971,29 @@ public class BpmTaskServiceImpl implements BpmTaskService { return BpmTaskConvert.INSTANCE.convertList(taskExtList, userMap, idTaskMap); } + @Override + public Map getTaskNameByTaskIds(Collection taskIds) { + List tasks = taskService.createTaskQuery().taskIds(taskIds).list(); + if (CollUtil.isNotEmpty(tasks)) { + Map taskMap = new HashMap<>(tasks.size()); + for (Task task : tasks) { + taskMap.putIfAbsent(task.getId(), task.getName()); + } + return taskMap; + } + return Collections.emptyMap(); + } + + @Override + public Map getProcessInstanceNameByProcessInstanceIds(Set processInstanceIds) { + List processInstances = runtimeService.createProcessInstanceQuery().processInstanceIds(processInstanceIds).list(); + if (CollUtil.isNotEmpty(processInstances)) { + Map processInstaneMap = new HashMap<>(processInstances.size()); + for (ProcessInstance processInstance : processInstances) { + processInstaneMap.putIfAbsent(processInstance.getId(), processInstance.getName()); + } + return processInstaneMap; + } + return Collections.emptyMap(); + } } diff --git a/yudao-module-bpm/yudao-module-bpm-biz/src/main/java/cn/iocoder/yudao/module/bpm/service/task/cc/BpmProcessInstanceCopyService.java b/yudao-module-bpm/yudao-module-bpm-biz/src/main/java/cn/iocoder/yudao/module/bpm/service/task/cc/BpmProcessInstanceCopyService.java new file mode 100644 index 000000000..b846d15fb --- /dev/null +++ b/yudao-module-bpm/yudao-module-bpm-biz/src/main/java/cn/iocoder/yudao/module/bpm/service/task/cc/BpmProcessInstanceCopyService.java @@ -0,0 +1,40 @@ +package cn.iocoder.yudao.module.bpm.service.task.cc; + +import cn.iocoder.yudao.framework.common.pojo.PageResult; +import cn.iocoder.yudao.module.bpm.controller.admin.task.vo.instance.BpmProcessInstanceCopyCreateReqVO; +import cn.iocoder.yudao.module.bpm.controller.admin.task.vo.instance.BpmProcessInstanceCopyMyPageReqVO; +import cn.iocoder.yudao.module.bpm.controller.admin.task.vo.instance.BpmProcessInstanceCopyPageItemRespVO; +import cn.iocoder.yudao.module.bpm.service.candidate.BpmCandidateSourceInfo; + +/** + * 流程抄送 Service 接口 + * + * 现在是在审批的时候进行流程抄送 + */ +public interface BpmProcessInstanceCopyService { + + // TODO 芋艿:这块要 review 下;思考下~~ + /** + * 抄送 + * @param sourceInfo 抄送源信息,方便抄送处理 + * @return + */ + boolean makeCopy(BpmCandidateSourceInfo sourceInfo); + + /** + * 流程实例的抄送 + * + * @param userId 当前登录用户 + * @param createReqVO 创建的抄送请求 + */ + Void createProcessInstanceCopy(Long userId, BpmProcessInstanceCopyCreateReqVO createReqVO); + + /** + * 抄送的流程的分页 + * @param loginUserId 登录用户id + * @param pageReqVO 分页请求 + * @return 抄送的分页结果 + */ + PageResult getMyProcessInstanceCopyPage(Long loginUserId, + BpmProcessInstanceCopyMyPageReqVO pageReqVO); +} diff --git a/yudao-module-bpm/yudao-module-bpm-biz/src/main/java/cn/iocoder/yudao/module/bpm/service/cc/BpmProcessInstanceCopyServiceImpl.java b/yudao-module-bpm/yudao-module-bpm-biz/src/main/java/cn/iocoder/yudao/module/bpm/service/task/cc/BpmProcessInstanceCopyServiceImpl.java similarity index 54% rename from yudao-module-bpm/yudao-module-bpm-biz/src/main/java/cn/iocoder/yudao/module/bpm/service/cc/BpmProcessInstanceCopyServiceImpl.java rename to yudao-module-bpm/yudao-module-bpm-biz/src/main/java/cn/iocoder/yudao/module/bpm/service/task/cc/BpmProcessInstanceCopyServiceImpl.java index edc5f7f0a..9b25b18bf 100644 --- a/yudao-module-bpm/yudao-module-bpm-biz/src/main/java/cn/iocoder/yudao/module/bpm/service/cc/BpmProcessInstanceCopyServiceImpl.java +++ b/yudao-module-bpm/yudao-module-bpm-biz/src/main/java/cn/iocoder/yudao/module/bpm/service/task/cc/BpmProcessInstanceCopyServiceImpl.java @@ -1,18 +1,23 @@ -package cn.iocoder.yudao.module.bpm.service.cc; +package cn.iocoder.yudao.module.bpm.service.task.cc; +import cn.hutool.core.bean.BeanUtil; import cn.hutool.core.collection.CollUtil; +import cn.hutool.core.util.ObjectUtil; +import cn.hutool.core.util.StrUtil; import cn.iocoder.yudao.framework.common.pojo.PageResult; -import cn.iocoder.yudao.module.bpm.controller.admin.task.vo.instance.BpmProcessInstanceCCMyPageReqVO; -import cn.iocoder.yudao.module.bpm.controller.admin.task.vo.instance.BpmProcessInstanceCCPageItemRespVO; -import cn.iocoder.yudao.module.bpm.controller.admin.task.vo.instance.BpmProcessInstanceCCReqVO; +import cn.iocoder.yudao.module.bpm.controller.admin.task.vo.instance.BpmProcessInstanceCopyCreateReqVO; +import cn.iocoder.yudao.module.bpm.controller.admin.task.vo.instance.BpmProcessInstanceCopyMyPageReqVO; +import cn.iocoder.yudao.module.bpm.controller.admin.task.vo.instance.BpmProcessInstanceCopyPageItemRespVO; import cn.iocoder.yudao.module.bpm.convert.cc.BpmProcessInstanceCopyConvert; import cn.iocoder.yudao.module.bpm.dal.dataobject.cc.BpmProcessInstanceCopyDO; import cn.iocoder.yudao.module.bpm.dal.mysql.cc.BpmProcessInstanceCopyMapper; +import cn.iocoder.yudao.module.bpm.enums.ErrorCodeConstants; +import cn.iocoder.yudao.module.bpm.enums.definition.BpmTaskAssignRuleTypeEnum; import cn.iocoder.yudao.module.bpm.service.candidate.BpmCandidateSourceInfo; import cn.iocoder.yudao.module.bpm.service.candidate.BpmCandidateSourceInfoProcessorChain; -import cn.iocoder.yudao.module.bpm.service.cc.dto.BpmDelegateExecutionDTO; import cn.iocoder.yudao.module.bpm.service.task.BpmProcessInstanceService; import cn.iocoder.yudao.module.bpm.service.task.BpmTaskService; +import cn.iocoder.yudao.module.bpm.service.task.cc.dto.BpmDelegateExecutionDTO; import cn.iocoder.yudao.module.bpm.util.FlowableUtils; import cn.iocoder.yudao.module.system.api.user.AdminUserApi; import cn.iocoder.yudao.module.system.api.user.dto.AdminUserRespDTO; @@ -22,6 +27,7 @@ import org.flowable.engine.RuntimeService; import org.flowable.engine.delegate.DelegateExecution; import org.flowable.engine.repository.ProcessDefinition; import org.flowable.engine.runtime.ProcessInstance; +import org.flowable.task.api.Task; import org.springframework.context.annotation.Lazy; import org.springframework.stereotype.Service; import org.springframework.validation.annotation.Validated; @@ -30,53 +36,52 @@ import java.time.LocalDateTime; import java.util.*; import java.util.stream.Collectors; -// TODO @kyle:类注释要写下 -@Slf4j // TODO @kyle:按照 @Service、@Validated、@Slf4j,从重要到不重要的顺序; +import static cn.iocoder.yudao.framework.common.exception.util.ServiceExceptionUtil.exception; +import static cn.iocoder.yudao.framework.common.util.collection.CollectionUtils.convertSet; + +/** + * Flowable流程抄送实现 + * + * @author kyle + */ @Service @Validated +@Slf4j public class BpmProcessInstanceCopyServiceImpl implements BpmProcessInstanceCopyService { - @Resource // TODO @kyle:第一个变量,和类之间要有空行; + + @Resource private BpmProcessInstanceCopyMapper processInstanceCopyMapper; - /** - * 和flowable有关的,查询流程名用的 TODO @kyle:可以不写哈注释; - */ @Resource private RuntimeService runtimeService; - /** - * 找抄送人用的 TODO @kyle:可以不写哈注释; - */ @Resource private BpmCandidateSourceInfoProcessorChain processorChain; - // TODO @kyle:多余的变量,可以去掉哈 @Resource - @Lazy // 解决循环依赖 private BpmTaskService bpmTaskService; + @Resource @Lazy // 解决循环依赖 private BpmProcessInstanceService bpmProcessInstanceService; @Resource private AdminUserApi adminUserApi; - @Override - public BpmProcessInstanceCopyVO queryById(Long copyId) { - BpmProcessInstanceCopyDO bpmProcessInstanceCopyDO = processInstanceCopyMapper.selectById(copyId); - return BpmProcessInstanceCopyConvert.INSTANCE.convert(bpmProcessInstanceCopyDO); - } - - // TODO @kyle:makeCopy 和 ccProcessInstance 的调用关系,感受上反了; - // makeCopy 有点像基于规则,查找抄送人,然后创建; - // ccProcessInstance 是已经有了抄送人,然后创建; - // 建议的改造:独立基于 processInstanceCopyMapper 做 insert @Override public boolean makeCopy(BpmCandidateSourceInfo sourceInfo) { if (null == sourceInfo) { return false; } - DelegateExecution executionEntity = new BpmDelegateExecutionDTO(sourceInfo.getProcessInstanceId()); + Task task = bpmTaskService.getTask(sourceInfo.getTaskId()); + if (ObjectUtil.isNull(task)) { + return false; + } + String processInstanceId = task.getProcessInstanceId(); + if (StrUtil.isBlank(processInstanceId)) { + return false; + } + DelegateExecution executionEntity = new BpmDelegateExecutionDTO(processInstanceId); Set ccCandidates = processorChain.calculateTaskCandidateUsers(executionEntity, sourceInfo); if (CollUtil.isEmpty(ccCandidates)) { log.warn("相关抄送人不存在 {}", sourceInfo.getTaskId()); @@ -87,9 +92,9 @@ public class BpmProcessInstanceCopyServiceImpl implements BpmProcessInstanceCopy // 设置任务id copyDO.setTaskId(sourceInfo.getTaskId()); copyDO.setTaskName(FlowableUtils.getTaskNameByTaskId(sourceInfo.getTaskId())); - copyDO.setProcessInstanceId(sourceInfo.getProcessInstanceId()); + copyDO.setProcessInstanceId(processInstanceId); ProcessInstance processInstance = runtimeService.createProcessInstanceQuery() - .processInstanceId(sourceInfo.getProcessInstanceId()) + .processInstanceId(processInstanceId) .singleResult(); if (null == processInstance) { log.warn("相关流程实例不存在 {}", sourceInfo.getTaskId()); @@ -98,13 +103,13 @@ public class BpmProcessInstanceCopyServiceImpl implements BpmProcessInstanceCopy copyDO.setStartUserId(FlowableUtils.getStartUserIdFromProcessInstance(processInstance)); copyDO.setProcessInstanceName(processInstance.getName()); ProcessDefinition processDefinition = FlowableUtils.getProcessDefinition(processInstance.getProcessDefinitionId()); - copyDO.setProcessDefinitionCategory(processDefinition.getCategory()); + copyDO.setCategory(processDefinition.getCategory()); copyDO.setReason(sourceInfo.getReason()); copyDO.setCreator(sourceInfo.getCreator()); copyDO.setCreateTime(LocalDateTime.now()); List copyList = new ArrayList<>(ccCandidates.size()); for (Long userId : ccCandidates) { - BpmProcessInstanceCopyDO copy = BpmProcessInstanceCopyConvert.INSTANCE.copy(copyDO); + BpmProcessInstanceCopyDO copy = BeanUtil.copyProperties(copyDO, BpmProcessInstanceCopyDO.class); copy.setUserId(userId); copyList.add(copy); } @@ -113,23 +118,51 @@ public class BpmProcessInstanceCopyServiceImpl implements BpmProcessInstanceCopy } @Override - public boolean ccProcessInstance(Long userId, BpmProcessInstanceCCReqVO reqVO) { - // 在能正常审批的情况下抄送流程 - BpmCandidateSourceInfo sourceInfo = new BpmCandidateSourceInfo(); - sourceInfo.setTaskId(reqVO.getTaskKey()); - sourceInfo.setProcessInstanceId(reqVO.getProcessInstanceKey()); - sourceInfo.addRule(reqVO); - sourceInfo.setCreator(String.valueOf(userId)); - sourceInfo.setReason(reqVO.getReason()); - if (!makeCopy(sourceInfo)) { - throw new RuntimeException("抄送任务失败"); + public Void createProcessInstanceCopy(Long userId, BpmProcessInstanceCopyCreateReqVO reqVO) { + if (!ObjectUtil.equal(reqVO.getType(), BpmTaskAssignRuleTypeEnum.USER.getType())) { + throw new IllegalArgumentException("业务仅支持USER"); } - return false; + Task task = bpmTaskService.getTask(reqVO.getTaskId()); + if (ObjectUtil.isNull(task)) { + throw exception(ErrorCodeConstants.TASK_NOT_EXISTS); + } + String processInstanceId = task.getProcessInstanceId(); + if (StrUtil.isBlank(processInstanceId)) { + throw exception(ErrorCodeConstants.PROCESS_INSTANCE_NOT_EXISTS); + } + // 在能正常审批的情况下抄送流程 + BpmProcessInstanceCopyDO copyDO = new BpmProcessInstanceCopyDO(); + // 调用 + // 设置任务id + copyDO.setTaskId(reqVO.getTaskId()); + copyDO.setTaskName(FlowableUtils.getTaskNameByTaskId(reqVO.getTaskId())); + copyDO.setProcessInstanceId(processInstanceId); + ProcessInstance processInstance = runtimeService.createProcessInstanceQuery() + .processInstanceId(processInstanceId) + .singleResult(); + if (null == processInstance) { + log.warn("相关流程实例不存在 {}", reqVO.getTaskId()); + throw exception(ErrorCodeConstants.PROCESS_INSTANCE_NOT_EXISTS); + } + copyDO.setStartUserId(FlowableUtils.getStartUserIdFromProcessInstance(processInstance)); + copyDO.setProcessInstanceName(processInstance.getName()); + ProcessDefinition processDefinition = FlowableUtils.getProcessDefinition(processInstance.getProcessDefinitionId()); + copyDO.setCategory(processDefinition.getCategory()); + copyDO.setReason(reqVO.getReason()); + copyDO.setCreator(String.valueOf(userId)); + copyDO.setCreateTime(LocalDateTime.now()); + List copyList = new ArrayList<>(reqVO.getOptions().size()); + for (Long copyUserId : reqVO.getOptions()) { + BpmProcessInstanceCopyDO copy = BeanUtil.copyProperties(copyDO, BpmProcessInstanceCopyDO.class); + copy.setUserId(copyUserId); + copyList.add(copy); + } + processInstanceCopyMapper.insertBatch(copyList); + return null; } - //获取流程抄送分页 TODO @kyle:接口已经注释,这里不用注释了哈; @Override - public PageResult getMyProcessInstanceCCPage(Long loginUserId, BpmProcessInstanceCCMyPageReqVO pageReqVO) { + public PageResult getMyProcessInstanceCopyPage(Long loginUserId, BpmProcessInstanceCopyMyPageReqVO pageReqVO) { // 通过 BpmProcessInstanceExtDO 表,先查询到对应的分页 // TODO @kyle:一般读逻辑,Service 返回 PageResult 即可。关联数据的查询和拼接,交给 Controller;目的是:保证 Service 聚焦写逻辑,清晰简洁; PageResult pageResult = processInstanceCopyMapper.selectPage(loginUserId, pageReqVO); @@ -137,29 +170,20 @@ public class BpmProcessInstanceCopyServiceImpl implements BpmProcessInstanceCopy return new PageResult<>(pageResult.getTotal()); } - // TODO @kyle:这种可以简洁点;参考如下 -// Map processInstanceMap = bpmProcessInstanceService.getProcessInstanceMap( -// convertSet(pageResult.getList(), BpmProcessInstanceCopyDO::getProcessInstanceId)); + Map taskNameByTaskIds = bpmTaskService.getTaskNameByTaskIds(convertSet(pageResult.getList(), BpmProcessInstanceCopyDO::getTaskId)); + Map processInstanceNameByProcessInstanceIds = bpmTaskService.getProcessInstanceNameByProcessInstanceIds(convertSet(pageResult.getList(), BpmProcessInstanceCopyDO::getProcessInstanceId)); - Set taskIds = new HashSet<>(); - Set processInstaneIds = new HashSet<>(); Set userIds = new HashSet<>(); for (BpmProcessInstanceCopyDO doItem : pageResult.getList()) { - taskIds.add(doItem.getTaskId()); - processInstaneIds.add(doItem.getProcessInstanceId()); userIds.add(doItem.getStartUserId()); Long userId = Long.valueOf(doItem.getCreator()); userIds.add(userId); } - - Map taskNameByTaskIds = FlowableUtils.getTaskNameByTaskIds(taskIds); - Map processInstanceNameByTaskIds = FlowableUtils.getProcessInstanceNameByTaskIds(processInstaneIds); - Map userMap = adminUserApi.getUserList(userIds).stream().collect(Collectors.toMap( AdminUserRespDTO::getId, AdminUserRespDTO::getNickname)); // 转换返回 - return BpmProcessInstanceCopyConvert.INSTANCE.convertPage(pageResult, taskNameByTaskIds, processInstanceNameByTaskIds, userMap); + return BpmProcessInstanceCopyConvert.INSTANCE.convertPage(pageResult, taskNameByTaskIds, processInstanceNameByProcessInstanceIds, userMap); } } diff --git a/yudao-module-bpm/yudao-module-bpm-biz/src/main/java/cn/iocoder/yudao/module/bpm/service/cc/dto/BpmDelegateExecutionDTO.java b/yudao-module-bpm/yudao-module-bpm-biz/src/main/java/cn/iocoder/yudao/module/bpm/service/task/cc/dto/BpmDelegateExecutionDTO.java similarity index 99% rename from yudao-module-bpm/yudao-module-bpm-biz/src/main/java/cn/iocoder/yudao/module/bpm/service/cc/dto/BpmDelegateExecutionDTO.java rename to yudao-module-bpm/yudao-module-bpm-biz/src/main/java/cn/iocoder/yudao/module/bpm/service/task/cc/dto/BpmDelegateExecutionDTO.java index 47213ae52..d010d8969 100644 --- a/yudao-module-bpm/yudao-module-bpm-biz/src/main/java/cn/iocoder/yudao/module/bpm/service/cc/dto/BpmDelegateExecutionDTO.java +++ b/yudao-module-bpm/yudao-module-bpm-biz/src/main/java/cn/iocoder/yudao/module/bpm/service/task/cc/dto/BpmDelegateExecutionDTO.java @@ -1,4 +1,4 @@ -package cn.iocoder.yudao.module.bpm.service.cc.dto; +package cn.iocoder.yudao.module.bpm.service.task.cc.dto; import org.flowable.bpmn.model.FlowElement; import org.flowable.bpmn.model.FlowableListener; diff --git a/yudao-module-bpm/yudao-module-bpm-biz/src/main/java/cn/iocoder/yudao/module/bpm/util/FlowableUtils.java b/yudao-module-bpm/yudao-module-bpm-biz/src/main/java/cn/iocoder/yudao/module/bpm/util/FlowableUtils.java index 0217ea382..c877c2a4a 100644 --- a/yudao-module-bpm/yudao-module-bpm-biz/src/main/java/cn/iocoder/yudao/module/bpm/util/FlowableUtils.java +++ b/yudao-module-bpm/yudao-module-bpm-biz/src/main/java/cn/iocoder/yudao/module/bpm/util/FlowableUtils.java @@ -1,7 +1,6 @@ package cn.iocoder.yudao.module.bpm.util; -import cn.hutool.core.collection.CollUtil; import cn.hutool.extra.spring.SpringUtil; import cn.iocoder.yudao.framework.common.util.number.NumberUtils; import org.flowable.bpmn.model.BpmnModel; @@ -15,7 +14,8 @@ import org.flowable.engine.repository.ProcessDefinition; import org.flowable.engine.runtime.ProcessInstance; import org.flowable.task.api.Task; -import java.util.*; +import java.util.List; +import java.util.Map; /** * 流程引擎工具类封装 @@ -88,40 +88,4 @@ public class FlowableUtils { return task.getName(); } - // TODO @kyle:Utils 里不做查询;可以封装到 bpmTaskService 里 - public static Map getTaskNameByTaskIds(Collection taskIds) { - TaskService taskService = SpringUtil.getBean(TaskService.class); - List tasks = taskService.createTaskQuery().taskIds(taskIds).list(); - if (CollUtil.isNotEmpty(tasks)) { - Map taskMap = new HashMap<>(tasks.size()); - for (Task task : tasks) { - taskMap.putIfAbsent(task.getId(), task.getName()); - } - return taskMap; - } - return Collections.emptyMap(); - } - - public static String getProcessInstanceNameByTaskId(String processInstanceId) { - RuntimeService runtimeService = SpringUtil.getBean(RuntimeService.class); - ProcessInstance processInstance = runtimeService.createProcessInstanceQuery() - .processInstanceId(processInstanceId) - .singleResult(); - return processInstance.getName(); - } - - // TODO @kyle:Utils 里不做查询;可以封装到 bpmTaskService 里 - public static Map getProcessInstanceNameByTaskIds(Set taskIds) { - RuntimeService runtimeService = SpringUtil.getBean(RuntimeService.class); - List processInstances = runtimeService.createProcessInstanceQuery().processInstanceIds(taskIds).list(); - if (CollUtil.isNotEmpty(processInstances)) { - Map processInstaneMap = new HashMap<>(processInstances.size()); - for (ProcessInstance processInstance : processInstances) { - processInstaneMap.putIfAbsent(processInstance.getId(), processInstance.getName()); - } - return processInstaneMap; - } - return Collections.emptyMap(); - } - } diff --git a/yudao-module-bpm/yudao-module-bpm-biz/src/test/java/cn/iocoder/yudao/module/bpm/service/cc/BpmProcessInstanceCopyServiceTest.java b/yudao-module-bpm/yudao-module-bpm-biz/src/test/java/cn/iocoder/yudao/module/bpm/service/cc/BpmProcessInstanceCopyServiceTest.java index 1f0ced103..8434399e0 100644 --- a/yudao-module-bpm/yudao-module-bpm-biz/src/test/java/cn/iocoder/yudao/module/bpm/service/cc/BpmProcessInstanceCopyServiceTest.java +++ b/yudao-module-bpm/yudao-module-bpm-biz/src/test/java/cn/iocoder/yudao/module/bpm/service/cc/BpmProcessInstanceCopyServiceTest.java @@ -1,6 +1,7 @@ package cn.iocoder.yudao.module.bpm.service.cc; import cn.iocoder.yudao.framework.test.core.ut.BaseDbUnitTest; +import cn.iocoder.yudao.module.bpm.service.task.cc.BpmProcessInstanceCopyServiceImpl; import jakarta.annotation.Resource; import org.junit.jupiter.api.Test; import org.springframework.context.annotation.Import; From 97d6aab41c12e96cce60865e6f9c0106367b659c Mon Sep 17 00:00:00 2001 From: kyle <573984425@qq.com> Date: Mon, 22 Jan 2024 12:01:06 +0800 Subject: [PATCH 016/119] =?UTF-8?q?fix:=20=E4=BF=AE=E6=AD=A3=E8=BF=90?= =?UTF-8?q?=E8=A1=8C=E6=97=B6=E7=9A=84=E6=B5=81=E7=A8=8B=E6=8A=84=E9=80=81?= =?UTF-8?q?=E7=9B=B8=E5=85=B3=E5=BC=82=E5=B8=B8?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../admin/task/BpmProcessInstanceCopyController.java | 2 +- .../module/bpm/convert/cc/BpmProcessInstanceCopyConvert.java | 3 +-- .../bpm/service/task/cc/BpmProcessInstanceCopyServiceImpl.java | 1 + 3 files changed, 3 insertions(+), 3 deletions(-) diff --git a/yudao-module-bpm/yudao-module-bpm-biz/src/main/java/cn/iocoder/yudao/module/bpm/controller/admin/task/BpmProcessInstanceCopyController.java b/yudao-module-bpm/yudao-module-bpm-biz/src/main/java/cn/iocoder/yudao/module/bpm/controller/admin/task/BpmProcessInstanceCopyController.java index 0ff980756..e1bd1ab6e 100644 --- a/yudao-module-bpm/yudao-module-bpm-biz/src/main/java/cn/iocoder/yudao/module/bpm/controller/admin/task/BpmProcessInstanceCopyController.java +++ b/yudao-module-bpm/yudao-module-bpm-biz/src/main/java/cn/iocoder/yudao/module/bpm/controller/admin/task/BpmProcessInstanceCopyController.java @@ -17,7 +17,7 @@ import org.springframework.web.bind.annotation.*; import static cn.iocoder.yudao.framework.common.pojo.CommonResult.success; import static cn.iocoder.yudao.framework.security.core.util.SecurityFrameworkUtils.getLoginUserId; -@Tag(name = "管理后台 - 流程实例") // 流程实例,通过流程定义创建的一次“申请” +@Tag(name = "管理后台 - 流程实例抄送") @RestController @RequestMapping("/bpm/process-instance/cc") @Validated diff --git a/yudao-module-bpm/yudao-module-bpm-biz/src/main/java/cn/iocoder/yudao/module/bpm/convert/cc/BpmProcessInstanceCopyConvert.java b/yudao-module-bpm/yudao-module-bpm-biz/src/main/java/cn/iocoder/yudao/module/bpm/convert/cc/BpmProcessInstanceCopyConvert.java index 7bfd8cd62..1b949dff3 100644 --- a/yudao-module-bpm/yudao-module-bpm-biz/src/main/java/cn/iocoder/yudao/module/bpm/convert/cc/BpmProcessInstanceCopyConvert.java +++ b/yudao-module-bpm/yudao-module-bpm-biz/src/main/java/cn/iocoder/yudao/module/bpm/convert/cc/BpmProcessInstanceCopyConvert.java @@ -31,8 +31,7 @@ public interface BpmProcessInstanceCopyConvert { , Map processInstaneMap , Map userMap ) { - List list = convertList(page.getList()); - List list2 = BeanUtils.toBean(page.getList(), + List list = BeanUtils.toBean(page.getList(), BpmProcessInstanceCopyPageItemRespVO.class, copy -> { MapUtils.findAndThen(userMap, Long.valueOf(copy.getCreator()), copy::setCreatorNickname); diff --git a/yudao-module-bpm/yudao-module-bpm-biz/src/main/java/cn/iocoder/yudao/module/bpm/service/task/cc/BpmProcessInstanceCopyServiceImpl.java b/yudao-module-bpm/yudao-module-bpm-biz/src/main/java/cn/iocoder/yudao/module/bpm/service/task/cc/BpmProcessInstanceCopyServiceImpl.java index 9b25b18bf..6ba0d8d82 100644 --- a/yudao-module-bpm/yudao-module-bpm-biz/src/main/java/cn/iocoder/yudao/module/bpm/service/task/cc/BpmProcessInstanceCopyServiceImpl.java +++ b/yudao-module-bpm/yudao-module-bpm-biz/src/main/java/cn/iocoder/yudao/module/bpm/service/task/cc/BpmProcessInstanceCopyServiceImpl.java @@ -59,6 +59,7 @@ public class BpmProcessInstanceCopyServiceImpl implements BpmProcessInstanceCopy private BpmCandidateSourceInfoProcessorChain processorChain; @Resource + @Lazy private BpmTaskService bpmTaskService; @Resource From 206899bfc09b7017a7c8b5b0ccc286d9e862fdb3 Mon Sep 17 00:00:00 2001 From: YunaiV Date: Mon, 22 Jan 2024 12:23:24 +0800 Subject: [PATCH 017/119] =?UTF-8?q?=F0=9F=93=96=20CRM=EF=BC=9Acode=20revie?= =?UTF-8?q?w=20=E5=BE=85=E5=8A=9E=E4=BA=8B=E9=A1=B9?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../module/crm/enums/ErrorCodeConstants.java | 1 - .../backlog/vo/CrmTodayCustomerPageReqVO.java | 10 +++++- .../dal/mysql/customer/CrmCustomerMapper.java | 35 ++++++++----------- .../message/CrmBacklogServiceImpl.java | 3 +- 4 files changed, 25 insertions(+), 24 deletions(-) diff --git a/yudao-module-crm/yudao-module-crm-api/src/main/java/cn/iocoder/yudao/module/crm/enums/ErrorCodeConstants.java b/yudao-module-crm/yudao-module-crm-api/src/main/java/cn/iocoder/yudao/module/crm/enums/ErrorCodeConstants.java index 6c0c24f0b..737e4100d 100644 --- a/yudao-module-crm/yudao-module-crm-api/src/main/java/cn/iocoder/yudao/module/crm/enums/ErrorCodeConstants.java +++ b/yudao-module-crm/yudao-module-crm-api/src/main/java/cn/iocoder/yudao/module/crm/enums/ErrorCodeConstants.java @@ -87,6 +87,5 @@ public interface ErrorCodeConstants { ErrorCode FOLLOW_UP_RECORD_DELETE_DENIED = new ErrorCode(1_020_013_001, "删除跟进记录失败,原因:没有权限"); // ========== 待办消息 1_020_014_000 ========== - ErrorCode BACKLOG_CONTACT_STATUS_INVALID = new ErrorCode(1_020_014_000, "客户联系状态有误"); } diff --git a/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/controller/admin/backlog/vo/CrmTodayCustomerPageReqVO.java b/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/controller/admin/backlog/vo/CrmTodayCustomerPageReqVO.java index e054792a9..21fd88c0b 100644 --- a/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/controller/admin/backlog/vo/CrmTodayCustomerPageReqVO.java +++ b/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/controller/admin/backlog/vo/CrmTodayCustomerPageReqVO.java @@ -14,11 +14,19 @@ import lombok.ToString; @ToString(callSuper = true) public class CrmTodayCustomerPageReqVO extends PageParam { + /** + * 联系状态 - 今日需联系 + */ public static final int CONTACT_TODAY = 1; + /** + * 联系状态 - 已逾期 + */ public static final int CONTACT_EXPIRED = 2; + /** + * 联系状态 - 已联系 + */ public static final int CONTACT_ALREADY = 3; - @Schema(description = "联系状态", example = "1") private Integer contactStatus; diff --git a/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/dal/mysql/customer/CrmCustomerMapper.java b/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/dal/mysql/customer/CrmCustomerMapper.java index 715500711..63e28329d 100644 --- a/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/dal/mysql/customer/CrmCustomerMapper.java +++ b/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/dal/mysql/customer/CrmCustomerMapper.java @@ -1,5 +1,6 @@ package cn.iocoder.yudao.module.crm.dal.mysql.customer; +import cn.hutool.core.date.LocalDateTimeUtil; import cn.iocoder.yudao.framework.common.pojo.PageResult; import cn.iocoder.yudao.framework.mybatis.core.mapper.BaseMapperX; import cn.iocoder.yudao.framework.mybatis.core.query.LambdaQueryWrapperX; @@ -13,15 +14,10 @@ import com.baomidou.mybatisplus.core.conditions.update.LambdaUpdateWrapper; import org.apache.ibatis.annotations.Mapper; import org.springframework.lang.Nullable; -import java.time.LocalDate; import java.time.LocalDateTime; -import java.time.LocalTime; import java.util.Collection; import java.util.List; -import static cn.iocoder.yudao.framework.common.exception.util.ServiceExceptionUtil.exception; -import static cn.iocoder.yudao.module.crm.enums.ErrorCodeConstants.BACKLOG_CONTACT_STATUS_INVALID; - /** * 客户 Mapper * @@ -85,24 +81,21 @@ public interface CrmCustomerMapper extends BaseMapperX { CrmQueryWrapperUtils.appendPermissionCondition(query, CrmBizTypeEnum.CRM_CUSTOMER.getType(), CrmCustomerDO::getId, userId, pageReqVO.getSceneType(), null); - query.selectAll(CrmCustomerDO.class); - // 拼接自身的查询条件 - LocalDateTime beginOfToday = LocalDate.now().atTime(LocalTime.MIN); - LocalDateTime endOfToday = LocalDate.now().atTime(LocalTime.MAX); - if (pageReqVO.getContactStatus().equals(CrmTodayCustomerPageReqVO.CONTACT_TODAY)) { - // 今天需联系 - query.between(CrmCustomerDO::getContactNextTime, beginOfToday, endOfToday); - } else if (pageReqVO.getContactStatus().equals(CrmTodayCustomerPageReqVO.CONTACT_EXPIRED)) { - // 已逾期 - query.lt(CrmCustomerDO::getContactNextTime, beginOfToday); - } else if (pageReqVO.getContactStatus().equals(CrmTodayCustomerPageReqVO.CONTACT_ALREADY)) { - // 已联系 - query.between(CrmCustomerDO::getContactLastTime, beginOfToday, endOfToday); - } else { - throw exception(BACKLOG_CONTACT_STATUS_INVALID); + query.selectAll(CrmCustomerDO.class); + if (pageReqVO.getContactStatus() != null) { + LocalDateTime beginOfToday = LocalDateTimeUtil.beginOfDay(LocalDateTime.now()); + LocalDateTime endOfToday = LocalDateTimeUtil.endOfDay(LocalDateTime.now()); + if (pageReqVO.getContactStatus().equals(CrmTodayCustomerPageReqVO.CONTACT_TODAY)) { // 今天需联系 + query.between(CrmCustomerDO::getContactNextTime, beginOfToday, endOfToday); + } else if (pageReqVO.getContactStatus().equals(CrmTodayCustomerPageReqVO.CONTACT_EXPIRED)) { // 已逾期 + query.lt(CrmCustomerDO::getContactNextTime, beginOfToday); + } else if (pageReqVO.getContactStatus().equals(CrmTodayCustomerPageReqVO.CONTACT_ALREADY)) { // 已联系 + query.between(CrmCustomerDO::getContactLastTime, beginOfToday, endOfToday); + } else { + throw new IllegalArgumentException("未知联系状态:" + pageReqVO.getContactStatus()); + } } - return selectJoinPage(pageReqVO, CrmCustomerDO.class, query); } diff --git a/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/service/message/CrmBacklogServiceImpl.java b/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/service/message/CrmBacklogServiceImpl.java index ff2560f09..5c2417266 100644 --- a/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/service/message/CrmBacklogServiceImpl.java +++ b/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/service/message/CrmBacklogServiceImpl.java @@ -10,8 +10,9 @@ import org.springframework.validation.annotation.Validated; /** * 待办消息 Service 实现类 + * + * @author dhb52 */ - @Component @Validated public class CrmBacklogServiceImpl implements CrmBacklogService { From b4150cafa7d75d3d391d2056b20feaa3985a0017 Mon Sep 17 00:00:00 2001 From: kyle <573984425@qq.com> Date: Mon, 22 Jan 2024 13:59:37 +0800 Subject: [PATCH 018/119] =?UTF-8?q?refactor:=20=E8=B0=83=E6=95=B4=E4=BB=A3?= =?UTF-8?q?=E7=A0=81=E5=88=86=E8=A3=85=E5=B1=82=E6=AC=A1?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../BpmProcessInstanceCopyController.java | 44 ++++++++++++++++++- .../cc/BpmProcessInstanceCopyService.java | 5 ++- .../cc/BpmProcessInstanceCopyServiceImpl.java | 29 +----------- 3 files changed, 48 insertions(+), 30 deletions(-) diff --git a/yudao-module-bpm/yudao-module-bpm-biz/src/main/java/cn/iocoder/yudao/module/bpm/controller/admin/task/BpmProcessInstanceCopyController.java b/yudao-module-bpm/yudao-module-bpm-biz/src/main/java/cn/iocoder/yudao/module/bpm/controller/admin/task/BpmProcessInstanceCopyController.java index e1bd1ab6e..ffb2cb5a6 100644 --- a/yudao-module-bpm/yudao-module-bpm-biz/src/main/java/cn/iocoder/yudao/module/bpm/controller/admin/task/BpmProcessInstanceCopyController.java +++ b/yudao-module-bpm/yudao-module-bpm-biz/src/main/java/cn/iocoder/yudao/module/bpm/controller/admin/task/BpmProcessInstanceCopyController.java @@ -1,20 +1,34 @@ package cn.iocoder.yudao.module.bpm.controller.admin.task; +import cn.hutool.core.collection.CollUtil; import cn.iocoder.yudao.framework.common.pojo.CommonResult; import cn.iocoder.yudao.framework.common.pojo.PageResult; import cn.iocoder.yudao.module.bpm.controller.admin.task.vo.instance.BpmProcessInstanceCopyCreateReqVO; import cn.iocoder.yudao.module.bpm.controller.admin.task.vo.instance.BpmProcessInstanceCopyMyPageReqVO; import cn.iocoder.yudao.module.bpm.controller.admin.task.vo.instance.BpmProcessInstanceCopyPageItemRespVO; +import cn.iocoder.yudao.module.bpm.convert.cc.BpmProcessInstanceCopyConvert; +import cn.iocoder.yudao.module.bpm.dal.dataobject.cc.BpmProcessInstanceCopyDO; +import cn.iocoder.yudao.module.bpm.service.task.BpmProcessInstanceService; +import cn.iocoder.yudao.module.bpm.service.task.BpmTaskService; import cn.iocoder.yudao.module.bpm.service.task.cc.BpmProcessInstanceCopyService; +import cn.iocoder.yudao.module.system.api.user.AdminUserApi; +import cn.iocoder.yudao.module.system.api.user.dto.AdminUserRespDTO; import io.swagger.v3.oas.annotations.Operation; import io.swagger.v3.oas.annotations.tags.Tag; import jakarta.annotation.Resource; import jakarta.validation.Valid; +import org.springframework.context.annotation.Lazy; import org.springframework.security.access.prepost.PreAuthorize; import org.springframework.validation.annotation.Validated; import org.springframework.web.bind.annotation.*; +import java.util.HashSet; +import java.util.Map; +import java.util.Set; +import java.util.stream.Collectors; + import static cn.iocoder.yudao.framework.common.pojo.CommonResult.success; +import static cn.iocoder.yudao.framework.common.util.collection.CollectionUtils.convertSet; import static cn.iocoder.yudao.framework.security.core.util.SecurityFrameworkUtils.getLoginUserId; @Tag(name = "管理后台 - 流程实例抄送") @@ -25,6 +39,13 @@ public class BpmProcessInstanceCopyController { @Resource private BpmProcessInstanceCopyService processInstanceCopyService; + @Resource + private BpmProcessInstanceService bpmProcessInstanceService; + @Resource + private AdminUserApi adminUserApi; + + @Resource + private BpmTaskService bpmTaskService; @PostMapping("/create") @Operation(summary = "抄送流程") @@ -38,7 +59,28 @@ public class BpmProcessInstanceCopyController { @PreAuthorize("@ss.hasPermission('bpm:process-instance-cc:query')") public CommonResult> getProcessInstanceCCPage( @Valid BpmProcessInstanceCopyMyPageReqVO pageReqVO) { - return success(processInstanceCopyService.getMyProcessInstanceCopyPage(getLoginUserId(), pageReqVO)); + return success(getMyProcessInstanceCopyPage(getLoginUserId(), pageReqVO)); } + public PageResult getMyProcessInstanceCopyPage(Long loginUserId, BpmProcessInstanceCopyMyPageReqVO pageReqVO) { + PageResult pageResult = processInstanceCopyService.getMyProcessInstanceCopyPage(loginUserId, pageReqVO); + if (CollUtil.isEmpty(pageResult.getList())) { + return new PageResult<>(pageResult.getTotal()); + } + + Map taskNameByTaskIds = bpmTaskService.getTaskNameByTaskIds(convertSet(pageResult.getList(), BpmProcessInstanceCopyDO::getTaskId)); + Map processInstanceNameByProcessInstanceIds = bpmTaskService.getProcessInstanceNameByProcessInstanceIds(convertSet(pageResult.getList(), BpmProcessInstanceCopyDO::getProcessInstanceId)); + + Set userIds = new HashSet<>(); + for (BpmProcessInstanceCopyDO doItem : pageResult.getList()) { + userIds.add(doItem.getStartUserId()); + Long userId = Long.valueOf(doItem.getCreator()); + userIds.add(userId); + } + Map userMap = adminUserApi.getUserList(userIds).stream().collect(Collectors.toMap( + AdminUserRespDTO::getId, AdminUserRespDTO::getNickname)); + + // 转换返回 + return BpmProcessInstanceCopyConvert.INSTANCE.convertPage(pageResult, taskNameByTaskIds, processInstanceNameByProcessInstanceIds, userMap); + } } diff --git a/yudao-module-bpm/yudao-module-bpm-biz/src/main/java/cn/iocoder/yudao/module/bpm/service/task/cc/BpmProcessInstanceCopyService.java b/yudao-module-bpm/yudao-module-bpm-biz/src/main/java/cn/iocoder/yudao/module/bpm/service/task/cc/BpmProcessInstanceCopyService.java index b846d15fb..93ab42492 100644 --- a/yudao-module-bpm/yudao-module-bpm-biz/src/main/java/cn/iocoder/yudao/module/bpm/service/task/cc/BpmProcessInstanceCopyService.java +++ b/yudao-module-bpm/yudao-module-bpm-biz/src/main/java/cn/iocoder/yudao/module/bpm/service/task/cc/BpmProcessInstanceCopyService.java @@ -4,6 +4,7 @@ import cn.iocoder.yudao.framework.common.pojo.PageResult; import cn.iocoder.yudao.module.bpm.controller.admin.task.vo.instance.BpmProcessInstanceCopyCreateReqVO; import cn.iocoder.yudao.module.bpm.controller.admin.task.vo.instance.BpmProcessInstanceCopyMyPageReqVO; import cn.iocoder.yudao.module.bpm.controller.admin.task.vo.instance.BpmProcessInstanceCopyPageItemRespVO; +import cn.iocoder.yudao.module.bpm.dal.dataobject.cc.BpmProcessInstanceCopyDO; import cn.iocoder.yudao.module.bpm.service.candidate.BpmCandidateSourceInfo; /** @@ -35,6 +36,6 @@ public interface BpmProcessInstanceCopyService { * @param pageReqVO 分页请求 * @return 抄送的分页结果 */ - PageResult getMyProcessInstanceCopyPage(Long loginUserId, - BpmProcessInstanceCopyMyPageReqVO pageReqVO); + PageResult getMyProcessInstanceCopyPage(Long loginUserId, + BpmProcessInstanceCopyMyPageReqVO pageReqVO); } diff --git a/yudao-module-bpm/yudao-module-bpm-biz/src/main/java/cn/iocoder/yudao/module/bpm/service/task/cc/BpmProcessInstanceCopyServiceImpl.java b/yudao-module-bpm/yudao-module-bpm-biz/src/main/java/cn/iocoder/yudao/module/bpm/service/task/cc/BpmProcessInstanceCopyServiceImpl.java index 6ba0d8d82..aad9815f4 100644 --- a/yudao-module-bpm/yudao-module-bpm-biz/src/main/java/cn/iocoder/yudao/module/bpm/service/task/cc/BpmProcessInstanceCopyServiceImpl.java +++ b/yudao-module-bpm/yudao-module-bpm-biz/src/main/java/cn/iocoder/yudao/module/bpm/service/task/cc/BpmProcessInstanceCopyServiceImpl.java @@ -62,12 +62,6 @@ public class BpmProcessInstanceCopyServiceImpl implements BpmProcessInstanceCopy @Lazy private BpmTaskService bpmTaskService; - @Resource - @Lazy // 解决循环依赖 - private BpmProcessInstanceService bpmProcessInstanceService; - @Resource - private AdminUserApi adminUserApi; - @Override public boolean makeCopy(BpmCandidateSourceInfo sourceInfo) { if (null == sourceInfo) { @@ -163,28 +157,9 @@ public class BpmProcessInstanceCopyServiceImpl implements BpmProcessInstanceCopy } @Override - public PageResult getMyProcessInstanceCopyPage(Long loginUserId, BpmProcessInstanceCopyMyPageReqVO pageReqVO) { + public PageResult getMyProcessInstanceCopyPage(Long loginUserId, BpmProcessInstanceCopyMyPageReqVO pageReqVO) { // 通过 BpmProcessInstanceExtDO 表,先查询到对应的分页 - // TODO @kyle:一般读逻辑,Service 返回 PageResult 即可。关联数据的查询和拼接,交给 Controller;目的是:保证 Service 聚焦写逻辑,清晰简洁; - PageResult pageResult = processInstanceCopyMapper.selectPage(loginUserId, pageReqVO); - if (CollUtil.isEmpty(pageResult.getList())) { - return new PageResult<>(pageResult.getTotal()); - } - - Map taskNameByTaskIds = bpmTaskService.getTaskNameByTaskIds(convertSet(pageResult.getList(), BpmProcessInstanceCopyDO::getTaskId)); - Map processInstanceNameByProcessInstanceIds = bpmTaskService.getProcessInstanceNameByProcessInstanceIds(convertSet(pageResult.getList(), BpmProcessInstanceCopyDO::getProcessInstanceId)); - - Set userIds = new HashSet<>(); - for (BpmProcessInstanceCopyDO doItem : pageResult.getList()) { - userIds.add(doItem.getStartUserId()); - Long userId = Long.valueOf(doItem.getCreator()); - userIds.add(userId); - } - Map userMap = adminUserApi.getUserList(userIds).stream().collect(Collectors.toMap( - AdminUserRespDTO::getId, AdminUserRespDTO::getNickname)); - - // 转换返回 - return BpmProcessInstanceCopyConvert.INSTANCE.convertPage(pageResult, taskNameByTaskIds, processInstanceNameByProcessInstanceIds, userMap); + return processInstanceCopyMapper.selectPage(loginUserId, pageReqVO); } } From fb54c5fc895acebca1ac11d2e76b5c664e16d21e Mon Sep 17 00:00:00 2001 From: lzxhqs <913313101@qq.com> Date: Mon, 22 Jan 2024 16:48:59 +0800 Subject: [PATCH 019/119] =?UTF-8?q?=E5=95=86=E6=9C=BA=E6=A8=A1=E5=9D=97?= =?UTF-8?q?=E4=BB=A3=E7=A0=81=E4=BC=98=E5=8C=96?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../product/CrmBusinessProductSaveReqVO.java | 7 +- .../dataobject/business/CrmBusinessDO.java | 2 +- .../business/CrmBusinessProductDO.java | 8 +- .../business/CrmBusinessProductMapper.java | 2 + .../dal/mysql/contract/CrmContractMapper.java | 5 +- .../business/CrmBusinessProductService.java | 43 ++++++++++ .../CrmBusinessProductServiceImpl.java | 48 +++++++++++ .../business/CrmBusinessServiceImpl.java | 83 +++++++++---------- .../contact/CrmContactBusinessService.java | 5 ++ .../CrmContactBusinessServiceImpl.java | 5 ++ .../service/contract/CrmContractService.java | 6 ++ .../contract/CrmContractServiceImpl.java | 5 ++ 12 files changed, 167 insertions(+), 52 deletions(-) create mode 100644 yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/service/business/CrmBusinessProductService.java create mode 100644 yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/service/business/CrmBusinessProductServiceImpl.java diff --git a/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/controller/admin/business/vo/product/CrmBusinessProductSaveReqVO.java b/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/controller/admin/business/vo/product/CrmBusinessProductSaveReqVO.java index 286f1a256..86598bad5 100644 --- a/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/controller/admin/business/vo/product/CrmBusinessProductSaveReqVO.java +++ b/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/controller/admin/business/vo/product/CrmBusinessProductSaveReqVO.java @@ -1,6 +1,7 @@ package cn.iocoder.yudao.module.crm.controller.admin.business.vo.product; import io.swagger.v3.oas.annotations.media.Schema; +import jakarta.validation.constraints.NotEmpty; import jakarta.validation.constraints.NotNull; import lombok.Data; @@ -16,12 +17,12 @@ public class CrmBusinessProductSaveReqVO { // TODO @lzxhqs:这个字段,应该是 Long 类型 @Schema(description = "商机编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "30320") @NotNull(message = "商机编号不能为空") - private Integer businessId; + private Long businessId; // TODO @lzxhqs:这个字段,应该是 Long 类型 @Schema(description = "产品编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "30320") @NotNull(message = "产品编号不能为空") - private Integer productId; + private Long productId; @Schema(description = "产品单价", requiredMode = Schema.RequiredMode.REQUIRED, example = "30320") @NotNull(message = "产品单价不能为空") @@ -45,7 +46,7 @@ public class CrmBusinessProductSaveReqVO { // TODO @lzxhqs:字符串,用 @NotEmpty,因为要考虑 "" 前端搞了这个玩意 @Schema(description = "单位", requiredMode = Schema.RequiredMode.REQUIRED, example = "30320") - @NotNull(message = "单位不能为空") + @NotEmpty(message = "单位不能为空") private String unit; } diff --git a/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/dal/dataobject/business/CrmBusinessDO.java b/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/dal/dataobject/business/CrmBusinessDO.java index e11ec5935..e8df68d2d 100644 --- a/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/dal/dataobject/business/CrmBusinessDO.java +++ b/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/dal/dataobject/business/CrmBusinessDO.java @@ -98,7 +98,7 @@ public class CrmBusinessDO extends BaseDO { * * TODO @lzxhqs:目前就是 Boolean;是否跟进 */ - private Integer followUpStatus; + private Boolean followUpStatus; /** * 负责人的用户编号 diff --git a/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/dal/dataobject/business/CrmBusinessProductDO.java b/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/dal/dataobject/business/CrmBusinessProductDO.java index 4558684e9..776d537ef 100644 --- a/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/dal/dataobject/business/CrmBusinessProductDO.java +++ b/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/dal/dataobject/business/CrmBusinessProductDO.java @@ -48,7 +48,7 @@ public class CrmBusinessProductDO extends BaseDO { /** * 产品单价 */ - private BigDecimal price; + private Integer price; /** * 销售价格 @@ -59,19 +59,19 @@ public class CrmBusinessProductDO extends BaseDO { /** * 数量 */ - private BigDecimal num; + private BigDecimal count; // TODO @lzxhqs:改成 discountPercent /** * 折扣 */ - private BigDecimal discount; + private BigDecimal discountPercent; // TODO @lzxhqs:改成 totalPrice;总计价格,和现有项目风格一致; /** * 小计(折扣后价格) */ - private BigDecimal subtotal; + private BigDecimal totalPrice; /** * 单位 diff --git a/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/dal/mysql/business/CrmBusinessProductMapper.java b/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/dal/mysql/business/CrmBusinessProductMapper.java index 5750491d8..ab84b2958 100644 --- a/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/dal/mysql/business/CrmBusinessProductMapper.java +++ b/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/dal/mysql/business/CrmBusinessProductMapper.java @@ -7,10 +7,12 @@ import org.apache.ibatis.annotations.Mapper; /** * 商机产品 Mapper // TODO @lzxhqs:类注释,和作者之间要有一个空行 + * * @author lzxhqs */ @Mapper public interface CrmBusinessProductMapper extends BaseMapperX { + default void deleteByBusinessId(Long id) { // TODO @lzxhqs:第一个方法,和类之间最好空一行; delete(CrmBusinessProductDO::getBusinessId, id); } diff --git a/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/dal/mysql/contract/CrmContractMapper.java b/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/dal/mysql/contract/CrmContractMapper.java index 2e7bafdcf..505381fb4 100644 --- a/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/dal/mysql/contract/CrmContractMapper.java +++ b/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/dal/mysql/contract/CrmContractMapper.java @@ -65,8 +65,9 @@ public interface CrmContractMapper extends BaseMapperX { default Long selectCountByContactId(Long contactId) { return selectCount(CrmContractDO::getContactId, contactId); } - default CrmContractDO selectByBizId(Long businessId) { // TODO @lzxhqs:1)方法和方法之间要有空行;2)selectCountByBusinessId,一个是应该求数量,一个是不要缩写 BizId 可读性; - return selectOne(CrmContractDO::getBusinessId, businessId); + + default Long selectCountByBusinessId(Long businessId) { // TODO @lzxhqs:1)方法和方法之间要有空行;2)selectCountByBusinessId,一个是应该求数量,一个是不要缩写 BizId 可读性; + return selectCount(CrmContractDO::getBusinessId, businessId); } } diff --git a/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/service/business/CrmBusinessProductService.java b/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/service/business/CrmBusinessProductService.java new file mode 100644 index 000000000..16dfce371 --- /dev/null +++ b/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/service/business/CrmBusinessProductService.java @@ -0,0 +1,43 @@ +package cn.iocoder.yudao.module.crm.service.business; + +import cn.iocoder.yudao.module.crm.dal.dataobject.business.CrmBusinessProductDO; + +import java.util.List; + +/** + * 商机产品关联表 Service 接口 + * + * @author lzxhqs + */ +public interface CrmBusinessProductService { + + /** + * 批量新增商机产品关联数据 + * @param list 商机产品集合 + */ + void insertBatch(List list); + + /** + * 根据商机id获取商机产品关联数据集合 + * @param businessId 商机id + */ + List selectListByBusinessId(Long businessId); + + /** + * 批量更新商机产品表 + * @param list 商机产品数据集合 + */ + void updateBatch(List list); + + /** + * 批量删除 + * @param list 需要删除的商机产品集合 + */ + void deleteBatch(List list); + + /** + *根据商机id删除商机产品关联数据 + * @param businessId 商机id + */ + void deleteByBusinessId(Long businessId); +} diff --git a/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/service/business/CrmBusinessProductServiceImpl.java b/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/service/business/CrmBusinessProductServiceImpl.java new file mode 100644 index 000000000..ec52a9d9f --- /dev/null +++ b/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/service/business/CrmBusinessProductServiceImpl.java @@ -0,0 +1,48 @@ +package cn.iocoder.yudao.module.crm.service.business; + +import cn.iocoder.yudao.framework.common.util.collection.CollectionUtils; +import cn.iocoder.yudao.module.crm.dal.dataobject.business.CrmBusinessProductDO; +import cn.iocoder.yudao.module.crm.dal.mysql.business.CrmBusinessProductMapper; +import jakarta.annotation.Resource; +import org.springframework.stereotype.Service; +import org.springframework.validation.annotation.Validated; + +import java.util.List; + +/** + * 商机产品关联表 Service 实现类 + * + * @author lzxhqs + */ +@Service +@Validated +public class CrmBusinessProductServiceImpl implements CrmBusinessProductService { + @Resource + private CrmBusinessProductMapper businessProductMapper; + + @Override + public void insertBatch(List list) { + businessProductMapper.insertBatch(list); + } + + @Override + public List selectListByBusinessId(Long businessId) { + return businessProductMapper.selectList(CrmBusinessProductDO::getBusinessId,businessId); + } + + @Override + public void updateBatch(List list) { + businessProductMapper.updateBatch(list); + } + + @Override + public void deleteBatch(List list) { + businessProductMapper.deleteBatchIds(CollectionUtils.convertList(list,CrmBusinessProductDO::getId)); + + } + + @Override + public void deleteByBusinessId(Long businessId) { + businessProductMapper.deleteByBusinessId(businessId); + } +} diff --git a/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/service/business/CrmBusinessServiceImpl.java b/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/service/business/CrmBusinessServiceImpl.java index 58c0851b5..abe55bc5f 100644 --- a/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/service/business/CrmBusinessServiceImpl.java +++ b/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/service/business/CrmBusinessServiceImpl.java @@ -2,7 +2,9 @@ package cn.iocoder.yudao.module.crm.service.business; import cn.hutool.core.collection.CollUtil; import cn.hutool.core.collection.ListUtil; +import cn.hutool.core.util.ObjectUtil; import cn.iocoder.yudao.framework.common.pojo.PageResult; +import cn.iocoder.yudao.framework.common.util.collection.CollectionUtils; import cn.iocoder.yudao.framework.common.util.object.BeanUtils; import cn.iocoder.yudao.module.crm.controller.admin.business.vo.business.CrmBusinessPageReqVO; import cn.iocoder.yudao.module.crm.controller.admin.business.vo.business.CrmBusinessSaveReqVO; @@ -13,15 +15,12 @@ import cn.iocoder.yudao.module.crm.convert.businessproduct.CrmBusinessProductCon import cn.iocoder.yudao.module.crm.dal.dataobject.business.CrmBusinessDO; import cn.iocoder.yudao.module.crm.dal.dataobject.business.CrmBusinessProductDO; import cn.iocoder.yudao.module.crm.dal.dataobject.contact.CrmContactBusinessDO; -import cn.iocoder.yudao.module.crm.dal.dataobject.contract.CrmContractDO; import cn.iocoder.yudao.module.crm.dal.mysql.business.CrmBusinessMapper; -import cn.iocoder.yudao.module.crm.dal.mysql.business.CrmBusinessProductMapper; -import cn.iocoder.yudao.module.crm.dal.mysql.contactbusinesslink.CrmContactBusinessMapper; -import cn.iocoder.yudao.module.crm.dal.mysql.contract.CrmContractMapper; import cn.iocoder.yudao.module.crm.enums.common.CrmBizTypeEnum; import cn.iocoder.yudao.module.crm.enums.permission.CrmPermissionLevelEnum; import cn.iocoder.yudao.module.crm.framework.permission.core.annotations.CrmPermission; import cn.iocoder.yudao.module.crm.service.contact.CrmContactBusinessService; +import cn.iocoder.yudao.module.crm.service.contract.CrmContractService; import cn.iocoder.yudao.module.crm.service.followup.bo.CrmUpdateFollowUpReqBO; import cn.iocoder.yudao.module.crm.service.permission.CrmPermissionService; import cn.iocoder.yudao.module.crm.service.permission.bo.CrmPermissionCreateReqBO; @@ -33,7 +32,6 @@ import org.springframework.stereotype.Service; import org.springframework.transaction.annotation.Transactional; import org.springframework.validation.annotation.Validated; -import java.util.ArrayList; import java.util.Collection; import java.util.List; @@ -56,14 +54,13 @@ public class CrmBusinessServiceImpl implements CrmBusinessService { private CrmBusinessMapper businessMapper; @Resource - private CrmBusinessProductMapper businessProductMapper; + private CrmBusinessProductService businessProductService; // TODO @lzxhqs:不直接调用这个 mapper,要调用对方的 service;每个业务独立收敛 @Resource - private CrmContractMapper contractMapper; + private CrmContractService contractService; // TODO @lzxhqs:不直接调用这个 mapper,要调用对方的 service;每个业务独立收敛 - @Resource - private CrmContactBusinessMapper contactBusinessMapper; + @Resource private CrmPermissionService permissionService; @Resource @@ -81,10 +78,9 @@ public class CrmBusinessServiceImpl implements CrmBusinessService { businessMapper.insert(business); // TODO 商机待定:插入商机与产品的关联表;校验商品存在 // TODO lzxhqs:新增时,是不是不用调用这个方法哈; - verifyCrmBusinessProduct(business.getId()); // TODO @lzxhqs:用 CollUtils.isNotEmpty; - if (!createReqVO.getProducts().isEmpty()) { - createBusinessProducts(createReqVO.getProducts(), business.getId()); + if (CollUtil.isNotEmpty(createReqVO.getProducts())) { + createBusinessProducts(createReqVO.getProducts(), business.getId(), false); } // TODO 商机待定:在联系人的详情页,如果直接【新建商机】,则需要关联下。这里要搞个 CrmContactBusinessDO 表 createContactBusiness(business.getId(), createReqVO.getContactId()); @@ -111,37 +107,39 @@ public class CrmBusinessServiceImpl implements CrmBusinessService { CrmContactBusinessDO contactBusiness = new CrmContactBusinessDO(); contactBusiness.setBusinessId(businessId); contactBusiness.setContactId(contactId); - contactBusinessMapper.insert(contactBusiness); + contactBusinessService.insert(contactBusiness); } // TODO @lzxhqs:这个方法注释格式不对;删除@description,然后把 插入商机产品关联表 作为方法注释; /** - * @param products 产品集合 - * @description 插入商机产品关联表 + * 插入商机产品关联表 + * + * @param products 产品集合 + * @param businessId 商机id + * @param updateFlag 更新标识 true 代表更新 * @author lzxhqs */ - private void createBusinessProducts(List products, Long businessId) { + private void createBusinessProducts(List products, Long businessId, Boolean updateFlag) { // TODO @lzxhqs:可以用 CollectionUtils.convertList; - List list = new ArrayList<>(); - for (CrmBusinessProductSaveReqVO product : products) { - CrmBusinessProductDO businessProductDO = CrmBusinessProductConvert.INSTANCE.convert(product); - businessProductDO.setBusinessId(businessId); - list.add(businessProductDO); - } - businessProductMapper.insertBatch(list); - } - - /** - * @param id businessId - * @description 校验管理的产品存在则删除 - * @author lzxhqs - */ - private void verifyCrmBusinessProduct(Long id) { - CrmBusinessProductDO businessProductDO = businessProductMapper.selectByBusinessId(id); - if (businessProductDO != null) { - //通过商机Id删除 - businessProductMapper.deleteByBusinessId(id); + List list = CollectionUtils.convertList(products, product -> + CrmBusinessProductConvert.INSTANCE.convert(product).setBusinessId(businessId)); + if (Boolean.TRUE.equals(updateFlag)) { +// 根据商机 id从商机产品关联表中获取已存在的数据集合 + List oldProducts = businessProductService.selectListByBusinessId(businessId); + List> diffList = CollectionUtils.diffList(oldProducts, list, (oldValue, newValue) -> + ObjectUtil.equal(oldValue.getProductId(), newValue.getProductId())); + if (CollUtil.isNotEmpty(diffList.getFirst())) { + businessProductService.insertBatch(diffList.getFirst()); + } + if (CollUtil.isNotEmpty(diffList.get(1))) { + businessProductService.updateBatch(diffList.get(1)); + } + if (CollUtil.isNotEmpty(diffList.get(2))) { + businessProductService.deleteBatch(diffList.get(2)); + } + } else { + businessProductService.insertBatch(list); } } @@ -160,9 +158,10 @@ public class CrmBusinessServiceImpl implements CrmBusinessService { businessMapper.updateById(updateObj); // TODO 商机待定:插入商机与产品的关联表;校验商品存在 // TODO @lzxhqs:更新时,可以调用 CollectionUtils 的 diffList,尽量避免这种先删除再插入;而是新增的插入、变更的更新,没的删除;不然这个表每次更新,会多好多数据; - verifyCrmBusinessProduct(updateReqVO.getId()); - if (!updateReqVO.getProducts().isEmpty()) { - createBusinessProducts(updateReqVO.getProducts(), updateReqVO.getId()); + if (CollUtil.isNotEmpty(updateReqVO.getProducts())) { + createBusinessProducts(updateReqVO.getProducts(), updateReqVO.getId(), true); + } else { + businessProductService.deleteByBusinessId(updateReqVO.getId()); } // TODO @商机待定:如果状态发生变化,插入商机状态变更记录表 @@ -197,14 +196,14 @@ public class CrmBusinessServiceImpl implements CrmBusinessService { } /** + * 删除校验合同是关联合同 + * * @param businessId 商机id - * @throws - * @description 删除校验合同是关联合同 * @author lzxhqs */ private void validateContractExists(Long businessId) { - CrmContractDO contract = contractMapper.selectByBizId(businessId); - if (contract != null) { + Long count = contractService.selectCountByBusinessId(businessId); + if (count > 0) { throw exception(BUSINESS_CONTRACT_EXISTS); } } diff --git a/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/service/contact/CrmContactBusinessService.java b/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/service/contact/CrmContactBusinessService.java index 4a6d4c7fb..7816040fb 100644 --- a/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/service/contact/CrmContactBusinessService.java +++ b/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/service/contact/CrmContactBusinessService.java @@ -42,4 +42,9 @@ public interface CrmContactBusinessService { */ List getContactBusinessListByContactId(Long contactId); + /** + * 新增联系人与商机的 + * @param contactBusiness 新增联系人与商机的对象 + */ + void insert(CrmContactBusinessDO contactBusiness); } \ No newline at end of file diff --git a/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/service/contact/CrmContactBusinessServiceImpl.java b/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/service/contact/CrmContactBusinessServiceImpl.java index d2e667919..10b6a2ec3 100644 --- a/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/service/contact/CrmContactBusinessServiceImpl.java +++ b/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/service/contact/CrmContactBusinessServiceImpl.java @@ -85,4 +85,9 @@ public class CrmContactBusinessServiceImpl implements CrmContactBusinessService return contactBusinessMapper.selectListByContactId(contactId); } + @Override + public void insert(CrmContactBusinessDO contactBusiness) { + contactBusinessMapper.insert(contactBusiness); + } + } \ No newline at end of file diff --git a/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/service/contract/CrmContractService.java b/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/service/contract/CrmContractService.java index ec52d85c0..ae1347853 100644 --- a/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/service/contract/CrmContractService.java +++ b/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/service/contract/CrmContractService.java @@ -110,4 +110,10 @@ public interface CrmContractService { */ Long getContractCountByCustomerId(Long customerId); + /** + * 根据商机ID获取关联客户的合同数量 + * @param businessId 商机ID + * @return 数量 + */ + Long selectCountByBusinessId(Long businessId); } diff --git a/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/service/contract/CrmContractServiceImpl.java b/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/service/contract/CrmContractServiceImpl.java index dc921e952..1f1561f9b 100644 --- a/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/service/contract/CrmContractServiceImpl.java +++ b/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/service/contract/CrmContractServiceImpl.java @@ -178,5 +178,10 @@ public class CrmContractServiceImpl implements CrmContractService { return contractMapper.selectCount(CrmContractDO::getCustomerId, customerId); } + @Override + public Long selectCountByBusinessId(Long businessId) { + return contractMapper.selectCountByBusinessId(businessId); + } + // TODO @合同待定:需要新增一个 ContractConfigDO 表,合同配置,重点是到期提醒; } From 5fb0c51fadf69b6a71d8c01dd87e8182d3e0cc45 Mon Sep 17 00:00:00 2001 From: kyle <573984425@qq.com> Date: Mon, 22 Jan 2024 17:23:53 +0800 Subject: [PATCH 020/119] =?UTF-8?q?refactor:=20=E6=B8=85=E7=90=86=E6=96=B9?= =?UTF-8?q?=E6=B3=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../admin/task/BpmProcessInstanceCopyController.java | 11 ++++------- 1 file changed, 4 insertions(+), 7 deletions(-) diff --git a/yudao-module-bpm/yudao-module-bpm-biz/src/main/java/cn/iocoder/yudao/module/bpm/controller/admin/task/BpmProcessInstanceCopyController.java b/yudao-module-bpm/yudao-module-bpm-biz/src/main/java/cn/iocoder/yudao/module/bpm/controller/admin/task/BpmProcessInstanceCopyController.java index ffb2cb5a6..98e04dd0a 100644 --- a/yudao-module-bpm/yudao-module-bpm-biz/src/main/java/cn/iocoder/yudao/module/bpm/controller/admin/task/BpmProcessInstanceCopyController.java +++ b/yudao-module-bpm/yudao-module-bpm-biz/src/main/java/cn/iocoder/yudao/module/bpm/controller/admin/task/BpmProcessInstanceCopyController.java @@ -59,13 +59,9 @@ public class BpmProcessInstanceCopyController { @PreAuthorize("@ss.hasPermission('bpm:process-instance-cc:query')") public CommonResult> getProcessInstanceCCPage( @Valid BpmProcessInstanceCopyMyPageReqVO pageReqVO) { - return success(getMyProcessInstanceCopyPage(getLoginUserId(), pageReqVO)); - } - - public PageResult getMyProcessInstanceCopyPage(Long loginUserId, BpmProcessInstanceCopyMyPageReqVO pageReqVO) { - PageResult pageResult = processInstanceCopyService.getMyProcessInstanceCopyPage(loginUserId, pageReqVO); + PageResult pageResult = processInstanceCopyService.getMyProcessInstanceCopyPage(getLoginUserId(), pageReqVO); if (CollUtil.isEmpty(pageResult.getList())) { - return new PageResult<>(pageResult.getTotal()); + return success(new PageResult<>(pageResult.getTotal())); } Map taskNameByTaskIds = bpmTaskService.getTaskNameByTaskIds(convertSet(pageResult.getList(), BpmProcessInstanceCopyDO::getTaskId)); @@ -81,6 +77,7 @@ public class BpmProcessInstanceCopyController { AdminUserRespDTO::getId, AdminUserRespDTO::getNickname)); // 转换返回 - return BpmProcessInstanceCopyConvert.INSTANCE.convertPage(pageResult, taskNameByTaskIds, processInstanceNameByProcessInstanceIds, userMap); + return success(BpmProcessInstanceCopyConvert.INSTANCE.convertPage(pageResult, taskNameByTaskIds, processInstanceNameByProcessInstanceIds, userMap)); } + } From f7d41186e48bb1ec32bb643885ae9be826987f61 Mon Sep 17 00:00:00 2001 From: puhui999 Date: Mon, 22 Jan 2024 20:30:12 +0800 Subject: [PATCH 021/119] =?UTF-8?q?CRM:=20=E8=8E=B7=E5=8F=96=E6=A8=A1?= =?UTF-8?q?=E5=9D=97=E6=93=8D=E4=BD=9C=E6=97=A5=E5=BF=97=E6=8E=A5=E5=8F=A3?= =?UTF-8?q?=E6=8A=BD=E7=A6=BB?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../admin/contact/CrmContactController.java | 17 ----- .../admin/customer/CrmCustomerController.java | 20 +----- .../operatelog/CrmOperateLogController.java | 62 +++++++++++++++++++ .../operatelog/vo/CrmOperateLogPageReqVO.java | 27 ++++++++ .../permission/CrmPermissionController.java | 4 +- .../admin/product/CrmProductController.java | 18 ------ .../permission/CrmPermissionConvert.java | 14 ----- .../permission/CrmPermissionServiceImpl.java | 5 +- .../bo/CrmPermissionUpdateReqBO.java | 36 ----------- 9 files changed, 96 insertions(+), 107 deletions(-) create mode 100644 yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/controller/admin/operatelog/CrmOperateLogController.java create mode 100644 yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/controller/admin/operatelog/vo/CrmOperateLogPageReqVO.java delete mode 100644 yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/service/permission/bo/CrmPermissionUpdateReqBO.java diff --git a/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/controller/admin/contact/CrmContactController.java b/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/controller/admin/contact/CrmContactController.java index 4e2e73e81..e3998834d 100644 --- a/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/controller/admin/contact/CrmContactController.java +++ b/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/controller/admin/contact/CrmContactController.java @@ -17,9 +17,6 @@ import cn.iocoder.yudao.module.crm.enums.ErrorCodeConstants; import cn.iocoder.yudao.module.crm.service.contact.CrmContactBusinessService; import cn.iocoder.yudao.module.crm.service.contact.CrmContactService; import cn.iocoder.yudao.module.crm.service.customer.CrmCustomerService; -import cn.iocoder.yudao.module.system.api.logger.OperateLogApi; -import cn.iocoder.yudao.module.system.api.logger.dto.OperateLogV2PageReqDTO; -import cn.iocoder.yudao.module.system.api.logger.dto.OperateLogV2RespDTO; import cn.iocoder.yudao.module.system.api.user.AdminUserApi; import cn.iocoder.yudao.module.system.api.user.dto.AdminUserRespDTO; import com.google.common.collect.Lists; @@ -46,7 +43,6 @@ import static cn.iocoder.yudao.framework.common.pojo.PageParam.PAGE_SIZE_NONE; import static cn.iocoder.yudao.framework.common.util.collection.CollectionUtils.*; import static cn.iocoder.yudao.framework.operatelog.core.enums.OperateTypeEnum.EXPORT; import static cn.iocoder.yudao.framework.security.core.util.SecurityFrameworkUtils.getLoginUserId; -import static cn.iocoder.yudao.module.crm.enums.LogRecordConstants.CRM_CONTACT_TYPE; @Tag(name = "管理后台 - CRM 联系人") @RestController @@ -64,8 +60,6 @@ public class CrmContactController { @Resource private AdminUserApi adminUserApi; - @Resource - private OperateLogApi operateLogApi; @PostMapping("/create") @Operation(summary = "创建联系人") @@ -158,17 +152,6 @@ public class CrmContactController { buildContactDetailPage(pageResult).getList()); } - @GetMapping("/operate-log-page") - @Operation(summary = "获得客户操作日志") - @PreAuthorize("@ss.hasPermission('crm:customer:query')") - public CommonResult> getCustomerOperateLog(@RequestParam("bizId") Long bizId) { - OperateLogV2PageReqDTO reqVO = new OperateLogV2PageReqDTO(); - reqVO.setPageSize(PAGE_SIZE_NONE); // 不分页 - reqVO.setBizType(CRM_CONTACT_TYPE); - reqVO.setBizId(bizId); - return success(operateLogApi.getOperateLogPage(BeanUtils.toBean(reqVO, OperateLogV2PageReqDTO.class))); - } - /** * 构建详细的联系人分页结果 * diff --git a/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/controller/admin/customer/CrmCustomerController.java b/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/controller/admin/customer/CrmCustomerController.java index a7b0a3730..03893b817 100644 --- a/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/controller/admin/customer/CrmCustomerController.java +++ b/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/controller/admin/customer/CrmCustomerController.java @@ -17,9 +17,6 @@ import cn.iocoder.yudao.module.crm.service.customer.CrmCustomerPoolConfigService import cn.iocoder.yudao.module.crm.service.customer.CrmCustomerService; import cn.iocoder.yudao.module.system.api.dept.DeptApi; import cn.iocoder.yudao.module.system.api.dept.dto.DeptRespDTO; -import cn.iocoder.yudao.module.system.api.logger.OperateLogApi; -import cn.iocoder.yudao.module.system.api.logger.dto.OperateLogV2PageReqDTO; -import cn.iocoder.yudao.module.system.api.logger.dto.OperateLogV2RespDTO; import cn.iocoder.yudao.module.system.api.user.AdminUserApi; import cn.iocoder.yudao.module.system.api.user.dto.AdminUserRespDTO; import io.swagger.v3.oas.annotations.Operation; @@ -44,7 +41,6 @@ import static cn.iocoder.yudao.framework.common.pojo.PageParam.PAGE_SIZE_NONE; import static cn.iocoder.yudao.framework.common.util.collection.CollectionUtils.*; import static cn.iocoder.yudao.framework.operatelog.core.enums.OperateTypeEnum.EXPORT; import static cn.iocoder.yudao.framework.security.core.util.SecurityFrameworkUtils.getLoginUserId; -import static cn.iocoder.yudao.module.crm.enums.LogRecordConstants.CRM_CUSTOMER_TYPE; @Tag(name = "管理后台 - CRM 客户") @RestController @@ -60,8 +56,7 @@ public class CrmCustomerController { private DeptApi deptApi; @Resource private AdminUserApi adminUserApi; - @Resource - private OperateLogApi operateLogApi; + @PostMapping("/create") @Operation(summary = "创建客户") @@ -182,19 +177,6 @@ public class CrmCustomerController { return success(true); } - // TODO @puhui999:要不搞个通用的 CrmOperateLogController,之后所有业务都调用它? - @GetMapping("/operate-log-page") - @Operation(summary = "获得客户操作日志") - @Parameter(name = "id", description = "客户编号", required = true) - @PreAuthorize("@ss.hasPermission('crm:customer:query')") - public CommonResult> getCustomerOperateLog(@RequestParam("id") Long id) { - OperateLogV2PageReqDTO reqDTO = new OperateLogV2PageReqDTO(); - reqDTO.setPageSize(PAGE_SIZE_NONE); // 不分页 - reqDTO.setBizType(CRM_CUSTOMER_TYPE); - reqDTO.setBizId(id); - return success(operateLogApi.getOperateLogPage(reqDTO)); - } - @PutMapping("/lock") @Operation(summary = "锁定/解锁客户") @PreAuthorize("@ss.hasPermission('crm:customer:update')") diff --git a/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/controller/admin/operatelog/CrmOperateLogController.java b/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/controller/admin/operatelog/CrmOperateLogController.java new file mode 100644 index 000000000..0894b43df --- /dev/null +++ b/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/controller/admin/operatelog/CrmOperateLogController.java @@ -0,0 +1,62 @@ +package cn.iocoder.yudao.module.crm.controller.admin.operatelog; + +import cn.iocoder.yudao.framework.common.pojo.CommonResult; +import cn.iocoder.yudao.framework.common.pojo.PageResult; +import cn.iocoder.yudao.module.crm.controller.admin.operatelog.vo.CrmOperateLogPageReqVO; +import cn.iocoder.yudao.module.crm.enums.common.CrmBizTypeEnum; +import cn.iocoder.yudao.module.system.api.logger.OperateLogApi; +import cn.iocoder.yudao.module.system.api.logger.dto.OperateLogV2PageReqDTO; +import cn.iocoder.yudao.module.system.api.logger.dto.OperateLogV2RespDTO; +import io.swagger.v3.oas.annotations.Operation; +import io.swagger.v3.oas.annotations.Parameter; +import io.swagger.v3.oas.annotations.tags.Tag; +import jakarta.annotation.Resource; +import jakarta.validation.Valid; +import org.springframework.security.access.prepost.PreAuthorize; +import org.springframework.validation.annotation.Validated; +import org.springframework.web.bind.annotation.GetMapping; +import org.springframework.web.bind.annotation.RequestMapping; +import org.springframework.web.bind.annotation.RestController; + +import java.util.HashMap; +import java.util.Map; + +import static cn.iocoder.yudao.framework.common.pojo.CommonResult.success; +import static cn.iocoder.yudao.framework.common.pojo.PageParam.PAGE_SIZE_NONE; +import static cn.iocoder.yudao.module.crm.enums.LogRecordConstants.*; + +@Tag(name = "管理后台 - 操作日志") +@RestController +@RequestMapping("/crm/operate-log") +@Validated +public class CrmOperateLogController { + + @Resource + private OperateLogApi operateLogApi; + + private static final Map BIZ_TYPE_MAP = new HashMap<>(); + + static { + BIZ_TYPE_MAP.put(CrmBizTypeEnum.CRM_LEADS.getType(), CRM_LEADS_TYPE); + BIZ_TYPE_MAP.put(CrmBizTypeEnum.CRM_CUSTOMER.getType(), CRM_CUSTOMER_TYPE); + BIZ_TYPE_MAP.put(CrmBizTypeEnum.CRM_CONTACT.getType(), CRM_CONTACT_TYPE); + BIZ_TYPE_MAP.put(CrmBizTypeEnum.CRM_BUSINESS.getType(), CRM_BUSINESS_TYPE); + BIZ_TYPE_MAP.put(CrmBizTypeEnum.CRM_CONTRACT.getType(), CRM_CONTRACT_TYPE); + BIZ_TYPE_MAP.put(CrmBizTypeEnum.CRM_PRODUCT.getType(), CRM_PRODUCT_TYPE); + BIZ_TYPE_MAP.put(CrmBizTypeEnum.CRM_RECEIVABLE.getType(), CRM_RECEIVABLE_TYPE); + BIZ_TYPE_MAP.put(CrmBizTypeEnum.CRM_RECEIVABLE_PLAN.getType(), CRM_RECEIVABLE_PLAN_TYPE); + } + + @GetMapping("/page") + @Operation(summary = "获得操作日志") + @Parameter(name = "id", description = "客户编号", required = true) + @PreAuthorize("@ss.hasPermission('crm:customer:query')") + public CommonResult> getCustomerOperateLog(@Valid CrmOperateLogPageReqVO pageReqVO) { + OperateLogV2PageReqDTO reqDTO = new OperateLogV2PageReqDTO(); + reqDTO.setPageSize(PAGE_SIZE_NONE); // 默认不分页,需要分页需注释 + reqDTO.setBizType(BIZ_TYPE_MAP.get(pageReqVO.getBizType())); + reqDTO.setBizId(pageReqVO.getBizId()); + return success(operateLogApi.getOperateLogPage(reqDTO)); + } + +} diff --git a/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/controller/admin/operatelog/vo/CrmOperateLogPageReqVO.java b/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/controller/admin/operatelog/vo/CrmOperateLogPageReqVO.java new file mode 100644 index 000000000..9f54247bf --- /dev/null +++ b/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/controller/admin/operatelog/vo/CrmOperateLogPageReqVO.java @@ -0,0 +1,27 @@ +package cn.iocoder.yudao.module.crm.controller.admin.operatelog.vo; + +import cn.iocoder.yudao.framework.common.pojo.PageParam; +import cn.iocoder.yudao.framework.common.validation.InEnum; +import cn.iocoder.yudao.module.crm.enums.common.CrmBizTypeEnum; +import io.swagger.v3.oas.annotations.media.Schema; +import jakarta.validation.constraints.NotNull; +import lombok.Data; +import lombok.EqualsAndHashCode; +import lombok.ToString; + +@Schema(description = "管理后台 - 跟进记录分页 Request VO") +@Data +@EqualsAndHashCode(callSuper = true) +@ToString(callSuper = true) +public class CrmOperateLogPageReqVO extends PageParam { + + @Schema(description = "数据类型", requiredMode = Schema.RequiredMode.REQUIRED, example = "2") + @InEnum(CrmBizTypeEnum.class) + @NotNull(message = "数据类型不能为空") + private Integer bizType; + + @Schema(description = "数据编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "2") + @NotNull(message = "数据编号不能为空") + private Long bizId; + +} diff --git a/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/controller/admin/permission/CrmPermissionController.java b/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/controller/admin/permission/CrmPermissionController.java index 8bc9a6d93..88b4b3011 100644 --- a/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/controller/admin/permission/CrmPermissionController.java +++ b/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/controller/admin/permission/CrmPermissionController.java @@ -3,6 +3,7 @@ package cn.iocoder.yudao.module.crm.controller.admin.permission; import cn.hutool.core.collection.CollUtil; import cn.iocoder.yudao.framework.common.pojo.CommonResult; import cn.iocoder.yudao.framework.common.util.collection.CollectionUtils; +import cn.iocoder.yudao.framework.common.util.object.BeanUtils; import cn.iocoder.yudao.module.crm.controller.admin.permission.vo.CrmPermissionCreateReqVO; import cn.iocoder.yudao.module.crm.controller.admin.permission.vo.CrmPermissionRespVO; import cn.iocoder.yudao.module.crm.controller.admin.permission.vo.CrmPermissionUpdateReqVO; @@ -11,6 +12,7 @@ import cn.iocoder.yudao.module.crm.dal.dataobject.permission.CrmPermissionDO; import cn.iocoder.yudao.module.crm.enums.permission.CrmPermissionLevelEnum; import cn.iocoder.yudao.module.crm.framework.permission.core.annotations.CrmPermission; import cn.iocoder.yudao.module.crm.service.permission.CrmPermissionService; +import cn.iocoder.yudao.module.crm.service.permission.bo.CrmPermissionCreateReqBO; import cn.iocoder.yudao.module.system.api.dept.DeptApi; import cn.iocoder.yudao.module.system.api.dept.PostApi; import cn.iocoder.yudao.module.system.api.dept.dto.DeptRespDTO; @@ -55,7 +57,7 @@ public class CrmPermissionController { @PreAuthorize("@ss.hasPermission('crm:permission:create')") @CrmPermission(bizTypeValue = "#reqVO.bizType", bizId = "#reqVO.bizId", level = CrmPermissionLevelEnum.OWNER) public CommonResult addPermission(@Valid @RequestBody CrmPermissionCreateReqVO reqVO) { - permissionService.createPermission(CrmPermissionConvert.INSTANCE.convert(reqVO)); + permissionService.createPermission(BeanUtils.toBean(reqVO, CrmPermissionCreateReqBO.class)); return success(true); } diff --git a/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/controller/admin/product/CrmProductController.java b/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/controller/admin/product/CrmProductController.java index fc4192443..94774373d 100644 --- a/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/controller/admin/product/CrmProductController.java +++ b/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/controller/admin/product/CrmProductController.java @@ -5,7 +5,6 @@ import cn.iocoder.yudao.framework.common.pojo.CommonResult; import cn.iocoder.yudao.framework.common.pojo.PageParam; import cn.iocoder.yudao.framework.common.pojo.PageResult; import cn.iocoder.yudao.framework.common.util.collection.SetUtils; -import cn.iocoder.yudao.framework.common.util.object.BeanUtils; import cn.iocoder.yudao.framework.excel.core.util.ExcelUtils; import cn.iocoder.yudao.framework.operatelog.core.annotations.OperateLog; import cn.iocoder.yudao.module.crm.controller.admin.product.vo.product.CrmProductPageReqVO; @@ -16,9 +15,6 @@ import cn.iocoder.yudao.module.crm.dal.dataobject.product.CrmProductCategoryDO; import cn.iocoder.yudao.module.crm.dal.dataobject.product.CrmProductDO; import cn.iocoder.yudao.module.crm.service.product.CrmProductCategoryService; import cn.iocoder.yudao.module.crm.service.product.CrmProductService; -import cn.iocoder.yudao.module.system.api.logger.OperateLogApi; -import cn.iocoder.yudao.module.system.api.logger.dto.OperateLogV2PageReqDTO; -import cn.iocoder.yudao.module.system.api.logger.dto.OperateLogV2RespDTO; import cn.iocoder.yudao.module.system.api.user.AdminUserApi; import cn.iocoder.yudao.module.system.api.user.dto.AdminUserRespDTO; import io.swagger.v3.oas.annotations.Operation; @@ -38,12 +34,10 @@ import java.util.Map; import java.util.stream.Stream; import static cn.iocoder.yudao.framework.common.pojo.CommonResult.success; -import static cn.iocoder.yudao.framework.common.pojo.PageParam.PAGE_SIZE_NONE; import static cn.iocoder.yudao.framework.common.util.collection.CollectionUtils.convertSet; import static cn.iocoder.yudao.framework.common.util.collection.CollectionUtils.convertSetByFlatMap; import static cn.iocoder.yudao.framework.operatelog.core.enums.OperateTypeEnum.EXPORT; import static cn.iocoder.yudao.framework.security.core.util.SecurityFrameworkUtils.getLoginUserId; -import static cn.iocoder.yudao.module.crm.enums.LogRecordConstants.CRM_PRODUCT_TYPE; @Tag(name = "管理后台 - CRM 产品") @RestController @@ -56,8 +50,6 @@ public class CrmProductController { @Resource private CrmProductCategoryService productCategoryService; @Resource - private OperateLogApi operateLogApi; - @Resource private AdminUserApi adminUserApi; @PostMapping("/create") @@ -131,14 +123,4 @@ public class CrmProductController { return CrmProductConvert.INSTANCE.convertList(list, userMap, productCategoryList); } - @GetMapping("/operate-log-page") - @Operation(summary = "获得产品操作日志") - @PreAuthorize("@ss.hasPermission('crm:product:query')") - public CommonResult> getProductOperateLog(@RequestParam("bizId") Long bizId) { - OperateLogV2PageReqDTO reqVO = new OperateLogV2PageReqDTO(); - reqVO.setPageSize(PAGE_SIZE_NONE); // 不分页 - reqVO.setBizType(CRM_PRODUCT_TYPE).setBizId(bizId); - return success(operateLogApi.getOperateLogPage(BeanUtils.toBean(reqVO, OperateLogV2PageReqDTO.class))); - } - } diff --git a/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/convert/permission/CrmPermissionConvert.java b/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/convert/permission/CrmPermissionConvert.java index 6979a055e..61145f688 100644 --- a/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/convert/permission/CrmPermissionConvert.java +++ b/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/convert/permission/CrmPermissionConvert.java @@ -3,12 +3,9 @@ package cn.iocoder.yudao.module.crm.convert.permission; import cn.hutool.core.collection.CollUtil; import cn.iocoder.yudao.framework.common.util.collection.CollectionUtils; import cn.iocoder.yudao.framework.common.util.collection.MapUtils; -import cn.iocoder.yudao.module.crm.controller.admin.permission.vo.CrmPermissionCreateReqVO; import cn.iocoder.yudao.module.crm.controller.admin.permission.vo.CrmPermissionRespVO; import cn.iocoder.yudao.module.crm.controller.admin.permission.vo.CrmPermissionUpdateReqVO; import cn.iocoder.yudao.module.crm.dal.dataobject.permission.CrmPermissionDO; -import cn.iocoder.yudao.module.crm.service.permission.bo.CrmPermissionCreateReqBO; -import cn.iocoder.yudao.module.crm.service.permission.bo.CrmPermissionUpdateReqBO; import cn.iocoder.yudao.module.system.api.dept.dto.DeptRespDTO; import cn.iocoder.yudao.module.system.api.dept.dto.PostRespDTO; import cn.iocoder.yudao.module.system.api.user.dto.AdminUserRespDTO; @@ -32,14 +29,6 @@ public interface CrmPermissionConvert { CrmPermissionConvert INSTANCE = Mappers.getMapper(CrmPermissionConvert.class); - CrmPermissionDO convert(CrmPermissionCreateReqBO createBO); - - CrmPermissionDO convert(CrmPermissionUpdateReqBO updateBO); - - CrmPermissionCreateReqBO convert(CrmPermissionCreateReqVO reqVO); - - CrmPermissionUpdateReqBO convert(CrmPermissionUpdateReqVO updateReqVO); - List convert(List permission); default List convert(List permission, List userList, @@ -65,7 +54,4 @@ public interface CrmPermissionConvert { id -> new CrmPermissionDO().setId(id).setLevel(updateReqVO.getLevel())); } - // TODO @puhui999:搞成 BeanUtils - List convertList(List list); - } diff --git a/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/service/permission/CrmPermissionServiceImpl.java b/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/service/permission/CrmPermissionServiceImpl.java index f135da993..07818bd07 100644 --- a/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/service/permission/CrmPermissionServiceImpl.java +++ b/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/service/permission/CrmPermissionServiceImpl.java @@ -2,6 +2,7 @@ package cn.iocoder.yudao.module.crm.service.permission; import cn.hutool.core.collection.CollUtil; import cn.hutool.core.util.ObjUtil; +import cn.iocoder.yudao.framework.common.util.object.BeanUtils; import cn.iocoder.yudao.module.crm.controller.admin.permission.vo.CrmPermissionUpdateReqVO; import cn.iocoder.yudao.module.crm.convert.permission.CrmPermissionConvert; import cn.iocoder.yudao.module.crm.dal.dataobject.permission.CrmPermissionDO; @@ -50,7 +51,7 @@ public class CrmPermissionServiceImpl implements CrmPermissionService { adminUserApi.validateUserList(Collections.singletonList(createReqBO.getUserId())); // 2. 创建 - CrmPermissionDO permission = CrmPermissionConvert.INSTANCE.convert(createReqBO); + CrmPermissionDO permission = BeanUtils.toBean(createReqBO, CrmPermissionDO.class); permissionMapper.insert(permission); return permission.getId(); } @@ -62,7 +63,7 @@ public class CrmPermissionServiceImpl implements CrmPermissionService { adminUserApi.validateUserList(convertSet(createReqBOs, CrmPermissionCreateReqBO::getUserId)); // 2. 创建 - List permissions = CrmPermissionConvert.INSTANCE.convertList(createReqBOs); + List permissions = BeanUtils.toBean(createReqBOs, CrmPermissionDO.class); permissionMapper.insertBatch(permissions); } diff --git a/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/service/permission/bo/CrmPermissionUpdateReqBO.java b/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/service/permission/bo/CrmPermissionUpdateReqBO.java deleted file mode 100644 index 0ac474101..000000000 --- a/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/service/permission/bo/CrmPermissionUpdateReqBO.java +++ /dev/null @@ -1,36 +0,0 @@ -package cn.iocoder.yudao.module.crm.service.permission.bo; - -import cn.iocoder.yudao.framework.common.validation.InEnum; -import cn.iocoder.yudao.module.crm.enums.permission.CrmPermissionLevelEnum; -import lombok.Data; - -import jakarta.validation.constraints.NotNull; - -/** - * crm 数据权限 Update Req BO - * - * @author HUIHUI - */ -@Data -public class CrmPermissionUpdateReqBO { - - /** - * 数据权限编号 - */ - @NotNull(message = "数据权限编号不能为空") - private Long id; - - /** - * 当前登录用户编号 - */ - @NotNull(message = "用户编号不能为空") - private Long userId; - - /** - * 权限级别 - */ - @NotNull(message = "权限级别不能为空") - @InEnum(CrmPermissionLevelEnum.class) - private Integer level; - -} From 8675d135484a6f30de32075ba57f686dd258859f Mon Sep 17 00:00:00 2001 From: puhui999 Date: Mon, 22 Jan 2024 22:23:23 +0800 Subject: [PATCH 022/119] =?UTF-8?q?CRM-=E7=BA=BF=E7=B4=A2=EF=BC=9A?= =?UTF-8?q?=E5=AE=8C=E5=96=84=E7=BA=BF=E7=B4=A2=E8=BD=AC=E5=AE=A2=E6=88=B7?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../admin/clue/CrmClueController.java | 2 +- .../followup/CrmFollowUpRecordMapper.java | 13 ++ .../crm/service/clue/CrmClueService.java | 3 +- .../crm/service/clue/CrmClueServiceImpl.java | 89 ++++++++----- .../service/customer/CrmCustomerService.java | 10 ++ .../customer/CrmCustomerServiceImpl.java | 22 +++ .../customer/bo/CrmCustomerCreateReqBO.java | 125 ++++++++++++++++++ .../followup/CrmFollowUpRecordService.java | 28 ++++ .../CrmFollowUpRecordServiceImpl.java | 23 ++++ .../followup/bo/CrmFollowUpCreateReqBO.java | 78 +++++++++++ .../service/clue/CrmClueServiceImplTest.java | 3 +- 11 files changed, 360 insertions(+), 36 deletions(-) create mode 100644 yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/service/customer/bo/CrmCustomerCreateReqBO.java create mode 100644 yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/service/followup/bo/CrmFollowUpCreateReqBO.java diff --git a/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/controller/admin/clue/CrmClueController.java b/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/controller/admin/clue/CrmClueController.java index f6d32f3a4..9c6a88f2d 100644 --- a/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/controller/admin/clue/CrmClueController.java +++ b/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/controller/admin/clue/CrmClueController.java @@ -39,7 +39,7 @@ public class CrmClueController { @Operation(summary = "创建线索") @PreAuthorize("@ss.hasPermission('crm:clue:create')") public CommonResult createClue(@Valid @RequestBody CrmClueSaveReqVO createReqVO) { - return success(clueService.createClue(createReqVO)); + return success(clueService.createClue(createReqVO, getLoginUserId())); } @PutMapping("/update") diff --git a/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/dal/mysql/followup/CrmFollowUpRecordMapper.java b/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/dal/mysql/followup/CrmFollowUpRecordMapper.java index a9b1dc315..59d800c22 100644 --- a/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/dal/mysql/followup/CrmFollowUpRecordMapper.java +++ b/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/dal/mysql/followup/CrmFollowUpRecordMapper.java @@ -7,6 +7,9 @@ import cn.iocoder.yudao.module.crm.controller.admin.followup.vo.CrmFollowUpRecor import cn.iocoder.yudao.module.crm.dal.dataobject.followup.CrmFollowUpRecordDO; import org.apache.ibatis.annotations.Mapper; +import java.util.Collection; +import java.util.List; + /** * 跟进记录 Mapper * @@ -22,4 +25,14 @@ public interface CrmFollowUpRecordMapper extends BaseMapperX().eq(CrmFollowUpRecordDO::getBizType, bizType) + .eq(CrmFollowUpRecordDO::getBizId, bizId)); + } + + default List selectListByBiz(Integer bizType, Collection bizIds) { + return selectList(new LambdaQueryWrapperX().eq(CrmFollowUpRecordDO::getBizType, bizType) + .in(CrmFollowUpRecordDO::getBizId, bizIds)); + } + } \ No newline at end of file diff --git a/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/service/clue/CrmClueService.java b/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/service/clue/CrmClueService.java index 6efffa96a..b189bd266 100644 --- a/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/service/clue/CrmClueService.java +++ b/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/service/clue/CrmClueService.java @@ -23,9 +23,10 @@ public interface CrmClueService { * 创建线索 * * @param createReqVO 创建信息 + * @param userId 用户编号 * @return 编号 */ - Long createClue(@Valid CrmClueSaveReqVO createReqVO); + Long createClue(@Valid CrmClueSaveReqVO createReqVO, Long userId); /** * 更新线索 diff --git a/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/service/clue/CrmClueServiceImpl.java b/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/service/clue/CrmClueServiceImpl.java index 996a6b74e..898a576a0 100644 --- a/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/service/clue/CrmClueServiceImpl.java +++ b/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/service/clue/CrmClueServiceImpl.java @@ -3,10 +3,9 @@ package cn.iocoder.yudao.module.crm.service.clue; import cn.hutool.core.collection.CollUtil; import cn.hutool.core.collection.ListUtil; import cn.hutool.core.lang.Assert; +import cn.hutool.core.util.ObjUtil; import cn.hutool.core.util.ObjectUtil; -import cn.hutool.core.util.StrUtil; import cn.iocoder.yudao.framework.common.pojo.PageResult; -import cn.iocoder.yudao.framework.common.util.collection.CollectionUtils; import cn.iocoder.yudao.framework.common.util.object.BeanUtils; import cn.iocoder.yudao.module.crm.controller.admin.clue.vo.CrmCluePageReqVO; import cn.iocoder.yudao.module.crm.controller.admin.clue.vo.CrmClueSaveReqVO; @@ -15,11 +14,16 @@ import cn.iocoder.yudao.module.crm.controller.admin.clue.vo.CrmClueTransformReqV import cn.iocoder.yudao.module.crm.controller.admin.customer.vo.CrmCustomerSaveReqVO; import cn.iocoder.yudao.module.crm.convert.clue.CrmClueConvert; import cn.iocoder.yudao.module.crm.dal.dataobject.clue.CrmClueDO; +import cn.iocoder.yudao.module.crm.dal.dataobject.customer.CrmCustomerDO; +import cn.iocoder.yudao.module.crm.dal.dataobject.followup.CrmFollowUpRecordDO; import cn.iocoder.yudao.module.crm.dal.mysql.clue.CrmClueMapper; import cn.iocoder.yudao.module.crm.enums.common.CrmBizTypeEnum; import cn.iocoder.yudao.module.crm.enums.permission.CrmPermissionLevelEnum; import cn.iocoder.yudao.module.crm.framework.permission.core.annotations.CrmPermission; import cn.iocoder.yudao.module.crm.service.customer.CrmCustomerService; +import cn.iocoder.yudao.module.crm.service.customer.bo.CrmCustomerCreateReqBO; +import cn.iocoder.yudao.module.crm.service.followup.CrmFollowUpRecordService; +import cn.iocoder.yudao.module.crm.service.followup.bo.CrmFollowUpCreateReqBO; import cn.iocoder.yudao.module.crm.service.followup.bo.CrmUpdateFollowUpReqBO; import cn.iocoder.yudao.module.crm.service.permission.CrmPermissionService; import cn.iocoder.yudao.module.crm.service.permission.bo.CrmPermissionCreateReqBO; @@ -32,17 +36,14 @@ import org.springframework.stereotype.Service; import org.springframework.transaction.annotation.Transactional; import org.springframework.validation.annotation.Validated; -import java.util.Collection; -import java.util.List; -import java.util.Objects; -import java.util.Set; +import java.util.*; import static cn.iocoder.yudao.framework.common.exception.util.ServiceExceptionUtil.exception; -import static cn.iocoder.yudao.framework.common.util.collection.CollectionUtils.convertSet; -import static cn.iocoder.yudao.framework.security.core.util.SecurityFrameworkUtils.getLoginUserId; +import static cn.iocoder.yudao.framework.common.util.collection.CollectionUtils.*; import static cn.iocoder.yudao.module.crm.enums.ErrorCodeConstants.*; import static cn.iocoder.yudao.module.crm.enums.LogRecordConstants.*; import static cn.iocoder.yudao.module.system.enums.ErrorCodeConstants.USER_NOT_EXISTS; +import static java.util.Collections.singletonList; /** * 线索 Service 实现类 @@ -61,7 +62,8 @@ public class CrmClueServiceImpl implements CrmClueService { @Resource private CrmPermissionService crmPermissionService; - + @Resource + private CrmFollowUpRecordService followUpRecordService; @Resource private AdminUserApi adminUserApi; @@ -69,21 +71,23 @@ public class CrmClueServiceImpl implements CrmClueService { @Transactional(rollbackFor = Exception.class) @LogRecord(type = CRM_LEADS_TYPE, subType = CRM_LEADS_CREATE_SUB_TYPE, bizNo = "{{#clue.id}}", success = CRM_LEADS_CREATE_SUCCESS) - public Long createClue(CrmClueSaveReqVO createReqVO) { + public Long createClue(CrmClueSaveReqVO createReqVO, Long userId) { // 1. 校验关联数据 validateRelationDataExists(createReqVO); // 2. 插入 CrmClueDO clue = BeanUtils.toBean(createReqVO, CrmClueDO.class); + if (ObjUtil.isNull(createReqVO.getOwnerUserId())) { + clue.setOwnerUserId(userId); // 如果没有设置负责人那么默认操作人为负责人 + } else { + // 校验负责人是否存在 + adminUserApi.validateUserList(singletonList(createReqVO.getOwnerUserId())); + } clueMapper.insert(clue); // 3. 创建数据权限 - CrmPermissionCreateReqBO createReqBO = new CrmPermissionCreateReqBO() - .setBizType(CrmBizTypeEnum.CRM_LEADS.getType()) - .setBizId(clue.getId()) - // 设置当前操作的人为负责人 - .setUserId(getLoginUserId()) - .setLevel(CrmPermissionLevelEnum.OWNER.getLevel()); + CrmPermissionCreateReqBO createReqBO = new CrmPermissionCreateReqBO().setBizType(CrmBizTypeEnum.CRM_LEADS.getType()) + .setBizId(clue.getId()).setUserId(clue.getOwnerUserId()).setLevel(CrmPermissionLevelEnum.OWNER.getLevel()); crmPermissionService.createPermission(createReqBO); // 4. 记录操作日志上下文 @@ -132,7 +136,10 @@ public class CrmClueServiceImpl implements CrmClueService { // 3. 删除数据权限 crmPermissionService.deletePermission(CrmBizTypeEnum.CRM_LEADS.getType(), id); - // 4. 记录操作日志上下文 + // 4. 删除跟进 + followUpRecordService.deleteFollowUpRecordByBiz(CrmBizTypeEnum.CRM_LEADS.getType(), id); + + // 记录操作日志上下文 LogRecordContext.putVariable("clueName", clue.getName()); } @@ -179,31 +186,47 @@ public class CrmClueServiceImpl implements CrmClueService { @Override @Transactional(rollbackFor = Exception.class) public void translateCustomer(CrmClueTransformReqVO reqVO, Long userId) { - // 校验线索都存在 + // 1.1 校验线索都存在 Set clueIds = reqVO.getIds(); List clues = getClueList(clueIds, userId); if (CollUtil.isEmpty(clues) || ObjectUtil.notEqual(clues.size(), clueIds.size())) { clueIds.removeAll(convertSet(clues, CrmClueDO::getId)); - throw exception(CLUE_ANY_CLUE_NOT_EXISTS, StrUtil.join(",", clueIds)); + throw exception(CLUE_ANY_CLUE_NOT_EXISTS, clueIds); } - - // 存在已经转化的,直接提示哈。避免操作的用户,以为都转化成功了 - List translatedClues = CollectionUtils.filterList(clues, + // 1.2 存在已经转化的,直接提示哈。避免操作的用户,以为都转化成功了 + List translatedClues = filterList(clues, clue -> ObjectUtil.equal(Boolean.TRUE, clue.getTransformStatus())); if (CollUtil.isNotEmpty(translatedClues)) { - throw exception(CLUE_ANY_CLUE_ALREADY_TRANSLATED, StrUtil.join(",", convertSet(translatedClues, CrmClueDO::getId))); + throw exception(CLUE_ANY_CLUE_ALREADY_TRANSLATED, convertSet(translatedClues, CrmClueDO::getId)); } - // 遍历线索(未转化的线索),创建对应的客户 - reqVO.getIds().forEach(id -> { - // 1. 创建客户 - CrmCustomerSaveReqVO customerSaveReqVO = BeanUtils.toBean(id, CrmCustomerSaveReqVO.class).setId(null); - Long customerId = customerService.createCustomer(customerSaveReqVO, userId); - // TODO @puhui999:如果有跟进记录,需要一起转过去;提问:艿艿这里是复制线索所有的跟进吗?还是直接把线索相关的跟进 bizType、bizId 全改为关联客户? - // 2. 更新线索 - clueMapper.updateById(new CrmClueDO().setId(id) - .setTransformStatus(Boolean.TRUE).setCustomerId(customerId)); - }); + // 2. 遍历线索(未转化的线索),创建对应的客户 + List translateClues = filterList(clues, clue -> ObjUtil.equal(Boolean.FALSE, clue.getTransformStatus())); + List customers = customerService.createCustomerBatch(convertList(translateClues, clue -> + BeanUtils.toBean(clue, CrmCustomerCreateReqBO.class)), userId); + + Map clueCustomerIdMap = new HashMap<>(translateClues.size()); + // 2.1 更新线索 + clueMapper.updateBatch(convertList(customers, customer -> { + CrmClueDO firstClue = findFirst(translateClues, clue -> ObjUtil.equal(clue.getName(), customer.getName())); + clueCustomerIdMap.put(firstClue.getId(), customer.getId()); + return new CrmClueDO().setId(firstClue.getId()).setTransformStatus(Boolean.TRUE).setCustomerId(customer.getId()); + })); + // 2.3 复制跟进 + updateFollowUpRecords(clueCustomerIdMap); + } + + private void updateFollowUpRecords(Map clueCustomerIdMap) { + List followUpRecords = followUpRecordService.getFollowUpRecordByBiz( + CrmBizTypeEnum.CRM_LEADS.getType(), clueCustomerIdMap.keySet()); + if (CollUtil.isEmpty(followUpRecords)) { + return; + } + + // 创建跟进 + followUpRecordService.createFollowUpRecordBatch(convertList(followUpRecords, followUpRecord -> + BeanUtils.toBean(followUpRecord, CrmFollowUpCreateReqBO.class).setBizType(CrmBizTypeEnum.CRM_CUSTOMER.getType()) + .setBizId(clueCustomerIdMap.get(followUpRecord.getBizId())))); } private void validateRelationDataExists(CrmClueSaveReqVO reqVO) { diff --git a/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/service/customer/CrmCustomerService.java b/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/service/customer/CrmCustomerService.java index 8cd2448b7..38d5f082b 100644 --- a/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/service/customer/CrmCustomerService.java +++ b/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/service/customer/CrmCustomerService.java @@ -6,6 +6,7 @@ import cn.iocoder.yudao.module.crm.controller.admin.customer.vo.CrmCustomerPageR import cn.iocoder.yudao.module.crm.controller.admin.customer.vo.CrmCustomerSaveReqVO; import cn.iocoder.yudao.module.crm.controller.admin.customer.vo.CrmCustomerTransferReqVO; import cn.iocoder.yudao.module.crm.dal.dataobject.customer.CrmCustomerDO; +import cn.iocoder.yudao.module.crm.service.customer.bo.CrmCustomerCreateReqBO; import cn.iocoder.yudao.module.crm.service.followup.bo.CrmUpdateFollowUpReqBO; import jakarta.validation.Valid; @@ -98,6 +99,15 @@ public interface CrmCustomerService { */ void updateCustomerFollowUp(CrmUpdateFollowUpReqBO customerUpdateFollowUpReqBO); + /** + * 批量创建客户 + * + * @param customerCreateReqBOs 请求 + * @param userId 用户编号 + * @return 客户列表 + */ + List createCustomerBatch(List customerCreateReqBOs, Long userId); + // ==================== 公海相关操作 ==================== /** diff --git a/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/service/customer/CrmCustomerServiceImpl.java b/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/service/customer/CrmCustomerServiceImpl.java index 5c1f5134a..45893fa87 100644 --- a/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/service/customer/CrmCustomerServiceImpl.java +++ b/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/service/customer/CrmCustomerServiceImpl.java @@ -21,6 +21,7 @@ import cn.iocoder.yudao.module.crm.framework.permission.core.util.CrmPermissionU import cn.iocoder.yudao.module.crm.service.business.CrmBusinessService; import cn.iocoder.yudao.module.crm.service.contact.CrmContactService; import cn.iocoder.yudao.module.crm.service.contract.CrmContractService; +import cn.iocoder.yudao.module.crm.service.customer.bo.CrmCustomerCreateReqBO; import cn.iocoder.yudao.module.crm.service.followup.bo.CrmUpdateFollowUpReqBO; import cn.iocoder.yudao.module.crm.service.permission.CrmPermissionService; import cn.iocoder.yudao.module.crm.service.permission.bo.CrmPermissionCreateReqBO; @@ -42,10 +43,12 @@ import java.util.Collections; import java.util.List; import static cn.iocoder.yudao.framework.common.exception.util.ServiceExceptionUtil.exception; +import static cn.iocoder.yudao.framework.common.util.collection.CollectionUtils.convertList; import static cn.iocoder.yudao.module.crm.enums.ErrorCodeConstants.*; import static cn.iocoder.yudao.module.crm.enums.LogRecordConstants.*; import static cn.iocoder.yudao.module.crm.enums.customer.CrmCustomerLimitConfigTypeEnum.CUSTOMER_LOCK_LIMIT; import static cn.iocoder.yudao.module.crm.enums.customer.CrmCustomerLimitConfigTypeEnum.CUSTOMER_OWNER_LIMIT; +import static java.util.Collections.emptyList; import static java.util.Collections.singletonList; /** @@ -209,6 +212,25 @@ public class CrmCustomerServiceImpl implements CrmCustomerService { customerMapper.updateById(BeanUtils.toBean(customerUpdateFollowUpReqBO, CrmCustomerDO.class).setId(customerUpdateFollowUpReqBO.getBizId())); } + @Override + @Transactional(rollbackFor = Exception.class) + public List createCustomerBatch(List customerCreateReqBOs, Long userId) { + if (CollUtil.isEmpty(customerCreateReqBOs)) { + return emptyList(); + } + + // 创建客户 + List customers = convertList(customerCreateReqBOs, customerBO -> + BeanUtils.toBean(customerBO, CrmCustomerDO.class).setOwnerUserId(userId)); + customerMapper.insertBatch(customers); + + // 创建负责人数据权限 + permissionService.createPermissionBatch(convertList(customers, customer -> new CrmPermissionCreateReqBO() + .setBizType(CrmBizTypeEnum.CRM_CUSTOMER.getType()).setBizId(customer.getId()).setUserId(userId) + .setLevel(CrmPermissionLevelEnum.OWNER.getLevel()))); + return customers; + } + // ==================== 公海相关操作 ==================== @Override diff --git a/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/service/customer/bo/CrmCustomerCreateReqBO.java b/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/service/customer/bo/CrmCustomerCreateReqBO.java new file mode 100644 index 000000000..6d80b0e4c --- /dev/null +++ b/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/service/customer/bo/CrmCustomerCreateReqBO.java @@ -0,0 +1,125 @@ +package cn.iocoder.yudao.module.crm.service.customer.bo; + +import cn.iocoder.yudao.framework.common.validation.Mobile; +import cn.iocoder.yudao.framework.common.validation.Telephone; +import cn.iocoder.yudao.module.crm.enums.DictTypeConstants; +import jakarta.validation.constraints.Email; +import jakarta.validation.constraints.NotEmpty; +import jakarta.validation.constraints.Size; +import lombok.Data; + +import java.time.LocalDateTime; + +/** + * 客户创建 Create Req BO + * + * @author HUIHUI + */ +@Data +public class CrmCustomerCreateReqBO { + + /** + * 客户名称 + */ + @NotEmpty(message = "客户名称不能为空") + private String name; + /** + * 跟进状态 + */ + private Boolean followUpStatus; + /** + * 锁定状态 + */ + private Boolean lockStatus; + /** + * 成交状态 + */ + private Boolean dealStatus; + /** + * 所属行业 + * + * 对应字典 {@link DictTypeConstants#CRM_CUSTOMER_INDUSTRY} + */ + private Integer industryId; + /** + * 客户等级 + * + * 对应字典 {@link DictTypeConstants#CRM_CUSTOMER_LEVEL} + */ + private Integer level; + /** + * 客户来源 + * + * 对应字典 {@link DictTypeConstants#CRM_CUSTOMER_SOURCE} + */ + private Integer source; + + /** + * 手机 + */ + @Mobile + private String mobile; + /** + * 电话 + */ + @Telephone + private String telephone; + /** + * 网址 + */ + private String website; + /** + * QQ + */ + private String qq; + /** + * wechat + */ + private String wechat; + + /** + * 邮箱 + */ + @Email(message = "邮箱格式不正确") + private String email; + + /** + * 客户描述 + */ + @Size(max = 4096, message = "客户描述长度不能超过 4096 个字符") + private String description; + /** + * 备注 + */ + private String remark; + /** + * 负责人的用户编号 + * + * 关联 AdminUserDO 的 id 字段 + */ + private Long ownerUserId; + /** + * 所在地 + * + * 关联 {@link cn.iocoder.yudao.framework.ip.core.Area#getId()} 字段 + */ + private Integer areaId; + /** + * 详细地址 + */ + private String detailAddress; + + /** + * 最后跟进时间 + */ + private LocalDateTime contactLastTime; + /** + * 最后跟进内容 + */ + private String contactLastContent; + /** + * 下次联系时间 + */ + private LocalDateTime contactNextTime; + +} diff --git a/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/service/followup/CrmFollowUpRecordService.java b/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/service/followup/CrmFollowUpRecordService.java index c0fb69f25..f881e5259 100644 --- a/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/service/followup/CrmFollowUpRecordService.java +++ b/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/service/followup/CrmFollowUpRecordService.java @@ -4,8 +4,12 @@ import cn.iocoder.yudao.framework.common.pojo.PageResult; import cn.iocoder.yudao.module.crm.controller.admin.followup.vo.CrmFollowUpRecordPageReqVO; import cn.iocoder.yudao.module.crm.controller.admin.followup.vo.CrmFollowUpRecordSaveReqVO; import cn.iocoder.yudao.module.crm.dal.dataobject.followup.CrmFollowUpRecordDO; +import cn.iocoder.yudao.module.crm.service.followup.bo.CrmFollowUpCreateReqBO; import jakarta.validation.Valid; +import java.util.Collection; +import java.util.List; + /** * 跟进记录 Service 接口 * @@ -21,6 +25,13 @@ public interface CrmFollowUpRecordService { */ Long createFollowUpRecord(@Valid CrmFollowUpRecordSaveReqVO createReqVO); + /** + * 创建更进 + * + * @param followUpCreateReqBOs 请求 + */ + void createFollowUpRecordBatch(List followUpCreateReqBOs); + /** * 删除跟进记录 (数据权限基于 bizType、 bizId) * @@ -29,6 +40,14 @@ public interface CrmFollowUpRecordService { */ void deleteFollowUpRecord(Long id, Long userId); + /** + * 删除跟进 + * + * @param bizType 模块类型 + * @param bizId 模块数据编号 + */ + void deleteFollowUpRecordByBiz(Integer bizType, Long bizId); + /** * 获得跟进记录 * @@ -45,4 +64,13 @@ public interface CrmFollowUpRecordService { */ PageResult getFollowUpRecordPage(CrmFollowUpRecordPageReqVO pageReqVO); + /** + * 获取跟进记录 + * + * @param bizType 模块类型 + * @param bizIds 模块数据编号 + * @return 跟进列表 + */ + List getFollowUpRecordByBiz(Integer bizType, Collection bizIds); + } \ No newline at end of file diff --git a/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/service/followup/CrmFollowUpRecordServiceImpl.java b/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/service/followup/CrmFollowUpRecordServiceImpl.java index 670fdacfc..ce76e6a8f 100644 --- a/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/service/followup/CrmFollowUpRecordServiceImpl.java +++ b/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/service/followup/CrmFollowUpRecordServiceImpl.java @@ -17,6 +17,7 @@ import cn.iocoder.yudao.module.crm.service.clue.CrmClueService; import cn.iocoder.yudao.module.crm.service.contact.CrmContactService; import cn.iocoder.yudao.module.crm.service.contract.CrmContractService; import cn.iocoder.yudao.module.crm.service.customer.CrmCustomerService; +import cn.iocoder.yudao.module.crm.service.followup.bo.CrmFollowUpCreateReqBO; import cn.iocoder.yudao.module.crm.service.followup.bo.CrmUpdateFollowUpReqBO; import cn.iocoder.yudao.module.crm.service.permission.CrmPermissionService; import jakarta.annotation.Resource; @@ -24,6 +25,7 @@ import org.springframework.stereotype.Service; import org.springframework.validation.annotation.Validated; import java.time.LocalDateTime; +import java.util.Collection; import java.util.Collections; import java.util.List; @@ -96,6 +98,16 @@ public class CrmFollowUpRecordServiceImpl implements CrmFollowUpRecordService { return followUpRecord.getId(); } + @Override + public void createFollowUpRecordBatch(List followUpCreateReqBOs) { + if (CollUtil.isEmpty(followUpCreateReqBOs)) { + return; + } + + List followUpRecords = BeanUtils.toBean(followUpCreateReqBOs, CrmFollowUpRecordDO.class); + crmFollowUpRecordMapper.insertBatch(followUpRecords); + } + @Override public void deleteFollowUpRecord(Long id, Long userId) { // 校验存在 @@ -113,6 +125,12 @@ public class CrmFollowUpRecordServiceImpl implements CrmFollowUpRecordService { crmFollowUpRecordMapper.deleteById(id); } + @Override + public void deleteFollowUpRecordByBiz(Integer bizType, Long bizId) { + // 删除 + crmFollowUpRecordMapper.deleteByBiz(bizType, bizId); + } + private CrmFollowUpRecordDO validateFollowUpRecordExists(Long id) { CrmFollowUpRecordDO followUpRecord = crmFollowUpRecordMapper.selectById(id); if (followUpRecord == null) { @@ -132,4 +150,9 @@ public class CrmFollowUpRecordServiceImpl implements CrmFollowUpRecordService { return crmFollowUpRecordMapper.selectPage(pageReqVO); } + @Override + public List getFollowUpRecordByBiz(Integer bizType, Collection bizIds) { + return crmFollowUpRecordMapper.selectListByBiz(bizType, bizIds); + } + } \ No newline at end of file diff --git a/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/service/followup/bo/CrmFollowUpCreateReqBO.java b/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/service/followup/bo/CrmFollowUpCreateReqBO.java new file mode 100644 index 000000000..dec219e29 --- /dev/null +++ b/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/service/followup/bo/CrmFollowUpCreateReqBO.java @@ -0,0 +1,78 @@ +package cn.iocoder.yudao.module.crm.service.followup.bo; + +import cn.iocoder.yudao.module.crm.dal.dataobject.business.CrmBusinessDO; +import cn.iocoder.yudao.module.crm.dal.dataobject.contact.CrmContactDO; +import cn.iocoder.yudao.module.crm.enums.DictTypeConstants; +import cn.iocoder.yudao.module.crm.enums.common.CrmBizTypeEnum; +import jakarta.validation.constraints.NotEmpty; +import jakarta.validation.constraints.NotNull; +import lombok.Data; + +import java.time.LocalDateTime; +import java.util.List; + +/** + * 跟进信息 Create Req BO + * + * @author HUIHUI + */ +@Data +public class CrmFollowUpCreateReqBO { + + /** + * 数据类型 + * + * 枚举 {@link CrmBizTypeEnum} + */ + @NotNull(message = "数据类型不能为空") + private Integer bizType; + /** + * 数据编号 + * + * 关联 {@link CrmBizTypeEnum} 对应模块 DO 的 id 字段 + */ + @NotNull(message = "数据编号不能为空") + private Long bizId; + + /** + * 跟进类型 + * + * 关联 {@link DictTypeConstants#CRM_FOLLOW_UP_TYPE} 字典 + */ + @NotNull(message = "跟进类型不能为空") + private Integer type; + /** + * 跟进内容 + */ + @NotEmpty(message = "跟进内容不能为空") + private String content; + /** + * 下次联系时间 + */ + @NotNull(message = "下次联系时间不能为空") + private LocalDateTime nextTime; + + /** + * 图片 + */ + private List picUrls; + /** + * 附件 + */ + private List fileUrls; + + /** + * 关联的商机编号数组 + * + * 关联 {@link CrmBusinessDO#getId()} + */ + private List businessIds; + + /** + * 关联的联系人编号数组 + * + * 关联 {@link CrmContactDO#getId()} + */ + private List contactIds; + +} diff --git a/yudao-module-crm/yudao-module-crm-biz/src/test/java/cn/iocoder/yudao/module/crm/service/clue/CrmClueServiceImplTest.java b/yudao-module-crm/yudao-module-crm-biz/src/test/java/cn/iocoder/yudao/module/crm/service/clue/CrmClueServiceImplTest.java index 9738c67b3..d73921f3d 100644 --- a/yudao-module-crm/yudao-module-crm-biz/src/test/java/cn/iocoder/yudao/module/crm/service/clue/CrmClueServiceImplTest.java +++ b/yudao-module-crm/yudao-module-crm-biz/src/test/java/cn/iocoder/yudao/module/crm/service/clue/CrmClueServiceImplTest.java @@ -15,6 +15,7 @@ import java.util.List; import static cn.iocoder.yudao.framework.common.pojo.PageParam.PAGE_SIZE_NONE; import static cn.iocoder.yudao.framework.common.util.object.ObjectUtils.cloneIgnoreId; +import static cn.iocoder.yudao.framework.security.core.util.SecurityFrameworkUtils.getLoginUserId; import static cn.iocoder.yudao.framework.test.core.util.AssertUtils.assertPojoEquals; import static cn.iocoder.yudao.framework.test.core.util.AssertUtils.assertServiceException; import static cn.iocoder.yudao.framework.test.core.util.RandomUtils.randomLongId; @@ -45,7 +46,7 @@ public class CrmClueServiceImplTest extends BaseDbUnitTest { CrmClueSaveReqVO reqVO = randomPojo(CrmClueSaveReqVO.class); // 调用 - Long clueId = clueService.createClue(reqVO); + Long clueId = clueService.createClue(reqVO, getLoginUserId()); // 断言 assertNotNull(clueId); // 校验记录的属性是否正确 From ca9f3c522d9c0d89a9168e5c630d5b583c81057c Mon Sep 17 00:00:00 2001 From: puhui999 Date: Mon, 22 Jan 2024 22:46:52 +0800 Subject: [PATCH 023/119] =?UTF-8?q?CRM-=E7=BA=BF=E7=B4=A2=EF=BC=9A?= =?UTF-8?q?=E5=AE=8C=E5=96=84=E6=93=8D=E4=BD=9C=E6=97=A5=E5=BF=97?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../module/crm/enums/LogRecordConstants.java | 6 +- .../admin/clue/vo/CrmClueSaveReqVO.java | 8 ++ .../crm/service/clue/CrmClueServiceImpl.java | 114 ++++++++++++------ 3 files changed, 90 insertions(+), 38 deletions(-) diff --git a/yudao-module-crm/yudao-module-crm-api/src/main/java/cn/iocoder/yudao/module/crm/enums/LogRecordConstants.java b/yudao-module-crm/yudao-module-crm-api/src/main/java/cn/iocoder/yudao/module/crm/enums/LogRecordConstants.java index 198886e68..a0b4559ef 100644 --- a/yudao-module-crm/yudao-module-crm-api/src/main/java/cn/iocoder/yudao/module/crm/enums/LogRecordConstants.java +++ b/yudao-module-crm/yudao-module-crm-api/src/main/java/cn/iocoder/yudao/module/crm/enums/LogRecordConstants.java @@ -14,9 +14,13 @@ public interface LogRecordConstants { String CRM_LEADS_CREATE_SUB_TYPE = "创建线索"; String CRM_LEADS_CREATE_SUCCESS = "创建了线索{{#clue.name}}"; String CRM_LEADS_UPDATE_SUB_TYPE = "更新线索"; - String CRM_LEADS_UPDATE_SUCCESS = "更新了线索【{{#clueName}}】: {_DIFF{#updateReqVO}}"; + String CRM_LEADS_UPDATE_SUCCESS = "更新了线索【{{#clueName}}】: {_DIFF{#updateReq}}"; String CRM_LEADS_DELETE_SUB_TYPE = "删除线索"; String CRM_LEADS_DELETE_SUCCESS = "删除了线索【{{#clueName}}】"; + String CRM_LEADS_TRANSFER_SUB_TYPE = "转移线索"; + String CRM_LEADS_TRANSFER_SUCCESS = "将线索【{{#clue.name}}】的负责人从【{getAdminUserById{#clue.ownerUserId}}】变更为了【{getAdminUserById{#reqVO.newOwnerUserId}}】"; + String CRM_LEADS_TRANSLATE_SUB_TYPE = "线索转化为客户"; + String CRM_LEADS_TRANSLATE_SUCCESS = "将线索【{{#clue.name}}】转化为客户"; // ======================= CRM_CUSTOMER 客户 ======================= diff --git a/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/controller/admin/clue/vo/CrmClueSaveReqVO.java b/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/controller/admin/clue/vo/CrmClueSaveReqVO.java index adbc650b9..8ceaae2c8 100644 --- a/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/controller/admin/clue/vo/CrmClueSaveReqVO.java +++ b/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/controller/admin/clue/vo/CrmClueSaveReqVO.java @@ -2,6 +2,7 @@ package cn.iocoder.yudao.module.crm.controller.admin.clue.vo; import cn.iocoder.yudao.framework.common.validation.Mobile; import cn.iocoder.yudao.framework.common.validation.Telephone; +import com.mzt.logapi.starter.annotation.DiffLogField; import io.swagger.v3.oas.annotations.media.Schema; import jakarta.validation.constraints.NotEmpty; import lombok.Data; @@ -19,32 +20,39 @@ public class CrmClueSaveReqVO { private Long id; @Schema(description = "线索名称", requiredMode = Schema.RequiredMode.REQUIRED, example = "线索xxx") + @DiffLogField(name = "线索名称") @NotEmpty(message = "线索名称不能为空") private String name; @Schema(description = "下次联系时间", example = "2023-10-18 01:00:00") + @DiffLogField(name = "下次联系时间") @DateTimeFormat(pattern = FORMAT_YEAR_MONTH_DAY_HOUR_MINUTE_SECOND) private LocalDateTime contactNextTime; @Schema(description = "电话", example = "18000000000") + @DiffLogField(name = "电话") @Telephone private String telephone; @Schema(description = "手机号", example = "18000000000") + @DiffLogField(name = "手机号") @Mobile private String mobile; @Schema(description = "地址", example = "北京市海淀区") + @DiffLogField(name = "地址") private String address; @Schema(description = "最后跟进时间") @DateTimeFormat(pattern = FORMAT_YEAR_MONTH_DAY_HOUR_MINUTE_SECOND) + @DiffLogField(name = "最后跟进时间") private LocalDateTime contactLastTime; @Schema(description = "负责人编号", example = "2048") private Long ownerUserId; @Schema(description = "备注", example = "随便") + @DiffLogField(name = "备注") private String remark; } diff --git a/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/service/clue/CrmClueServiceImpl.java b/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/service/clue/CrmClueServiceImpl.java index 898a576a0..da721ef5a 100644 --- a/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/service/clue/CrmClueServiceImpl.java +++ b/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/service/clue/CrmClueServiceImpl.java @@ -5,6 +5,7 @@ import cn.hutool.core.collection.ListUtil; import cn.hutool.core.lang.Assert; import cn.hutool.core.util.ObjUtil; import cn.hutool.core.util.ObjectUtil; +import cn.hutool.extra.spring.SpringUtil; import cn.iocoder.yudao.framework.common.pojo.PageResult; import cn.iocoder.yudao.framework.common.util.object.BeanUtils; import cn.iocoder.yudao.module.crm.controller.admin.clue.vo.CrmCluePageReqVO; @@ -76,7 +77,7 @@ public class CrmClueServiceImpl implements CrmClueService { validateRelationDataExists(createReqVO); // 2. 插入 - CrmClueDO clue = BeanUtils.toBean(createReqVO, CrmClueDO.class); + CrmClueDO clue = BeanUtils.toBean(createReqVO, CrmClueDO.class).setId(null); if (ObjUtil.isNull(createReqVO.getOwnerUserId())) { clue.setOwnerUserId(userId); // 如果没有设置负责人那么默认操作人为负责人 } else { @@ -99,16 +100,16 @@ public class CrmClueServiceImpl implements CrmClueService { @Transactional(rollbackFor = Exception.class) @LogRecord(type = CRM_LEADS_TYPE, subType = CRM_LEADS_UPDATE_SUB_TYPE, bizNo = "{{#updateReqVO.id}}", success = CRM_LEADS_UPDATE_SUCCESS) - @CrmPermission(bizType = CrmBizTypeEnum.CRM_LEADS, bizId = "#updateReqVO.id", level = CrmPermissionLevelEnum.WRITE) - public void updateClue(CrmClueSaveReqVO updateReqVO) { - Assert.notNull(updateReqVO.getId(), "线索编号不能为空"); + @CrmPermission(bizType = CrmBizTypeEnum.CRM_LEADS, bizId = "#updateReq.id", level = CrmPermissionLevelEnum.OWNER) + public void updateClue(CrmClueSaveReqVO updateReq) { + Assert.notNull(updateReq.getId(), "线索编号不能为空"); // 1. 校验线索是否存在 - CrmClueDO oldClue = validateClueExists(updateReqVO.getId()); + CrmClueDO oldClue = validateClueExists(updateReq.getId()); // 2. 校验关联数据 - validateRelationDataExists(updateReqVO); + validateRelationDataExists(updateReq); // 3. 更新 - CrmClueDO updateObj = BeanUtils.toBean(updateReqVO, CrmClueDO.class); + CrmClueDO updateObj = BeanUtils.toBean(updateReq, CrmClueDO.class); clueMapper.updateById(updateObj); // 3. 记录操作日志上下文 @@ -117,8 +118,19 @@ public class CrmClueServiceImpl implements CrmClueService { } @Override - public void updateClueFollowUp(CrmUpdateFollowUpReqBO clueUpdateFollowUpReqBO) { - clueMapper.updateById(BeanUtils.toBean(clueUpdateFollowUpReqBO, CrmClueDO.class).setId(clueUpdateFollowUpReqBO.getBizId())); + @LogRecord(type = CRM_LEADS_TYPE, subType = CRM_LEADS_UPDATE_SUB_TYPE, bizNo = "{{#updateReq.bizId}", + success = CRM_LEADS_UPDATE_SUCCESS) + public void updateClueFollowUp(CrmUpdateFollowUpReqBO updateReq) { + // 校验线索是否存在 + CrmClueDO oldClue = validateClueExists(updateReq.getBizId()); + + // 更新 + clueMapper.updateById(BeanUtils.toBean(updateReq, CrmClueDO.class).setId(updateReq.getBizId())); + + // 3. 记录操作日志上下文 + LogRecordContext.putVariable(DiffParseFunction.OLD_OBJECT, BeanUtils.toBean(oldClue, CrmUpdateFollowUpReqBO.class)); + LogRecordContext.putVariable("clueName", oldClue.getName()); + } @Override @@ -143,48 +155,28 @@ public class CrmClueServiceImpl implements CrmClueService { LogRecordContext.putVariable("clueName", clue.getName()); } - private CrmClueDO validateClueExists(Long id) { - CrmClueDO crmClueDO = clueMapper.selectById(id); - if (crmClueDO == null) { - throw exception(CLUE_NOT_EXISTS); - } - return crmClueDO; - } - - @Override - @CrmPermission(bizType = CrmBizTypeEnum.CRM_LEADS, bizId = "#id", level = CrmPermissionLevelEnum.READ) - public CrmClueDO getClue(Long id) { - return clueMapper.selectById(id); - } - - @Override - public List getClueList(Collection ids, Long userId) { - if (CollUtil.isEmpty(ids)) { - return ListUtil.empty(); - } - return clueMapper.selectBatchIds(ids, userId); - } - - @Override - public PageResult getCluePage(CrmCluePageReqVO pageReqVO, Long userId) { - return clueMapper.selectPage(pageReqVO, userId); - } @Override + @Transactional(rollbackFor = Exception.class) + @LogRecord(type = CRM_LEADS_TYPE, subType = CRM_LEADS_TRANSFER_SUB_TYPE, bizNo = "{{#reqVO.id}}", + success = CRM_LEADS_TRANSFER_SUCCESS) + @CrmPermission(bizType = CrmBizTypeEnum.CRM_LEADS, bizId = "#id", level = CrmPermissionLevelEnum.OWNER) public void transferClue(CrmClueTransferReqVO reqVO, Long userId) { // 1 校验线索是否存在 - validateClueExists(reqVO.getId()); + CrmClueDO clue = validateClueExists(reqVO.getId()); // 2.1 数据权限转移 crmPermissionService.transferPermission(CrmClueConvert.INSTANCE.convert(reqVO, userId).setBizType(CrmBizTypeEnum.CRM_LEADS.getType())); // 2.2 设置新的负责人 clueMapper.updateOwnerUserIdById(reqVO.getId(), reqVO.getNewOwnerUserId()); - // 3. TODO 记录转移日志 + // 3. 记录转移日志 + LogRecordContext.putVariable("clue", clue); } @Override @Transactional(rollbackFor = Exception.class) + @CrmPermission(bizType = CrmBizTypeEnum.CRM_LEADS, bizId = "#id", level = CrmPermissionLevelEnum.OWNER) public void translateCustomer(CrmClueTransformReqVO reqVO, Long userId) { // 1.1 校验线索都存在 Set clueIds = reqVO.getIds(); @@ -214,6 +206,11 @@ public class CrmClueServiceImpl implements CrmClueService { })); // 2.3 复制跟进 updateFollowUpRecords(clueCustomerIdMap); + + // 3. 记录操作日志 + for (CrmClueDO clue : translateClues) { + getSelf().receiveClueLog(clue); + } } private void updateFollowUpRecords(Map clueCustomerIdMap) { @@ -229,6 +226,13 @@ public class CrmClueServiceImpl implements CrmClueService { .setBizId(clueCustomerIdMap.get(followUpRecord.getBizId())))); } + @LogRecord(type = CRM_LEADS_TYPE, subType = CRM_LEADS_TRANSLATE_SUB_TYPE, bizNo = "{{#clue.id}}", + success = CRM_LEADS_TRANSLATE_SUCCESS) + public void receiveClueLog(CrmClueDO clue) { + // 记录操作日志上下文 + LogRecordContext.putVariable("clue", clue); + } + private void validateRelationDataExists(CrmClueSaveReqVO reqVO) { // 校验负责人 if (Objects.nonNull(reqVO.getOwnerUserId()) && @@ -237,4 +241,40 @@ public class CrmClueServiceImpl implements CrmClueService { } } + private CrmClueDO validateClueExists(Long id) { + CrmClueDO crmClueDO = clueMapper.selectById(id); + if (crmClueDO == null) { + throw exception(CLUE_NOT_EXISTS); + } + return crmClueDO; + } + + @Override + @CrmPermission(bizType = CrmBizTypeEnum.CRM_LEADS, bizId = "#id", level = CrmPermissionLevelEnum.READ) + public CrmClueDO getClue(Long id) { + return clueMapper.selectById(id); + } + + @Override + public List getClueList(Collection ids, Long userId) { + if (CollUtil.isEmpty(ids)) { + return ListUtil.empty(); + } + return clueMapper.selectBatchIds(ids, userId); + } + + @Override + public PageResult getCluePage(CrmCluePageReqVO pageReqVO, Long userId) { + return clueMapper.selectPage(pageReqVO, userId); + } + + /** + * 获得自身的代理对象,解决 AOP 生效问题 + * + * @return 自己 + */ + private CrmClueServiceImpl getSelf() { + return SpringUtil.getBean(getClass()); + } + } From 86a177226de67dfa9fda08fb7ea3da74fee78d54 Mon Sep 17 00:00:00 2001 From: puhui999 Date: Mon, 22 Jan 2024 23:23:00 +0800 Subject: [PATCH 024/119] =?UTF-8?q?FIX:=20=E4=BF=AE=E5=A4=8D=E5=90=AF?= =?UTF-8?q?=E5=8A=A8=E6=8A=A5=E9=94=99?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../crm/service/followup/CrmFollowUpRecordServiceImpl.java | 7 +++++++ 1 file changed, 7 insertions(+) diff --git a/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/service/followup/CrmFollowUpRecordServiceImpl.java b/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/service/followup/CrmFollowUpRecordServiceImpl.java index ce76e6a8f..fc573643d 100644 --- a/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/service/followup/CrmFollowUpRecordServiceImpl.java +++ b/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/service/followup/CrmFollowUpRecordServiceImpl.java @@ -21,6 +21,7 @@ import cn.iocoder.yudao.module.crm.service.followup.bo.CrmFollowUpCreateReqBO; import cn.iocoder.yudao.module.crm.service.followup.bo.CrmUpdateFollowUpReqBO; import cn.iocoder.yudao.module.crm.service.permission.CrmPermissionService; import jakarta.annotation.Resource; +import org.springframework.context.annotation.Lazy; import org.springframework.stereotype.Service; import org.springframework.validation.annotation.Validated; @@ -48,16 +49,22 @@ public class CrmFollowUpRecordServiceImpl implements CrmFollowUpRecordService { private CrmFollowUpRecordMapper crmFollowUpRecordMapper; @Resource + @Lazy private CrmPermissionService permissionService; @Resource + @Lazy private CrmBusinessService businessService; @Resource + @Lazy private CrmClueService clueService; @Resource + @Lazy private CrmContactService contactService; @Resource + @Lazy private CrmContractService contractService; @Resource + @Lazy private CrmCustomerService customerService; @Override From d732008ef8ee647d003c91e860aba504ea9c9f25 Mon Sep 17 00:00:00 2001 From: YunaiV Date: Tue, 23 Jan 2024 09:22:02 +0800 Subject: [PATCH 025/119] =?UTF-8?q?=F0=9F=93=96=20CRM=EF=BC=9Acode=20revie?= =?UTF-8?q?w=20=E8=B7=9F=E8=BF=9B=E6=97=A5=E5=BF=97?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../operatelog/CrmOperateLogController.java | 10 +++++++--- .../operatelog/vo/CrmOperateLogPageReqVO.java | 2 +- .../permission/CrmPermissionConvert.java | 1 + .../followup/CrmFollowUpRecordMapper.java | 6 ++++-- .../crm/service/clue/CrmClueServiceImpl.java | 18 +++++++++++------- .../followup/CrmFollowUpRecordServiceImpl.java | 6 +++--- 6 files changed, 27 insertions(+), 16 deletions(-) diff --git a/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/controller/admin/operatelog/CrmOperateLogController.java b/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/controller/admin/operatelog/CrmOperateLogController.java index 0894b43df..2290d7307 100644 --- a/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/controller/admin/operatelog/CrmOperateLogController.java +++ b/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/controller/admin/operatelog/CrmOperateLogController.java @@ -3,6 +3,7 @@ package cn.iocoder.yudao.module.crm.controller.admin.operatelog; import cn.iocoder.yudao.framework.common.pojo.CommonResult; import cn.iocoder.yudao.framework.common.pojo.PageResult; import cn.iocoder.yudao.module.crm.controller.admin.operatelog.vo.CrmOperateLogPageReqVO; +import cn.iocoder.yudao.module.crm.enums.LogRecordConstants; import cn.iocoder.yudao.module.crm.enums.common.CrmBizTypeEnum; import cn.iocoder.yudao.module.system.api.logger.OperateLogApi; import cn.iocoder.yudao.module.system.api.logger.dto.OperateLogV2PageReqDTO; @@ -25,7 +26,7 @@ import static cn.iocoder.yudao.framework.common.pojo.CommonResult.success; import static cn.iocoder.yudao.framework.common.pojo.PageParam.PAGE_SIZE_NONE; import static cn.iocoder.yudao.module.crm.enums.LogRecordConstants.*; -@Tag(name = "管理后台 - 操作日志") +@Tag(name = "管理后台 - CRM 操作日志") @RestController @RequestMapping("/crm/operate-log") @Validated @@ -34,6 +35,9 @@ public class CrmOperateLogController { @Resource private OperateLogApi operateLogApi; + /** + * {@link CrmBizTypeEnum} 与 {@link LogRecordConstants} 的映射关系 + */ private static final Map BIZ_TYPE_MAP = new HashMap<>(); static { @@ -47,6 +51,7 @@ public class CrmOperateLogController { BIZ_TYPE_MAP.put(CrmBizTypeEnum.CRM_RECEIVABLE_PLAN.getType(), CRM_RECEIVABLE_PLAN_TYPE); } + // TODO @puhui999:还是搞个 VO 出来哈 @GetMapping("/page") @Operation(summary = "获得操作日志") @Parameter(name = "id", description = "客户编号", required = true) @@ -54,8 +59,7 @@ public class CrmOperateLogController { public CommonResult> getCustomerOperateLog(@Valid CrmOperateLogPageReqVO pageReqVO) { OperateLogV2PageReqDTO reqDTO = new OperateLogV2PageReqDTO(); reqDTO.setPageSize(PAGE_SIZE_NONE); // 默认不分页,需要分页需注释 - reqDTO.setBizType(BIZ_TYPE_MAP.get(pageReqVO.getBizType())); - reqDTO.setBizId(pageReqVO.getBizId()); + reqDTO.setBizType(BIZ_TYPE_MAP.get(pageReqVO.getBizType())).setBizId(pageReqVO.getBizId()); return success(operateLogApi.getOperateLogPage(reqDTO)); } diff --git a/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/controller/admin/operatelog/vo/CrmOperateLogPageReqVO.java b/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/controller/admin/operatelog/vo/CrmOperateLogPageReqVO.java index 9f54247bf..f49ccb38b 100644 --- a/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/controller/admin/operatelog/vo/CrmOperateLogPageReqVO.java +++ b/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/controller/admin/operatelog/vo/CrmOperateLogPageReqVO.java @@ -9,7 +9,7 @@ import lombok.Data; import lombok.EqualsAndHashCode; import lombok.ToString; -@Schema(description = "管理后台 - 跟进记录分页 Request VO") +@Schema(description = "管理后台 - CRM 操作日志 Request VO") @Data @EqualsAndHashCode(callSuper = true) @ToString(callSuper = true) diff --git a/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/convert/permission/CrmPermissionConvert.java b/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/convert/permission/CrmPermissionConvert.java index 61145f688..d6c36f176 100644 --- a/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/convert/permission/CrmPermissionConvert.java +++ b/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/convert/permission/CrmPermissionConvert.java @@ -29,6 +29,7 @@ public interface CrmPermissionConvert { CrmPermissionConvert INSTANCE = Mappers.getMapper(CrmPermissionConvert.class); + // TODO @puhui999:这个要不也搞到 copy 里 List convert(List permission); default List convert(List permission, List userList, diff --git a/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/dal/mysql/followup/CrmFollowUpRecordMapper.java b/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/dal/mysql/followup/CrmFollowUpRecordMapper.java index 59d800c22..45e2b412e 100644 --- a/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/dal/mysql/followup/CrmFollowUpRecordMapper.java +++ b/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/dal/mysql/followup/CrmFollowUpRecordMapper.java @@ -26,12 +26,14 @@ public interface CrmFollowUpRecordMapper extends BaseMapperX().eq(CrmFollowUpRecordDO::getBizType, bizType) + delete(new LambdaQueryWrapperX() + .eq(CrmFollowUpRecordDO::getBizType, bizType) .eq(CrmFollowUpRecordDO::getBizId, bizId)); } default List selectListByBiz(Integer bizType, Collection bizIds) { - return selectList(new LambdaQueryWrapperX().eq(CrmFollowUpRecordDO::getBizType, bizType) + return selectList(new LambdaQueryWrapperX() + .eq(CrmFollowUpRecordDO::getBizType, bizType) .in(CrmFollowUpRecordDO::getBizId, bizIds)); } diff --git a/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/service/clue/CrmClueServiceImpl.java b/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/service/clue/CrmClueServiceImpl.java index da721ef5a..304b150fe 100644 --- a/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/service/clue/CrmClueServiceImpl.java +++ b/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/service/clue/CrmClueServiceImpl.java @@ -73,17 +73,17 @@ public class CrmClueServiceImpl implements CrmClueService { @LogRecord(type = CRM_LEADS_TYPE, subType = CRM_LEADS_CREATE_SUB_TYPE, bizNo = "{{#clue.id}}", success = CRM_LEADS_CREATE_SUCCESS) public Long createClue(CrmClueSaveReqVO createReqVO, Long userId) { - // 1. 校验关联数据 + // 1.1 校验关联数据 validateRelationDataExists(createReqVO); + // 1.2 校验负责人是否存在 + if (createReqVO.getOwnerUserId() != null) { + adminUserApi.validateUserList(singletonList(createReqVO.getOwnerUserId())); + } else { + createReqVO.setOwnerUserId(userId); // 如果没有设置负责人那么默认操作人为负责人 + } // 2. 插入 CrmClueDO clue = BeanUtils.toBean(createReqVO, CrmClueDO.class).setId(null); - if (ObjUtil.isNull(createReqVO.getOwnerUserId())) { - clue.setOwnerUserId(userId); // 如果没有设置负责人那么默认操作人为负责人 - } else { - // 校验负责人是否存在 - adminUserApi.validateUserList(singletonList(createReqVO.getOwnerUserId())); - } clueMapper.insert(clue); // 3. 创建数据权限 @@ -193,10 +193,13 @@ public class CrmClueServiceImpl implements CrmClueService { } // 2. 遍历线索(未转化的线索),创建对应的客户 + // TODO @puhui999:这里不用过滤了; List translateClues = filterList(clues, clue -> ObjUtil.equal(Boolean.FALSE, clue.getTransformStatus())); List customers = customerService.createCustomerBatch(convertList(translateClues, clue -> BeanUtils.toBean(clue, CrmCustomerCreateReqBO.class)), userId); + // TODO @puhui999:这里不用搞一个 clueCustomerIdMap 出来;可以考虑逐个创建,然后把 customerId 设置回 CrmClueDO;避免 name 匹配,极端会有问题哈; + // TODO 是不是就直接 foreach 处理好了;因为本身量不大,for 处理性能 ok,可阅读性好 Map clueCustomerIdMap = new HashMap<>(translateClues.size()); // 2.1 更新线索 clueMapper.updateBatch(convertList(customers, customer -> { @@ -209,6 +212,7 @@ public class CrmClueServiceImpl implements CrmClueService { // 3. 记录操作日志 for (CrmClueDO clue : translateClues) { + // TODO @puhui999:这里优化下,translate 操作日志 getSelf().receiveClueLog(clue); } } diff --git a/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/service/followup/CrmFollowUpRecordServiceImpl.java b/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/service/followup/CrmFollowUpRecordServiceImpl.java index fc573643d..e63631e4a 100644 --- a/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/service/followup/CrmFollowUpRecordServiceImpl.java +++ b/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/service/followup/CrmFollowUpRecordServiceImpl.java @@ -120,11 +120,12 @@ public class CrmFollowUpRecordServiceImpl implements CrmFollowUpRecordService { // 校验存在 CrmFollowUpRecordDO followUpRecord = validateFollowUpRecordExists(id); // 校验权限 + // TODO @puhui999:是不是封装一个 hasPermission,更简介一点; List permissionList = permissionService.getPermissionListByBiz( followUpRecord.getBizType(), followUpRecord.getBizId()); - boolean condition = anyMatch(permissionList, permission -> + boolean hasPermission = anyMatch(permissionList, permission -> ObjUtil.equal(permission.getUserId(), userId) && ObjUtil.equal(permission.getLevel(), CrmPermissionLevelEnum.OWNER.getLevel())); - if (!condition) { + if (!hasPermission) { throw exception(FOLLOW_UP_RECORD_DELETE_DENIED); } @@ -134,7 +135,6 @@ public class CrmFollowUpRecordServiceImpl implements CrmFollowUpRecordService { @Override public void deleteFollowUpRecordByBiz(Integer bizType, Long bizId) { - // 删除 crmFollowUpRecordMapper.deleteByBiz(bizType, bizId); } From a86bce6f8baf21950c5fbd9b14e2554a2d2974f3 Mon Sep 17 00:00:00 2001 From: YunaiV Date: Tue, 23 Jan 2024 09:35:45 +0800 Subject: [PATCH 026/119] =?UTF-8?q?=F0=9F=93=96=20CRM=EF=BC=9Acode=20revie?= =?UTF-8?q?w=20=E5=95=86=E6=9C=BA=E6=A8=A1=E5=9D=97?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../vo/product/CrmBusinessProductSaveReqVO.java | 3 --- .../crm/dal/dataobject/business/CrmBusinessDO.java | 2 -- .../dataobject/business/CrmBusinessProductDO.java | 2 -- .../dal/mysql/business/CrmBusinessProductMapper.java | 5 +++-- .../crm/dal/mysql/contract/CrmContractMapper.java | 2 +- .../service/business/CrmBusinessProductService.java | 1 + .../business/CrmBusinessProductServiceImpl.java | 6 ++++-- .../crm/service/business/CrmBusinessServiceImpl.java | 12 ++---------- .../service/contact/CrmContactBusinessService.java | 4 +++- .../crm/service/contract/CrmContractService.java | 2 +- .../followup/CrmFollowUpRecordServiceImpl.java | 1 + 11 files changed, 16 insertions(+), 24 deletions(-) diff --git a/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/controller/admin/business/vo/product/CrmBusinessProductSaveReqVO.java b/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/controller/admin/business/vo/product/CrmBusinessProductSaveReqVO.java index 86598bad5..f28f0f350 100644 --- a/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/controller/admin/business/vo/product/CrmBusinessProductSaveReqVO.java +++ b/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/controller/admin/business/vo/product/CrmBusinessProductSaveReqVO.java @@ -14,12 +14,10 @@ public class CrmBusinessProductSaveReqVO { @Schema(description = "主键", requiredMode = Schema.RequiredMode.REQUIRED, example = "32129") private Long id; - // TODO @lzxhqs:这个字段,应该是 Long 类型 @Schema(description = "商机编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "30320") @NotNull(message = "商机编号不能为空") private Long businessId; - // TODO @lzxhqs:这个字段,应该是 Long 类型 @Schema(description = "产品编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "30320") @NotNull(message = "产品编号不能为空") private Long productId; @@ -44,7 +42,6 @@ public class CrmBusinessProductSaveReqVO { @NotNull(message = "小计(折扣后价格)不能为空") private BigDecimal subtotal; - // TODO @lzxhqs:字符串,用 @NotEmpty,因为要考虑 "" 前端搞了这个玩意 @Schema(description = "单位", requiredMode = Schema.RequiredMode.REQUIRED, example = "30320") @NotEmpty(message = "单位不能为空") private String unit; diff --git a/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/dal/dataobject/business/CrmBusinessDO.java b/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/dal/dataobject/business/CrmBusinessDO.java index e8df68d2d..3a543712b 100644 --- a/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/dal/dataobject/business/CrmBusinessDO.java +++ b/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/dal/dataobject/business/CrmBusinessDO.java @@ -95,8 +95,6 @@ public class CrmBusinessDO extends BaseDO { private LocalDateTime contactLastTime; /** * 跟进状态 - * - * TODO @lzxhqs:目前就是 Boolean;是否跟进 */ private Boolean followUpStatus; diff --git a/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/dal/dataobject/business/CrmBusinessProductDO.java b/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/dal/dataobject/business/CrmBusinessProductDO.java index 776d537ef..b1275f4c5 100644 --- a/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/dal/dataobject/business/CrmBusinessProductDO.java +++ b/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/dal/dataobject/business/CrmBusinessProductDO.java @@ -44,7 +44,6 @@ public class CrmBusinessProductDO extends BaseDO { */ private Long productId; - // TODO @lzxhqs:改成 Integer,单位:分。目前整体倾向放大 100 倍哈 /** * 产品单价 */ @@ -55,7 +54,6 @@ public class CrmBusinessProductDO extends BaseDO { */ private BigDecimal salesPrice; - // TODO @lzxhqs:改成 count /** * 数量 */ diff --git a/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/dal/mysql/business/CrmBusinessProductMapper.java b/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/dal/mysql/business/CrmBusinessProductMapper.java index ab84b2958..1730067fe 100644 --- a/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/dal/mysql/business/CrmBusinessProductMapper.java +++ b/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/dal/mysql/business/CrmBusinessProductMapper.java @@ -6,7 +6,7 @@ import cn.iocoder.yudao.module.crm.dal.dataobject.business.CrmBusinessProductDO; import org.apache.ibatis.annotations.Mapper; /** - * 商机产品 Mapper // TODO @lzxhqs:类注释,和作者之间要有一个空行 + * 商机产品 Mapper * * @author lzxhqs */ @@ -17,7 +17,8 @@ public interface CrmBusinessProductMapper extends BaseMapperX { return selectCount(CrmContractDO::getContactId, contactId); } - default Long selectCountByBusinessId(Long businessId) { // TODO @lzxhqs:1)方法和方法之间要有空行;2)selectCountByBusinessId,一个是应该求数量,一个是不要缩写 BizId 可读性; + default Long selectCountByBusinessId(Long businessId) { return selectCount(CrmContractDO::getBusinessId, businessId); } diff --git a/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/service/business/CrmBusinessProductService.java b/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/service/business/CrmBusinessProductService.java index 16dfce371..010be4a92 100644 --- a/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/service/business/CrmBusinessProductService.java +++ b/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/service/business/CrmBusinessProductService.java @@ -4,6 +4,7 @@ import cn.iocoder.yudao.module.crm.dal.dataobject.business.CrmBusinessProductDO; import java.util.List; +// TODO @lzxhqs:方法名上,带下 BusinessProduct;主要考虑不精简的原因,是因为一个逻辑,可能会出现一些超越它自身方法,省略不容易懂; /** * 商机产品关联表 Service 接口 * diff --git a/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/service/business/CrmBusinessProductServiceImpl.java b/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/service/business/CrmBusinessProductServiceImpl.java index ec52a9d9f..afad6ae31 100644 --- a/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/service/business/CrmBusinessProductServiceImpl.java +++ b/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/service/business/CrmBusinessProductServiceImpl.java @@ -17,6 +17,7 @@ import java.util.List; @Service @Validated public class CrmBusinessProductServiceImpl implements CrmBusinessProductService { + @Resource private CrmBusinessProductMapper businessProductMapper; @@ -35,14 +36,15 @@ public class CrmBusinessProductServiceImpl implements CrmBusinessProductService businessProductMapper.updateBatch(list); } + // TODO @lzxhqs:这个方法,可以直接调用 deleteList 方法,然后传递 ids 就好了; @Override public void deleteBatch(List list) { - businessProductMapper.deleteBatchIds(CollectionUtils.convertList(list,CrmBusinessProductDO::getId)); - + businessProductMapper.deleteBatchIds(CollectionUtils.convertList(list, CrmBusinessProductDO::getId)); } @Override public void deleteByBusinessId(Long businessId) { businessProductMapper.deleteByBusinessId(businessId); } + } diff --git a/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/service/business/CrmBusinessServiceImpl.java b/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/service/business/CrmBusinessServiceImpl.java index abe55bc5f..716485007 100644 --- a/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/service/business/CrmBusinessServiceImpl.java +++ b/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/service/business/CrmBusinessServiceImpl.java @@ -55,12 +55,8 @@ public class CrmBusinessServiceImpl implements CrmBusinessService { @Resource private CrmBusinessProductService businessProductService; - // TODO @lzxhqs:不直接调用这个 mapper,要调用对方的 service;每个业务独立收敛 @Resource private CrmContractService contractService; - - // TODO @lzxhqs:不直接调用这个 mapper,要调用对方的 service;每个业务独立收敛 - @Resource private CrmPermissionService permissionService; @Resource @@ -77,8 +73,6 @@ public class CrmBusinessServiceImpl implements CrmBusinessService { .setOwnerUserId(userId); businessMapper.insert(business); // TODO 商机待定:插入商机与产品的关联表;校验商品存在 - // TODO lzxhqs:新增时,是不是不用调用这个方法哈; - // TODO @lzxhqs:用 CollUtils.isNotEmpty; if (CollUtil.isNotEmpty(createReqVO.getProducts())) { createBusinessProducts(createReqVO.getProducts(), business.getId(), false); } @@ -108,7 +102,6 @@ public class CrmBusinessServiceImpl implements CrmBusinessService { contactBusiness.setBusinessId(businessId); contactBusiness.setContactId(contactId); contactBusinessService.insert(contactBusiness); - } // TODO @lzxhqs:这个方法注释格式不对;删除@description,然后把 插入商机产品关联表 作为方法注释; @@ -121,7 +114,6 @@ public class CrmBusinessServiceImpl implements CrmBusinessService { * @author lzxhqs */ private void createBusinessProducts(List products, Long businessId, Boolean updateFlag) { - // TODO @lzxhqs:可以用 CollectionUtils.convertList; List list = CollectionUtils.convertList(products, product -> CrmBusinessProductConvert.INSTANCE.convert(product).setBusinessId(businessId)); if (Boolean.TRUE.equals(updateFlag)) { @@ -141,7 +133,6 @@ public class CrmBusinessServiceImpl implements CrmBusinessService { } else { businessProductService.insertBatch(list); } - } @Override @@ -157,7 +148,7 @@ public class CrmBusinessServiceImpl implements CrmBusinessService { CrmBusinessDO updateObj = BeanUtils.toBean(updateReqVO, CrmBusinessDO.class); businessMapper.updateById(updateObj); // TODO 商机待定:插入商机与产品的关联表;校验商品存在 - // TODO @lzxhqs:更新时,可以调用 CollectionUtils 的 diffList,尽量避免这种先删除再插入;而是新增的插入、变更的更新,没的删除;不然这个表每次更新,会多好多数据; + // TODO @lzxhqs:createBusinessProducts 可以抽成两个方法,一个新增;一个修改,修改需要把 businessProductService.deleteByBusinessId(updateReqVO.getId()); 一起处理进去; if (CollUtil.isNotEmpty(updateReqVO.getProducts())) { createBusinessProducts(updateReqVO.getProducts(), updateReqVO.getId(), true); } else { @@ -202,6 +193,7 @@ public class CrmBusinessServiceImpl implements CrmBusinessService { * @author lzxhqs */ private void validateContractExists(Long businessId) { + // TODO @lzxhqs:保持风格的统一,selectCountByBusinessId 改成 getContractCountByBusinessId;另外,可以不用声明 count,因为就一次性使用,直接把 197 和 198 合并成一行; Long count = contractService.selectCountByBusinessId(businessId); if (count > 0) { throw exception(BUSINESS_CONTRACT_EXISTS); diff --git a/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/service/contact/CrmContactBusinessService.java b/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/service/contact/CrmContactBusinessService.java index 7816040fb..8a9c4192f 100644 --- a/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/service/contact/CrmContactBusinessService.java +++ b/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/service/contact/CrmContactBusinessService.java @@ -43,8 +43,10 @@ public interface CrmContactBusinessService { List getContactBusinessListByContactId(Long contactId); /** - * 新增联系人与商机的 + * 新增联系人与商机的关联 + * * @param contactBusiness 新增联系人与商机的对象 */ void insert(CrmContactBusinessDO contactBusiness); + } \ No newline at end of file diff --git a/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/service/contract/CrmContractService.java b/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/service/contract/CrmContractService.java index ae1347853..6695e4f5d 100644 --- a/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/service/contract/CrmContractService.java +++ b/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/service/contract/CrmContractService.java @@ -111,7 +111,7 @@ public interface CrmContractService { Long getContractCountByCustomerId(Long customerId); /** - * 根据商机ID获取关联客户的合同数量 + * 根据商机ID获取关联客户的合同数量 TODO @lzxhqs:1)方法注释,和参数注释之间要有空行;2)中英文之间有空格,更清晰,例如说 商机 ID * @param businessId 商机ID * @return 数量 */ diff --git a/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/service/followup/CrmFollowUpRecordServiceImpl.java b/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/service/followup/CrmFollowUpRecordServiceImpl.java index e63631e4a..dc2001565 100644 --- a/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/service/followup/CrmFollowUpRecordServiceImpl.java +++ b/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/service/followup/CrmFollowUpRecordServiceImpl.java @@ -94,6 +94,7 @@ public class CrmFollowUpRecordServiceImpl implements CrmFollowUpRecordService { customerService.updateCustomerFollowUp(updateFollowUpReqBO); } + // TODO @puhui999:这两个,不更新 contactLastTime、contactLastContent,只更新 nextTime // 3.1 更新 contactIds 对应的记录 if (CollUtil.isNotEmpty(createReqVO.getContactIds())) { contactService.updateContactFollowUpBatch(convertList(createReqVO.getContactIds(), updateFollowUpReqBO::setBizId)); From 7bb171512a35522ae060e4b0a313a55ca2be8cef Mon Sep 17 00:00:00 2001 From: YunaiV Date: Tue, 23 Jan 2024 12:55:13 +0800 Subject: [PATCH 027/119] =?UTF-8?q?=F0=9F=93=96=20BPM=EF=BC=9Acode=20revie?= =?UTF-8?q?w=20=E6=8A=84=E9=80=81=E9=80=BB=E8=BE=91?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../BpmProcessInstanceCopyController.java | 34 +++---- .../BpmProcessInstanceCopyCreateReqVO.java | 7 +- .../BpmProcessInstanceCopyPageItemRespVO.java | 2 +- .../vo/task/BpmProcessInstanceCopyVO.java | 2 + .../cc/BpmProcessInstanceCopyConvert.java | 23 ++--- .../cc/BpmProcessInstanceCopyDO.java | 22 ++--- .../task/BpmProcessInstanceService.java | 11 +++ .../bpm/service/task/BpmTaskService.java | 16 +--- .../bpm/service/task/BpmTaskServiceImpl.java | 30 +----- .../cc/BpmProcessInstanceCopyService.java | 7 +- .../cc/BpmProcessInstanceCopyServiceImpl.java | 78 ++++++---------- .../yudao/module/bpm/util/FlowableUtils.java | 91 ------------------- .../cc/BpmProcessInstanceCopyServiceTest.java | 17 ---- 13 files changed, 87 insertions(+), 253 deletions(-) delete mode 100644 yudao-module-bpm/yudao-module-bpm-biz/src/main/java/cn/iocoder/yudao/module/bpm/util/FlowableUtils.java delete mode 100644 yudao-module-bpm/yudao-module-bpm-biz/src/test/java/cn/iocoder/yudao/module/bpm/service/cc/BpmProcessInstanceCopyServiceTest.java diff --git a/yudao-module-bpm/yudao-module-bpm-biz/src/main/java/cn/iocoder/yudao/module/bpm/controller/admin/task/BpmProcessInstanceCopyController.java b/yudao-module-bpm/yudao-module-bpm-biz/src/main/java/cn/iocoder/yudao/module/bpm/controller/admin/task/BpmProcessInstanceCopyController.java index 98e04dd0a..fe3511af7 100644 --- a/yudao-module-bpm/yudao-module-bpm-biz/src/main/java/cn/iocoder/yudao/module/bpm/controller/admin/task/BpmProcessInstanceCopyController.java +++ b/yudao-module-bpm/yudao-module-bpm-biz/src/main/java/cn/iocoder/yudao/module/bpm/controller/admin/task/BpmProcessInstanceCopyController.java @@ -17,17 +17,15 @@ import io.swagger.v3.oas.annotations.Operation; import io.swagger.v3.oas.annotations.tags.Tag; import jakarta.annotation.Resource; import jakarta.validation.Valid; -import org.springframework.context.annotation.Lazy; import org.springframework.security.access.prepost.PreAuthorize; import org.springframework.validation.annotation.Validated; import org.springframework.web.bind.annotation.*; -import java.util.HashSet; import java.util.Map; -import java.util.Set; -import java.util.stream.Collectors; +import java.util.stream.Stream; import static cn.iocoder.yudao.framework.common.pojo.CommonResult.success; +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.security.core.util.SecurityFrameworkUtils.getLoginUserId; @@ -41,6 +39,7 @@ public class BpmProcessInstanceCopyController { private BpmProcessInstanceCopyService processInstanceCopyService; @Resource private BpmProcessInstanceService bpmProcessInstanceService; + @Resource private AdminUserApi adminUserApi; @@ -50,8 +49,9 @@ public class BpmProcessInstanceCopyController { @PostMapping("/create") @Operation(summary = "抄送流程") @PreAuthorize("@ss.hasPermission('bpm:process-instance-cc:create')") - public CommonResult createProcessInstanceCC(@Valid @RequestBody BpmProcessInstanceCopyCreateReqVO createReqVO) { - return success(processInstanceCopyService.createProcessInstanceCopy(getLoginUserId(), createReqVO)); + public CommonResult createProcessInstanceCC(@Valid @RequestBody BpmProcessInstanceCopyCreateReqVO createReqVO) { + processInstanceCopyService.createProcessInstanceCopy(getLoginUserId(), createReqVO); + return success(true); } @GetMapping("/my-page") @@ -64,20 +64,14 @@ public class BpmProcessInstanceCopyController { return success(new PageResult<>(pageResult.getTotal())); } - Map taskNameByTaskIds = bpmTaskService.getTaskNameByTaskIds(convertSet(pageResult.getList(), BpmProcessInstanceCopyDO::getTaskId)); - Map processInstanceNameByProcessInstanceIds = bpmTaskService.getProcessInstanceNameByProcessInstanceIds(convertSet(pageResult.getList(), BpmProcessInstanceCopyDO::getProcessInstanceId)); - - Set userIds = new HashSet<>(); - for (BpmProcessInstanceCopyDO doItem : pageResult.getList()) { - userIds.add(doItem.getStartUserId()); - Long userId = Long.valueOf(doItem.getCreator()); - userIds.add(userId); - } - Map userMap = adminUserApi.getUserList(userIds).stream().collect(Collectors.toMap( - AdminUserRespDTO::getId, AdminUserRespDTO::getNickname)); - - // 转换返回 - return success(BpmProcessInstanceCopyConvert.INSTANCE.convertPage(pageResult, taskNameByTaskIds, processInstanceNameByProcessInstanceIds, userMap)); + // 拼接返回 + Map taskNameMap = bpmTaskService.getTaskNameByTaskIds( + convertSet(pageResult.getList(), BpmProcessInstanceCopyDO::getTaskId)); + Map processNameMap = bpmProcessInstanceService.getProcessInstanceNameMap( + convertSet(pageResult.getList(), BpmProcessInstanceCopyDO::getProcessInstanceId)); + Map userMap = adminUserApi.getUserMap(convertListByFlatMap(pageResult.getList(), + copy -> Stream.of(copy.getStartUserId(), Long.parseLong(copy.getCreator())))); + return success(BpmProcessInstanceCopyConvert.INSTANCE.convertPage(pageResult, taskNameMap, processNameMap, userMap)); } } diff --git a/yudao-module-bpm/yudao-module-bpm-biz/src/main/java/cn/iocoder/yudao/module/bpm/controller/admin/task/vo/instance/BpmProcessInstanceCopyCreateReqVO.java b/yudao-module-bpm/yudao-module-bpm-biz/src/main/java/cn/iocoder/yudao/module/bpm/controller/admin/task/vo/instance/BpmProcessInstanceCopyCreateReqVO.java index 5847d2a1c..3a1b1d45c 100644 --- a/yudao-module-bpm/yudao-module-bpm-biz/src/main/java/cn/iocoder/yudao/module/bpm/controller/admin/task/vo/instance/BpmProcessInstanceCopyCreateReqVO.java +++ b/yudao-module-bpm/yudao-module-bpm-biz/src/main/java/cn/iocoder/yudao/module/bpm/controller/admin/task/vo/instance/BpmProcessInstanceCopyCreateReqVO.java @@ -1,18 +1,13 @@ package cn.iocoder.yudao.module.bpm.controller.admin.task.vo.instance; -import cn.iocoder.yudao.module.bpm.controller.admin.candidate.vo.BpmTaskCandidateRuleVO; import io.swagger.v3.oas.annotations.media.Schema; import jakarta.validation.constraints.NotBlank; import jakarta.validation.constraints.NotEmpty; import lombok.Data; -import lombok.EqualsAndHashCode; -import lombok.ToString; @Schema(description = "管理后台 - 流程实例抄送的创建 Request VO") @Data -@EqualsAndHashCode(callSuper = true) -@ToString(callSuper = true) -public class BpmProcessInstanceCopyCreateReqVO extends BpmTaskCandidateRuleVO { +public class BpmProcessInstanceCopyCreateReqVO { @Schema(description = "任务编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "1024") @NotEmpty(message = "任务编号不能为空") diff --git a/yudao-module-bpm/yudao-module-bpm-biz/src/main/java/cn/iocoder/yudao/module/bpm/controller/admin/task/vo/instance/BpmProcessInstanceCopyPageItemRespVO.java b/yudao-module-bpm/yudao-module-bpm-biz/src/main/java/cn/iocoder/yudao/module/bpm/controller/admin/task/vo/instance/BpmProcessInstanceCopyPageItemRespVO.java index ee23e4c0b..4b149a65e 100644 --- a/yudao-module-bpm/yudao-module-bpm-biz/src/main/java/cn/iocoder/yudao/module/bpm/controller/admin/task/vo/instance/BpmProcessInstanceCopyPageItemRespVO.java +++ b/yudao-module-bpm/yudao-module-bpm-biz/src/main/java/cn/iocoder/yudao/module/bpm/controller/admin/task/vo/instance/BpmProcessInstanceCopyPageItemRespVO.java @@ -12,7 +12,7 @@ public class BpmProcessInstanceCopyPageItemRespVO { @Schema(description = "抄送主键") private Long id; - @Schema(description = "发起人Id") + @Schema(description = "发起人 ID") private Long startUserId; @Schema(description = "发起人别名") diff --git a/yudao-module-bpm/yudao-module-bpm-biz/src/main/java/cn/iocoder/yudao/module/bpm/controller/admin/task/vo/task/BpmProcessInstanceCopyVO.java b/yudao-module-bpm/yudao-module-bpm-biz/src/main/java/cn/iocoder/yudao/module/bpm/controller/admin/task/vo/task/BpmProcessInstanceCopyVO.java index 4be3d0bbe..977ec41d8 100644 --- a/yudao-module-bpm/yudao-module-bpm-biz/src/main/java/cn/iocoder/yudao/module/bpm/controller/admin/task/vo/task/BpmProcessInstanceCopyVO.java +++ b/yudao-module-bpm/yudao-module-bpm-biz/src/main/java/cn/iocoder/yudao/module/bpm/controller/admin/task/vo/task/BpmProcessInstanceCopyVO.java @@ -5,6 +5,7 @@ import lombok.Data; import java.time.LocalDateTime; +// TODO @kyle:1)明确是 Req 还是 Resp;2)注释可以合并到 swagger 里;3)example 写一下,这样一些 mock 接口平台可以读取 example /** * 流程抄送视图对象 */ @@ -60,4 +61,5 @@ public class BpmProcessInstanceCopyVO { @Schema(description = "抄送时间") private LocalDateTime createTime; + } diff --git a/yudao-module-bpm/yudao-module-bpm-biz/src/main/java/cn/iocoder/yudao/module/bpm/convert/cc/BpmProcessInstanceCopyConvert.java b/yudao-module-bpm/yudao-module-bpm-biz/src/main/java/cn/iocoder/yudao/module/bpm/convert/cc/BpmProcessInstanceCopyConvert.java index 1b949dff3..f482c71e6 100644 --- a/yudao-module-bpm/yudao-module-bpm-biz/src/main/java/cn/iocoder/yudao/module/bpm/convert/cc/BpmProcessInstanceCopyConvert.java +++ b/yudao-module-bpm/yudao-module-bpm-biz/src/main/java/cn/iocoder/yudao/module/bpm/convert/cc/BpmProcessInstanceCopyConvert.java @@ -4,8 +4,8 @@ import cn.iocoder.yudao.framework.common.pojo.PageResult; import cn.iocoder.yudao.framework.common.util.collection.MapUtils; import cn.iocoder.yudao.framework.common.util.object.BeanUtils; import cn.iocoder.yudao.module.bpm.controller.admin.task.vo.instance.BpmProcessInstanceCopyPageItemRespVO; -import cn.iocoder.yudao.module.bpm.controller.admin.task.vo.task.BpmProcessInstanceCopyVO; import cn.iocoder.yudao.module.bpm.dal.dataobject.cc.BpmProcessInstanceCopyDO; +import cn.iocoder.yudao.module.system.api.user.dto.AdminUserRespDTO; import org.mapstruct.Mapper; import org.mapstruct.factory.Mappers; @@ -22,22 +22,17 @@ public interface BpmProcessInstanceCopyConvert { BpmProcessInstanceCopyConvert INSTANCE = Mappers.getMapper(BpmProcessInstanceCopyConvert.class); - BpmProcessInstanceCopyVO convert(BpmProcessInstanceCopyDO bean); - - List convertList(List list); - - default PageResult convertPage(PageResult page - , Map taskMap - , Map processInstaneMap - , Map userMap - ) { + default PageResult convertPage(PageResult page, + Map taskNameMap, + Map processInstaneNameMap, + Map userMap) { List list = BeanUtils.toBean(page.getList(), BpmProcessInstanceCopyPageItemRespVO.class, copy -> { - MapUtils.findAndThen(userMap, Long.valueOf(copy.getCreator()), copy::setCreatorNickname); - MapUtils.findAndThen(userMap, copy.getStartUserId(), copy::setStartUserNickname); - MapUtils.findAndThen(taskMap, copy.getTaskId(), copy::setTaskName); - MapUtils.findAndThen(processInstaneMap, copy.getProcessInstanceId(), copy::setProcessInstanceName); + MapUtils.findAndThen(userMap, Long.valueOf(copy.getCreator()), user -> user.setNickname(user.getNickname())); + MapUtils.findAndThen(userMap, copy.getStartUserId(), user -> copy.setStartUserNickname(user.getNickname())); + MapUtils.findAndThen(taskNameMap, copy.getTaskId(), copy::setTaskName); + MapUtils.findAndThen(processInstaneNameMap, copy.getProcessInstanceId(), copy::setProcessInstanceName); }); return new PageResult<>(list, page.getTotal()); } diff --git a/yudao-module-bpm/yudao-module-bpm-biz/src/main/java/cn/iocoder/yudao/module/bpm/dal/dataobject/cc/BpmProcessInstanceCopyDO.java b/yudao-module-bpm/yudao-module-bpm-biz/src/main/java/cn/iocoder/yudao/module/bpm/dal/dataobject/cc/BpmProcessInstanceCopyDO.java index c9192e103..7ca65f3db 100644 --- a/yudao-module-bpm/yudao-module-bpm-biz/src/main/java/cn/iocoder/yudao/module/bpm/dal/dataobject/cc/BpmProcessInstanceCopyDO.java +++ b/yudao-module-bpm/yudao-module-bpm-biz/src/main/java/cn/iocoder/yudao/module/bpm/dal/dataobject/cc/BpmProcessInstanceCopyDO.java @@ -28,40 +28,40 @@ public class BpmProcessInstanceCopyDO extends BaseDO { /** * 发起人 Id - *

+ * * 关联 system_users 的 id 属性 */ private Long startUserId; /** * 流程名 - *

- * 冗余字段 + * + * 冗余 ProcessInstance 的 name 字段 */ private String processInstanceName; /** * 流程实例的编号 - *

+ * * 关联 ProcessInstance 的 id 属性 */ private String processInstanceId; /** * 任务主键 - *

- * 关联 task 的 id 属性 + * + * 关联 Task 的 id 属性 */ private String taskId; /** * 任务名称 - *

- * 冗余字段 + * + * 冗余 Task 的 name 属性 */ private String taskName; /** * 用户编号 - *

+ * * 关联 system_users 的 id 属性 */ private Long userId; @@ -73,8 +73,8 @@ public class BpmProcessInstanceCopyDO extends BaseDO { /** * 流程分类 - *

- * 冗余字段 + * + * 冗余 ProcessInstance 的 category 字段 */ private String category; diff --git a/yudao-module-bpm/yudao-module-bpm-biz/src/main/java/cn/iocoder/yudao/module/bpm/service/task/BpmProcessInstanceService.java b/yudao-module-bpm/yudao-module-bpm-biz/src/main/java/cn/iocoder/yudao/module/bpm/service/task/BpmProcessInstanceService.java index a0cc1c71b..01a29c559 100644 --- a/yudao-module-bpm/yudao-module-bpm-biz/src/main/java/cn/iocoder/yudao/module/bpm/service/task/BpmProcessInstanceService.java +++ b/yudao-module-bpm/yudao-module-bpm-biz/src/main/java/cn/iocoder/yudao/module/bpm/service/task/BpmProcessInstanceService.java @@ -46,6 +46,17 @@ public interface BpmProcessInstanceService { return CollectionUtils.convertMap(getProcessInstances(ids), ProcessInstance::getProcessInstanceId); } + /** + * 获得流程实例名字 Map + * + * @param ids 流程实例的编号集合 + * @return 对应的映射关系 + */ + default Map getProcessInstanceNameMap(Set ids) { + return CollectionUtils.convertMap(getProcessInstances(ids), + ProcessInstance::getProcessInstanceId, ProcessInstance::getName); + } + /** * 获得流程实例的分页 * diff --git a/yudao-module-bpm/yudao-module-bpm-biz/src/main/java/cn/iocoder/yudao/module/bpm/service/task/BpmTaskService.java b/yudao-module-bpm/yudao-module-bpm-biz/src/main/java/cn/iocoder/yudao/module/bpm/service/task/BpmTaskService.java index 05925a858..97018451d 100644 --- a/yudao-module-bpm/yudao-module-bpm-biz/src/main/java/cn/iocoder/yudao/module/bpm/service/task/BpmTaskService.java +++ b/yudao-module-bpm/yudao-module-bpm-biz/src/main/java/cn/iocoder/yudao/module/bpm/service/task/BpmTaskService.java @@ -10,7 +10,6 @@ import org.flowable.task.api.Task; import java.util.Collection; import java.util.List; import java.util.Map; -import java.util.Set; /** * 流程任务实例 Service 接口 @@ -186,18 +185,11 @@ public interface BpmTaskService { List getChildrenTaskList(String parentId); /** - * 通过任务id查询任务名 + * 通过任务 ID,查询任务名 Map * - * @param taskIds 任务id - * @return 对应的映射关系 + * @param taskIds 任务 ID + * @return 任务 ID 与名字的 Map */ - Map getTaskNameByTaskIds(Collection taskIds); + Map getTaskNameByTaskIds(Collection taskIds); - /** - * 通过流程实例id获取到流程实例名 - * - * @param processInstaneIds 流程实例Id - * @return 对应的映射关系 - */ - Map getProcessInstanceNameByProcessInstanceIds(Set processInstaneIds); } diff --git a/yudao-module-bpm/yudao-module-bpm-biz/src/main/java/cn/iocoder/yudao/module/bpm/service/task/BpmTaskServiceImpl.java b/yudao-module-bpm/yudao-module-bpm-biz/src/main/java/cn/iocoder/yudao/module/bpm/service/task/BpmTaskServiceImpl.java index eaebccb93..6e9929d37 100644 --- a/yudao-module-bpm/yudao-module-bpm-biz/src/main/java/cn/iocoder/yudao/module/bpm/service/task/BpmTaskServiceImpl.java +++ b/yudao-module-bpm/yudao-module-bpm-biz/src/main/java/cn/iocoder/yudao/module/bpm/service/task/BpmTaskServiceImpl.java @@ -21,7 +21,6 @@ import cn.iocoder.yudao.module.bpm.enums.task.BpmProcessInstanceResultEnum; import cn.iocoder.yudao.module.bpm.enums.task.BpmTaskAddSignTypeEnum; import cn.iocoder.yudao.module.bpm.service.definition.BpmModelService; import cn.iocoder.yudao.module.bpm.service.message.BpmMessageService; -import cn.iocoder.yudao.module.bpm.service.task.cc.BpmProcessInstanceCopyService; import cn.iocoder.yudao.module.system.api.dept.DeptApi; import cn.iocoder.yudao.module.system.api.dept.dto.DeptRespDTO; import cn.iocoder.yudao.module.system.api.user.AdminUserApi; @@ -95,9 +94,6 @@ public class BpmTaskServiceImpl implements BpmTaskService { @Resource private ManagementService managementService; - @Resource - private BpmProcessInstanceCopyService processInstanceCopyService; - @Override public PageResult getTodoTaskPage(Long userId, BpmTaskTodoPageReqVO pageVO) { // 查询待办任务 @@ -972,28 +968,12 @@ public class BpmTaskServiceImpl implements BpmTaskService { } @Override - public Map getTaskNameByTaskIds(Collection taskIds) { - List tasks = taskService.createTaskQuery().taskIds(taskIds).list(); - if (CollUtil.isNotEmpty(tasks)) { - Map taskMap = new HashMap<>(tasks.size()); - for (Task task : tasks) { - taskMap.putIfAbsent(task.getId(), task.getName()); - } - return taskMap; + public Map getTaskNameByTaskIds(Collection taskIds) { + if (CollUtil.isEmpty(taskIds)) { + return Collections.emptyMap(); } - return Collections.emptyMap(); + List tasks = taskService.createTaskQuery().taskIds(taskIds).list(); + return convertMap(tasks, Task::getId, Task::getName); } - @Override - public Map getProcessInstanceNameByProcessInstanceIds(Set processInstanceIds) { - List processInstances = runtimeService.createProcessInstanceQuery().processInstanceIds(processInstanceIds).list(); - if (CollUtil.isNotEmpty(processInstances)) { - Map processInstaneMap = new HashMap<>(processInstances.size()); - for (ProcessInstance processInstance : processInstances) { - processInstaneMap.putIfAbsent(processInstance.getId(), processInstance.getName()); - } - return processInstaneMap; - } - return Collections.emptyMap(); - } } diff --git a/yudao-module-bpm/yudao-module-bpm-biz/src/main/java/cn/iocoder/yudao/module/bpm/service/task/cc/BpmProcessInstanceCopyService.java b/yudao-module-bpm/yudao-module-bpm-biz/src/main/java/cn/iocoder/yudao/module/bpm/service/task/cc/BpmProcessInstanceCopyService.java index 93ab42492..208749a57 100644 --- a/yudao-module-bpm/yudao-module-bpm-biz/src/main/java/cn/iocoder/yudao/module/bpm/service/task/cc/BpmProcessInstanceCopyService.java +++ b/yudao-module-bpm/yudao-module-bpm-biz/src/main/java/cn/iocoder/yudao/module/bpm/service/task/cc/BpmProcessInstanceCopyService.java @@ -3,7 +3,6 @@ package cn.iocoder.yudao.module.bpm.service.task.cc; import cn.iocoder.yudao.framework.common.pojo.PageResult; import cn.iocoder.yudao.module.bpm.controller.admin.task.vo.instance.BpmProcessInstanceCopyCreateReqVO; import cn.iocoder.yudao.module.bpm.controller.admin.task.vo.instance.BpmProcessInstanceCopyMyPageReqVO; -import cn.iocoder.yudao.module.bpm.controller.admin.task.vo.instance.BpmProcessInstanceCopyPageItemRespVO; import cn.iocoder.yudao.module.bpm.dal.dataobject.cc.BpmProcessInstanceCopyDO; import cn.iocoder.yudao.module.bpm.service.candidate.BpmCandidateSourceInfo; @@ -28,14 +27,14 @@ public interface BpmProcessInstanceCopyService { * @param userId 当前登录用户 * @param createReqVO 创建的抄送请求 */ - Void createProcessInstanceCopy(Long userId, BpmProcessInstanceCopyCreateReqVO createReqVO); + void createProcessInstanceCopy(Long userId, BpmProcessInstanceCopyCreateReqVO createReqVO); /** * 抄送的流程的分页 - * @param loginUserId 登录用户id + * @param userId 当前登录用户 * @param pageReqVO 分页请求 * @return 抄送的分页结果 */ - PageResult getMyProcessInstanceCopyPage(Long loginUserId, + PageResult getMyProcessInstanceCopyPage(Long userId, BpmProcessInstanceCopyMyPageReqVO pageReqVO); } diff --git a/yudao-module-bpm/yudao-module-bpm-biz/src/main/java/cn/iocoder/yudao/module/bpm/service/task/cc/BpmProcessInstanceCopyServiceImpl.java b/yudao-module-bpm/yudao-module-bpm-biz/src/main/java/cn/iocoder/yudao/module/bpm/service/task/cc/BpmProcessInstanceCopyServiceImpl.java index aad9815f4..50d042cdc 100644 --- a/yudao-module-bpm/yudao-module-bpm-biz/src/main/java/cn/iocoder/yudao/module/bpm/service/task/cc/BpmProcessInstanceCopyServiceImpl.java +++ b/yudao-module-bpm/yudao-module-bpm-biz/src/main/java/cn/iocoder/yudao/module/bpm/service/task/cc/BpmProcessInstanceCopyServiceImpl.java @@ -7,25 +7,18 @@ import cn.hutool.core.util.StrUtil; import cn.iocoder.yudao.framework.common.pojo.PageResult; import cn.iocoder.yudao.module.bpm.controller.admin.task.vo.instance.BpmProcessInstanceCopyCreateReqVO; import cn.iocoder.yudao.module.bpm.controller.admin.task.vo.instance.BpmProcessInstanceCopyMyPageReqVO; -import cn.iocoder.yudao.module.bpm.controller.admin.task.vo.instance.BpmProcessInstanceCopyPageItemRespVO; -import cn.iocoder.yudao.module.bpm.convert.cc.BpmProcessInstanceCopyConvert; import cn.iocoder.yudao.module.bpm.dal.dataobject.cc.BpmProcessInstanceCopyDO; import cn.iocoder.yudao.module.bpm.dal.mysql.cc.BpmProcessInstanceCopyMapper; import cn.iocoder.yudao.module.bpm.enums.ErrorCodeConstants; -import cn.iocoder.yudao.module.bpm.enums.definition.BpmTaskAssignRuleTypeEnum; import cn.iocoder.yudao.module.bpm.service.candidate.BpmCandidateSourceInfo; import cn.iocoder.yudao.module.bpm.service.candidate.BpmCandidateSourceInfoProcessorChain; import cn.iocoder.yudao.module.bpm.service.task.BpmProcessInstanceService; import cn.iocoder.yudao.module.bpm.service.task.BpmTaskService; import cn.iocoder.yudao.module.bpm.service.task.cc.dto.BpmDelegateExecutionDTO; -import cn.iocoder.yudao.module.bpm.util.FlowableUtils; -import cn.iocoder.yudao.module.system.api.user.AdminUserApi; -import cn.iocoder.yudao.module.system.api.user.dto.AdminUserRespDTO; import jakarta.annotation.Resource; import lombok.extern.slf4j.Slf4j; import org.flowable.engine.RuntimeService; import org.flowable.engine.delegate.DelegateExecution; -import org.flowable.engine.repository.ProcessDefinition; import org.flowable.engine.runtime.ProcessInstance; import org.flowable.task.api.Task; import org.springframework.context.annotation.Lazy; @@ -33,14 +26,14 @@ import org.springframework.stereotype.Service; import org.springframework.validation.annotation.Validated; import java.time.LocalDateTime; -import java.util.*; -import java.util.stream.Collectors; +import java.util.ArrayList; +import java.util.List; +import java.util.Set; import static cn.iocoder.yudao.framework.common.exception.util.ServiceExceptionUtil.exception; -import static cn.iocoder.yudao.framework.common.util.collection.CollectionUtils.convertSet; /** - * Flowable流程抄送实现 + * 流程抄送 Service 实现类 * * @author kyle */ @@ -61,6 +54,9 @@ public class BpmProcessInstanceCopyServiceImpl implements BpmProcessInstanceCopy @Resource @Lazy private BpmTaskService bpmTaskService; + @Resource + @Lazy + private BpmProcessInstanceService bpmProcessInstanceService; @Override public boolean makeCopy(BpmCandidateSourceInfo sourceInfo) { @@ -86,7 +82,7 @@ public class BpmProcessInstanceCopyServiceImpl implements BpmProcessInstanceCopy // 调用 // 设置任务id copyDO.setTaskId(sourceInfo.getTaskId()); - copyDO.setTaskName(FlowableUtils.getTaskNameByTaskId(sourceInfo.getTaskId())); + copyDO.setTaskName(task.getName()); copyDO.setProcessInstanceId(processInstanceId); ProcessInstance processInstance = runtimeService.createProcessInstanceQuery() .processInstanceId(processInstanceId) @@ -95,10 +91,9 @@ public class BpmProcessInstanceCopyServiceImpl implements BpmProcessInstanceCopy log.warn("相关流程实例不存在 {}", sourceInfo.getTaskId()); return false; } - copyDO.setStartUserId(FlowableUtils.getStartUserIdFromProcessInstance(processInstance)); + copyDO.setStartUserId(Long.parseLong(processInstance.getStartUserId())); copyDO.setProcessInstanceName(processInstance.getName()); - ProcessDefinition processDefinition = FlowableUtils.getProcessDefinition(processInstance.getProcessDefinitionId()); - copyDO.setCategory(processDefinition.getCategory()); + copyDO.setCategory(processInstance.getProcessDefinitionCategory()); copyDO.setReason(sourceInfo.getReason()); copyDO.setCreator(sourceInfo.getCreator()); copyDO.setCreateTime(LocalDateTime.now()); @@ -113,53 +108,32 @@ public class BpmProcessInstanceCopyServiceImpl implements BpmProcessInstanceCopy } @Override - public Void createProcessInstanceCopy(Long userId, BpmProcessInstanceCopyCreateReqVO reqVO) { - if (!ObjectUtil.equal(reqVO.getType(), BpmTaskAssignRuleTypeEnum.USER.getType())) { - throw new IllegalArgumentException("业务仅支持USER"); - } + public void createProcessInstanceCopy(Long userId, BpmProcessInstanceCopyCreateReqVO reqVO) { + // 1.1 校验任务存在 Task task = bpmTaskService.getTask(reqVO.getTaskId()); if (ObjectUtil.isNull(task)) { throw exception(ErrorCodeConstants.TASK_NOT_EXISTS); } + // 1.2 校验流程存在 String processInstanceId = task.getProcessInstanceId(); - if (StrUtil.isBlank(processInstanceId)) { + ProcessInstance processInstance = bpmProcessInstanceService.getProcessInstance(processInstanceId); + if (processInstance == null) { + log.warn("[createProcessInstanceCopy][任务({}) 对应的流程不存在]", reqVO.getTaskId()); throw exception(ErrorCodeConstants.PROCESS_INSTANCE_NOT_EXISTS); } - // 在能正常审批的情况下抄送流程 - BpmProcessInstanceCopyDO copyDO = new BpmProcessInstanceCopyDO(); - // 调用 - // 设置任务id - copyDO.setTaskId(reqVO.getTaskId()); - copyDO.setTaskName(FlowableUtils.getTaskNameByTaskId(reqVO.getTaskId())); - copyDO.setProcessInstanceId(processInstanceId); - ProcessInstance processInstance = runtimeService.createProcessInstanceQuery() - .processInstanceId(processInstanceId) - .singleResult(); - if (null == processInstance) { - log.warn("相关流程实例不存在 {}", reqVO.getTaskId()); - throw exception(ErrorCodeConstants.PROCESS_INSTANCE_NOT_EXISTS); - } - copyDO.setStartUserId(FlowableUtils.getStartUserIdFromProcessInstance(processInstance)); - copyDO.setProcessInstanceName(processInstance.getName()); - ProcessDefinition processDefinition = FlowableUtils.getProcessDefinition(processInstance.getProcessDefinitionId()); - copyDO.setCategory(processDefinition.getCategory()); - copyDO.setReason(reqVO.getReason()); - copyDO.setCreator(String.valueOf(userId)); - copyDO.setCreateTime(LocalDateTime.now()); - List copyList = new ArrayList<>(reqVO.getOptions().size()); - for (Long copyUserId : reqVO.getOptions()) { - BpmProcessInstanceCopyDO copy = BeanUtil.copyProperties(copyDO, BpmProcessInstanceCopyDO.class); - copy.setUserId(copyUserId); - copyList.add(copy); - } - processInstanceCopyMapper.insertBatch(copyList); - return null; + + // 2. 创建抄送流程 + BpmProcessInstanceCopyDO copy = new BpmProcessInstanceCopyDO() + .setTaskId(reqVO.getTaskId()).setTaskName(task.getName()) + .setProcessInstanceId(processInstanceId).setStartUserId(Long.valueOf(processInstance.getStartUserId())) + .setProcessInstanceName(processInstance.getName()).setCategory(processInstance.getProcessDefinitionCategory()) + .setReason(reqVO.getReason()); + processInstanceCopyMapper.insert(copy); } @Override - public PageResult getMyProcessInstanceCopyPage(Long loginUserId, BpmProcessInstanceCopyMyPageReqVO pageReqVO) { - // 通过 BpmProcessInstanceExtDO 表,先查询到对应的分页 - return processInstanceCopyMapper.selectPage(loginUserId, pageReqVO); + public PageResult getMyProcessInstanceCopyPage(Long userId, BpmProcessInstanceCopyMyPageReqVO pageReqVO) { + return processInstanceCopyMapper.selectPage(userId, pageReqVO); } } diff --git a/yudao-module-bpm/yudao-module-bpm-biz/src/main/java/cn/iocoder/yudao/module/bpm/util/FlowableUtils.java b/yudao-module-bpm/yudao-module-bpm-biz/src/main/java/cn/iocoder/yudao/module/bpm/util/FlowableUtils.java deleted file mode 100644 index c877c2a4a..000000000 --- a/yudao-module-bpm/yudao-module-bpm-biz/src/main/java/cn/iocoder/yudao/module/bpm/util/FlowableUtils.java +++ /dev/null @@ -1,91 +0,0 @@ -package cn.iocoder.yudao.module.bpm.util; - - -import cn.hutool.extra.spring.SpringUtil; -import cn.iocoder.yudao.framework.common.util.number.NumberUtils; -import org.flowable.bpmn.model.BpmnModel; -import org.flowable.bpmn.model.ExtensionElement; -import org.flowable.bpmn.model.FlowElement; -import org.flowable.bpmn.model.FlowNode; -import org.flowable.engine.RepositoryService; -import org.flowable.engine.RuntimeService; -import org.flowable.engine.TaskService; -import org.flowable.engine.repository.ProcessDefinition; -import org.flowable.engine.runtime.ProcessInstance; -import org.flowable.task.api.Task; - -import java.util.List; -import java.util.Map; - -/** - * 流程引擎工具类封装 - * - * @author: linjinp - * @create: 2019-12-24 13:51 - **/ -public class FlowableUtils { - - /** - * 获取流程名称 - * - * @param processDefinitionId - * @return - */ - public static String getProcessDefinitionName(String processDefinitionId) { - RepositoryService repositoryService = SpringUtil.getBean(RepositoryService.class); - ProcessDefinition processDefinition = repositoryService.getProcessDefinition(processDefinitionId); - return processDefinition.getName(); - } - - public static ProcessDefinition getProcessDefinition(String processDefinitionId) { - RepositoryService repositoryService = SpringUtil.getBean(RepositoryService.class); - return repositoryService.getProcessDefinition(processDefinitionId); - } - - /** - * 获取节点数据 - * - * @param processInstanceId - * @param nodeId - * @return - */ - public static FlowNode getFlowNode(String processInstanceId, String nodeId) { - - RuntimeService runtimeService = SpringUtil.getBean(RuntimeService.class); - RepositoryService repositoryService = SpringUtil.getBean(RepositoryService.class); - - String definitionld = runtimeService.createProcessInstanceQuery().processInstanceId(processInstanceId).singleResult().getProcessDefinitionId(); // 获取bpm(模型)对象 - BpmnModel bpmnModel = repositoryService.getBpmnModel(definitionld); - // 传节点定义key获取当前节点 - FlowNode flowNode = (FlowNode) bpmnModel.getFlowElement(nodeId); - return flowNode; - } - - public static ExtensionElement generateFlowNodeIdExtension(String nodeId) { - ExtensionElement extensionElement = new ExtensionElement(); - extensionElement.setElementText(nodeId); - extensionElement.setName("nodeId"); - extensionElement.setNamespacePrefix("flowable"); - extensionElement.setNamespace("nodeId"); - return extensionElement; - } - - public static String getNodeIdFromExtension(FlowElement flowElement) { - Map> extensionElements = flowElement.getExtensionElements(); - return extensionElements.get("nodeId").get(0).getElementText(); - } - - public static Long getStartUserIdFromProcessInstance(ProcessInstance instance) { - if (null == instance) { - return null; - } - return NumberUtils.parseLong(instance.getStartUserId()); - } - - public static String getTaskNameByTaskId(String taskId) { - TaskService taskService = SpringUtil.getBean(TaskService.class); - Task task = taskService.createTaskQuery().taskId(taskId).singleResult(); - return task.getName(); - } - -} diff --git a/yudao-module-bpm/yudao-module-bpm-biz/src/test/java/cn/iocoder/yudao/module/bpm/service/cc/BpmProcessInstanceCopyServiceTest.java b/yudao-module-bpm/yudao-module-bpm-biz/src/test/java/cn/iocoder/yudao/module/bpm/service/cc/BpmProcessInstanceCopyServiceTest.java deleted file mode 100644 index 8434399e0..000000000 --- a/yudao-module-bpm/yudao-module-bpm-biz/src/test/java/cn/iocoder/yudao/module/bpm/service/cc/BpmProcessInstanceCopyServiceTest.java +++ /dev/null @@ -1,17 +0,0 @@ -package cn.iocoder.yudao.module.bpm.service.cc; - -import cn.iocoder.yudao.framework.test.core.ut.BaseDbUnitTest; -import cn.iocoder.yudao.module.bpm.service.task.cc.BpmProcessInstanceCopyServiceImpl; -import jakarta.annotation.Resource; -import org.junit.jupiter.api.Test; -import org.springframework.context.annotation.Import; - -@Import({BpmProcessInstanceCopyServiceImpl.class}) -class BpmProcessInstanceCopyServiceTest extends BaseDbUnitTest { - @Resource - private BpmProcessInstanceCopyServiceImpl service; - - @Test - void queryById() { - } -} \ No newline at end of file From 6850c7c71d236f73a99658a0af04b98e9bdb2e6b Mon Sep 17 00:00:00 2001 From: puhui999 Date: Tue, 23 Jan 2024 22:31:51 +0800 Subject: [PATCH 028/119] =?UTF-8?q?CRM:=20=E5=AE=8C=E5=96=84=E8=B7=9F?= =?UTF-8?q?=E8=BF=9B=E6=97=A5=E5=BF=97=20TODO?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../operatelog/CrmOperateLogController.java | 12 ++- .../operatelog/vo/CrmOperateLogV2RespVO.java | 89 +++++++++++++++++++ .../permission/CrmPermissionConvert.java | 8 +- .../dataobject/customer/CrmCustomerDO.java | 5 ++ .../core/util/CrmPermissionUtils.java | 28 ++++++ .../crm/service/clue/CrmClueServiceImpl.java | 37 +++----- .../CrmContactBusinessServiceImpl.java | 10 ++- .../service/customer/CrmCustomerService.java | 8 +- .../customer/CrmCustomerServiceImpl.java | 34 ++++--- .../CrmFollowUpRecordServiceImpl.java | 20 ++--- .../followup/bo/CrmUpdateFollowUpReqBO.java | 2 - 11 files changed, 178 insertions(+), 75 deletions(-) create mode 100644 yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/controller/admin/operatelog/vo/CrmOperateLogV2RespVO.java diff --git a/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/controller/admin/operatelog/CrmOperateLogController.java b/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/controller/admin/operatelog/CrmOperateLogController.java index 2290d7307..982ad3c0b 100644 --- a/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/controller/admin/operatelog/CrmOperateLogController.java +++ b/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/controller/admin/operatelog/CrmOperateLogController.java @@ -2,14 +2,14 @@ package cn.iocoder.yudao.module.crm.controller.admin.operatelog; import cn.iocoder.yudao.framework.common.pojo.CommonResult; import cn.iocoder.yudao.framework.common.pojo.PageResult; +import cn.iocoder.yudao.framework.common.util.object.BeanUtils; import cn.iocoder.yudao.module.crm.controller.admin.operatelog.vo.CrmOperateLogPageReqVO; +import cn.iocoder.yudao.module.crm.controller.admin.operatelog.vo.CrmOperateLogV2RespVO; import cn.iocoder.yudao.module.crm.enums.LogRecordConstants; import cn.iocoder.yudao.module.crm.enums.common.CrmBizTypeEnum; import cn.iocoder.yudao.module.system.api.logger.OperateLogApi; import cn.iocoder.yudao.module.system.api.logger.dto.OperateLogV2PageReqDTO; -import cn.iocoder.yudao.module.system.api.logger.dto.OperateLogV2RespDTO; import io.swagger.v3.oas.annotations.Operation; -import io.swagger.v3.oas.annotations.Parameter; import io.swagger.v3.oas.annotations.tags.Tag; import jakarta.annotation.Resource; import jakarta.validation.Valid; @@ -51,16 +51,14 @@ public class CrmOperateLogController { BIZ_TYPE_MAP.put(CrmBizTypeEnum.CRM_RECEIVABLE_PLAN.getType(), CRM_RECEIVABLE_PLAN_TYPE); } - // TODO @puhui999:还是搞个 VO 出来哈 @GetMapping("/page") @Operation(summary = "获得操作日志") - @Parameter(name = "id", description = "客户编号", required = true) - @PreAuthorize("@ss.hasPermission('crm:customer:query')") - public CommonResult> getCustomerOperateLog(@Valid CrmOperateLogPageReqVO pageReqVO) { + @PreAuthorize("@ss.hasPermission('crm:operate-log:query')") + public CommonResult> getCustomerOperateLog(@Valid CrmOperateLogPageReqVO pageReqVO) { OperateLogV2PageReqDTO reqDTO = new OperateLogV2PageReqDTO(); reqDTO.setPageSize(PAGE_SIZE_NONE); // 默认不分页,需要分页需注释 reqDTO.setBizType(BIZ_TYPE_MAP.get(pageReqVO.getBizType())).setBizId(pageReqVO.getBizId()); - return success(operateLogApi.getOperateLogPage(reqDTO)); + return success(BeanUtils.toBean(operateLogApi.getOperateLogPage(reqDTO), CrmOperateLogV2RespVO.class)); } } diff --git a/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/controller/admin/operatelog/vo/CrmOperateLogV2RespVO.java b/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/controller/admin/operatelog/vo/CrmOperateLogV2RespVO.java new file mode 100644 index 000000000..298b5a51d --- /dev/null +++ b/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/controller/admin/operatelog/vo/CrmOperateLogV2RespVO.java @@ -0,0 +1,89 @@ +package cn.iocoder.yudao.module.crm.controller.admin.operatelog.vo; + +import com.alibaba.excel.annotation.ExcelIgnoreUnannotated; +import io.swagger.v3.oas.annotations.media.Schema; +import lombok.Data; + +import java.time.LocalDateTime; + +@Schema(description = "管理后台 - CRM 跟进 Response VO") +@Data +@ExcelIgnoreUnannotated +public class CrmOperateLogV2RespVO { + + @Schema(description = "编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "13563") + private Long id; + /** + * 链路追踪编号 + */ + @Schema(description = "编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "13563") + private String traceId; + /** + * 用户编号 + */ + @Schema(description = "编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "1024") + private Long userId; + /** + * 用户名称 + */ + @Schema(description = "编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "芋艿") + private String userName; + /** + * 用户类型 + */ + @Schema(description = "编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "1") + private Integer userType; + /** + * 操作模块类型 + */ + @Schema(description = "编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "13563") + private String type; + /** + * 操作名 + */ + @Schema(description = "编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "修改客户") + private String subType; + /** + * 操作模块业务编号 + */ + @Schema(description = "编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "13563") + private Long bizId; + /** + * 操作内容 + */ + @Schema(description = "编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "将什么从什么改为了什么") + private String action; + /** + * 拓展字段 + */ + @Schema(description = "编号", example = "{orderId: 1}") + private String extra; + + /** + * 请求方法名 + */ + @Schema(description = "编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "13563") + private String requestMethod; + /** + * 请求地址 + */ + @Schema(description = "编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "13563") + private String requestUrl; + /** + * 用户 IP + */ + @Schema(description = "编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "13563") + private String userIp; + /** + * 浏览器 UA + */ + @Schema(description = "编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "13563") + private String userAgent; + + /** + * 创建时间 + */ + @Schema(description = "编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "2024-01-01") + private LocalDateTime createTime; + +} diff --git a/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/convert/permission/CrmPermissionConvert.java b/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/convert/permission/CrmPermissionConvert.java index d6c36f176..f51544cae 100644 --- a/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/convert/permission/CrmPermissionConvert.java +++ b/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/convert/permission/CrmPermissionConvert.java @@ -3,6 +3,7 @@ package cn.iocoder.yudao.module.crm.convert.permission; import cn.hutool.core.collection.CollUtil; import cn.iocoder.yudao.framework.common.util.collection.CollectionUtils; import cn.iocoder.yudao.framework.common.util.collection.MapUtils; +import cn.iocoder.yudao.framework.common.util.object.BeanUtils; import cn.iocoder.yudao.module.crm.controller.admin.permission.vo.CrmPermissionRespVO; import cn.iocoder.yudao.module.crm.controller.admin.permission.vo.CrmPermissionUpdateReqVO; import cn.iocoder.yudao.module.crm.dal.dataobject.permission.CrmPermissionDO; @@ -29,13 +30,10 @@ public interface CrmPermissionConvert { CrmPermissionConvert INSTANCE = Mappers.getMapper(CrmPermissionConvert.class); - // TODO @puhui999:这个要不也搞到 copy 里 - List convert(List permission); - - default List convert(List permission, List userList, + default List convert(List permissions, List userList, Map deptMap, Map postMap) { Map userMap = CollectionUtils.convertMap(userList, AdminUserRespDTO::getId); - return CollectionUtils.convertList(convert(permission), item -> { + return CollectionUtils.convertList(BeanUtils.toBean(permissions, CrmPermissionRespVO.class), item -> { findAndThen(userMap, item.getUserId(), user -> { item.setNickname(user.getNickname()); findAndThen(deptMap, user.getDeptId(), deptRespDTO -> item.setDeptName(deptRespDTO.getName())); diff --git a/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/dal/dataobject/customer/CrmCustomerDO.java b/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/dal/dataobject/customer/CrmCustomerDO.java index 96e4bf520..2bd614f57 100644 --- a/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/dal/dataobject/customer/CrmCustomerDO.java +++ b/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/dal/dataobject/customer/CrmCustomerDO.java @@ -114,10 +114,15 @@ public class CrmCustomerDO extends BaseDO { */ private String detailAddress; + /** + * 最后接收时间 + */ + private LocalDateTime receiveTime; /** * 最后跟进时间 */ private LocalDateTime contactLastTime; + /** * 最后跟进内容 */ diff --git a/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/framework/permission/core/util/CrmPermissionUtils.java b/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/framework/permission/core/util/CrmPermissionUtils.java index 43bb729b6..8f9c19410 100644 --- a/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/framework/permission/core/util/CrmPermissionUtils.java +++ b/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/framework/permission/core/util/CrmPermissionUtils.java @@ -1,9 +1,17 @@ package cn.iocoder.yudao.module.crm.framework.permission.core.util; +import cn.hutool.core.util.ObjUtil; import cn.hutool.extra.spring.SpringUtil; +import cn.iocoder.yudao.module.crm.dal.dataobject.permission.CrmPermissionDO; +import cn.iocoder.yudao.module.crm.enums.common.CrmBizTypeEnum; +import cn.iocoder.yudao.module.crm.enums.permission.CrmPermissionLevelEnum; import cn.iocoder.yudao.module.crm.enums.permission.CrmPermissionRoleCodeEnum; +import cn.iocoder.yudao.module.crm.service.permission.CrmPermissionService; import cn.iocoder.yudao.module.system.api.permission.PermissionApi; +import java.util.List; + +import static cn.iocoder.yudao.framework.common.util.collection.CollectionUtils.anyMatch; import static cn.iocoder.yudao.framework.security.core.util.SecurityFrameworkUtils.getLoginUserId; /** @@ -22,6 +30,21 @@ public class CrmPermissionUtils { return SingletonManager.getPermissionApi().hasAnyRoles(getLoginUserId(), CrmPermissionRoleCodeEnum.CRM_ADMIN.getCode()); } + /** + * 校验权限 + * + * @param bizType 数据类型,关联 {@link CrmBizTypeEnum} + * @param bizId 数据编号,关联 {@link CrmBizTypeEnum} 对应模块 DO#getId() + * @param userId 用户编号 + * @param levelEnum 权限级别 + * @return boolean + */ + public static boolean hasPermission(Integer bizType, Long bizId, Long userId, CrmPermissionLevelEnum levelEnum) { + List permissionList = SingletonManager.getCrmPermissionService().getPermissionListByBiz(bizType, bizId); + return anyMatch(permissionList, permission -> + ObjUtil.equal(permission.getUserId(), userId) && ObjUtil.equal(permission.getLevel(), levelEnum.getLevel())); + } + /** * 静态内部类实现单例获取 * @@ -30,11 +53,16 @@ public class CrmPermissionUtils { private static class SingletonManager { private static final PermissionApi PERMISSION_API = SpringUtil.getBean(PermissionApi.class); + private static final CrmPermissionService CRM_PERMISSION_SERVICE = SpringUtil.getBean(CrmPermissionService.class); public static PermissionApi getPermissionApi() { return PERMISSION_API; } + public static CrmPermissionService getCrmPermissionService() { + return CRM_PERMISSION_SERVICE; + } + } } diff --git a/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/service/clue/CrmClueServiceImpl.java b/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/service/clue/CrmClueServiceImpl.java index 304b150fe..2329c4dce 100644 --- a/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/service/clue/CrmClueServiceImpl.java +++ b/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/service/clue/CrmClueServiceImpl.java @@ -3,7 +3,6 @@ package cn.iocoder.yudao.module.crm.service.clue; import cn.hutool.core.collection.CollUtil; import cn.hutool.core.collection.ListUtil; import cn.hutool.core.lang.Assert; -import cn.hutool.core.util.ObjUtil; import cn.hutool.core.util.ObjectUtil; import cn.hutool.extra.spring.SpringUtil; import cn.iocoder.yudao.framework.common.pojo.PageResult; @@ -15,7 +14,6 @@ import cn.iocoder.yudao.module.crm.controller.admin.clue.vo.CrmClueTransformReqV import cn.iocoder.yudao.module.crm.controller.admin.customer.vo.CrmCustomerSaveReqVO; import cn.iocoder.yudao.module.crm.convert.clue.CrmClueConvert; import cn.iocoder.yudao.module.crm.dal.dataobject.clue.CrmClueDO; -import cn.iocoder.yudao.module.crm.dal.dataobject.customer.CrmCustomerDO; import cn.iocoder.yudao.module.crm.dal.dataobject.followup.CrmFollowUpRecordDO; import cn.iocoder.yudao.module.crm.dal.mysql.clue.CrmClueMapper; import cn.iocoder.yudao.module.crm.enums.common.CrmBizTypeEnum; @@ -193,46 +191,39 @@ public class CrmClueServiceImpl implements CrmClueService { } // 2. 遍历线索(未转化的线索),创建对应的客户 - // TODO @puhui999:这里不用过滤了; - List translateClues = filterList(clues, clue -> ObjUtil.equal(Boolean.FALSE, clue.getTransformStatus())); - List customers = customerService.createCustomerBatch(convertList(translateClues, clue -> - BeanUtils.toBean(clue, CrmCustomerCreateReqBO.class)), userId); + clues.forEach(clue -> { + Long customerId = customerService.createCustomer(BeanUtils.toBean(clue, CrmCustomerCreateReqBO.class), userId); + clue.setCustomerId(customerId); + }); - // TODO @puhui999:这里不用搞一个 clueCustomerIdMap 出来;可以考虑逐个创建,然后把 customerId 设置回 CrmClueDO;避免 name 匹配,极端会有问题哈; - // TODO 是不是就直接 foreach 处理好了;因为本身量不大,for 处理性能 ok,可阅读性好 - Map clueCustomerIdMap = new HashMap<>(translateClues.size()); // 2.1 更新线索 - clueMapper.updateBatch(convertList(customers, customer -> { - CrmClueDO firstClue = findFirst(translateClues, clue -> ObjUtil.equal(clue.getName(), customer.getName())); - clueCustomerIdMap.put(firstClue.getId(), customer.getId()); - return new CrmClueDO().setId(firstClue.getId()).setTransformStatus(Boolean.TRUE).setCustomerId(customer.getId()); - })); + clueMapper.updateBatch(convertList(clues, clue -> new CrmClueDO().setId(clue.getId()).setTransformStatus(Boolean.TRUE) + .setCustomerId(clue.getCustomerId()))); // 2.3 复制跟进 - updateFollowUpRecords(clueCustomerIdMap); - + updateFollowUpRecords(clues); // 3. 记录操作日志 - for (CrmClueDO clue : translateClues) { - // TODO @puhui999:这里优化下,translate 操作日志 - getSelf().receiveClueLog(clue); + for (CrmClueDO clue : clues) { + getSelf().translateCustomerLog(clue); } } - private void updateFollowUpRecords(Map clueCustomerIdMap) { + private void updateFollowUpRecords(List clues) { List followUpRecords = followUpRecordService.getFollowUpRecordByBiz( - CrmBizTypeEnum.CRM_LEADS.getType(), clueCustomerIdMap.keySet()); + CrmBizTypeEnum.CRM_LEADS.getType(), convertSet(clues, CrmClueDO::getId)); if (CollUtil.isEmpty(followUpRecords)) { return; } + Map clueMap = convertMap(clues, CrmClueDO::getId); // 创建跟进 followUpRecordService.createFollowUpRecordBatch(convertList(followUpRecords, followUpRecord -> BeanUtils.toBean(followUpRecord, CrmFollowUpCreateReqBO.class).setBizType(CrmBizTypeEnum.CRM_CUSTOMER.getType()) - .setBizId(clueCustomerIdMap.get(followUpRecord.getBizId())))); + .setBizId(clueMap.get(followUpRecord.getBizId()).getCustomerId()))); } @LogRecord(type = CRM_LEADS_TYPE, subType = CRM_LEADS_TRANSLATE_SUB_TYPE, bizNo = "{{#clue.id}}", success = CRM_LEADS_TRANSLATE_SUCCESS) - public void receiveClueLog(CrmClueDO clue) { + public void translateCustomerLog(CrmClueDO clue) { // 记录操作日志上下文 LogRecordContext.putVariable("clue", clue); } diff --git a/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/service/contact/CrmContactBusinessServiceImpl.java b/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/service/contact/CrmContactBusinessServiceImpl.java index 10b6a2ec3..7b0711334 100644 --- a/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/service/contact/CrmContactBusinessServiceImpl.java +++ b/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/service/contact/CrmContactBusinessServiceImpl.java @@ -6,6 +6,9 @@ import cn.iocoder.yudao.module.crm.dal.dataobject.business.CrmBusinessDO; import cn.iocoder.yudao.module.crm.dal.dataobject.contact.CrmContactBusinessDO; import cn.iocoder.yudao.module.crm.dal.dataobject.contact.CrmContactDO; import cn.iocoder.yudao.module.crm.dal.mysql.contactbusinesslink.CrmContactBusinessMapper; +import cn.iocoder.yudao.module.crm.enums.common.CrmBizTypeEnum; +import cn.iocoder.yudao.module.crm.enums.permission.CrmPermissionLevelEnum; +import cn.iocoder.yudao.module.crm.framework.permission.core.annotations.CrmPermission; import cn.iocoder.yudao.module.crm.service.business.CrmBusinessService; import jakarta.annotation.Resource; import org.springframework.context.annotation.Lazy; @@ -19,7 +22,6 @@ import static cn.iocoder.yudao.framework.common.exception.util.ServiceExceptionU import static cn.iocoder.yudao.module.crm.enums.ErrorCodeConstants.BUSINESS_NOT_EXISTS; import static cn.iocoder.yudao.module.crm.enums.ErrorCodeConstants.CONTACT_NOT_EXISTS; -// TODO @puhui999:数据权限的校验;每个操作; /** * 联系人与商机的关联 Service 实现类 * @@ -40,6 +42,7 @@ public class CrmContactBusinessServiceImpl implements CrmContactBusinessService private CrmContactService contactService; @Override + @CrmPermission(bizType = CrmBizTypeEnum.CRM_CONTACT, bizId = "#createReqVO.contactId", level = CrmPermissionLevelEnum.WRITE) public void createContactBusinessList(CrmContactBusinessReqVO createReqVO) { CrmContactDO contact = contactService.getContact(createReqVO.getContactId()); if (contact == null) { @@ -65,6 +68,7 @@ public class CrmContactBusinessServiceImpl implements CrmContactBusinessService } @Override + @CrmPermission(bizType = CrmBizTypeEnum.CRM_CONTACT, bizId = "#deleteReqVO.contactId", level = CrmPermissionLevelEnum.WRITE) public void deleteContactBusinessList(CrmContactBusinessReqVO deleteReqVO) { CrmContactDO contact = contactService.getContact(deleteReqVO.getContactId()); if (contact == null) { @@ -76,11 +80,13 @@ public class CrmContactBusinessServiceImpl implements CrmContactBusinessService } @Override + @CrmPermission(bizType = CrmBizTypeEnum.CRM_CONTACT, bizId = "#contactId", level = CrmPermissionLevelEnum.WRITE) public void deleteContactBusinessByContactId(Long contactId) { - contactBusinessMapper.delete(CrmContactBusinessDO::getContactId,contactId); + contactBusinessMapper.delete(CrmContactBusinessDO::getContactId, contactId); } @Override + @CrmPermission(bizType = CrmBizTypeEnum.CRM_CONTACT, bizId = "#contactId", level = CrmPermissionLevelEnum.READ) public List getContactBusinessListByContactId(Long contactId) { return contactBusinessMapper.selectListByContactId(contactId); } diff --git a/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/service/customer/CrmCustomerService.java b/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/service/customer/CrmCustomerService.java index 38d5f082b..d813b2b4d 100644 --- a/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/service/customer/CrmCustomerService.java +++ b/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/service/customer/CrmCustomerService.java @@ -100,13 +100,13 @@ public interface CrmCustomerService { void updateCustomerFollowUp(CrmUpdateFollowUpReqBO customerUpdateFollowUpReqBO); /** - * 批量创建客户 + * 创建客户 * - * @param customerCreateReqBOs 请求 - * @param userId 用户编号 + * @param customerCreateReq 请求信息 + * @param userId 用户编号 * @return 客户列表 */ - List createCustomerBatch(List customerCreateReqBOs, Long userId); + Long createCustomer(CrmCustomerCreateReqBO customerCreateReq, Long userId); // ==================== 公海相关操作 ==================== diff --git a/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/service/customer/CrmCustomerServiceImpl.java b/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/service/customer/CrmCustomerServiceImpl.java index 45893fa87..2958dbdf3 100644 --- a/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/service/customer/CrmCustomerServiceImpl.java +++ b/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/service/customer/CrmCustomerServiceImpl.java @@ -43,12 +43,10 @@ import java.util.Collections; import java.util.List; import static cn.iocoder.yudao.framework.common.exception.util.ServiceExceptionUtil.exception; -import static cn.iocoder.yudao.framework.common.util.collection.CollectionUtils.convertList; import static cn.iocoder.yudao.module.crm.enums.ErrorCodeConstants.*; import static cn.iocoder.yudao.module.crm.enums.LogRecordConstants.*; import static cn.iocoder.yudao.module.crm.enums.customer.CrmCustomerLimitConfigTypeEnum.CUSTOMER_LOCK_LIMIT; import static cn.iocoder.yudao.module.crm.enums.customer.CrmCustomerLimitConfigTypeEnum.CUSTOMER_OWNER_LIMIT; -import static java.util.Collections.emptyList; import static java.util.Collections.singletonList; /** @@ -91,9 +89,7 @@ public class CrmCustomerServiceImpl implements CrmCustomerService { // 2. 插入客户 CrmCustomerDO customer = BeanUtils.toBean(createReqVO, CrmCustomerDO.class) - .setLockStatus(false).setDealStatus(false) - .setContactLastTime(LocalDateTime.now()); - // TODO @puhui999:可能要加个 receiveTime 字段,记录最后接收时间 + .setLockStatus(false).setDealStatus(false).setContactLastTime(LocalDateTime.now()); customerMapper.insert(customer); // 3. 创建数据权限 @@ -214,24 +210,24 @@ public class CrmCustomerServiceImpl implements CrmCustomerService { @Override @Transactional(rollbackFor = Exception.class) - public List createCustomerBatch(List customerCreateReqBOs, Long userId) { - if (CollUtil.isEmpty(customerCreateReqBOs)) { - return emptyList(); - } + @LogRecord(type = CRM_CUSTOMER_TYPE, subType = CRM_CUSTOMER_CREATE_SUB_TYPE, bizNo = "{{#customer.id}}", + success = CRM_CUSTOMER_CREATE_SUCCESS) + public Long createCustomer(CrmCustomerCreateReqBO customerCreateReq, Long userId) { + // 1. 插入客户 + CrmCustomerDO customer = BeanUtils.toBean(customerCreateReq, CrmCustomerDO.class).setOwnerUserId(userId) + .setLockStatus(false).setDealStatus(false).setReceiveTime(LocalDateTime.now()); + customerMapper.insert(customer); - // 创建客户 - List customers = convertList(customerCreateReqBOs, customerBO -> - BeanUtils.toBean(customerBO, CrmCustomerDO.class).setOwnerUserId(userId)); - customerMapper.insertBatch(customers); + // 2. 创建数据权限 + permissionService.createPermission(new CrmPermissionCreateReqBO().setBizType(CrmBizTypeEnum.CRM_CUSTOMER.getType()) + .setBizId(customer.getId()).setUserId(userId).setLevel(CrmPermissionLevelEnum.OWNER.getLevel())); // 设置当前操作的人为负责人 - // 创建负责人数据权限 - permissionService.createPermissionBatch(convertList(customers, customer -> new CrmPermissionCreateReqBO() - .setBizType(CrmBizTypeEnum.CRM_CUSTOMER.getType()).setBizId(customer.getId()).setUserId(userId) - .setLevel(CrmPermissionLevelEnum.OWNER.getLevel()))); - return customers; + // 3. 记录操作日志上下文 + LogRecordContext.putVariable("customer", customer); + return customer.getId(); } - // ==================== 公海相关操作 ==================== +// ==================== 公海相关操作 ==================== @Override @Transactional(rollbackFor = Exception.class) diff --git a/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/service/followup/CrmFollowUpRecordServiceImpl.java b/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/service/followup/CrmFollowUpRecordServiceImpl.java index dc2001565..9a04e2d94 100644 --- a/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/service/followup/CrmFollowUpRecordServiceImpl.java +++ b/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/service/followup/CrmFollowUpRecordServiceImpl.java @@ -7,7 +7,6 @@ import cn.iocoder.yudao.framework.common.util.object.BeanUtils; import cn.iocoder.yudao.module.crm.controller.admin.followup.vo.CrmFollowUpRecordPageReqVO; import cn.iocoder.yudao.module.crm.controller.admin.followup.vo.CrmFollowUpRecordSaveReqVO; import cn.iocoder.yudao.module.crm.dal.dataobject.followup.CrmFollowUpRecordDO; -import cn.iocoder.yudao.module.crm.dal.dataobject.permission.CrmPermissionDO; import cn.iocoder.yudao.module.crm.dal.mysql.followup.CrmFollowUpRecordMapper; import cn.iocoder.yudao.module.crm.enums.common.CrmBizTypeEnum; import cn.iocoder.yudao.module.crm.enums.permission.CrmPermissionLevelEnum; @@ -31,10 +30,10 @@ import java.util.Collections; import java.util.List; import static cn.iocoder.yudao.framework.common.exception.util.ServiceExceptionUtil.exception; -import static cn.iocoder.yudao.framework.common.util.collection.CollectionUtils.anyMatch; import static cn.iocoder.yudao.framework.common.util.collection.CollectionUtils.convertList; import static cn.iocoder.yudao.module.crm.enums.ErrorCodeConstants.FOLLOW_UP_RECORD_DELETE_DENIED; import static cn.iocoder.yudao.module.crm.enums.ErrorCodeConstants.FOLLOW_UP_RECORD_NOT_EXISTS; +import static cn.iocoder.yudao.module.crm.framework.permission.core.util.CrmPermissionUtils.hasPermission; /** * 跟进记录 Service 实现类 @@ -94,14 +93,15 @@ public class CrmFollowUpRecordServiceImpl implements CrmFollowUpRecordService { customerService.updateCustomerFollowUp(updateFollowUpReqBO); } - // TODO @puhui999:这两个,不更新 contactLastTime、contactLastContent,只更新 nextTime // 3.1 更新 contactIds 对应的记录 if (CollUtil.isNotEmpty(createReqVO.getContactIds())) { - contactService.updateContactFollowUpBatch(convertList(createReqVO.getContactIds(), updateFollowUpReqBO::setBizId)); + contactService.updateContactFollowUpBatch(convertList(createReqVO.getContactIds(), + contactId -> updateFollowUpReqBO.setBizId(contactId).setContactLastTime(null).setContactLastContent(null))); } // 3.2 需要更新 businessIds、contactIds 对应的记录 if (CollUtil.isNotEmpty(createReqVO.getBusinessIds())) { - businessService.updateBusinessFollowUpBatch(convertList(createReqVO.getBusinessIds(), updateFollowUpReqBO::setBizId)); + businessService.updateBusinessFollowUpBatch(convertList(createReqVO.getBusinessIds(), + businessId -> updateFollowUpReqBO.setBizId(businessId).setContactLastTime(null).setContactLastContent(null))); } return followUpRecord.getId(); } @@ -112,8 +112,7 @@ public class CrmFollowUpRecordServiceImpl implements CrmFollowUpRecordService { return; } - List followUpRecords = BeanUtils.toBean(followUpCreateReqBOs, CrmFollowUpRecordDO.class); - crmFollowUpRecordMapper.insertBatch(followUpRecords); + crmFollowUpRecordMapper.insertBatch(BeanUtils.toBean(followUpCreateReqBOs, CrmFollowUpRecordDO.class)); } @Override @@ -121,12 +120,7 @@ public class CrmFollowUpRecordServiceImpl implements CrmFollowUpRecordService { // 校验存在 CrmFollowUpRecordDO followUpRecord = validateFollowUpRecordExists(id); // 校验权限 - // TODO @puhui999:是不是封装一个 hasPermission,更简介一点; - List permissionList = permissionService.getPermissionListByBiz( - followUpRecord.getBizType(), followUpRecord.getBizId()); - boolean hasPermission = anyMatch(permissionList, permission -> - ObjUtil.equal(permission.getUserId(), userId) && ObjUtil.equal(permission.getLevel(), CrmPermissionLevelEnum.OWNER.getLevel())); - if (!hasPermission) { + if (!hasPermission(followUpRecord.getBizType(), followUpRecord.getBizId(), userId, CrmPermissionLevelEnum.OWNER)) { throw exception(FOLLOW_UP_RECORD_DELETE_DENIED); } diff --git a/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/service/followup/bo/CrmUpdateFollowUpReqBO.java b/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/service/followup/bo/CrmUpdateFollowUpReqBO.java index 74e789436..57f1849eb 100644 --- a/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/service/followup/bo/CrmUpdateFollowUpReqBO.java +++ b/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/service/followup/bo/CrmUpdateFollowUpReqBO.java @@ -21,7 +21,6 @@ public class CrmUpdateFollowUpReqBO { @Schema(description = "最后跟进时间") @DiffLogField(name = "最后跟进时间") - @NotNull(message = "最后跟进时间不能为空") private LocalDateTime contactLastTime; @Schema(description = "下次联系时间") @@ -30,7 +29,6 @@ public class CrmUpdateFollowUpReqBO { @Schema(description = "最后更进内容") @DiffLogField(name = "最后更进内容") - @NotNull(message = "最后更进内容不能为空") private String contactLastContent; } From ed92bf45ce2b157fe309e59c24dfb12bd1cfb72e Mon Sep 17 00:00:00 2001 From: puhui999 Date: Tue, 23 Jan 2024 23:30:13 +0800 Subject: [PATCH 029/119] =?UTF-8?q?CRM:=20=E5=AE=A2=E6=88=B7=E8=87=AA?= =?UTF-8?q?=E5=8A=A8=E6=8E=89=E5=85=A5=E5=85=AC=E6=B5=B7?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- yudao-module-crm/yudao-module-crm-biz/pom.xml | 4 ++ .../dal/mysql/customer/CrmCustomerMapper.java | 7 ++ .../customer/CrmCustomerAutoPutPoolJob.java | 27 ++++++++ .../yudao/module/crm/job/package-info.java | 1 + .../service/customer/CrmCustomerService.java | 7 ++ .../customer/CrmCustomerServiceImpl.java | 64 +++++++++++++++---- 6 files changed, 99 insertions(+), 11 deletions(-) create mode 100644 yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/job/customer/CrmCustomerAutoPutPoolJob.java create mode 100644 yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/job/package-info.java diff --git a/yudao-module-crm/yudao-module-crm-biz/pom.xml b/yudao-module-crm/yudao-module-crm-biz/pom.xml index 9e1a9e152..d786a90fa 100644 --- a/yudao-module-crm/yudao-module-crm-biz/pom.xml +++ b/yudao-module-crm/yudao-module-crm-biz/pom.xml @@ -70,5 +70,9 @@ cn.iocoder.boot yudao-spring-boot-starter-test + + cn.iocoder.boot + yudao-spring-boot-starter-biz-tenant + diff --git a/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/dal/mysql/customer/CrmCustomerMapper.java b/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/dal/mysql/customer/CrmCustomerMapper.java index 63e28329d..c38d114c2 100644 --- a/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/dal/mysql/customer/CrmCustomerMapper.java +++ b/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/dal/mysql/customer/CrmCustomerMapper.java @@ -10,6 +10,7 @@ import cn.iocoder.yudao.module.crm.controller.admin.customer.vo.CrmCustomerPageR import cn.iocoder.yudao.module.crm.dal.dataobject.customer.CrmCustomerDO; import cn.iocoder.yudao.module.crm.enums.common.CrmBizTypeEnum; import cn.iocoder.yudao.module.crm.util.CrmQueryWrapperUtils; +import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper; import com.baomidou.mybatisplus.core.conditions.update.LambdaUpdateWrapper; import org.apache.ibatis.annotations.Mapper; import org.springframework.lang.Nullable; @@ -99,4 +100,10 @@ public interface CrmCustomerMapper extends BaseMapperX { return selectJoinPage(pageReqVO, CrmCustomerDO.class, query); } + default List selectListByLockStatusAndOwnerUserIdNotNull(Boolean lockStatus) { + return selectList(new LambdaQueryWrapper() + .eq(CrmCustomerDO::getLockStatus, lockStatus) + .isNotNull(CrmCustomerDO::getOwnerUserId)); + } + } diff --git a/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/job/customer/CrmCustomerAutoPutPoolJob.java b/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/job/customer/CrmCustomerAutoPutPoolJob.java new file mode 100644 index 000000000..3d71df4f4 --- /dev/null +++ b/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/job/customer/CrmCustomerAutoPutPoolJob.java @@ -0,0 +1,27 @@ +package cn.iocoder.yudao.module.crm.job.customer; + +import cn.iocoder.yudao.framework.quartz.core.handler.JobHandler; +import cn.iocoder.yudao.framework.tenant.core.job.TenantJob; +import cn.iocoder.yudao.module.crm.service.customer.CrmCustomerService; +import jakarta.annotation.Resource; +import org.springframework.stereotype.Component; + +/** + * 客户自动掉入公海 Job + * + * @author 芋道源码 + */ +@Component +public class CrmCustomerAutoPutPoolJob implements JobHandler { + + @Resource + private CrmCustomerService customerService; + + @Override + @TenantJob + public String execute(String param) { + int count = customerService.customerAutoPutPoolBySystem(); + return String.format("掉入公海客户 %s 个", count); + } + +} \ No newline at end of file diff --git a/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/job/package-info.java b/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/job/package-info.java new file mode 100644 index 000000000..85cccce72 --- /dev/null +++ b/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/job/package-info.java @@ -0,0 +1 @@ +package cn.iocoder.yudao.module.crm.job; \ No newline at end of file diff --git a/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/service/customer/CrmCustomerService.java b/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/service/customer/CrmCustomerService.java index d813b2b4d..e4d06d2fc 100644 --- a/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/service/customer/CrmCustomerService.java +++ b/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/service/customer/CrmCustomerService.java @@ -126,4 +126,11 @@ public interface CrmCustomerService { */ void receiveCustomer(List ids, Long ownerUserId, Boolean isReceive); + /** + * 【系统】客户自动掉入公海 + * + * @return 掉入公海数量 + */ + int customerAutoPutPoolBySystem(); + } diff --git a/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/service/customer/CrmCustomerServiceImpl.java b/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/service/customer/CrmCustomerServiceImpl.java index 2958dbdf3..2077359ed 100644 --- a/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/service/customer/CrmCustomerServiceImpl.java +++ b/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/service/customer/CrmCustomerServiceImpl.java @@ -2,9 +2,11 @@ package cn.iocoder.yudao.module.crm.service.customer; import cn.hutool.core.collection.CollUtil; import cn.hutool.core.lang.Assert; +import cn.hutool.core.util.ObjUtil; import cn.hutool.extra.spring.SpringUtil; import cn.iocoder.yudao.framework.common.pojo.PageResult; import cn.iocoder.yudao.framework.common.util.collection.CollectionUtils; +import cn.iocoder.yudao.framework.common.util.date.LocalDateTimeUtils; import cn.iocoder.yudao.framework.common.util.object.BeanUtils; import cn.iocoder.yudao.module.crm.controller.admin.customer.vo.CrmCustomerLockReqVO; import cn.iocoder.yudao.module.crm.controller.admin.customer.vo.CrmCustomerPageReqVO; @@ -13,6 +15,7 @@ import cn.iocoder.yudao.module.crm.controller.admin.customer.vo.CrmCustomerTrans import cn.iocoder.yudao.module.crm.convert.customer.CrmCustomerConvert; import cn.iocoder.yudao.module.crm.dal.dataobject.customer.CrmCustomerDO; import cn.iocoder.yudao.module.crm.dal.dataobject.customer.CrmCustomerLimitConfigDO; +import cn.iocoder.yudao.module.crm.dal.dataobject.customer.CrmCustomerPoolConfigDO; import cn.iocoder.yudao.module.crm.dal.mysql.customer.CrmCustomerMapper; import cn.iocoder.yudao.module.crm.enums.common.CrmBizTypeEnum; import cn.iocoder.yudao.module.crm.enums.permission.CrmPermissionLevelEnum; @@ -31,6 +34,7 @@ import com.mzt.logapi.context.LogRecordContext; import com.mzt.logapi.service.impl.DiffParseFunction; import com.mzt.logapi.starter.annotation.LogRecord; import jakarta.annotation.Resource; +import lombok.extern.slf4j.Slf4j; import org.springframework.context.annotation.Lazy; import org.springframework.stereotype.Service; import org.springframework.transaction.annotation.Transactional; @@ -55,6 +59,7 @@ import static java.util.Collections.singletonList; * @author Wanwan */ @Service +@Slf4j @Validated public class CrmCustomerServiceImpl implements CrmCustomerService { @@ -67,6 +72,9 @@ public class CrmCustomerServiceImpl implements CrmCustomerService { private CrmCustomerLimitConfigService customerLimitConfigService; @Resource @Lazy + private CrmCustomerPoolConfigService customerPoolConfigService; + @Resource + @Lazy private CrmContactService contactService; @Resource @Lazy @@ -245,17 +253,8 @@ public class CrmCustomerServiceImpl implements CrmCustomerService { // 1.3. 校验客户是否锁定 validateCustomerIsLocked(customer, true); - // 2.1 设置负责人为 NULL - int updateOwnerUserIncr = customerMapper.updateOwnerUserIdById(customer.getId(), null); - if (updateOwnerUserIncr == 0) { - throw exception(CUSTOMER_UPDATE_OWNER_USER_FAIL); - } - // 2.2 删除负责人数据权限 - permissionService.deletePermission(CrmBizTypeEnum.CRM_CUSTOMER.getType(), customer.getId(), - CrmPermissionLevelEnum.OWNER.getLevel()); - - // 3. 联系人的负责人,也要设置为 null。因为:因为领取后,负责人也要关联过来,这块和 receiveCustomer 是对应的 - contactService.updateOwnerUserIdByCustomerId(customer.getId(), null); + // 2. 客户放入公海 + putCustomerPool(customer); // 记录操作日志上下文 LogRecordContext.putVariable("customerName", customer.getName()); @@ -313,6 +312,49 @@ public class CrmCustomerServiceImpl implements CrmCustomerService { } } + @Override + public int customerAutoPutPoolBySystem() { + CrmCustomerPoolConfigDO poolConfig = customerPoolConfigService.getCustomerPoolConfig(); + if (poolConfig == null || !poolConfig.getEnabled()) { + return 0; + } + // 获取没有锁定的不在公海的客户 + List customerList = customerMapper.selectListByLockStatusAndOwnerUserIdNotNull(Boolean.FALSE); + List poolCustomerList = CollectionUtils.filterList(customerList, customer -> { + // 1.1 未成交放入公海 + if (!customer.getDealStatus()) { + return (poolConfig.getDealExpireDays() - LocalDateTimeUtils.between(customer.getCreateTime())) <= 0; + } + // 1.2 未跟进放入公海 + LocalDateTime lastTime = ObjUtil.defaultIfNull(customer.getContactLastTime(), customer.getCreateTime()); + return (poolConfig.getContactExpireDays() - LocalDateTimeUtils.between(lastTime)) <= 0; + }); + int count = 0; + for (CrmCustomerDO customer : poolCustomerList) { + try { + getSelf().putCustomerPool(customer); + count++; + } catch (Throwable e) { + log.error("[customerAutoPutPoolBySystem][Customer 客户({}) 放入公海异常]", customer.getId(), e); + } + } + return count; + } + + private void putCustomerPool(CrmCustomerDO customer) { + // 1. 设置负责人为 NULL + int updateOwnerUserIncr = customerMapper.updateOwnerUserIdById(customer.getId(), null); + if (updateOwnerUserIncr == 0) { + throw exception(CUSTOMER_UPDATE_OWNER_USER_FAIL); + } + // 2. 删除负责人数据权限 + permissionService.deletePermission(CrmBizTypeEnum.CRM_CUSTOMER.getType(), customer.getId(), + CrmPermissionLevelEnum.OWNER.getLevel()); + + // 3. 联系人的负责人,也要设置为 null。因为:因为领取后,负责人也要关联过来,这块和 receiveCustomer 是对应的 + contactService.updateOwnerUserIdByCustomerId(customer.getId(), null); + } + @LogRecord(type = CRM_CUSTOMER_TYPE, subType = CRM_CUSTOMER_RECEIVE_SUB_TYPE, bizNo = "{{#customer.id}}", success = CRM_CUSTOMER_RECEIVE_SUCCESS) public void receiveCustomerLog(CrmCustomerDO customer, String ownerUserName) { From ce397d4fbd0467769d3c506fa9bbf85d5641cca2 Mon Sep 17 00:00:00 2001 From: min Date: Wed, 24 Jan 2024 00:27:09 +0800 Subject: [PATCH 030/119] =?UTF-8?q?CRM=EF=BC=9A=E3=80=90=E7=BA=BF=E7=B4=A2?= =?UTF-8?q?=E3=80=91=E5=A2=9E=E5=8A=A0=E5=AD=97=E6=AE=B5?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../admin/clue/CrmClueController.java | 2 +- .../admin/clue/vo/CrmCluePageReqVO.java | 9 ++++ .../admin/clue/vo/CrmClueRespVO.java | 34 ++++++++++++++ .../admin/clue/vo/CrmClueSaveReqVO.java | 47 +++++++++++++++++++ ...mReqVO.java => CrmClueTranslateReqVO.java} | 2 +- .../crm/dal/dataobject/clue/CrmClueDO.java | 43 ++++++++++++++--- .../crm/dal/mysql/clue/CrmClueMapper.java | 3 ++ .../crm/service/clue/CrmClueService.java | 4 +- .../crm/service/clue/CrmClueServiceImpl.java | 4 +- 9 files changed, 135 insertions(+), 13 deletions(-) rename yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/controller/admin/clue/vo/{CrmClueTransformReqVO.java => CrmClueTranslateReqVO.java} (92%) diff --git a/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/controller/admin/clue/CrmClueController.java b/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/controller/admin/clue/CrmClueController.java index 9c6a88f2d..dca364cba 100644 --- a/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/controller/admin/clue/CrmClueController.java +++ b/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/controller/admin/clue/CrmClueController.java @@ -99,7 +99,7 @@ public class CrmClueController { @PostMapping("/transform") @Operation(summary = "线索转化为客户") @PreAuthorize("@ss.hasPermission('crm:clue:update')") - public CommonResult translateCustomer(@Valid @RequestBody CrmClueTransformReqVO reqVO) { + public CommonResult translateCustomer(@Valid @RequestBody CrmClueTranslateReqVO reqVO) { clueService.translateCustomer(reqVO, getLoginUserId()); return success(Boolean.TRUE); } diff --git a/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/controller/admin/clue/vo/CrmCluePageReqVO.java b/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/controller/admin/clue/vo/CrmCluePageReqVO.java index 0b6e7a50a..3ba823d54 100644 --- a/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/controller/admin/clue/vo/CrmCluePageReqVO.java +++ b/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/controller/admin/clue/vo/CrmCluePageReqVO.java @@ -30,4 +30,13 @@ public class CrmCluePageReqVO extends PageParam { @Schema(description = "是否为公海数据", requiredMode = Schema.RequiredMode.REQUIRED, example = "false") private Boolean pool; // null 则表示为不是公海数据 + @Schema(description = "所属行业", example = "1") + private Integer industryId; + + @Schema(description = "客户等级", example = "1") + private Integer level; + + @Schema(description = "客户来源", example = "1") + private Integer source; + } diff --git a/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/controller/admin/clue/vo/CrmClueRespVO.java b/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/controller/admin/clue/vo/CrmClueRespVO.java index b9e41ed82..53a94cb81 100644 --- a/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/controller/admin/clue/vo/CrmClueRespVO.java +++ b/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/controller/admin/clue/vo/CrmClueRespVO.java @@ -77,4 +77,38 @@ public class CrmClueRespVO { @ExcelProperty("创建时间") private LocalDateTime createTime; + @Schema(description = "所属行业", requiredMode = Schema.RequiredMode.REQUIRED, example = "13563") + @ExcelProperty(value = "所属行业", converter = DictConvert.class) + @DictFormat(cn.iocoder.yudao.module.crm.enums.DictTypeConstants.CRM_CUSTOMER_INDUSTRY) + private Integer industryId; + + @Schema(description = "客户等级", requiredMode = Schema.RequiredMode.REQUIRED, example = "13563") + @ExcelProperty(value = "客户等级", converter = DictConvert.class) + @DictFormat(cn.iocoder.yudao.module.crm.enums.DictTypeConstants.CRM_CUSTOMER_LEVEL) + private Integer level; + + @Schema(description = "客户来源", requiredMode = Schema.RequiredMode.REQUIRED, example = "13563") + @ExcelProperty(value = "客户来源", converter = DictConvert.class) + @DictFormat(cn.iocoder.yudao.module.crm.enums.DictTypeConstants.CRM_CUSTOMER_SOURCE) + private Integer source; + + @Schema(description = "负责人的用户编号", example = "25682") + @ExcelProperty("网址") + private String website; + + @Schema(description = "负责人的用户编号", example = "25682") + @ExcelProperty("QQ") + private String qq; + + @Schema(description = "负责人的用户编号", example = "25682") + @ExcelProperty("wechat") + private String wechat; + + @Schema(description = "负责人的用户编号", example = "25682") + @ExcelProperty("email") + private String email; + + @Schema(description = "负责人的用户编号", example = "25682") + @ExcelProperty("客户描述") + private String description; } diff --git a/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/controller/admin/clue/vo/CrmClueSaveReqVO.java b/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/controller/admin/clue/vo/CrmClueSaveReqVO.java index 8ceaae2c8..4ca004a59 100644 --- a/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/controller/admin/clue/vo/CrmClueSaveReqVO.java +++ b/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/controller/admin/clue/vo/CrmClueSaveReqVO.java @@ -1,16 +1,25 @@ package cn.iocoder.yudao.module.crm.controller.admin.clue.vo; +import cn.iocoder.yudao.framework.common.validation.InEnum; import cn.iocoder.yudao.framework.common.validation.Mobile; import cn.iocoder.yudao.framework.common.validation.Telephone; +import cn.iocoder.yudao.framework.excel.core.annotations.DictFormat; +import cn.iocoder.yudao.module.crm.enums.customer.CrmCustomerLevelEnum; +import cn.iocoder.yudao.module.crm.framework.operatelog.core.CrmCustomerIndustryParseFunction; +import cn.iocoder.yudao.module.crm.framework.operatelog.core.CrmCustomerLevelParseFunction; +import cn.iocoder.yudao.module.crm.framework.operatelog.core.CrmCustomerSourceParseFunction; import com.mzt.logapi.starter.annotation.DiffLogField; import io.swagger.v3.oas.annotations.media.Schema; +import jakarta.validation.constraints.Email; import jakarta.validation.constraints.NotEmpty; +import jakarta.validation.constraints.Size; import lombok.Data; import org.springframework.format.annotation.DateTimeFormat; import java.time.LocalDateTime; import static cn.iocoder.yudao.framework.common.util.date.DateUtils.FORMAT_YEAR_MONTH_DAY_HOUR_MINUTE_SECOND; +import static cn.iocoder.yudao.module.crm.enums.DictTypeConstants.CRM_CUSTOMER_INDUSTRY; @Schema(description = "管理后台 - CRM 线索 创建/更新 Request VO") @Data @@ -55,4 +64,42 @@ public class CrmClueSaveReqVO { @DiffLogField(name = "备注") private String remark; + @Schema(description = "所属行业", example = "1") + @DiffLogField(name = "所属行业", function = CrmCustomerIndustryParseFunction.NAME) + @DictFormat(CRM_CUSTOMER_INDUSTRY) + private Integer industryId; + + @Schema(description = "客户等级", example = "2") + @DiffLogField(name = "客户等级", function = CrmCustomerLevelParseFunction.NAME) + @InEnum(CrmCustomerLevelEnum.class) + private Integer level; + + @Schema(description = "客户来源", example = "3") + @DiffLogField(name = "客户来源", function = CrmCustomerSourceParseFunction.NAME) + private Integer source; + + @Schema(description = "网址", example = "https://www.baidu.com") + @DiffLogField(name = "网址") + private String website; + + @Schema(description = "QQ", example = "123456789") + @DiffLogField(name = "QQ") + @Size(max = 20, message = "QQ长度不能超过 20 个字符") + private String qq; + + @Schema(description = "微信", example = "123456789") + @DiffLogField(name = "微信") + @Size(max = 255, message = "微信长度不能超过 255 个字符") + private String wechat; + + @Schema(description = "邮箱", example = "123456789@qq.com") + @DiffLogField(name = "邮箱") + @Email(message = "邮箱格式不正确") + @Size(max = 255, message = "邮箱长度不能超过 255 个字符") + private String email; + + @Schema(description = "客户描述", example = "任意文字") + @DiffLogField(name = "客户描述") + @Size(max = 4096, message = "客户描述长度不能超过 4096 个字符") + private String description; } diff --git a/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/controller/admin/clue/vo/CrmClueTransformReqVO.java b/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/controller/admin/clue/vo/CrmClueTranslateReqVO.java similarity index 92% rename from yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/controller/admin/clue/vo/CrmClueTransformReqVO.java rename to yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/controller/admin/clue/vo/CrmClueTranslateReqVO.java index 68bb02b3f..03a4d78f1 100644 --- a/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/controller/admin/clue/vo/CrmClueTransformReqVO.java +++ b/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/controller/admin/clue/vo/CrmClueTranslateReqVO.java @@ -8,7 +8,7 @@ import java.util.Set; @Schema(description = "管理后台 - 线索转化为客户 Request VO") @Data -public class CrmClueTransformReqVO { +public class CrmClueTranslateReqVO { @Schema(description = "线索编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "[1024, 1025]") @NotEmpty(message = "线索编号不能为空") diff --git a/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/dal/dataobject/clue/CrmClueDO.java b/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/dal/dataobject/clue/CrmClueDO.java index 7d85c6ac1..5ea1dea28 100644 --- a/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/dal/dataobject/clue/CrmClueDO.java +++ b/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/dal/dataobject/clue/CrmClueDO.java @@ -2,6 +2,7 @@ package cn.iocoder.yudao.module.crm.dal.dataobject.clue; import cn.iocoder.yudao.framework.mybatis.core.dataobject.BaseDO; import cn.iocoder.yudao.module.crm.dal.dataobject.customer.CrmCustomerDO; +import cn.iocoder.yudao.module.crm.enums.DictTypeConstants; import com.baomidou.mybatisplus.annotation.KeySequence; import com.baomidou.mybatisplus.annotation.TableId; import com.baomidou.mybatisplus.annotation.TableName; @@ -72,16 +73,44 @@ public class CrmClueDO extends BaseDO { * 备注 */ private String remark; - /** * 负责人的用户编号 - * * 关联 AdminUserDO 的 id 字段 */ private Long ownerUserId; - - // TODO 芋艿:客户级别; - // TODO 芋艿:线索来源; - // TODO 芋艿:客户行业; - + /** + * 所属行业 + * 对应字典 {@link DictTypeConstants#CRM_CUSTOMER_INDUSTRY} + */ + private Integer industryId; + /** + * 客户等级 + * 对应字典 {@link DictTypeConstants#CRM_CUSTOMER_LEVEL} + */ + private Integer level; + /** + * 客户来源 + * 对应字典 {@link DictTypeConstants#CRM_CUSTOMER_SOURCE} + */ + private Integer source; + /** + * 网址 + */ + private String website; + /** + * QQ + */ + private String qq; + /** + * wechat + */ + private String wechat; + /** + * email + */ + private String email; + /** + * 客户描述 + */ + private String description; } diff --git a/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/dal/mysql/clue/CrmClueMapper.java b/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/dal/mysql/clue/CrmClueMapper.java index ec21cbe93..cab4c4662 100644 --- a/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/dal/mysql/clue/CrmClueMapper.java +++ b/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/dal/mysql/clue/CrmClueMapper.java @@ -37,6 +37,9 @@ public interface CrmClueMapper extends BaseMapperX { .likeIfPresent(CrmClueDO::getName, pageReqVO.getName()) .likeIfPresent(CrmClueDO::getTelephone, pageReqVO.getTelephone()) .likeIfPresent(CrmClueDO::getMobile, pageReqVO.getMobile()) + .eqIfPresent(CrmClueDO::getIndustryId, pageReqVO.getIndustryId()) + .eqIfPresent(CrmClueDO::getLevel, pageReqVO.getLevel()) + .eqIfPresent(CrmClueDO::getSource, pageReqVO.getSource()) .orderByDesc(CrmClueDO::getId); return selectJoinPage(pageReqVO, CrmClueDO.class, query); } diff --git a/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/service/clue/CrmClueService.java b/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/service/clue/CrmClueService.java index b189bd266..1472bf02f 100644 --- a/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/service/clue/CrmClueService.java +++ b/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/service/clue/CrmClueService.java @@ -4,7 +4,7 @@ import cn.iocoder.yudao.framework.common.pojo.PageResult; import cn.iocoder.yudao.module.crm.controller.admin.clue.vo.CrmCluePageReqVO; import cn.iocoder.yudao.module.crm.controller.admin.clue.vo.CrmClueSaveReqVO; import cn.iocoder.yudao.module.crm.controller.admin.clue.vo.CrmClueTransferReqVO; -import cn.iocoder.yudao.module.crm.controller.admin.clue.vo.CrmClueTransformReqVO; +import cn.iocoder.yudao.module.crm.controller.admin.clue.vo.CrmClueTranslateReqVO; import cn.iocoder.yudao.module.crm.dal.dataobject.clue.CrmClueDO; import cn.iocoder.yudao.module.crm.service.followup.bo.CrmUpdateFollowUpReqBO; import jakarta.validation.Valid; @@ -88,6 +88,6 @@ public interface CrmClueService { * @param reqVO 线索编号 * @param userId 用户编号 */ - void translateCustomer(CrmClueTransformReqVO reqVO, Long userId); + void translateCustomer(CrmClueTranslateReqVO reqVO, Long userId); } diff --git a/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/service/clue/CrmClueServiceImpl.java b/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/service/clue/CrmClueServiceImpl.java index 304b150fe..54cc09034 100644 --- a/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/service/clue/CrmClueServiceImpl.java +++ b/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/service/clue/CrmClueServiceImpl.java @@ -11,7 +11,7 @@ import cn.iocoder.yudao.framework.common.util.object.BeanUtils; import cn.iocoder.yudao.module.crm.controller.admin.clue.vo.CrmCluePageReqVO; import cn.iocoder.yudao.module.crm.controller.admin.clue.vo.CrmClueSaveReqVO; import cn.iocoder.yudao.module.crm.controller.admin.clue.vo.CrmClueTransferReqVO; -import cn.iocoder.yudao.module.crm.controller.admin.clue.vo.CrmClueTransformReqVO; +import cn.iocoder.yudao.module.crm.controller.admin.clue.vo.CrmClueTranslateReqVO; import cn.iocoder.yudao.module.crm.controller.admin.customer.vo.CrmCustomerSaveReqVO; import cn.iocoder.yudao.module.crm.convert.clue.CrmClueConvert; import cn.iocoder.yudao.module.crm.dal.dataobject.clue.CrmClueDO; @@ -177,7 +177,7 @@ public class CrmClueServiceImpl implements CrmClueService { @Override @Transactional(rollbackFor = Exception.class) @CrmPermission(bizType = CrmBizTypeEnum.CRM_LEADS, bizId = "#id", level = CrmPermissionLevelEnum.OWNER) - public void translateCustomer(CrmClueTransformReqVO reqVO, Long userId) { + public void translateCustomer(CrmClueTranslateReqVO reqVO, Long userId) { // 1.1 校验线索都存在 Set clueIds = reqVO.getIds(); List clues = getClueList(clueIds, userId); From d611ebc0a29f86339d65f8e298151f389fe13375 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E6=9D=A8=E5=AE=87=E5=BA=86?= Date: Thu, 25 Jan 2024 06:28:30 +0000 Subject: [PATCH 031/119] =?UTF-8?q?=E4=BF=AE=E5=A4=8D=E3=80=90=E7=9F=AD?= =?UTF-8?q?=E4=BF=A1=E5=8F=91=E9=80=81=E8=BF=87=E4=BA=8E=E9=A2=91=E7=8E=87?= =?UTF-8?q?=E3=80=91=E7=9A=84=E6=8B=BC=E5=86=99=E9=94=99=E8=AF=AF?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: 杨宇庆 --- .../iocoder/yudao/module/system/enums/ErrorCodeConstants.java | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/yudao-module-system/yudao-module-system-api/src/main/java/cn/iocoder/yudao/module/system/enums/ErrorCodeConstants.java b/yudao-module-system/yudao-module-system-api/src/main/java/cn/iocoder/yudao/module/system/enums/ErrorCodeConstants.java index ef5c3a624..2f41f67e9 100644 --- a/yudao-module-system/yudao-module-system-api/src/main/java/cn/iocoder/yudao/module/system/enums/ErrorCodeConstants.java +++ b/yudao-module-system/yudao-module-system-api/src/main/java/cn/iocoder/yudao/module/system/enums/ErrorCodeConstants.java @@ -98,7 +98,7 @@ public interface ErrorCodeConstants { ErrorCode SMS_CODE_USED = new ErrorCode(1_002_014_002, "验证码已使用"); ErrorCode SMS_CODE_NOT_CORRECT = new ErrorCode(1_002_014_003, "验证码不正确"); ErrorCode SMS_CODE_EXCEED_SEND_MAXIMUM_QUANTITY_PER_DAY = new ErrorCode(1_002_014_004, "超过每日短信发送数量"); - ErrorCode SMS_CODE_SEND_TOO_FAST = new ErrorCode(1_002_014_005, "短信发送过于频率"); + ErrorCode SMS_CODE_SEND_TOO_FAST = new ErrorCode(1_002_014_005, "短信发送过于频繁"); ErrorCode SMS_CODE_IS_EXISTS = new ErrorCode(1_002_014_006, "手机号已被使用"); ErrorCode SMS_CODE_IS_UNUSED = new ErrorCode(1_002_014_007, "验证码未被使用"); From 443409f462297e8bbd18ef5a3dff1d906b32c7ad Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E6=9D=A8=E5=AE=87=E5=BA=86?= Date: Thu, 25 Jan 2024 07:19:44 +0000 Subject: [PATCH 032/119] =?UTF-8?q?=E8=A7=A3=E5=86=B3deploy.sh=E9=87=8C?= =?UTF-8?q?=E5=81=9C=E6=9C=8D=E5=8A=A1=E6=97=A0=E6=B3=95=E6=AD=A3=E5=B8=B8?= =?UTF-8?q?=E6=98=BE=E7=A4=BA=E6=9C=8D=E5=8A=A1=E5=90=8D=E7=9A=84=E9=97=AE?= =?UTF-8?q?=E9=A2=98=20=E8=A7=A3=E5=86=B3deploy.sh=E9=87=8C=E5=81=9C?= =?UTF-8?q?=E6=9C=8D=E5=8A=A1=E6=97=A0=E6=B3=95=E6=AD=A3=E5=B8=B8=E6=98=BE?= =?UTF-8?q?=E7=A4=BA=E6=9C=8D=E5=8A=A1=E5=90=8D=E7=9A=84=E9=97=AE=E9=A2=98?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: 杨宇庆 --- script/shell/deploy.sh | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/script/shell/deploy.sh b/script/shell/deploy.sh index f0fdf1fe6..b635a70b8 100644 --- a/script/shell/deploy.sh +++ b/script/shell/deploy.sh @@ -74,7 +74,7 @@ function stop() { if [ -n "$PID" ]; then echo -e ".\c" else - echo '[stop] 停止 $BASE_PATH/$SERVER_NAME 成功' + echo "[stop] 停止 $BASE_PATH/$SERVER_NAME 成功" break fi done From 11ce24ad1efe771b260161fe17badbd3d521905d Mon Sep 17 00:00:00 2001 From: Minh-X Date: Thu, 25 Jan 2024 14:17:24 +0000 Subject: [PATCH 033/119] =?UTF-8?q?=E4=BF=AE=E6=94=B9CrmClueRespVO?= =?UTF-8?q?=E5=AD=97=E6=AE=B5=E6=8F=8F=E8=BF=B0?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: Minh-X --- .../crm/controller/admin/clue/vo/CrmClueRespVO.java | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/controller/admin/clue/vo/CrmClueRespVO.java b/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/controller/admin/clue/vo/CrmClueRespVO.java index 53a94cb81..0858b6f3a 100644 --- a/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/controller/admin/clue/vo/CrmClueRespVO.java +++ b/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/controller/admin/clue/vo/CrmClueRespVO.java @@ -92,23 +92,23 @@ public class CrmClueRespVO { @DictFormat(cn.iocoder.yudao.module.crm.enums.DictTypeConstants.CRM_CUSTOMER_SOURCE) private Integer source; - @Schema(description = "负责人的用户编号", example = "25682") + @Schema(description = "网址", example = "25682") @ExcelProperty("网址") private String website; - @Schema(description = "负责人的用户编号", example = "25682") + @Schema(description = "QQ", example = "25682") @ExcelProperty("QQ") private String qq; - @Schema(description = "负责人的用户编号", example = "25682") + @Schema(description = "wechat", example = "25682") @ExcelProperty("wechat") private String wechat; - @Schema(description = "负责人的用户编号", example = "25682") + @Schema(description = "email", example = "25682") @ExcelProperty("email") private String email; - @Schema(description = "负责人的用户编号", example = "25682") + @Schema(description = "客户描述", example = "25682") @ExcelProperty("客户描述") private String description; } From 814b6f688d8751f61f16ddc124c41de91bc5270c Mon Sep 17 00:00:00 2001 From: YunaiV Date: Fri, 26 Jan 2024 23:46:02 +0800 Subject: [PATCH 034/119] =?UTF-8?q?=F0=9F=93=96=20CRM=EF=BC=9Acode=20revie?= =?UTF-8?q?w=20=E8=B7=9F=E8=BF=9B=E8=AE=B0=E5=BD=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- script/shell/deploy.sh | 2 +- yudao-module-crm/yudao-module-crm-biz/pom.xml | 2 + .../operatelog/vo/CrmOperateLogV2RespVO.java | 61 +++---------------- .../dal/mysql/customer/CrmCustomerMapper.java | 1 + .../core/util/CrmPermissionUtils.java | 1 + .../yudao/module/crm/job/package-info.java | 3 + .../crm/service/clue/CrmClueServiceImpl.java | 22 ++++--- .../service/customer/CrmCustomerService.java | 1 + .../followup/CrmFollowUpRecordService.java | 4 +- .../CrmFollowUpRecordServiceImpl.java | 11 ++-- .../system/enums/ErrorCodeConstants.java | 2 +- 11 files changed, 38 insertions(+), 72 deletions(-) diff --git a/script/shell/deploy.sh b/script/shell/deploy.sh index f0fdf1fe6..b635a70b8 100644 --- a/script/shell/deploy.sh +++ b/script/shell/deploy.sh @@ -74,7 +74,7 @@ function stop() { if [ -n "$PID" ]; then echo -e ".\c" else - echo '[stop] 停止 $BASE_PATH/$SERVER_NAME 成功' + echo "[stop] 停止 $BASE_PATH/$SERVER_NAME 成功" break fi done diff --git a/yudao-module-crm/yudao-module-crm-biz/pom.xml b/yudao-module-crm/yudao-module-crm-biz/pom.xml index d786a90fa..234cf268e 100644 --- a/yudao-module-crm/yudao-module-crm-biz/pom.xml +++ b/yudao-module-crm/yudao-module-crm-biz/pom.xml @@ -70,6 +70,8 @@ cn.iocoder.boot yudao-spring-boot-starter-test + + cn.iocoder.boot yudao-spring-boot-starter-biz-tenant diff --git a/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/controller/admin/operatelog/vo/CrmOperateLogV2RespVO.java b/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/controller/admin/operatelog/vo/CrmOperateLogV2RespVO.java index 298b5a51d..b3405428f 100644 --- a/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/controller/admin/operatelog/vo/CrmOperateLogV2RespVO.java +++ b/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/controller/admin/operatelog/vo/CrmOperateLogV2RespVO.java @@ -13,76 +13,31 @@ public class CrmOperateLogV2RespVO { @Schema(description = "编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "13563") private Long id; - /** - * 链路追踪编号 - */ - @Schema(description = "编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "13563") - private String traceId; - /** - * 用户编号 - */ + @Schema(description = "编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "1024") private Long userId; - /** - * 用户名称 - */ + @Schema(description = "编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "芋艿") private String userName; - /** - * 用户类型 - */ + @Schema(description = "编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "1") private Integer userType; - /** - * 操作模块类型 - */ + @Schema(description = "编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "13563") private String type; - /** - * 操作名 - */ + @Schema(description = "编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "修改客户") private String subType; - /** - * 操作模块业务编号 - */ + @Schema(description = "编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "13563") private Long bizId; - /** - * 操作内容 - */ + @Schema(description = "编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "将什么从什么改为了什么") private String action; - /** - * 拓展字段 - */ + @Schema(description = "编号", example = "{orderId: 1}") private String extra; - /** - * 请求方法名 - */ - @Schema(description = "编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "13563") - private String requestMethod; - /** - * 请求地址 - */ - @Schema(description = "编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "13563") - private String requestUrl; - /** - * 用户 IP - */ - @Schema(description = "编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "13563") - private String userIp; - /** - * 浏览器 UA - */ - @Schema(description = "编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "13563") - private String userAgent; - - /** - * 创建时间 - */ @Schema(description = "编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "2024-01-01") private LocalDateTime createTime; diff --git a/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/dal/mysql/customer/CrmCustomerMapper.java b/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/dal/mysql/customer/CrmCustomerMapper.java index c38d114c2..79ba99d22 100644 --- a/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/dal/mysql/customer/CrmCustomerMapper.java +++ b/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/dal/mysql/customer/CrmCustomerMapper.java @@ -103,6 +103,7 @@ public interface CrmCustomerMapper extends BaseMapperX { default List selectListByLockStatusAndOwnerUserIdNotNull(Boolean lockStatus) { return selectList(new LambdaQueryWrapper() .eq(CrmCustomerDO::getLockStatus, lockStatus) + // TODO @puhui999:not null 可以转化成大于 0 .isNotNull(CrmCustomerDO::getOwnerUserId)); } diff --git a/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/framework/permission/core/util/CrmPermissionUtils.java b/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/framework/permission/core/util/CrmPermissionUtils.java index 8f9c19410..4e5898455 100644 --- a/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/framework/permission/core/util/CrmPermissionUtils.java +++ b/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/framework/permission/core/util/CrmPermissionUtils.java @@ -30,6 +30,7 @@ public class CrmPermissionUtils { return SingletonManager.getPermissionApi().hasAnyRoles(getLoginUserId(), CrmPermissionRoleCodeEnum.CRM_ADMIN.getCode()); } + // TODO @puhui999:这个貌似直接放到 CrmPermissionService 会更好? /** * 校验权限 * diff --git a/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/job/package-info.java b/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/job/package-info.java index 85cccce72..144f64d02 100644 --- a/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/job/package-info.java +++ b/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/job/package-info.java @@ -1 +1,4 @@ +/** + * TODO 芋艿:临时占位,后续可删除 + */ package cn.iocoder.yudao.module.crm.job; \ No newline at end of file diff --git a/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/service/clue/CrmClueServiceImpl.java b/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/service/clue/CrmClueServiceImpl.java index 2329c4dce..387d9732f 100644 --- a/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/service/clue/CrmClueServiceImpl.java +++ b/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/service/clue/CrmClueServiceImpl.java @@ -190,32 +190,36 @@ public class CrmClueServiceImpl implements CrmClueService { throw exception(CLUE_ANY_CLUE_ALREADY_TRANSLATED, convertSet(translatedClues, CrmClueDO::getId)); } - // 2. 遍历线索(未转化的线索),创建对应的客户 + // 2.1 遍历线索(未转化的线索),创建对应的客户 clues.forEach(clue -> { Long customerId = customerService.createCustomer(BeanUtils.toBean(clue, CrmCustomerCreateReqBO.class), userId); clue.setCustomerId(customerId); }); + // 2.2 更新线索 + clueMapper.updateBatch(convertList(clues, clue -> new CrmClueDO().setId(clue.getId()) + .setTransformStatus(Boolean.TRUE).setCustomerId(clue.getCustomerId()))); + // 2.3 复制跟进记录 + copyFollowUpRecords(clues); - // 2.1 更新线索 - clueMapper.updateBatch(convertList(clues, clue -> new CrmClueDO().setId(clue.getId()).setTransformStatus(Boolean.TRUE) - .setCustomerId(clue.getCustomerId()))); - // 2.3 复制跟进 - updateFollowUpRecords(clues); // 3. 记录操作日志 for (CrmClueDO clue : clues) { getSelf().translateCustomerLog(clue); } } - private void updateFollowUpRecords(List clues) { + /** + * 线索被转换客户后,需要将线索的跟进记录,复制到客户上 + * + * @param clues 被转化的线索 + */ + private void copyFollowUpRecords(List clues) { List followUpRecords = followUpRecordService.getFollowUpRecordByBiz( CrmBizTypeEnum.CRM_LEADS.getType(), convertSet(clues, CrmClueDO::getId)); if (CollUtil.isEmpty(followUpRecords)) { return; } - - Map clueMap = convertMap(clues, CrmClueDO::getId); // 创建跟进 + Map clueMap = convertMap(clues, CrmClueDO::getId); followUpRecordService.createFollowUpRecordBatch(convertList(followUpRecords, followUpRecord -> BeanUtils.toBean(followUpRecord, CrmFollowUpCreateReqBO.class).setBizType(CrmBizTypeEnum.CRM_CUSTOMER.getType()) .setBizId(clueMap.get(followUpRecord.getBizId()).getCustomerId()))); diff --git a/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/service/customer/CrmCustomerService.java b/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/service/customer/CrmCustomerService.java index e4d06d2fc..bff150c14 100644 --- a/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/service/customer/CrmCustomerService.java +++ b/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/service/customer/CrmCustomerService.java @@ -126,6 +126,7 @@ public interface CrmCustomerService { */ void receiveCustomer(List ids, Long ownerUserId, Boolean isReceive); + // TODO @puhui999:autoPutCustomerPool,注释说明是系统就好哈; /** * 【系统】客户自动掉入公海 * diff --git a/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/service/followup/CrmFollowUpRecordService.java b/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/service/followup/CrmFollowUpRecordService.java index f881e5259..d2a7cb8f9 100644 --- a/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/service/followup/CrmFollowUpRecordService.java +++ b/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/service/followup/CrmFollowUpRecordService.java @@ -28,9 +28,9 @@ public interface CrmFollowUpRecordService { /** * 创建更进 * - * @param followUpCreateReqBOs 请求 + * @param list 请求 */ - void createFollowUpRecordBatch(List followUpCreateReqBOs); + void createFollowUpRecordBatch(List list); /** * 删除跟进记录 (数据权限基于 bizType、 bizId) diff --git a/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/service/followup/CrmFollowUpRecordServiceImpl.java b/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/service/followup/CrmFollowUpRecordServiceImpl.java index 9a04e2d94..9d6f87faa 100644 --- a/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/service/followup/CrmFollowUpRecordServiceImpl.java +++ b/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/service/followup/CrmFollowUpRecordServiceImpl.java @@ -93,12 +93,12 @@ public class CrmFollowUpRecordServiceImpl implements CrmFollowUpRecordService { customerService.updateCustomerFollowUp(updateFollowUpReqBO); } - // 3.1 更新 contactIds 对应的记录 + // 3.1 更新 contactIds 对应的记录,不更新 lastTime 和 lastContent if (CollUtil.isNotEmpty(createReqVO.getContactIds())) { contactService.updateContactFollowUpBatch(convertList(createReqVO.getContactIds(), contactId -> updateFollowUpReqBO.setBizId(contactId).setContactLastTime(null).setContactLastContent(null))); } - // 3.2 需要更新 businessIds、contactIds 对应的记录 + // 3.2 需要更新 businessIds 对应的记录,不更新 lastTime 和 lastContent if (CollUtil.isNotEmpty(createReqVO.getBusinessIds())) { businessService.updateBusinessFollowUpBatch(convertList(createReqVO.getBusinessIds(), businessId -> updateFollowUpReqBO.setBizId(businessId).setContactLastTime(null).setContactLastContent(null))); @@ -107,12 +107,11 @@ public class CrmFollowUpRecordServiceImpl implements CrmFollowUpRecordService { } @Override - public void createFollowUpRecordBatch(List followUpCreateReqBOs) { - if (CollUtil.isEmpty(followUpCreateReqBOs)) { + public void createFollowUpRecordBatch(List list) { + if (CollUtil.isEmpty(list)) { return; } - - crmFollowUpRecordMapper.insertBatch(BeanUtils.toBean(followUpCreateReqBOs, CrmFollowUpRecordDO.class)); + crmFollowUpRecordMapper.insertBatch(BeanUtils.toBean(list, CrmFollowUpRecordDO.class)); } @Override diff --git a/yudao-module-system/yudao-module-system-api/src/main/java/cn/iocoder/yudao/module/system/enums/ErrorCodeConstants.java b/yudao-module-system/yudao-module-system-api/src/main/java/cn/iocoder/yudao/module/system/enums/ErrorCodeConstants.java index ef5c3a624..2f41f67e9 100644 --- a/yudao-module-system/yudao-module-system-api/src/main/java/cn/iocoder/yudao/module/system/enums/ErrorCodeConstants.java +++ b/yudao-module-system/yudao-module-system-api/src/main/java/cn/iocoder/yudao/module/system/enums/ErrorCodeConstants.java @@ -98,7 +98,7 @@ public interface ErrorCodeConstants { ErrorCode SMS_CODE_USED = new ErrorCode(1_002_014_002, "验证码已使用"); ErrorCode SMS_CODE_NOT_CORRECT = new ErrorCode(1_002_014_003, "验证码不正确"); ErrorCode SMS_CODE_EXCEED_SEND_MAXIMUM_QUANTITY_PER_DAY = new ErrorCode(1_002_014_004, "超过每日短信发送数量"); - ErrorCode SMS_CODE_SEND_TOO_FAST = new ErrorCode(1_002_014_005, "短信发送过于频率"); + ErrorCode SMS_CODE_SEND_TOO_FAST = new ErrorCode(1_002_014_005, "短信发送过于频繁"); ErrorCode SMS_CODE_IS_EXISTS = new ErrorCode(1_002_014_006, "手机号已被使用"); ErrorCode SMS_CODE_IS_UNUSED = new ErrorCode(1_002_014_007, "验证码未被使用"); From d492daced4678b8bb6cfc258dd48f0825b15fd03 Mon Sep 17 00:00:00 2001 From: YunaiV Date: Sat, 27 Jan 2024 00:55:42 +0800 Subject: [PATCH 035/119] =?UTF-8?q?=F0=9F=93=96=20CRM=EF=BC=9Acode=20revie?= =?UTF-8?q?w=20=E8=B7=9F=E8=BF=9B=E8=AE=B0=E5=BD=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../module/crm/controller/admin/clue/vo/CrmClueRespVO.java | 1 + .../module/crm/service/customer/CrmCustomerServiceImpl.java | 5 ++++- 2 files changed, 5 insertions(+), 1 deletion(-) diff --git a/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/controller/admin/clue/vo/CrmClueRespVO.java b/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/controller/admin/clue/vo/CrmClueRespVO.java index 0858b6f3a..35d30956e 100644 --- a/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/controller/admin/clue/vo/CrmClueRespVO.java +++ b/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/controller/admin/clue/vo/CrmClueRespVO.java @@ -111,4 +111,5 @@ public class CrmClueRespVO { @Schema(description = "客户描述", example = "25682") @ExcelProperty("客户描述") private String description; + } diff --git a/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/service/customer/CrmCustomerServiceImpl.java b/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/service/customer/CrmCustomerServiceImpl.java index 2077359ed..ff9d9a030 100644 --- a/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/service/customer/CrmCustomerServiceImpl.java +++ b/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/service/customer/CrmCustomerServiceImpl.java @@ -318,9 +318,10 @@ public class CrmCustomerServiceImpl implements CrmCustomerService { if (poolConfig == null || !poolConfig.getEnabled()) { return 0; } - // 获取没有锁定的不在公海的客户 + // 1. 获取没有锁定的不在公海的客户 List customerList = customerMapper.selectListByLockStatusAndOwnerUserIdNotNull(Boolean.FALSE); List poolCustomerList = CollectionUtils.filterList(customerList, customer -> { + // TODO @puhui999:建议这里作为一个查询条件哈,不放内存里过滤; // 1.1 未成交放入公海 if (!customer.getDealStatus()) { return (poolConfig.getDealExpireDays() - LocalDateTimeUtils.between(customer.getCreateTime())) <= 0; @@ -329,6 +330,8 @@ public class CrmCustomerServiceImpl implements CrmCustomerService { LocalDateTime lastTime = ObjUtil.defaultIfNull(customer.getContactLastTime(), customer.getCreateTime()); return (poolConfig.getContactExpireDays() - LocalDateTimeUtils.between(lastTime)) <= 0; }); + + // 2. 逐个放入公海 int count = 0; for (CrmCustomerDO customer : poolCustomerList) { try { From 5b69df074cbe3215ea6077063f14df83db99477e Mon Sep 17 00:00:00 2001 From: YunaiV Date: Sat, 27 Jan 2024 10:25:25 +0800 Subject: [PATCH 036/119] =?UTF-8?q?=E2=9C=A8=20=E5=85=A8=E5=B1=80=EF=BC=9A?= =?UTF-8?q?=E5=B0=86=20banner=E3=80=81error-code=E3=80=81desensitize=20?= =?UTF-8?q?=E8=9E=8D=E5=90=88=E5=88=B0=20web=20=E7=BB=84=E4=BB=B6=E9=87=8C?= =?UTF-8?q?=EF=BC=8C=E5=87=8F=E5=B0=91=20starter?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- yudao-dependencies/pom.xml | 10 ---- yudao-framework/pom.xml | 3 -- .../yudao-spring-boot-starter-banner/pom.xml | 30 ------------ ...ot.autoconfigure.AutoConfiguration.imports | 1 - .../pom.xml | 49 ------------------- ...ot.autoconfigure.AutoConfiguration.imports | 1 - .../pom.xml | 38 -------------- .../yudao-spring-boot-starter-web/pom.xml | 18 ++++++- .../config/YudaoBannerAutoConfiguration.java | 0 .../banner/core/BannerApplicationRunner.java | 0 .../yudao/framework/banner/package-info.java | 0 .../core/base/annotation/DesensitizeBy.java | 0 .../base/handler/DesensitizationHandler.java | 0 .../StringDesensitizeSerializer.java | 0 .../regex/annotation/EmailDesensitize.java | 0 .../regex/annotation/RegexDesensitize.java | 0 .../AbstractRegexDesensitizationHandler.java | 0 .../DefaultRegexDesensitizationHandler.java | 0 .../handler/EmailDesensitizationHandler.java | 0 .../annotation/BankCardDesensitize.java | 0 .../annotation/CarLicenseDesensitize.java | 0 .../annotation/ChineseNameDesensitize.java | 0 .../annotation/FixedPhoneDesensitize.java | 0 .../slider/annotation/IdCardDesensitize.java | 0 .../slider/annotation/MobileDesensitize.java | 0 .../annotation/PasswordDesensitize.java | 0 .../slider/annotation/SliderDesensitize.java | 0 .../AbstractSliderDesensitizationHandler.java | 0 .../handler/BankCardDesensitization.java | 0 .../handler/CarLicenseDesensitization.java | 0 .../handler/ChineseNameDesensitization.java | 0 .../DefaultDesensitizationHandler.java | 0 .../handler/FixedPhoneDesensitization.java | 0 .../slider/handler/IdCardDesensitization.java | 0 .../slider/handler/MobileDesensitization.java | 0 .../handler/PasswordDesensitization.java | 0 .../framework/desensitize}/package-info.java | 2 +- .../errorcode/config/ErrorCodeProperties.java | 0 .../YudaoErrorCodeAutoConfiguration.java | 0 .../generator/ErrorCodeAutoGenerator.java | 0 .../generator/ErrorCodeAutoGeneratorImpl.java | 0 .../core/loader/ErrorCodeLoader.java | 0 .../core/loader/ErrorCodeLoaderImpl.java | 0 .../framework/errorcode/package-info.java | 0 ...ot.autoconfigure.AutoConfiguration.imports | 2 + .../src/main/resources/banner.txt | 0 .../desensitize/core/DesensitizeTest.java | 20 +++----- .../desensitize/core/annotation/Address.java | 2 +- .../core/handler/AddressHandler.java | 0 yudao-server/pom.xml | 8 --- 50 files changed, 29 insertions(+), 155 deletions(-) delete mode 100644 yudao-framework/yudao-spring-boot-starter-banner/pom.xml delete mode 100644 yudao-framework/yudao-spring-boot-starter-banner/src/main/resources/META-INF/spring/org.springframework.boot.autoconfigure.AutoConfiguration.imports delete mode 100644 yudao-framework/yudao-spring-boot-starter-biz-error-code/pom.xml delete mode 100644 yudao-framework/yudao-spring-boot-starter-biz-error-code/src/main/resources/META-INF/spring/org.springframework.boot.autoconfigure.AutoConfiguration.imports delete mode 100644 yudao-framework/yudao-spring-boot-starter-desensitize/pom.xml rename yudao-framework/{yudao-spring-boot-starter-banner => yudao-spring-boot-starter-web}/src/main/java/cn/iocoder/yudao/framework/banner/config/YudaoBannerAutoConfiguration.java (100%) rename yudao-framework/{yudao-spring-boot-starter-banner => yudao-spring-boot-starter-web}/src/main/java/cn/iocoder/yudao/framework/banner/core/BannerApplicationRunner.java (100%) rename yudao-framework/{yudao-spring-boot-starter-banner => yudao-spring-boot-starter-web}/src/main/java/cn/iocoder/yudao/framework/banner/package-info.java (100%) rename yudao-framework/{yudao-spring-boot-starter-desensitize => yudao-spring-boot-starter-web}/src/main/java/cn/iocoder/yudao/framework/desensitize/core/base/annotation/DesensitizeBy.java (100%) rename yudao-framework/{yudao-spring-boot-starter-desensitize => yudao-spring-boot-starter-web}/src/main/java/cn/iocoder/yudao/framework/desensitize/core/base/handler/DesensitizationHandler.java (100%) rename yudao-framework/{yudao-spring-boot-starter-desensitize => yudao-spring-boot-starter-web}/src/main/java/cn/iocoder/yudao/framework/desensitize/core/base/serializer/StringDesensitizeSerializer.java (100%) rename yudao-framework/{yudao-spring-boot-starter-desensitize => yudao-spring-boot-starter-web}/src/main/java/cn/iocoder/yudao/framework/desensitize/core/regex/annotation/EmailDesensitize.java (100%) rename yudao-framework/{yudao-spring-boot-starter-desensitize => yudao-spring-boot-starter-web}/src/main/java/cn/iocoder/yudao/framework/desensitize/core/regex/annotation/RegexDesensitize.java (100%) rename yudao-framework/{yudao-spring-boot-starter-desensitize => yudao-spring-boot-starter-web}/src/main/java/cn/iocoder/yudao/framework/desensitize/core/regex/handler/AbstractRegexDesensitizationHandler.java (100%) rename yudao-framework/{yudao-spring-boot-starter-desensitize => yudao-spring-boot-starter-web}/src/main/java/cn/iocoder/yudao/framework/desensitize/core/regex/handler/DefaultRegexDesensitizationHandler.java (100%) rename yudao-framework/{yudao-spring-boot-starter-desensitize => yudao-spring-boot-starter-web}/src/main/java/cn/iocoder/yudao/framework/desensitize/core/regex/handler/EmailDesensitizationHandler.java (100%) rename yudao-framework/{yudao-spring-boot-starter-desensitize => yudao-spring-boot-starter-web}/src/main/java/cn/iocoder/yudao/framework/desensitize/core/slider/annotation/BankCardDesensitize.java (100%) rename yudao-framework/{yudao-spring-boot-starter-desensitize => yudao-spring-boot-starter-web}/src/main/java/cn/iocoder/yudao/framework/desensitize/core/slider/annotation/CarLicenseDesensitize.java (100%) rename yudao-framework/{yudao-spring-boot-starter-desensitize => yudao-spring-boot-starter-web}/src/main/java/cn/iocoder/yudao/framework/desensitize/core/slider/annotation/ChineseNameDesensitize.java (100%) rename yudao-framework/{yudao-spring-boot-starter-desensitize => yudao-spring-boot-starter-web}/src/main/java/cn/iocoder/yudao/framework/desensitize/core/slider/annotation/FixedPhoneDesensitize.java (100%) rename yudao-framework/{yudao-spring-boot-starter-desensitize => yudao-spring-boot-starter-web}/src/main/java/cn/iocoder/yudao/framework/desensitize/core/slider/annotation/IdCardDesensitize.java (100%) rename yudao-framework/{yudao-spring-boot-starter-desensitize => yudao-spring-boot-starter-web}/src/main/java/cn/iocoder/yudao/framework/desensitize/core/slider/annotation/MobileDesensitize.java (100%) rename yudao-framework/{yudao-spring-boot-starter-desensitize => yudao-spring-boot-starter-web}/src/main/java/cn/iocoder/yudao/framework/desensitize/core/slider/annotation/PasswordDesensitize.java (100%) rename yudao-framework/{yudao-spring-boot-starter-desensitize => yudao-spring-boot-starter-web}/src/main/java/cn/iocoder/yudao/framework/desensitize/core/slider/annotation/SliderDesensitize.java (100%) rename yudao-framework/{yudao-spring-boot-starter-desensitize => yudao-spring-boot-starter-web}/src/main/java/cn/iocoder/yudao/framework/desensitize/core/slider/handler/AbstractSliderDesensitizationHandler.java (100%) rename yudao-framework/{yudao-spring-boot-starter-desensitize => yudao-spring-boot-starter-web}/src/main/java/cn/iocoder/yudao/framework/desensitize/core/slider/handler/BankCardDesensitization.java (100%) rename yudao-framework/{yudao-spring-boot-starter-desensitize => yudao-spring-boot-starter-web}/src/main/java/cn/iocoder/yudao/framework/desensitize/core/slider/handler/CarLicenseDesensitization.java (100%) rename yudao-framework/{yudao-spring-boot-starter-desensitize => yudao-spring-boot-starter-web}/src/main/java/cn/iocoder/yudao/framework/desensitize/core/slider/handler/ChineseNameDesensitization.java (100%) rename yudao-framework/{yudao-spring-boot-starter-desensitize => yudao-spring-boot-starter-web}/src/main/java/cn/iocoder/yudao/framework/desensitize/core/slider/handler/DefaultDesensitizationHandler.java (100%) rename yudao-framework/{yudao-spring-boot-starter-desensitize => yudao-spring-boot-starter-web}/src/main/java/cn/iocoder/yudao/framework/desensitize/core/slider/handler/FixedPhoneDesensitization.java (100%) rename yudao-framework/{yudao-spring-boot-starter-desensitize => yudao-spring-boot-starter-web}/src/main/java/cn/iocoder/yudao/framework/desensitize/core/slider/handler/IdCardDesensitization.java (100%) rename yudao-framework/{yudao-spring-boot-starter-desensitize => yudao-spring-boot-starter-web}/src/main/java/cn/iocoder/yudao/framework/desensitize/core/slider/handler/MobileDesensitization.java (100%) rename yudao-framework/{yudao-spring-boot-starter-desensitize => yudao-spring-boot-starter-web}/src/main/java/cn/iocoder/yudao/framework/desensitize/core/slider/handler/PasswordDesensitization.java (100%) rename yudao-framework/{yudao-spring-boot-starter-desensitize/src/main/java/cn/iocoder/yudao/framework/desensitize/core => yudao-spring-boot-starter-web/src/main/java/cn/iocoder/yudao/framework/desensitize}/package-info.java (64%) rename yudao-framework/{yudao-spring-boot-starter-biz-error-code => yudao-spring-boot-starter-web}/src/main/java/cn/iocoder/yudao/framework/errorcode/config/ErrorCodeProperties.java (100%) rename yudao-framework/{yudao-spring-boot-starter-biz-error-code => yudao-spring-boot-starter-web}/src/main/java/cn/iocoder/yudao/framework/errorcode/config/YudaoErrorCodeAutoConfiguration.java (100%) rename yudao-framework/{yudao-spring-boot-starter-biz-error-code => yudao-spring-boot-starter-web}/src/main/java/cn/iocoder/yudao/framework/errorcode/core/generator/ErrorCodeAutoGenerator.java (100%) rename yudao-framework/{yudao-spring-boot-starter-biz-error-code => yudao-spring-boot-starter-web}/src/main/java/cn/iocoder/yudao/framework/errorcode/core/generator/ErrorCodeAutoGeneratorImpl.java (100%) rename yudao-framework/{yudao-spring-boot-starter-biz-error-code => yudao-spring-boot-starter-web}/src/main/java/cn/iocoder/yudao/framework/errorcode/core/loader/ErrorCodeLoader.java (100%) rename yudao-framework/{yudao-spring-boot-starter-biz-error-code => yudao-spring-boot-starter-web}/src/main/java/cn/iocoder/yudao/framework/errorcode/core/loader/ErrorCodeLoaderImpl.java (100%) rename yudao-framework/{yudao-spring-boot-starter-biz-error-code => yudao-spring-boot-starter-web}/src/main/java/cn/iocoder/yudao/framework/errorcode/package-info.java (100%) rename yudao-framework/{yudao-spring-boot-starter-banner => yudao-spring-boot-starter-web}/src/main/resources/banner.txt (100%) rename yudao-framework/{yudao-spring-boot-starter-desensitize => yudao-spring-boot-starter-web}/src/test/java/cn/iocoder/yudao/framework/desensitize/core/DesensitizeTest.java (80%) rename yudao-framework/{yudao-spring-boot-starter-desensitize => yudao-spring-boot-starter-web}/src/test/java/cn/iocoder/yudao/framework/desensitize/core/annotation/Address.java (100%) rename yudao-framework/{yudao-spring-boot-starter-desensitize => yudao-spring-boot-starter-web}/src/test/java/cn/iocoder/yudao/framework/desensitize/core/handler/AddressHandler.java (100%) diff --git a/yudao-dependencies/pom.xml b/yudao-dependencies/pom.xml index 6614202f2..a23f602be 100644 --- a/yudao-dependencies/pom.xml +++ b/yudao-dependencies/pom.xml @@ -90,11 +90,6 @@ - - cn.iocoder.boot - yudao-spring-boot-starter-banner - ${revision} - cn.iocoder.boot yudao-spring-boot-starter-biz-operatelog @@ -136,11 +131,6 @@ yudao-spring-boot-starter-biz-data-permission ${revision} - - cn.iocoder.boot - yudao-spring-boot-starter-biz-error-code - ${revision} - cn.iocoder.boot yudao-spring-boot-starter-biz-ip diff --git a/yudao-framework/pom.xml b/yudao-framework/pom.xml index 6a8212314..3e98ea301 100644 --- a/yudao-framework/pom.xml +++ b/yudao-framework/pom.xml @@ -11,7 +11,6 @@ pom yudao-common - yudao-spring-boot-starter-banner yudao-spring-boot-starter-mybatis yudao-spring-boot-starter-redis yudao-spring-boot-starter-web @@ -33,13 +32,11 @@ yudao-spring-boot-starter-biz-pay yudao-spring-boot-starter-biz-tenant yudao-spring-boot-starter-biz-data-permission - yudao-spring-boot-starter-biz-error-code yudao-spring-boot-starter-biz-ip yudao-spring-boot-starter-flowable yudao-spring-boot-starter-captcha yudao-spring-boot-starter-websocket - yudao-spring-boot-starter-desensitize yudao-framework diff --git a/yudao-framework/yudao-spring-boot-starter-banner/pom.xml b/yudao-framework/yudao-spring-boot-starter-banner/pom.xml deleted file mode 100644 index e740fce5f..000000000 --- a/yudao-framework/yudao-spring-boot-starter-banner/pom.xml +++ /dev/null @@ -1,30 +0,0 @@ - - - - yudao-framework - cn.iocoder.boot - ${revision} - - 4.0.0 - yudao-spring-boot-starter-banner - jar - - ${project.artifactId} - Banner 用于在 console 控制台,打印开发文档、接口文档等 - https://github.com/YunaiV/ruoyi-vue-pro - - - - cn.iocoder.boot - yudao-common - - - - org.springframework.boot - spring-boot-starter - - - - diff --git a/yudao-framework/yudao-spring-boot-starter-banner/src/main/resources/META-INF/spring/org.springframework.boot.autoconfigure.AutoConfiguration.imports b/yudao-framework/yudao-spring-boot-starter-banner/src/main/resources/META-INF/spring/org.springframework.boot.autoconfigure.AutoConfiguration.imports deleted file mode 100644 index e04c9b42c..000000000 --- a/yudao-framework/yudao-spring-boot-starter-banner/src/main/resources/META-INF/spring/org.springframework.boot.autoconfigure.AutoConfiguration.imports +++ /dev/null @@ -1 +0,0 @@ -cn.iocoder.yudao.framework.banner.config.YudaoBannerAutoConfiguration \ No newline at end of file diff --git a/yudao-framework/yudao-spring-boot-starter-biz-error-code/pom.xml b/yudao-framework/yudao-spring-boot-starter-biz-error-code/pom.xml deleted file mode 100644 index 06e41c1eb..000000000 --- a/yudao-framework/yudao-spring-boot-starter-biz-error-code/pom.xml +++ /dev/null @@ -1,49 +0,0 @@ - - - - yudao-framework - cn.iocoder.boot - ${revision} - - 4.0.0 - yudao-spring-boot-starter-biz-error-code - jar - - ${project.artifactId} - - 错误码 ErrorCode 的自动配置功能,提供如下功能: - 1. 远程读取:项目启动时,从 system-server 服务,读取数据库中的 ErrorCode 错误码,实现错误码的提示可配置; - 2. 自动更新:管理员在管理后台修数据库中的 ErrorCode 错误码时,项目自动从 system-server 服务加载最新的 ErrorCode 错误码; - 3. 自动写入:项目启动时,将项目本地的错误码写到 system-server 服务中,方便管理员在管理后台编辑; - - https://github.com/YunaiV/ruoyi-vue-pro - - - - cn.iocoder.boot - yudao-common - - - - - org.springframework.boot - spring-boot-starter - - - - - cn.iocoder.boot - yudao-module-system-api - ${revision} - - - - jakarta.validation - jakarta.validation-api - provided - - - - diff --git a/yudao-framework/yudao-spring-boot-starter-biz-error-code/src/main/resources/META-INF/spring/org.springframework.boot.autoconfigure.AutoConfiguration.imports b/yudao-framework/yudao-spring-boot-starter-biz-error-code/src/main/resources/META-INF/spring/org.springframework.boot.autoconfigure.AutoConfiguration.imports deleted file mode 100644 index ecd3f7183..000000000 --- a/yudao-framework/yudao-spring-boot-starter-biz-error-code/src/main/resources/META-INF/spring/org.springframework.boot.autoconfigure.AutoConfiguration.imports +++ /dev/null @@ -1 +0,0 @@ -cn.iocoder.yudao.framework.errorcode.config.YudaoErrorCodeAutoConfiguration diff --git a/yudao-framework/yudao-spring-boot-starter-desensitize/pom.xml b/yudao-framework/yudao-spring-boot-starter-desensitize/pom.xml deleted file mode 100644 index c4a96ebe1..000000000 --- a/yudao-framework/yudao-spring-boot-starter-desensitize/pom.xml +++ /dev/null @@ -1,38 +0,0 @@ - - - 4.0.0 - - yudao-framework - cn.iocoder.boot - ${revision} - - - yudao-spring-boot-starter-desensitize - 脱敏组件:支持 JSON 返回数据时,将邮箱、手机等字段进行脱敏 - - - - cn.iocoder.boot - yudao-common - - - - - com.fasterxml.jackson.core - jackson-annotations - - - com.fasterxml.jackson.core - jackson-databind - - - - - cn.iocoder.boot - yudao-spring-boot-starter-test - test - - - diff --git a/yudao-framework/yudao-spring-boot-starter-web/pom.xml b/yudao-framework/yudao-spring-boot-starter-web/pom.xml index fbffa750e..b5d0aa84d 100644 --- a/yudao-framework/yudao-spring-boot-starter-web/pom.xml +++ b/yudao-framework/yudao-spring-boot-starter-web/pom.xml @@ -12,7 +12,7 @@ jar ${project.artifactId} - Web 框架,全局异常、API 日志等 + Web 框架,全局异常、API 日志、脱敏、错误码等 https://github.com/YunaiV/ruoyi-vue-pro @@ -54,6 +54,11 @@ yudao-module-infra-api ${revision} + + cn.iocoder.boot + yudao-module-system-api + ${revision} + @@ -61,6 +66,17 @@ jsoup + + + org.springframework.boot + spring-boot-starter-test + test + + + org.mockito + mockito-inline + test + diff --git a/yudao-framework/yudao-spring-boot-starter-banner/src/main/java/cn/iocoder/yudao/framework/banner/config/YudaoBannerAutoConfiguration.java b/yudao-framework/yudao-spring-boot-starter-web/src/main/java/cn/iocoder/yudao/framework/banner/config/YudaoBannerAutoConfiguration.java similarity index 100% rename from yudao-framework/yudao-spring-boot-starter-banner/src/main/java/cn/iocoder/yudao/framework/banner/config/YudaoBannerAutoConfiguration.java rename to yudao-framework/yudao-spring-boot-starter-web/src/main/java/cn/iocoder/yudao/framework/banner/config/YudaoBannerAutoConfiguration.java diff --git a/yudao-framework/yudao-spring-boot-starter-banner/src/main/java/cn/iocoder/yudao/framework/banner/core/BannerApplicationRunner.java b/yudao-framework/yudao-spring-boot-starter-web/src/main/java/cn/iocoder/yudao/framework/banner/core/BannerApplicationRunner.java similarity index 100% rename from yudao-framework/yudao-spring-boot-starter-banner/src/main/java/cn/iocoder/yudao/framework/banner/core/BannerApplicationRunner.java rename to yudao-framework/yudao-spring-boot-starter-web/src/main/java/cn/iocoder/yudao/framework/banner/core/BannerApplicationRunner.java diff --git a/yudao-framework/yudao-spring-boot-starter-banner/src/main/java/cn/iocoder/yudao/framework/banner/package-info.java b/yudao-framework/yudao-spring-boot-starter-web/src/main/java/cn/iocoder/yudao/framework/banner/package-info.java similarity index 100% rename from yudao-framework/yudao-spring-boot-starter-banner/src/main/java/cn/iocoder/yudao/framework/banner/package-info.java rename to yudao-framework/yudao-spring-boot-starter-web/src/main/java/cn/iocoder/yudao/framework/banner/package-info.java diff --git a/yudao-framework/yudao-spring-boot-starter-desensitize/src/main/java/cn/iocoder/yudao/framework/desensitize/core/base/annotation/DesensitizeBy.java b/yudao-framework/yudao-spring-boot-starter-web/src/main/java/cn/iocoder/yudao/framework/desensitize/core/base/annotation/DesensitizeBy.java similarity index 100% rename from yudao-framework/yudao-spring-boot-starter-desensitize/src/main/java/cn/iocoder/yudao/framework/desensitize/core/base/annotation/DesensitizeBy.java rename to yudao-framework/yudao-spring-boot-starter-web/src/main/java/cn/iocoder/yudao/framework/desensitize/core/base/annotation/DesensitizeBy.java diff --git a/yudao-framework/yudao-spring-boot-starter-desensitize/src/main/java/cn/iocoder/yudao/framework/desensitize/core/base/handler/DesensitizationHandler.java b/yudao-framework/yudao-spring-boot-starter-web/src/main/java/cn/iocoder/yudao/framework/desensitize/core/base/handler/DesensitizationHandler.java similarity index 100% rename from yudao-framework/yudao-spring-boot-starter-desensitize/src/main/java/cn/iocoder/yudao/framework/desensitize/core/base/handler/DesensitizationHandler.java rename to yudao-framework/yudao-spring-boot-starter-web/src/main/java/cn/iocoder/yudao/framework/desensitize/core/base/handler/DesensitizationHandler.java diff --git a/yudao-framework/yudao-spring-boot-starter-desensitize/src/main/java/cn/iocoder/yudao/framework/desensitize/core/base/serializer/StringDesensitizeSerializer.java b/yudao-framework/yudao-spring-boot-starter-web/src/main/java/cn/iocoder/yudao/framework/desensitize/core/base/serializer/StringDesensitizeSerializer.java similarity index 100% rename from yudao-framework/yudao-spring-boot-starter-desensitize/src/main/java/cn/iocoder/yudao/framework/desensitize/core/base/serializer/StringDesensitizeSerializer.java rename to yudao-framework/yudao-spring-boot-starter-web/src/main/java/cn/iocoder/yudao/framework/desensitize/core/base/serializer/StringDesensitizeSerializer.java diff --git a/yudao-framework/yudao-spring-boot-starter-desensitize/src/main/java/cn/iocoder/yudao/framework/desensitize/core/regex/annotation/EmailDesensitize.java b/yudao-framework/yudao-spring-boot-starter-web/src/main/java/cn/iocoder/yudao/framework/desensitize/core/regex/annotation/EmailDesensitize.java similarity index 100% rename from yudao-framework/yudao-spring-boot-starter-desensitize/src/main/java/cn/iocoder/yudao/framework/desensitize/core/regex/annotation/EmailDesensitize.java rename to yudao-framework/yudao-spring-boot-starter-web/src/main/java/cn/iocoder/yudao/framework/desensitize/core/regex/annotation/EmailDesensitize.java diff --git a/yudao-framework/yudao-spring-boot-starter-desensitize/src/main/java/cn/iocoder/yudao/framework/desensitize/core/regex/annotation/RegexDesensitize.java b/yudao-framework/yudao-spring-boot-starter-web/src/main/java/cn/iocoder/yudao/framework/desensitize/core/regex/annotation/RegexDesensitize.java similarity index 100% rename from yudao-framework/yudao-spring-boot-starter-desensitize/src/main/java/cn/iocoder/yudao/framework/desensitize/core/regex/annotation/RegexDesensitize.java rename to yudao-framework/yudao-spring-boot-starter-web/src/main/java/cn/iocoder/yudao/framework/desensitize/core/regex/annotation/RegexDesensitize.java diff --git a/yudao-framework/yudao-spring-boot-starter-desensitize/src/main/java/cn/iocoder/yudao/framework/desensitize/core/regex/handler/AbstractRegexDesensitizationHandler.java b/yudao-framework/yudao-spring-boot-starter-web/src/main/java/cn/iocoder/yudao/framework/desensitize/core/regex/handler/AbstractRegexDesensitizationHandler.java similarity index 100% rename from yudao-framework/yudao-spring-boot-starter-desensitize/src/main/java/cn/iocoder/yudao/framework/desensitize/core/regex/handler/AbstractRegexDesensitizationHandler.java rename to yudao-framework/yudao-spring-boot-starter-web/src/main/java/cn/iocoder/yudao/framework/desensitize/core/regex/handler/AbstractRegexDesensitizationHandler.java diff --git a/yudao-framework/yudao-spring-boot-starter-desensitize/src/main/java/cn/iocoder/yudao/framework/desensitize/core/regex/handler/DefaultRegexDesensitizationHandler.java b/yudao-framework/yudao-spring-boot-starter-web/src/main/java/cn/iocoder/yudao/framework/desensitize/core/regex/handler/DefaultRegexDesensitizationHandler.java similarity index 100% rename from yudao-framework/yudao-spring-boot-starter-desensitize/src/main/java/cn/iocoder/yudao/framework/desensitize/core/regex/handler/DefaultRegexDesensitizationHandler.java rename to yudao-framework/yudao-spring-boot-starter-web/src/main/java/cn/iocoder/yudao/framework/desensitize/core/regex/handler/DefaultRegexDesensitizationHandler.java diff --git a/yudao-framework/yudao-spring-boot-starter-desensitize/src/main/java/cn/iocoder/yudao/framework/desensitize/core/regex/handler/EmailDesensitizationHandler.java b/yudao-framework/yudao-spring-boot-starter-web/src/main/java/cn/iocoder/yudao/framework/desensitize/core/regex/handler/EmailDesensitizationHandler.java similarity index 100% rename from yudao-framework/yudao-spring-boot-starter-desensitize/src/main/java/cn/iocoder/yudao/framework/desensitize/core/regex/handler/EmailDesensitizationHandler.java rename to yudao-framework/yudao-spring-boot-starter-web/src/main/java/cn/iocoder/yudao/framework/desensitize/core/regex/handler/EmailDesensitizationHandler.java diff --git a/yudao-framework/yudao-spring-boot-starter-desensitize/src/main/java/cn/iocoder/yudao/framework/desensitize/core/slider/annotation/BankCardDesensitize.java b/yudao-framework/yudao-spring-boot-starter-web/src/main/java/cn/iocoder/yudao/framework/desensitize/core/slider/annotation/BankCardDesensitize.java similarity index 100% rename from yudao-framework/yudao-spring-boot-starter-desensitize/src/main/java/cn/iocoder/yudao/framework/desensitize/core/slider/annotation/BankCardDesensitize.java rename to yudao-framework/yudao-spring-boot-starter-web/src/main/java/cn/iocoder/yudao/framework/desensitize/core/slider/annotation/BankCardDesensitize.java diff --git a/yudao-framework/yudao-spring-boot-starter-desensitize/src/main/java/cn/iocoder/yudao/framework/desensitize/core/slider/annotation/CarLicenseDesensitize.java b/yudao-framework/yudao-spring-boot-starter-web/src/main/java/cn/iocoder/yudao/framework/desensitize/core/slider/annotation/CarLicenseDesensitize.java similarity index 100% rename from yudao-framework/yudao-spring-boot-starter-desensitize/src/main/java/cn/iocoder/yudao/framework/desensitize/core/slider/annotation/CarLicenseDesensitize.java rename to yudao-framework/yudao-spring-boot-starter-web/src/main/java/cn/iocoder/yudao/framework/desensitize/core/slider/annotation/CarLicenseDesensitize.java diff --git a/yudao-framework/yudao-spring-boot-starter-desensitize/src/main/java/cn/iocoder/yudao/framework/desensitize/core/slider/annotation/ChineseNameDesensitize.java b/yudao-framework/yudao-spring-boot-starter-web/src/main/java/cn/iocoder/yudao/framework/desensitize/core/slider/annotation/ChineseNameDesensitize.java similarity index 100% rename from yudao-framework/yudao-spring-boot-starter-desensitize/src/main/java/cn/iocoder/yudao/framework/desensitize/core/slider/annotation/ChineseNameDesensitize.java rename to yudao-framework/yudao-spring-boot-starter-web/src/main/java/cn/iocoder/yudao/framework/desensitize/core/slider/annotation/ChineseNameDesensitize.java diff --git a/yudao-framework/yudao-spring-boot-starter-desensitize/src/main/java/cn/iocoder/yudao/framework/desensitize/core/slider/annotation/FixedPhoneDesensitize.java b/yudao-framework/yudao-spring-boot-starter-web/src/main/java/cn/iocoder/yudao/framework/desensitize/core/slider/annotation/FixedPhoneDesensitize.java similarity index 100% rename from yudao-framework/yudao-spring-boot-starter-desensitize/src/main/java/cn/iocoder/yudao/framework/desensitize/core/slider/annotation/FixedPhoneDesensitize.java rename to yudao-framework/yudao-spring-boot-starter-web/src/main/java/cn/iocoder/yudao/framework/desensitize/core/slider/annotation/FixedPhoneDesensitize.java diff --git a/yudao-framework/yudao-spring-boot-starter-desensitize/src/main/java/cn/iocoder/yudao/framework/desensitize/core/slider/annotation/IdCardDesensitize.java b/yudao-framework/yudao-spring-boot-starter-web/src/main/java/cn/iocoder/yudao/framework/desensitize/core/slider/annotation/IdCardDesensitize.java similarity index 100% rename from yudao-framework/yudao-spring-boot-starter-desensitize/src/main/java/cn/iocoder/yudao/framework/desensitize/core/slider/annotation/IdCardDesensitize.java rename to yudao-framework/yudao-spring-boot-starter-web/src/main/java/cn/iocoder/yudao/framework/desensitize/core/slider/annotation/IdCardDesensitize.java diff --git a/yudao-framework/yudao-spring-boot-starter-desensitize/src/main/java/cn/iocoder/yudao/framework/desensitize/core/slider/annotation/MobileDesensitize.java b/yudao-framework/yudao-spring-boot-starter-web/src/main/java/cn/iocoder/yudao/framework/desensitize/core/slider/annotation/MobileDesensitize.java similarity index 100% rename from yudao-framework/yudao-spring-boot-starter-desensitize/src/main/java/cn/iocoder/yudao/framework/desensitize/core/slider/annotation/MobileDesensitize.java rename to yudao-framework/yudao-spring-boot-starter-web/src/main/java/cn/iocoder/yudao/framework/desensitize/core/slider/annotation/MobileDesensitize.java diff --git a/yudao-framework/yudao-spring-boot-starter-desensitize/src/main/java/cn/iocoder/yudao/framework/desensitize/core/slider/annotation/PasswordDesensitize.java b/yudao-framework/yudao-spring-boot-starter-web/src/main/java/cn/iocoder/yudao/framework/desensitize/core/slider/annotation/PasswordDesensitize.java similarity index 100% rename from yudao-framework/yudao-spring-boot-starter-desensitize/src/main/java/cn/iocoder/yudao/framework/desensitize/core/slider/annotation/PasswordDesensitize.java rename to yudao-framework/yudao-spring-boot-starter-web/src/main/java/cn/iocoder/yudao/framework/desensitize/core/slider/annotation/PasswordDesensitize.java diff --git a/yudao-framework/yudao-spring-boot-starter-desensitize/src/main/java/cn/iocoder/yudao/framework/desensitize/core/slider/annotation/SliderDesensitize.java b/yudao-framework/yudao-spring-boot-starter-web/src/main/java/cn/iocoder/yudao/framework/desensitize/core/slider/annotation/SliderDesensitize.java similarity index 100% rename from yudao-framework/yudao-spring-boot-starter-desensitize/src/main/java/cn/iocoder/yudao/framework/desensitize/core/slider/annotation/SliderDesensitize.java rename to yudao-framework/yudao-spring-boot-starter-web/src/main/java/cn/iocoder/yudao/framework/desensitize/core/slider/annotation/SliderDesensitize.java diff --git a/yudao-framework/yudao-spring-boot-starter-desensitize/src/main/java/cn/iocoder/yudao/framework/desensitize/core/slider/handler/AbstractSliderDesensitizationHandler.java b/yudao-framework/yudao-spring-boot-starter-web/src/main/java/cn/iocoder/yudao/framework/desensitize/core/slider/handler/AbstractSliderDesensitizationHandler.java similarity index 100% rename from yudao-framework/yudao-spring-boot-starter-desensitize/src/main/java/cn/iocoder/yudao/framework/desensitize/core/slider/handler/AbstractSliderDesensitizationHandler.java rename to yudao-framework/yudao-spring-boot-starter-web/src/main/java/cn/iocoder/yudao/framework/desensitize/core/slider/handler/AbstractSliderDesensitizationHandler.java diff --git a/yudao-framework/yudao-spring-boot-starter-desensitize/src/main/java/cn/iocoder/yudao/framework/desensitize/core/slider/handler/BankCardDesensitization.java b/yudao-framework/yudao-spring-boot-starter-web/src/main/java/cn/iocoder/yudao/framework/desensitize/core/slider/handler/BankCardDesensitization.java similarity index 100% rename from yudao-framework/yudao-spring-boot-starter-desensitize/src/main/java/cn/iocoder/yudao/framework/desensitize/core/slider/handler/BankCardDesensitization.java rename to yudao-framework/yudao-spring-boot-starter-web/src/main/java/cn/iocoder/yudao/framework/desensitize/core/slider/handler/BankCardDesensitization.java diff --git a/yudao-framework/yudao-spring-boot-starter-desensitize/src/main/java/cn/iocoder/yudao/framework/desensitize/core/slider/handler/CarLicenseDesensitization.java b/yudao-framework/yudao-spring-boot-starter-web/src/main/java/cn/iocoder/yudao/framework/desensitize/core/slider/handler/CarLicenseDesensitization.java similarity index 100% rename from yudao-framework/yudao-spring-boot-starter-desensitize/src/main/java/cn/iocoder/yudao/framework/desensitize/core/slider/handler/CarLicenseDesensitization.java rename to yudao-framework/yudao-spring-boot-starter-web/src/main/java/cn/iocoder/yudao/framework/desensitize/core/slider/handler/CarLicenseDesensitization.java diff --git a/yudao-framework/yudao-spring-boot-starter-desensitize/src/main/java/cn/iocoder/yudao/framework/desensitize/core/slider/handler/ChineseNameDesensitization.java b/yudao-framework/yudao-spring-boot-starter-web/src/main/java/cn/iocoder/yudao/framework/desensitize/core/slider/handler/ChineseNameDesensitization.java similarity index 100% rename from yudao-framework/yudao-spring-boot-starter-desensitize/src/main/java/cn/iocoder/yudao/framework/desensitize/core/slider/handler/ChineseNameDesensitization.java rename to yudao-framework/yudao-spring-boot-starter-web/src/main/java/cn/iocoder/yudao/framework/desensitize/core/slider/handler/ChineseNameDesensitization.java diff --git a/yudao-framework/yudao-spring-boot-starter-desensitize/src/main/java/cn/iocoder/yudao/framework/desensitize/core/slider/handler/DefaultDesensitizationHandler.java b/yudao-framework/yudao-spring-boot-starter-web/src/main/java/cn/iocoder/yudao/framework/desensitize/core/slider/handler/DefaultDesensitizationHandler.java similarity index 100% rename from yudao-framework/yudao-spring-boot-starter-desensitize/src/main/java/cn/iocoder/yudao/framework/desensitize/core/slider/handler/DefaultDesensitizationHandler.java rename to yudao-framework/yudao-spring-boot-starter-web/src/main/java/cn/iocoder/yudao/framework/desensitize/core/slider/handler/DefaultDesensitizationHandler.java diff --git a/yudao-framework/yudao-spring-boot-starter-desensitize/src/main/java/cn/iocoder/yudao/framework/desensitize/core/slider/handler/FixedPhoneDesensitization.java b/yudao-framework/yudao-spring-boot-starter-web/src/main/java/cn/iocoder/yudao/framework/desensitize/core/slider/handler/FixedPhoneDesensitization.java similarity index 100% rename from yudao-framework/yudao-spring-boot-starter-desensitize/src/main/java/cn/iocoder/yudao/framework/desensitize/core/slider/handler/FixedPhoneDesensitization.java rename to yudao-framework/yudao-spring-boot-starter-web/src/main/java/cn/iocoder/yudao/framework/desensitize/core/slider/handler/FixedPhoneDesensitization.java diff --git a/yudao-framework/yudao-spring-boot-starter-desensitize/src/main/java/cn/iocoder/yudao/framework/desensitize/core/slider/handler/IdCardDesensitization.java b/yudao-framework/yudao-spring-boot-starter-web/src/main/java/cn/iocoder/yudao/framework/desensitize/core/slider/handler/IdCardDesensitization.java similarity index 100% rename from yudao-framework/yudao-spring-boot-starter-desensitize/src/main/java/cn/iocoder/yudao/framework/desensitize/core/slider/handler/IdCardDesensitization.java rename to yudao-framework/yudao-spring-boot-starter-web/src/main/java/cn/iocoder/yudao/framework/desensitize/core/slider/handler/IdCardDesensitization.java diff --git a/yudao-framework/yudao-spring-boot-starter-desensitize/src/main/java/cn/iocoder/yudao/framework/desensitize/core/slider/handler/MobileDesensitization.java b/yudao-framework/yudao-spring-boot-starter-web/src/main/java/cn/iocoder/yudao/framework/desensitize/core/slider/handler/MobileDesensitization.java similarity index 100% rename from yudao-framework/yudao-spring-boot-starter-desensitize/src/main/java/cn/iocoder/yudao/framework/desensitize/core/slider/handler/MobileDesensitization.java rename to yudao-framework/yudao-spring-boot-starter-web/src/main/java/cn/iocoder/yudao/framework/desensitize/core/slider/handler/MobileDesensitization.java diff --git a/yudao-framework/yudao-spring-boot-starter-desensitize/src/main/java/cn/iocoder/yudao/framework/desensitize/core/slider/handler/PasswordDesensitization.java b/yudao-framework/yudao-spring-boot-starter-web/src/main/java/cn/iocoder/yudao/framework/desensitize/core/slider/handler/PasswordDesensitization.java similarity index 100% rename from yudao-framework/yudao-spring-boot-starter-desensitize/src/main/java/cn/iocoder/yudao/framework/desensitize/core/slider/handler/PasswordDesensitization.java rename to yudao-framework/yudao-spring-boot-starter-web/src/main/java/cn/iocoder/yudao/framework/desensitize/core/slider/handler/PasswordDesensitization.java diff --git a/yudao-framework/yudao-spring-boot-starter-desensitize/src/main/java/cn/iocoder/yudao/framework/desensitize/core/package-info.java b/yudao-framework/yudao-spring-boot-starter-web/src/main/java/cn/iocoder/yudao/framework/desensitize/package-info.java similarity index 64% rename from yudao-framework/yudao-spring-boot-starter-desensitize/src/main/java/cn/iocoder/yudao/framework/desensitize/core/package-info.java rename to yudao-framework/yudao-spring-boot-starter-web/src/main/java/cn/iocoder/yudao/framework/desensitize/package-info.java index d56282535..bfe0187be 100644 --- a/yudao-framework/yudao-spring-boot-starter-desensitize/src/main/java/cn/iocoder/yudao/framework/desensitize/core/package-info.java +++ b/yudao-framework/yudao-spring-boot-starter-web/src/main/java/cn/iocoder/yudao/framework/desensitize/package-info.java @@ -1,4 +1,4 @@ /** * 脱敏组件:支持 JSON 返回数据时,将邮箱、手机等字段进行脱敏 */ -package cn.iocoder.yudao.framework.desensitize.core; +package cn.iocoder.yudao.framework.desensitize; diff --git a/yudao-framework/yudao-spring-boot-starter-biz-error-code/src/main/java/cn/iocoder/yudao/framework/errorcode/config/ErrorCodeProperties.java b/yudao-framework/yudao-spring-boot-starter-web/src/main/java/cn/iocoder/yudao/framework/errorcode/config/ErrorCodeProperties.java similarity index 100% rename from yudao-framework/yudao-spring-boot-starter-biz-error-code/src/main/java/cn/iocoder/yudao/framework/errorcode/config/ErrorCodeProperties.java rename to yudao-framework/yudao-spring-boot-starter-web/src/main/java/cn/iocoder/yudao/framework/errorcode/config/ErrorCodeProperties.java diff --git a/yudao-framework/yudao-spring-boot-starter-biz-error-code/src/main/java/cn/iocoder/yudao/framework/errorcode/config/YudaoErrorCodeAutoConfiguration.java b/yudao-framework/yudao-spring-boot-starter-web/src/main/java/cn/iocoder/yudao/framework/errorcode/config/YudaoErrorCodeAutoConfiguration.java similarity index 100% rename from yudao-framework/yudao-spring-boot-starter-biz-error-code/src/main/java/cn/iocoder/yudao/framework/errorcode/config/YudaoErrorCodeAutoConfiguration.java rename to yudao-framework/yudao-spring-boot-starter-web/src/main/java/cn/iocoder/yudao/framework/errorcode/config/YudaoErrorCodeAutoConfiguration.java diff --git a/yudao-framework/yudao-spring-boot-starter-biz-error-code/src/main/java/cn/iocoder/yudao/framework/errorcode/core/generator/ErrorCodeAutoGenerator.java b/yudao-framework/yudao-spring-boot-starter-web/src/main/java/cn/iocoder/yudao/framework/errorcode/core/generator/ErrorCodeAutoGenerator.java similarity index 100% rename from yudao-framework/yudao-spring-boot-starter-biz-error-code/src/main/java/cn/iocoder/yudao/framework/errorcode/core/generator/ErrorCodeAutoGenerator.java rename to yudao-framework/yudao-spring-boot-starter-web/src/main/java/cn/iocoder/yudao/framework/errorcode/core/generator/ErrorCodeAutoGenerator.java diff --git a/yudao-framework/yudao-spring-boot-starter-biz-error-code/src/main/java/cn/iocoder/yudao/framework/errorcode/core/generator/ErrorCodeAutoGeneratorImpl.java b/yudao-framework/yudao-spring-boot-starter-web/src/main/java/cn/iocoder/yudao/framework/errorcode/core/generator/ErrorCodeAutoGeneratorImpl.java similarity index 100% rename from yudao-framework/yudao-spring-boot-starter-biz-error-code/src/main/java/cn/iocoder/yudao/framework/errorcode/core/generator/ErrorCodeAutoGeneratorImpl.java rename to yudao-framework/yudao-spring-boot-starter-web/src/main/java/cn/iocoder/yudao/framework/errorcode/core/generator/ErrorCodeAutoGeneratorImpl.java diff --git a/yudao-framework/yudao-spring-boot-starter-biz-error-code/src/main/java/cn/iocoder/yudao/framework/errorcode/core/loader/ErrorCodeLoader.java b/yudao-framework/yudao-spring-boot-starter-web/src/main/java/cn/iocoder/yudao/framework/errorcode/core/loader/ErrorCodeLoader.java similarity index 100% rename from yudao-framework/yudao-spring-boot-starter-biz-error-code/src/main/java/cn/iocoder/yudao/framework/errorcode/core/loader/ErrorCodeLoader.java rename to yudao-framework/yudao-spring-boot-starter-web/src/main/java/cn/iocoder/yudao/framework/errorcode/core/loader/ErrorCodeLoader.java diff --git a/yudao-framework/yudao-spring-boot-starter-biz-error-code/src/main/java/cn/iocoder/yudao/framework/errorcode/core/loader/ErrorCodeLoaderImpl.java b/yudao-framework/yudao-spring-boot-starter-web/src/main/java/cn/iocoder/yudao/framework/errorcode/core/loader/ErrorCodeLoaderImpl.java similarity index 100% rename from yudao-framework/yudao-spring-boot-starter-biz-error-code/src/main/java/cn/iocoder/yudao/framework/errorcode/core/loader/ErrorCodeLoaderImpl.java rename to yudao-framework/yudao-spring-boot-starter-web/src/main/java/cn/iocoder/yudao/framework/errorcode/core/loader/ErrorCodeLoaderImpl.java diff --git a/yudao-framework/yudao-spring-boot-starter-biz-error-code/src/main/java/cn/iocoder/yudao/framework/errorcode/package-info.java b/yudao-framework/yudao-spring-boot-starter-web/src/main/java/cn/iocoder/yudao/framework/errorcode/package-info.java similarity index 100% rename from yudao-framework/yudao-spring-boot-starter-biz-error-code/src/main/java/cn/iocoder/yudao/framework/errorcode/package-info.java rename to yudao-framework/yudao-spring-boot-starter-web/src/main/java/cn/iocoder/yudao/framework/errorcode/package-info.java diff --git a/yudao-framework/yudao-spring-boot-starter-web/src/main/resources/META-INF/spring/org.springframework.boot.autoconfigure.AutoConfiguration.imports b/yudao-framework/yudao-spring-boot-starter-web/src/main/resources/META-INF/spring/org.springframework.boot.autoconfigure.AutoConfiguration.imports index 818e33aa3..36ba94cbb 100644 --- a/yudao-framework/yudao-spring-boot-starter-web/src/main/resources/META-INF/spring/org.springframework.boot.autoconfigure.AutoConfiguration.imports +++ b/yudao-framework/yudao-spring-boot-starter-web/src/main/resources/META-INF/spring/org.springframework.boot.autoconfigure.AutoConfiguration.imports @@ -3,3 +3,5 @@ cn.iocoder.yudao.framework.jackson.config.YudaoJacksonAutoConfiguration cn.iocoder.yudao.framework.swagger.config.YudaoSwaggerAutoConfiguration cn.iocoder.yudao.framework.web.config.YudaoWebAutoConfiguration cn.iocoder.yudao.framework.xss.config.YudaoXssAutoConfiguration +cn.iocoder.yudao.framework.banner.config.YudaoBannerAutoConfiguration +cn.iocoder.yudao.framework.errorcode.config.YudaoErrorCodeAutoConfiguration \ No newline at end of file diff --git a/yudao-framework/yudao-spring-boot-starter-banner/src/main/resources/banner.txt b/yudao-framework/yudao-spring-boot-starter-web/src/main/resources/banner.txt similarity index 100% rename from yudao-framework/yudao-spring-boot-starter-banner/src/main/resources/banner.txt rename to yudao-framework/yudao-spring-boot-starter-web/src/main/resources/banner.txt diff --git a/yudao-framework/yudao-spring-boot-starter-desensitize/src/test/java/cn/iocoder/yudao/framework/desensitize/core/DesensitizeTest.java b/yudao-framework/yudao-spring-boot-starter-web/src/test/java/cn/iocoder/yudao/framework/desensitize/core/DesensitizeTest.java similarity index 80% rename from yudao-framework/yudao-spring-boot-starter-desensitize/src/test/java/cn/iocoder/yudao/framework/desensitize/core/DesensitizeTest.java rename to yudao-framework/yudao-spring-boot-starter-web/src/test/java/cn/iocoder/yudao/framework/desensitize/core/DesensitizeTest.java index c308a0eb5..dd214f0c3 100644 --- a/yudao-framework/yudao-spring-boot-starter-desensitize/src/test/java/cn/iocoder/yudao/framework/desensitize/core/DesensitizeTest.java +++ b/yudao-framework/yudao-spring-boot-starter-web/src/test/java/cn/iocoder/yudao/framework/desensitize/core/DesensitizeTest.java @@ -1,27 +1,23 @@ package cn.iocoder.yudao.framework.desensitize.core; import cn.iocoder.yudao.framework.common.util.json.JsonUtils; +import cn.iocoder.yudao.framework.desensitize.core.annotation.Address; import cn.iocoder.yudao.framework.desensitize.core.regex.annotation.EmailDesensitize; import cn.iocoder.yudao.framework.desensitize.core.regex.annotation.RegexDesensitize; -import cn.iocoder.yudao.framework.desensitize.core.annotation.Address; -import cn.iocoder.yudao.framework.desensitize.core.slider.annotation.BankCardDesensitize; -import cn.iocoder.yudao.framework.desensitize.core.slider.annotation.CarLicenseDesensitize; -import cn.iocoder.yudao.framework.desensitize.core.slider.annotation.ChineseNameDesensitize; -import cn.iocoder.yudao.framework.desensitize.core.slider.annotation.FixedPhoneDesensitize; -import cn.iocoder.yudao.framework.desensitize.core.slider.annotation.IdCardDesensitize; -import cn.iocoder.yudao.framework.desensitize.core.slider.annotation.PasswordDesensitize; -import cn.iocoder.yudao.framework.desensitize.core.slider.annotation.MobileDesensitize; -import cn.iocoder.yudao.framework.desensitize.core.slider.annotation.SliderDesensitize; -import cn.iocoder.yudao.framework.test.core.ut.BaseMockitoUnitTest; +import cn.iocoder.yudao.framework.desensitize.core.slider.annotation.*; import lombok.Data; import org.junit.jupiter.api.Test; +import org.junit.jupiter.api.extension.ExtendWith; +import org.mockito.junit.jupiter.MockitoExtension; -import static org.junit.jupiter.api.Assertions.*; +import static org.junit.jupiter.api.Assertions.assertEquals; +import static org.junit.jupiter.api.Assertions.assertNotNull; /** * {@link DesensitizeTest} 的单元测试 */ -public class DesensitizeTest extends BaseMockitoUnitTest { +@ExtendWith(MockitoExtension.class) +public class DesensitizeTest { @Test public void test() { diff --git a/yudao-framework/yudao-spring-boot-starter-desensitize/src/test/java/cn/iocoder/yudao/framework/desensitize/core/annotation/Address.java b/yudao-framework/yudao-spring-boot-starter-web/src/test/java/cn/iocoder/yudao/framework/desensitize/core/annotation/Address.java similarity index 100% rename from yudao-framework/yudao-spring-boot-starter-desensitize/src/test/java/cn/iocoder/yudao/framework/desensitize/core/annotation/Address.java rename to yudao-framework/yudao-spring-boot-starter-web/src/test/java/cn/iocoder/yudao/framework/desensitize/core/annotation/Address.java index 735d25b34..130120981 100644 --- a/yudao-framework/yudao-spring-boot-starter-desensitize/src/test/java/cn/iocoder/yudao/framework/desensitize/core/annotation/Address.java +++ b/yudao-framework/yudao-spring-boot-starter-web/src/test/java/cn/iocoder/yudao/framework/desensitize/core/annotation/Address.java @@ -1,8 +1,8 @@ package cn.iocoder.yudao.framework.desensitize.core.annotation; import cn.iocoder.yudao.framework.desensitize.core.DesensitizeTest; -import cn.iocoder.yudao.framework.desensitize.core.base.annotation.DesensitizeBy; import cn.iocoder.yudao.framework.desensitize.core.handler.AddressHandler; +import cn.iocoder.yudao.framework.desensitize.core.base.annotation.DesensitizeBy; import com.fasterxml.jackson.annotation.JacksonAnnotationsInside; import java.lang.annotation.Documented; diff --git a/yudao-framework/yudao-spring-boot-starter-desensitize/src/test/java/cn/iocoder/yudao/framework/desensitize/core/handler/AddressHandler.java b/yudao-framework/yudao-spring-boot-starter-web/src/test/java/cn/iocoder/yudao/framework/desensitize/core/handler/AddressHandler.java similarity index 100% rename from yudao-framework/yudao-spring-boot-starter-desensitize/src/test/java/cn/iocoder/yudao/framework/desensitize/core/handler/AddressHandler.java rename to yudao-framework/yudao-spring-boot-starter-web/src/test/java/cn/iocoder/yudao/framework/desensitize/core/handler/AddressHandler.java diff --git a/yudao-server/pom.xml b/yudao-server/pom.xml index 20b67725b..25e684e6c 100644 --- a/yudao-server/pom.xml +++ b/yudao-server/pom.xml @@ -31,10 +31,6 @@ yudao-module-infra-biz ${revision} - - cn.iocoder.boot - yudao-spring-boot-starter-biz-error-code - @@ -104,10 +100,6 @@ spring-boot-configuration-processor true - - cn.iocoder.boot - yudao-spring-boot-starter-banner - From 5acdd1554ef2f2c2540cf44207be2684282870f4 Mon Sep 17 00:00:00 2001 From: YunaiV Date: Sat, 27 Jan 2024 11:25:43 +0800 Subject: [PATCH 037/119] =?UTF-8?q?=E2=9C=A8=20=E5=85=A8=E5=B1=80=EF=BC=9A?= =?UTF-8?q?=E5=B0=86=20sms=20=E8=9E=8D=E5=90=88=E5=88=B0=20system=20?= =?UTF-8?q?=E6=A8=A1=E5=9D=97=E9=87=8C=EF=BC=8C=E5=87=8F=E5=B0=91=20starte?= =?UTF-8?q?r?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../sms/config/YudaoSmsAutoConfiguration.java | 21 -------- .../enums/SmsFrameworkErrorCodeConstants.java | 50 ------------------- ...ot.autoconfigure.AutoConfiguration.imports | 1 - .../yudao-module-system-biz/pom.xml | 12 +++++ .../admin/sms/SmsCallbackController.java | 2 +- .../dal/dataobject/sms/SmsChannelDO.java | 2 +- .../framework/sms/SmsCodeConfiguration.java | 9 ---- .../sms/{ => config}/SmsCodeProperties.java | 2 +- .../sms/config/SmsConfiguration.java | 23 +++++++++ .../framework/sms/core/client/SmsClient.java | 8 +-- .../sms/core/client/SmsClientFactory.java | 4 +- .../core/client/dto/SmsReceiveRespDTO.java | 2 +- .../sms/core/client/dto/SmsSendRespDTO.java | 2 +- .../core/client/dto/SmsTemplateRespDTO.java | 4 +- .../core/client/impl/AbstractSmsClient.java | 6 +-- .../core/client/impl}/AliyunSmsClient.java | 13 +++-- .../client/impl}/DebugDingTalkSmsClient.java | 13 +++-- .../client/impl/SmsClientFactoryImpl.java | 13 ++--- .../core/client/impl}/TencentSmsClient.java | 13 +++-- .../sms/core/enums/SmsChannelEnum.java | 2 +- .../enums/SmsTemplateAuditStatusEnum.java | 2 +- .../core/property/SmsChannelProperties.java | 4 +- .../system/service/sms/SmsChannelService.java | 2 +- .../service/sms/SmsChannelServiceImpl.java | 6 +-- .../service/sms/SmsCodeServiceImpl.java | 2 +- .../service/sms/SmsSendServiceImpl.java | 6 +-- .../service/sms/SmsTemplateServiceImpl.java | 6 +-- .../client/impl}/AliyunSmsClientTest.java | 12 ++--- .../client/impl}/TencentSmsClientTest.java | 12 ++--- .../service/sms/SmsChannelServiceTest.java | 6 +-- .../service/sms/SmsCodeServiceImplTest.java | 2 +- .../service/sms/SmsSendServiceImplTest.java | 6 +-- .../sms/SmsTemplateServiceImplTest.java | 6 +-- 33 files changed, 111 insertions(+), 163 deletions(-) delete mode 100644 yudao-framework/yudao-spring-boot-starter-biz-sms/src/main/java/cn/iocoder/yudao/framework/sms/config/YudaoSmsAutoConfiguration.java delete mode 100644 yudao-framework/yudao-spring-boot-starter-biz-sms/src/main/java/cn/iocoder/yudao/framework/sms/core/enums/SmsFrameworkErrorCodeConstants.java delete mode 100644 yudao-framework/yudao-spring-boot-starter-biz-sms/src/main/resources/META-INF/spring/org.springframework.boot.autoconfigure.AutoConfiguration.imports delete mode 100644 yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/framework/sms/SmsCodeConfiguration.java rename yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/framework/sms/{ => config}/SmsCodeProperties.java (94%) create mode 100644 yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/framework/sms/config/SmsConfiguration.java rename {yudao-framework/yudao-spring-boot-starter-biz-sms/src/main/java/cn/iocoder/yudao => yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system}/framework/sms/core/client/SmsClient.java (80%) rename {yudao-framework/yudao-spring-boot-starter-biz-sms/src/main/java/cn/iocoder/yudao => yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system}/framework/sms/core/client/SmsClientFactory.java (79%) rename {yudao-framework/yudao-spring-boot-starter-biz-sms/src/main/java/cn/iocoder/yudao => yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system}/framework/sms/core/client/dto/SmsReceiveRespDTO.java (91%) rename {yudao-framework/yudao-spring-boot-starter-biz-sms/src/main/java/cn/iocoder/yudao => yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system}/framework/sms/core/client/dto/SmsSendRespDTO.java (91%) rename {yudao-framework/yudao-spring-boot-starter-biz-sms/src/main/java/cn/iocoder/yudao => yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system}/framework/sms/core/client/dto/SmsTemplateRespDTO.java (73%) rename {yudao-framework/yudao-spring-boot-starter-biz-sms/src/main/java/cn/iocoder/yudao => yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system}/framework/sms/core/client/impl/AbstractSmsClient.java (82%) rename {yudao-framework/yudao-spring-boot-starter-biz-sms/src/main/java/cn/iocoder/yudao/framework/sms/core/client/impl/aliyun => yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/framework/sms/core/client/impl}/AliyunSmsClient.java (92%) rename {yudao-framework/yudao-spring-boot-starter-biz-sms/src/main/java/cn/iocoder/yudao/framework/sms/core/client/impl/debug => yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/framework/sms/core/client/impl}/DebugDingTalkSmsClient.java (87%) rename {yudao-framework/yudao-spring-boot-starter-biz-sms/src/main/java/cn/iocoder/yudao => yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system}/framework/sms/core/client/impl/SmsClientFactoryImpl.java (84%) rename {yudao-framework/yudao-spring-boot-starter-biz-sms/src/main/java/cn/iocoder/yudao/framework/sms/core/client/impl/tencent => yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/framework/sms/core/client/impl}/TencentSmsClient.java (93%) rename {yudao-framework/yudao-spring-boot-starter-biz-sms/src/main/java/cn/iocoder/yudao => yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system}/framework/sms/core/enums/SmsChannelEnum.java (91%) rename {yudao-framework/yudao-spring-boot-starter-biz-sms/src/main/java/cn/iocoder/yudao => yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system}/framework/sms/core/enums/SmsTemplateAuditStatusEnum.java (81%) rename {yudao-framework/yudao-spring-boot-starter-biz-sms/src/main/java/cn/iocoder/yudao => yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system}/framework/sms/core/property/SmsChannelProperties.java (87%) rename {yudao-framework/yudao-spring-boot-starter-biz-sms/src/test/java/cn/iocoder/yudao/framework/sms/core/client/impl/aliyun => yudao-module-system/yudao-module-system-biz/src/test/java/cn/iocoder/yudao/module/system/framework/sms/core/client/impl}/AliyunSmsClientTest.java (93%) rename {yudao-framework/yudao-spring-boot-starter-biz-sms/src/test/java/cn/iocoder/yudao/framework/sms/core/client/impl/tencent => yudao-module-system/yudao-module-system-biz/src/test/java/cn/iocoder/yudao/module/system/framework/sms/core/client/impl}/TencentSmsClientTest.java (95%) diff --git a/yudao-framework/yudao-spring-boot-starter-biz-sms/src/main/java/cn/iocoder/yudao/framework/sms/config/YudaoSmsAutoConfiguration.java b/yudao-framework/yudao-spring-boot-starter-biz-sms/src/main/java/cn/iocoder/yudao/framework/sms/config/YudaoSmsAutoConfiguration.java deleted file mode 100644 index 9873c80d5..000000000 --- a/yudao-framework/yudao-spring-boot-starter-biz-sms/src/main/java/cn/iocoder/yudao/framework/sms/config/YudaoSmsAutoConfiguration.java +++ /dev/null @@ -1,21 +0,0 @@ -package cn.iocoder.yudao.framework.sms.config; - -import cn.iocoder.yudao.framework.sms.core.client.SmsClientFactory; -import cn.iocoder.yudao.framework.sms.core.client.impl.SmsClientFactoryImpl; -import org.springframework.boot.autoconfigure.AutoConfiguration; -import org.springframework.context.annotation.Bean; - -/** - * 短信配置类 - * - * @author 芋道源码 - */ -@AutoConfiguration -public class YudaoSmsAutoConfiguration { - - @Bean - public SmsClientFactory smsClientFactory() { - return new SmsClientFactoryImpl(); - } - -} diff --git a/yudao-framework/yudao-spring-boot-starter-biz-sms/src/main/java/cn/iocoder/yudao/framework/sms/core/enums/SmsFrameworkErrorCodeConstants.java b/yudao-framework/yudao-spring-boot-starter-biz-sms/src/main/java/cn/iocoder/yudao/framework/sms/core/enums/SmsFrameworkErrorCodeConstants.java deleted file mode 100644 index b9a226fdb..000000000 --- a/yudao-framework/yudao-spring-boot-starter-biz-sms/src/main/java/cn/iocoder/yudao/framework/sms/core/enums/SmsFrameworkErrorCodeConstants.java +++ /dev/null @@ -1,50 +0,0 @@ -package cn.iocoder.yudao.framework.sms.core.enums; - -import cn.iocoder.yudao.framework.common.exception.ErrorCode; - -/** - * 短信框架的错误码枚举 - * - * 短信框架,使用 2-001-000-000 段 - * - * @author 芋道源码 - */ -public interface SmsFrameworkErrorCodeConstants { - - ErrorCode SMS_UNKNOWN = new ErrorCode(2_001_000_000, "未知错误,需要解析"); - - // ========== 权限 / 限流等相关 2-001-000-100 ========== - - ErrorCode SMS_PERMISSION_DENY = new ErrorCode(2_001_000_100, "没有发送短信的权限"); - ErrorCode SMS_IP_DENY = new ErrorCode(2_001_000_100, "IP 不允许发送短信"); - - // 阿里云:将短信发送频率限制在正常的业务限流范围内。默认短信验证码:使用同一签名,对同一个手机号验证码,支持 1 条 / 分钟,5 条 / 小时,累计 10 条 / 天。 - ErrorCode SMS_SEND_BUSINESS_LIMIT_CONTROL = new ErrorCode(2_001_000_102, "指定手机的发送限流"); - // 阿里云:已经达到您在控制台设置的短信日发送量限额值。在国内消息设置 > 安全设置,修改发送总量阈值。 - ErrorCode SMS_SEND_DAY_LIMIT_CONTROL = new ErrorCode(2_001_000_103, "每天的发送限流"); - - ErrorCode SMS_SEND_CONTENT_INVALID = new ErrorCode(2_001_000_104, "短信内容有敏感词"); - - // 腾讯云:为避免骚扰用户,营销短信只允许在8点到22点发送。 - ErrorCode SMS_SEND_MARKET_LIMIT_CONTROL = new ErrorCode(2_001_000_105, "营销短信发送时间限制"); - - // ========== 模板相关 2-001-000-200 ========== - ErrorCode SMS_TEMPLATE_INVALID = new ErrorCode(2_001_000_200, "短信模板不合法"); // 包括短信模板不存在 - ErrorCode SMS_TEMPLATE_PARAM_ERROR = new ErrorCode(2_001_000_201, "模板参数不正确"); - - // ========== 签名相关 2-001-000-300 ========== - ErrorCode SMS_SIGN_INVALID = new ErrorCode(2_001_000_300, "短信签名不可用"); - - // ========== 账户相关 2-001-000-400 ========== - ErrorCode SMS_ACCOUNT_MONEY_NOT_ENOUGH = new ErrorCode(2_001_000_400, "账户余额不足"); - ErrorCode SMS_ACCOUNT_INVALID = new ErrorCode(2_001_000_401, "apiKey 不存在"); - - // ========== 其它相关 2-001-000-900 开头 ========== - ErrorCode SMS_API_PARAM_ERROR = new ErrorCode(2_001_000_900, "请求参数缺失"); - ErrorCode SMS_MOBILE_INVALID = new ErrorCode(2_001_000_901, "手机格式不正确"); - ErrorCode SMS_MOBILE_BLACK = new ErrorCode(2_001_000_902, "手机号在黑名单中"); - ErrorCode SMS_APP_ID_INVALID = new ErrorCode(2_001_000_903, "SdkAppId不合法"); - - ErrorCode EXCEPTION = new ErrorCode(2_001_000_999, "调用异常"); - -} diff --git a/yudao-framework/yudao-spring-boot-starter-biz-sms/src/main/resources/META-INF/spring/org.springframework.boot.autoconfigure.AutoConfiguration.imports b/yudao-framework/yudao-spring-boot-starter-biz-sms/src/main/resources/META-INF/spring/org.springframework.boot.autoconfigure.AutoConfiguration.imports deleted file mode 100644 index 7c9b740ca..000000000 --- a/yudao-framework/yudao-spring-boot-starter-biz-sms/src/main/resources/META-INF/spring/org.springframework.boot.autoconfigure.AutoConfiguration.imports +++ /dev/null @@ -1 +0,0 @@ -cn.iocoder.yudao.framework.sms.config.YudaoSmsAutoConfiguration \ No newline at end of file diff --git a/yudao-module-system/yudao-module-system-biz/pom.xml b/yudao-module-system/yudao-module-system-biz/pom.xml index dc8a1b454..87c076c78 100644 --- a/yudao-module-system/yudao-module-system-biz/pom.xml +++ b/yudao-module-system/yudao-module-system-biz/pom.xml @@ -127,6 +127,18 @@ wx-java-miniapp-spring-boot-starter + + com.aliyun + aliyun-java-sdk-core + + + com.aliyun + aliyun-java-sdk-dysmsapi + + + com.tencentcloudapi + tencentcloud-sdk-java-sms + diff --git a/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/controller/admin/sms/SmsCallbackController.java b/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/controller/admin/sms/SmsCallbackController.java index 5a5535251..f392ac759 100644 --- a/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/controller/admin/sms/SmsCallbackController.java +++ b/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/controller/admin/sms/SmsCallbackController.java @@ -3,7 +3,7 @@ package cn.iocoder.yudao.module.system.controller.admin.sms; import cn.iocoder.yudao.framework.common.pojo.CommonResult; import cn.iocoder.yudao.framework.common.util.servlet.ServletUtils; import cn.iocoder.yudao.framework.operatelog.core.annotations.OperateLog; -import cn.iocoder.yudao.framework.sms.core.enums.SmsChannelEnum; +import cn.iocoder.yudao.module.system.framework.sms.core.enums.SmsChannelEnum; import cn.iocoder.yudao.module.system.service.sms.SmsSendService; import io.swagger.v3.oas.annotations.Operation; import io.swagger.v3.oas.annotations.tags.Tag; diff --git a/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/dal/dataobject/sms/SmsChannelDO.java b/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/dal/dataobject/sms/SmsChannelDO.java index c57ea5b59..6ecb4f142 100644 --- a/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/dal/dataobject/sms/SmsChannelDO.java +++ b/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/dal/dataobject/sms/SmsChannelDO.java @@ -2,7 +2,7 @@ package cn.iocoder.yudao.module.system.dal.dataobject.sms; import cn.iocoder.yudao.framework.common.enums.CommonStatusEnum; import cn.iocoder.yudao.framework.mybatis.core.dataobject.BaseDO; -import cn.iocoder.yudao.framework.sms.core.enums.SmsChannelEnum; +import cn.iocoder.yudao.module.system.framework.sms.core.enums.SmsChannelEnum; import com.baomidou.mybatisplus.annotation.KeySequence; import com.baomidou.mybatisplus.annotation.TableName; import lombok.Data; diff --git a/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/framework/sms/SmsCodeConfiguration.java b/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/framework/sms/SmsCodeConfiguration.java deleted file mode 100644 index ddc70a39e..000000000 --- a/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/framework/sms/SmsCodeConfiguration.java +++ /dev/null @@ -1,9 +0,0 @@ -package cn.iocoder.yudao.module.system.framework.sms; - -import org.springframework.boot.context.properties.EnableConfigurationProperties; -import org.springframework.context.annotation.Configuration; - -@Configuration(proxyBeanMethods = false) -@EnableConfigurationProperties(SmsCodeProperties.class) -public class SmsCodeConfiguration { -} diff --git a/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/framework/sms/SmsCodeProperties.java b/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/framework/sms/config/SmsCodeProperties.java similarity index 94% rename from yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/framework/sms/SmsCodeProperties.java rename to yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/framework/sms/config/SmsCodeProperties.java index f2c05a112..16f15a595 100644 --- a/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/framework/sms/SmsCodeProperties.java +++ b/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/framework/sms/config/SmsCodeProperties.java @@ -1,4 +1,4 @@ -package cn.iocoder.yudao.module.system.framework.sms; +package cn.iocoder.yudao.module.system.framework.sms.config; import lombok.Data; import org.springframework.boot.context.properties.ConfigurationProperties; diff --git a/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/framework/sms/config/SmsConfiguration.java b/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/framework/sms/config/SmsConfiguration.java new file mode 100644 index 000000000..eb34775fe --- /dev/null +++ b/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/framework/sms/config/SmsConfiguration.java @@ -0,0 +1,23 @@ +package cn.iocoder.yudao.module.system.framework.sms.config; + +import cn.iocoder.yudao.module.system.framework.sms.core.client.SmsClientFactory; +import cn.iocoder.yudao.module.system.framework.sms.core.client.impl.SmsClientFactoryImpl; +import org.springframework.boot.context.properties.EnableConfigurationProperties; +import org.springframework.context.annotation.Bean; +import org.springframework.context.annotation.Configuration; + +/** + * 短信配置类,包括短信客户端、短信验证码两部分 + * + * @author 芋道源码 + */ +@Configuration(proxyBeanMethods = false) +@EnableConfigurationProperties(SmsCodeProperties.class) +public class SmsConfiguration { + + @Bean + public SmsClientFactory smsClientFactory() { + return new SmsClientFactoryImpl(); + } + +} diff --git a/yudao-framework/yudao-spring-boot-starter-biz-sms/src/main/java/cn/iocoder/yudao/framework/sms/core/client/SmsClient.java b/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/framework/sms/core/client/SmsClient.java similarity index 80% rename from yudao-framework/yudao-spring-boot-starter-biz-sms/src/main/java/cn/iocoder/yudao/framework/sms/core/client/SmsClient.java rename to yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/framework/sms/core/client/SmsClient.java index ef945a329..46224663c 100644 --- a/yudao-framework/yudao-spring-boot-starter-biz-sms/src/main/java/cn/iocoder/yudao/framework/sms/core/client/SmsClient.java +++ b/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/framework/sms/core/client/SmsClient.java @@ -1,9 +1,9 @@ -package cn.iocoder.yudao.framework.sms.core.client; +package cn.iocoder.yudao.module.system.framework.sms.core.client; import cn.iocoder.yudao.framework.common.core.KeyValue; -import cn.iocoder.yudao.framework.sms.core.client.dto.SmsReceiveRespDTO; -import cn.iocoder.yudao.framework.sms.core.client.dto.SmsSendRespDTO; -import cn.iocoder.yudao.framework.sms.core.client.dto.SmsTemplateRespDTO; +import cn.iocoder.yudao.module.system.framework.sms.core.client.dto.SmsReceiveRespDTO; +import cn.iocoder.yudao.module.system.framework.sms.core.client.dto.SmsSendRespDTO; +import cn.iocoder.yudao.module.system.framework.sms.core.client.dto.SmsTemplateRespDTO; import java.util.List; diff --git a/yudao-framework/yudao-spring-boot-starter-biz-sms/src/main/java/cn/iocoder/yudao/framework/sms/core/client/SmsClientFactory.java b/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/framework/sms/core/client/SmsClientFactory.java similarity index 79% rename from yudao-framework/yudao-spring-boot-starter-biz-sms/src/main/java/cn/iocoder/yudao/framework/sms/core/client/SmsClientFactory.java rename to yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/framework/sms/core/client/SmsClientFactory.java index d063e58f3..a1133177f 100644 --- a/yudao-framework/yudao-spring-boot-starter-biz-sms/src/main/java/cn/iocoder/yudao/framework/sms/core/client/SmsClientFactory.java +++ b/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/framework/sms/core/client/SmsClientFactory.java @@ -1,6 +1,6 @@ -package cn.iocoder.yudao.framework.sms.core.client; +package cn.iocoder.yudao.module.system.framework.sms.core.client; -import cn.iocoder.yudao.framework.sms.core.property.SmsChannelProperties; +import cn.iocoder.yudao.module.system.framework.sms.core.property.SmsChannelProperties; /** * 短信客户端的工厂接口 diff --git a/yudao-framework/yudao-spring-boot-starter-biz-sms/src/main/java/cn/iocoder/yudao/framework/sms/core/client/dto/SmsReceiveRespDTO.java b/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/framework/sms/core/client/dto/SmsReceiveRespDTO.java similarity index 91% rename from yudao-framework/yudao-spring-boot-starter-biz-sms/src/main/java/cn/iocoder/yudao/framework/sms/core/client/dto/SmsReceiveRespDTO.java rename to yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/framework/sms/core/client/dto/SmsReceiveRespDTO.java index 4def4a25c..c90a33e63 100644 --- a/yudao-framework/yudao-spring-boot-starter-biz-sms/src/main/java/cn/iocoder/yudao/framework/sms/core/client/dto/SmsReceiveRespDTO.java +++ b/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/framework/sms/core/client/dto/SmsReceiveRespDTO.java @@ -1,4 +1,4 @@ -package cn.iocoder.yudao.framework.sms.core.client.dto; +package cn.iocoder.yudao.module.system.framework.sms.core.client.dto; import lombok.Data; diff --git a/yudao-framework/yudao-spring-boot-starter-biz-sms/src/main/java/cn/iocoder/yudao/framework/sms/core/client/dto/SmsSendRespDTO.java b/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/framework/sms/core/client/dto/SmsSendRespDTO.java similarity index 91% rename from yudao-framework/yudao-spring-boot-starter-biz-sms/src/main/java/cn/iocoder/yudao/framework/sms/core/client/dto/SmsSendRespDTO.java rename to yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/framework/sms/core/client/dto/SmsSendRespDTO.java index ec517508a..9f3094bcb 100644 --- a/yudao-framework/yudao-spring-boot-starter-biz-sms/src/main/java/cn/iocoder/yudao/framework/sms/core/client/dto/SmsSendRespDTO.java +++ b/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/framework/sms/core/client/dto/SmsSendRespDTO.java @@ -1,4 +1,4 @@ -package cn.iocoder.yudao.framework.sms.core.client.dto; +package cn.iocoder.yudao.module.system.framework.sms.core.client.dto; import lombok.Data; diff --git a/yudao-framework/yudao-spring-boot-starter-biz-sms/src/main/java/cn/iocoder/yudao/framework/sms/core/client/dto/SmsTemplateRespDTO.java b/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/framework/sms/core/client/dto/SmsTemplateRespDTO.java similarity index 73% rename from yudao-framework/yudao-spring-boot-starter-biz-sms/src/main/java/cn/iocoder/yudao/framework/sms/core/client/dto/SmsTemplateRespDTO.java rename to yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/framework/sms/core/client/dto/SmsTemplateRespDTO.java index 70e8df400..38a43aa28 100644 --- a/yudao-framework/yudao-spring-boot-starter-biz-sms/src/main/java/cn/iocoder/yudao/framework/sms/core/client/dto/SmsTemplateRespDTO.java +++ b/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/framework/sms/core/client/dto/SmsTemplateRespDTO.java @@ -1,6 +1,6 @@ -package cn.iocoder.yudao.framework.sms.core.client.dto; +package cn.iocoder.yudao.module.system.framework.sms.core.client.dto; -import cn.iocoder.yudao.framework.sms.core.enums.SmsTemplateAuditStatusEnum; +import cn.iocoder.yudao.module.system.framework.sms.core.enums.SmsTemplateAuditStatusEnum; import lombok.Data; /** diff --git a/yudao-framework/yudao-spring-boot-starter-biz-sms/src/main/java/cn/iocoder/yudao/framework/sms/core/client/impl/AbstractSmsClient.java b/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/framework/sms/core/client/impl/AbstractSmsClient.java similarity index 82% rename from yudao-framework/yudao-spring-boot-starter-biz-sms/src/main/java/cn/iocoder/yudao/framework/sms/core/client/impl/AbstractSmsClient.java rename to yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/framework/sms/core/client/impl/AbstractSmsClient.java index a3b92d5c3..3b6e0eb0d 100644 --- a/yudao-framework/yudao-spring-boot-starter-biz-sms/src/main/java/cn/iocoder/yudao/framework/sms/core/client/impl/AbstractSmsClient.java +++ b/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/framework/sms/core/client/impl/AbstractSmsClient.java @@ -1,7 +1,7 @@ -package cn.iocoder.yudao.framework.sms.core.client.impl; +package cn.iocoder.yudao.module.system.framework.sms.core.client.impl; -import cn.iocoder.yudao.framework.sms.core.client.SmsClient; -import cn.iocoder.yudao.framework.sms.core.property.SmsChannelProperties; +import cn.iocoder.yudao.module.system.framework.sms.core.client.SmsClient; +import cn.iocoder.yudao.module.system.framework.sms.core.property.SmsChannelProperties; import lombok.extern.slf4j.Slf4j; /** diff --git a/yudao-framework/yudao-spring-boot-starter-biz-sms/src/main/java/cn/iocoder/yudao/framework/sms/core/client/impl/aliyun/AliyunSmsClient.java b/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/framework/sms/core/client/impl/AliyunSmsClient.java similarity index 92% rename from yudao-framework/yudao-spring-boot-starter-biz-sms/src/main/java/cn/iocoder/yudao/framework/sms/core/client/impl/aliyun/AliyunSmsClient.java rename to yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/framework/sms/core/client/impl/AliyunSmsClient.java index d32a5bb11..7d01e6cdf 100644 --- a/yudao-framework/yudao-spring-boot-starter-biz-sms/src/main/java/cn/iocoder/yudao/framework/sms/core/client/impl/aliyun/AliyunSmsClient.java +++ b/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/framework/sms/core/client/impl/AliyunSmsClient.java @@ -1,15 +1,14 @@ -package cn.iocoder.yudao.framework.sms.core.client.impl.aliyun; +package cn.iocoder.yudao.module.system.framework.sms.core.client.impl; import cn.hutool.core.lang.Assert; import cn.iocoder.yudao.framework.common.core.KeyValue; import cn.iocoder.yudao.framework.common.util.collection.MapUtils; import cn.iocoder.yudao.framework.common.util.json.JsonUtils; -import cn.iocoder.yudao.framework.sms.core.client.dto.SmsReceiveRespDTO; -import cn.iocoder.yudao.framework.sms.core.client.dto.SmsSendRespDTO; -import cn.iocoder.yudao.framework.sms.core.client.dto.SmsTemplateRespDTO; -import cn.iocoder.yudao.framework.sms.core.client.impl.AbstractSmsClient; -import cn.iocoder.yudao.framework.sms.core.enums.SmsTemplateAuditStatusEnum; -import cn.iocoder.yudao.framework.sms.core.property.SmsChannelProperties; +import cn.iocoder.yudao.module.system.framework.sms.core.client.dto.SmsReceiveRespDTO; +import cn.iocoder.yudao.module.system.framework.sms.core.client.dto.SmsSendRespDTO; +import cn.iocoder.yudao.module.system.framework.sms.core.client.dto.SmsTemplateRespDTO; +import cn.iocoder.yudao.module.system.framework.sms.core.enums.SmsTemplateAuditStatusEnum; +import cn.iocoder.yudao.module.system.framework.sms.core.property.SmsChannelProperties; import com.aliyuncs.DefaultAcsClient; import com.aliyuncs.IAcsClient; import com.aliyuncs.dysmsapi.model.v20170525.QuerySmsTemplateRequest; diff --git a/yudao-framework/yudao-spring-boot-starter-biz-sms/src/main/java/cn/iocoder/yudao/framework/sms/core/client/impl/debug/DebugDingTalkSmsClient.java b/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/framework/sms/core/client/impl/DebugDingTalkSmsClient.java similarity index 87% rename from yudao-framework/yudao-spring-boot-starter-biz-sms/src/main/java/cn/iocoder/yudao/framework/sms/core/client/impl/debug/DebugDingTalkSmsClient.java rename to yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/framework/sms/core/client/impl/DebugDingTalkSmsClient.java index 315edf942..e9fcc6c41 100644 --- a/yudao-framework/yudao-spring-boot-starter-biz-sms/src/main/java/cn/iocoder/yudao/framework/sms/core/client/impl/debug/DebugDingTalkSmsClient.java +++ b/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/framework/sms/core/client/impl/DebugDingTalkSmsClient.java @@ -1,4 +1,4 @@ -package cn.iocoder.yudao.framework.sms.core.client.impl.debug; +package cn.iocoder.yudao.module.system.framework.sms.core.client.impl; import cn.hutool.core.codec.Base64; import cn.hutool.core.lang.Assert; @@ -10,12 +10,11 @@ import cn.hutool.http.HttpUtil; import cn.iocoder.yudao.framework.common.core.KeyValue; import cn.iocoder.yudao.framework.common.util.collection.MapUtils; import cn.iocoder.yudao.framework.common.util.json.JsonUtils; -import cn.iocoder.yudao.framework.sms.core.client.dto.SmsReceiveRespDTO; -import cn.iocoder.yudao.framework.sms.core.client.dto.SmsSendRespDTO; -import cn.iocoder.yudao.framework.sms.core.client.dto.SmsTemplateRespDTO; -import cn.iocoder.yudao.framework.sms.core.client.impl.AbstractSmsClient; -import cn.iocoder.yudao.framework.sms.core.enums.SmsTemplateAuditStatusEnum; -import cn.iocoder.yudao.framework.sms.core.property.SmsChannelProperties; +import cn.iocoder.yudao.module.system.framework.sms.core.client.dto.SmsReceiveRespDTO; +import cn.iocoder.yudao.module.system.framework.sms.core.client.dto.SmsSendRespDTO; +import cn.iocoder.yudao.module.system.framework.sms.core.client.dto.SmsTemplateRespDTO; +import cn.iocoder.yudao.module.system.framework.sms.core.enums.SmsTemplateAuditStatusEnum; +import cn.iocoder.yudao.module.system.framework.sms.core.property.SmsChannelProperties; import java.util.HashMap; import java.util.List; diff --git a/yudao-framework/yudao-spring-boot-starter-biz-sms/src/main/java/cn/iocoder/yudao/framework/sms/core/client/impl/SmsClientFactoryImpl.java b/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/framework/sms/core/client/impl/SmsClientFactoryImpl.java similarity index 84% rename from yudao-framework/yudao-spring-boot-starter-biz-sms/src/main/java/cn/iocoder/yudao/framework/sms/core/client/impl/SmsClientFactoryImpl.java rename to yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/framework/sms/core/client/impl/SmsClientFactoryImpl.java index abb7dda1b..94fe88da9 100644 --- a/yudao-framework/yudao-spring-boot-starter-biz-sms/src/main/java/cn/iocoder/yudao/framework/sms/core/client/impl/SmsClientFactoryImpl.java +++ b/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/framework/sms/core/client/impl/SmsClientFactoryImpl.java @@ -1,12 +1,9 @@ -package cn.iocoder.yudao.framework.sms.core.client.impl; +package cn.iocoder.yudao.module.system.framework.sms.core.client.impl; -import cn.iocoder.yudao.framework.sms.core.client.SmsClient; -import cn.iocoder.yudao.framework.sms.core.client.SmsClientFactory; -import cn.iocoder.yudao.framework.sms.core.client.impl.aliyun.AliyunSmsClient; -import cn.iocoder.yudao.framework.sms.core.client.impl.debug.DebugDingTalkSmsClient; -import cn.iocoder.yudao.framework.sms.core.client.impl.tencent.TencentSmsClient; -import cn.iocoder.yudao.framework.sms.core.enums.SmsChannelEnum; -import cn.iocoder.yudao.framework.sms.core.property.SmsChannelProperties; +import cn.iocoder.yudao.module.system.framework.sms.core.client.SmsClient; +import cn.iocoder.yudao.module.system.framework.sms.core.client.SmsClientFactory; +import cn.iocoder.yudao.module.system.framework.sms.core.enums.SmsChannelEnum; +import cn.iocoder.yudao.module.system.framework.sms.core.property.SmsChannelProperties; import lombok.extern.slf4j.Slf4j; import org.springframework.util.Assert; import org.springframework.validation.annotation.Validated; diff --git a/yudao-framework/yudao-spring-boot-starter-biz-sms/src/main/java/cn/iocoder/yudao/framework/sms/core/client/impl/tencent/TencentSmsClient.java b/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/framework/sms/core/client/impl/TencentSmsClient.java similarity index 93% rename from yudao-framework/yudao-spring-boot-starter-biz-sms/src/main/java/cn/iocoder/yudao/framework/sms/core/client/impl/tencent/TencentSmsClient.java rename to yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/framework/sms/core/client/impl/TencentSmsClient.java index eeb287ffe..dc238be77 100644 --- a/yudao-framework/yudao-spring-boot-starter-biz-sms/src/main/java/cn/iocoder/yudao/framework/sms/core/client/impl/tencent/TencentSmsClient.java +++ b/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/framework/sms/core/client/impl/TencentSmsClient.java @@ -1,16 +1,15 @@ -package cn.iocoder.yudao.framework.sms.core.client.impl.tencent; +package cn.iocoder.yudao.module.system.framework.sms.core.client.impl; import cn.hutool.core.lang.Assert; import cn.hutool.core.util.StrUtil; import cn.iocoder.yudao.framework.common.core.KeyValue; import cn.iocoder.yudao.framework.common.util.collection.ArrayUtils; import cn.iocoder.yudao.framework.common.util.json.JsonUtils; -import cn.iocoder.yudao.framework.sms.core.client.dto.SmsReceiveRespDTO; -import cn.iocoder.yudao.framework.sms.core.client.dto.SmsSendRespDTO; -import cn.iocoder.yudao.framework.sms.core.client.dto.SmsTemplateRespDTO; -import cn.iocoder.yudao.framework.sms.core.client.impl.AbstractSmsClient; -import cn.iocoder.yudao.framework.sms.core.enums.SmsTemplateAuditStatusEnum; -import cn.iocoder.yudao.framework.sms.core.property.SmsChannelProperties; +import cn.iocoder.yudao.module.system.framework.sms.core.client.dto.SmsReceiveRespDTO; +import cn.iocoder.yudao.module.system.framework.sms.core.client.dto.SmsSendRespDTO; +import cn.iocoder.yudao.module.system.framework.sms.core.client.dto.SmsTemplateRespDTO; +import cn.iocoder.yudao.module.system.framework.sms.core.enums.SmsTemplateAuditStatusEnum; +import cn.iocoder.yudao.module.system.framework.sms.core.property.SmsChannelProperties; import com.fasterxml.jackson.annotation.JsonFormat; import com.fasterxml.jackson.annotation.JsonProperty; import com.google.common.annotations.VisibleForTesting; diff --git a/yudao-framework/yudao-spring-boot-starter-biz-sms/src/main/java/cn/iocoder/yudao/framework/sms/core/enums/SmsChannelEnum.java b/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/framework/sms/core/enums/SmsChannelEnum.java similarity index 91% rename from yudao-framework/yudao-spring-boot-starter-biz-sms/src/main/java/cn/iocoder/yudao/framework/sms/core/enums/SmsChannelEnum.java rename to yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/framework/sms/core/enums/SmsChannelEnum.java index 66410bd2c..7bd192223 100644 --- a/yudao-framework/yudao-spring-boot-starter-biz-sms/src/main/java/cn/iocoder/yudao/framework/sms/core/enums/SmsChannelEnum.java +++ b/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/framework/sms/core/enums/SmsChannelEnum.java @@ -1,4 +1,4 @@ -package cn.iocoder.yudao.framework.sms.core.enums; +package cn.iocoder.yudao.module.system.framework.sms.core.enums; import cn.hutool.core.util.ArrayUtil; import lombok.AllArgsConstructor; diff --git a/yudao-framework/yudao-spring-boot-starter-biz-sms/src/main/java/cn/iocoder/yudao/framework/sms/core/enums/SmsTemplateAuditStatusEnum.java b/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/framework/sms/core/enums/SmsTemplateAuditStatusEnum.java similarity index 81% rename from yudao-framework/yudao-spring-boot-starter-biz-sms/src/main/java/cn/iocoder/yudao/framework/sms/core/enums/SmsTemplateAuditStatusEnum.java rename to yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/framework/sms/core/enums/SmsTemplateAuditStatusEnum.java index 255565002..489f69e45 100644 --- a/yudao-framework/yudao-spring-boot-starter-biz-sms/src/main/java/cn/iocoder/yudao/framework/sms/core/enums/SmsTemplateAuditStatusEnum.java +++ b/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/framework/sms/core/enums/SmsTemplateAuditStatusEnum.java @@ -1,4 +1,4 @@ -package cn.iocoder.yudao.framework.sms.core.enums; +package cn.iocoder.yudao.module.system.framework.sms.core.enums; import lombok.AllArgsConstructor; import lombok.Getter; diff --git a/yudao-framework/yudao-spring-boot-starter-biz-sms/src/main/java/cn/iocoder/yudao/framework/sms/core/property/SmsChannelProperties.java b/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/framework/sms/core/property/SmsChannelProperties.java similarity index 87% rename from yudao-framework/yudao-spring-boot-starter-biz-sms/src/main/java/cn/iocoder/yudao/framework/sms/core/property/SmsChannelProperties.java rename to yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/framework/sms/core/property/SmsChannelProperties.java index 491dd437a..0362b92b1 100644 --- a/yudao-framework/yudao-spring-boot-starter-biz-sms/src/main/java/cn/iocoder/yudao/framework/sms/core/property/SmsChannelProperties.java +++ b/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/framework/sms/core/property/SmsChannelProperties.java @@ -1,6 +1,6 @@ -package cn.iocoder.yudao.framework.sms.core.property; +package cn.iocoder.yudao.module.system.framework.sms.core.property; -import cn.iocoder.yudao.framework.sms.core.enums.SmsChannelEnum; +import cn.iocoder.yudao.module.system.framework.sms.core.enums.SmsChannelEnum; import lombok.Data; import org.springframework.validation.annotation.Validated; diff --git a/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/service/sms/SmsChannelService.java b/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/service/sms/SmsChannelService.java index 13cd84308..c33c7752c 100644 --- a/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/service/sms/SmsChannelService.java +++ b/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/service/sms/SmsChannelService.java @@ -1,7 +1,7 @@ package cn.iocoder.yudao.module.system.service.sms; import cn.iocoder.yudao.framework.common.pojo.PageResult; -import cn.iocoder.yudao.framework.sms.core.client.SmsClient; +import cn.iocoder.yudao.module.system.framework.sms.core.client.SmsClient; import cn.iocoder.yudao.module.system.controller.admin.sms.vo.channel.SmsChannelPageReqVO; import cn.iocoder.yudao.module.system.controller.admin.sms.vo.channel.SmsChannelSaveReqVO; import cn.iocoder.yudao.module.system.dal.dataobject.sms.SmsChannelDO; diff --git a/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/service/sms/SmsChannelServiceImpl.java b/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/service/sms/SmsChannelServiceImpl.java index c4d08890e..cca3741fe 100644 --- a/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/service/sms/SmsChannelServiceImpl.java +++ b/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/service/sms/SmsChannelServiceImpl.java @@ -3,9 +3,9 @@ package cn.iocoder.yudao.module.system.service.sms; import cn.hutool.core.util.StrUtil; import cn.iocoder.yudao.framework.common.pojo.PageResult; import cn.iocoder.yudao.framework.common.util.object.BeanUtils; -import cn.iocoder.yudao.framework.sms.core.client.SmsClient; -import cn.iocoder.yudao.framework.sms.core.client.SmsClientFactory; -import cn.iocoder.yudao.framework.sms.core.property.SmsChannelProperties; +import cn.iocoder.yudao.module.system.framework.sms.core.client.SmsClient; +import cn.iocoder.yudao.module.system.framework.sms.core.client.SmsClientFactory; +import cn.iocoder.yudao.module.system.framework.sms.core.property.SmsChannelProperties; import cn.iocoder.yudao.module.system.controller.admin.sms.vo.channel.SmsChannelPageReqVO; import cn.iocoder.yudao.module.system.controller.admin.sms.vo.channel.SmsChannelSaveReqVO; import cn.iocoder.yudao.module.system.dal.dataobject.sms.SmsChannelDO; diff --git a/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/service/sms/SmsCodeServiceImpl.java b/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/service/sms/SmsCodeServiceImpl.java index 065f5fdcb..5e6637fbd 100644 --- a/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/service/sms/SmsCodeServiceImpl.java +++ b/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/service/sms/SmsCodeServiceImpl.java @@ -9,7 +9,7 @@ import cn.iocoder.yudao.module.system.api.sms.dto.code.SmsCodeValidateReqDTO; import cn.iocoder.yudao.module.system.dal.dataobject.sms.SmsCodeDO; import cn.iocoder.yudao.module.system.dal.mysql.sms.SmsCodeMapper; import cn.iocoder.yudao.module.system.enums.sms.SmsSceneEnum; -import cn.iocoder.yudao.module.system.framework.sms.SmsCodeProperties; +import cn.iocoder.yudao.module.system.framework.sms.config.SmsCodeProperties; import org.springframework.stereotype.Service; import org.springframework.validation.annotation.Validated; diff --git a/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/service/sms/SmsSendServiceImpl.java b/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/service/sms/SmsSendServiceImpl.java index b05d1302e..41f429eca 100644 --- a/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/service/sms/SmsSendServiceImpl.java +++ b/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/service/sms/SmsSendServiceImpl.java @@ -8,9 +8,9 @@ import cn.iocoder.yudao.framework.common.core.KeyValue; import cn.iocoder.yudao.framework.common.enums.CommonStatusEnum; import cn.iocoder.yudao.framework.common.enums.UserTypeEnum; import cn.iocoder.yudao.framework.datapermission.core.annotation.DataPermission; -import cn.iocoder.yudao.framework.sms.core.client.SmsClient; -import cn.iocoder.yudao.framework.sms.core.client.dto.SmsReceiveRespDTO; -import cn.iocoder.yudao.framework.sms.core.client.dto.SmsSendRespDTO; +import cn.iocoder.yudao.module.system.framework.sms.core.client.SmsClient; +import cn.iocoder.yudao.module.system.framework.sms.core.client.dto.SmsReceiveRespDTO; +import cn.iocoder.yudao.module.system.framework.sms.core.client.dto.SmsSendRespDTO; import cn.iocoder.yudao.module.system.dal.dataobject.sms.SmsChannelDO; import cn.iocoder.yudao.module.system.dal.dataobject.sms.SmsTemplateDO; import cn.iocoder.yudao.module.system.dal.dataobject.user.AdminUserDO; diff --git a/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/service/sms/SmsTemplateServiceImpl.java b/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/service/sms/SmsTemplateServiceImpl.java index 809670732..a8762a92c 100644 --- a/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/service/sms/SmsTemplateServiceImpl.java +++ b/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/service/sms/SmsTemplateServiceImpl.java @@ -7,9 +7,9 @@ import cn.hutool.core.util.StrUtil; import cn.iocoder.yudao.framework.common.enums.CommonStatusEnum; import cn.iocoder.yudao.framework.common.pojo.PageResult; import cn.iocoder.yudao.framework.common.util.object.BeanUtils; -import cn.iocoder.yudao.framework.sms.core.client.SmsClient; -import cn.iocoder.yudao.framework.sms.core.client.dto.SmsTemplateRespDTO; -import cn.iocoder.yudao.framework.sms.core.enums.SmsTemplateAuditStatusEnum; +import cn.iocoder.yudao.module.system.framework.sms.core.client.SmsClient; +import cn.iocoder.yudao.module.system.framework.sms.core.client.dto.SmsTemplateRespDTO; +import cn.iocoder.yudao.module.system.framework.sms.core.enums.SmsTemplateAuditStatusEnum; import cn.iocoder.yudao.module.system.controller.admin.sms.vo.template.SmsTemplatePageReqVO; import cn.iocoder.yudao.module.system.controller.admin.sms.vo.template.SmsTemplateSaveReqVO; import cn.iocoder.yudao.module.system.dal.dataobject.sms.SmsChannelDO; diff --git a/yudao-framework/yudao-spring-boot-starter-biz-sms/src/test/java/cn/iocoder/yudao/framework/sms/core/client/impl/aliyun/AliyunSmsClientTest.java b/yudao-module-system/yudao-module-system-biz/src/test/java/cn/iocoder/yudao/module/system/framework/sms/core/client/impl/AliyunSmsClientTest.java similarity index 93% rename from yudao-framework/yudao-spring-boot-starter-biz-sms/src/test/java/cn/iocoder/yudao/framework/sms/core/client/impl/aliyun/AliyunSmsClientTest.java rename to yudao-module-system/yudao-module-system-biz/src/test/java/cn/iocoder/yudao/module/system/framework/sms/core/client/impl/AliyunSmsClientTest.java index c60cd26a1..ac26d139b 100644 --- a/yudao-framework/yudao-spring-boot-starter-biz-sms/src/test/java/cn/iocoder/yudao/framework/sms/core/client/impl/aliyun/AliyunSmsClientTest.java +++ b/yudao-module-system/yudao-module-system-biz/src/test/java/cn/iocoder/yudao/module/system/framework/sms/core/client/impl/AliyunSmsClientTest.java @@ -1,14 +1,14 @@ -package cn.iocoder.yudao.framework.sms.core.client.impl.aliyun; +package cn.iocoder.yudao.module.system.framework.sms.core.client.impl; import cn.hutool.core.util.ReflectUtil; import cn.iocoder.yudao.framework.common.core.KeyValue; import cn.iocoder.yudao.framework.common.util.collection.MapUtils; -import cn.iocoder.yudao.framework.sms.core.client.dto.SmsReceiveRespDTO; -import cn.iocoder.yudao.framework.sms.core.client.dto.SmsSendRespDTO; -import cn.iocoder.yudao.framework.sms.core.client.dto.SmsTemplateRespDTO; -import cn.iocoder.yudao.framework.sms.core.enums.SmsTemplateAuditStatusEnum; -import cn.iocoder.yudao.framework.sms.core.property.SmsChannelProperties; import cn.iocoder.yudao.framework.test.core.ut.BaseMockitoUnitTest; +import cn.iocoder.yudao.module.system.framework.sms.core.client.dto.SmsReceiveRespDTO; +import cn.iocoder.yudao.module.system.framework.sms.core.client.dto.SmsSendRespDTO; +import cn.iocoder.yudao.module.system.framework.sms.core.client.dto.SmsTemplateRespDTO; +import cn.iocoder.yudao.module.system.framework.sms.core.enums.SmsTemplateAuditStatusEnum; +import cn.iocoder.yudao.module.system.framework.sms.core.property.SmsChannelProperties; import com.aliyuncs.IAcsClient; import com.aliyuncs.dysmsapi.model.v20170525.QuerySmsTemplateRequest; import com.aliyuncs.dysmsapi.model.v20170525.QuerySmsTemplateResponse; diff --git a/yudao-framework/yudao-spring-boot-starter-biz-sms/src/test/java/cn/iocoder/yudao/framework/sms/core/client/impl/tencent/TencentSmsClientTest.java b/yudao-module-system/yudao-module-system-biz/src/test/java/cn/iocoder/yudao/module/system/framework/sms/core/client/impl/TencentSmsClientTest.java similarity index 95% rename from yudao-framework/yudao-spring-boot-starter-biz-sms/src/test/java/cn/iocoder/yudao/framework/sms/core/client/impl/tencent/TencentSmsClientTest.java rename to yudao-module-system/yudao-module-system-biz/src/test/java/cn/iocoder/yudao/module/system/framework/sms/core/client/impl/TencentSmsClientTest.java index d62eed1e1..e93435f4d 100644 --- a/yudao-framework/yudao-spring-boot-starter-biz-sms/src/test/java/cn/iocoder/yudao/framework/sms/core/client/impl/tencent/TencentSmsClientTest.java +++ b/yudao-module-system/yudao-module-system-biz/src/test/java/cn/iocoder/yudao/module/system/framework/sms/core/client/impl/TencentSmsClientTest.java @@ -1,16 +1,16 @@ -package cn.iocoder.yudao.framework.sms.core.client.impl.tencent; +package cn.iocoder.yudao.module.system.framework.sms.core.client.impl; import cn.hutool.core.util.ReflectUtil; import cn.iocoder.yudao.framework.common.core.KeyValue; import cn.iocoder.yudao.framework.common.util.collection.ArrayUtils; import cn.iocoder.yudao.framework.common.util.collection.MapUtils; import cn.iocoder.yudao.framework.common.util.json.JsonUtils; -import cn.iocoder.yudao.framework.sms.core.client.dto.SmsReceiveRespDTO; -import cn.iocoder.yudao.framework.sms.core.client.dto.SmsSendRespDTO; -import cn.iocoder.yudao.framework.sms.core.client.dto.SmsTemplateRespDTO; -import cn.iocoder.yudao.framework.sms.core.enums.SmsTemplateAuditStatusEnum; -import cn.iocoder.yudao.framework.sms.core.property.SmsChannelProperties; import cn.iocoder.yudao.framework.test.core.ut.BaseMockitoUnitTest; +import cn.iocoder.yudao.module.system.framework.sms.core.client.dto.SmsReceiveRespDTO; +import cn.iocoder.yudao.module.system.framework.sms.core.client.dto.SmsSendRespDTO; +import cn.iocoder.yudao.module.system.framework.sms.core.client.dto.SmsTemplateRespDTO; +import cn.iocoder.yudao.module.system.framework.sms.core.enums.SmsTemplateAuditStatusEnum; +import cn.iocoder.yudao.module.system.framework.sms.core.property.SmsChannelProperties; import com.google.common.collect.Lists; import com.tencentcloudapi.sms.v20210111.SmsClient; import com.tencentcloudapi.sms.v20210111.models.DescribeSmsTemplateListResponse; diff --git a/yudao-module-system/yudao-module-system-biz/src/test/java/cn/iocoder/yudao/module/system/service/sms/SmsChannelServiceTest.java b/yudao-module-system/yudao-module-system-biz/src/test/java/cn/iocoder/yudao/module/system/service/sms/SmsChannelServiceTest.java index 02842ea28..1cc9152c3 100644 --- a/yudao-module-system/yudao-module-system-biz/src/test/java/cn/iocoder/yudao/module/system/service/sms/SmsChannelServiceTest.java +++ b/yudao-module-system/yudao-module-system-biz/src/test/java/cn/iocoder/yudao/module/system/service/sms/SmsChannelServiceTest.java @@ -3,9 +3,9 @@ package cn.iocoder.yudao.module.system.service.sms; import cn.iocoder.yudao.framework.common.enums.CommonStatusEnum; import cn.iocoder.yudao.framework.common.pojo.PageResult; import cn.iocoder.yudao.framework.common.util.object.BeanUtils; -import cn.iocoder.yudao.framework.sms.core.client.SmsClient; -import cn.iocoder.yudao.framework.sms.core.client.SmsClientFactory; -import cn.iocoder.yudao.framework.sms.core.property.SmsChannelProperties; +import cn.iocoder.yudao.module.system.framework.sms.core.client.SmsClient; +import cn.iocoder.yudao.module.system.framework.sms.core.client.SmsClientFactory; +import cn.iocoder.yudao.module.system.framework.sms.core.property.SmsChannelProperties; import cn.iocoder.yudao.framework.test.core.ut.BaseDbUnitTest; import cn.iocoder.yudao.module.system.controller.admin.sms.vo.channel.SmsChannelPageReqVO; import cn.iocoder.yudao.module.system.controller.admin.sms.vo.channel.SmsChannelSaveReqVO; diff --git a/yudao-module-system/yudao-module-system-biz/src/test/java/cn/iocoder/yudao/module/system/service/sms/SmsCodeServiceImplTest.java b/yudao-module-system/yudao-module-system-biz/src/test/java/cn/iocoder/yudao/module/system/service/sms/SmsCodeServiceImplTest.java index 2888dcefe..ef9d2ff23 100644 --- a/yudao-module-system/yudao-module-system-biz/src/test/java/cn/iocoder/yudao/module/system/service/sms/SmsCodeServiceImplTest.java +++ b/yudao-module-system/yudao-module-system-biz/src/test/java/cn/iocoder/yudao/module/system/service/sms/SmsCodeServiceImplTest.java @@ -9,7 +9,7 @@ import cn.iocoder.yudao.module.system.api.sms.dto.code.SmsCodeValidateReqDTO; import cn.iocoder.yudao.module.system.dal.dataobject.sms.SmsCodeDO; import cn.iocoder.yudao.module.system.dal.mysql.sms.SmsCodeMapper; import cn.iocoder.yudao.module.system.enums.sms.SmsSceneEnum; -import cn.iocoder.yudao.module.system.framework.sms.SmsCodeProperties; +import cn.iocoder.yudao.module.system.framework.sms.config.SmsCodeProperties; import com.baomidou.mybatisplus.annotation.DbType; import org.junit.jupiter.api.BeforeEach; import org.junit.jupiter.api.Test; diff --git a/yudao-module-system/yudao-module-system-biz/src/test/java/cn/iocoder/yudao/module/system/service/sms/SmsSendServiceImplTest.java b/yudao-module-system/yudao-module-system-biz/src/test/java/cn/iocoder/yudao/module/system/service/sms/SmsSendServiceImplTest.java index 6e35fe31a..487c6f7fe 100644 --- a/yudao-module-system/yudao-module-system-biz/src/test/java/cn/iocoder/yudao/module/system/service/sms/SmsSendServiceImplTest.java +++ b/yudao-module-system/yudao-module-system-biz/src/test/java/cn/iocoder/yudao/module/system/service/sms/SmsSendServiceImplTest.java @@ -4,9 +4,9 @@ import cn.hutool.core.map.MapUtil; import cn.iocoder.yudao.framework.common.core.KeyValue; import cn.iocoder.yudao.framework.common.enums.CommonStatusEnum; import cn.iocoder.yudao.framework.common.enums.UserTypeEnum; -import cn.iocoder.yudao.framework.sms.core.client.SmsClient; -import cn.iocoder.yudao.framework.sms.core.client.dto.SmsReceiveRespDTO; -import cn.iocoder.yudao.framework.sms.core.client.dto.SmsSendRespDTO; +import cn.iocoder.yudao.module.system.framework.sms.core.client.SmsClient; +import cn.iocoder.yudao.module.system.framework.sms.core.client.dto.SmsReceiveRespDTO; +import cn.iocoder.yudao.module.system.framework.sms.core.client.dto.SmsSendRespDTO; import cn.iocoder.yudao.framework.test.core.ut.BaseMockitoUnitTest; import cn.iocoder.yudao.module.system.dal.dataobject.sms.SmsChannelDO; import cn.iocoder.yudao.module.system.dal.dataobject.sms.SmsTemplateDO; diff --git a/yudao-module-system/yudao-module-system-biz/src/test/java/cn/iocoder/yudao/module/system/service/sms/SmsTemplateServiceImplTest.java b/yudao-module-system/yudao-module-system-biz/src/test/java/cn/iocoder/yudao/module/system/service/sms/SmsTemplateServiceImplTest.java index b4d0c0e0f..22f737d80 100644 --- a/yudao-module-system/yudao-module-system-biz/src/test/java/cn/iocoder/yudao/module/system/service/sms/SmsTemplateServiceImplTest.java +++ b/yudao-module-system/yudao-module-system-biz/src/test/java/cn/iocoder/yudao/module/system/service/sms/SmsTemplateServiceImplTest.java @@ -5,9 +5,9 @@ import cn.iocoder.yudao.framework.common.enums.CommonStatusEnum; import cn.iocoder.yudao.framework.common.pojo.PageResult; import cn.iocoder.yudao.framework.common.util.collection.ArrayUtils; import cn.iocoder.yudao.framework.common.util.object.ObjectUtils; -import cn.iocoder.yudao.framework.sms.core.client.SmsClient; -import cn.iocoder.yudao.framework.sms.core.client.dto.SmsTemplateRespDTO; -import cn.iocoder.yudao.framework.sms.core.enums.SmsTemplateAuditStatusEnum; +import cn.iocoder.yudao.module.system.framework.sms.core.client.SmsClient; +import cn.iocoder.yudao.module.system.framework.sms.core.client.dto.SmsTemplateRespDTO; +import cn.iocoder.yudao.module.system.framework.sms.core.enums.SmsTemplateAuditStatusEnum; import cn.iocoder.yudao.framework.test.core.ut.BaseDbUnitTest; import cn.iocoder.yudao.module.system.controller.admin.sms.vo.template.SmsTemplatePageReqVO; import cn.iocoder.yudao.module.system.controller.admin.sms.vo.template.SmsTemplateSaveReqVO; From 524ee8c4674cc5b16ab5465a6b3c8dcd2cc2d5df Mon Sep 17 00:00:00 2001 From: YunaiV Date: Sat, 27 Jan 2024 13:06:15 +0800 Subject: [PATCH 038/119] =?UTF-8?q?=E2=9C=A8=20=E5=85=A8=E5=B1=80=EF=BC=9A?= =?UTF-8?q?=E5=B0=86=20sms=20=E8=9E=8D=E5=90=88=E5=88=B0=20system=20?= =?UTF-8?q?=E6=A8=A1=E5=9D=97=E9=87=8C=EF=BC=8C=E5=87=8F=E5=B0=91=20starte?= =?UTF-8?q?r?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- yudao-framework/pom.xml | 1 - .../yudao-spring-boot-starter-biz-sms/pom.xml | 82 ------------------- 2 files changed, 83 deletions(-) delete mode 100644 yudao-framework/yudao-spring-boot-starter-biz-sms/pom.xml diff --git a/yudao-framework/pom.xml b/yudao-framework/pom.xml index 3e98ea301..9595bbdbd 100644 --- a/yudao-framework/pom.xml +++ b/yudao-framework/pom.xml @@ -27,7 +27,6 @@ yudao-spring-boot-starter-biz-operatelog yudao-spring-boot-starter-biz-dict - yudao-spring-boot-starter-biz-sms yudao-spring-boot-starter-biz-pay yudao-spring-boot-starter-biz-tenant diff --git a/yudao-framework/yudao-spring-boot-starter-biz-sms/pom.xml b/yudao-framework/yudao-spring-boot-starter-biz-sms/pom.xml deleted file mode 100644 index faa6a8d34..000000000 --- a/yudao-framework/yudao-spring-boot-starter-biz-sms/pom.xml +++ /dev/null @@ -1,82 +0,0 @@ - - - - cn.iocoder.boot - yudao-framework - ${revision} - - 4.0.0 - yudao-spring-boot-starter-biz-sms - jar - - ${project.artifactId} - 短信拓展,支持阿里云、腾讯云 - https://github.com/YunaiV/ruoyi-vue-pro - - - - cn.iocoder.boot - yudao-common - - - - - org.springframework.boot - spring-boot-starter - - - - - io.opentracing - opentracing-util - - - - - cn.iocoder.boot - yudao-spring-boot-starter-test - test - - - - - com.google.guava - guava - true - - - - com.fasterxml.jackson.core - jackson-databind - - - com.fasterxml.jackson.core - jackson-core - - - - jakarta.validation - jakarta.validation-api - - - - - - - com.aliyun - aliyun-java-sdk-core - - - com.aliyun - aliyun-java-sdk-dysmsapi - - - com.tencentcloudapi - tencentcloud-sdk-java-sms - - - - - From 35205edff91ff31c32b63e4d60e4cd9c59acc0fb Mon Sep 17 00:00:00 2001 From: YunaiV Date: Sat, 27 Jan 2024 13:09:25 +0800 Subject: [PATCH 039/119] =?UTF-8?q?=E2=9C=A8=20=E5=85=A8=E5=B1=80=EF=BC=9A?= =?UTF-8?q?=E5=B0=86=20sms=20=E8=9E=8D=E5=90=88=E5=88=B0=20system=20?= =?UTF-8?q?=E6=A8=A1=E5=9D=97=E9=87=8C=EF=BC=8C=E5=87=8F=E5=B0=91=20starte?= =?UTF-8?q?r?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- yudao-dependencies/pom.xml | 5 ----- yudao-module-system/yudao-module-system-biz/pom.xml | 4 ---- 2 files changed, 9 deletions(-) diff --git a/yudao-dependencies/pom.xml b/yudao-dependencies/pom.xml index a23f602be..9f641c1d0 100644 --- a/yudao-dependencies/pom.xml +++ b/yudao-dependencies/pom.xml @@ -111,11 +111,6 @@ yudao-spring-boot-starter-biz-dict ${revision} - - cn.iocoder.boot - yudao-spring-boot-starter-biz-sms - ${revision} - cn.iocoder.boot yudao-spring-boot-starter-biz-pay diff --git a/yudao-module-system/yudao-module-system-biz/pom.xml b/yudao-module-system/yudao-module-system-biz/pom.xml index 87c076c78..350ff4bad 100644 --- a/yudao-module-system/yudao-module-system-biz/pom.xml +++ b/yudao-module-system/yudao-module-system-biz/pom.xml @@ -34,10 +34,6 @@ cn.iocoder.boot yudao-spring-boot-starter-biz-operatelog - - cn.iocoder.boot - yudao-spring-boot-starter-biz-sms - cn.iocoder.boot yudao-spring-boot-starter-biz-dict From d8b2da8eed232143f04f90c43472bf51fb9e4e02 Mon Sep 17 00:00:00 2001 From: puhui999 Date: Sat, 27 Jan 2024 13:34:59 +0800 Subject: [PATCH 040/119] =?UTF-8?q?CRM-=E5=AE=A2=E6=88=B7:=20=E5=AE=8C?= =?UTF-8?q?=E5=96=84=20TODO?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- yudao-module-crm/yudao-module-crm-biz/pom.xml | 10 +++---- .../dal/mysql/customer/CrmCustomerMapper.java | 6 ++-- .../core/util/CrmPermissionUtils.java | 29 ------------------- .../customer/CrmCustomerAutoPutPoolJob.java | 2 +- .../service/customer/CrmCustomerService.java | 3 +- .../customer/CrmCustomerServiceImpl.java | 22 +++++++------- .../CrmFollowUpRecordServiceImpl.java | 3 +- .../permission/CrmPermissionService.java | 11 +++++++ .../permission/CrmPermissionServiceImpl.java | 8 +++++ 9 files changed, 40 insertions(+), 54 deletions(-) diff --git a/yudao-module-crm/yudao-module-crm-biz/pom.xml b/yudao-module-crm/yudao-module-crm-biz/pom.xml index 234cf268e..c54b61c89 100644 --- a/yudao-module-crm/yudao-module-crm-biz/pom.xml +++ b/yudao-module-crm/yudao-module-crm-biz/pom.xml @@ -37,6 +37,10 @@ cn.iocoder.boot yudao-spring-boot-starter-biz-ip + + cn.iocoder.boot + yudao-spring-boot-starter-biz-tenant + @@ -70,11 +74,5 @@ cn.iocoder.boot yudao-spring-boot-starter-test - - - - cn.iocoder.boot - yudao-spring-boot-starter-biz-tenant - diff --git a/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/dal/mysql/customer/CrmCustomerMapper.java b/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/dal/mysql/customer/CrmCustomerMapper.java index 79ba99d22..f0c18f52d 100644 --- a/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/dal/mysql/customer/CrmCustomerMapper.java +++ b/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/dal/mysql/customer/CrmCustomerMapper.java @@ -100,11 +100,11 @@ public interface CrmCustomerMapper extends BaseMapperX { return selectJoinPage(pageReqVO, CrmCustomerDO.class, query); } - default List selectListByLockStatusAndOwnerUserIdNotNull(Boolean lockStatus) { + default List selectListByLockAndDealStatusAndNotPool(Boolean lockStatus, Boolean dealStatus) { return selectList(new LambdaQueryWrapper() .eq(CrmCustomerDO::getLockStatus, lockStatus) - // TODO @puhui999:not null 可以转化成大于 0 - .isNotNull(CrmCustomerDO::getOwnerUserId)); + .eq(CrmCustomerDO::getDealStatus, dealStatus) + .gt(CrmCustomerDO::getOwnerUserId, 0)); } } diff --git a/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/framework/permission/core/util/CrmPermissionUtils.java b/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/framework/permission/core/util/CrmPermissionUtils.java index 4e5898455..43bb729b6 100644 --- a/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/framework/permission/core/util/CrmPermissionUtils.java +++ b/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/framework/permission/core/util/CrmPermissionUtils.java @@ -1,17 +1,9 @@ package cn.iocoder.yudao.module.crm.framework.permission.core.util; -import cn.hutool.core.util.ObjUtil; import cn.hutool.extra.spring.SpringUtil; -import cn.iocoder.yudao.module.crm.dal.dataobject.permission.CrmPermissionDO; -import cn.iocoder.yudao.module.crm.enums.common.CrmBizTypeEnum; -import cn.iocoder.yudao.module.crm.enums.permission.CrmPermissionLevelEnum; import cn.iocoder.yudao.module.crm.enums.permission.CrmPermissionRoleCodeEnum; -import cn.iocoder.yudao.module.crm.service.permission.CrmPermissionService; import cn.iocoder.yudao.module.system.api.permission.PermissionApi; -import java.util.List; - -import static cn.iocoder.yudao.framework.common.util.collection.CollectionUtils.anyMatch; import static cn.iocoder.yudao.framework.security.core.util.SecurityFrameworkUtils.getLoginUserId; /** @@ -30,22 +22,6 @@ public class CrmPermissionUtils { return SingletonManager.getPermissionApi().hasAnyRoles(getLoginUserId(), CrmPermissionRoleCodeEnum.CRM_ADMIN.getCode()); } - // TODO @puhui999:这个貌似直接放到 CrmPermissionService 会更好? - /** - * 校验权限 - * - * @param bizType 数据类型,关联 {@link CrmBizTypeEnum} - * @param bizId 数据编号,关联 {@link CrmBizTypeEnum} 对应模块 DO#getId() - * @param userId 用户编号 - * @param levelEnum 权限级别 - * @return boolean - */ - public static boolean hasPermission(Integer bizType, Long bizId, Long userId, CrmPermissionLevelEnum levelEnum) { - List permissionList = SingletonManager.getCrmPermissionService().getPermissionListByBiz(bizType, bizId); - return anyMatch(permissionList, permission -> - ObjUtil.equal(permission.getUserId(), userId) && ObjUtil.equal(permission.getLevel(), levelEnum.getLevel())); - } - /** * 静态内部类实现单例获取 * @@ -54,16 +30,11 @@ public class CrmPermissionUtils { private static class SingletonManager { private static final PermissionApi PERMISSION_API = SpringUtil.getBean(PermissionApi.class); - private static final CrmPermissionService CRM_PERMISSION_SERVICE = SpringUtil.getBean(CrmPermissionService.class); public static PermissionApi getPermissionApi() { return PERMISSION_API; } - public static CrmPermissionService getCrmPermissionService() { - return CRM_PERMISSION_SERVICE; - } - } } diff --git a/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/job/customer/CrmCustomerAutoPutPoolJob.java b/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/job/customer/CrmCustomerAutoPutPoolJob.java index 3d71df4f4..6f5817015 100644 --- a/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/job/customer/CrmCustomerAutoPutPoolJob.java +++ b/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/job/customer/CrmCustomerAutoPutPoolJob.java @@ -20,7 +20,7 @@ public class CrmCustomerAutoPutPoolJob implements JobHandler { @Override @TenantJob public String execute(String param) { - int count = customerService.customerAutoPutPoolBySystem(); + int count = customerService.autoPutCustomerPool(); return String.format("掉入公海客户 %s 个", count); } diff --git a/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/service/customer/CrmCustomerService.java b/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/service/customer/CrmCustomerService.java index bff150c14..dc5c9448e 100644 --- a/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/service/customer/CrmCustomerService.java +++ b/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/service/customer/CrmCustomerService.java @@ -126,12 +126,11 @@ public interface CrmCustomerService { */ void receiveCustomer(List ids, Long ownerUserId, Boolean isReceive); - // TODO @puhui999:autoPutCustomerPool,注释说明是系统就好哈; /** * 【系统】客户自动掉入公海 * * @return 掉入公海数量 */ - int customerAutoPutPoolBySystem(); + int autoPutCustomerPool(); } diff --git a/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/service/customer/CrmCustomerServiceImpl.java b/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/service/customer/CrmCustomerServiceImpl.java index ff9d9a030..ace7b21d4 100644 --- a/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/service/customer/CrmCustomerServiceImpl.java +++ b/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/service/customer/CrmCustomerServiceImpl.java @@ -47,6 +47,7 @@ import java.util.Collections; import java.util.List; import static cn.iocoder.yudao.framework.common.exception.util.ServiceExceptionUtil.exception; +import static cn.iocoder.yudao.framework.common.util.collection.CollectionUtils.filterList; import static cn.iocoder.yudao.module.crm.enums.ErrorCodeConstants.*; import static cn.iocoder.yudao.module.crm.enums.LogRecordConstants.*; import static cn.iocoder.yudao.module.crm.enums.customer.CrmCustomerLimitConfigTypeEnum.CUSTOMER_LOCK_LIMIT; @@ -313,23 +314,22 @@ public class CrmCustomerServiceImpl implements CrmCustomerService { } @Override - public int customerAutoPutPoolBySystem() { + public int autoPutCustomerPool() { CrmCustomerPoolConfigDO poolConfig = customerPoolConfigService.getCustomerPoolConfig(); if (poolConfig == null || !poolConfig.getEnabled()) { return 0; } - // 1. 获取没有锁定的不在公海的客户 - List customerList = customerMapper.selectListByLockStatusAndOwnerUserIdNotNull(Boolean.FALSE); - List poolCustomerList = CollectionUtils.filterList(customerList, customer -> { - // TODO @puhui999:建议这里作为一个查询条件哈,不放内存里过滤; - // 1.1 未成交放入公海 - if (!customer.getDealStatus()) { - return (poolConfig.getDealExpireDays() - LocalDateTimeUtils.between(customer.getCreateTime())) <= 0; - } - // 1.2 未跟进放入公海 + // 1.1 获取没有锁定的不在公海的客户且没有成交的 + List notDealCustomerList = customerMapper.selectListByLockAndDealStatusAndNotPool(Boolean.FALSE, Boolean.FALSE); + // 1.2 获取没有锁定的不在公海的客户且成交的 + List dealCustomerList = customerMapper.selectListByLockAndDealStatusAndNotPool(Boolean.FALSE, Boolean.TRUE); + List poolCustomerList = new ArrayList<>(); + poolCustomerList.addAll(filterList(notDealCustomerList, customer -> + (poolConfig.getDealExpireDays() - LocalDateTimeUtils.between(customer.getCreateTime())) <= 0)); + poolCustomerList.addAll(filterList(dealCustomerList, customer -> { LocalDateTime lastTime = ObjUtil.defaultIfNull(customer.getContactLastTime(), customer.getCreateTime()); return (poolConfig.getContactExpireDays() - LocalDateTimeUtils.between(lastTime)) <= 0; - }); + })); // 2. 逐个放入公海 int count = 0; diff --git a/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/service/followup/CrmFollowUpRecordServiceImpl.java b/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/service/followup/CrmFollowUpRecordServiceImpl.java index 9d6f87faa..88f0b887c 100644 --- a/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/service/followup/CrmFollowUpRecordServiceImpl.java +++ b/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/service/followup/CrmFollowUpRecordServiceImpl.java @@ -33,7 +33,6 @@ import static cn.iocoder.yudao.framework.common.exception.util.ServiceExceptionU import static cn.iocoder.yudao.framework.common.util.collection.CollectionUtils.convertList; import static cn.iocoder.yudao.module.crm.enums.ErrorCodeConstants.FOLLOW_UP_RECORD_DELETE_DENIED; import static cn.iocoder.yudao.module.crm.enums.ErrorCodeConstants.FOLLOW_UP_RECORD_NOT_EXISTS; -import static cn.iocoder.yudao.module.crm.framework.permission.core.util.CrmPermissionUtils.hasPermission; /** * 跟进记录 Service 实现类 @@ -119,7 +118,7 @@ public class CrmFollowUpRecordServiceImpl implements CrmFollowUpRecordService { // 校验存在 CrmFollowUpRecordDO followUpRecord = validateFollowUpRecordExists(id); // 校验权限 - if (!hasPermission(followUpRecord.getBizType(), followUpRecord.getBizId(), userId, CrmPermissionLevelEnum.OWNER)) { + if (!permissionService.hasPermission(followUpRecord.getBizType(), followUpRecord.getBizId(), userId, CrmPermissionLevelEnum.OWNER)) { throw exception(FOLLOW_UP_RECORD_DELETE_DENIED); } diff --git a/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/service/permission/CrmPermissionService.java b/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/service/permission/CrmPermissionService.java index e822ac2ff..3385899fe 100644 --- a/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/service/permission/CrmPermissionService.java +++ b/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/service/permission/CrmPermissionService.java @@ -108,4 +108,15 @@ public interface CrmPermissionService { */ List getPermissionListByBizTypeAndUserId(Integer bizType, Long userId); + /** + * 校验权限 + * + * @param bizType 数据类型,关联 {@link CrmBizTypeEnum} + * @param bizId 数据编号,关联 {@link CrmBizTypeEnum} 对应模块 DO#getId() + * @param userId 用户编号 + * @param levelEnum 权限级别 + * @return boolean + */ + boolean hasPermission(Integer bizType, Long bizId, Long userId, CrmPermissionLevelEnum levelEnum); + } diff --git a/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/service/permission/CrmPermissionServiceImpl.java b/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/service/permission/CrmPermissionServiceImpl.java index 07818bd07..36a616938 100644 --- a/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/service/permission/CrmPermissionServiceImpl.java +++ b/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/service/permission/CrmPermissionServiceImpl.java @@ -24,6 +24,7 @@ import java.util.List; import java.util.Set; import static cn.iocoder.yudao.framework.common.exception.util.ServiceExceptionUtil.exception; +import static cn.iocoder.yudao.framework.common.util.collection.CollectionUtils.anyMatch; import static cn.iocoder.yudao.framework.common.util.collection.CollectionUtils.convertSet; import static cn.iocoder.yudao.module.crm.enums.ErrorCodeConstants.*; import static cn.iocoder.yudao.module.crm.enums.permission.CrmPermissionLevelEnum.isOwner; @@ -211,4 +212,11 @@ public class CrmPermissionServiceImpl implements CrmPermissionService { return permissionMapper.selectListByBizTypeAndUserId(bizType, userId); } + @Override + public boolean hasPermission(Integer bizType, Long bizId, Long userId, CrmPermissionLevelEnum levelEnum) { + List permissionList = permissionMapper.selectByBizTypeAndBizId(bizType, bizId); + return anyMatch(permissionList, permission -> + ObjUtil.equal(permission.getUserId(), userId) && ObjUtil.equal(permission.getLevel(), levelEnum.getLevel())); + } + } From 4605e931051898ef9a5d3fbe948f8458638ab099 Mon Sep 17 00:00:00 2001 From: puhui999 Date: Sat, 27 Jan 2024 14:30:30 +0800 Subject: [PATCH 041/119] =?UTF-8?q?CRM-=E5=AE=A2=E6=88=B7:=20=E5=AE=8C?= =?UTF-8?q?=E5=96=84=E5=AE=A2=E6=88=B7=E5=AF=BC=E5=85=A5?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../module/crm/enums/ErrorCodeConstants.java | 7 +- .../admin/customer/CrmCustomerController.java | 33 +++++++++ .../customer/vo/CrmCustomerImportExcelVO.java | 74 +++++++++++++++++++ .../customer/vo/CrmCustomerImportRespVO.java | 24 ++++++ .../dal/mysql/customer/CrmCustomerMapper.java | 4 + .../service/customer/CrmCustomerService.java | 14 +++- .../customer/CrmCustomerServiceImpl.java | 57 +++++++++++--- 7 files changed, 198 insertions(+), 15 deletions(-) create mode 100644 yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/controller/admin/customer/vo/CrmCustomerImportExcelVO.java create mode 100644 yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/controller/admin/customer/vo/CrmCustomerImportRespVO.java diff --git a/yudao-module-crm/yudao-module-crm-api/src/main/java/cn/iocoder/yudao/module/crm/enums/ErrorCodeConstants.java b/yudao-module-crm/yudao-module-crm-api/src/main/java/cn/iocoder/yudao/module/crm/enums/ErrorCodeConstants.java index 737e4100d..9db937aa6 100644 --- a/yudao-module-crm/yudao-module-crm-api/src/main/java/cn/iocoder/yudao/module/crm/enums/ErrorCodeConstants.java +++ b/yudao-module-crm/yudao-module-crm-api/src/main/java/cn/iocoder/yudao/module/crm/enums/ErrorCodeConstants.java @@ -26,8 +26,8 @@ public interface ErrorCodeConstants { // ========== 联系人管理 1-020-003-000 ========== ErrorCode CONTACT_NOT_EXISTS = new ErrorCode(1_020_003_000, "联系人不存在"); - ErrorCode CONTACT_BUSINESS_LINK_NOT_EXISTS = new ErrorCode( 1_020_003_001, "联系人商机关联不存在"); - ErrorCode CONTACT_DELETE_FAIL_CONTRACT_LINK_EXISTS = new ErrorCode( 1_020_003_002, "联系人已关联合同,不能删除"); + ErrorCode CONTACT_BUSINESS_LINK_NOT_EXISTS = new ErrorCode(1_020_003_001, "联系人商机关联不存在"); + ErrorCode CONTACT_DELETE_FAIL_CONTRACT_LINK_EXISTS = new ErrorCode(1_020_003_002, "联系人已关联合同,不能删除"); // ========== 回款 1-020-004-000 ========== ErrorCode RECEIVABLE_NOT_EXISTS = new ErrorCode(1_020_004_000, "回款不存在"); @@ -48,6 +48,9 @@ public interface ErrorCodeConstants { ErrorCode CUSTOMER_LOCK_EXCEED_LIMIT = new ErrorCode(1_020_006_009, "锁定客户失败,超出锁定规则上限"); ErrorCode CUSTOMER_OWNER_EXCEED_LIMIT = new ErrorCode(1_020_006_010, "操作失败,超出客户数拥有上限"); ErrorCode CUSTOMER_DELETE_FAIL_HAVE_REFERENCE = new ErrorCode(1_020_006_011, "删除客户失败,有关联{}"); + ErrorCode CUSTOMER_IMPORT_LIST_IS_EMPTY = new ErrorCode(1_020_006_012, "导入客户数据不能为空!"); + ErrorCode CUSTOMER_CREATE_NAME_NOT_NULL = new ErrorCode(1_020_006_013, "客户名称不能为空!"); + ErrorCode CUSTOMER_NAME_EXISTS = new ErrorCode(1_020_006_014, "已存在名为【{}】的客户!"); // ========== 权限管理 1_020_007_000 ========== ErrorCode CRM_PERMISSION_NOT_EXISTS = new ErrorCode(1_020_007_000, "数据权限不存在"); diff --git a/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/controller/admin/customer/CrmCustomerController.java b/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/controller/admin/customer/CrmCustomerController.java index 03893b817..fe802f86d 100644 --- a/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/controller/admin/customer/CrmCustomerController.java +++ b/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/controller/admin/customer/CrmCustomerController.java @@ -21,6 +21,7 @@ import cn.iocoder.yudao.module.system.api.user.AdminUserApi; import cn.iocoder.yudao.module.system.api.user.dto.AdminUserRespDTO; import io.swagger.v3.oas.annotations.Operation; import io.swagger.v3.oas.annotations.Parameter; +import io.swagger.v3.oas.annotations.Parameters; import io.swagger.v3.oas.annotations.tags.Tag; import jakarta.annotation.Resource; import jakarta.servlet.http.HttpServletResponse; @@ -29,9 +30,11 @@ import org.mapstruct.ap.internal.util.Collections; import org.springframework.security.access.prepost.PreAuthorize; import org.springframework.validation.annotation.Validated; import org.springframework.web.bind.annotation.*; +import org.springframework.web.multipart.MultipartFile; import java.io.IOException; import java.time.LocalDateTime; +import java.util.Arrays; import java.util.List; import java.util.Map; import java.util.stream.Stream; @@ -169,6 +172,36 @@ public class CrmCustomerController { BeanUtils.toBean(list, CrmCustomerRespVO.class)); } + @GetMapping("/get-import-template") + @Operation(summary = "获得导入客户模板") + public void importTemplate(HttpServletResponse response) throws IOException { + // 手动创建导出 demo + List list = Arrays.asList( + CrmCustomerImportExcelVO.builder().name("芋道").industryId(1).level(1).source(1).mobile("15601691300").telephone("") + .website("https://doc.iocoder.cn/").qq("").wechat("").email("yunai@iocoder.cn").description("").remark("") + .areaId(null).detailAddress("").build(), + CrmCustomerImportExcelVO.builder().name("源码").industryId(1).level(1).source(1).mobile("15601691300").telephone("") + .website("https://doc.iocoder.cn/").qq("").wechat("").email("yunai@iocoder.cn").description("").remark("") + .areaId(null).detailAddress("").build() + ); + // 输出 + ExcelUtils.write(response, "客户导入模板.xls", "客户列表", CrmCustomerImportExcelVO.class, list); + } + + @PostMapping("/import") + @Operation(summary = "导入客户") + @Parameters({ + @Parameter(name = "file", description = "Excel 文件", required = true), + @Parameter(name = "updateSupport", description = "是否支持更新,默认为 false", example = "true") + }) + @PreAuthorize("@ss.hasPermission('system:customer:import')") + public CommonResult importExcel(@RequestParam("file") MultipartFile file, + @RequestParam(value = "updateSupport", required = false, defaultValue = "false") Boolean updateSupport) throws Exception { + List list = ExcelUtils.read(file, CrmCustomerImportExcelVO.class); + return success(customerService.importCustomerList(list, updateSupport)); + } + + @PutMapping("/transfer") @Operation(summary = "转移客户") @PreAuthorize("@ss.hasPermission('crm:customer:update')") diff --git a/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/controller/admin/customer/vo/CrmCustomerImportExcelVO.java b/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/controller/admin/customer/vo/CrmCustomerImportExcelVO.java new file mode 100644 index 000000000..378abb6dd --- /dev/null +++ b/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/controller/admin/customer/vo/CrmCustomerImportExcelVO.java @@ -0,0 +1,74 @@ +package cn.iocoder.yudao.module.crm.controller.admin.customer.vo; + +import cn.iocoder.yudao.framework.excel.core.annotations.DictFormat; +import cn.iocoder.yudao.framework.excel.core.convert.DictConvert; +import com.alibaba.excel.annotation.ExcelProperty; +import jakarta.validation.constraints.Size; +import lombok.AllArgsConstructor; +import lombok.Builder; +import lombok.Data; +import lombok.NoArgsConstructor; +import lombok.experimental.Accessors; + +import static cn.iocoder.yudao.module.crm.enums.DictTypeConstants.*; + +/** + * 客户 Excel 导入 VO + */ +@Data +@Builder +@AllArgsConstructor +@NoArgsConstructor +@Accessors(chain = false) // 设置 chain = false,避免用户导入有问题 +public class CrmCustomerImportExcelVO { + + @ExcelProperty("客户名称") + private String name; + + @ExcelProperty(value = "所属行业", converter = DictConvert.class) + @DictFormat(CRM_CUSTOMER_INDUSTRY) + private Integer industryId; + + @ExcelProperty(value = "客户等级", converter = DictConvert.class) + @DictFormat(CRM_CUSTOMER_LEVEL) + private Integer level; + + @ExcelProperty(value = "客户来源", converter = DictConvert.class) + @DictFormat(CRM_CUSTOMER_SOURCE) + private Integer source; + + @ExcelProperty("手机") + private String mobile; + + @ExcelProperty("电话") + private String telephone; + + @ExcelProperty("网址") + private String website; + + @Size(max = 20, message = "QQ长度不能超过 20 个字符") + @ExcelProperty("QQ") + private String qq; + + @Size(max = 255, message = "微信长度不能超过 255 个字符") + @ExcelProperty("微信") + private String wechat; + + @Size(max = 255, message = "邮箱长度不能超过 255 个字符") + @ExcelProperty("邮箱") + private String email; + + @Size(max = 4096, message = "客户描述长度不能超过 4096 个字符") + @ExcelProperty("客户描述") + private String description; + + @ExcelProperty("备注") + private String remark; + + @ExcelProperty("地区编号") + private Integer areaId; + + @ExcelProperty("详细地址") + private String detailAddress; + +} diff --git a/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/controller/admin/customer/vo/CrmCustomerImportRespVO.java b/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/controller/admin/customer/vo/CrmCustomerImportRespVO.java new file mode 100644 index 000000000..de35b7b92 --- /dev/null +++ b/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/controller/admin/customer/vo/CrmCustomerImportRespVO.java @@ -0,0 +1,24 @@ +package cn.iocoder.yudao.module.crm.controller.admin.customer.vo; + +import io.swagger.v3.oas.annotations.media.Schema; +import lombok.Builder; +import lombok.Data; + +import java.util.List; +import java.util.Map; + +@Schema(description = "管理后台 - 客户导入 Response VO") +@Data +@Builder +public class CrmCustomerImportRespVO { + + @Schema(description = "创建成功的客户名数组", requiredMode = Schema.RequiredMode.REQUIRED) + private List createCustomerNames; + + @Schema(description = "更新成功的客户名数组", requiredMode = Schema.RequiredMode.REQUIRED) + private List updateCustomerNames; + + @Schema(description = "导入失败的客户集合,key 为客户名,value 为失败原因", requiredMode = Schema.RequiredMode.REQUIRED) + private Map failureCustomerNames; + +} diff --git a/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/dal/mysql/customer/CrmCustomerMapper.java b/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/dal/mysql/customer/CrmCustomerMapper.java index f0c18f52d..af8b0d176 100644 --- a/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/dal/mysql/customer/CrmCustomerMapper.java +++ b/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/dal/mysql/customer/CrmCustomerMapper.java @@ -107,4 +107,8 @@ public interface CrmCustomerMapper extends BaseMapperX { .gt(CrmCustomerDO::getOwnerUserId, 0)); } + default CrmCustomerDO selectByCustomerName(String name) { + return selectOne(CrmCustomerDO::getName, name); + } + } diff --git a/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/service/customer/CrmCustomerService.java b/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/service/customer/CrmCustomerService.java index dc5c9448e..76e91b7d4 100644 --- a/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/service/customer/CrmCustomerService.java +++ b/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/service/customer/CrmCustomerService.java @@ -1,10 +1,7 @@ package cn.iocoder.yudao.module.crm.service.customer; import cn.iocoder.yudao.framework.common.pojo.PageResult; -import cn.iocoder.yudao.module.crm.controller.admin.customer.vo.CrmCustomerLockReqVO; -import cn.iocoder.yudao.module.crm.controller.admin.customer.vo.CrmCustomerPageReqVO; -import cn.iocoder.yudao.module.crm.controller.admin.customer.vo.CrmCustomerSaveReqVO; -import cn.iocoder.yudao.module.crm.controller.admin.customer.vo.CrmCustomerTransferReqVO; +import cn.iocoder.yudao.module.crm.controller.admin.customer.vo.*; import cn.iocoder.yudao.module.crm.dal.dataobject.customer.CrmCustomerDO; import cn.iocoder.yudao.module.crm.service.customer.bo.CrmCustomerCreateReqBO; import cn.iocoder.yudao.module.crm.service.followup.bo.CrmUpdateFollowUpReqBO; @@ -108,6 +105,15 @@ public interface CrmCustomerService { */ Long createCustomer(CrmCustomerCreateReqBO customerCreateReq, Long userId); + /** + * 批量导入客户 + * + * @param importCustomers 导入客户列表 + * @param isUpdateSupport 是否支持更新 + * @return 导入结果 + */ + CrmCustomerImportRespVO importCustomerList(List importCustomers, Boolean isUpdateSupport); + // ==================== 公海相关操作 ==================== /** diff --git a/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/service/customer/CrmCustomerServiceImpl.java b/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/service/customer/CrmCustomerServiceImpl.java index ace7b21d4..78493e046 100644 --- a/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/service/customer/CrmCustomerServiceImpl.java +++ b/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/service/customer/CrmCustomerServiceImpl.java @@ -3,15 +3,14 @@ package cn.iocoder.yudao.module.crm.service.customer; import cn.hutool.core.collection.CollUtil; import cn.hutool.core.lang.Assert; import cn.hutool.core.util.ObjUtil; +import cn.hutool.core.util.StrUtil; import cn.hutool.extra.spring.SpringUtil; +import cn.iocoder.yudao.framework.common.exception.ServiceException; import cn.iocoder.yudao.framework.common.pojo.PageResult; import cn.iocoder.yudao.framework.common.util.collection.CollectionUtils; import cn.iocoder.yudao.framework.common.util.date.LocalDateTimeUtils; import cn.iocoder.yudao.framework.common.util.object.BeanUtils; -import cn.iocoder.yudao.module.crm.controller.admin.customer.vo.CrmCustomerLockReqVO; -import cn.iocoder.yudao.module.crm.controller.admin.customer.vo.CrmCustomerPageReqVO; -import cn.iocoder.yudao.module.crm.controller.admin.customer.vo.CrmCustomerSaveReqVO; -import cn.iocoder.yudao.module.crm.controller.admin.customer.vo.CrmCustomerTransferReqVO; +import cn.iocoder.yudao.module.crm.controller.admin.customer.vo.*; import cn.iocoder.yudao.module.crm.convert.customer.CrmCustomerConvert; import cn.iocoder.yudao.module.crm.dal.dataobject.customer.CrmCustomerDO; import cn.iocoder.yudao.module.crm.dal.dataobject.customer.CrmCustomerLimitConfigDO; @@ -41,10 +40,7 @@ import org.springframework.transaction.annotation.Transactional; import org.springframework.validation.annotation.Validated; import java.time.LocalDateTime; -import java.util.ArrayList; -import java.util.Collection; -import java.util.Collections; -import java.util.List; +import java.util.*; import static cn.iocoder.yudao.framework.common.exception.util.ServiceExceptionUtil.exception; import static cn.iocoder.yudao.framework.common.util.collection.CollectionUtils.filterList; @@ -236,7 +232,50 @@ public class CrmCustomerServiceImpl implements CrmCustomerService { return customer.getId(); } -// ==================== 公海相关操作 ==================== + @Override + public CrmCustomerImportRespVO importCustomerList(List importCustomers, Boolean isUpdateSupport) { + if (CollUtil.isEmpty(importCustomers)) { + throw exception(CUSTOMER_IMPORT_LIST_IS_EMPTY); + } + CrmCustomerImportRespVO respVO = CrmCustomerImportRespVO.builder().createCustomerNames(new ArrayList<>()) + .updateCustomerNames(new ArrayList<>()).failureCustomerNames(new LinkedHashMap<>()).build(); + importCustomers.forEach(importCustomer -> { + // 校验,判断是否有不符合的原因 + try { + validateCustomerForCreate(importCustomer); + } catch (ServiceException ex) { + respVO.getFailureCustomerNames().put(importCustomer.getName(), ex.getMessage()); + return; + } + // 判断如果不存在,在进行插入 + CrmCustomerDO existCustomer = customerMapper.selectByCustomerName(importCustomer.getName()); + if (existCustomer == null) { + customerMapper.insert(BeanUtils.toBean(importCustomer, CrmCustomerDO.class)); + respVO.getCreateCustomerNames().add(importCustomer.getName()); + return; + } + // 如果存在,判断是否允许更新 + if (!isUpdateSupport) { + respVO.getFailureCustomerNames().put(importCustomer.getName(), + StrUtil.format(CUSTOMER_NAME_EXISTS.getMsg(), importCustomer.getName())); + return; + } + CrmCustomerDO updateCustomer = BeanUtils.toBean(importCustomer, CrmCustomerDO.class); + updateCustomer.setId(existCustomer.getId()); + customerMapper.updateById(updateCustomer); + respVO.getUpdateCustomerNames().add(importCustomer.getName()); + }); + return respVO; + } + + private void validateCustomerForCreate(CrmCustomerImportExcelVO importCustomer) { + // 校验客户名称不能为空 + if (StrUtil.isEmptyIfStr(importCustomer.getName())) { + throw exception(CUSTOMER_CREATE_NAME_NOT_NULL); + } + } + + // ==================== 公海相关操作 ==================== @Override @Transactional(rollbackFor = Exception.class) From a877bb47317a96220d8e05c0741bae1e57b447a8 Mon Sep 17 00:00:00 2001 From: puhui999 Date: Sat, 27 Jan 2024 15:15:30 +0800 Subject: [PATCH 042/119] =?UTF-8?q?CRM-=E5=AE=A2=E6=88=B7:=20=E5=AE=8C?= =?UTF-8?q?=E5=96=84=E5=AE=A2=E6=88=B7=E5=AF=BC=E5=85=A5?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../admin/customer/CrmCustomerController.java | 2 +- .../crm/service/customer/CrmCustomerService.java | 3 ++- .../crm/service/customer/CrmCustomerServiceImpl.java | 11 ++++++++--- 3 files changed, 11 insertions(+), 5 deletions(-) diff --git a/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/controller/admin/customer/CrmCustomerController.java b/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/controller/admin/customer/CrmCustomerController.java index fe802f86d..4bb158732 100644 --- a/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/controller/admin/customer/CrmCustomerController.java +++ b/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/controller/admin/customer/CrmCustomerController.java @@ -198,7 +198,7 @@ public class CrmCustomerController { public CommonResult importExcel(@RequestParam("file") MultipartFile file, @RequestParam(value = "updateSupport", required = false, defaultValue = "false") Boolean updateSupport) throws Exception { List list = ExcelUtils.read(file, CrmCustomerImportExcelVO.class); - return success(customerService.importCustomerList(list, updateSupport)); + return success(customerService.importCustomerList(list, updateSupport, getLoginUserId())); } diff --git a/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/service/customer/CrmCustomerService.java b/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/service/customer/CrmCustomerService.java index 76e91b7d4..0f068a1b3 100644 --- a/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/service/customer/CrmCustomerService.java +++ b/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/service/customer/CrmCustomerService.java @@ -110,9 +110,10 @@ public interface CrmCustomerService { * * @param importCustomers 导入客户列表 * @param isUpdateSupport 是否支持更新 + * @param userId 用户编号 * @return 导入结果 */ - CrmCustomerImportRespVO importCustomerList(List importCustomers, Boolean isUpdateSupport); + CrmCustomerImportRespVO importCustomerList(List importCustomers, Boolean isUpdateSupport, Long userId); // ==================== 公海相关操作 ==================== diff --git a/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/service/customer/CrmCustomerServiceImpl.java b/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/service/customer/CrmCustomerServiceImpl.java index 78493e046..74ec7783c 100644 --- a/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/service/customer/CrmCustomerServiceImpl.java +++ b/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/service/customer/CrmCustomerServiceImpl.java @@ -93,7 +93,7 @@ public class CrmCustomerServiceImpl implements CrmCustomerService { validateCustomerExceedOwnerLimit(createReqVO.getOwnerUserId(), 1); // 2. 插入客户 - CrmCustomerDO customer = BeanUtils.toBean(createReqVO, CrmCustomerDO.class) + CrmCustomerDO customer = BeanUtils.toBean(createReqVO, CrmCustomerDO.class).setOwnerUserId(userId) .setLockStatus(false).setDealStatus(false).setContactLastTime(LocalDateTime.now()); customerMapper.insert(customer); @@ -233,7 +233,7 @@ public class CrmCustomerServiceImpl implements CrmCustomerService { } @Override - public CrmCustomerImportRespVO importCustomerList(List importCustomers, Boolean isUpdateSupport) { + public CrmCustomerImportRespVO importCustomerList(List importCustomers, Boolean isUpdateSupport, Long userId) { if (CollUtil.isEmpty(importCustomers)) { throw exception(CUSTOMER_IMPORT_LIST_IS_EMPTY); } @@ -250,8 +250,13 @@ public class CrmCustomerServiceImpl implements CrmCustomerService { // 判断如果不存在,在进行插入 CrmCustomerDO existCustomer = customerMapper.selectByCustomerName(importCustomer.getName()); if (existCustomer == null) { - customerMapper.insert(BeanUtils.toBean(importCustomer, CrmCustomerDO.class)); + CrmCustomerDO customer = BeanUtils.toBean(importCustomer, CrmCustomerDO.class).setOwnerUserId(userId) + .setLockStatus(false).setDealStatus(false).setContactLastTime(LocalDateTime.now()); + customerMapper.insert(customer); respVO.getCreateCustomerNames().add(importCustomer.getName()); + // 创建数据权限 + permissionService.createPermission(new CrmPermissionCreateReqBO().setBizType(CrmBizTypeEnum.CRM_CUSTOMER.getType()) + .setBizId(customer.getId()).setUserId(userId).setLevel(CrmPermissionLevelEnum.OWNER.getLevel())); // 设置当前操作的人为负责人 return; } // 如果存在,判断是否允许更新 From ebd92227641046dfbce00a47ab0c4542979a58ed Mon Sep 17 00:00:00 2001 From: YunaiV Date: Sat, 27 Jan 2024 17:25:07 +0800 Subject: [PATCH 043/119] =?UTF-8?q?=E2=9C=A8=20ERP=EF=BC=9A=E5=88=9D?= =?UTF-8?q?=E5=A7=8B=E5=8C=96=E6=A8=A1=E5=9D=97=EF=BC=8C=E7=AB=8B=E4=B8=AA?= =?UTF-8?q?=202024=20=E5=B9=B4=E7=9A=84=20flag?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- pom.xml | 3 +- yudao-module-crm/pom.xml | 1 - .../admin/business/CrmBusinessController.java | 2 +- .../CrmBusinessStatusTypeController.java | 2 +- yudao-module-erp/pom.xml | 24 +++++++ yudao-module-erp/yudao-module-erp-api/pom.xml | 33 +++++++++ .../yudao/module/erp/api/package-info.java | 4 ++ .../module/erp/enums/DictTypeConstants.java | 10 +++ .../module/erp/enums/ErrorCodeConstants.java | 11 +++ .../module/erp/enums/LogRecordConstants.java | 12 ++++ yudao-module-erp/yudao-module-erp-biz/pom.xml | 72 +++++++++++++++++++ .../admin/sale/ErpSaleOrderController.http | 4 ++ .../admin/sale/ErpSaleOrderController.java | 23 ++++++ .../module/erp/controller/package-info.java | 6 ++ .../yudao/module/erp/package-info.java | 10 +++ yudao-server/pom.xml | 17 +++-- 16 files changed, 225 insertions(+), 9 deletions(-) create mode 100644 yudao-module-erp/pom.xml create mode 100644 yudao-module-erp/yudao-module-erp-api/pom.xml create mode 100644 yudao-module-erp/yudao-module-erp-api/src/main/java/cn/iocoder/yudao/module/erp/api/package-info.java create mode 100644 yudao-module-erp/yudao-module-erp-api/src/main/java/cn/iocoder/yudao/module/erp/enums/DictTypeConstants.java create mode 100644 yudao-module-erp/yudao-module-erp-api/src/main/java/cn/iocoder/yudao/module/erp/enums/ErrorCodeConstants.java create mode 100644 yudao-module-erp/yudao-module-erp-api/src/main/java/cn/iocoder/yudao/module/erp/enums/LogRecordConstants.java create mode 100644 yudao-module-erp/yudao-module-erp-biz/pom.xml create mode 100644 yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/controller/admin/sale/ErpSaleOrderController.http create mode 100644 yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/controller/admin/sale/ErpSaleOrderController.java create mode 100644 yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/controller/package-info.java create mode 100644 yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/package-info.java diff --git a/pom.xml b/pom.xml index 8a2e2a8f3..89807a7d0 100644 --- a/pom.xml +++ b/pom.xml @@ -21,7 +21,8 @@ - + yudao-module-crm + yudao-module-erp diff --git a/yudao-module-crm/pom.xml b/yudao-module-crm/pom.xml index 2a7b748c3..310a7df87 100644 --- a/yudao-module-crm/pom.xml +++ b/yudao-module-crm/pom.xml @@ -16,7 +16,6 @@ pom ${project.artifactId} - crm 包下,客户关系管理(Customer Relationship Management)。 例如说:客户、联系人、商机、合同、回款等等 diff --git a/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/controller/admin/business/CrmBusinessController.java b/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/controller/admin/business/CrmBusinessController.java index fd2154d7a..90b00dd48 100644 --- a/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/controller/admin/business/CrmBusinessController.java +++ b/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/controller/admin/business/CrmBusinessController.java @@ -41,7 +41,7 @@ import static cn.iocoder.yudao.framework.operatelog.core.enums.OperateTypeEnum.E import static cn.iocoder.yudao.framework.security.core.util.SecurityFrameworkUtils.getLoginUserId; import static cn.iocoder.yudao.module.crm.enums.ErrorCodeConstants.CUSTOMER_NOT_EXISTS; -@Tag(name = "管理后台 - 商机") +@Tag(name = "管理后台 - CRM 商机") @RestController @RequestMapping("/crm/business") @Validated diff --git a/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/controller/admin/business/CrmBusinessStatusTypeController.java b/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/controller/admin/business/CrmBusinessStatusTypeController.java index 231f66683..925fa4953 100644 --- a/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/controller/admin/business/CrmBusinessStatusTypeController.java +++ b/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/controller/admin/business/CrmBusinessStatusTypeController.java @@ -40,7 +40,7 @@ import java.util.Set; import static cn.iocoder.yudao.framework.common.pojo.CommonResult.success; import static cn.iocoder.yudao.framework.operatelog.core.enums.OperateTypeEnum.EXPORT; -@Tag(name = "管理后台 - 商机状态类型") +@Tag(name = "管理后台 - CRM 商机状态类型") @RestController @RequestMapping("/crm/business-status-type") @Validated diff --git a/yudao-module-erp/pom.xml b/yudao-module-erp/pom.xml new file mode 100644 index 000000000..22fe0eea4 --- /dev/null +++ b/yudao-module-erp/pom.xml @@ -0,0 +1,24 @@ + + + + cn.iocoder.boot + yudao + ${revision} + + + yudao-module-erp-api + yudao-module-erp-biz + + 4.0.0 + yudao-module-erp + pom + + ${project.artifactId} + + erp 包下,企业资源管理(Enterprise Resource Planning)。 + 例如说:采购、销售、库存、财务、产品等等 + + + \ No newline at end of file diff --git a/yudao-module-erp/yudao-module-erp-api/pom.xml b/yudao-module-erp/yudao-module-erp-api/pom.xml new file mode 100644 index 000000000..961845ce3 --- /dev/null +++ b/yudao-module-erp/yudao-module-erp-api/pom.xml @@ -0,0 +1,33 @@ + + + + cn.iocoder.boot + yudao-module-erp + ${revision} + + 4.0.0 + yudao-module-erp-api + jar + + ${project.artifactId} + + erp 模块 API,暴露给其它模块调用 + + + + + cn.iocoder.boot + yudao-common + + + + + org.springframework.boot + spring-boot-starter-validation + true + + + + \ No newline at end of file diff --git a/yudao-module-erp/yudao-module-erp-api/src/main/java/cn/iocoder/yudao/module/erp/api/package-info.java b/yudao-module-erp/yudao-module-erp-api/src/main/java/cn/iocoder/yudao/module/erp/api/package-info.java new file mode 100644 index 000000000..540f18f0e --- /dev/null +++ b/yudao-module-erp/yudao-module-erp-api/src/main/java/cn/iocoder/yudao/module/erp/api/package-info.java @@ -0,0 +1,4 @@ +/** + * erp API 包,定义暴露给其它模块的 API + */ +package cn.iocoder.yudao.module.erp.api; diff --git a/yudao-module-erp/yudao-module-erp-api/src/main/java/cn/iocoder/yudao/module/erp/enums/DictTypeConstants.java b/yudao-module-erp/yudao-module-erp-api/src/main/java/cn/iocoder/yudao/module/erp/enums/DictTypeConstants.java new file mode 100644 index 000000000..87b498543 --- /dev/null +++ b/yudao-module-erp/yudao-module-erp-api/src/main/java/cn/iocoder/yudao/module/erp/enums/DictTypeConstants.java @@ -0,0 +1,10 @@ +package cn.iocoder.yudao.module.erp.enums; + +/** + * ERP 字典类型的枚举类 + * + * @author 芋道源码 + */ +public interface DictTypeConstants { + +} diff --git a/yudao-module-erp/yudao-module-erp-api/src/main/java/cn/iocoder/yudao/module/erp/enums/ErrorCodeConstants.java b/yudao-module-erp/yudao-module-erp-api/src/main/java/cn/iocoder/yudao/module/erp/enums/ErrorCodeConstants.java new file mode 100644 index 000000000..371790559 --- /dev/null +++ b/yudao-module-erp/yudao-module-erp-api/src/main/java/cn/iocoder/yudao/module/erp/enums/ErrorCodeConstants.java @@ -0,0 +1,11 @@ +package cn.iocoder.yudao.module.erp.enums; + +/** + * ERP 错误码枚举类 + *

+ * erp 系统,使用 1-030-000-000 段 + */ +public interface ErrorCodeConstants { + + +} diff --git a/yudao-module-erp/yudao-module-erp-api/src/main/java/cn/iocoder/yudao/module/erp/enums/LogRecordConstants.java b/yudao-module-erp/yudao-module-erp-api/src/main/java/cn/iocoder/yudao/module/erp/enums/LogRecordConstants.java new file mode 100644 index 000000000..73b72c0a9 --- /dev/null +++ b/yudao-module-erp/yudao-module-erp-api/src/main/java/cn/iocoder/yudao/module/erp/enums/LogRecordConstants.java @@ -0,0 +1,12 @@ +package cn.iocoder.yudao.module.erp.enums; + +/** + * ERP 操作日志枚举 + * 目的:统一管理,也减少 Service 里各种“复杂”字符串 + * + * @author 芋道源码 + */ +public interface LogRecordConstants { + + +} diff --git a/yudao-module-erp/yudao-module-erp-biz/pom.xml b/yudao-module-erp/yudao-module-erp-biz/pom.xml new file mode 100644 index 000000000..83b3900cf --- /dev/null +++ b/yudao-module-erp/yudao-module-erp-biz/pom.xml @@ -0,0 +1,72 @@ + + + + cn.iocoder.boot + yudao-module-erp + ${revision} + + 4.0.0 + yudao-module-erp-biz + + ${project.artifactId} + + erp 包下,企业资源管理(Enterprise Resource Planning)。 + 例如说:采购、销售、库存、财务、产品等等 + + + + + cn.iocoder.boot + yudao-module-system-api + ${revision} + + + cn.iocoder.boot + yudao-module-erp-api + ${revision} + + + + + cn.iocoder.boot + yudao-spring-boot-starter-biz-operatelog + + + + + cn.iocoder.boot + yudao-spring-boot-starter-web + + + + cn.iocoder.boot + yudao-spring-boot-starter-security + + + + + cn.iocoder.boot + yudao-spring-boot-starter-mybatis + + + + + cn.iocoder.boot + yudao-spring-boot-starter-excel + + + cn.iocoder.boot + yudao-spring-boot-starter-biz-dict + + + + + cn.iocoder.boot + yudao-spring-boot-starter-test + + + + + \ No newline at end of file diff --git a/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/controller/admin/sale/ErpSaleOrderController.http b/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/controller/admin/sale/ErpSaleOrderController.http new file mode 100644 index 000000000..f8a5c970e --- /dev/null +++ b/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/controller/admin/sale/ErpSaleOrderController.http @@ -0,0 +1,4 @@ +### 请求 /transfer +GET {{baseUrl}}/erp/sale-order/demo +Authorization: Bearer {{token}} +tenant-id: {{adminTenentId}} \ No newline at end of file diff --git a/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/controller/admin/sale/ErpSaleOrderController.java b/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/controller/admin/sale/ErpSaleOrderController.java new file mode 100644 index 000000000..cd2425fe9 --- /dev/null +++ b/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/controller/admin/sale/ErpSaleOrderController.java @@ -0,0 +1,23 @@ +package cn.iocoder.yudao.module.erp.controller.admin.sale; + +import cn.iocoder.yudao.framework.common.pojo.CommonResult; +import io.swagger.v3.oas.annotations.tags.Tag; +import org.springframework.validation.annotation.Validated; +import org.springframework.web.bind.annotation.GetMapping; +import org.springframework.web.bind.annotation.RequestMapping; +import org.springframework.web.bind.annotation.RestController; + +import static cn.iocoder.yudao.framework.common.pojo.CommonResult.success; + +@Tag(name = "管理后台 - ERP 销售订单") +@RestController +@RequestMapping("/erp/sale-order") +@Validated +public class ErpSaleOrderController { + + @GetMapping("/demo") + public CommonResult demo() { + return success(true); + } + +} diff --git a/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/controller/package-info.java b/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/controller/package-info.java new file mode 100644 index 000000000..ef0e5accf --- /dev/null +++ b/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/controller/package-info.java @@ -0,0 +1,6 @@ +/** + * 提供 RESTful API 给前端: + * 1. admin 包:提供给管理后台 yudao-ui-admin 前端项目 + * 2. app 包:提供给用户 APP yudao-ui-app 前端项目,它的 Controller 和 VO 都要添加 App 前缀,用于和管理后台进行区分 + */ +package cn.iocoder.yudao.module.erp.controller; diff --git a/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/package-info.java b/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/package-info.java new file mode 100644 index 000000000..2608a9889 --- /dev/null +++ b/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/package-info.java @@ -0,0 +1,10 @@ +/** + * erp 包下,企业资源管理(Enterprise Resource Planning)。 + * 例如说:采购、销售、库存、财务、产品等等 + * + * 1. Controller URL:以 /erp/ 开头,避免和其它 Module 冲突 + * 2. DataObject 表名:以 erp_ 开头,方便在数据库中区分 + * + * 注意,由于 Erp 模块下,容易和其它模块重名,所以类名都加载 Erp 的前缀~ + */ +package cn.iocoder.yudao.module.erp; diff --git a/yudao-server/pom.xml b/yudao-server/pom.xml index 25e684e6c..7c288f725 100644 --- a/yudao-server/pom.xml +++ b/yudao-server/pom.xml @@ -88,11 +88,18 @@ - - - - - + + cn.iocoder.boot + yudao-module-crm-biz + ${revision} + + + + + cn.iocoder.boot + yudao-module-erp-biz + ${revision} + From 6e005f46d97596b7a59e757a5ea5d1f1ab303eab Mon Sep 17 00:00:00 2001 From: YunaiV Date: Sat, 27 Jan 2024 23:25:52 +0800 Subject: [PATCH 044/119] =?UTF-8?q?=E2=9C=A8=20ERP=EF=BC=9A=E3=80=90?= =?UTF-8?q?=E9=94=80=E5=94=AE=E8=AE=A2=E5=8D=95=E3=80=91=E5=88=9D=E5=A7=8B?= =?UTF-8?q?=E5=8C=96?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../module/erp/enums/ErrorCodeConstants.java | 4 + .../enums/sale/ErpSaleOrderStatusEnum.java | 40 +++++++ .../admin/sale/ErpSaleOrderController.java | 89 ++++++++++++++- .../sale/vo/order/ErpSaleOrderPageReqVO.java | 39 +++++++ .../sale/vo/order/ErpSaleOrderRespVO.java | 78 +++++++++++++ .../sale/vo/order/ErpSaleOrderSaveReqVO.java | 74 ++++++++++++ .../dal/dataobject/sale/ErpSaleOrderDO.java | 100 +++++++++++++++++ .../dataobject/sale/ErpSalesOrderItemDO.java | 88 +++++++++++++++ .../dal/mysql/sale/ErpSaleOrderMapper.java | 30 +++++ .../mysql/sale/ErpSalesOrderItemMapper.java | 25 +++++ .../erp/service/sale/ErpSaleOrderService.java | 54 +++++++++ .../service/sale/ErpSaleOrderServiceImpl.java | 106 ++++++++++++++++++ 12 files changed, 721 insertions(+), 6 deletions(-) create mode 100644 yudao-module-erp/yudao-module-erp-api/src/main/java/cn/iocoder/yudao/module/erp/enums/sale/ErpSaleOrderStatusEnum.java create mode 100644 yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/controller/admin/sale/vo/order/ErpSaleOrderPageReqVO.java create mode 100644 yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/controller/admin/sale/vo/order/ErpSaleOrderRespVO.java create mode 100644 yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/controller/admin/sale/vo/order/ErpSaleOrderSaveReqVO.java create mode 100644 yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/dal/dataobject/sale/ErpSaleOrderDO.java create mode 100644 yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/dal/dataobject/sale/ErpSalesOrderItemDO.java create mode 100644 yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/dal/mysql/sale/ErpSaleOrderMapper.java create mode 100644 yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/dal/mysql/sale/ErpSalesOrderItemMapper.java create mode 100644 yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/service/sale/ErpSaleOrderService.java create mode 100644 yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/service/sale/ErpSaleOrderServiceImpl.java diff --git a/yudao-module-erp/yudao-module-erp-api/src/main/java/cn/iocoder/yudao/module/erp/enums/ErrorCodeConstants.java b/yudao-module-erp/yudao-module-erp-api/src/main/java/cn/iocoder/yudao/module/erp/enums/ErrorCodeConstants.java index 371790559..7b11fa0a5 100644 --- a/yudao-module-erp/yudao-module-erp-api/src/main/java/cn/iocoder/yudao/module/erp/enums/ErrorCodeConstants.java +++ b/yudao-module-erp/yudao-module-erp-api/src/main/java/cn/iocoder/yudao/module/erp/enums/ErrorCodeConstants.java @@ -1,5 +1,7 @@ package cn.iocoder.yudao.module.erp.enums; +import cn.iocoder.yudao.framework.common.exception.ErrorCode; + /** * ERP 错误码枚举类 *

@@ -7,5 +9,7 @@ package cn.iocoder.yudao.module.erp.enums; */ public interface ErrorCodeConstants { + // ========== 销售订单(1-030-000-000) ========== + ErrorCode SALE_ORDER_NOT_EXISTS = new ErrorCode(1_030_000_000, "销售订单不存在"); } diff --git a/yudao-module-erp/yudao-module-erp-api/src/main/java/cn/iocoder/yudao/module/erp/enums/sale/ErpSaleOrderStatusEnum.java b/yudao-module-erp/yudao-module-erp-api/src/main/java/cn/iocoder/yudao/module/erp/enums/sale/ErpSaleOrderStatusEnum.java new file mode 100644 index 000000000..4caa7f515 --- /dev/null +++ b/yudao-module-erp/yudao-module-erp-api/src/main/java/cn/iocoder/yudao/module/erp/enums/sale/ErpSaleOrderStatusEnum.java @@ -0,0 +1,40 @@ +package cn.iocoder.yudao.module.erp.enums.sale; + +import cn.iocoder.yudao.framework.common.core.IntArrayValuable; +import lombok.AllArgsConstructor; +import lombok.Getter; + +import java.util.Arrays; + +/** + * ERP 销售订单的状态枚举 + * + * @author 芋道源码 + */ +@AllArgsConstructor +@Getter +public enum ErpSaleOrderStatusEnum implements IntArrayValuable { + + AUDIT_NONE(0, "未审核"), + AUDIT_PASS(10, "已审核"), + SALE_PART(20, "部分销售"), + SALE_ALL(21, "完成销售"), + ; + + public static final int[] ARRAYS = Arrays.stream(values()).mapToInt(ErpSaleOrderStatusEnum::getStatus).toArray(); + + /** + * 状态 + */ + private final Integer status; + /** + * 状态名 + */ + private final String name; + + @Override + public int[] array() { + return ARRAYS; + } + +} diff --git a/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/controller/admin/sale/ErpSaleOrderController.java b/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/controller/admin/sale/ErpSaleOrderController.java index cd2425fe9..ba1345166 100644 --- a/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/controller/admin/sale/ErpSaleOrderController.java +++ b/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/controller/admin/sale/ErpSaleOrderController.java @@ -1,13 +1,32 @@ package cn.iocoder.yudao.module.erp.controller.admin.sale; import cn.iocoder.yudao.framework.common.pojo.CommonResult; +import cn.iocoder.yudao.framework.common.pojo.PageParam; +import cn.iocoder.yudao.framework.common.pojo.PageResult; +import cn.iocoder.yudao.framework.common.util.object.BeanUtils; +import cn.iocoder.yudao.framework.excel.core.util.ExcelUtils; +import cn.iocoder.yudao.framework.operatelog.core.annotations.OperateLog; +import cn.iocoder.yudao.module.erp.controller.admin.sale.vo.order.ErpSaleOrderPageReqVO; +import cn.iocoder.yudao.module.erp.controller.admin.sale.vo.order.ErpSaleOrderRespVO; +import cn.iocoder.yudao.module.erp.controller.admin.sale.vo.order.ErpSaleOrderSaveReqVO; +import cn.iocoder.yudao.module.erp.dal.dataobject.sale.ErpSaleOrderDO; +import cn.iocoder.yudao.module.erp.service.sale.ErpSaleOrderService; +import io.swagger.v3.oas.annotations.Operation; +import io.swagger.v3.oas.annotations.Parameter; import io.swagger.v3.oas.annotations.tags.Tag; +import jakarta.annotation.Resource; +import jakarta.servlet.http.HttpServletResponse; +import jakarta.validation.Valid; +import org.springframework.security.access.prepost.PreAuthorize; import org.springframework.validation.annotation.Validated; -import org.springframework.web.bind.annotation.GetMapping; -import org.springframework.web.bind.annotation.RequestMapping; -import org.springframework.web.bind.annotation.RestController; +import org.springframework.web.bind.annotation.*; + +import java.io.IOException; +import java.util.List; import static cn.iocoder.yudao.framework.common.pojo.CommonResult.success; +import static cn.iocoder.yudao.framework.operatelog.core.enums.OperateTypeEnum.EXPORT; + @Tag(name = "管理后台 - ERP 销售订单") @RestController @@ -15,9 +34,67 @@ import static cn.iocoder.yudao.framework.common.pojo.CommonResult.success; @Validated public class ErpSaleOrderController { - @GetMapping("/demo") - public CommonResult demo() { + @Resource + private ErpSaleOrderService saleOrderService; + + // TODO 芋艿:待 review + @PostMapping("/create") + @Operation(summary = "创建ERP 销售订单") + @PreAuthorize("@ss.hasPermission('erp:sale-order:create')") + public CommonResult createSaleOrder(@Valid @RequestBody ErpSaleOrderSaveReqVO createReqVO) { + return success(saleOrderService.createSaleOrder(createReqVO)); + } + + // TODO 芋艿:待 review + @PutMapping("/update") + @Operation(summary = "更新ERP 销售订单") + @PreAuthorize("@ss.hasPermission('erp:sale-order:update')") + public CommonResult updateSaleOrder(@Valid @RequestBody ErpSaleOrderSaveReqVO updateReqVO) { + saleOrderService.updateSaleOrder(updateReqVO); return success(true); } -} + // TODO 芋艿:待 review + @DeleteMapping("/delete") + @Operation(summary = "删除ERP 销售订单") + @Parameter(name = "id", description = "编号", required = true) + @PreAuthorize("@ss.hasPermission('erp:sale-order:delete')") + public CommonResult deleteSaleOrder(@RequestParam("id") Long id) { + saleOrderService.deleteSaleOrder(id); + return success(true); + } + + // TODO 芋艿:待 review + @GetMapping("/get") + @Operation(summary = "获得ERP 销售订单") + @Parameter(name = "id", description = "编号", required = true, example = "1024") + @PreAuthorize("@ss.hasPermission('erp:sale-order:query')") + public CommonResult getSaleOrder(@RequestParam("id") Long id) { + ErpSaleOrderDO saleOrder = saleOrderService.getSaleOrder(id); + return success(BeanUtils.toBean(saleOrder, ErpSaleOrderRespVO.class)); + } + + // TODO 芋艿:待 review + @GetMapping("/page") + @Operation(summary = "获得ERP 销售订单分页") + @PreAuthorize("@ss.hasPermission('erp:sale-order:query')") + public CommonResult> getSaleOrderPage(@Valid ErpSaleOrderPageReqVO pageReqVO) { + PageResult pageResult = saleOrderService.getSaleOrderPage(pageReqVO); + return success(BeanUtils.toBean(pageResult, ErpSaleOrderRespVO.class)); + } + + // TODO 芋艿:待 review + @GetMapping("/export-excel") + @Operation(summary = "导出ERP 销售订单 Excel") + @PreAuthorize("@ss.hasPermission('erp:sale-order:export')") + @OperateLog(type = EXPORT) + public void exportSaleOrderExcel(@Valid ErpSaleOrderPageReqVO pageReqVO, + HttpServletResponse response) throws IOException { + pageReqVO.setPageSize(PageParam.PAGE_SIZE_NONE); + List list = saleOrderService.getSaleOrderPage(pageReqVO).getList(); + // 导出 Excel + ExcelUtils.write(response, "ERP 销售订单.xls", "数据", ErpSaleOrderRespVO.class, + BeanUtils.toBean(list, ErpSaleOrderRespVO.class)); + } + +} \ No newline at end of file diff --git a/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/controller/admin/sale/vo/order/ErpSaleOrderPageReqVO.java b/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/controller/admin/sale/vo/order/ErpSaleOrderPageReqVO.java new file mode 100644 index 000000000..8e46a64b0 --- /dev/null +++ b/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/controller/admin/sale/vo/order/ErpSaleOrderPageReqVO.java @@ -0,0 +1,39 @@ +package cn.iocoder.yudao.module.erp.controller.admin.sale.vo.order; + +import cn.iocoder.yudao.framework.common.pojo.PageParam; +import io.swagger.v3.oas.annotations.media.Schema; +import lombok.Data; +import lombok.EqualsAndHashCode; +import lombok.ToString; +import org.springframework.format.annotation.DateTimeFormat; + +import java.time.LocalDateTime; + +import static cn.iocoder.yudao.framework.common.util.date.DateUtils.FORMAT_YEAR_MONTH_DAY_HOUR_MINUTE_SECOND; + +@Schema(description = "管理后台 - ERP 销售订单分页 Request VO") +@Data +@EqualsAndHashCode(callSuper = true) +@ToString(callSuper = true) +public class ErpSaleOrderPageReqVO extends PageParam { + + @Schema(description = "销售单编号", example = "XS001") + private String no; + + @Schema(description = "客户编号", example = "1724") + private Long customerId; + + @Schema(description = "下单时间") + @DateTimeFormat(pattern = FORMAT_YEAR_MONTH_DAY_HOUR_MINUTE_SECOND) + private LocalDateTime[] orderTime; + + @Schema(description = "备注", example = "你猜") + private String description; + + @Schema(description = "销售状态", example = "2") + private Integer status; + + @Schema(description = "创建者") + private String creator; + +} \ No newline at end of file diff --git a/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/controller/admin/sale/vo/order/ErpSaleOrderRespVO.java b/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/controller/admin/sale/vo/order/ErpSaleOrderRespVO.java new file mode 100644 index 000000000..ea24e08ca --- /dev/null +++ b/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/controller/admin/sale/vo/order/ErpSaleOrderRespVO.java @@ -0,0 +1,78 @@ +package cn.iocoder.yudao.module.erp.controller.admin.sale.vo.order; + +import com.alibaba.excel.annotation.ExcelIgnoreUnannotated; +import com.alibaba.excel.annotation.ExcelProperty; +import io.swagger.v3.oas.annotations.media.Schema; +import lombok.Data; + +import java.math.BigDecimal; +import java.time.LocalDateTime; + +// TODO 芋艿:导出最后搞 +@Schema(description = "管理后台 - ERP 销售订单 Response VO") +@Data +@ExcelIgnoreUnannotated +public class ErpSaleOrderRespVO { + + @Schema(description = "编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "17386") + @ExcelProperty("编号") + private Long id; + + @Schema(description = "销售单编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "XS001") + @ExcelProperty("销售单编号") + private String no; + + @Schema(description = "客户编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "1724") + @ExcelProperty("客户编号") + private Long customerId; + + @Schema(description = "下单时间", requiredMode = Schema.RequiredMode.REQUIRED) + @ExcelProperty("下单时间") + private LocalDateTime orderTime; + + // TODO 芋艿:example 后面 + @Schema(description = "销售员编号数组") + @ExcelProperty("销售员编号数组") + private String salePersonIds; + + @Schema(description = "合计价格,单位:元", requiredMode = Schema.RequiredMode.REQUIRED, example = "26094") + @ExcelProperty("合计价格,单位:元") + private BigDecimal totalPrice; + + @Schema(description = "优惠率,百分比", requiredMode = Schema.RequiredMode.REQUIRED, example = "99.88") + @ExcelProperty("优惠率,百分比") + private BigDecimal discountPercent; + + @Schema(description = "优惠金额,单位:元", requiredMode = Schema.RequiredMode.REQUIRED, example = "44.52") + @ExcelProperty("优惠金额,单位:元") + private BigDecimal discountPrice; + + @Schema(description = "支付金额,单位:元", requiredMode = Schema.RequiredMode.REQUIRED, example = "322.40") + @ExcelProperty("支付金额,单位:元") + private BigDecimal payPrice; + + @Schema(description = "定金金额,单位:元", requiredMode = Schema.RequiredMode.REQUIRED, example = "71.27") + @ExcelProperty("定金金额,单位:元") + private BigDecimal depositPrice; + + @Schema(description = "附件地址", example = "https://www.iocoder.cn") + @ExcelProperty("附件地址") + private String fileUrl; + + @Schema(description = "结算账户编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "311.89") + @ExcelProperty("结算账户编号") + private Long accountId; + + @Schema(description = "备注", example = "你猜") + @ExcelProperty("备注") + private String description; + + @Schema(description = "销售状态", requiredMode = Schema.RequiredMode.REQUIRED, example = "2") + @ExcelProperty("销售状态") + private Integer status; + + @Schema(description = "创建时间", requiredMode = Schema.RequiredMode.REQUIRED) + @ExcelProperty("创建时间") + private LocalDateTime createTime; + +} \ No newline at end of file diff --git a/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/controller/admin/sale/vo/order/ErpSaleOrderSaveReqVO.java b/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/controller/admin/sale/vo/order/ErpSaleOrderSaveReqVO.java new file mode 100644 index 000000000..cf74e2f14 --- /dev/null +++ b/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/controller/admin/sale/vo/order/ErpSaleOrderSaveReqVO.java @@ -0,0 +1,74 @@ +package cn.iocoder.yudao.module.erp.controller.admin.sale.vo.order; + +import cn.iocoder.yudao.module.erp.dal.dataobject.sale.ErpSalesOrderItemDO; +import io.swagger.v3.oas.annotations.media.Schema; +import jakarta.validation.constraints.NotEmpty; +import jakarta.validation.constraints.NotNull; +import lombok.Data; + +import java.math.BigDecimal; +import java.time.LocalDateTime; +import java.util.List; + +@Schema(description = "管理后台 - ERP 销售订单新增/修改 Request VO") +@Data +public class ErpSaleOrderSaveReqVO { + + @Schema(description = "编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "17386") + private Long id; + + @Schema(description = "销售单编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "XS001") + @NotEmpty(message = "销售单编号不能为空") + private String no; + + @Schema(description = "客户编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "1724") + @NotNull(message = "客户编号不能为空") + private Long customerId; + + @Schema(description = "下单时间", requiredMode = Schema.RequiredMode.REQUIRED) + @NotNull(message = "下单时间不能为空") + private LocalDateTime orderTime; + + @Schema(description = "销售员编号数组") + private String salePersonIds; + + @Schema(description = "合计价格,单位:元", requiredMode = Schema.RequiredMode.REQUIRED, example = "26094") + @NotNull(message = "合计价格,单位:元不能为空") + private BigDecimal totalPrice; + + @Schema(description = "优惠率,百分比", requiredMode = Schema.RequiredMode.REQUIRED, example = "99.88") + @NotNull(message = "优惠率,百分比不能为空") + private BigDecimal discountPercent; + + @Schema(description = "优惠金额,单位:元", requiredMode = Schema.RequiredMode.REQUIRED, example = "4452") + @NotNull(message = "优惠金额,单位:元不能为空") + private BigDecimal discountPrice; + + // TODO 芋艿:后面删除 +// @Schema(description = "支付金额,单位:元", requiredMode = Schema.RequiredMode.REQUIRED, example = "32240") +// @NotNull(message = "支付金额,单位:元不能为空") +// private BigDecimal payPrice; + + @Schema(description = "定金金额,单位:元", requiredMode = Schema.RequiredMode.REQUIRED, example = "7127") + @NotNull(message = "定金金额,单位:元不能为空") + private BigDecimal depositPrice; + + @Schema(description = "附件地址", example = "https://www.iocoder.cn") + private String fileUrl; + + @Schema(description = "结算账户编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "31189") + @NotNull(message = "结算账户编号不能为空") + private Long accountId; + + @Schema(description = "备注", example = "你猜") + private String description; + + // TODO 芋艿:后面删除 +// @Schema(description = "销售状态", requiredMode = Schema.RequiredMode.REQUIRED, example = "2") +// @NotNull(message = "销售状态不能为空") +// private Integer status; + + @Schema(description = "ERP 销售订单明细列表") + private List salesOrderItems; + +} \ No newline at end of file diff --git a/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/dal/dataobject/sale/ErpSaleOrderDO.java b/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/dal/dataobject/sale/ErpSaleOrderDO.java new file mode 100644 index 000000000..749eabd49 --- /dev/null +++ b/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/dal/dataobject/sale/ErpSaleOrderDO.java @@ -0,0 +1,100 @@ +package cn.iocoder.yudao.module.erp.dal.dataobject.sale; + +import cn.iocoder.yudao.framework.mybatis.core.dataobject.BaseDO; +import cn.iocoder.yudao.framework.mybatis.core.type.LongListTypeHandler; +import cn.iocoder.yudao.module.erp.enums.sale.ErpSaleOrderStatusEnum; +import com.baomidou.mybatisplus.annotation.KeySequence; +import com.baomidou.mybatisplus.annotation.TableField; +import com.baomidou.mybatisplus.annotation.TableId; +import com.baomidou.mybatisplus.annotation.TableName; +import lombok.*; + +import java.math.BigDecimal; +import java.time.LocalDateTime; +import java.util.List; + +/** + * ERP 销售订单 DO + * + * @author 芋道源码 + */ +@TableName(value = "erp_sale_order", autoResultMap = true) +@KeySequence("erp_sale_order_seq") // 用于 Oracle、PostgreSQL、Kingbase、DB2、H2 数据库的主键自增。如果是 MySQL 等数据库,可不写。 +@Data +@EqualsAndHashCode(callSuper = true) +@ToString(callSuper = true) +@Builder +@NoArgsConstructor +@AllArgsConstructor +public class ErpSaleOrderDO extends BaseDO { + + /** + * 编号 + */ + @TableId + private Long id; + /** + * 销售单编号 + */ + private String no; + /** + * 销售状态 + * + * 枚举 {@link ErpSaleOrderStatusEnum} + */ + private Integer status; + /** + * 客户编号 + * + * TODO 芋艿:关联 + */ + private Long customerId; + /** + * 结算账户编号 + * + * TODO 芋艿:关联 + */ + private Long accountId; + /** + * 销售员编号数组 + * + * TODO 芋艿:关联 + */ + @TableField(typeHandler = LongListTypeHandler.class) + private List salePersonIds; + /** + * 下单时间 + */ + private LocalDateTime orderTime; + + /** + * 合计价格,单位:元 + */ + private BigDecimal totalPrice; + /** + * 优惠率,百分比 + */ + private BigDecimal discountPercent; + /** + * 优惠金额,单位:元 + */ + private BigDecimal discountPrice; + /** + * 支付金额,单位:元 + */ + private BigDecimal payPrice; + /** + * 定金金额,单位:元 + */ + private BigDecimal depositPrice; + + /** + * 附件地址 + */ + private String fileUrl; + /** + * 备注 + */ + private String description; + +} \ No newline at end of file diff --git a/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/dal/dataobject/sale/ErpSalesOrderItemDO.java b/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/dal/dataobject/sale/ErpSalesOrderItemDO.java new file mode 100644 index 000000000..7e1b25f8d --- /dev/null +++ b/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/dal/dataobject/sale/ErpSalesOrderItemDO.java @@ -0,0 +1,88 @@ +package cn.iocoder.yudao.module.erp.dal.dataobject.sale; + +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.*; + +import java.math.BigDecimal; + +/** + * ERP 销售订单明细 DO + * + * @author 芋道源码 + */ +@TableName("erp_sales_order_items") +@KeySequence("erp_sales_order_items_seq") // 用于 Oracle、PostgreSQL、Kingbase、DB2、H2 数据库的主键自增。如果是 MySQL 等数据库,可不写。 +@Data +@EqualsAndHashCode(callSuper = true) +@ToString(callSuper = true) +@Builder +@NoArgsConstructor +@AllArgsConstructor +public class ErpSalesOrderItemDO extends BaseDO { + + /** + * 编号 + */ + @TableId + private Long id; + /** + * 销售订单编号 + * + * 关联 {@link ErpSaleOrderDO#getId()} + */ + private Long orderId; + + /** + * 商品 SPU 编号 + * + * TODO 芋艿 关联 + */ + private Long productSpuId; + /** + * 商品 SKU 编号 + * + * TODO 芋艿 关联 + */ + private Long productSkuId; + /** + * 商品单位 + * + * TODO 芋艿 冗余 + */ + private String productUnit; + /** + * 商品单价 + * + * TODO 芋艿 冗余 + */ + private BigDecimal productPrice; + + /** + * 数量 + */ + private Integer count; + /** + * 总价 + */ + private BigDecimal totalPrice; + /** + * 备注 + */ + private String description; + /** + * 税率,百分比 + */ + private BigDecimal taxPercent; + /** + * 税额,单位:元 + */ + private BigDecimal taxPrice; + /** + * 支付金额,单位:元 + */ + private BigDecimal payPrice; + +} \ No newline at end of file diff --git a/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/dal/mysql/sale/ErpSaleOrderMapper.java b/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/dal/mysql/sale/ErpSaleOrderMapper.java new file mode 100644 index 000000000..07c80c480 --- /dev/null +++ b/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/dal/mysql/sale/ErpSaleOrderMapper.java @@ -0,0 +1,30 @@ +package cn.iocoder.yudao.module.erp.dal.mysql.sale; + + +import cn.iocoder.yudao.framework.common.pojo.PageResult; +import cn.iocoder.yudao.framework.mybatis.core.mapper.BaseMapperX; +import cn.iocoder.yudao.framework.mybatis.core.query.LambdaQueryWrapperX; +import cn.iocoder.yudao.module.erp.controller.admin.sale.vo.order.ErpSaleOrderPageReqVO; +import cn.iocoder.yudao.module.erp.dal.dataobject.sale.ErpSaleOrderDO; +import org.apache.ibatis.annotations.Mapper; + +/** + * ERP 销售订单 Mapper + * + * @author 芋道源码 + */ +@Mapper +public interface ErpSaleOrderMapper extends BaseMapperX { + + default PageResult selectPage(ErpSaleOrderPageReqVO reqVO) { + return selectPage(reqVO, new LambdaQueryWrapperX() + .likeIfPresent(ErpSaleOrderDO::getNo, reqVO.getNo()) + .eqIfPresent(ErpSaleOrderDO::getCustomerId, reqVO.getCustomerId()) + .betweenIfPresent(ErpSaleOrderDO::getOrderTime, reqVO.getOrderTime()) + .eqIfPresent(ErpSaleOrderDO::getDescription, reqVO.getDescription()) + .eqIfPresent(ErpSaleOrderDO::getStatus, reqVO.getStatus()) + .eqIfPresent(ErpSaleOrderDO::getCreator, reqVO.getCreator()) + .orderByDesc(ErpSaleOrderDO::getId)); + } + +} \ No newline at end of file diff --git a/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/dal/mysql/sale/ErpSalesOrderItemMapper.java b/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/dal/mysql/sale/ErpSalesOrderItemMapper.java new file mode 100644 index 000000000..eb8628291 --- /dev/null +++ b/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/dal/mysql/sale/ErpSalesOrderItemMapper.java @@ -0,0 +1,25 @@ +package cn.iocoder.yudao.module.erp.dal.mysql.sale; + +import cn.iocoder.yudao.framework.mybatis.core.mapper.BaseMapperX; +import cn.iocoder.yudao.module.erp.dal.dataobject.sale.ErpSalesOrderItemDO; +import org.apache.ibatis.annotations.Mapper; + +import java.util.List; + +/** + * ERP 销售订单明细 Mapper + * + * @author 芋道源码 + */ +@Mapper +public interface ErpSalesOrderItemMapper extends BaseMapperX { + + default List selectListById(Long id) { + return selectList(ErpSalesOrderItemDO::getId, id); + } + + default int deleteById(Long id) { + return delete(ErpSalesOrderItemDO::getId, id); + } + +} \ No newline at end of file diff --git a/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/service/sale/ErpSaleOrderService.java b/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/service/sale/ErpSaleOrderService.java new file mode 100644 index 000000000..6554f2c18 --- /dev/null +++ b/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/service/sale/ErpSaleOrderService.java @@ -0,0 +1,54 @@ +package cn.iocoder.yudao.module.erp.service.sale; + +import cn.iocoder.yudao.framework.common.pojo.PageResult; +import cn.iocoder.yudao.module.erp.controller.admin.sale.vo.order.ErpSaleOrderPageReqVO; +import cn.iocoder.yudao.module.erp.controller.admin.sale.vo.order.ErpSaleOrderSaveReqVO; +import cn.iocoder.yudao.module.erp.dal.dataobject.sale.ErpSaleOrderDO; +import jakarta.validation.Valid; + +/** + * ERP 销售订单 Service 接口 + * + * @author 芋道源码 + */ +public interface ErpSaleOrderService { + + /** + * 创建ERP 销售订单 + * + * @param createReqVO 创建信息 + * @return 编号 + */ + Long createSaleOrder(@Valid ErpSaleOrderSaveReqVO createReqVO); + + /** + * 更新ERP 销售订单 + * + * @param updateReqVO 更新信息 + */ + void updateSaleOrder(@Valid ErpSaleOrderSaveReqVO updateReqVO); + + /** + * 删除ERP 销售订单 + * + * @param id 编号 + */ + void deleteSaleOrder(Long id); + + /** + * 获得ERP 销售订单 + * + * @param id 编号 + * @return ERP 销售订单 + */ + ErpSaleOrderDO getSaleOrder(Long id); + + /** + * 获得ERP 销售订单分页 + * + * @param pageReqVO 分页查询 + * @return ERP 销售订单分页 + */ + PageResult getSaleOrderPage(ErpSaleOrderPageReqVO pageReqVO); + +} \ No newline at end of file diff --git a/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/service/sale/ErpSaleOrderServiceImpl.java b/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/service/sale/ErpSaleOrderServiceImpl.java new file mode 100644 index 000000000..d8ccb0e28 --- /dev/null +++ b/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/service/sale/ErpSaleOrderServiceImpl.java @@ -0,0 +1,106 @@ +package cn.iocoder.yudao.module.erp.service.sale; + +import cn.iocoder.yudao.framework.common.pojo.PageResult; +import cn.iocoder.yudao.framework.common.util.object.BeanUtils; +import cn.iocoder.yudao.module.erp.controller.admin.sale.vo.order.ErpSaleOrderPageReqVO; +import cn.iocoder.yudao.module.erp.controller.admin.sale.vo.order.ErpSaleOrderSaveReqVO; +import cn.iocoder.yudao.module.erp.dal.dataobject.sale.ErpSaleOrderDO; +import cn.iocoder.yudao.module.erp.dal.dataobject.sale.ErpSalesOrderItemDO; +import cn.iocoder.yudao.module.erp.dal.mysql.sale.ErpSaleOrderMapper; +import cn.iocoder.yudao.module.erp.dal.mysql.sale.ErpSalesOrderItemMapper; +import jakarta.annotation.Resource; +import org.springframework.stereotype.Service; +import org.springframework.transaction.annotation.Transactional; +import org.springframework.validation.annotation.Validated; + +import java.util.List; + +import static cn.iocoder.yudao.framework.common.exception.util.ServiceExceptionUtil.exception; +import static cn.iocoder.yudao.module.erp.enums.ErrorCodeConstants.*; + +/** + * ERP 销售订单 Service 实现类 + * + * @author 芋道源码 + */ +@Service +@Validated +public class ErpSaleOrderServiceImpl implements ErpSaleOrderService { + + @Resource + private ErpSaleOrderMapper saleOrderMapper; + @Resource + private ErpSalesOrderItemMapper salesOrderItemMapper; + + @Override + @Transactional(rollbackFor = Exception.class) + public Long createSaleOrder(ErpSaleOrderSaveReqVO createReqVO) { + // 插入 + ErpSaleOrderDO saleOrder = BeanUtils.toBean(createReqVO, ErpSaleOrderDO.class); + saleOrderMapper.insert(saleOrder); + + // 插入子表 + createSalesOrderItemsList(saleOrder.getId(), createReqVO.getSalesOrderItems()); + // 返回 + return saleOrder.getId(); + } + + @Override + @Transactional(rollbackFor = Exception.class) + public void updateSaleOrder(ErpSaleOrderSaveReqVO updateReqVO) { + // 校验存在 + validateSaleOrderExists(updateReqVO.getId()); + // 更新 + ErpSaleOrderDO updateObj = BeanUtils.toBean(updateReqVO, ErpSaleOrderDO.class); + saleOrderMapper.updateById(updateObj); + + // 更新子表 + updateSalesOrderItemsList(updateReqVO.getId(), updateReqVO.getSalesOrderItems()); + } + + @Override + @Transactional(rollbackFor = Exception.class) + public void deleteSaleOrder(Long id) { + // 校验存在 + validateSaleOrderExists(id); + // 删除 + saleOrderMapper.deleteById(id); + + // 删除子表 + deleteSalesOrderItemsById(id); + } + + private void validateSaleOrderExists(Long id) { + if (saleOrderMapper.selectById(id) == null) { + throw exception(SALE_ORDER_NOT_EXISTS); + } + } + + @Override + public ErpSaleOrderDO getSaleOrder(Long id) { + return saleOrderMapper.selectById(id); + } + + @Override + public PageResult getSaleOrderPage(ErpSaleOrderPageReqVO pageReqVO) { + return saleOrderMapper.selectPage(pageReqVO); + } + + // ==================== 子表(ERP 销售订单明细) ==================== + + private void createSalesOrderItemsList(Long id, List list) { + list.forEach(o -> o.setId(id)); + salesOrderItemMapper.insertBatch(list); + } + + private void updateSalesOrderItemsList(Long id, List list) { + deleteSalesOrderItemsById(id); + list.forEach(o -> o.setId(null).setUpdater(null).setUpdateTime(null)); // 解决更新情况下:1)id 冲突;2)updateTime 不更新 + createSalesOrderItemsList(id, list); + } + + private void deleteSalesOrderItemsById(Long id) { + salesOrderItemMapper.deleteById(id); + } + +} \ No newline at end of file From 5d8ca19b175019fb5b45e6084f98bd6288e8c09c Mon Sep 17 00:00:00 2001 From: dhb52 Date: Sun, 28 Jan 2024 00:22:58 +0800 Subject: [PATCH 045/119] =?UTF-8?q?feat:=20CRM-backlog-=E5=BE=85=E8=BF=9B?= =?UTF-8?q?=E5=85=A5=E5=85=AC=E6=B5=B7=E7=9A=84=E5=AE=A2=E6=88=B7?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../module/crm/enums/ErrorCodeConstants.java | 7 +-- .../admin/customer/CrmCustomerController.java | 31 +++++++++++ .../dal/mysql/customer/CrmCustomerMapper.java | 52 +++++++++++++++++++ .../service/customer/CrmCustomerService.java | 4 ++ .../customer/CrmCustomerServiceImpl.java | 6 +++ 5 files changed, 97 insertions(+), 3 deletions(-) diff --git a/yudao-module-crm/yudao-module-crm-api/src/main/java/cn/iocoder/yudao/module/crm/enums/ErrorCodeConstants.java b/yudao-module-crm/yudao-module-crm-api/src/main/java/cn/iocoder/yudao/module/crm/enums/ErrorCodeConstants.java index 737e4100d..35c8f98e8 100644 --- a/yudao-module-crm/yudao-module-crm-api/src/main/java/cn/iocoder/yudao/module/crm/enums/ErrorCodeConstants.java +++ b/yudao-module-crm/yudao-module-crm-api/src/main/java/cn/iocoder/yudao/module/crm/enums/ErrorCodeConstants.java @@ -26,8 +26,8 @@ public interface ErrorCodeConstants { // ========== 联系人管理 1-020-003-000 ========== ErrorCode CONTACT_NOT_EXISTS = new ErrorCode(1_020_003_000, "联系人不存在"); - ErrorCode CONTACT_BUSINESS_LINK_NOT_EXISTS = new ErrorCode( 1_020_003_001, "联系人商机关联不存在"); - ErrorCode CONTACT_DELETE_FAIL_CONTRACT_LINK_EXISTS = new ErrorCode( 1_020_003_002, "联系人已关联合同,不能删除"); + ErrorCode CONTACT_BUSINESS_LINK_NOT_EXISTS = new ErrorCode(1_020_003_001, "联系人商机关联不存在"); + ErrorCode CONTACT_DELETE_FAIL_CONTRACT_LINK_EXISTS = new ErrorCode(1_020_003_002, "联系人已关联合同,不能删除"); // ========== 回款 1-020-004-000 ========== ErrorCode RECEIVABLE_NOT_EXISTS = new ErrorCode(1_020_004_000, "回款不存在"); @@ -80,7 +80,8 @@ public interface ErrorCodeConstants { ErrorCode BUSINESS_STATUS_NOT_EXISTS = new ErrorCode(1_020_011_000, "商机状态不存在"); // ========== 客户公海规则设置 1_020_012_000 ========== - ErrorCode CUSTOMER_LIMIT_CONFIG_NOT_EXISTS = new ErrorCode(1_020_012_000, "客户限制配置不存在"); + ErrorCode CUSTOMER_POOL_CONFIG_NOT_EXISTS_OR_DISABLED = new ErrorCode(1_020_012_000, "客户公海配置不存在或未启用"); + ErrorCode CUSTOMER_LIMIT_CONFIG_NOT_EXISTS = new ErrorCode(1_020_012_001, "客户限制配置不存在"); // ========== 跟进记录 1_020_013_000 ========== ErrorCode FOLLOW_UP_RECORD_NOT_EXISTS = new ErrorCode(1_020_013_000, "跟进记录不存在"); diff --git a/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/controller/admin/customer/CrmCustomerController.java b/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/controller/admin/customer/CrmCustomerController.java index 03893b817..84c669778 100644 --- a/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/controller/admin/customer/CrmCustomerController.java +++ b/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/controller/admin/customer/CrmCustomerController.java @@ -36,11 +36,13 @@ import java.util.List; import java.util.Map; import java.util.stream.Stream; +import static cn.iocoder.yudao.framework.common.exception.util.ServiceExceptionUtil.exception; import static cn.iocoder.yudao.framework.common.pojo.CommonResult.success; import static cn.iocoder.yudao.framework.common.pojo.PageParam.PAGE_SIZE_NONE; import static cn.iocoder.yudao.framework.common.util.collection.CollectionUtils.*; import static cn.iocoder.yudao.framework.operatelog.core.enums.OperateTypeEnum.EXPORT; import static cn.iocoder.yudao.framework.security.core.util.SecurityFrameworkUtils.getLoginUserId; +import static cn.iocoder.yudao.module.crm.enums.ErrorCodeConstants.CUSTOMER_POOL_CONFIG_NOT_EXISTS_OR_DISABLED; @Tag(name = "管理后台 - CRM 客户") @RestController @@ -118,6 +120,35 @@ public class CrmCustomerController { return success(CrmCustomerConvert.INSTANCE.convertPage(pageResult, userMap, deptMap, poolDayMap)); } + + @GetMapping("/put-in-pool-remind-page") + @Operation(summary = "获得待进入公海客户分页") + @PreAuthorize("@ss.hasPermission('crm:customer:query')") + public CommonResult> getPutInPoolRemindCustomerPage(@Valid CrmCustomerPageReqVO pageVO) { + // 获取公海配置 + CrmCustomerPoolConfigDO poolConfigDO = customerPoolConfigService.getCustomerPoolConfig(); + if (ObjUtil.isNull(poolConfigDO) + || Boolean.FALSE.equals(poolConfigDO.getEnabled()) + || Boolean.FALSE.equals(poolConfigDO.getNotifyEnabled()) + ) { + throw exception(CUSTOMER_POOL_CONFIG_NOT_EXISTS_OR_DISABLED); + } + + // 1. 查询客户分页 + PageResult pageResult = customerService.getPutInPoolRemindCustomerPage(pageVO, poolConfigDO, getLoginUserId()); + if (CollUtil.isEmpty(pageResult.getList())) { + return success(PageResult.empty(pageResult.getTotal())); + } + + // 2. 拼接数据 + Map poolDayMap = getPoolDayMap(pageResult.getList()); // 客户界面,需要查看距离进入公海的时间 + Map userMap = adminUserApi.getUserMap( + convertSetByFlatMap(pageResult.getList(), user -> Stream.of(Long.parseLong(user.getCreator()), user.getOwnerUserId()))); + Map deptMap = deptApi.getDeptMap(convertSet(userMap.values(), AdminUserRespDTO::getDeptId)); + + return success(CrmCustomerConvert.INSTANCE.convertPage(pageResult, userMap, deptMap, poolDayMap)); + } + /** * 获取距离进入公海的时间 * diff --git a/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/dal/mysql/customer/CrmCustomerMapper.java b/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/dal/mysql/customer/CrmCustomerMapper.java index 79ba99d22..db25dcff8 100644 --- a/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/dal/mysql/customer/CrmCustomerMapper.java +++ b/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/dal/mysql/customer/CrmCustomerMapper.java @@ -8,6 +8,7 @@ import cn.iocoder.yudao.framework.mybatis.core.query.MPJLambdaWrapperX; import cn.iocoder.yudao.module.crm.controller.admin.backlog.vo.CrmTodayCustomerPageReqVO; import cn.iocoder.yudao.module.crm.controller.admin.customer.vo.CrmCustomerPageReqVO; import cn.iocoder.yudao.module.crm.dal.dataobject.customer.CrmCustomerDO; +import cn.iocoder.yudao.module.crm.dal.dataobject.customer.CrmCustomerPoolConfigDO; import cn.iocoder.yudao.module.crm.enums.common.CrmBizTypeEnum; import cn.iocoder.yudao.module.crm.util.CrmQueryWrapperUtils; import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper; @@ -107,4 +108,55 @@ public interface CrmCustomerMapper extends BaseMapperX { .isNotNull(CrmCustomerDO::getOwnerUserId)); } + default PageResult selectPutInPoolRemindCustomerPage(CrmCustomerPageReqVO pageReqVO, + CrmCustomerPoolConfigDO poolConfigDO, + Long userId) { + MPJLambdaWrapperX query = new MPJLambdaWrapperX<>(); + // 拼接数据权限的查询条件 + CrmQueryWrapperUtils.appendPermissionCondition(query, CrmBizTypeEnum.CRM_CUSTOMER.getType(), + CrmCustomerDO::getId, userId, pageReqVO.getSceneType(), null); + + // 拼接自身的查询条件 + query.selectAll(CrmCustomerDO.class); + + // 未跟进放入公海天数 + final Integer contactExpireDays = poolConfigDO.getContactExpireDays(); + // 未成交放入公海天数 + final Integer dealExpireDays = poolConfigDO.getDealExpireDays(); + // 提前提醒天数 + final Integer notifyDays = poolConfigDO.getNotifyDays(); + + // 未成交提醒日期区间 + // dealExpireDays 开始提醒 + LocalDateTime startDealRemindDate = LocalDateTimeUtil.beginOfDay(LocalDateTime.now()) + .minusDays(dealExpireDays); + // dealExpireDays - notifyDays 结束提醒 + LocalDateTime endDealRemindDate = LocalDateTimeUtil.endOfDay(LocalDateTime.now()) + .minusDays(Math.max(dealExpireDays - notifyDays, 0)); + + // 未跟进提醒日期区间 + // contactExpireDays 开始提醒 + LocalDateTime startContactRemindDate = LocalDateTimeUtil.beginOfDay(LocalDateTime.now()) + .minusDays(contactExpireDays); + // contactExpireDays - notifyDays 结束提醒 + LocalDateTime endContactRemindDate = LocalDateTimeUtil.endOfDay(LocalDateTime.now()) + .minusDays(Math.max(contactExpireDays - notifyDays, 0)); + + query + // 1.1 未成交放入公海提醒 + .eq(CrmCustomerDO::getDealStatus, false) + .between(CrmCustomerDO::getCreateTime, startDealRemindDate, endDealRemindDate) + .or() + // 1.2 未跟进放入公海提醒 + // 1.2.1 ContactLastTime 为空 + .isNull(CrmCustomerDO::getContactLastTime) + .between(CrmCustomerDO::getCreateTime, startContactRemindDate, endContactRemindDate) + .or() + // 1.2.2 ContactLastTime 不为空 + .between(CrmCustomerDO::getContactLastTime, startContactRemindDate, endContactRemindDate) + ; + + return selectJoinPage(pageReqVO, CrmCustomerDO.class, query); + } + } diff --git a/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/service/customer/CrmCustomerService.java b/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/service/customer/CrmCustomerService.java index bff150c14..589fcbf20 100644 --- a/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/service/customer/CrmCustomerService.java +++ b/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/service/customer/CrmCustomerService.java @@ -6,6 +6,7 @@ import cn.iocoder.yudao.module.crm.controller.admin.customer.vo.CrmCustomerPageR import cn.iocoder.yudao.module.crm.controller.admin.customer.vo.CrmCustomerSaveReqVO; import cn.iocoder.yudao.module.crm.controller.admin.customer.vo.CrmCustomerTransferReqVO; import cn.iocoder.yudao.module.crm.dal.dataobject.customer.CrmCustomerDO; +import cn.iocoder.yudao.module.crm.dal.dataobject.customer.CrmCustomerPoolConfigDO; import cn.iocoder.yudao.module.crm.service.customer.bo.CrmCustomerCreateReqBO; import cn.iocoder.yudao.module.crm.service.followup.bo.CrmUpdateFollowUpReqBO; import jakarta.validation.Valid; @@ -134,4 +135,7 @@ public interface CrmCustomerService { */ int customerAutoPutPoolBySystem(); + PageResult getPutInPoolRemindCustomerPage(CrmCustomerPageReqVO pageVO, + CrmCustomerPoolConfigDO poolConfigDO, + Long loginUserId); } diff --git a/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/service/customer/CrmCustomerServiceImpl.java b/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/service/customer/CrmCustomerServiceImpl.java index ff9d9a030..b84cc4414 100644 --- a/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/service/customer/CrmCustomerServiceImpl.java +++ b/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/service/customer/CrmCustomerServiceImpl.java @@ -387,6 +387,12 @@ public class CrmCustomerServiceImpl implements CrmCustomerService { return customerMapper.selectPage(pageReqVO, userId); } + public PageResult getPutInPoolRemindCustomerPage(CrmCustomerPageReqVO pageReqVO, + CrmCustomerPoolConfigDO poolConfigDO, + Long userId) { + return customerMapper.selectPutInPoolRemindCustomerPage(pageReqVO, poolConfigDO, userId); + } + // ======================= 校验相关 ======================= /** From 1cab3c009c516513a2128d37278f3cfcb77d2d8b Mon Sep 17 00:00:00 2001 From: puhui999 Date: Sun, 28 Jan 2024 01:50:27 +0800 Subject: [PATCH 046/119] =?UTF-8?q?CRM-=E5=90=88=E5=90=8C=EF=BC=9A?= =?UTF-8?q?=E6=96=B0=E5=A2=9E=E5=8F=91=E8=B5=B7=E5=90=88=E5=90=8C=E5=AE=A1?= =?UTF-8?q?=E6=89=B9?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- yudao-module-crm/yudao-module-crm-biz/pom.xml | 5 +++ .../admin/contract/CrmContractController.java | 8 +++++ .../contract/vo/CrmContractSaveReqVO.java | 33 +++++++++++++------ .../business/CrmBusinessProductDO.java | 27 +++++++-------- .../dataobject/contract/CrmContractDO.java | 2 +- .../dal/dataobject/product/CrmProductDO.java | 3 +- .../dal/mysql/contract/CrmContractMapper.java | 4 +-- .../service/contract/CrmContractService.java | 14 ++++++-- .../contract/CrmContractServiceImpl.java | 25 +++++++++++--- 9 files changed, 85 insertions(+), 36 deletions(-) diff --git a/yudao-module-crm/yudao-module-crm-biz/pom.xml b/yudao-module-crm/yudao-module-crm-biz/pom.xml index c54b61c89..b905bf6da 100644 --- a/yudao-module-crm/yudao-module-crm-biz/pom.xml +++ b/yudao-module-crm/yudao-module-crm-biz/pom.xml @@ -27,6 +27,11 @@ yudao-module-crm-api ${revision} + + cn.iocoder.boot + yudao-module-bpm-api + ${revision} + diff --git a/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/controller/admin/contract/CrmContractController.java b/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/controller/admin/contract/CrmContractController.java index c2935184f..7f2541ae7 100644 --- a/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/controller/admin/contract/CrmContractController.java +++ b/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/controller/admin/contract/CrmContractController.java @@ -140,4 +140,12 @@ public class CrmContractController { return success(true); } + @PutMapping("/approve") + @Operation(summary = "发起合同审批流程") + @PreAuthorize("@ss.hasPermission('crm:contract:update')") + public CommonResult transfer(@RequestParam("id") Long id) { + contractService.handleApprove(id, getLoginUserId()); + return success(true); + } + } diff --git a/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/controller/admin/contract/vo/CrmContractSaveReqVO.java b/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/controller/admin/contract/vo/CrmContractSaveReqVO.java index e495bbfa5..607aa08f5 100644 --- a/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/controller/admin/contract/vo/CrmContractSaveReqVO.java +++ b/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/controller/admin/contract/vo/CrmContractSaveReqVO.java @@ -7,10 +7,13 @@ import cn.iocoder.yudao.module.crm.framework.operatelog.core.SysAdminUserParseFu import com.mzt.logapi.starter.annotation.DiffLogField; import io.swagger.v3.oas.annotations.media.Schema; import jakarta.validation.constraints.NotNull; +import lombok.AllArgsConstructor; import lombok.Data; +import lombok.NoArgsConstructor; import org.springframework.format.annotation.DateTimeFormat; import java.time.LocalDateTime; +import java.util.List; import static cn.iocoder.yudao.framework.common.util.date.DateUtils.FORMAT_YEAR_MONTH_DAY_HOUR_MINUTE_SECOND; @@ -35,10 +38,6 @@ public class CrmContractSaveReqVO { @DiffLogField(name = "商机", function = CrmBusinessParseFunction.NAME) private Long businessId; - @Schema(description = "工作流编号", example = "1043") - @DiffLogField(name = "工作流编号") - private Long processInstanceId; - @Schema(description = "下单日期", requiredMode = Schema.RequiredMode.REQUIRED) @DiffLogField(name = "下单日期") @DateTimeFormat(pattern = FORMAT_YEAR_MONTH_DAY_HOUR_MINUTE_SECOND) @@ -86,16 +85,30 @@ public class CrmContractSaveReqVO { @DiffLogField(name = "公司签约人", function = SysAdminUserParseFunction.NAME) private Long signUserId; - @Schema(description = "最后跟进时间") - @DiffLogField(name = "最后跟进时间") - @DateTimeFormat(pattern = FORMAT_YEAR_MONTH_DAY_HOUR_MINUTE_SECOND) - private LocalDateTime contactLastTime; - @Schema(description = "备注", example = "你猜") @DiffLogField(name = "备注") private String remark; - // TODO @dhb52:增加一个 status 字段:具体有哪些值,你来枚举下;主要页面上有个【草稿】【提交审核】的流程,可以看看。然后要对接工作流,这块也可以看看,不确定的地方问我。 + @Schema(description = "产品列表") + private List productItems; + @Schema(description = "商品属性") + @Data + @NoArgsConstructor + @AllArgsConstructor + public static class CrmContractProductItem { + + @Schema(description = "产品编号", example = "20529") + @NotNull(message = "产品编号不能为空") + private Long id; + + @Schema(description = "产品数量", requiredMode = Schema.RequiredMode.REQUIRED, example = "8911") + @NotNull(message = "产品数量不能为空") + private Long count; + + @Schema(description = "产品折扣") + private Integer discountPercent; + + } } diff --git a/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/dal/dataobject/business/CrmBusinessProductDO.java b/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/dal/dataobject/business/CrmBusinessProductDO.java index b1275f4c5..83121dbdd 100644 --- a/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/dal/dataobject/business/CrmBusinessProductDO.java +++ b/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/dal/dataobject/business/CrmBusinessProductDO.java @@ -2,13 +2,12 @@ package cn.iocoder.yudao.module.crm.dal.dataobject.business; import cn.iocoder.yudao.framework.mybatis.core.dataobject.BaseDO; import cn.iocoder.yudao.module.crm.dal.dataobject.product.CrmProductDO; +import cn.iocoder.yudao.module.crm.enums.DictTypeConstants; import com.baomidou.mybatisplus.annotation.KeySequence; import com.baomidou.mybatisplus.annotation.TableId; import com.baomidou.mybatisplus.annotation.TableName; import lombok.*; -import java.math.BigDecimal; - /** * 商机产品关联表 DO * @@ -29,14 +28,12 @@ public class CrmBusinessProductDO extends BaseDO { */ @TableId private Long id; - /** * 商机编号 * * 关联 {@link CrmBusinessDO#getId()} */ private Long businessId; - /** * 产品编号 * @@ -50,29 +47,27 @@ public class CrmBusinessProductDO extends BaseDO { private Integer price; /** - * 销售价格 + * 销售价格, 单位:分 */ - private BigDecimal salesPrice; - + private Integer salesPrice; /** * 数量 */ - private BigDecimal count; - - // TODO @lzxhqs:改成 discountPercent + private Integer count; /** * 折扣 */ - private BigDecimal discountPercent; - - // TODO @lzxhqs:改成 totalPrice;总计价格,和现有项目风格一致; + private Integer discountPercent; /** - * 小计(折扣后价格) + * 总计价格(折扣后价格) */ - private BigDecimal totalPrice; + private Integer totalPrice; /** * 单位 + * + * 字典 {@link DictTypeConstants#CRM_PRODUCT_UNIT} */ - private String unit; + private Integer unit; + } diff --git a/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/dal/dataobject/contract/CrmContractDO.java b/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/dal/dataobject/contract/CrmContractDO.java index bdaff7271..e70e7a3cb 100644 --- a/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/dal/dataobject/contract/CrmContractDO.java +++ b/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/dal/dataobject/contract/CrmContractDO.java @@ -45,7 +45,7 @@ public class CrmContractDO extends BaseDO { /** * 工作流编号 */ - private Long processInstanceId; + private String processInstanceId; /** * 下单日期 */ diff --git a/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/dal/dataobject/product/CrmProductDO.java b/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/dal/dataobject/product/CrmProductDO.java index a4ac3d3d7..6523782dd 100644 --- a/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/dal/dataobject/product/CrmProductDO.java +++ b/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/dal/dataobject/product/CrmProductDO.java @@ -1,6 +1,7 @@ package cn.iocoder.yudao.module.crm.dal.dataobject.product; import cn.iocoder.yudao.framework.mybatis.core.dataobject.BaseDO; +import cn.iocoder.yudao.module.crm.enums.DictTypeConstants; import cn.iocoder.yudao.module.crm.enums.product.CrmProductStatusEnum; import com.baomidou.mybatisplus.annotation.KeySequence; import com.baomidou.mybatisplus.annotation.TableId; @@ -38,7 +39,7 @@ public class CrmProductDO extends BaseDO { /** * 单位 * - * 字典 {@link cn.iocoder.yudao.module.crm.enums.DictTypeConstants#CRM_PRODUCT_UNIT} + * 字典 {@link DictTypeConstants#CRM_PRODUCT_UNIT} */ private Integer unit; /** diff --git a/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/dal/mysql/contract/CrmContractMapper.java b/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/dal/mysql/contract/CrmContractMapper.java index f4e33dfa0..a3e631201 100644 --- a/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/dal/mysql/contract/CrmContractMapper.java +++ b/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/dal/mysql/contract/CrmContractMapper.java @@ -41,7 +41,7 @@ public interface CrmContractMapper extends BaseMapperX { default PageResult selectPage(CrmContractPageReqVO pageReqVO, Long userId) { MPJLambdaWrapperX mpjLambdaWrapperX = new MPJLambdaWrapperX<>(); // 拼接数据权限的查询条件 - CrmQueryWrapperUtils.appendPermissionCondition(mpjLambdaWrapperX, CrmBizTypeEnum.CRM_CONTACT.getType(), + CrmQueryWrapperUtils.appendPermissionCondition(mpjLambdaWrapperX, CrmBizTypeEnum.CRM_CONTRACT.getType(), CrmContractDO::getId, userId, pageReqVO.getSceneType(), Boolean.FALSE); // 拼接自身的查询条件 mpjLambdaWrapperX.selectAll(CrmContractDO.class) @@ -56,7 +56,7 @@ public interface CrmContractMapper extends BaseMapperX { default List selectBatchIds(Collection ids, Long userId) { MPJLambdaWrapperX query = new MPJLambdaWrapperX<>(); // 构建数据权限连表条件 - CrmQueryWrapperUtils.appendPermissionCondition(query, CrmBizTypeEnum.CRM_CONTACT.getType(), ids, userId); + CrmQueryWrapperUtils.appendPermissionCondition(query, CrmBizTypeEnum.CRM_CONTRACT.getType(), ids, userId); // 拼接自身的查询条件 query.selectAll(CrmContractDO.class).in(CrmContractDO::getId, ids).orderByDesc(CrmContractDO::getId); return selectJoinList(CrmContractDO.class, query); diff --git a/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/service/contract/CrmContractService.java b/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/service/contract/CrmContractService.java index 6695e4f5d..9847af328 100644 --- a/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/service/contract/CrmContractService.java +++ b/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/service/contract/CrmContractService.java @@ -57,6 +57,14 @@ public interface CrmContractService { */ void updateContractFollowUp(CrmUpdateFollowUpReqBO contractUpdateFollowUpReqBO); + /** + * 发起合同审批流程 + * + * @param id 合同编号 + * @param userId 用户编号 + */ + void handleApprove(Long id, Long userId); + /** * 获得合同 * @@ -111,9 +119,11 @@ public interface CrmContractService { Long getContractCountByCustomerId(Long customerId); /** - * 根据商机ID获取关联客户的合同数量 TODO @lzxhqs:1)方法注释,和参数注释之间要有空行;2)中英文之间有空格,更清晰,例如说 商机 ID - * @param businessId 商机ID + * 根据商机ID获取关联客户的合同数量 + * + * @param businessId 商机编号 * @return 数量 */ Long selectCountByBusinessId(Long businessId); + } diff --git a/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/service/contract/CrmContractServiceImpl.java b/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/service/contract/CrmContractServiceImpl.java index 1f1561f9b..5e83eccb0 100644 --- a/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/service/contract/CrmContractServiceImpl.java +++ b/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/service/contract/CrmContractServiceImpl.java @@ -4,6 +4,8 @@ import cn.hutool.core.collection.CollUtil; import cn.hutool.core.collection.ListUtil; import cn.iocoder.yudao.framework.common.pojo.PageResult; import cn.iocoder.yudao.framework.common.util.object.BeanUtils; +import cn.iocoder.yudao.module.bpm.api.task.BpmProcessInstanceApi; +import cn.iocoder.yudao.module.bpm.api.task.dto.BpmProcessInstanceCreateReqDTO; import cn.iocoder.yudao.module.crm.controller.admin.contract.vo.CrmContractPageReqVO; import cn.iocoder.yudao.module.crm.controller.admin.contract.vo.CrmContractSaveReqVO; import cn.iocoder.yudao.module.crm.controller.admin.contract.vo.CrmContractTransferReqVO; @@ -13,6 +15,7 @@ import cn.iocoder.yudao.module.crm.dal.mysql.contract.CrmContractMapper; import cn.iocoder.yudao.module.crm.enums.common.CrmBizTypeEnum; import cn.iocoder.yudao.module.crm.enums.permission.CrmPermissionLevelEnum; import cn.iocoder.yudao.module.crm.framework.permission.core.annotations.CrmPermission; +import cn.iocoder.yudao.module.crm.service.business.CrmBusinessProductService; import cn.iocoder.yudao.module.crm.service.followup.bo.CrmUpdateFollowUpReqBO; import cn.iocoder.yudao.module.crm.service.permission.CrmPermissionService; import cn.iocoder.yudao.module.crm.service.permission.bo.CrmPermissionCreateReqBO; @@ -40,28 +43,33 @@ import static cn.iocoder.yudao.module.crm.enums.LogRecordConstants.*; @Validated public class CrmContractServiceImpl implements CrmContractService { + public static final String CONTRACT_APPROVE = "contract-approve"; // 合同审批流程标识 + @Resource private CrmContractMapper contractMapper; @Resource private CrmPermissionService crmPermissionService; + @Resource + private CrmBusinessProductService businessProductService; + + @Resource + private BpmProcessInstanceApi bpmProcessInstanceApi; @Override @Transactional(rollbackFor = Exception.class) @LogRecord(type = CRM_CONTRACT_TYPE, subType = CRM_CONTRACT_CREATE_SUB_TYPE, bizNo = "{{#contract.id}}", success = CRM_CONTRACT_CREATE_SUCCESS) public Long createContract(CrmContractSaveReqVO createReqVO, Long userId) { - createReqVO.setId(null); // TODO @合同待定:插入合同商品;需要搞个 BusinessProductDO // 插入合同 - CrmContractDO contract = BeanUtils.toBean(createReqVO, CrmContractDO.class); + CrmContractDO contract = BeanUtils.toBean(createReqVO, CrmContractDO.class).setId(null); contractMapper.insert(contract); // 创建数据权限 crmPermissionService.createPermission(new CrmPermissionCreateReqBO().setUserId(userId) .setBizType(CrmBizTypeEnum.CRM_CONTRACT.getType()).setBizId(contract.getId()) .setLevel(CrmPermissionLevelEnum.OWNER.getLevel())); - // 4. 记录操作日志上下文 LogRecordContext.putVariable("contract", contract); return contract.getId(); @@ -141,6 +149,16 @@ public class CrmContractServiceImpl implements CrmContractService { contractMapper.updateById(BeanUtils.toBean(contractUpdateFollowUpReqBO, CrmContractDO.class).setId(contractUpdateFollowUpReqBO.getBizId())); } + @Override + public void handleApprove(Long id, Long userId) { + // 创建合同审批流程实例 + String processInstanceId = bpmProcessInstanceApi.createProcessInstance(userId, new BpmProcessInstanceCreateReqDTO() + .setProcessDefinitionKey(CONTRACT_APPROVE).setBusinessKey(String.valueOf(id))); + + // 更新合同工作流编号 + contractMapper.updateById(new CrmContractDO().setId(id).setProcessInstanceId(processInstanceId)); + } + //======================= 查询相关 ======================= @Override @@ -182,6 +200,5 @@ public class CrmContractServiceImpl implements CrmContractService { public Long selectCountByBusinessId(Long businessId) { return contractMapper.selectCountByBusinessId(businessId); } - // TODO @合同待定:需要新增一个 ContractConfigDO 表,合同配置,重点是到期提醒; } From ea6752f15e565b5451e9164e02e082680b0b4a0a Mon Sep 17 00:00:00 2001 From: puhui999 Date: Sun, 28 Jan 2024 16:34:39 +0800 Subject: [PATCH 047/119] =?UTF-8?q?BPM:=20=E6=96=B0=E5=A2=9E=E9=80=9A?= =?UTF-8?q?=E8=BF=87=E6=B5=81=E7=A8=8B=E6=A0=87=E8=AF=86=E8=8E=B7=E5=8F=96?= =?UTF-8?q?=E6=B5=81=E7=A8=8B=E5=9B=BE?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../admin/definition/BpmModelController.java | 18 +++++++++++++----- .../service/definition/BpmModelService.java | 13 ++++++++++--- .../definition/BpmModelServiceImpl.java | 17 +++++++++++++++-- .../contract/CrmContractServiceImpl.java | 4 +++- .../listener/CrmContractResultListener.java | 4 ++++ 5 files changed, 45 insertions(+), 11 deletions(-) create mode 100644 yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/service/contract/listener/CrmContractResultListener.java diff --git a/yudao-module-bpm/yudao-module-bpm-biz/src/main/java/cn/iocoder/yudao/module/bpm/controller/admin/definition/BpmModelController.java b/yudao-module-bpm/yudao-module-bpm-biz/src/main/java/cn/iocoder/yudao/module/bpm/controller/admin/definition/BpmModelController.java index 824a2f862..7cb931689 100644 --- a/yudao-module-bpm/yudao-module-bpm-biz/src/main/java/cn/iocoder/yudao/module/bpm/controller/admin/definition/BpmModelController.java +++ b/yudao-module-bpm/yudao-module-bpm-biz/src/main/java/cn/iocoder/yudao/module/bpm/controller/admin/definition/BpmModelController.java @@ -6,16 +6,15 @@ import cn.iocoder.yudao.framework.common.util.io.IoUtils; import cn.iocoder.yudao.module.bpm.controller.admin.definition.vo.model.*; import cn.iocoder.yudao.module.bpm.convert.definition.BpmModelConvert; import cn.iocoder.yudao.module.bpm.service.definition.BpmModelService; -import io.swagger.v3.oas.annotations.tags.Tag; -import io.swagger.v3.oas.annotations.Parameter; import io.swagger.v3.oas.annotations.Operation; +import io.swagger.v3.oas.annotations.Parameter; +import io.swagger.v3.oas.annotations.tags.Tag; +import jakarta.annotation.Resource; +import jakarta.validation.Valid; import org.springframework.security.access.prepost.PreAuthorize; import org.springframework.validation.annotation.Validated; import org.springframework.web.bind.annotation.*; -import jakarta.annotation.Resource; -import jakarta.validation.Valid; - import java.io.IOException; import static cn.iocoder.yudao.framework.common.pojo.CommonResult.success; @@ -44,6 +43,15 @@ public class BpmModelController { return success(model); } + @GetMapping("/get-by-key") + @Operation(summary = "获得模型") + @Parameter(name = "key", description = "流程标识", required = true, example = "oa_leave") + @PreAuthorize("@ss.hasPermission('bpm:model:query')") + public CommonResult getModelByKey(@RequestParam("key") String key) { + BpmModelRespVO model = modelService.getBpmnModelByKey(key); + return success(model); + } + @PostMapping("/create") @Operation(summary = "新建模型") @PreAuthorize("@ss.hasPermission('bpm:model:create')") diff --git a/yudao-module-bpm/yudao-module-bpm-biz/src/main/java/cn/iocoder/yudao/module/bpm/service/definition/BpmModelService.java b/yudao-module-bpm/yudao-module-bpm-biz/src/main/java/cn/iocoder/yudao/module/bpm/service/definition/BpmModelService.java index d7cdd89cb..4c3b0ba10 100644 --- a/yudao-module-bpm/yudao-module-bpm-biz/src/main/java/cn/iocoder/yudao/module/bpm/service/definition/BpmModelService.java +++ b/yudao-module-bpm/yudao-module-bpm-biz/src/main/java/cn/iocoder/yudao/module/bpm/service/definition/BpmModelService.java @@ -2,9 +2,8 @@ package cn.iocoder.yudao.module.bpm.service.definition; import cn.iocoder.yudao.framework.common.pojo.PageResult; import cn.iocoder.yudao.module.bpm.controller.admin.definition.vo.model.*; -import org.flowable.bpmn.model.BpmnModel; - import jakarta.validation.Valid; +import org.flowable.bpmn.model.BpmnModel; /** * Flowable流程模型接口 @@ -38,6 +37,14 @@ public interface BpmModelService { */ BpmModelRespVO getModel(String id); + /** + * 获得流程模块 + * + * @param key 流程标识 + * @return 流程模型 + */ + BpmModelRespVO getBpmnModelByKey(String key); + /** * 修改流程模型 * @@ -62,7 +69,7 @@ public interface BpmModelService { /** * 修改模型的状态,实际更新的部署的流程定义的状态 * - * @param id 编号 + * @param id 编号 * @param state 状态 */ void updateModelState(String id, Integer state); diff --git a/yudao-module-bpm/yudao-module-bpm-biz/src/main/java/cn/iocoder/yudao/module/bpm/service/definition/BpmModelServiceImpl.java b/yudao-module-bpm/yudao-module-bpm-biz/src/main/java/cn/iocoder/yudao/module/bpm/service/definition/BpmModelServiceImpl.java index fecf2e1ff..e23ac90e5 100644 --- a/yudao-module-bpm/yudao-module-bpm-biz/src/main/java/cn/iocoder/yudao/module/bpm/service/definition/BpmModelServiceImpl.java +++ b/yudao-module-bpm/yudao-module-bpm-biz/src/main/java/cn/iocoder/yudao/module/bpm/service/definition/BpmModelServiceImpl.java @@ -14,6 +14,8 @@ import cn.iocoder.yudao.module.bpm.dal.dataobject.definition.BpmFormDO; import cn.iocoder.yudao.module.bpm.enums.definition.BpmModelFormTypeEnum; import cn.iocoder.yudao.module.bpm.service.definition.dto.BpmModelMetaInfoRespDTO; import cn.iocoder.yudao.module.bpm.service.definition.dto.BpmProcessDefinitionCreateReqDTO; +import jakarta.annotation.Resource; +import jakarta.validation.Valid; import lombok.extern.slf4j.Slf4j; import org.flowable.bpmn.converter.BpmnXMLConverter; import org.flowable.bpmn.model.BpmnModel; @@ -29,8 +31,6 @@ import org.springframework.transaction.annotation.Transactional; import org.springframework.util.ObjectUtils; import org.springframework.validation.annotation.Validated; -import jakarta.annotation.Resource; -import jakarta.validation.Valid; import java.util.*; import static cn.iocoder.yudao.framework.common.exception.util.ServiceExceptionUtil.exception; @@ -134,6 +134,19 @@ public class BpmModelServiceImpl implements BpmModelService { return modelRespVO; } + @Override + public BpmModelRespVO getBpmnModelByKey(String key) { + Model model = getModelByKey(key); + if (model == null) { + return null; + } + BpmModelRespVO modelRespVO = BpmModelConvert.INSTANCE.convert(model); + // 拼接 bpmn XML + byte[] bpmnBytes = repositoryService.getModelEditorSource(model.getId()); + modelRespVO.setBpmnXml(StrUtil.utf8Str(bpmnBytes)); + return modelRespVO; + } + @Override @Transactional(rollbackFor = Exception.class) // 因为进行多个操作,所以开启事务 public void updateModel(@Valid BpmModelUpdateReqVO updateReqVO) { diff --git a/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/service/contract/CrmContractServiceImpl.java b/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/service/contract/CrmContractServiceImpl.java index 5e83eccb0..8a1ad339e 100644 --- a/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/service/contract/CrmContractServiceImpl.java +++ b/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/service/contract/CrmContractServiceImpl.java @@ -12,6 +12,7 @@ import cn.iocoder.yudao.module.crm.controller.admin.contract.vo.CrmContractTrans import cn.iocoder.yudao.module.crm.convert.contract.CrmContractConvert; import cn.iocoder.yudao.module.crm.dal.dataobject.contract.CrmContractDO; import cn.iocoder.yudao.module.crm.dal.mysql.contract.CrmContractMapper; +import cn.iocoder.yudao.module.crm.enums.common.CrmAuditStatusEnum; import cn.iocoder.yudao.module.crm.enums.common.CrmBizTypeEnum; import cn.iocoder.yudao.module.crm.enums.permission.CrmPermissionLevelEnum; import cn.iocoder.yudao.module.crm.framework.permission.core.annotations.CrmPermission; @@ -156,7 +157,8 @@ public class CrmContractServiceImpl implements CrmContractService { .setProcessDefinitionKey(CONTRACT_APPROVE).setBusinessKey(String.valueOf(id))); // 更新合同工作流编号 - contractMapper.updateById(new CrmContractDO().setId(id).setProcessInstanceId(processInstanceId)); + contractMapper.updateById(new CrmContractDO().setId(id).setProcessInstanceId(processInstanceId) + .setAuditStatus(CrmAuditStatusEnum.PROCESS.getStatus())); } //======================= 查询相关 ======================= diff --git a/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/service/contract/listener/CrmContractResultListener.java b/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/service/contract/listener/CrmContractResultListener.java new file mode 100644 index 000000000..078bbbd6a --- /dev/null +++ b/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/service/contract/listener/CrmContractResultListener.java @@ -0,0 +1,4 @@ +package cn.iocoder.yudao.module.crm.service.contract.listener; + +public class CrmContractResultListener { +} From ab43e89a48709453c51b2ddd1f51e5e15cf196c2 Mon Sep 17 00:00:00 2001 From: anhaohao <1036606149@qq.com> Date: Sun, 28 Jan 2024 20:00:51 +0800 Subject: [PATCH 048/119] =?UTF-8?q?=E4=BF=AE=E6=94=B9=EF=BC=9ACRM=20?= =?UTF-8?q?=E5=95=86=E4=B8=9A=E6=99=BA=E8=83=BD=EF=BC=8C=E5=90=88=E5=90=8C?= =?UTF-8?q?=E9=87=91=E9=A2=9D=E6=8E=92=E8=A1=8C=E6=A6=9C=E5=92=8C=E5=9B=9E?= =?UTF-8?q?=E6=AC=BE=E9=87=91=E9=A2=9D=E6=8E=92=E8=A1=8C=E6=A6=9C?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- yudao-module-crm/pom.xml | 3 + yudao-module-crm/yudao-module-bi-api/pom.xml | 73 +++++ .../yudao/module/bi/api/package-info.java | 1 + .../yudao/module/bi/enums/package-info.java | 1 + yudao-module-crm/yudao-module-bi-biz/pom.xml | 74 ++++++ .../admin/ranking/BiRankingController.http | 10 + .../admin/ranking/BiRankingController.java | 53 ++++ .../ranking/vo/BiContractRanKingRespVO.java | 24 ++ .../controller/admin/ranking/vo/BiParams.java | 41 +++ .../admin/ranking/vo/BiRankReqVO.java | 20 ++ .../vo/BiReceivablesRanKingRespVO.java | 23 ++ .../module/bi/controller/package-info.java | 6 + .../module/bi/dal/mysql/BiRankingMapper.java | 31 +++ .../module/bi/framework/package-info.java | 6 + .../web/config/BiWebConfiguration.java | 24 ++ .../module/bi/framework/web/package-info.java | 4 + .../iocoder/yudao/module/bi/package-info.java | 7 + .../bi/service/ranking/BiRankingService.java | 30 +++ .../service/ranking/BiRankingServiceImpl.java | 53 ++++ .../yudao/module/bi/util/BiTimeUtil.java | 249 ++++++++++++++++++ .../resources/mapper/rank/BiRankingMapper.xml | 42 +++ .../yudao/module/system/api/dept/DeptApi.java | 8 + .../module/system/api/dept/DeptApiImpl.java | 9 + yudao-server/pom.xml | 5 + 24 files changed, 797 insertions(+) create mode 100644 yudao-module-crm/yudao-module-bi-api/pom.xml create mode 100644 yudao-module-crm/yudao-module-bi-api/src/main/java/cn/iocoder/yudao/module/bi/api/package-info.java create mode 100644 yudao-module-crm/yudao-module-bi-api/src/main/java/cn/iocoder/yudao/module/bi/enums/package-info.java create mode 100644 yudao-module-crm/yudao-module-bi-biz/pom.xml create mode 100644 yudao-module-crm/yudao-module-bi-biz/src/main/java/cn/iocoder/yudao/module/bi/controller/admin/ranking/BiRankingController.http create mode 100644 yudao-module-crm/yudao-module-bi-biz/src/main/java/cn/iocoder/yudao/module/bi/controller/admin/ranking/BiRankingController.java create mode 100644 yudao-module-crm/yudao-module-bi-biz/src/main/java/cn/iocoder/yudao/module/bi/controller/admin/ranking/vo/BiContractRanKingRespVO.java create mode 100644 yudao-module-crm/yudao-module-bi-biz/src/main/java/cn/iocoder/yudao/module/bi/controller/admin/ranking/vo/BiParams.java create mode 100644 yudao-module-crm/yudao-module-bi-biz/src/main/java/cn/iocoder/yudao/module/bi/controller/admin/ranking/vo/BiRankReqVO.java create mode 100644 yudao-module-crm/yudao-module-bi-biz/src/main/java/cn/iocoder/yudao/module/bi/controller/admin/ranking/vo/BiReceivablesRanKingRespVO.java create mode 100644 yudao-module-crm/yudao-module-bi-biz/src/main/java/cn/iocoder/yudao/module/bi/controller/package-info.java create mode 100644 yudao-module-crm/yudao-module-bi-biz/src/main/java/cn/iocoder/yudao/module/bi/dal/mysql/BiRankingMapper.java create mode 100644 yudao-module-crm/yudao-module-bi-biz/src/main/java/cn/iocoder/yudao/module/bi/framework/package-info.java create mode 100644 yudao-module-crm/yudao-module-bi-biz/src/main/java/cn/iocoder/yudao/module/bi/framework/web/config/BiWebConfiguration.java create mode 100644 yudao-module-crm/yudao-module-bi-biz/src/main/java/cn/iocoder/yudao/module/bi/framework/web/package-info.java create mode 100644 yudao-module-crm/yudao-module-bi-biz/src/main/java/cn/iocoder/yudao/module/bi/package-info.java create mode 100644 yudao-module-crm/yudao-module-bi-biz/src/main/java/cn/iocoder/yudao/module/bi/service/ranking/BiRankingService.java create mode 100644 yudao-module-crm/yudao-module-bi-biz/src/main/java/cn/iocoder/yudao/module/bi/service/ranking/BiRankingServiceImpl.java create mode 100644 yudao-module-crm/yudao-module-bi-biz/src/main/java/cn/iocoder/yudao/module/bi/util/BiTimeUtil.java create mode 100644 yudao-module-crm/yudao-module-bi-biz/src/main/resources/mapper/rank/BiRankingMapper.xml diff --git a/yudao-module-crm/pom.xml b/yudao-module-crm/pom.xml index 2a7b748c3..c281c7bfa 100644 --- a/yudao-module-crm/pom.xml +++ b/yudao-module-crm/pom.xml @@ -10,6 +10,8 @@ yudao-module-crm-api yudao-module-crm-biz + yudao-module-bi-biz + yudao-module-bi-api 4.0.0 yudao-module-crm @@ -20,6 +22,7 @@ crm 包下,客户关系管理(Customer Relationship Management)。 例如说:客户、联系人、商机、合同、回款等等 + 商业智能 BI 模块,包括:报表、图表、数据大屏等等 diff --git a/yudao-module-crm/yudao-module-bi-api/pom.xml b/yudao-module-crm/yudao-module-bi-api/pom.xml new file mode 100644 index 000000000..aa21b85f9 --- /dev/null +++ b/yudao-module-crm/yudao-module-bi-api/pom.xml @@ -0,0 +1,73 @@ + + + + cn.iocoder.boot + yudao-module-crm + ${revision} + + 4.0.0 + yudao-module-bi-api + + ${project.artifactId} + + bi 模块 API,暴露给其它模块调用 + + + + + cn.iocoder.boot + yudao-module-system-api + ${revision} + + + cn.iocoder.boot + yudao-module-crm-api + ${revision} + + + + + cn.iocoder.boot + yudao-spring-boot-starter-biz-operatelog + + + cn.iocoder.boot + yudao-spring-boot-starter-biz-ip + + + + + cn.iocoder.boot + yudao-spring-boot-starter-web + + + + cn.iocoder.boot + yudao-spring-boot-starter-security + + + + + cn.iocoder.boot + yudao-spring-boot-starter-mybatis + + + + + cn.iocoder.boot + yudao-spring-boot-starter-excel + + + cn.iocoder.boot + yudao-spring-boot-starter-biz-dict + + + + + cn.iocoder.boot + yudao-spring-boot-starter-test + + + \ No newline at end of file diff --git a/yudao-module-crm/yudao-module-bi-api/src/main/java/cn/iocoder/yudao/module/bi/api/package-info.java b/yudao-module-crm/yudao-module-bi-api/src/main/java/cn/iocoder/yudao/module/bi/api/package-info.java new file mode 100644 index 000000000..77e7d2290 --- /dev/null +++ b/yudao-module-crm/yudao-module-bi-api/src/main/java/cn/iocoder/yudao/module/bi/api/package-info.java @@ -0,0 +1 @@ +package cn.iocoder.yudao.module.bi.api; \ No newline at end of file diff --git a/yudao-module-crm/yudao-module-bi-api/src/main/java/cn/iocoder/yudao/module/bi/enums/package-info.java b/yudao-module-crm/yudao-module-bi-api/src/main/java/cn/iocoder/yudao/module/bi/enums/package-info.java new file mode 100644 index 000000000..eb4c1e428 --- /dev/null +++ b/yudao-module-crm/yudao-module-bi-api/src/main/java/cn/iocoder/yudao/module/bi/enums/package-info.java @@ -0,0 +1 @@ +package cn.iocoder.yudao.module.bi.enums; \ No newline at end of file diff --git a/yudao-module-crm/yudao-module-bi-biz/pom.xml b/yudao-module-crm/yudao-module-bi-biz/pom.xml new file mode 100644 index 000000000..92c8e2f9f --- /dev/null +++ b/yudao-module-crm/yudao-module-bi-biz/pom.xml @@ -0,0 +1,74 @@ + + + + cn.iocoder.boot + yudao-module-crm + ${revision} + + 4.0.0 + yudao-module-bi-biz + + ${project.artifactId} + + crm 包下,商业智能(Business Intelligence)。 + 例如说:报表、图表、数据分析等等 + + + + + cn.iocoder.boot + yudao-module-system-api + ${revision} + + + cn.iocoder.boot + yudao-module-crm-api + ${revision} + + + + + cn.iocoder.boot + yudao-spring-boot-starter-biz-operatelog + + + cn.iocoder.boot + yudao-spring-boot-starter-biz-ip + + + + + cn.iocoder.boot + yudao-spring-boot-starter-web + + + + cn.iocoder.boot + yudao-spring-boot-starter-security + + + + + cn.iocoder.boot + yudao-spring-boot-starter-mybatis + + + + + cn.iocoder.boot + yudao-spring-boot-starter-excel + + + cn.iocoder.boot + yudao-spring-boot-starter-biz-dict + + + + + cn.iocoder.boot + yudao-spring-boot-starter-test + + + \ No newline at end of file diff --git a/yudao-module-crm/yudao-module-bi-biz/src/main/java/cn/iocoder/yudao/module/bi/controller/admin/ranking/BiRankingController.http b/yudao-module-crm/yudao-module-bi-biz/src/main/java/cn/iocoder/yudao/module/bi/controller/admin/ranking/BiRankingController.http new file mode 100644 index 000000000..50ab7ec2b --- /dev/null +++ b/yudao-module-crm/yudao-module-bi-biz/src/main/java/cn/iocoder/yudao/module/bi/controller/admin/ranking/BiRankingController.http @@ -0,0 +1,10 @@ +### 合同金额排行榜 +GET {{baseUrl}}/bi/rank/contract-ranKing +Authorization: Bearer {{token}} +tenant-id: {{adminTenentId}} + + +### 回款金额排行榜 +GET {{baseUrl}}/bi/rank/receivables-ranKing +Authorization: Bearer {{token}} +tenant-id: {{adminTenentId}} diff --git a/yudao-module-crm/yudao-module-bi-biz/src/main/java/cn/iocoder/yudao/module/bi/controller/admin/ranking/BiRankingController.java b/yudao-module-crm/yudao-module-bi-biz/src/main/java/cn/iocoder/yudao/module/bi/controller/admin/ranking/BiRankingController.java new file mode 100644 index 000000000..2d81ae80d --- /dev/null +++ b/yudao-module-crm/yudao-module-bi-biz/src/main/java/cn/iocoder/yudao/module/bi/controller/admin/ranking/BiRankingController.java @@ -0,0 +1,53 @@ +package cn.iocoder.yudao.module.bi.controller.admin.ranking; + + +import cn.iocoder.yudao.framework.common.pojo.CommonResult; +import cn.iocoder.yudao.module.bi.controller.admin.ranking.vo.BiContractRanKingRespVO; +import cn.iocoder.yudao.module.bi.controller.admin.ranking.vo.BiRankReqVO; +import cn.iocoder.yudao.module.bi.controller.admin.ranking.vo.BiReceivablesRanKingRespVO; +import cn.iocoder.yudao.module.bi.service.ranking.BiRankingService; +import io.swagger.v3.oas.annotations.Operation; +import io.swagger.v3.oas.annotations.tags.Tag; +import jakarta.annotation.Resource; +import org.springframework.security.access.prepost.PreAuthorize; +import org.springframework.validation.annotation.Validated; +import org.springframework.web.bind.annotation.GetMapping; +import org.springframework.web.bind.annotation.RequestMapping; +import org.springframework.web.bind.annotation.RestController; + +import java.util.List; + +import static cn.iocoder.yudao.framework.common.pojo.CommonResult.success; + +/** + * @author anhaohao + */ +@Tag(name = "管理后台 - 排行榜") +@RestController +@RequestMapping("/bi/ranking") +@Validated +public class BiRankingController { + + @Resource + private BiRankingService biRankingService; + + /** + * 合同金额排行榜 + */ + @GetMapping("/contract-ranking") + @Operation(summary = "合同金额排行榜") + @PreAuthorize("@ss.hasPermission('bi:ranking:query')") + public CommonResult> contractAmountRanking(BiRankReqVO biRankReqVO) { + return success(biRankingService.contractRanKing(biRankReqVO)); + } + + /** + * 回款金额排行榜 + */ + @GetMapping("/receivables-ranking") + @Operation(summary = "回款金额排行榜") + @PreAuthorize("@ss.hasPermission('bi:ranking:query')") + public CommonResult> receivablesRanKing(BiRankReqVO biRankReqVO) { + return success(biRankingService.receivablesRanKing(biRankReqVO)); + } +} diff --git a/yudao-module-crm/yudao-module-bi-biz/src/main/java/cn/iocoder/yudao/module/bi/controller/admin/ranking/vo/BiContractRanKingRespVO.java b/yudao-module-crm/yudao-module-bi-biz/src/main/java/cn/iocoder/yudao/module/bi/controller/admin/ranking/vo/BiContractRanKingRespVO.java new file mode 100644 index 000000000..777996b90 --- /dev/null +++ b/yudao-module-crm/yudao-module-bi-biz/src/main/java/cn/iocoder/yudao/module/bi/controller/admin/ranking/vo/BiContractRanKingRespVO.java @@ -0,0 +1,24 @@ +package cn.iocoder.yudao.module.bi.controller.admin.ranking.vo; + +import io.swagger.v3.oas.annotations.media.Schema; +import lombok.Data; + +/** + * 管理后台 - BI 排行榜 Response VO + * + * @author anhaohao + */ +@Schema(description = "管理后台 - BI 合同金额排行榜 Response VO") +@Data +public class BiContractRanKingRespVO { + + @Schema(description = "金额", example = "1") + private Integer price; + + @Schema(description = "姓名", example = "1") + private String nickname; + + + @Schema(description = "部门名称", example = "1") + private String deptName; +} diff --git a/yudao-module-crm/yudao-module-bi-biz/src/main/java/cn/iocoder/yudao/module/bi/controller/admin/ranking/vo/BiParams.java b/yudao-module-crm/yudao-module-bi-biz/src/main/java/cn/iocoder/yudao/module/bi/controller/admin/ranking/vo/BiParams.java new file mode 100644 index 000000000..5cce4c6cb --- /dev/null +++ b/yudao-module-crm/yudao-module-bi-biz/src/main/java/cn/iocoder/yudao/module/bi/controller/admin/ranking/vo/BiParams.java @@ -0,0 +1,41 @@ +package cn.iocoder.yudao.module.bi.controller.admin.ranking.vo; + +import cn.iocoder.yudao.framework.common.pojo.PageParam; +import io.swagger.v3.oas.annotations.media.Schema; +import lombok.Data; +import lombok.EqualsAndHashCode; + +import java.util.List; + +/** + * @author anhaohao + * bi参数 + */ +@EqualsAndHashCode(callSuper = true) +@Schema(description = "bi查询相关参数") +@Data +public class BiParams extends PageParam { + + @Schema(description = "部门ID") + private Long deptId; + + @Schema(description = "用户ID") + private Long userId; + + @Schema(description = "用户IDs") + private List userIds; + + @Schema(description = "类型") + private String type; + + @Schema(description = "开始时间") + private String startTime; + + @Schema(description = "结束时间") + private String endTime; + + @Schema(description = "0 部门 1员工") + private Integer isUser = 1; + + +} diff --git a/yudao-module-crm/yudao-module-bi-biz/src/main/java/cn/iocoder/yudao/module/bi/controller/admin/ranking/vo/BiRankReqVO.java b/yudao-module-crm/yudao-module-bi-biz/src/main/java/cn/iocoder/yudao/module/bi/controller/admin/ranking/vo/BiRankReqVO.java new file mode 100644 index 000000000..1569ba88d --- /dev/null +++ b/yudao-module-crm/yudao-module-bi-biz/src/main/java/cn/iocoder/yudao/module/bi/controller/admin/ranking/vo/BiRankReqVO.java @@ -0,0 +1,20 @@ +package cn.iocoder.yudao.module.bi.controller.admin.ranking.vo; + +import io.swagger.v3.oas.annotations.media.Schema; +import lombok.Data; + +/** + * 管理后台 - 排行榜 Request VO + * + * @author anhaohao + */ +@Schema(description = "管理后台 - 排行榜 Request VO") +@Data +public class BiRankReqVO { + + @Schema(description = "部门id", requiredMode = Schema.RequiredMode.REQUIRED, example = "1") + private Long deptId; + + @Schema(description = "分析类型(1.今天 2.昨天 3.本周 4.上周 5.本月 6.上月 7.本季度 8.上季度 9.本年 10 上年)", requiredMode = Schema.RequiredMode.REQUIRED, example = "1") + private String type; +} diff --git a/yudao-module-crm/yudao-module-bi-biz/src/main/java/cn/iocoder/yudao/module/bi/controller/admin/ranking/vo/BiReceivablesRanKingRespVO.java b/yudao-module-crm/yudao-module-bi-biz/src/main/java/cn/iocoder/yudao/module/bi/controller/admin/ranking/vo/BiReceivablesRanKingRespVO.java new file mode 100644 index 000000000..32b49231f --- /dev/null +++ b/yudao-module-crm/yudao-module-bi-biz/src/main/java/cn/iocoder/yudao/module/bi/controller/admin/ranking/vo/BiReceivablesRanKingRespVO.java @@ -0,0 +1,23 @@ +package cn.iocoder.yudao.module.bi.controller.admin.ranking.vo; + +import io.swagger.v3.oas.annotations.media.Schema; +import lombok.Data; + +/** + * 管理后台 - BI 排行榜 Response VO + * + * @author anhaohao + */ +@Schema(description = "管理后台 - BI 合同金额排行榜 Response VO") +@Data +public class BiReceivablesRanKingRespVO { + + @Schema(description = "金额", example = "100") + private Integer price; + + @Schema(description = "姓名", example = "张三") + private String nickname; + + @Schema(description = "部门名称", example = "研发部") + private String deptName; +} diff --git a/yudao-module-crm/yudao-module-bi-biz/src/main/java/cn/iocoder/yudao/module/bi/controller/package-info.java b/yudao-module-crm/yudao-module-bi-biz/src/main/java/cn/iocoder/yudao/module/bi/controller/package-info.java new file mode 100644 index 000000000..052f6238f --- /dev/null +++ b/yudao-module-crm/yudao-module-bi-biz/src/main/java/cn/iocoder/yudao/module/bi/controller/package-info.java @@ -0,0 +1,6 @@ +/** + * 提供 RESTful API 给前端: + * 1. admin 包:提供给管理后台 yudao-ui-admin 前端项目 + * 2. app 包:提供给用户 APP yudao-ui-app 前端项目,它的 Controller 和 VO 都要添加 App 前缀,用于和管理后台进行区分 + */ +package cn.iocoder.yudao.module.bi.controller; diff --git a/yudao-module-crm/yudao-module-bi-biz/src/main/java/cn/iocoder/yudao/module/bi/dal/mysql/BiRankingMapper.java b/yudao-module-crm/yudao-module-bi-biz/src/main/java/cn/iocoder/yudao/module/bi/dal/mysql/BiRankingMapper.java new file mode 100644 index 000000000..e37184031 --- /dev/null +++ b/yudao-module-crm/yudao-module-bi-biz/src/main/java/cn/iocoder/yudao/module/bi/dal/mysql/BiRankingMapper.java @@ -0,0 +1,31 @@ +package cn.iocoder.yudao.module.bi.dal.mysql; + +import cn.iocoder.yudao.framework.mybatis.core.mapper.BaseMapperX; +import cn.iocoder.yudao.module.bi.controller.admin.ranking.vo.BiContractRanKingRespVO; +import cn.iocoder.yudao.module.bi.controller.admin.ranking.vo.BiReceivablesRanKingRespVO; +import cn.iocoder.yudao.module.bi.util.BiTimeUtil; +import org.apache.ibatis.annotations.Mapper; + +import java.util.List; + +/** + * @author anhaohao + */ +@Mapper +public interface BiRankingMapper extends BaseMapperX { + /** + * 合同金额排行榜 + * + * @param biTimeEntity 参数 + * @return List + */ + List contractRanKing(BiTimeUtil.BiTimeEntity biTimeEntity); + + /** + * 回款金额排行榜 + * + * @param biTimeEntity 参数 + * @return List + */ + List receivablesRanKing(BiTimeUtil.BiTimeEntity biTimeEntity); +} diff --git a/yudao-module-crm/yudao-module-bi-biz/src/main/java/cn/iocoder/yudao/module/bi/framework/package-info.java b/yudao-module-crm/yudao-module-bi-biz/src/main/java/cn/iocoder/yudao/module/bi/framework/package-info.java new file mode 100644 index 000000000..8b004cf8c --- /dev/null +++ b/yudao-module-crm/yudao-module-bi-biz/src/main/java/cn/iocoder/yudao/module/bi/framework/package-info.java @@ -0,0 +1,6 @@ +/** + * 属于 bi 模块的 framework 封装 + * + * @author 芋道源码 + */ +package cn.iocoder.yudao.module.bi.framework; diff --git a/yudao-module-crm/yudao-module-bi-biz/src/main/java/cn/iocoder/yudao/module/bi/framework/web/config/BiWebConfiguration.java b/yudao-module-crm/yudao-module-bi-biz/src/main/java/cn/iocoder/yudao/module/bi/framework/web/config/BiWebConfiguration.java new file mode 100644 index 000000000..ad10cdccd --- /dev/null +++ b/yudao-module-crm/yudao-module-bi-biz/src/main/java/cn/iocoder/yudao/module/bi/framework/web/config/BiWebConfiguration.java @@ -0,0 +1,24 @@ +package cn.iocoder.yudao.module.bi.framework.web.config; + +import cn.iocoder.yudao.framework.swagger.config.YudaoSwaggerAutoConfiguration; +import org.springdoc.core.models.GroupedOpenApi; +import org.springframework.context.annotation.Bean; +import org.springframework.context.annotation.Configuration; + +/** + * bi 模块的 web 组件的 Configuration + * + * @author 芋道源码 + */ +@Configuration(proxyBeanMethods = false) +public class BiWebConfiguration { + + /** + * bi 模块的 API 分组 + */ + @Bean + public GroupedOpenApi biGroupedOpenApi() { + return YudaoSwaggerAutoConfiguration.buildGroupedOpenApi("bi"); + } + +} diff --git a/yudao-module-crm/yudao-module-bi-biz/src/main/java/cn/iocoder/yudao/module/bi/framework/web/package-info.java b/yudao-module-crm/yudao-module-bi-biz/src/main/java/cn/iocoder/yudao/module/bi/framework/web/package-info.java new file mode 100644 index 000000000..e17abbb1c --- /dev/null +++ b/yudao-module-crm/yudao-module-bi-biz/src/main/java/cn/iocoder/yudao/module/bi/framework/web/package-info.java @@ -0,0 +1,4 @@ +/** + * bi 模块的 web 配置 + */ +package cn.iocoder.yudao.module.bi.framework.web; diff --git a/yudao-module-crm/yudao-module-bi-biz/src/main/java/cn/iocoder/yudao/module/bi/package-info.java b/yudao-module-crm/yudao-module-bi-biz/src/main/java/cn/iocoder/yudao/module/bi/package-info.java new file mode 100644 index 000000000..b45b8458d --- /dev/null +++ b/yudao-module-crm/yudao-module-bi-biz/src/main/java/cn/iocoder/yudao/module/bi/package-info.java @@ -0,0 +1,7 @@ +/** + * crm 包下,商业智能(Business Intelligence)。 + * 例如说:报表、图表、数据分析等等 + *

+ * 1. Controller URL:以 /bi/ 开头,避免和其它 Module 冲突 + */ +package cn.iocoder.yudao.module.bi; \ No newline at end of file diff --git a/yudao-module-crm/yudao-module-bi-biz/src/main/java/cn/iocoder/yudao/module/bi/service/ranking/BiRankingService.java b/yudao-module-crm/yudao-module-bi-biz/src/main/java/cn/iocoder/yudao/module/bi/service/ranking/BiRankingService.java new file mode 100644 index 000000000..98f1346de --- /dev/null +++ b/yudao-module-crm/yudao-module-bi-biz/src/main/java/cn/iocoder/yudao/module/bi/service/ranking/BiRankingService.java @@ -0,0 +1,30 @@ +package cn.iocoder.yudao.module.bi.service.ranking; + +import cn.iocoder.yudao.module.bi.controller.admin.ranking.vo.BiContractRanKingRespVO; +import cn.iocoder.yudao.module.bi.controller.admin.ranking.vo.BiRankReqVO; +import cn.iocoder.yudao.module.bi.controller.admin.ranking.vo.BiReceivablesRanKingRespVO; + +import java.util.List; + +/** + * BI 排行榜 Service 接口 + * + * @author anhaohao + */ +public interface BiRankingService { + /** + * 合同金额排行榜 + * + * @param biRankReqVO 参数 + * @return List + */ + List contractRanKing(BiRankReqVO biRankReqVO); + + /** + * 回款金额排行榜 + * + * @param biRankReqVO 参数 + * @return List + */ + List receivablesRanKing(BiRankReqVO biRankReqVO); +} diff --git a/yudao-module-crm/yudao-module-bi-biz/src/main/java/cn/iocoder/yudao/module/bi/service/ranking/BiRankingServiceImpl.java b/yudao-module-crm/yudao-module-bi-biz/src/main/java/cn/iocoder/yudao/module/bi/service/ranking/BiRankingServiceImpl.java new file mode 100644 index 000000000..1ed468547 --- /dev/null +++ b/yudao-module-crm/yudao-module-bi-biz/src/main/java/cn/iocoder/yudao/module/bi/service/ranking/BiRankingServiceImpl.java @@ -0,0 +1,53 @@ +package cn.iocoder.yudao.module.bi.service.ranking; + +import cn.iocoder.yudao.module.bi.controller.admin.ranking.vo.BiContractRanKingRespVO; +import cn.iocoder.yudao.module.bi.controller.admin.ranking.vo.BiParams; +import cn.iocoder.yudao.module.bi.controller.admin.ranking.vo.BiRankReqVO; +import cn.iocoder.yudao.module.bi.controller.admin.ranking.vo.BiReceivablesRanKingRespVO; +import cn.iocoder.yudao.module.bi.dal.mysql.BiRankingMapper; +import cn.iocoder.yudao.module.bi.util.BiTimeUtil; +import jakarta.annotation.Resource; +import org.springframework.stereotype.Service; +import org.springframework.validation.annotation.Validated; + +import java.util.ArrayList; +import java.util.List; + +/** + * @author anhaohao + */ +@Service(value = "biRankService") +@Validated +public class BiRankingServiceImpl implements BiRankingService { + + @Resource + private BiRankingMapper biRankingMapper; + + @Override + public List contractRanKing(BiRankReqVO biRankReqVO) { + BiParams biParams = new BiParams(); + biParams.setType(biRankReqVO.getType()); + biParams.setDeptId(biRankReqVO.getDeptId()); + biParams.setIsUser(0); + BiTimeUtil.BiTimeEntity biTimeEntity = BiTimeUtil.analyzeType(biParams); + List userIds = biTimeEntity.getUserIds(); + if (userIds.isEmpty()) { + return new ArrayList<>(); + } + return biRankingMapper.contractRanKing(biTimeEntity); + } + + @Override + public List receivablesRanKing(BiRankReqVO biRankReqVO) { + BiParams biParams = new BiParams(); + biParams.setType(biRankReqVO.getType()); + biParams.setDeptId(biRankReqVO.getDeptId()); + biParams.setIsUser(0); + BiTimeUtil.BiTimeEntity biTimeEntity = BiTimeUtil.analyzeType(biParams); + List userIds = biTimeEntity.getUserIds(); + if (userIds.isEmpty()) { + return new ArrayList<>(); + } + return biRankingMapper.receivablesRanKing(biTimeEntity); + } +} diff --git a/yudao-module-crm/yudao-module-bi-biz/src/main/java/cn/iocoder/yudao/module/bi/util/BiTimeUtil.java b/yudao-module-crm/yudao-module-bi-biz/src/main/java/cn/iocoder/yudao/module/bi/util/BiTimeUtil.java new file mode 100644 index 000000000..b1b68aea2 --- /dev/null +++ b/yudao-module-crm/yudao-module-bi-biz/src/main/java/cn/iocoder/yudao/module/bi/util/BiTimeUtil.java @@ -0,0 +1,249 @@ +package cn.iocoder.yudao.module.bi.util; + +import cn.hutool.core.date.DateUnit; +import cn.hutool.core.date.DateUtil; +import cn.hutool.core.util.StrUtil; +import cn.hutool.extra.spring.SpringUtil; +import cn.iocoder.yudao.framework.security.core.util.SecurityFrameworkUtils; +import cn.iocoder.yudao.module.bi.controller.admin.ranking.vo.BiParams; +import cn.iocoder.yudao.module.system.api.dept.DeptApi; +import cn.iocoder.yudao.module.system.api.dept.dto.DeptRespDTO; +import cn.iocoder.yudao.module.system.api.user.AdminUserApi; +import cn.iocoder.yudao.module.system.api.user.dto.AdminUserRespDTO; +import lombok.Data; +import lombok.experimental.Accessors; + +import java.util.ArrayList; +import java.util.Date; +import java.util.List; + +/** + * bi时间工具类 + * + * @author anhaohao + */ +public class BiTimeUtil { + + public static BiTimeEntity analyzeType(BiParams biParams) { + // 解析时间 + BiTimeEntity biTimeEntity = analyzeTime(biParams); + // 解析权限 + biTimeEntity.setUserIds(analyzeAuth(biParams)); + return biTimeEntity; + } + + /** + * 解析权限 + * + * @param biParams bi参数 + * @return List + */ + public static List analyzeAuth(BiParams biParams) { + List userIdList = new ArrayList<>(); + Long deptId = biParams.getDeptId(); + Long userId = biParams.getUserId(); + Integer isUser = biParams.getIsUser(); + // 获取部门和用户的api + DeptApi deptApi = SpringUtil.getBean("deptApiImpl"); + AdminUserApi adminUserApi = SpringUtil.getBean("adminUserApiImpl"); + // 0.部门 1.用户 + if (isUser == 0) { + if (deptId == null) { + deptId = adminUserApi.getUser(SecurityFrameworkUtils.getLoginUserId()).getDeptId(); + } + List childDeptList = deptApi.getChildDeptList(deptId); + List deptIds = new ArrayList<>(); + deptIds.add(deptId); + if (childDeptList != null && !childDeptList.isEmpty()) { + for (DeptRespDTO deptRespDTO : childDeptList) { + deptIds.add(deptRespDTO.getId()); + } + } + // 获取部门下的用户 + adminUserApi.getUserListByDeptIds(deptIds).forEach(adminUserRespDTO -> userIdList.add(adminUserRespDTO.getId())); + } else { + if (userId == null) { + List userListBySubordinate = adminUserApi.getUserListBySubordinate(SecurityFrameworkUtils.getLoginUserId()); + userListBySubordinate.forEach(adminUserRespDTO -> userIdList.add(adminUserRespDTO.getId())); + } else { + userIdList.add(userId); + } + } + return userIdList; + } + + + /** + * 解析时间 + * + * @param biParams bi参数 + * @return BiTimeEntity + */ + public static BiTimeEntity analyzeTime(BiParams biParams) { + Date beginDate = DateUtil.date(); + Date endDate = DateUtil.date(); + int cycleNum = 12; + String sqlDateFormat = "%Y%m"; + String dateFormat = "yyyyMM"; + String type = biParams.getType(); + String startTime = biParams.getStartTime(); + String endTime = biParams.getEndTime(); + if (StrUtil.isNotEmpty(type)) { + //1.今天 2.昨天 3.本周 4.上周 5.本月 6.上月 7.本季度 8.上季度 9.本年 10 上年 + switch (type) { + case "1": + beginDate = DateUtil.beginOfDay(DateUtil.date()); + endDate = DateUtil.endOfDay(DateUtil.date()); + sqlDateFormat = "%Y%m%d"; + dateFormat = "yyyyMMdd"; + cycleNum = 1; + break; + case "2": + beginDate = DateUtil.beginOfDay(new Date(System.currentTimeMillis() - 86400000)); + endDate = DateUtil.endOfDay(new Date(System.currentTimeMillis() - 86400000)); + sqlDateFormat = "%Y%m%d"; + dateFormat = "yyyyMMdd"; + cycleNum = 1; + break; + case "3": + beginDate = DateUtil.beginOfWeek(DateUtil.date()); + endDate = DateUtil.endOfWeek(DateUtil.date()); + sqlDateFormat = "%Y%m%d"; + dateFormat = "yyyyMMdd"; + cycleNum = 7; + break; + case "4": + beginDate = DateUtil.beginOfWeek(DateUtil.offsetWeek(DateUtil.date(), -1)); + endDate = DateUtil.endOfWeek(DateUtil.offsetWeek(DateUtil.date(), -1)); + sqlDateFormat = "%Y%m%d"; + dateFormat = "yyyyMMdd"; + cycleNum = 7; + break; + case "5": + beginDate = DateUtil.beginOfMonth(DateUtil.date()); + endDate = DateUtil.endOfMonth(DateUtil.date()); + sqlDateFormat = "%Y%m%d"; + dateFormat = "yyyyMMdd"; + cycleNum = (int) DateUtil.between(beginDate, endDate, DateUnit.DAY) + 1; + break; + case "6": + beginDate = DateUtil.beginOfMonth(DateUtil.offsetMonth(DateUtil.date(), -1)); + endDate = DateUtil.endOfMonth(DateUtil.offsetMonth(DateUtil.date(), -1)); + sqlDateFormat = "%Y%m%d"; + dateFormat = "yyyyMMdd"; + cycleNum = (int) DateUtil.between(beginDate, endDate, DateUnit.DAY) + 1; + break; + case "7": + beginDate = DateUtil.beginOfQuarter(DateUtil.date()); + endDate = DateUtil.endOfQuarter(DateUtil.date()); + cycleNum = 3; + break; + case "8": + beginDate = DateUtil.beginOfQuarter(DateUtil.offsetMonth(DateUtil.date(), -3)); + endDate = DateUtil.endOfQuarter(DateUtil.offsetMonth(DateUtil.date(), -3)); + cycleNum = 3; + break; + case "9": + beginDate = DateUtil.beginOfYear(DateUtil.date()); + endDate = DateUtil.endOfYear(DateUtil.date()); + break; + case "10": + beginDate = DateUtil.beginOfYear(DateUtil.offsetMonth(DateUtil.date(), -12)); + endDate = DateUtil.endOfYear(DateUtil.offsetMonth(DateUtil.date(), -12)); + break; + default: + break; + } + } else if (StrUtil.isNotEmpty(startTime) && StrUtil.isNotEmpty(endTime)) { + Date start; + Date end; + if (startTime.length() == 6) { + start = DateUtil.parse(startTime, "yyyyMM"); + end = DateUtil.endOfMonth(DateUtil.parse(endTime, "yyyyMM")); + } else { + start = DateUtil.parse(startTime); + end = DateUtil.parse(endTime); + } + Integer startMonth = Integer.valueOf(DateUtil.format(start, "yyyyMM")); + int endMonth = Integer.parseInt(DateUtil.format(end, "yyyyMM")); + if (startMonth.equals(endMonth)) { + sqlDateFormat = "%Y%m%d"; + dateFormat = "yyyyMMdd"; + long diffDay = DateUtil.between(start, end, DateUnit.DAY); + cycleNum = (int) diffDay + 1; + } else { + sqlDateFormat = "%Y%m"; + dateFormat = "yyyyMM"; + int diffYear = Integer.parseInt(Integer.toString(endMonth).substring(0, 4)) - Integer.parseInt(startMonth.toString().substring(0, 4)); + int diffMonth = endMonth % 100 - startMonth % 100 + 1; + cycleNum = diffYear * 12 + diffMonth; + } + beginDate = start; + endDate = end; + } + Integer beginTime = Integer.valueOf(DateUtil.format(beginDate, dateFormat)); + Integer finalTime = Integer.valueOf(DateUtil.format(endDate, dateFormat)); + return new BiTimeEntity(sqlDateFormat, dateFormat, beginDate, endDate, cycleNum, beginTime, finalTime, new ArrayList<>()); + } + + @Data + @Accessors(chain = true) + public static class BiTimeEntity { + /** + * sql日期格式化 + */ + private String sqlDateFormat; + + /** + * 日期格式化 + */ + private String dateFormat; + + /** + * 开始时间 + */ + private Date beginDate; + + /** + * 结束时间 + */ + private Date endDate; + + /** + * 周期 + */ + private Integer cycleNum; + + /** + * 开始时间 字符串格式 如20200101 + */ + private Integer beginTime; + + /** + * 结束时间 字符串格式 如20200101 + */ + private Integer finalTime; + + /** + * user列表 + */ + private List userIds = new ArrayList<>(); + private Integer page; + private Integer limit; + + public BiTimeEntity(String sqlDateFormat, String dateFormat, Date beginDate, Date endDate, Integer cycleNum, Integer beginTime, Integer finalTime, List userIds) { + this.sqlDateFormat = sqlDateFormat; + this.dateFormat = dateFormat; + this.beginDate = beginDate; + this.endDate = endDate; + this.cycleNum = cycleNum; + this.beginTime = beginTime; + this.finalTime = finalTime; + this.userIds = userIds; + } + + public BiTimeEntity() { + } + + } +} diff --git a/yudao-module-crm/yudao-module-bi-biz/src/main/resources/mapper/rank/BiRankingMapper.xml b/yudao-module-crm/yudao-module-bi-biz/src/main/resources/mapper/rank/BiRankingMapper.xml new file mode 100644 index 000000000..9bee4fbaf --- /dev/null +++ b/yudao-module-crm/yudao-module-bi-biz/src/main/resources/mapper/rank/BiRankingMapper.xml @@ -0,0 +1,42 @@ + + + + + + + + diff --git a/yudao-module-system/yudao-module-system-api/src/main/java/cn/iocoder/yudao/module/system/api/dept/DeptApi.java b/yudao-module-system/yudao-module-system-api/src/main/java/cn/iocoder/yudao/module/system/api/dept/DeptApi.java index f8059fbb7..bdc3ba59b 100644 --- a/yudao-module-system/yudao-module-system-api/src/main/java/cn/iocoder/yudao/module/system/api/dept/DeptApi.java +++ b/yudao-module-system/yudao-module-system-api/src/main/java/cn/iocoder/yudao/module/system/api/dept/DeptApi.java @@ -50,4 +50,12 @@ public interface DeptApi { return CollectionUtils.convertMap(list, DeptRespDTO::getId); } + /** + * 获得指定部门的所有子部门 + * + * @param id 部门编号 + * @return 子部门列表 + */ + List getChildDeptList(Long id); + } diff --git a/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/api/dept/DeptApiImpl.java b/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/api/dept/DeptApiImpl.java index 76685cf31..00d79ceaa 100644 --- a/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/api/dept/DeptApiImpl.java +++ b/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/api/dept/DeptApiImpl.java @@ -4,6 +4,7 @@ import cn.iocoder.yudao.framework.common.util.object.BeanUtils; import cn.iocoder.yudao.module.system.api.dept.dto.DeptRespDTO; import cn.iocoder.yudao.module.system.dal.dataobject.dept.DeptDO; import cn.iocoder.yudao.module.system.service.dept.DeptService; +import org.springframework.context.annotation.Lazy; import org.springframework.stereotype.Service; import jakarta.annotation.Resource; @@ -19,6 +20,7 @@ import java.util.List; public class DeptApiImpl implements DeptApi { @Resource + @Lazy // 延迟加载,解决相互依赖的问题 private DeptService deptService; @Override @@ -38,4 +40,11 @@ public class DeptApiImpl implements DeptApi { deptService.validateDeptList(ids); } + @Override + public List getChildDeptList(Long id) { + List childDeptList = deptService.getChildDeptList(id); + return BeanUtils.toBean(childDeptList, DeptRespDTO.class); + } + + } diff --git a/yudao-server/pom.xml b/yudao-server/pom.xml index 85b284c3c..3caebe16c 100644 --- a/yudao-server/pom.xml +++ b/yudao-server/pom.xml @@ -97,6 +97,11 @@ yudao-module-crm-biz ${revision} + + cn.iocoder.boot + yudao-module-bi-biz + ${revision} + From 65d7f8c4ab8086480709201816f9747885a7e022 Mon Sep 17 00:00:00 2001 From: anhaohao <1036606149@qq.com> Date: Sun, 28 Jan 2024 20:06:56 +0800 Subject: [PATCH 049/119] =?UTF-8?q?=E6=96=B0=E5=A2=9E=EF=BC=9ACRM=20?= =?UTF-8?q?=E5=95=86=E4=B8=9A=E6=99=BA=E8=83=BD=EF=BC=8C=E5=90=88=E5=90=8C?= =?UTF-8?q?=E9=87=91=E9=A2=9D=E6=8E=92=E8=A1=8C=E6=A6=9C=E5=92=8C=E5=9B=9E?= =?UTF-8?q?=E6=AC=BE=E9=87=91=E9=A2=9D=E6=8E=92=E8=A1=8C=E6=A6=9C?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- yudao-module-crm/pom.xml | 3 + yudao-module-crm/yudao-module-bi-api/pom.xml | 73 +++++ .../yudao/module/bi/api/package-info.java | 1 + .../yudao/module/bi/enums/package-info.java | 1 + yudao-module-crm/yudao-module-bi-biz/pom.xml | 74 ++++++ .../admin/ranking/BiRankingController.http | 10 + .../admin/ranking/BiRankingController.java | 53 ++++ .../ranking/vo/BiContractRanKingRespVO.java | 24 ++ .../controller/admin/ranking/vo/BiParams.java | 41 +++ .../admin/ranking/vo/BiRankReqVO.java | 20 ++ .../vo/BiReceivablesRanKingRespVO.java | 23 ++ .../module/bi/controller/package-info.java | 6 + .../module/bi/dal/mysql/BiRankingMapper.java | 31 +++ .../module/bi/framework/package-info.java | 6 + .../web/config/BiWebConfiguration.java | 24 ++ .../module/bi/framework/web/package-info.java | 4 + .../iocoder/yudao/module/bi/package-info.java | 7 + .../bi/service/ranking/BiRankingService.java | 30 +++ .../service/ranking/BiRankingServiceImpl.java | 53 ++++ .../yudao/module/bi/util/BiTimeUtil.java | 249 ++++++++++++++++++ .../resources/mapper/rank/BiRankingMapper.xml | 42 +++ .../yudao/module/system/api/dept/DeptApi.java | 8 + .../module/system/api/dept/DeptApiImpl.java | 9 + yudao-server/pom.xml | 5 + 24 files changed, 797 insertions(+) create mode 100644 yudao-module-crm/yudao-module-bi-api/pom.xml create mode 100644 yudao-module-crm/yudao-module-bi-api/src/main/java/cn/iocoder/yudao/module/bi/api/package-info.java create mode 100644 yudao-module-crm/yudao-module-bi-api/src/main/java/cn/iocoder/yudao/module/bi/enums/package-info.java create mode 100644 yudao-module-crm/yudao-module-bi-biz/pom.xml create mode 100644 yudao-module-crm/yudao-module-bi-biz/src/main/java/cn/iocoder/yudao/module/bi/controller/admin/ranking/BiRankingController.http create mode 100644 yudao-module-crm/yudao-module-bi-biz/src/main/java/cn/iocoder/yudao/module/bi/controller/admin/ranking/BiRankingController.java create mode 100644 yudao-module-crm/yudao-module-bi-biz/src/main/java/cn/iocoder/yudao/module/bi/controller/admin/ranking/vo/BiContractRanKingRespVO.java create mode 100644 yudao-module-crm/yudao-module-bi-biz/src/main/java/cn/iocoder/yudao/module/bi/controller/admin/ranking/vo/BiParams.java create mode 100644 yudao-module-crm/yudao-module-bi-biz/src/main/java/cn/iocoder/yudao/module/bi/controller/admin/ranking/vo/BiRankReqVO.java create mode 100644 yudao-module-crm/yudao-module-bi-biz/src/main/java/cn/iocoder/yudao/module/bi/controller/admin/ranking/vo/BiReceivablesRanKingRespVO.java create mode 100644 yudao-module-crm/yudao-module-bi-biz/src/main/java/cn/iocoder/yudao/module/bi/controller/package-info.java create mode 100644 yudao-module-crm/yudao-module-bi-biz/src/main/java/cn/iocoder/yudao/module/bi/dal/mysql/BiRankingMapper.java create mode 100644 yudao-module-crm/yudao-module-bi-biz/src/main/java/cn/iocoder/yudao/module/bi/framework/package-info.java create mode 100644 yudao-module-crm/yudao-module-bi-biz/src/main/java/cn/iocoder/yudao/module/bi/framework/web/config/BiWebConfiguration.java create mode 100644 yudao-module-crm/yudao-module-bi-biz/src/main/java/cn/iocoder/yudao/module/bi/framework/web/package-info.java create mode 100644 yudao-module-crm/yudao-module-bi-biz/src/main/java/cn/iocoder/yudao/module/bi/package-info.java create mode 100644 yudao-module-crm/yudao-module-bi-biz/src/main/java/cn/iocoder/yudao/module/bi/service/ranking/BiRankingService.java create mode 100644 yudao-module-crm/yudao-module-bi-biz/src/main/java/cn/iocoder/yudao/module/bi/service/ranking/BiRankingServiceImpl.java create mode 100644 yudao-module-crm/yudao-module-bi-biz/src/main/java/cn/iocoder/yudao/module/bi/util/BiTimeUtil.java create mode 100644 yudao-module-crm/yudao-module-bi-biz/src/main/resources/mapper/rank/BiRankingMapper.xml diff --git a/yudao-module-crm/pom.xml b/yudao-module-crm/pom.xml index 2a7b748c3..c281c7bfa 100644 --- a/yudao-module-crm/pom.xml +++ b/yudao-module-crm/pom.xml @@ -10,6 +10,8 @@ yudao-module-crm-api yudao-module-crm-biz + yudao-module-bi-biz + yudao-module-bi-api 4.0.0 yudao-module-crm @@ -20,6 +22,7 @@ crm 包下,客户关系管理(Customer Relationship Management)。 例如说:客户、联系人、商机、合同、回款等等 + 商业智能 BI 模块,包括:报表、图表、数据大屏等等 diff --git a/yudao-module-crm/yudao-module-bi-api/pom.xml b/yudao-module-crm/yudao-module-bi-api/pom.xml new file mode 100644 index 000000000..aa21b85f9 --- /dev/null +++ b/yudao-module-crm/yudao-module-bi-api/pom.xml @@ -0,0 +1,73 @@ + + + + cn.iocoder.boot + yudao-module-crm + ${revision} + + 4.0.0 + yudao-module-bi-api + + ${project.artifactId} + + bi 模块 API,暴露给其它模块调用 + + + + + cn.iocoder.boot + yudao-module-system-api + ${revision} + + + cn.iocoder.boot + yudao-module-crm-api + ${revision} + + + + + cn.iocoder.boot + yudao-spring-boot-starter-biz-operatelog + + + cn.iocoder.boot + yudao-spring-boot-starter-biz-ip + + + + + cn.iocoder.boot + yudao-spring-boot-starter-web + + + + cn.iocoder.boot + yudao-spring-boot-starter-security + + + + + cn.iocoder.boot + yudao-spring-boot-starter-mybatis + + + + + cn.iocoder.boot + yudao-spring-boot-starter-excel + + + cn.iocoder.boot + yudao-spring-boot-starter-biz-dict + + + + + cn.iocoder.boot + yudao-spring-boot-starter-test + + + \ No newline at end of file diff --git a/yudao-module-crm/yudao-module-bi-api/src/main/java/cn/iocoder/yudao/module/bi/api/package-info.java b/yudao-module-crm/yudao-module-bi-api/src/main/java/cn/iocoder/yudao/module/bi/api/package-info.java new file mode 100644 index 000000000..77e7d2290 --- /dev/null +++ b/yudao-module-crm/yudao-module-bi-api/src/main/java/cn/iocoder/yudao/module/bi/api/package-info.java @@ -0,0 +1 @@ +package cn.iocoder.yudao.module.bi.api; \ No newline at end of file diff --git a/yudao-module-crm/yudao-module-bi-api/src/main/java/cn/iocoder/yudao/module/bi/enums/package-info.java b/yudao-module-crm/yudao-module-bi-api/src/main/java/cn/iocoder/yudao/module/bi/enums/package-info.java new file mode 100644 index 000000000..eb4c1e428 --- /dev/null +++ b/yudao-module-crm/yudao-module-bi-api/src/main/java/cn/iocoder/yudao/module/bi/enums/package-info.java @@ -0,0 +1 @@ +package cn.iocoder.yudao.module.bi.enums; \ No newline at end of file diff --git a/yudao-module-crm/yudao-module-bi-biz/pom.xml b/yudao-module-crm/yudao-module-bi-biz/pom.xml new file mode 100644 index 000000000..92c8e2f9f --- /dev/null +++ b/yudao-module-crm/yudao-module-bi-biz/pom.xml @@ -0,0 +1,74 @@ + + + + cn.iocoder.boot + yudao-module-crm + ${revision} + + 4.0.0 + yudao-module-bi-biz + + ${project.artifactId} + + crm 包下,商业智能(Business Intelligence)。 + 例如说:报表、图表、数据分析等等 + + + + + cn.iocoder.boot + yudao-module-system-api + ${revision} + + + cn.iocoder.boot + yudao-module-crm-api + ${revision} + + + + + cn.iocoder.boot + yudao-spring-boot-starter-biz-operatelog + + + cn.iocoder.boot + yudao-spring-boot-starter-biz-ip + + + + + cn.iocoder.boot + yudao-spring-boot-starter-web + + + + cn.iocoder.boot + yudao-spring-boot-starter-security + + + + + cn.iocoder.boot + yudao-spring-boot-starter-mybatis + + + + + cn.iocoder.boot + yudao-spring-boot-starter-excel + + + cn.iocoder.boot + yudao-spring-boot-starter-biz-dict + + + + + cn.iocoder.boot + yudao-spring-boot-starter-test + + + \ No newline at end of file diff --git a/yudao-module-crm/yudao-module-bi-biz/src/main/java/cn/iocoder/yudao/module/bi/controller/admin/ranking/BiRankingController.http b/yudao-module-crm/yudao-module-bi-biz/src/main/java/cn/iocoder/yudao/module/bi/controller/admin/ranking/BiRankingController.http new file mode 100644 index 000000000..50ab7ec2b --- /dev/null +++ b/yudao-module-crm/yudao-module-bi-biz/src/main/java/cn/iocoder/yudao/module/bi/controller/admin/ranking/BiRankingController.http @@ -0,0 +1,10 @@ +### 合同金额排行榜 +GET {{baseUrl}}/bi/rank/contract-ranKing +Authorization: Bearer {{token}} +tenant-id: {{adminTenentId}} + + +### 回款金额排行榜 +GET {{baseUrl}}/bi/rank/receivables-ranKing +Authorization: Bearer {{token}} +tenant-id: {{adminTenentId}} diff --git a/yudao-module-crm/yudao-module-bi-biz/src/main/java/cn/iocoder/yudao/module/bi/controller/admin/ranking/BiRankingController.java b/yudao-module-crm/yudao-module-bi-biz/src/main/java/cn/iocoder/yudao/module/bi/controller/admin/ranking/BiRankingController.java new file mode 100644 index 000000000..2d81ae80d --- /dev/null +++ b/yudao-module-crm/yudao-module-bi-biz/src/main/java/cn/iocoder/yudao/module/bi/controller/admin/ranking/BiRankingController.java @@ -0,0 +1,53 @@ +package cn.iocoder.yudao.module.bi.controller.admin.ranking; + + +import cn.iocoder.yudao.framework.common.pojo.CommonResult; +import cn.iocoder.yudao.module.bi.controller.admin.ranking.vo.BiContractRanKingRespVO; +import cn.iocoder.yudao.module.bi.controller.admin.ranking.vo.BiRankReqVO; +import cn.iocoder.yudao.module.bi.controller.admin.ranking.vo.BiReceivablesRanKingRespVO; +import cn.iocoder.yudao.module.bi.service.ranking.BiRankingService; +import io.swagger.v3.oas.annotations.Operation; +import io.swagger.v3.oas.annotations.tags.Tag; +import jakarta.annotation.Resource; +import org.springframework.security.access.prepost.PreAuthorize; +import org.springframework.validation.annotation.Validated; +import org.springframework.web.bind.annotation.GetMapping; +import org.springframework.web.bind.annotation.RequestMapping; +import org.springframework.web.bind.annotation.RestController; + +import java.util.List; + +import static cn.iocoder.yudao.framework.common.pojo.CommonResult.success; + +/** + * @author anhaohao + */ +@Tag(name = "管理后台 - 排行榜") +@RestController +@RequestMapping("/bi/ranking") +@Validated +public class BiRankingController { + + @Resource + private BiRankingService biRankingService; + + /** + * 合同金额排行榜 + */ + @GetMapping("/contract-ranking") + @Operation(summary = "合同金额排行榜") + @PreAuthorize("@ss.hasPermission('bi:ranking:query')") + public CommonResult> contractAmountRanking(BiRankReqVO biRankReqVO) { + return success(biRankingService.contractRanKing(biRankReqVO)); + } + + /** + * 回款金额排行榜 + */ + @GetMapping("/receivables-ranking") + @Operation(summary = "回款金额排行榜") + @PreAuthorize("@ss.hasPermission('bi:ranking:query')") + public CommonResult> receivablesRanKing(BiRankReqVO biRankReqVO) { + return success(biRankingService.receivablesRanKing(biRankReqVO)); + } +} diff --git a/yudao-module-crm/yudao-module-bi-biz/src/main/java/cn/iocoder/yudao/module/bi/controller/admin/ranking/vo/BiContractRanKingRespVO.java b/yudao-module-crm/yudao-module-bi-biz/src/main/java/cn/iocoder/yudao/module/bi/controller/admin/ranking/vo/BiContractRanKingRespVO.java new file mode 100644 index 000000000..777996b90 --- /dev/null +++ b/yudao-module-crm/yudao-module-bi-biz/src/main/java/cn/iocoder/yudao/module/bi/controller/admin/ranking/vo/BiContractRanKingRespVO.java @@ -0,0 +1,24 @@ +package cn.iocoder.yudao.module.bi.controller.admin.ranking.vo; + +import io.swagger.v3.oas.annotations.media.Schema; +import lombok.Data; + +/** + * 管理后台 - BI 排行榜 Response VO + * + * @author anhaohao + */ +@Schema(description = "管理后台 - BI 合同金额排行榜 Response VO") +@Data +public class BiContractRanKingRespVO { + + @Schema(description = "金额", example = "1") + private Integer price; + + @Schema(description = "姓名", example = "1") + private String nickname; + + + @Schema(description = "部门名称", example = "1") + private String deptName; +} diff --git a/yudao-module-crm/yudao-module-bi-biz/src/main/java/cn/iocoder/yudao/module/bi/controller/admin/ranking/vo/BiParams.java b/yudao-module-crm/yudao-module-bi-biz/src/main/java/cn/iocoder/yudao/module/bi/controller/admin/ranking/vo/BiParams.java new file mode 100644 index 000000000..5cce4c6cb --- /dev/null +++ b/yudao-module-crm/yudao-module-bi-biz/src/main/java/cn/iocoder/yudao/module/bi/controller/admin/ranking/vo/BiParams.java @@ -0,0 +1,41 @@ +package cn.iocoder.yudao.module.bi.controller.admin.ranking.vo; + +import cn.iocoder.yudao.framework.common.pojo.PageParam; +import io.swagger.v3.oas.annotations.media.Schema; +import lombok.Data; +import lombok.EqualsAndHashCode; + +import java.util.List; + +/** + * @author anhaohao + * bi参数 + */ +@EqualsAndHashCode(callSuper = true) +@Schema(description = "bi查询相关参数") +@Data +public class BiParams extends PageParam { + + @Schema(description = "部门ID") + private Long deptId; + + @Schema(description = "用户ID") + private Long userId; + + @Schema(description = "用户IDs") + private List userIds; + + @Schema(description = "类型") + private String type; + + @Schema(description = "开始时间") + private String startTime; + + @Schema(description = "结束时间") + private String endTime; + + @Schema(description = "0 部门 1员工") + private Integer isUser = 1; + + +} diff --git a/yudao-module-crm/yudao-module-bi-biz/src/main/java/cn/iocoder/yudao/module/bi/controller/admin/ranking/vo/BiRankReqVO.java b/yudao-module-crm/yudao-module-bi-biz/src/main/java/cn/iocoder/yudao/module/bi/controller/admin/ranking/vo/BiRankReqVO.java new file mode 100644 index 000000000..1569ba88d --- /dev/null +++ b/yudao-module-crm/yudao-module-bi-biz/src/main/java/cn/iocoder/yudao/module/bi/controller/admin/ranking/vo/BiRankReqVO.java @@ -0,0 +1,20 @@ +package cn.iocoder.yudao.module.bi.controller.admin.ranking.vo; + +import io.swagger.v3.oas.annotations.media.Schema; +import lombok.Data; + +/** + * 管理后台 - 排行榜 Request VO + * + * @author anhaohao + */ +@Schema(description = "管理后台 - 排行榜 Request VO") +@Data +public class BiRankReqVO { + + @Schema(description = "部门id", requiredMode = Schema.RequiredMode.REQUIRED, example = "1") + private Long deptId; + + @Schema(description = "分析类型(1.今天 2.昨天 3.本周 4.上周 5.本月 6.上月 7.本季度 8.上季度 9.本年 10 上年)", requiredMode = Schema.RequiredMode.REQUIRED, example = "1") + private String type; +} diff --git a/yudao-module-crm/yudao-module-bi-biz/src/main/java/cn/iocoder/yudao/module/bi/controller/admin/ranking/vo/BiReceivablesRanKingRespVO.java b/yudao-module-crm/yudao-module-bi-biz/src/main/java/cn/iocoder/yudao/module/bi/controller/admin/ranking/vo/BiReceivablesRanKingRespVO.java new file mode 100644 index 000000000..32b49231f --- /dev/null +++ b/yudao-module-crm/yudao-module-bi-biz/src/main/java/cn/iocoder/yudao/module/bi/controller/admin/ranking/vo/BiReceivablesRanKingRespVO.java @@ -0,0 +1,23 @@ +package cn.iocoder.yudao.module.bi.controller.admin.ranking.vo; + +import io.swagger.v3.oas.annotations.media.Schema; +import lombok.Data; + +/** + * 管理后台 - BI 排行榜 Response VO + * + * @author anhaohao + */ +@Schema(description = "管理后台 - BI 合同金额排行榜 Response VO") +@Data +public class BiReceivablesRanKingRespVO { + + @Schema(description = "金额", example = "100") + private Integer price; + + @Schema(description = "姓名", example = "张三") + private String nickname; + + @Schema(description = "部门名称", example = "研发部") + private String deptName; +} diff --git a/yudao-module-crm/yudao-module-bi-biz/src/main/java/cn/iocoder/yudao/module/bi/controller/package-info.java b/yudao-module-crm/yudao-module-bi-biz/src/main/java/cn/iocoder/yudao/module/bi/controller/package-info.java new file mode 100644 index 000000000..052f6238f --- /dev/null +++ b/yudao-module-crm/yudao-module-bi-biz/src/main/java/cn/iocoder/yudao/module/bi/controller/package-info.java @@ -0,0 +1,6 @@ +/** + * 提供 RESTful API 给前端: + * 1. admin 包:提供给管理后台 yudao-ui-admin 前端项目 + * 2. app 包:提供给用户 APP yudao-ui-app 前端项目,它的 Controller 和 VO 都要添加 App 前缀,用于和管理后台进行区分 + */ +package cn.iocoder.yudao.module.bi.controller; diff --git a/yudao-module-crm/yudao-module-bi-biz/src/main/java/cn/iocoder/yudao/module/bi/dal/mysql/BiRankingMapper.java b/yudao-module-crm/yudao-module-bi-biz/src/main/java/cn/iocoder/yudao/module/bi/dal/mysql/BiRankingMapper.java new file mode 100644 index 000000000..e37184031 --- /dev/null +++ b/yudao-module-crm/yudao-module-bi-biz/src/main/java/cn/iocoder/yudao/module/bi/dal/mysql/BiRankingMapper.java @@ -0,0 +1,31 @@ +package cn.iocoder.yudao.module.bi.dal.mysql; + +import cn.iocoder.yudao.framework.mybatis.core.mapper.BaseMapperX; +import cn.iocoder.yudao.module.bi.controller.admin.ranking.vo.BiContractRanKingRespVO; +import cn.iocoder.yudao.module.bi.controller.admin.ranking.vo.BiReceivablesRanKingRespVO; +import cn.iocoder.yudao.module.bi.util.BiTimeUtil; +import org.apache.ibatis.annotations.Mapper; + +import java.util.List; + +/** + * @author anhaohao + */ +@Mapper +public interface BiRankingMapper extends BaseMapperX { + /** + * 合同金额排行榜 + * + * @param biTimeEntity 参数 + * @return List + */ + List contractRanKing(BiTimeUtil.BiTimeEntity biTimeEntity); + + /** + * 回款金额排行榜 + * + * @param biTimeEntity 参数 + * @return List + */ + List receivablesRanKing(BiTimeUtil.BiTimeEntity biTimeEntity); +} diff --git a/yudao-module-crm/yudao-module-bi-biz/src/main/java/cn/iocoder/yudao/module/bi/framework/package-info.java b/yudao-module-crm/yudao-module-bi-biz/src/main/java/cn/iocoder/yudao/module/bi/framework/package-info.java new file mode 100644 index 000000000..8b004cf8c --- /dev/null +++ b/yudao-module-crm/yudao-module-bi-biz/src/main/java/cn/iocoder/yudao/module/bi/framework/package-info.java @@ -0,0 +1,6 @@ +/** + * 属于 bi 模块的 framework 封装 + * + * @author 芋道源码 + */ +package cn.iocoder.yudao.module.bi.framework; diff --git a/yudao-module-crm/yudao-module-bi-biz/src/main/java/cn/iocoder/yudao/module/bi/framework/web/config/BiWebConfiguration.java b/yudao-module-crm/yudao-module-bi-biz/src/main/java/cn/iocoder/yudao/module/bi/framework/web/config/BiWebConfiguration.java new file mode 100644 index 000000000..ad10cdccd --- /dev/null +++ b/yudao-module-crm/yudao-module-bi-biz/src/main/java/cn/iocoder/yudao/module/bi/framework/web/config/BiWebConfiguration.java @@ -0,0 +1,24 @@ +package cn.iocoder.yudao.module.bi.framework.web.config; + +import cn.iocoder.yudao.framework.swagger.config.YudaoSwaggerAutoConfiguration; +import org.springdoc.core.models.GroupedOpenApi; +import org.springframework.context.annotation.Bean; +import org.springframework.context.annotation.Configuration; + +/** + * bi 模块的 web 组件的 Configuration + * + * @author 芋道源码 + */ +@Configuration(proxyBeanMethods = false) +public class BiWebConfiguration { + + /** + * bi 模块的 API 分组 + */ + @Bean + public GroupedOpenApi biGroupedOpenApi() { + return YudaoSwaggerAutoConfiguration.buildGroupedOpenApi("bi"); + } + +} diff --git a/yudao-module-crm/yudao-module-bi-biz/src/main/java/cn/iocoder/yudao/module/bi/framework/web/package-info.java b/yudao-module-crm/yudao-module-bi-biz/src/main/java/cn/iocoder/yudao/module/bi/framework/web/package-info.java new file mode 100644 index 000000000..e17abbb1c --- /dev/null +++ b/yudao-module-crm/yudao-module-bi-biz/src/main/java/cn/iocoder/yudao/module/bi/framework/web/package-info.java @@ -0,0 +1,4 @@ +/** + * bi 模块的 web 配置 + */ +package cn.iocoder.yudao.module.bi.framework.web; diff --git a/yudao-module-crm/yudao-module-bi-biz/src/main/java/cn/iocoder/yudao/module/bi/package-info.java b/yudao-module-crm/yudao-module-bi-biz/src/main/java/cn/iocoder/yudao/module/bi/package-info.java new file mode 100644 index 000000000..b45b8458d --- /dev/null +++ b/yudao-module-crm/yudao-module-bi-biz/src/main/java/cn/iocoder/yudao/module/bi/package-info.java @@ -0,0 +1,7 @@ +/** + * crm 包下,商业智能(Business Intelligence)。 + * 例如说:报表、图表、数据分析等等 + *

+ * 1. Controller URL:以 /bi/ 开头,避免和其它 Module 冲突 + */ +package cn.iocoder.yudao.module.bi; \ No newline at end of file diff --git a/yudao-module-crm/yudao-module-bi-biz/src/main/java/cn/iocoder/yudao/module/bi/service/ranking/BiRankingService.java b/yudao-module-crm/yudao-module-bi-biz/src/main/java/cn/iocoder/yudao/module/bi/service/ranking/BiRankingService.java new file mode 100644 index 000000000..98f1346de --- /dev/null +++ b/yudao-module-crm/yudao-module-bi-biz/src/main/java/cn/iocoder/yudao/module/bi/service/ranking/BiRankingService.java @@ -0,0 +1,30 @@ +package cn.iocoder.yudao.module.bi.service.ranking; + +import cn.iocoder.yudao.module.bi.controller.admin.ranking.vo.BiContractRanKingRespVO; +import cn.iocoder.yudao.module.bi.controller.admin.ranking.vo.BiRankReqVO; +import cn.iocoder.yudao.module.bi.controller.admin.ranking.vo.BiReceivablesRanKingRespVO; + +import java.util.List; + +/** + * BI 排行榜 Service 接口 + * + * @author anhaohao + */ +public interface BiRankingService { + /** + * 合同金额排行榜 + * + * @param biRankReqVO 参数 + * @return List + */ + List contractRanKing(BiRankReqVO biRankReqVO); + + /** + * 回款金额排行榜 + * + * @param biRankReqVO 参数 + * @return List + */ + List receivablesRanKing(BiRankReqVO biRankReqVO); +} diff --git a/yudao-module-crm/yudao-module-bi-biz/src/main/java/cn/iocoder/yudao/module/bi/service/ranking/BiRankingServiceImpl.java b/yudao-module-crm/yudao-module-bi-biz/src/main/java/cn/iocoder/yudao/module/bi/service/ranking/BiRankingServiceImpl.java new file mode 100644 index 000000000..1ed468547 --- /dev/null +++ b/yudao-module-crm/yudao-module-bi-biz/src/main/java/cn/iocoder/yudao/module/bi/service/ranking/BiRankingServiceImpl.java @@ -0,0 +1,53 @@ +package cn.iocoder.yudao.module.bi.service.ranking; + +import cn.iocoder.yudao.module.bi.controller.admin.ranking.vo.BiContractRanKingRespVO; +import cn.iocoder.yudao.module.bi.controller.admin.ranking.vo.BiParams; +import cn.iocoder.yudao.module.bi.controller.admin.ranking.vo.BiRankReqVO; +import cn.iocoder.yudao.module.bi.controller.admin.ranking.vo.BiReceivablesRanKingRespVO; +import cn.iocoder.yudao.module.bi.dal.mysql.BiRankingMapper; +import cn.iocoder.yudao.module.bi.util.BiTimeUtil; +import jakarta.annotation.Resource; +import org.springframework.stereotype.Service; +import org.springframework.validation.annotation.Validated; + +import java.util.ArrayList; +import java.util.List; + +/** + * @author anhaohao + */ +@Service(value = "biRankService") +@Validated +public class BiRankingServiceImpl implements BiRankingService { + + @Resource + private BiRankingMapper biRankingMapper; + + @Override + public List contractRanKing(BiRankReqVO biRankReqVO) { + BiParams biParams = new BiParams(); + biParams.setType(biRankReqVO.getType()); + biParams.setDeptId(biRankReqVO.getDeptId()); + biParams.setIsUser(0); + BiTimeUtil.BiTimeEntity biTimeEntity = BiTimeUtil.analyzeType(biParams); + List userIds = biTimeEntity.getUserIds(); + if (userIds.isEmpty()) { + return new ArrayList<>(); + } + return biRankingMapper.contractRanKing(biTimeEntity); + } + + @Override + public List receivablesRanKing(BiRankReqVO biRankReqVO) { + BiParams biParams = new BiParams(); + biParams.setType(biRankReqVO.getType()); + biParams.setDeptId(biRankReqVO.getDeptId()); + biParams.setIsUser(0); + BiTimeUtil.BiTimeEntity biTimeEntity = BiTimeUtil.analyzeType(biParams); + List userIds = biTimeEntity.getUserIds(); + if (userIds.isEmpty()) { + return new ArrayList<>(); + } + return biRankingMapper.receivablesRanKing(biTimeEntity); + } +} diff --git a/yudao-module-crm/yudao-module-bi-biz/src/main/java/cn/iocoder/yudao/module/bi/util/BiTimeUtil.java b/yudao-module-crm/yudao-module-bi-biz/src/main/java/cn/iocoder/yudao/module/bi/util/BiTimeUtil.java new file mode 100644 index 000000000..b1b68aea2 --- /dev/null +++ b/yudao-module-crm/yudao-module-bi-biz/src/main/java/cn/iocoder/yudao/module/bi/util/BiTimeUtil.java @@ -0,0 +1,249 @@ +package cn.iocoder.yudao.module.bi.util; + +import cn.hutool.core.date.DateUnit; +import cn.hutool.core.date.DateUtil; +import cn.hutool.core.util.StrUtil; +import cn.hutool.extra.spring.SpringUtil; +import cn.iocoder.yudao.framework.security.core.util.SecurityFrameworkUtils; +import cn.iocoder.yudao.module.bi.controller.admin.ranking.vo.BiParams; +import cn.iocoder.yudao.module.system.api.dept.DeptApi; +import cn.iocoder.yudao.module.system.api.dept.dto.DeptRespDTO; +import cn.iocoder.yudao.module.system.api.user.AdminUserApi; +import cn.iocoder.yudao.module.system.api.user.dto.AdminUserRespDTO; +import lombok.Data; +import lombok.experimental.Accessors; + +import java.util.ArrayList; +import java.util.Date; +import java.util.List; + +/** + * bi时间工具类 + * + * @author anhaohao + */ +public class BiTimeUtil { + + public static BiTimeEntity analyzeType(BiParams biParams) { + // 解析时间 + BiTimeEntity biTimeEntity = analyzeTime(biParams); + // 解析权限 + biTimeEntity.setUserIds(analyzeAuth(biParams)); + return biTimeEntity; + } + + /** + * 解析权限 + * + * @param biParams bi参数 + * @return List + */ + public static List analyzeAuth(BiParams biParams) { + List userIdList = new ArrayList<>(); + Long deptId = biParams.getDeptId(); + Long userId = biParams.getUserId(); + Integer isUser = biParams.getIsUser(); + // 获取部门和用户的api + DeptApi deptApi = SpringUtil.getBean("deptApiImpl"); + AdminUserApi adminUserApi = SpringUtil.getBean("adminUserApiImpl"); + // 0.部门 1.用户 + if (isUser == 0) { + if (deptId == null) { + deptId = adminUserApi.getUser(SecurityFrameworkUtils.getLoginUserId()).getDeptId(); + } + List childDeptList = deptApi.getChildDeptList(deptId); + List deptIds = new ArrayList<>(); + deptIds.add(deptId); + if (childDeptList != null && !childDeptList.isEmpty()) { + for (DeptRespDTO deptRespDTO : childDeptList) { + deptIds.add(deptRespDTO.getId()); + } + } + // 获取部门下的用户 + adminUserApi.getUserListByDeptIds(deptIds).forEach(adminUserRespDTO -> userIdList.add(adminUserRespDTO.getId())); + } else { + if (userId == null) { + List userListBySubordinate = adminUserApi.getUserListBySubordinate(SecurityFrameworkUtils.getLoginUserId()); + userListBySubordinate.forEach(adminUserRespDTO -> userIdList.add(adminUserRespDTO.getId())); + } else { + userIdList.add(userId); + } + } + return userIdList; + } + + + /** + * 解析时间 + * + * @param biParams bi参数 + * @return BiTimeEntity + */ + public static BiTimeEntity analyzeTime(BiParams biParams) { + Date beginDate = DateUtil.date(); + Date endDate = DateUtil.date(); + int cycleNum = 12; + String sqlDateFormat = "%Y%m"; + String dateFormat = "yyyyMM"; + String type = biParams.getType(); + String startTime = biParams.getStartTime(); + String endTime = biParams.getEndTime(); + if (StrUtil.isNotEmpty(type)) { + //1.今天 2.昨天 3.本周 4.上周 5.本月 6.上月 7.本季度 8.上季度 9.本年 10 上年 + switch (type) { + case "1": + beginDate = DateUtil.beginOfDay(DateUtil.date()); + endDate = DateUtil.endOfDay(DateUtil.date()); + sqlDateFormat = "%Y%m%d"; + dateFormat = "yyyyMMdd"; + cycleNum = 1; + break; + case "2": + beginDate = DateUtil.beginOfDay(new Date(System.currentTimeMillis() - 86400000)); + endDate = DateUtil.endOfDay(new Date(System.currentTimeMillis() - 86400000)); + sqlDateFormat = "%Y%m%d"; + dateFormat = "yyyyMMdd"; + cycleNum = 1; + break; + case "3": + beginDate = DateUtil.beginOfWeek(DateUtil.date()); + endDate = DateUtil.endOfWeek(DateUtil.date()); + sqlDateFormat = "%Y%m%d"; + dateFormat = "yyyyMMdd"; + cycleNum = 7; + break; + case "4": + beginDate = DateUtil.beginOfWeek(DateUtil.offsetWeek(DateUtil.date(), -1)); + endDate = DateUtil.endOfWeek(DateUtil.offsetWeek(DateUtil.date(), -1)); + sqlDateFormat = "%Y%m%d"; + dateFormat = "yyyyMMdd"; + cycleNum = 7; + break; + case "5": + beginDate = DateUtil.beginOfMonth(DateUtil.date()); + endDate = DateUtil.endOfMonth(DateUtil.date()); + sqlDateFormat = "%Y%m%d"; + dateFormat = "yyyyMMdd"; + cycleNum = (int) DateUtil.between(beginDate, endDate, DateUnit.DAY) + 1; + break; + case "6": + beginDate = DateUtil.beginOfMonth(DateUtil.offsetMonth(DateUtil.date(), -1)); + endDate = DateUtil.endOfMonth(DateUtil.offsetMonth(DateUtil.date(), -1)); + sqlDateFormat = "%Y%m%d"; + dateFormat = "yyyyMMdd"; + cycleNum = (int) DateUtil.between(beginDate, endDate, DateUnit.DAY) + 1; + break; + case "7": + beginDate = DateUtil.beginOfQuarter(DateUtil.date()); + endDate = DateUtil.endOfQuarter(DateUtil.date()); + cycleNum = 3; + break; + case "8": + beginDate = DateUtil.beginOfQuarter(DateUtil.offsetMonth(DateUtil.date(), -3)); + endDate = DateUtil.endOfQuarter(DateUtil.offsetMonth(DateUtil.date(), -3)); + cycleNum = 3; + break; + case "9": + beginDate = DateUtil.beginOfYear(DateUtil.date()); + endDate = DateUtil.endOfYear(DateUtil.date()); + break; + case "10": + beginDate = DateUtil.beginOfYear(DateUtil.offsetMonth(DateUtil.date(), -12)); + endDate = DateUtil.endOfYear(DateUtil.offsetMonth(DateUtil.date(), -12)); + break; + default: + break; + } + } else if (StrUtil.isNotEmpty(startTime) && StrUtil.isNotEmpty(endTime)) { + Date start; + Date end; + if (startTime.length() == 6) { + start = DateUtil.parse(startTime, "yyyyMM"); + end = DateUtil.endOfMonth(DateUtil.parse(endTime, "yyyyMM")); + } else { + start = DateUtil.parse(startTime); + end = DateUtil.parse(endTime); + } + Integer startMonth = Integer.valueOf(DateUtil.format(start, "yyyyMM")); + int endMonth = Integer.parseInt(DateUtil.format(end, "yyyyMM")); + if (startMonth.equals(endMonth)) { + sqlDateFormat = "%Y%m%d"; + dateFormat = "yyyyMMdd"; + long diffDay = DateUtil.between(start, end, DateUnit.DAY); + cycleNum = (int) diffDay + 1; + } else { + sqlDateFormat = "%Y%m"; + dateFormat = "yyyyMM"; + int diffYear = Integer.parseInt(Integer.toString(endMonth).substring(0, 4)) - Integer.parseInt(startMonth.toString().substring(0, 4)); + int diffMonth = endMonth % 100 - startMonth % 100 + 1; + cycleNum = diffYear * 12 + diffMonth; + } + beginDate = start; + endDate = end; + } + Integer beginTime = Integer.valueOf(DateUtil.format(beginDate, dateFormat)); + Integer finalTime = Integer.valueOf(DateUtil.format(endDate, dateFormat)); + return new BiTimeEntity(sqlDateFormat, dateFormat, beginDate, endDate, cycleNum, beginTime, finalTime, new ArrayList<>()); + } + + @Data + @Accessors(chain = true) + public static class BiTimeEntity { + /** + * sql日期格式化 + */ + private String sqlDateFormat; + + /** + * 日期格式化 + */ + private String dateFormat; + + /** + * 开始时间 + */ + private Date beginDate; + + /** + * 结束时间 + */ + private Date endDate; + + /** + * 周期 + */ + private Integer cycleNum; + + /** + * 开始时间 字符串格式 如20200101 + */ + private Integer beginTime; + + /** + * 结束时间 字符串格式 如20200101 + */ + private Integer finalTime; + + /** + * user列表 + */ + private List userIds = new ArrayList<>(); + private Integer page; + private Integer limit; + + public BiTimeEntity(String sqlDateFormat, String dateFormat, Date beginDate, Date endDate, Integer cycleNum, Integer beginTime, Integer finalTime, List userIds) { + this.sqlDateFormat = sqlDateFormat; + this.dateFormat = dateFormat; + this.beginDate = beginDate; + this.endDate = endDate; + this.cycleNum = cycleNum; + this.beginTime = beginTime; + this.finalTime = finalTime; + this.userIds = userIds; + } + + public BiTimeEntity() { + } + + } +} diff --git a/yudao-module-crm/yudao-module-bi-biz/src/main/resources/mapper/rank/BiRankingMapper.xml b/yudao-module-crm/yudao-module-bi-biz/src/main/resources/mapper/rank/BiRankingMapper.xml new file mode 100644 index 000000000..9bee4fbaf --- /dev/null +++ b/yudao-module-crm/yudao-module-bi-biz/src/main/resources/mapper/rank/BiRankingMapper.xml @@ -0,0 +1,42 @@ + + + + + + + + diff --git a/yudao-module-system/yudao-module-system-api/src/main/java/cn/iocoder/yudao/module/system/api/dept/DeptApi.java b/yudao-module-system/yudao-module-system-api/src/main/java/cn/iocoder/yudao/module/system/api/dept/DeptApi.java index f8059fbb7..bdc3ba59b 100644 --- a/yudao-module-system/yudao-module-system-api/src/main/java/cn/iocoder/yudao/module/system/api/dept/DeptApi.java +++ b/yudao-module-system/yudao-module-system-api/src/main/java/cn/iocoder/yudao/module/system/api/dept/DeptApi.java @@ -50,4 +50,12 @@ public interface DeptApi { return CollectionUtils.convertMap(list, DeptRespDTO::getId); } + /** + * 获得指定部门的所有子部门 + * + * @param id 部门编号 + * @return 子部门列表 + */ + List getChildDeptList(Long id); + } diff --git a/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/api/dept/DeptApiImpl.java b/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/api/dept/DeptApiImpl.java index 76685cf31..00d79ceaa 100644 --- a/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/api/dept/DeptApiImpl.java +++ b/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/api/dept/DeptApiImpl.java @@ -4,6 +4,7 @@ import cn.iocoder.yudao.framework.common.util.object.BeanUtils; import cn.iocoder.yudao.module.system.api.dept.dto.DeptRespDTO; import cn.iocoder.yudao.module.system.dal.dataobject.dept.DeptDO; import cn.iocoder.yudao.module.system.service.dept.DeptService; +import org.springframework.context.annotation.Lazy; import org.springframework.stereotype.Service; import jakarta.annotation.Resource; @@ -19,6 +20,7 @@ import java.util.List; public class DeptApiImpl implements DeptApi { @Resource + @Lazy // 延迟加载,解决相互依赖的问题 private DeptService deptService; @Override @@ -38,4 +40,11 @@ public class DeptApiImpl implements DeptApi { deptService.validateDeptList(ids); } + @Override + public List getChildDeptList(Long id) { + List childDeptList = deptService.getChildDeptList(id); + return BeanUtils.toBean(childDeptList, DeptRespDTO.class); + } + + } diff --git a/yudao-server/pom.xml b/yudao-server/pom.xml index 85b284c3c..3caebe16c 100644 --- a/yudao-server/pom.xml +++ b/yudao-server/pom.xml @@ -97,6 +97,11 @@ yudao-module-crm-biz ${revision} + + cn.iocoder.boot + yudao-module-bi-biz + ${revision} + From 4418a7bebce6497e63c19d1626f4b772f4025e7a Mon Sep 17 00:00:00 2001 From: puhui999 Date: Sun, 28 Jan 2024 20:15:11 +0800 Subject: [PATCH 050/119] =?UTF-8?q?CRM-=E5=90=88=E5=90=8C=EF=BC=9A?= =?UTF-8?q?=E5=AE=8C=E5=96=84=E6=96=B0=E5=A2=9E=E5=90=88=E5=90=8C=E6=8F=92?= =?UTF-8?q?=E5=85=A5=E5=85=B3=E8=81=94=E7=9A=84=E5=95=86=E5=93=81?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../module/crm/enums/ErrorCodeConstants.java | 1 + .../contract/vo/CrmContractSaveReqVO.java | 5 +- .../contract/CrmContractServiceImpl.java | 93 ++++++++++++++++++- .../listener/CrmContractResultListener.java | 1 + 4 files changed, 94 insertions(+), 6 deletions(-) diff --git a/yudao-module-crm/yudao-module-crm-api/src/main/java/cn/iocoder/yudao/module/crm/enums/ErrorCodeConstants.java b/yudao-module-crm/yudao-module-crm-api/src/main/java/cn/iocoder/yudao/module/crm/enums/ErrorCodeConstants.java index 9db937aa6..b12990dd3 100644 --- a/yudao-module-crm/yudao-module-crm-api/src/main/java/cn/iocoder/yudao/module/crm/enums/ErrorCodeConstants.java +++ b/yudao-module-crm/yudao-module-crm-api/src/main/java/cn/iocoder/yudao/module/crm/enums/ErrorCodeConstants.java @@ -11,6 +11,7 @@ public interface ErrorCodeConstants { // ========== 合同管理 1-020-000-000 ========== ErrorCode CONTRACT_NOT_EXISTS = new ErrorCode(1_020_000_000, "合同不存在"); + ErrorCode CONTRACT_UPDATE_FAIL_EDITING_PROHIBITED = new ErrorCode(1_020_000_001, "更新合同失败,原因:禁止编辑"); // ========== 线索管理 1-020-001-000 ========== ErrorCode CLUE_NOT_EXISTS = new ErrorCode(1_020_001_000, "线索不存在"); diff --git a/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/controller/admin/contract/vo/CrmContractSaveReqVO.java b/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/controller/admin/contract/vo/CrmContractSaveReqVO.java index 607aa08f5..ef90f2f2f 100644 --- a/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/controller/admin/contract/vo/CrmContractSaveReqVO.java +++ b/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/controller/admin/contract/vo/CrmContractSaveReqVO.java @@ -89,6 +89,9 @@ public class CrmContractSaveReqVO { @DiffLogField(name = "备注") private String remark; + @Schema(description = "审批状态", example = "1") + private Integer auditStatus; + @Schema(description = "产品列表") private List productItems; @@ -104,7 +107,7 @@ public class CrmContractSaveReqVO { @Schema(description = "产品数量", requiredMode = Schema.RequiredMode.REQUIRED, example = "8911") @NotNull(message = "产品数量不能为空") - private Long count; + private Integer count; @Schema(description = "产品折扣") private Integer discountPercent; diff --git a/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/service/contract/CrmContractServiceImpl.java b/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/service/contract/CrmContractServiceImpl.java index 8a1ad339e..59274b522 100644 --- a/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/service/contract/CrmContractServiceImpl.java +++ b/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/service/contract/CrmContractServiceImpl.java @@ -2,7 +2,9 @@ package cn.iocoder.yudao.module.crm.service.contract; import cn.hutool.core.collection.CollUtil; import cn.hutool.core.collection.ListUtil; +import cn.hutool.core.util.ObjUtil; 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.bpm.api.task.BpmProcessInstanceApi; import cn.iocoder.yudao.module.bpm.api.task.dto.BpmProcessInstanceCreateReqDTO; @@ -10,16 +12,23 @@ import cn.iocoder.yudao.module.crm.controller.admin.contract.vo.CrmContractPageR import cn.iocoder.yudao.module.crm.controller.admin.contract.vo.CrmContractSaveReqVO; import cn.iocoder.yudao.module.crm.controller.admin.contract.vo.CrmContractTransferReqVO; import cn.iocoder.yudao.module.crm.convert.contract.CrmContractConvert; +import cn.iocoder.yudao.module.crm.dal.dataobject.business.CrmBusinessProductDO; import cn.iocoder.yudao.module.crm.dal.dataobject.contract.CrmContractDO; +import cn.iocoder.yudao.module.crm.dal.dataobject.product.CrmProductDO; import cn.iocoder.yudao.module.crm.dal.mysql.contract.CrmContractMapper; import cn.iocoder.yudao.module.crm.enums.common.CrmAuditStatusEnum; import cn.iocoder.yudao.module.crm.enums.common.CrmBizTypeEnum; import cn.iocoder.yudao.module.crm.enums.permission.CrmPermissionLevelEnum; import cn.iocoder.yudao.module.crm.framework.permission.core.annotations.CrmPermission; import cn.iocoder.yudao.module.crm.service.business.CrmBusinessProductService; +import cn.iocoder.yudao.module.crm.service.business.CrmBusinessService; +import cn.iocoder.yudao.module.crm.service.contact.CrmContactService; +import cn.iocoder.yudao.module.crm.service.customer.CrmCustomerService; import cn.iocoder.yudao.module.crm.service.followup.bo.CrmUpdateFollowUpReqBO; import cn.iocoder.yudao.module.crm.service.permission.CrmPermissionService; import cn.iocoder.yudao.module.crm.service.permission.bo.CrmPermissionCreateReqBO; +import cn.iocoder.yudao.module.crm.service.product.CrmProductService; +import cn.iocoder.yudao.module.system.api.user.AdminUserApi; import com.mzt.logapi.context.LogRecordContext; import com.mzt.logapi.service.impl.DiffParseFunction; import com.mzt.logapi.starter.annotation.LogRecord; @@ -30,10 +39,14 @@ import org.springframework.validation.annotation.Validated; import java.util.Collection; import java.util.List; +import java.util.Map; +import java.util.Set; import static cn.iocoder.yudao.framework.common.exception.util.ServiceExceptionUtil.exception; -import static cn.iocoder.yudao.module.crm.enums.ErrorCodeConstants.CONTRACT_NOT_EXISTS; +import static cn.iocoder.yudao.framework.common.util.collection.CollectionUtils.*; +import static cn.iocoder.yudao.module.crm.enums.ErrorCodeConstants.*; import static cn.iocoder.yudao.module.crm.enums.LogRecordConstants.*; +import static cn.iocoder.yudao.module.system.enums.ErrorCodeConstants.USER_NOT_EXISTS; /** * CRM 合同 Service 实现类 @@ -53,16 +66,25 @@ public class CrmContractServiceImpl implements CrmContractService { private CrmPermissionService crmPermissionService; @Resource private CrmBusinessProductService businessProductService; - + @Resource + private CrmProductService productService; @Resource private BpmProcessInstanceApi bpmProcessInstanceApi; + @Resource + private CrmCustomerService customerService; + @Resource + private CrmContactService contactService; + @Resource + private CrmBusinessService businessService; + @Resource + private AdminUserApi adminUserApi; @Override @Transactional(rollbackFor = Exception.class) @LogRecord(type = CRM_CONTRACT_TYPE, subType = CRM_CONTRACT_CREATE_SUB_TYPE, bizNo = "{{#contract.id}}", success = CRM_CONTRACT_CREATE_SUCCESS) public Long createContract(CrmContractSaveReqVO createReqVO, Long userId) { - // TODO @合同待定:插入合同商品;需要搞个 BusinessProductDO + validateRelationDataExists(createReqVO); // 插入合同 CrmContractDO contract = BeanUtils.toBean(createReqVO, CrmContractDO.class).setId(null); contractMapper.insert(contract); @@ -71,6 +93,10 @@ public class CrmContractServiceImpl implements CrmContractService { crmPermissionService.createPermission(new CrmPermissionCreateReqBO().setUserId(userId) .setBizType(CrmBizTypeEnum.CRM_CONTRACT.getType()).setBizId(contract.getId()) .setLevel(CrmPermissionLevelEnum.OWNER.getLevel())); + + // 插入商机关联商品 + List businessProduct = convertBusinessProductList(createReqVO); + businessProductService.insertBatch(businessProduct); // 4. 记录操作日志上下文 LogRecordContext.putVariable("contract", contract); return contract.getId(); @@ -83,12 +109,21 @@ public class CrmContractServiceImpl implements CrmContractService { @CrmPermission(bizType = CrmBizTypeEnum.CRM_CONTRACT, bizId = "#updateReqVO.id", level = CrmPermissionLevelEnum.WRITE) public void updateContract(CrmContractSaveReqVO updateReqVO) { // TODO @合同待定:只有草稿、审批中,可以编辑; + if (ObjUtil.notEqual(updateReqVO.getAuditStatus(), CrmAuditStatusEnum.DRAFT.getStatus()) || + ObjUtil.notEqual(updateReqVO.getAuditStatus(), CrmAuditStatusEnum.PROCESS.getStatus())) { + throw exception(CONTRACT_UPDATE_FAIL_EDITING_PROHIBITED); + } + validateRelationDataExists(updateReqVO); // 校验存在 CrmContractDO oldContract = validateContractExists(updateReqVO.getId()); // 更新合同 CrmContractDO updateObj = BeanUtils.toBean(updateReqVO, CrmContractDO.class); contractMapper.updateById(updateObj); - // TODO @合同待定:插入合同商品;需要搞个 BusinessProductDO + + // TODO puhui999: @芋艿:合同变更关联的商机后商品怎么处理? + //List businessProduct = convertBusinessProductList(updateReqVO); + //businessProductService.selectListByBusinessId() + //diffList() // 3. 记录操作日志上下文 LogRecordContext.putVariable(DiffParseFunction.OLD_OBJECT, BeanUtils.toBean(oldContract, CrmContractSaveReqVO.class)); @@ -97,8 +132,55 @@ public class CrmContractServiceImpl implements CrmContractService { // TODO @合同待定:缺一个取消合同的接口;只有草稿、审批中可以取消;CrmAuditStatusEnum - // TODO @合同待定:缺一个发起审批的接口;只有草稿可以发起审批;CrmAuditStatusEnum + private List convertBusinessProductList(CrmContractSaveReqVO reqVO) { + // 校验商品存在 + Set productIds = convertSet(reqVO.getProductItems(), CrmContractSaveReqVO.CrmContractProductItem::getId); + List productList = productService.getProductList(productIds); + if (CollUtil.isEmpty(productIds) || productList.size() != productIds.size()) { + throw exception(PRODUCT_NOT_EXISTS); + } + Map productMap = convertMap(productList, CrmProductDO::getId); + return convertList(reqVO.getProductItems(), productItem -> { + CrmBusinessProductDO businessProduct = BeanUtils.toBean(productMap.get(productItem.getId()), CrmBusinessProductDO.class); + businessProduct.setId(null).setBusinessId(reqVO.getBusinessId()).setProductId(productItem.getId()) + .setCount(productItem.getCount()).setDiscountPercent(productItem.getDiscountPercent()).setTotalPrice(calculator(businessProduct)); + return businessProduct; + }); + } + /** + * 计算商品总价 + * + * @param businessProduct 关联商品 + * @return 商品总价 + */ + private Integer calculator(CrmBusinessProductDO businessProduct) { + int price = businessProduct.getPrice() * businessProduct.getCount(); + if (businessProduct.getDiscountPercent() == null) { + return price; + } + return MoneyUtils.calculateRatePriceFloor(price, (double) (businessProduct.getDiscountPercent() / 100)); + } + + /** + * 校验关联数据是否存在 + * + * @param reqVO 请求 + */ + private void validateRelationDataExists(CrmContractSaveReqVO reqVO) { + // 1. 校验客户 + if (reqVO.getCustomerId() != null && customerService.getCustomer(reqVO.getCustomerId()) == null) { + throw exception(CUSTOMER_NOT_EXISTS); + } + // 2. 校验负责人 + if (reqVO.getOwnerUserId() != null && adminUserApi.getUser(reqVO.getOwnerUserId()) == null) { + throw exception(USER_NOT_EXISTS); + } + // 4. 如果有关联商机,则需要校验存在 + if (reqVO.getBusinessId() != null && businessService.getBusiness(reqVO.getBusinessId()) == null) { + throw exception(BUSINESS_NOT_EXISTS); + } + } @Override @Transactional(rollbackFor = Exception.class) @@ -151,6 +233,7 @@ public class CrmContractServiceImpl implements CrmContractService { } @Override + @Transactional(rollbackFor = Exception.class) public void handleApprove(Long id, Long userId) { // 创建合同审批流程实例 String processInstanceId = bpmProcessInstanceApi.createProcessInstance(userId, new BpmProcessInstanceCreateReqDTO() diff --git a/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/service/contract/listener/CrmContractResultListener.java b/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/service/contract/listener/CrmContractResultListener.java index 078bbbd6a..e393c2664 100644 --- a/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/service/contract/listener/CrmContractResultListener.java +++ b/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/service/contract/listener/CrmContractResultListener.java @@ -1,4 +1,5 @@ package cn.iocoder.yudao.module.crm.service.contract.listener; public class CrmContractResultListener { + // TODO puhui999: @芋艿: 艿艿写一下这个,没研究明白哈哈 } From bfed37af6f65f691c6a2e6cca36284c29d792978 Mon Sep 17 00:00:00 2001 From: anhaohao <1036606149@qq.com> Date: Sun, 28 Jan 2024 21:47:52 +0800 Subject: [PATCH 051/119] =?UTF-8?q?=E4=BF=AE=E6=94=B9=EF=BC=9ACRM=20?= =?UTF-8?q?=E5=95=86=E4=B8=9A=E6=99=BA=E8=83=BD=EF=BC=8C=E5=9B=9E=E6=AC=BE?= =?UTF-8?q?=E9=87=91=E9=A2=9D=E6=8E=92=E8=A1=8C=E6=A6=9C=E6=97=B6=E9=97=B4?= =?UTF-8?q?=E5=AD=97=E6=AE=B5=20bug?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../src/main/resources/mapper/rank/BiRankingMapper.xml | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/yudao-module-crm/yudao-module-bi-biz/src/main/resources/mapper/rank/BiRankingMapper.xml b/yudao-module-crm/yudao-module-bi-biz/src/main/resources/mapper/rank/BiRankingMapper.xml index 9bee4fbaf..ed12ded42 100644 --- a/yudao-module-crm/yudao-module-bi-biz/src/main/resources/mapper/rank/BiRankingMapper.xml +++ b/yudao-module-crm/yudao-module-bi-biz/src/main/resources/mapper/rank/BiRankingMapper.xml @@ -35,7 +35,7 @@ #{item} - AND DATE_FORMAT(t.order_date,'${sqlDateFormat}') between #{beginTime} and #{finalTime} + AND DATE_FORMAT(t.return_time,'${sqlDateFormat}') between #{beginTime} and #{finalTime} GROUP BY t.owner_user_id ORDER BY price DESC From 52a68e18388a4c6f5395d500b1a149eb26e2de6a Mon Sep 17 00:00:00 2001 From: YunaiV Date: Tue, 30 Jan 2024 09:24:42 +0800 Subject: [PATCH 052/119] =?UTF-8?q?=F0=9F=93=96=20CRM=EF=BC=9Acode=20revie?= =?UTF-8?q?w=20=E5=90=88=E5=90=8C=E9=87=91=E9=A2=9D=E6=8E=92=E8=A1=8C?= =?UTF-8?q?=E6=A6=9C=E3=80=81=E5=9B=9E=E6=AC=BE=E9=87=91=E9=A2=9D=E6=8E=92?= =?UTF-8?q?=E8=A1=8C=E6=A6=9C?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../admin/ranking/BiRankingController.http | 3 +- .../admin/ranking/BiRankingController.java | 2 + .../ranking/vo/BiContractRanKingRespVO.java | 4 +- .../controller/admin/ranking/vo/BiParams.java | 5 +- .../admin/ranking/vo/BiRankReqVO.java | 2 + .../vo/BiReceivablesRanKingRespVO.java | 2 + .../iocoder/yudao/module/bi/package-info.java | 3 + .../bi/service/ranking/BiRankingService.java | 2 +- .../yudao/module/bi/util/BiTimeUtil.java | 1 + .../resources/mapper/rank/BiRankingMapper.xml | 3 + .../sale/vo/order/ErpSaleOrderSaveReqVO.java | 60 ++++++++++++++++++- .../service/sale/ErpSaleOrderServiceImpl.java | 26 ++++---- .../module/system/api/dept/DeptApiImpl.java | 1 - 13 files changed, 92 insertions(+), 22 deletions(-) diff --git a/yudao-module-crm/yudao-module-bi-biz/src/main/java/cn/iocoder/yudao/module/bi/controller/admin/ranking/BiRankingController.http b/yudao-module-crm/yudao-module-bi-biz/src/main/java/cn/iocoder/yudao/module/bi/controller/admin/ranking/BiRankingController.http index 50ab7ec2b..e56a1fcfe 100644 --- a/yudao-module-crm/yudao-module-bi-biz/src/main/java/cn/iocoder/yudao/module/bi/controller/admin/ranking/BiRankingController.http +++ b/yudao-module-crm/yudao-module-bi-biz/src/main/java/cn/iocoder/yudao/module/bi/controller/admin/ranking/BiRankingController.http @@ -3,8 +3,7 @@ GET {{baseUrl}}/bi/rank/contract-ranKing Authorization: Bearer {{token}} tenant-id: {{adminTenentId}} - ### 回款金额排行榜 GET {{baseUrl}}/bi/rank/receivables-ranKing Authorization: Bearer {{token}} -tenant-id: {{adminTenentId}} +tenant-id: {{adminTenentId}} \ No newline at end of file diff --git a/yudao-module-crm/yudao-module-bi-biz/src/main/java/cn/iocoder/yudao/module/bi/controller/admin/ranking/BiRankingController.java b/yudao-module-crm/yudao-module-bi-biz/src/main/java/cn/iocoder/yudao/module/bi/controller/admin/ranking/BiRankingController.java index 2d81ae80d..131d43892 100644 --- a/yudao-module-crm/yudao-module-bi-biz/src/main/java/cn/iocoder/yudao/module/bi/controller/admin/ranking/BiRankingController.java +++ b/yudao-module-crm/yudao-module-bi-biz/src/main/java/cn/iocoder/yudao/module/bi/controller/admin/ranking/BiRankingController.java @@ -19,6 +19,7 @@ import java.util.List; import static cn.iocoder.yudao.framework.common.pojo.CommonResult.success; +// TODO @anhaohao:写了 swagger 注解,不写注释哈 /** * @author anhaohao */ @@ -50,4 +51,5 @@ public class BiRankingController { public CommonResult> receivablesRanKing(BiRankReqVO biRankReqVO) { return success(biRankingService.receivablesRanKing(biRankReqVO)); } + } diff --git a/yudao-module-crm/yudao-module-bi-biz/src/main/java/cn/iocoder/yudao/module/bi/controller/admin/ranking/vo/BiContractRanKingRespVO.java b/yudao-module-crm/yudao-module-bi-biz/src/main/java/cn/iocoder/yudao/module/bi/controller/admin/ranking/vo/BiContractRanKingRespVO.java index 777996b90..487ebe031 100644 --- a/yudao-module-crm/yudao-module-bi-biz/src/main/java/cn/iocoder/yudao/module/bi/controller/admin/ranking/vo/BiContractRanKingRespVO.java +++ b/yudao-module-crm/yudao-module-bi-biz/src/main/java/cn/iocoder/yudao/module/bi/controller/admin/ranking/vo/BiContractRanKingRespVO.java @@ -3,6 +3,7 @@ package cn.iocoder.yudao.module.bi.controller.admin.ranking.vo; import io.swagger.v3.oas.annotations.media.Schema; import lombok.Data; +// TODO @anhaohao:VO 类有 swagger 注解,不写注释哈 /** * 管理后台 - BI 排行榜 Response VO * @@ -12,13 +13,14 @@ import lombok.Data; @Data public class BiContractRanKingRespVO { + // TODO @anhaohao:如果一定返回的字段,需要加 requiredMode = Schema.RequiredMode.REQUIRED, 哈 @Schema(description = "金额", example = "1") private Integer price; @Schema(description = "姓名", example = "1") private String nickname; - @Schema(description = "部门名称", example = "1") private String deptName; + } diff --git a/yudao-module-crm/yudao-module-bi-biz/src/main/java/cn/iocoder/yudao/module/bi/controller/admin/ranking/vo/BiParams.java b/yudao-module-crm/yudao-module-bi-biz/src/main/java/cn/iocoder/yudao/module/bi/controller/admin/ranking/vo/BiParams.java index 5cce4c6cb..7cbf469c8 100644 --- a/yudao-module-crm/yudao-module-bi-biz/src/main/java/cn/iocoder/yudao/module/bi/controller/admin/ranking/vo/BiParams.java +++ b/yudao-module-crm/yudao-module-bi-biz/src/main/java/cn/iocoder/yudao/module/bi/controller/admin/ranking/vo/BiParams.java @@ -7,6 +7,7 @@ import lombok.EqualsAndHashCode; import java.util.List; +// TODO @anhaohao:这个类的命名,还是保持和其它一致使用 ReqVO 结尾;例如说,CrmStatisticsCommonParamReqVO /** * @author anhaohao * bi参数 @@ -25,17 +26,19 @@ public class BiParams extends PageParam { @Schema(description = "用户IDs") private List userIds; + // TODO @anhaohao:这个字段,可以融合到 startTime、endTime 里去,交给前端计算哈; @Schema(description = "类型") private String type; + // TODO @anhaohao:还是使用 LocalDateTime @Schema(description = "开始时间") private String startTime; @Schema(description = "结束时间") private String endTime; + // TODO @anhaohao:这个字段,是不是直接只基于 deptId 和 userId 来判断即可哈? @Schema(description = "0 部门 1员工") private Integer isUser = 1; - } diff --git a/yudao-module-crm/yudao-module-bi-biz/src/main/java/cn/iocoder/yudao/module/bi/controller/admin/ranking/vo/BiRankReqVO.java b/yudao-module-crm/yudao-module-bi-biz/src/main/java/cn/iocoder/yudao/module/bi/controller/admin/ranking/vo/BiRankReqVO.java index 1569ba88d..bca6c8c10 100644 --- a/yudao-module-crm/yudao-module-bi-biz/src/main/java/cn/iocoder/yudao/module/bi/controller/admin/ranking/vo/BiRankReqVO.java +++ b/yudao-module-crm/yudao-module-bi-biz/src/main/java/cn/iocoder/yudao/module/bi/controller/admin/ranking/vo/BiRankReqVO.java @@ -15,6 +15,8 @@ public class BiRankReqVO { @Schema(description = "部门id", requiredMode = Schema.RequiredMode.REQUIRED, example = "1") private Long deptId; + // TODO @anhaohao:这个字段,参考 BiParams 的 type 建议 @Schema(description = "分析类型(1.今天 2.昨天 3.本周 4.上周 5.本月 6.上月 7.本季度 8.上季度 9.本年 10 上年)", requiredMode = Schema.RequiredMode.REQUIRED, example = "1") private String type; + } diff --git a/yudao-module-crm/yudao-module-bi-biz/src/main/java/cn/iocoder/yudao/module/bi/controller/admin/ranking/vo/BiReceivablesRanKingRespVO.java b/yudao-module-crm/yudao-module-bi-biz/src/main/java/cn/iocoder/yudao/module/bi/controller/admin/ranking/vo/BiReceivablesRanKingRespVO.java index 32b49231f..0b395acde 100644 --- a/yudao-module-crm/yudao-module-bi-biz/src/main/java/cn/iocoder/yudao/module/bi/controller/admin/ranking/vo/BiReceivablesRanKingRespVO.java +++ b/yudao-module-crm/yudao-module-bi-biz/src/main/java/cn/iocoder/yudao/module/bi/controller/admin/ranking/vo/BiReceivablesRanKingRespVO.java @@ -3,6 +3,7 @@ package cn.iocoder.yudao.module.bi.controller.admin.ranking.vo; import io.swagger.v3.oas.annotations.media.Schema; import lombok.Data; +// TODO @anhaohao:参考 BiContractRanKingRespVO 的建议 /** * 管理后台 - BI 排行榜 Response VO * @@ -20,4 +21,5 @@ public class BiReceivablesRanKingRespVO { @Schema(description = "部门名称", example = "研发部") private String deptName; + } diff --git a/yudao-module-crm/yudao-module-bi-biz/src/main/java/cn/iocoder/yudao/module/bi/package-info.java b/yudao-module-crm/yudao-module-bi-biz/src/main/java/cn/iocoder/yudao/module/bi/package-info.java index b45b8458d..d412dd6fd 100644 --- a/yudao-module-crm/yudao-module-bi-biz/src/main/java/cn/iocoder/yudao/module/bi/package-info.java +++ b/yudao-module-crm/yudao-module-bi-biz/src/main/java/cn/iocoder/yudao/module/bi/package-info.java @@ -3,5 +3,8 @@ * 例如说:报表、图表、数据分析等等 *

* 1. Controller URL:以 /bi/ 开头,避免和其它 Module 冲突 + * + * TODO @anhaohao:mall 当时独立拆分一个 statistics 模块的原因,是因为 mall 拆分了多个模块,没有模块适合承接统计的能力,所以独立了。 + * TODO crm 因为没有拆分,所以可以直接放在 crm 模块下面;这样,我们可以在 controller/admin 和 service 下,新建一个 bi 包,专门放置统计的代码。 */ package cn.iocoder.yudao.module.bi; \ No newline at end of file diff --git a/yudao-module-crm/yudao-module-bi-biz/src/main/java/cn/iocoder/yudao/module/bi/service/ranking/BiRankingService.java b/yudao-module-crm/yudao-module-bi-biz/src/main/java/cn/iocoder/yudao/module/bi/service/ranking/BiRankingService.java index 98f1346de..121029b19 100644 --- a/yudao-module-crm/yudao-module-bi-biz/src/main/java/cn/iocoder/yudao/module/bi/service/ranking/BiRankingService.java +++ b/yudao-module-crm/yudao-module-bi-biz/src/main/java/cn/iocoder/yudao/module/bi/service/ranking/BiRankingService.java @@ -11,7 +11,7 @@ import java.util.List; * * @author anhaohao */ -public interface BiRankingService { +public interface BiRankingService { // TODO @anhaohao:第一个方法,和类要有一个空行 /** * 合同金额排行榜 * diff --git a/yudao-module-crm/yudao-module-bi-biz/src/main/java/cn/iocoder/yudao/module/bi/util/BiTimeUtil.java b/yudao-module-crm/yudao-module-bi-biz/src/main/java/cn/iocoder/yudao/module/bi/util/BiTimeUtil.java index b1b68aea2..123122328 100644 --- a/yudao-module-crm/yudao-module-bi-biz/src/main/java/cn/iocoder/yudao/module/bi/util/BiTimeUtil.java +++ b/yudao-module-crm/yudao-module-bi-biz/src/main/java/cn/iocoder/yudao/module/bi/util/BiTimeUtil.java @@ -28,6 +28,7 @@ public class BiTimeUtil { // 解析时间 BiTimeEntity biTimeEntity = analyzeTime(biParams); // 解析权限 + // TODO @anhaohao:涉及到数据的读取,不放在 Util 里,还是搞会到 Service 哈; biTimeEntity.setUserIds(analyzeAuth(biParams)); return biTimeEntity; } diff --git a/yudao-module-crm/yudao-module-bi-biz/src/main/resources/mapper/rank/BiRankingMapper.xml b/yudao-module-crm/yudao-module-bi-biz/src/main/resources/mapper/rank/BiRankingMapper.xml index ed12ded42..a41dc5d7f 100644 --- a/yudao-module-crm/yudao-module-bi-biz/src/main/resources/mapper/rank/BiRankingMapper.xml +++ b/yudao-module-crm/yudao-module-bi-biz/src/main/resources/mapper/rank/BiRankingMapper.xml @@ -7,6 +7,7 @@ resultType="cn.iocoder.yudao.module.bi.controller.admin.ranking.vo.BiContractRanKingRespVO"> SELECT IFNULL(SUM(t.price), 0) AS price, su.nickname, t.owner_user_id, dept.name AS deptName FROM crm_contract t + LEFT JOIN system_users AS su ON su.id = t.owner_user_id LEFT JOIN system_dept AS dept ON dept.id = su.dept_id WHERE t.deleted = 0 @@ -17,10 +18,12 @@ #{item} + AND DATE_FORMAT(t.order_date,'${sqlDateFormat}') between #{beginTime} and #{finalTime} GROUP BY t.owner_user_id ORDER BY price DESC + - SELECT IFNULL(SUM(t.price), 0) AS price, su.nickname, t.owner_user_id, dept.name AS deptName - FROM crm_contract t - - LEFT JOIN system_users AS su ON su.id = t.owner_user_id - LEFT JOIN system_dept AS dept ON dept.id = su.dept_id - WHERE t.deleted = 0 - AND t.audit_status = 20 - - and t.owner_user_id in - - #{item} - - - - AND DATE_FORMAT(t.order_date,'${sqlDateFormat}') between #{beginTime} and #{finalTime} - GROUP BY t.owner_user_id - ORDER BY price DESC - - - - diff --git a/yudao-module-crm/yudao-module-bi-biz/src/main/java/cn/iocoder/yudao/module/bi/controller/admin/ranking/BiRankingController.http b/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/controller/admin/bi/BiRankingController.http similarity index 63% rename from yudao-module-crm/yudao-module-bi-biz/src/main/java/cn/iocoder/yudao/module/bi/controller/admin/ranking/BiRankingController.http rename to yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/controller/admin/bi/BiRankingController.http index e56a1fcfe..23acfee92 100644 --- a/yudao-module-crm/yudao-module-bi-biz/src/main/java/cn/iocoder/yudao/module/bi/controller/admin/ranking/BiRankingController.http +++ b/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/controller/admin/bi/BiRankingController.http @@ -1,9 +1,9 @@ ### 合同金额排行榜 -GET {{baseUrl}}/bi/rank/contract-ranKing +GET {{baseUrl}}/crm/bi-ranking/contract-ranKing Authorization: Bearer {{token}} tenant-id: {{adminTenentId}} ### 回款金额排行榜 -GET {{baseUrl}}/bi/rank/receivables-ranKing +GET {{baseUrl}}/crm/bi-ranking/receivables-ranKing Authorization: Bearer {{token}} tenant-id: {{adminTenentId}} \ No newline at end of file diff --git a/yudao-module-crm/yudao-module-bi-biz/src/main/java/cn/iocoder/yudao/module/bi/controller/admin/ranking/BiRankingController.java b/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/controller/admin/bi/BiRankingController.java similarity index 60% rename from yudao-module-crm/yudao-module-bi-biz/src/main/java/cn/iocoder/yudao/module/bi/controller/admin/ranking/BiRankingController.java rename to yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/controller/admin/bi/BiRankingController.java index 131d43892..2af4f23fa 100644 --- a/yudao-module-crm/yudao-module-bi-biz/src/main/java/cn/iocoder/yudao/module/bi/controller/admin/ranking/BiRankingController.java +++ b/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/controller/admin/bi/BiRankingController.java @@ -1,11 +1,11 @@ -package cn.iocoder.yudao.module.bi.controller.admin.ranking; +package cn.iocoder.yudao.module.crm.controller.admin.bi; + import cn.iocoder.yudao.framework.common.pojo.CommonResult; -import cn.iocoder.yudao.module.bi.controller.admin.ranking.vo.BiContractRanKingRespVO; -import cn.iocoder.yudao.module.bi.controller.admin.ranking.vo.BiRankReqVO; -import cn.iocoder.yudao.module.bi.controller.admin.ranking.vo.BiReceivablesRanKingRespVO; -import cn.iocoder.yudao.module.bi.service.ranking.BiRankingService; +import cn.iocoder.yudao.module.crm.controller.admin.bi.vo.BiRanKingRespVO; +import cn.iocoder.yudao.module.crm.controller.admin.bi.vo.BiRankingReqVO; +import cn.iocoder.yudao.module.crm.service.bi.BiRankingService; import io.swagger.v3.oas.annotations.Operation; import io.swagger.v3.oas.annotations.tags.Tag; import jakarta.annotation.Resource; @@ -19,13 +19,10 @@ import java.util.List; import static cn.iocoder.yudao.framework.common.pojo.CommonResult.success; -// TODO @anhaohao:写了 swagger 注解,不写注释哈 -/** - * @author anhaohao - */ + @Tag(name = "管理后台 - 排行榜") @RestController -@RequestMapping("/bi/ranking") +@RequestMapping("/crm/bi-ranking") @Validated public class BiRankingController { @@ -38,8 +35,8 @@ public class BiRankingController { @GetMapping("/contract-ranking") @Operation(summary = "合同金额排行榜") @PreAuthorize("@ss.hasPermission('bi:ranking:query')") - public CommonResult> contractAmountRanking(BiRankReqVO biRankReqVO) { - return success(biRankingService.contractRanKing(biRankReqVO)); + public CommonResult> contractAmountRanking(BiRankingReqVO biRankingReqVO) { + return success(biRankingService.contractRanKing(biRankingReqVO)); } /** @@ -48,8 +45,8 @@ public class BiRankingController { @GetMapping("/receivables-ranking") @Operation(summary = "回款金额排行榜") @PreAuthorize("@ss.hasPermission('bi:ranking:query')") - public CommonResult> receivablesRanKing(BiRankReqVO biRankReqVO) { - return success(biRankingService.receivablesRanKing(biRankReqVO)); + public CommonResult> receivablesRanKing(BiRankingReqVO biRankingReqVO) { + return success(biRankingService.receivablesRanKing(biRankingReqVO)); } } diff --git a/yudao-module-crm/yudao-module-bi-biz/src/main/java/cn/iocoder/yudao/module/bi/controller/admin/ranking/vo/BiParams.java b/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/controller/admin/bi/vo/BiParams.java similarity index 73% rename from yudao-module-crm/yudao-module-bi-biz/src/main/java/cn/iocoder/yudao/module/bi/controller/admin/ranking/vo/BiParams.java rename to yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/controller/admin/bi/vo/BiParams.java index 7cbf469c8..0dee1c092 100644 --- a/yudao-module-crm/yudao-module-bi-biz/src/main/java/cn/iocoder/yudao/module/bi/controller/admin/ranking/vo/BiParams.java +++ b/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/controller/admin/bi/vo/BiParams.java @@ -1,12 +1,10 @@ -package cn.iocoder.yudao.module.bi.controller.admin.ranking.vo; +package cn.iocoder.yudao.module.crm.controller.admin.bi.vo; import cn.iocoder.yudao.framework.common.pojo.PageParam; import io.swagger.v3.oas.annotations.media.Schema; import lombok.Data; import lombok.EqualsAndHashCode; -import java.util.List; - // TODO @anhaohao:这个类的命名,还是保持和其它一致使用 ReqVO 结尾;例如说,CrmStatisticsCommonParamReqVO /** * @author anhaohao @@ -23,9 +21,6 @@ public class BiParams extends PageParam { @Schema(description = "用户ID") private Long userId; - @Schema(description = "用户IDs") - private List userIds; - // TODO @anhaohao:这个字段,可以融合到 startTime、endTime 里去,交给前端计算哈; @Schema(description = "类型") private String type; @@ -37,8 +32,4 @@ public class BiParams extends PageParam { @Schema(description = "结束时间") private String endTime; - // TODO @anhaohao:这个字段,是不是直接只基于 deptId 和 userId 来判断即可哈? - @Schema(description = "0 部门 1员工") - private Integer isUser = 1; - } diff --git a/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/controller/admin/bi/vo/BiRanKingRespVO.java b/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/controller/admin/bi/vo/BiRanKingRespVO.java new file mode 100644 index 000000000..8aef25b96 --- /dev/null +++ b/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/controller/admin/bi/vo/BiRanKingRespVO.java @@ -0,0 +1,23 @@ +package cn.iocoder.yudao.module.crm.controller.admin.bi.vo; + +import io.swagger.v3.oas.annotations.media.Schema; +import lombok.Data; + + +@Schema(description = "管理后台 - BI 排行榜 Response VO") +@Data +public class BiRanKingRespVO { + + @Schema(description = "金额", requiredMode = Schema.RequiredMode.REQUIRED, example = "1") + private Integer price; + + @Schema(description = "姓名", requiredMode = Schema.RequiredMode.REQUIRED, example = "1") + private String nickname; + + @Schema(description = "部门名称", requiredMode = Schema.RequiredMode.REQUIRED, example = "1") + private String deptName; + + @Schema(description = "负责人编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "1") + private Long ownerUserId; + +} diff --git a/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/controller/admin/bi/vo/BiRankingReqVO.java b/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/controller/admin/bi/vo/BiRankingReqVO.java new file mode 100644 index 000000000..06b013333 --- /dev/null +++ b/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/controller/admin/bi/vo/BiRankingReqVO.java @@ -0,0 +1,35 @@ +package cn.iocoder.yudao.module.crm.controller.admin.bi.vo; + +import io.swagger.v3.oas.annotations.media.Schema; +import lombok.Data; +import org.springframework.format.annotation.DateTimeFormat; + +import java.time.LocalDateTime; +import java.util.List; + +import static cn.iocoder.yudao.framework.common.util.date.DateUtils.FORMAT_YEAR_MONTH_DAY_HOUR_MINUTE_SECOND; + +/** + * 管理后台 - 排行榜 Request VO + * + * @author anhaohao + */ +@Schema(description = "管理后台 - 排行榜 Request VO") +@Data +public class BiRankingReqVO { + + @Schema(description = "部门id", requiredMode = Schema.RequiredMode.REQUIRED, example = "1") + private Long deptId; + + @Schema(description = "开始时间", requiredMode = Schema.RequiredMode.REQUIRED, example = "2023-12-12 00:00:00") + @DateTimeFormat(pattern = FORMAT_YEAR_MONTH_DAY_HOUR_MINUTE_SECOND) + private LocalDateTime startTime; + + @Schema(description = "结束时间", requiredMode = Schema.RequiredMode.REQUIRED, example = "2023-12-12 23:59:59") + @DateTimeFormat(pattern = FORMAT_YEAR_MONTH_DAY_HOUR_MINUTE_SECOND) + private LocalDateTime endTime; + + @Schema(description = "负责人用户 id 集合", requiredMode = Schema.RequiredMode.NOT_REQUIRED, example = "1") + private List userIds; + +} diff --git a/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/controller/admin/contract/CrmContractController.java b/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/controller/admin/contract/CrmContractController.java index 7f2541ae7..73fcd646c 100644 --- a/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/controller/admin/contract/CrmContractController.java +++ b/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/controller/admin/contract/CrmContractController.java @@ -22,6 +22,7 @@ import io.swagger.v3.oas.annotations.tags.Tag; import jakarta.annotation.Resource; import jakarta.servlet.http.HttpServletResponse; import jakarta.validation.Valid; +import org.springframework.context.annotation.Lazy; import org.springframework.security.access.prepost.PreAuthorize; import org.springframework.validation.annotation.Validated; import org.springframework.web.bind.annotation.*; @@ -44,6 +45,7 @@ import static cn.iocoder.yudao.framework.security.core.util.SecurityFrameworkUti public class CrmContractController { @Resource + @Lazy private CrmContractService contractService; @Resource private CrmCustomerService customerService; diff --git a/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/controller/admin/receivable/CrmReceivableController.java b/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/controller/admin/receivable/CrmReceivableController.java index 8516ebd66..020b84c56 100644 --- a/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/controller/admin/receivable/CrmReceivableController.java +++ b/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/controller/admin/receivable/CrmReceivableController.java @@ -26,6 +26,7 @@ import io.swagger.v3.oas.annotations.tags.Tag; import jakarta.annotation.Resource; import jakarta.servlet.http.HttpServletResponse; import jakarta.validation.Valid; +import org.springframework.context.annotation.Lazy; import org.springframework.security.access.prepost.PreAuthorize; import org.springframework.validation.annotation.Validated; import org.springframework.web.bind.annotation.*; @@ -51,6 +52,7 @@ public class CrmReceivableController { @Resource private CrmReceivableService receivableService; @Resource + @Lazy private CrmContractService contractService; @Resource private CrmCustomerService customerService; diff --git a/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/controller/admin/receivable/CrmReceivablePlanController.java b/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/controller/admin/receivable/CrmReceivablePlanController.java index 481914e8b..252d714f4 100644 --- a/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/controller/admin/receivable/CrmReceivablePlanController.java +++ b/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/controller/admin/receivable/CrmReceivablePlanController.java @@ -28,6 +28,7 @@ import io.swagger.v3.oas.annotations.tags.Tag; import jakarta.annotation.Resource; import jakarta.servlet.http.HttpServletResponse; import jakarta.validation.Valid; +import org.springframework.context.annotation.Lazy; import org.springframework.security.access.prepost.PreAuthorize; import org.springframework.validation.annotation.Validated; import org.springframework.web.bind.annotation.*; @@ -55,6 +56,7 @@ public class CrmReceivablePlanController { @Resource private CrmReceivableService receivableService; @Resource + @Lazy private CrmContractService contractService; @Resource private CrmCustomerService customerService; diff --git a/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/dal/mysql/bi/BiRankingMapper.java b/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/dal/mysql/bi/BiRankingMapper.java new file mode 100644 index 000000000..a35e80777 --- /dev/null +++ b/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/dal/mysql/bi/BiRankingMapper.java @@ -0,0 +1,31 @@ +package cn.iocoder.yudao.module.crm.dal.mysql.bi; + +import cn.iocoder.yudao.framework.mybatis.core.mapper.BaseMapperX; +import cn.iocoder.yudao.module.crm.controller.admin.bi.vo.BiRanKingRespVO; +import cn.iocoder.yudao.module.crm.controller.admin.bi.vo.BiRankingReqVO; +import org.apache.ibatis.annotations.Mapper; + +import java.util.List; + +/** + * @author anhaohao + */ +@Mapper +public interface BiRankingMapper extends BaseMapperX { + /** + * 合同金额排行榜 + * + * @param biRankingReqVO 参数 + * @return List + */ + List contractRanKing(BiRankingReqVO biRankingReqVO); + + + /** + * 回款金额排行榜 + * + * @param biRankingReqVO 参数 + * @return List + */ + List receivablesRanKing(BiRankingReqVO biRankingReqVO); +} diff --git a/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/framework/operatelog/core/CrmContractParseFunction.java b/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/framework/operatelog/core/CrmContractParseFunction.java index d3c58522e..812417bf2 100644 --- a/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/framework/operatelog/core/CrmContractParseFunction.java +++ b/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/framework/operatelog/core/CrmContractParseFunction.java @@ -6,6 +6,7 @@ import cn.iocoder.yudao.module.crm.service.contract.CrmContractService; import com.mzt.logapi.service.IParseFunction; import jakarta.annotation.Resource; import lombok.extern.slf4j.Slf4j; +import org.springframework.context.annotation.Lazy; import org.springframework.stereotype.Component; /** @@ -20,6 +21,7 @@ public class CrmContractParseFunction implements IParseFunction { public static final String NAME = "getContractById"; @Resource + @Lazy private CrmContractService contractService; @Override diff --git a/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/service/bi/BiRankingService.java b/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/service/bi/BiRankingService.java new file mode 100644 index 000000000..17c9722de --- /dev/null +++ b/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/service/bi/BiRankingService.java @@ -0,0 +1,31 @@ +package cn.iocoder.yudao.module.crm.service.bi; + + +import cn.iocoder.yudao.module.crm.controller.admin.bi.vo.BiRanKingRespVO; +import cn.iocoder.yudao.module.crm.controller.admin.bi.vo.BiRankingReqVO; + +import java.util.List; + +/** + * BI 排行榜 Service 接口 + * + * @author anhaohao + */ +public interface BiRankingService { + + /** + * 合同金额排行榜 + * + * @param biRankingReqVO 参数 + * @return List + */ + List contractRanKing(BiRankingReqVO biRankingReqVO); + + /** + * 回款金额排行榜 + * + * @param biRankingReqVO 参数 + * @return List + */ + List receivablesRanKing(BiRankingReqVO biRankingReqVO); +} diff --git a/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/service/bi/BiRankingServiceImpl.java b/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/service/bi/BiRankingServiceImpl.java new file mode 100644 index 000000000..9a6534067 --- /dev/null +++ b/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/service/bi/BiRankingServiceImpl.java @@ -0,0 +1,93 @@ +package cn.iocoder.yudao.module.crm.service.bi; + +import cn.iocoder.yudao.framework.security.core.util.SecurityFrameworkUtils; + +import cn.iocoder.yudao.module.crm.controller.admin.bi.vo.BiRanKingRespVO; +import cn.iocoder.yudao.module.crm.controller.admin.bi.vo.BiRankingReqVO; +import cn.iocoder.yudao.module.crm.dal.mysql.bi.BiRankingMapper; +import cn.iocoder.yudao.module.system.api.dept.DeptApi; +import cn.iocoder.yudao.module.system.api.dept.dto.DeptRespDTO; +import cn.iocoder.yudao.module.system.api.user.AdminUserApi; +import cn.iocoder.yudao.module.system.api.user.dto.AdminUserRespDTO; +import jakarta.annotation.Resource; +import org.springframework.stereotype.Service; +import org.springframework.validation.annotation.Validated; + +import java.util.ArrayList; +import java.util.List; +import java.util.Map; +import java.util.function.Function; +import java.util.stream.Collectors; + +@Service(value = "biRankingService") +@Validated +public class BiRankingServiceImpl implements BiRankingService { + + @Resource + private BiRankingMapper biRankingMapper; + @Resource + private AdminUserApi adminUserApi; + @Resource + private DeptApi deptApi; + + @Override + public List contractRanKing(BiRankingReqVO biRankingReqVO) { + return processRanking(biRankingReqVO, biRankingMapper::contractRanKing); + } + + @Override + public List receivablesRanKing(BiRankingReqVO biRankingReqVO) { + return processRanking(biRankingReqVO, biRankingMapper::receivablesRanKing); + } + + /** + * 处理排行榜 + * + * @param biRankingReqVO 参数 + * @param rankingFunction 排行榜方法 + * @return List + */ + private List processRanking(BiRankingReqVO biRankingReqVO, Function> rankingFunction) { + analyzeAuth(biRankingReqVO); + if (biRankingReqVO.getUserIds().isEmpty()) { + return new ArrayList<>(); + } + List biRanKingRespVOS = rankingFunction.apply(biRankingReqVO); + return setName(biRanKingRespVOS); + } + + /** + * 设置用户名称 + * + * @param biRanKingRespVOS 排行榜数据 + * @return List + */ + private List setName(List biRanKingRespVOS) { + List userIds = biRanKingRespVOS.stream().map(BiRanKingRespVO::getOwnerUserId).collect(Collectors.toList()); + Map userMap = adminUserApi.getUserMap(userIds); + Map deptMap = deptApi.getDeptMap(userMap.values().stream().map(AdminUserRespDTO::getDeptId).collect(Collectors.toList())); + for (BiRanKingRespVO biRanKingRespVO : biRanKingRespVOS) { + AdminUserRespDTO adminUserRespDTO = userMap.get(biRanKingRespVO.getOwnerUserId()); + if (adminUserRespDTO != null) { + biRanKingRespVO.setNickname(adminUserRespDTO.getNickname()); + DeptRespDTO deptRespDTO = deptMap.get(adminUserRespDTO.getDeptId()); + if (deptRespDTO != null) { + biRanKingRespVO.setDeptName(deptRespDTO.getName()); + } + } + } + return biRanKingRespVOS; + } + + /** + * 分析权限 + * + * @param biRankingReqVO 参数 + */ + public void analyzeAuth(BiRankingReqVO biRankingReqVO) { + Long deptId = biRankingReqVO.getDeptId() == null ? adminUserApi.getUser(SecurityFrameworkUtils.getLoginUserId()).getDeptId() : biRankingReqVO.getDeptId(); + List deptIds = deptApi.getChildDeptList(deptId).stream().map(DeptRespDTO::getId).collect(Collectors.toList()); + deptIds.add(deptId); + biRankingReqVO.setUserIds(adminUserApi.getUserListByDeptIds(deptIds).stream().map(AdminUserRespDTO::getId).collect(Collectors.toList())); + } +} \ No newline at end of file diff --git a/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/service/business/CrmBusinessServiceImpl.java b/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/service/business/CrmBusinessServiceImpl.java index 716485007..877971435 100644 --- a/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/service/business/CrmBusinessServiceImpl.java +++ b/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/service/business/CrmBusinessServiceImpl.java @@ -28,6 +28,7 @@ import com.mzt.logapi.context.LogRecordContext; import com.mzt.logapi.service.impl.DiffParseFunction; import com.mzt.logapi.starter.annotation.LogRecord; 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; @@ -56,6 +57,7 @@ public class CrmBusinessServiceImpl implements CrmBusinessService { @Resource private CrmBusinessProductService businessProductService; @Resource + @Lazy private CrmContractService contractService; @Resource private CrmPermissionService permissionService; diff --git a/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/service/contact/CrmContactServiceImpl.java b/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/service/contact/CrmContactServiceImpl.java index 52f2d6cf7..4c1a7fd95 100644 --- a/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/service/contact/CrmContactServiceImpl.java +++ b/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/service/contact/CrmContactServiceImpl.java @@ -25,6 +25,7 @@ import com.mzt.logapi.context.LogRecordContext; import com.mzt.logapi.service.impl.DiffParseFunction; import com.mzt.logapi.starter.annotation.LogRecord; 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; @@ -56,6 +57,7 @@ public class CrmContactServiceImpl implements CrmContactService { @Resource private CrmPermissionService permissionService; @Resource + @Lazy private CrmContractService contractService; @Resource private CrmContactBusinessService contactBusinessService; diff --git a/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/service/receivable/CrmReceivablePlanServiceImpl.java b/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/service/receivable/CrmReceivablePlanServiceImpl.java index d05647cfb..c4008590c 100644 --- a/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/service/receivable/CrmReceivablePlanServiceImpl.java +++ b/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/service/receivable/CrmReceivablePlanServiceImpl.java @@ -24,6 +24,7 @@ import com.mzt.logapi.context.LogRecordContext; import com.mzt.logapi.service.impl.DiffParseFunction; import com.mzt.logapi.starter.annotation.LogRecord; import jakarta.annotation.Resource; +import org.springframework.context.annotation.Lazy; import org.springframework.stereotype.Service; import org.springframework.validation.annotation.Validated; @@ -49,6 +50,7 @@ public class CrmReceivablePlanServiceImpl implements CrmReceivablePlanService { private CrmReceivablePlanMapper receivablePlanMapper; @Resource + @Lazy private CrmContractService contractService; @Resource private CrmCustomerService customerService; diff --git a/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/service/receivable/CrmReceivableServiceImpl.java b/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/service/receivable/CrmReceivableServiceImpl.java index 54c4aa82a..b0777787f 100644 --- a/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/service/receivable/CrmReceivableServiceImpl.java +++ b/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/service/receivable/CrmReceivableServiceImpl.java @@ -27,6 +27,7 @@ import com.mzt.logapi.context.LogRecordContext; import com.mzt.logapi.service.impl.DiffParseFunction; import com.mzt.logapi.starter.annotation.LogRecord; import jakarta.annotation.Resource; +import org.springframework.context.annotation.Lazy; import org.springframework.stereotype.Service; import org.springframework.validation.annotation.Validated; @@ -50,6 +51,7 @@ public class CrmReceivableServiceImpl implements CrmReceivableService { private CrmReceivableMapper receivableMapper; @Resource + @Lazy private CrmContractService contractService; @Resource private CrmCustomerService customerService; diff --git a/yudao-module-crm/yudao-module-crm-biz/src/main/resources/mapper/bi/BiRankingMapper.xml b/yudao-module-crm/yudao-module-crm-biz/src/main/resources/mapper/bi/BiRankingMapper.xml new file mode 100644 index 000000000..9ebcbda0e --- /dev/null +++ b/yudao-module-crm/yudao-module-crm-biz/src/main/resources/mapper/bi/BiRankingMapper.xml @@ -0,0 +1,35 @@ + + + + + + + + + diff --git a/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/api/dept/DeptApiImpl.java b/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/api/dept/DeptApiImpl.java index 81062994e..6eb55ef48 100644 --- a/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/api/dept/DeptApiImpl.java +++ b/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/api/dept/DeptApiImpl.java @@ -20,7 +20,6 @@ import java.util.List; public class DeptApiImpl implements DeptApi { @Resource - @Lazy // 延迟加载,解决相互依赖的问题 private DeptService deptService; @Override diff --git a/yudao-server/pom.xml b/yudao-server/pom.xml index 39d6c14c7..7c288f725 100644 --- a/yudao-server/pom.xml +++ b/yudao-server/pom.xml @@ -93,11 +93,6 @@ yudao-module-crm-biz ${revision} - - cn.iocoder.boot - yudao-module-bi-biz - ${revision} - From 624b35988ec2a008190bab1b532af4d7ea6f55c9 Mon Sep 17 00:00:00 2001 From: puhui999 Date: Thu, 1 Feb 2024 00:45:29 +0800 Subject: [PATCH 055/119] =?UTF-8?q?BPM:=20=E5=AE=9E=E7=8E=B0=E4=B8=9A?= =?UTF-8?q?=E5=8A=A1=E6=B5=81=E7=A8=8B=E7=BB=93=E6=9E=9C=E7=9B=91=E5=90=AC?= =?UTF-8?q?=E5=99=A8?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- pom.xml | 2 +- .../api/listener/BpmResultListenerApi.java | 26 ++++++++++++++ .../dto/BpmResultListenerRespDTO.java | 31 ++++++++++++++++ .../listener/BpmServiceResultListener.java | 35 +++++++++++++++++++ .../business/CrmBusinessServiceImpl.java | 2 ++ .../contact/CrmContactServiceImpl.java | 2 ++ .../service/contract/CrmContractService.java | 7 ++++ .../contract/CrmContractServiceImpl.java | 10 ++++++ .../listener/CrmContractResultListener.java | 30 ++++++++++++++-- yudao-server/pom.xml | 10 +++--- 10 files changed, 147 insertions(+), 8 deletions(-) create mode 100644 yudao-module-bpm/yudao-module-bpm-api/src/main/java/cn/iocoder/yudao/module/bpm/api/listener/BpmResultListenerApi.java create mode 100644 yudao-module-bpm/yudao-module-bpm-api/src/main/java/cn/iocoder/yudao/module/bpm/api/listener/dto/BpmResultListenerRespDTO.java create mode 100644 yudao-module-bpm/yudao-module-bpm-biz/src/main/java/cn/iocoder/yudao/module/bpm/framework/bpm/listener/BpmServiceResultListener.java diff --git a/pom.xml b/pom.xml index 89807a7d0..5cf738c52 100644 --- a/pom.xml +++ b/pom.xml @@ -16,7 +16,7 @@ yudao-module-system yudao-module-infra - + yudao-module-bpm diff --git a/yudao-module-bpm/yudao-module-bpm-api/src/main/java/cn/iocoder/yudao/module/bpm/api/listener/BpmResultListenerApi.java b/yudao-module-bpm/yudao-module-bpm-api/src/main/java/cn/iocoder/yudao/module/bpm/api/listener/BpmResultListenerApi.java new file mode 100644 index 000000000..65b038311 --- /dev/null +++ b/yudao-module-bpm/yudao-module-bpm-api/src/main/java/cn/iocoder/yudao/module/bpm/api/listener/BpmResultListenerApi.java @@ -0,0 +1,26 @@ +package cn.iocoder.yudao.module.bpm.api.listener; + +import cn.iocoder.yudao.module.bpm.api.listener.dto.BpmResultListenerRespDTO; + +/** + * 业务流程实例的结果发生变化的监听器 Api + * + * @author HUIHUI + */ +public interface BpmResultListenerApi { + + /** + * 监听的流程定义 Key + * + * @return 返回监听的流程定义 Key + */ + String getProcessDefinitionKey(); + + /** + * 处理事件 + * + * @param event 事件 + */ + void onEvent(BpmResultListenerRespDTO event); + +} diff --git a/yudao-module-bpm/yudao-module-bpm-api/src/main/java/cn/iocoder/yudao/module/bpm/api/listener/dto/BpmResultListenerRespDTO.java b/yudao-module-bpm/yudao-module-bpm-api/src/main/java/cn/iocoder/yudao/module/bpm/api/listener/dto/BpmResultListenerRespDTO.java new file mode 100644 index 000000000..75f9d02f0 --- /dev/null +++ b/yudao-module-bpm/yudao-module-bpm-api/src/main/java/cn/iocoder/yudao/module/bpm/api/listener/dto/BpmResultListenerRespDTO.java @@ -0,0 +1,31 @@ +package cn.iocoder.yudao.module.bpm.api.listener.dto; + +import lombok.Data; + +/** + * 业务流程实例的结果 Response DTO + * + * @author HUIHUI + */ +@Data +public class BpmResultListenerRespDTO { + + /** + * 流程实例的编号 + */ + private String id; + /** + * 流程实例的 key + */ + private String processDefinitionKey; + /** + * 流程实例的结果 + */ + private Integer result; + /** + * 流程实例对应的业务标识 + * 例如说,请假 + */ + private String businessKey; + +} diff --git a/yudao-module-bpm/yudao-module-bpm-biz/src/main/java/cn/iocoder/yudao/module/bpm/framework/bpm/listener/BpmServiceResultListener.java b/yudao-module-bpm/yudao-module-bpm-biz/src/main/java/cn/iocoder/yudao/module/bpm/framework/bpm/listener/BpmServiceResultListener.java new file mode 100644 index 000000000..3081fb360 --- /dev/null +++ b/yudao-module-bpm/yudao-module-bpm-biz/src/main/java/cn/iocoder/yudao/module/bpm/framework/bpm/listener/BpmServiceResultListener.java @@ -0,0 +1,35 @@ +package cn.iocoder.yudao.module.bpm.framework.bpm.listener; + +import cn.hutool.core.util.StrUtil; +import cn.iocoder.yudao.framework.common.util.object.BeanUtils; +import cn.iocoder.yudao.module.bpm.api.listener.BpmResultListenerApi; +import cn.iocoder.yudao.module.bpm.api.listener.dto.BpmResultListenerRespDTO; +import cn.iocoder.yudao.module.bpm.framework.bpm.core.event.BpmProcessInstanceResultEvent; +import jakarta.annotation.Resource; +import org.springframework.context.ApplicationListener; +import org.springframework.stereotype.Component; + +import java.util.List; + +/** + * 业务流程结果监听器实现类 + * + * @author HUIHUI + */ +@Component +public class BpmServiceResultListener implements ApplicationListener { + + @Resource + private List bpmResultListenerApis; + + @Override + public final void onApplicationEvent(BpmProcessInstanceResultEvent event) { + bpmResultListenerApis.forEach(bpmResultListenerApi -> { + if (!StrUtil.equals(event.getProcessDefinitionKey(), bpmResultListenerApi.getProcessDefinitionKey())) { + return; + } + bpmResultListenerApi.onEvent(BeanUtils.toBean(event, BpmResultListenerRespDTO.class)); + }); + } + +} diff --git a/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/service/business/CrmBusinessServiceImpl.java b/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/service/business/CrmBusinessServiceImpl.java index 716485007..877971435 100644 --- a/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/service/business/CrmBusinessServiceImpl.java +++ b/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/service/business/CrmBusinessServiceImpl.java @@ -28,6 +28,7 @@ import com.mzt.logapi.context.LogRecordContext; import com.mzt.logapi.service.impl.DiffParseFunction; import com.mzt.logapi.starter.annotation.LogRecord; 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; @@ -56,6 +57,7 @@ public class CrmBusinessServiceImpl implements CrmBusinessService { @Resource private CrmBusinessProductService businessProductService; @Resource + @Lazy private CrmContractService contractService; @Resource private CrmPermissionService permissionService; diff --git a/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/service/contact/CrmContactServiceImpl.java b/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/service/contact/CrmContactServiceImpl.java index 52f2d6cf7..4c1a7fd95 100644 --- a/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/service/contact/CrmContactServiceImpl.java +++ b/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/service/contact/CrmContactServiceImpl.java @@ -25,6 +25,7 @@ import com.mzt.logapi.context.LogRecordContext; import com.mzt.logapi.service.impl.DiffParseFunction; import com.mzt.logapi.starter.annotation.LogRecord; 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; @@ -56,6 +57,7 @@ public class CrmContactServiceImpl implements CrmContactService { @Resource private CrmPermissionService permissionService; @Resource + @Lazy private CrmContractService contractService; @Resource private CrmContactBusinessService contactBusinessService; diff --git a/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/service/contract/CrmContractService.java b/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/service/contract/CrmContractService.java index 9847af328..9d3cdb85b 100644 --- a/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/service/contract/CrmContractService.java +++ b/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/service/contract/CrmContractService.java @@ -1,6 +1,7 @@ package cn.iocoder.yudao.module.crm.service.contract; import cn.iocoder.yudao.framework.common.pojo.PageResult; +import cn.iocoder.yudao.module.bpm.api.listener.dto.BpmResultListenerRespDTO; import cn.iocoder.yudao.module.crm.controller.admin.contract.vo.CrmContractPageReqVO; import cn.iocoder.yudao.module.crm.controller.admin.contract.vo.CrmContractSaveReqVO; import cn.iocoder.yudao.module.crm.controller.admin.contract.vo.CrmContractTransferReqVO; @@ -65,6 +66,12 @@ public interface CrmContractService { */ void handleApprove(Long id, Long userId); + /** + * 更新合同流程审批结果 + * + * @param event 审批结果 + */ + void updateContractAuditStatus(BpmResultListenerRespDTO event); /** * 获得合同 * diff --git a/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/service/contract/CrmContractServiceImpl.java b/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/service/contract/CrmContractServiceImpl.java index 59274b522..c58ce15f0 100644 --- a/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/service/contract/CrmContractServiceImpl.java +++ b/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/service/contract/CrmContractServiceImpl.java @@ -6,6 +6,7 @@ import cn.hutool.core.util.ObjUtil; 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.bpm.api.listener.dto.BpmResultListenerRespDTO; import cn.iocoder.yudao.module.bpm.api.task.BpmProcessInstanceApi; import cn.iocoder.yudao.module.bpm.api.task.dto.BpmProcessInstanceCreateReqDTO; import cn.iocoder.yudao.module.crm.controller.admin.contract.vo.CrmContractPageReqVO; @@ -33,6 +34,7 @@ import com.mzt.logapi.context.LogRecordContext; import com.mzt.logapi.service.impl.DiffParseFunction; import com.mzt.logapi.starter.annotation.LogRecord; 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; @@ -73,8 +75,10 @@ public class CrmContractServiceImpl implements CrmContractService { @Resource private CrmCustomerService customerService; @Resource + @Lazy private CrmContactService contactService; @Resource + @Lazy private CrmBusinessService businessService; @Resource private AdminUserApi adminUserApi; @@ -244,6 +248,12 @@ public class CrmContractServiceImpl implements CrmContractService { .setAuditStatus(CrmAuditStatusEnum.PROCESS.getStatus())); } + @Override + @Transactional(rollbackFor = Exception.class) + public void updateContractAuditStatus(BpmResultListenerRespDTO event) { + contractMapper.updateById(new CrmContractDO().setId(Long.parseLong(event.getBusinessKey())).setAuditStatus(event.getResult())); + } + //======================= 查询相关 ======================= @Override diff --git a/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/service/contract/listener/CrmContractResultListener.java b/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/service/contract/listener/CrmContractResultListener.java index e393c2664..f175bd43d 100644 --- a/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/service/contract/listener/CrmContractResultListener.java +++ b/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/service/contract/listener/CrmContractResultListener.java @@ -1,5 +1,31 @@ package cn.iocoder.yudao.module.crm.service.contract.listener; -public class CrmContractResultListener { - // TODO puhui999: @芋艿: 艿艿写一下这个,没研究明白哈哈 +import cn.iocoder.yudao.module.bpm.api.listener.BpmResultListenerApi; +import cn.iocoder.yudao.module.bpm.api.listener.dto.BpmResultListenerRespDTO; +import cn.iocoder.yudao.module.crm.service.contract.CrmContractService; +import cn.iocoder.yudao.module.crm.service.contract.CrmContractServiceImpl; +import jakarta.annotation.Resource; +import org.springframework.stereotype.Component; + +/** + * 合同审批的结果的监听器实现类 + * + * @author HUIHUI + */ +@Component +public class CrmContractResultListener implements BpmResultListenerApi { + + @Resource + private CrmContractService contractService; + + @Override + public String getProcessDefinitionKey() { + return CrmContractServiceImpl.CONTRACT_APPROVE; + } + + @Override + public void onEvent(BpmResultListenerRespDTO event) { + contractService.updateContractAuditStatus(event); + } + } diff --git a/yudao-server/pom.xml b/yudao-server/pom.xml index 39d6c14c7..bf640588b 100644 --- a/yudao-server/pom.xml +++ b/yudao-server/pom.xml @@ -46,11 +46,11 @@ - - - - - + + cn.iocoder.boot + yudao-module-bpm-biz + ${revision} + From f5f827b59fa08f2e2bab5c76c978df5f409e8e42 Mon Sep 17 00:00:00 2001 From: YunaiV Date: Thu, 1 Feb 2024 09:46:32 +0800 Subject: [PATCH 056/119] =?UTF-8?q?=F0=9F=93=96=20CRM=EF=BC=9Acode=20revie?= =?UTF-8?q?w=20=E5=90=88=E5=90=8C=E6=B5=81=E7=A8=8B?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../admin/definition/BpmModelController.java | 1 + .../admin/contract/CrmContractController.java | 2 ++ .../contract/vo/CrmContractSaveReqVO.java | 1 + .../admin/customer/CrmCustomerController.java | 7 ++--- .../customer/vo/CrmCustomerImportExcelVO.java | 7 ++--- .../service/contract/CrmContractService.java | 1 + .../contract/CrmContractServiceImpl.java | 27 ++++++++++--------- .../customer/CrmCustomerServiceImpl.java | 9 +++++-- .../permission/CrmPermissionService.java | 8 +++--- .../permission/CrmPermissionServiceImpl.java | 4 +-- 10 files changed, 39 insertions(+), 28 deletions(-) diff --git a/yudao-module-bpm/yudao-module-bpm-biz/src/main/java/cn/iocoder/yudao/module/bpm/controller/admin/definition/BpmModelController.java b/yudao-module-bpm/yudao-module-bpm-biz/src/main/java/cn/iocoder/yudao/module/bpm/controller/admin/definition/BpmModelController.java index 7cb931689..861698ac0 100644 --- a/yudao-module-bpm/yudao-module-bpm-biz/src/main/java/cn/iocoder/yudao/module/bpm/controller/admin/definition/BpmModelController.java +++ b/yudao-module-bpm/yudao-module-bpm-biz/src/main/java/cn/iocoder/yudao/module/bpm/controller/admin/definition/BpmModelController.java @@ -43,6 +43,7 @@ public class BpmModelController { return success(model); } + // TODO @puhui999:这个接口的目的是啥呀? @GetMapping("/get-by-key") @Operation(summary = "获得模型") @Parameter(name = "key", description = "流程标识", required = true, example = "oa_leave") diff --git a/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/controller/admin/contract/CrmContractController.java b/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/controller/admin/contract/CrmContractController.java index 7f2541ae7..28c71c4e2 100644 --- a/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/controller/admin/contract/CrmContractController.java +++ b/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/controller/admin/contract/CrmContractController.java @@ -132,6 +132,7 @@ public class CrmContractController { return CrmContractConvert.INSTANCE.convertPage(pageResult, userMap, customerList); } + // TODO @puhui999:transferContract @PutMapping("/transfer") @Operation(summary = "合同转移") @PreAuthorize("@ss.hasPermission('crm:contract:update')") @@ -140,6 +141,7 @@ public class CrmContractController { return success(true); } + // TODO @puhui999:方法名不对哈;要不改成 submit?提交审核的意思 @PutMapping("/approve") @Operation(summary = "发起合同审批流程") @PreAuthorize("@ss.hasPermission('crm:contract:update')") diff --git a/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/controller/admin/contract/vo/CrmContractSaveReqVO.java b/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/controller/admin/contract/vo/CrmContractSaveReqVO.java index ef90f2f2f..f1ab8c581 100644 --- a/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/controller/admin/contract/vo/CrmContractSaveReqVO.java +++ b/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/controller/admin/contract/vo/CrmContractSaveReqVO.java @@ -89,6 +89,7 @@ public class CrmContractSaveReqVO { @DiffLogField(name = "备注") private String remark; + // TODO @puhui999:这个字段,按道理不用传递? @Schema(description = "审批状态", example = "1") private Integer auditStatus; diff --git a/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/controller/admin/customer/CrmCustomerController.java b/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/controller/admin/customer/CrmCustomerController.java index 3bbd4dfd7..09057fd78 100644 --- a/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/controller/admin/customer/CrmCustomerController.java +++ b/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/controller/admin/customer/CrmCustomerController.java @@ -217,6 +217,8 @@ public class CrmCustomerController { ExcelUtils.write(response, "客户导入模板.xls", "客户列表", CrmCustomerImportExcelVO.class, list); } + // TODO @puhui999:updateSupport 要不改成前端必须传递;哈哈哈,代码排版看着有点乱; + // TODO @puhui999:加一个选择负责人;允许空,空就进入公海; @PostMapping("/import") @Operation(summary = "导入客户") @Parameters({ @@ -224,13 +226,12 @@ public class CrmCustomerController { @Parameter(name = "updateSupport", description = "是否支持更新,默认为 false", example = "true") }) @PreAuthorize("@ss.hasPermission('system:customer:import')") - public CommonResult importExcel(@RequestParam("file") MultipartFile file, - @RequestParam(value = "updateSupport", required = false, defaultValue = "false") Boolean updateSupport) throws Exception { + public CommonResult importExcel(@RequestParam("file") MultipartFile file, @RequestParam(value = "updateSupport", required = false, defaultValue = "false") Boolean updateSupport) + throws Exception { List list = ExcelUtils.read(file, CrmCustomerImportExcelVO.class); return success(customerService.importCustomerList(list, updateSupport, getLoginUserId())); } - @PutMapping("/transfer") @Operation(summary = "转移客户") @PreAuthorize("@ss.hasPermission('crm:customer:update')") diff --git a/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/controller/admin/customer/vo/CrmCustomerImportExcelVO.java b/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/controller/admin/customer/vo/CrmCustomerImportExcelVO.java index 378abb6dd..4f57564dd 100644 --- a/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/controller/admin/customer/vo/CrmCustomerImportExcelVO.java +++ b/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/controller/admin/customer/vo/CrmCustomerImportExcelVO.java @@ -3,7 +3,6 @@ package cn.iocoder.yudao.module.crm.controller.admin.customer.vo; import cn.iocoder.yudao.framework.excel.core.annotations.DictFormat; import cn.iocoder.yudao.framework.excel.core.convert.DictConvert; import com.alibaba.excel.annotation.ExcelProperty; -import jakarta.validation.constraints.Size; import lombok.AllArgsConstructor; import lombok.Builder; import lombok.Data; @@ -25,6 +24,7 @@ public class CrmCustomerImportExcelVO { @ExcelProperty("客户名称") private String name; + // TODO @puhui999:industryId、level、source 字段,可以研究下怎么搞下拉框 @ExcelProperty(value = "所属行业", converter = DictConvert.class) @DictFormat(CRM_CUSTOMER_INDUSTRY) private Integer industryId; @@ -46,25 +46,22 @@ public class CrmCustomerImportExcelVO { @ExcelProperty("网址") private String website; - @Size(max = 20, message = "QQ长度不能超过 20 个字符") @ExcelProperty("QQ") private String qq; - @Size(max = 255, message = "微信长度不能超过 255 个字符") @ExcelProperty("微信") private String wechat; - @Size(max = 255, message = "邮箱长度不能超过 255 个字符") @ExcelProperty("邮箱") private String email; - @Size(max = 4096, message = "客户描述长度不能超过 4096 个字符") @ExcelProperty("客户描述") private String description; @ExcelProperty("备注") private String remark; + // TODO @puhui999:需要选择省市区,需要研究下,怎么搞合理点; @ExcelProperty("地区编号") private Integer areaId; diff --git a/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/service/contract/CrmContractService.java b/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/service/contract/CrmContractService.java index 9847af328..ea7972228 100644 --- a/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/service/contract/CrmContractService.java +++ b/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/service/contract/CrmContractService.java @@ -118,6 +118,7 @@ public interface CrmContractService { */ Long getContractCountByCustomerId(Long customerId); + // TODO @puhui999:要不改成 getContractCountByBusinessId /** * 根据商机ID获取关联客户的合同数量 * diff --git a/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/service/contract/CrmContractServiceImpl.java b/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/service/contract/CrmContractServiceImpl.java index 59274b522..130f0f709 100644 --- a/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/service/contract/CrmContractServiceImpl.java +++ b/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/service/contract/CrmContractServiceImpl.java @@ -22,7 +22,6 @@ import cn.iocoder.yudao.module.crm.enums.permission.CrmPermissionLevelEnum; import cn.iocoder.yudao.module.crm.framework.permission.core.annotations.CrmPermission; import cn.iocoder.yudao.module.crm.service.business.CrmBusinessProductService; import cn.iocoder.yudao.module.crm.service.business.CrmBusinessService; -import cn.iocoder.yudao.module.crm.service.contact.CrmContactService; import cn.iocoder.yudao.module.crm.service.customer.CrmCustomerService; import cn.iocoder.yudao.module.crm.service.followup.bo.CrmUpdateFollowUpReqBO; import cn.iocoder.yudao.module.crm.service.permission.CrmPermissionService; @@ -69,15 +68,14 @@ public class CrmContractServiceImpl implements CrmContractService { @Resource private CrmProductService productService; @Resource - private BpmProcessInstanceApi bpmProcessInstanceApi; - @Resource private CrmCustomerService customerService; @Resource - private CrmContactService contactService; - @Resource private CrmBusinessService businessService; + @Resource private AdminUserApi adminUserApi; + @Resource + private BpmProcessInstanceApi bpmProcessInstanceApi; @Override @Transactional(rollbackFor = Exception.class) @@ -85,19 +83,19 @@ public class CrmContractServiceImpl implements CrmContractService { success = CRM_CONTRACT_CREATE_SUCCESS) public Long createContract(CrmContractSaveReqVO createReqVO, Long userId) { validateRelationDataExists(createReqVO); - // 插入合同 + // 1.1 插入合同 CrmContractDO contract = BeanUtils.toBean(createReqVO, CrmContractDO.class).setId(null); contractMapper.insert(contract); + // 1.2 插入商机关联商品 + List businessProduct = convertBusinessProductList(createReqVO); + businessProductService.insertBatch(businessProduct); - // 创建数据权限 + // 2. 创建数据权限 crmPermissionService.createPermission(new CrmPermissionCreateReqBO().setUserId(userId) .setBizType(CrmBizTypeEnum.CRM_CONTRACT.getType()).setBizId(contract.getId()) .setLevel(CrmPermissionLevelEnum.OWNER.getLevel())); - // 插入商机关联商品 - List businessProduct = convertBusinessProductList(createReqVO); - businessProductService.insertBatch(businessProduct); - // 4. 记录操作日志上下文 + // 3. 记录操作日志上下文 LogRecordContext.putVariable("contract", contract); return contract.getId(); } @@ -121,6 +119,7 @@ public class CrmContractServiceImpl implements CrmContractService { contractMapper.updateById(updateObj); // TODO puhui999: @芋艿:合同变更关联的商机后商品怎么处理? + // TODO @puhui999:和商品 spu、sku 编辑一样;新增的插入;修改的更新;删除的删除 //List businessProduct = convertBusinessProductList(updateReqVO); //businessProductService.selectListByBusinessId() //diffList() @@ -141,6 +140,7 @@ public class CrmContractServiceImpl implements CrmContractService { } Map productMap = convertMap(productList, CrmProductDO::getId); return convertList(reqVO.getProductItems(), productItem -> { + // TODO @puhui999:这里可以改成直接 return,不用弄一个 businessProduct 变量哈; CrmBusinessProductDO businessProduct = BeanUtils.toBean(productMap.get(productItem.getId()), CrmBusinessProductDO.class); businessProduct.setId(null).setBusinessId(reqVO.getBusinessId()).setProductId(productItem.getId()) .setCount(productItem.getCount()).setDiscountPercent(productItem.getDiscountPercent()).setTotalPrice(calculator(businessProduct)); @@ -154,6 +154,7 @@ public class CrmContractServiceImpl implements CrmContractService { * @param businessProduct 关联商品 * @return 商品总价 */ + // TODO @puhui999:这个逻辑的计算,是不是可以封装到 calculateRatePriceFloor 里; private Integer calculator(CrmBusinessProductDO businessProduct) { int price = businessProduct.getPrice() * businessProduct.getCount(); if (businessProduct.getDiscountPercent() == null) { @@ -176,7 +177,7 @@ public class CrmContractServiceImpl implements CrmContractService { if (reqVO.getOwnerUserId() != null && adminUserApi.getUser(reqVO.getOwnerUserId()) == null) { throw exception(USER_NOT_EXISTS); } - // 4. 如果有关联商机,则需要校验存在 + // 3. 如果有关联商机,则需要校验存在 if (reqVO.getBusinessId() != null && businessService.getBusiness(reqVO.getBusinessId()) == null) { throw exception(BUSINESS_NOT_EXISTS); } @@ -235,6 +236,8 @@ public class CrmContractServiceImpl implements CrmContractService { @Override @Transactional(rollbackFor = Exception.class) public void handleApprove(Long id, Long userId) { + // TODO @puhui999:需要做状态检查 + // 创建合同审批流程实例 String processInstanceId = bpmProcessInstanceApi.createProcessInstance(userId, new BpmProcessInstanceCreateReqDTO() .setProcessDefinitionKey(CONTRACT_APPROVE).setBusinessKey(String.valueOf(id))); diff --git a/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/service/customer/CrmCustomerServiceImpl.java b/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/service/customer/CrmCustomerServiceImpl.java index 26e0e2346..a7ddb2da9 100644 --- a/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/service/customer/CrmCustomerServiceImpl.java +++ b/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/service/customer/CrmCustomerServiceImpl.java @@ -232,8 +232,10 @@ public class CrmCustomerServiceImpl implements CrmCustomerService { return customer.getId(); } + // TODO @puhui999:操作日志 @Override - public CrmCustomerImportRespVO importCustomerList(List importCustomers, Boolean isUpdateSupport, Long userId) { + public CrmCustomerImportRespVO importCustomerList(List importCustomers, + Boolean isUpdateSupport, Long userId) { if (CollUtil.isEmpty(importCustomers)) { throw exception(CUSTOMER_IMPORT_LIST_IS_EMPTY); } @@ -241,6 +243,7 @@ public class CrmCustomerServiceImpl implements CrmCustomerService { .updateCustomerNames(new ArrayList<>()).failureCustomerNames(new LinkedHashMap<>()).build(); importCustomers.forEach(importCustomer -> { // 校验,判断是否有不符合的原因 + // TODO @puhui999:可以用 ValidationUtils 做参数校验;可能要封装一个方法,返回 message;这样的话,就可以在 CrmCustomerImportExcelVO 写需要校验的参数啦; try { validateCustomerForCreate(importCustomer); } catch (ServiceException ex) { @@ -250,6 +253,7 @@ public class CrmCustomerServiceImpl implements CrmCustomerService { // 判断如果不存在,在进行插入 CrmCustomerDO existCustomer = customerMapper.selectByCustomerName(importCustomer.getName()); if (existCustomer == null) { + // TODO @puhui999:可以搞个 initCustomer 方法;这样可以把 create 和导入复用下这个方法; CrmCustomerDO customer = BeanUtils.toBean(importCustomer, CrmCustomerDO.class).setOwnerUserId(userId) .setLockStatus(false).setDealStatus(false).setContactLastTime(LocalDateTime.now()); customerMapper.insert(customer); @@ -366,6 +370,7 @@ public class CrmCustomerServiceImpl implements CrmCustomerService { // 1.1 获取没有锁定的不在公海的客户且没有成交的 List notDealCustomerList = customerMapper.selectListByLockAndDealStatusAndNotPool(Boolean.FALSE, Boolean.FALSE); // 1.2 获取没有锁定的不在公海的客户且成交的 + // TODO @puhui999:下面也搞到 sql 里去哈;写 or 查询,问题不大的; List dealCustomerList = customerMapper.selectListByLockAndDealStatusAndNotPool(Boolean.FALSE, Boolean.TRUE); List poolCustomerList = new ArrayList<>(); poolCustomerList.addAll(filterList(notDealCustomerList, customer -> @@ -382,7 +387,7 @@ public class CrmCustomerServiceImpl implements CrmCustomerService { getSelf().putCustomerPool(customer); count++; } catch (Throwable e) { - log.error("[customerAutoPutPoolBySystem][Customer 客户({}) 放入公海异常]", customer.getId(), e); + log.error("[autoPutCustomerPool][Customer 客户({}) 放入公海异常]", customer.getId(), e); } } return count; diff --git a/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/service/permission/CrmPermissionService.java b/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/service/permission/CrmPermissionService.java index 3385899fe..39b101323 100644 --- a/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/service/permission/CrmPermissionService.java +++ b/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/service/permission/CrmPermissionService.java @@ -109,14 +109,14 @@ public interface CrmPermissionService { List getPermissionListByBizTypeAndUserId(Integer bizType, Long userId); /** - * 校验权限 + * 校验是否有指定数据的操作权限 * * @param bizType 数据类型,关联 {@link CrmBizTypeEnum} * @param bizId 数据编号,关联 {@link CrmBizTypeEnum} 对应模块 DO#getId() * @param userId 用户编号 - * @param levelEnum 权限级别 - * @return boolean + * @param level 权限级别 + * @return 是否有权限 */ - boolean hasPermission(Integer bizType, Long bizId, Long userId, CrmPermissionLevelEnum levelEnum); + boolean hasPermission(Integer bizType, Long bizId, Long userId, CrmPermissionLevelEnum level); } diff --git a/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/service/permission/CrmPermissionServiceImpl.java b/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/service/permission/CrmPermissionServiceImpl.java index 36a616938..ba3e50c6d 100644 --- a/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/service/permission/CrmPermissionServiceImpl.java +++ b/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/service/permission/CrmPermissionServiceImpl.java @@ -213,10 +213,10 @@ public class CrmPermissionServiceImpl implements CrmPermissionService { } @Override - public boolean hasPermission(Integer bizType, Long bizId, Long userId, CrmPermissionLevelEnum levelEnum) { + public boolean hasPermission(Integer bizType, Long bizId, Long userId, CrmPermissionLevelEnum level) { List permissionList = permissionMapper.selectByBizTypeAndBizId(bizType, bizId); return anyMatch(permissionList, permission -> - ObjUtil.equal(permission.getUserId(), userId) && ObjUtil.equal(permission.getLevel(), levelEnum.getLevel())); + ObjUtil.equal(permission.getUserId(), userId) && ObjUtil.equal(permission.getLevel(), level.getLevel())); } } From e9a29e6dd40445a93fb6d1e3f2c59514626270f8 Mon Sep 17 00:00:00 2001 From: YunaiV Date: Sat, 3 Feb 2024 01:14:35 +0800 Subject: [PATCH 057/119] =?UTF-8?q?CRM=EF=BC=9A=E4=BC=98=E5=8C=96=E5=90=88?= =?UTF-8?q?=E5=90=8C=E9=87=91=E9=A2=9D=E6=8E=92=E8=A1=8C=E3=80=81=E5=9B=9E?= =?UTF-8?q?=E6=AC=BE=E9=87=91=E9=A2=9D=E6=8E=92=E8=A1=8C?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- pom.xml | 2 +- .../admin/bi/BiRankingController.http | 9 -- .../admin/bi/BiRankingController.java | 52 --------- .../admin/bi/CrmBiRankController.http | 9 ++ .../admin/bi/CrmBiRankController.java | 45 ++++++++ .../crm/controller/admin/bi/vo/BiParams.java | 35 ------ .../admin/bi/vo/BiRankingReqVO.java | 35 ------ ...anKingRespVO.java => CrmBiRanKRespVO.java} | 18 ++- .../admin/bi/vo/CrmBiRankReqVO.java | 35 ++++++ .../admin/contract/CrmContractController.java | 1 - .../receivable/CrmReceivableController.java | 2 - .../crm/dal/mysql/bi/BiRankingMapper.java | 31 ------ .../crm/dal/mysql/bi/CrmBiRankingMapper.java | 33 ++++++ .../core/CrmContractParseFunction.java | 2 - .../crm/service/bi/BiRankingService.java | 31 ------ .../crm/service/bi/BiRankingServiceImpl.java | 93 ---------------- .../crm/service/bi/CrmBiRankingService.java | 32 ++++++ .../service/bi/CrmBiRankingServiceImpl.java | 104 ++++++++++++++++++ .../business/CrmBusinessServiceImpl.java | 2 +- .../contact/CrmContactServiceImpl.java | 2 - .../CrmReceivablePlanServiceImpl.java | 1 - .../receivable/CrmReceivableServiceImpl.java | 1 - .../resources/mapper/bi/BiRankingMapper.xml | 35 ------ .../mapper/bi/CrmBiRankingMapper.xml | 33 ++++++ .../auth/vo/AuthPermissionInfoRespVO.java | 3 + .../system/convert/auth/AuthConvert.java | 3 +- yudao-server/pom.xml | 10 +- 27 files changed, 315 insertions(+), 344 deletions(-) delete mode 100644 yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/controller/admin/bi/BiRankingController.http delete mode 100644 yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/controller/admin/bi/BiRankingController.java create mode 100644 yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/controller/admin/bi/CrmBiRankController.http create mode 100644 yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/controller/admin/bi/CrmBiRankController.java delete mode 100644 yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/controller/admin/bi/vo/BiParams.java delete mode 100644 yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/controller/admin/bi/vo/BiRankingReqVO.java rename yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/controller/admin/bi/vo/{BiRanKingRespVO.java => CrmBiRanKRespVO.java} (51%) create mode 100644 yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/controller/admin/bi/vo/CrmBiRankReqVO.java delete mode 100644 yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/dal/mysql/bi/BiRankingMapper.java create mode 100644 yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/dal/mysql/bi/CrmBiRankingMapper.java delete mode 100644 yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/service/bi/BiRankingService.java delete mode 100644 yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/service/bi/BiRankingServiceImpl.java create mode 100644 yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/service/bi/CrmBiRankingService.java create mode 100644 yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/service/bi/CrmBiRankingServiceImpl.java delete mode 100644 yudao-module-crm/yudao-module-crm-biz/src/main/resources/mapper/bi/BiRankingMapper.xml create mode 100644 yudao-module-crm/yudao-module-crm-biz/src/main/resources/mapper/bi/CrmBiRankingMapper.xml diff --git a/pom.xml b/pom.xml index 89807a7d0..5cf738c52 100644 --- a/pom.xml +++ b/pom.xml @@ -16,7 +16,7 @@ yudao-module-system yudao-module-infra - + yudao-module-bpm diff --git a/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/controller/admin/bi/BiRankingController.http b/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/controller/admin/bi/BiRankingController.http deleted file mode 100644 index 23acfee92..000000000 --- a/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/controller/admin/bi/BiRankingController.http +++ /dev/null @@ -1,9 +0,0 @@ -### 合同金额排行榜 -GET {{baseUrl}}/crm/bi-ranking/contract-ranKing -Authorization: Bearer {{token}} -tenant-id: {{adminTenentId}} - -### 回款金额排行榜 -GET {{baseUrl}}/crm/bi-ranking/receivables-ranKing -Authorization: Bearer {{token}} -tenant-id: {{adminTenentId}} \ No newline at end of file diff --git a/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/controller/admin/bi/BiRankingController.java b/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/controller/admin/bi/BiRankingController.java deleted file mode 100644 index 2af4f23fa..000000000 --- a/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/controller/admin/bi/BiRankingController.java +++ /dev/null @@ -1,52 +0,0 @@ -package cn.iocoder.yudao.module.crm.controller.admin.bi; - - - -import cn.iocoder.yudao.framework.common.pojo.CommonResult; -import cn.iocoder.yudao.module.crm.controller.admin.bi.vo.BiRanKingRespVO; -import cn.iocoder.yudao.module.crm.controller.admin.bi.vo.BiRankingReqVO; -import cn.iocoder.yudao.module.crm.service.bi.BiRankingService; -import io.swagger.v3.oas.annotations.Operation; -import io.swagger.v3.oas.annotations.tags.Tag; -import jakarta.annotation.Resource; -import org.springframework.security.access.prepost.PreAuthorize; -import org.springframework.validation.annotation.Validated; -import org.springframework.web.bind.annotation.GetMapping; -import org.springframework.web.bind.annotation.RequestMapping; -import org.springframework.web.bind.annotation.RestController; - -import java.util.List; - -import static cn.iocoder.yudao.framework.common.pojo.CommonResult.success; - - -@Tag(name = "管理后台 - 排行榜") -@RestController -@RequestMapping("/crm/bi-ranking") -@Validated -public class BiRankingController { - - @Resource - private BiRankingService biRankingService; - - /** - * 合同金额排行榜 - */ - @GetMapping("/contract-ranking") - @Operation(summary = "合同金额排行榜") - @PreAuthorize("@ss.hasPermission('bi:ranking:query')") - public CommonResult> contractAmountRanking(BiRankingReqVO biRankingReqVO) { - return success(biRankingService.contractRanKing(biRankingReqVO)); - } - - /** - * 回款金额排行榜 - */ - @GetMapping("/receivables-ranking") - @Operation(summary = "回款金额排行榜") - @PreAuthorize("@ss.hasPermission('bi:ranking:query')") - public CommonResult> receivablesRanKing(BiRankingReqVO biRankingReqVO) { - return success(biRankingService.receivablesRanKing(biRankingReqVO)); - } - -} diff --git a/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/controller/admin/bi/CrmBiRankController.http b/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/controller/admin/bi/CrmBiRankController.http new file mode 100644 index 000000000..b9e9a4edf --- /dev/null +++ b/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/controller/admin/bi/CrmBiRankController.http @@ -0,0 +1,9 @@ +### 合同金额排行榜 +GET {{baseUrl}}/crm/bi-rank/get-contract-price-rank?deptId=100×[0]=2022-12-12 00:00:00×[1]=2024-12-12 23:59:59 +Authorization: Bearer {{token}} +tenant-id: {{adminTenentId}} + +### 回款金额排行榜 +GET {{baseUrl}}/crm/bi-rank/get-receivable-price-rank?deptId=100×[0]=2022-12-12 00:00:00×[1]=2024-12-12 23:59:59 +Authorization: Bearer {{token}} +tenant-id: {{adminTenentId}} \ No newline at end of file diff --git a/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/controller/admin/bi/CrmBiRankController.java b/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/controller/admin/bi/CrmBiRankController.java new file mode 100644 index 000000000..a188232ef --- /dev/null +++ b/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/controller/admin/bi/CrmBiRankController.java @@ -0,0 +1,45 @@ +package cn.iocoder.yudao.module.crm.controller.admin.bi; + +import cn.iocoder.yudao.framework.common.pojo.CommonResult; +import cn.iocoder.yudao.module.crm.controller.admin.bi.vo.CrmBiRanKRespVO; +import cn.iocoder.yudao.module.crm.controller.admin.bi.vo.CrmBiRankReqVO; +import cn.iocoder.yudao.module.crm.service.bi.CrmBiRankingService; +import io.swagger.v3.oas.annotations.Operation; +import io.swagger.v3.oas.annotations.tags.Tag; +import jakarta.annotation.Resource; +import jakarta.validation.Valid; +import org.springframework.security.access.prepost.PreAuthorize; +import org.springframework.validation.annotation.Validated; +import org.springframework.web.bind.annotation.GetMapping; +import org.springframework.web.bind.annotation.RequestMapping; +import org.springframework.web.bind.annotation.RestController; + +import java.util.List; + +import static cn.iocoder.yudao.framework.common.pojo.CommonResult.success; + + +@Tag(name = "管理后台 - CRM BI 排行榜") +@RestController +@RequestMapping("/crm/bi-rank") +@Validated +public class CrmBiRankController { + + @Resource + private CrmBiRankingService rankingService; + + @GetMapping("/get-contract-price-rank") + @Operation(summary = "获得合同金额排行榜") + @PreAuthorize("@ss.hasPermission('crm:bi-rank:query')") + public CommonResult> getContractPriceRank(@Valid CrmBiRankReqVO rankingReqVO) { + return success(rankingService.getContractPriceRank(rankingReqVO)); + } + + @GetMapping("/get-receivable-price-rank") + @Operation(summary = "获得回款金额排行榜") + @PreAuthorize("@ss.hasPermission('crm:bi-rank:query')") + public CommonResult> getReceivablePriceRank(@Valid CrmBiRankReqVO rankingReqVO) { + return success(rankingService.getReceivablePriceRank(rankingReqVO)); + } + +} diff --git a/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/controller/admin/bi/vo/BiParams.java b/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/controller/admin/bi/vo/BiParams.java deleted file mode 100644 index 0dee1c092..000000000 --- a/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/controller/admin/bi/vo/BiParams.java +++ /dev/null @@ -1,35 +0,0 @@ -package cn.iocoder.yudao.module.crm.controller.admin.bi.vo; - -import cn.iocoder.yudao.framework.common.pojo.PageParam; -import io.swagger.v3.oas.annotations.media.Schema; -import lombok.Data; -import lombok.EqualsAndHashCode; - -// TODO @anhaohao:这个类的命名,还是保持和其它一致使用 ReqVO 结尾;例如说,CrmStatisticsCommonParamReqVO -/** - * @author anhaohao - * bi参数 - */ -@EqualsAndHashCode(callSuper = true) -@Schema(description = "bi查询相关参数") -@Data -public class BiParams extends PageParam { - - @Schema(description = "部门ID") - private Long deptId; - - @Schema(description = "用户ID") - private Long userId; - - // TODO @anhaohao:这个字段,可以融合到 startTime、endTime 里去,交给前端计算哈; - @Schema(description = "类型") - private String type; - - // TODO @anhaohao:还是使用 LocalDateTime - @Schema(description = "开始时间") - private String startTime; - - @Schema(description = "结束时间") - private String endTime; - -} diff --git a/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/controller/admin/bi/vo/BiRankingReqVO.java b/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/controller/admin/bi/vo/BiRankingReqVO.java deleted file mode 100644 index 06b013333..000000000 --- a/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/controller/admin/bi/vo/BiRankingReqVO.java +++ /dev/null @@ -1,35 +0,0 @@ -package cn.iocoder.yudao.module.crm.controller.admin.bi.vo; - -import io.swagger.v3.oas.annotations.media.Schema; -import lombok.Data; -import org.springframework.format.annotation.DateTimeFormat; - -import java.time.LocalDateTime; -import java.util.List; - -import static cn.iocoder.yudao.framework.common.util.date.DateUtils.FORMAT_YEAR_MONTH_DAY_HOUR_MINUTE_SECOND; - -/** - * 管理后台 - 排行榜 Request VO - * - * @author anhaohao - */ -@Schema(description = "管理后台 - 排行榜 Request VO") -@Data -public class BiRankingReqVO { - - @Schema(description = "部门id", requiredMode = Schema.RequiredMode.REQUIRED, example = "1") - private Long deptId; - - @Schema(description = "开始时间", requiredMode = Schema.RequiredMode.REQUIRED, example = "2023-12-12 00:00:00") - @DateTimeFormat(pattern = FORMAT_YEAR_MONTH_DAY_HOUR_MINUTE_SECOND) - private LocalDateTime startTime; - - @Schema(description = "结束时间", requiredMode = Schema.RequiredMode.REQUIRED, example = "2023-12-12 23:59:59") - @DateTimeFormat(pattern = FORMAT_YEAR_MONTH_DAY_HOUR_MINUTE_SECOND) - private LocalDateTime endTime; - - @Schema(description = "负责人用户 id 集合", requiredMode = Schema.RequiredMode.NOT_REQUIRED, example = "1") - private List userIds; - -} diff --git a/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/controller/admin/bi/vo/BiRanKingRespVO.java b/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/controller/admin/bi/vo/CrmBiRanKRespVO.java similarity index 51% rename from yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/controller/admin/bi/vo/BiRanKingRespVO.java rename to yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/controller/admin/bi/vo/CrmBiRanKRespVO.java index 8aef25b96..404ee3352 100644 --- a/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/controller/admin/bi/vo/BiRanKingRespVO.java +++ b/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/controller/admin/bi/vo/CrmBiRanKRespVO.java @@ -4,12 +4,12 @@ import io.swagger.v3.oas.annotations.media.Schema; import lombok.Data; -@Schema(description = "管理后台 - BI 排行榜 Response VO") +@Schema(description = "管理后台 - CRM BI 排行榜 Response VO") @Data -public class BiRanKingRespVO { +public class CrmBiRanKRespVO { - @Schema(description = "金额", requiredMode = Schema.RequiredMode.REQUIRED, example = "1") - private Integer price; + @Schema(description = "负责人编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "1") + private Long ownerUserId; @Schema(description = "姓名", requiredMode = Schema.RequiredMode.REQUIRED, example = "1") private String nickname; @@ -17,7 +17,13 @@ public class BiRanKingRespVO { @Schema(description = "部门名称", requiredMode = Schema.RequiredMode.REQUIRED, example = "1") private String deptName; - @Schema(description = "负责人编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "1") - private Long ownerUserId; + /** + * 数量是个特别“抽象”的概念,在不同排行下,代表不同含义 + * + * 1. 金额:合同金额排行、回款金额排行 + * 2. 个数:签约合同排行、产品销量排行、产品销量排行、新增客户数排行、新增联系人排行、跟进次数排行、跟进客户数排行 + */ + @Schema(description = "数量", requiredMode = Schema.RequiredMode.REQUIRED, example = "1") + private Integer count; } diff --git a/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/controller/admin/bi/vo/CrmBiRankReqVO.java b/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/controller/admin/bi/vo/CrmBiRankReqVO.java new file mode 100644 index 000000000..6d36f6d6f --- /dev/null +++ b/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/controller/admin/bi/vo/CrmBiRankReqVO.java @@ -0,0 +1,35 @@ +package cn.iocoder.yudao.module.crm.controller.admin.bi.vo; + +import io.swagger.v3.oas.annotations.media.Schema; +import jakarta.validation.constraints.NotEmpty; +import jakarta.validation.constraints.NotNull; +import lombok.Data; +import org.springframework.format.annotation.DateTimeFormat; + +import java.time.LocalDateTime; +import java.util.List; + +import static cn.iocoder.yudao.framework.common.util.date.DateUtils.FORMAT_YEAR_MONTH_DAY_HOUR_MINUTE_SECOND; + +@Schema(description = "管理后台 - CRM BI 排行榜 Request VO") +@Data +public class CrmBiRankReqVO { + + @Schema(description = "部门 id", requiredMode = Schema.RequiredMode.REQUIRED, example = "1") + @NotNull(message = "部门 id 不能为空") + private Long deptId; + + /** + * userIds 目前不用前端传递,目前是方便后端通过 deptId 读取编号后,设置回来 + * + * 后续,可能会支持选择部分用户进行查询 + */ + @Schema(description = "负责人用户 id 集合", requiredMode = Schema.RequiredMode.NOT_REQUIRED, example = "2") + private List userIds; + + @Schema(description = "时间范围", requiredMode = Schema.RequiredMode.REQUIRED) + @DateTimeFormat(pattern = FORMAT_YEAR_MONTH_DAY_HOUR_MINUTE_SECOND) + @NotEmpty(message = "时间范围不能为空") + private LocalDateTime[] times; + +} diff --git a/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/controller/admin/contract/CrmContractController.java b/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/controller/admin/contract/CrmContractController.java index b259e7bad..328695b8b 100644 --- a/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/controller/admin/contract/CrmContractController.java +++ b/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/controller/admin/contract/CrmContractController.java @@ -45,7 +45,6 @@ import static cn.iocoder.yudao.framework.security.core.util.SecurityFrameworkUti public class CrmContractController { @Resource - @Lazy private CrmContractService contractService; @Resource private CrmCustomerService customerService; diff --git a/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/controller/admin/receivable/CrmReceivableController.java b/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/controller/admin/receivable/CrmReceivableController.java index 020b84c56..8516ebd66 100644 --- a/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/controller/admin/receivable/CrmReceivableController.java +++ b/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/controller/admin/receivable/CrmReceivableController.java @@ -26,7 +26,6 @@ import io.swagger.v3.oas.annotations.tags.Tag; import jakarta.annotation.Resource; import jakarta.servlet.http.HttpServletResponse; import jakarta.validation.Valid; -import org.springframework.context.annotation.Lazy; import org.springframework.security.access.prepost.PreAuthorize; import org.springframework.validation.annotation.Validated; import org.springframework.web.bind.annotation.*; @@ -52,7 +51,6 @@ public class CrmReceivableController { @Resource private CrmReceivableService receivableService; @Resource - @Lazy private CrmContractService contractService; @Resource private CrmCustomerService customerService; diff --git a/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/dal/mysql/bi/BiRankingMapper.java b/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/dal/mysql/bi/BiRankingMapper.java deleted file mode 100644 index a35e80777..000000000 --- a/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/dal/mysql/bi/BiRankingMapper.java +++ /dev/null @@ -1,31 +0,0 @@ -package cn.iocoder.yudao.module.crm.dal.mysql.bi; - -import cn.iocoder.yudao.framework.mybatis.core.mapper.BaseMapperX; -import cn.iocoder.yudao.module.crm.controller.admin.bi.vo.BiRanKingRespVO; -import cn.iocoder.yudao.module.crm.controller.admin.bi.vo.BiRankingReqVO; -import org.apache.ibatis.annotations.Mapper; - -import java.util.List; - -/** - * @author anhaohao - */ -@Mapper -public interface BiRankingMapper extends BaseMapperX { - /** - * 合同金额排行榜 - * - * @param biRankingReqVO 参数 - * @return List - */ - List contractRanKing(BiRankingReqVO biRankingReqVO); - - - /** - * 回款金额排行榜 - * - * @param biRankingReqVO 参数 - * @return List - */ - List receivablesRanKing(BiRankingReqVO biRankingReqVO); -} diff --git a/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/dal/mysql/bi/CrmBiRankingMapper.java b/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/dal/mysql/bi/CrmBiRankingMapper.java new file mode 100644 index 000000000..91b7a191b --- /dev/null +++ b/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/dal/mysql/bi/CrmBiRankingMapper.java @@ -0,0 +1,33 @@ +package cn.iocoder.yudao.module.crm.dal.mysql.bi; + +import cn.iocoder.yudao.module.crm.controller.admin.bi.vo.CrmBiRanKRespVO; +import cn.iocoder.yudao.module.crm.controller.admin.bi.vo.CrmBiRankReqVO; +import org.apache.ibatis.annotations.Mapper; + +import java.util.List; + +/** + * CRM BI 排行榜 Mapper + * + * @author anhaohao + */ +@Mapper +public interface CrmBiRankingMapper { + + /** + * 查询合同金额排行榜 + * + * @param rankReqVO 参数 + * @return 合同金额排行榜 + */ + List selectContractPriceRank(CrmBiRankReqVO rankReqVO); + + /** + * 查询回款金额排行榜 + * + * @param rankReqVO 参数 + * @return 回款金额排行榜 + */ + List selectReceivablePriceRank(CrmBiRankReqVO rankReqVO); + +} diff --git a/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/framework/operatelog/core/CrmContractParseFunction.java b/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/framework/operatelog/core/CrmContractParseFunction.java index 812417bf2..d3c58522e 100644 --- a/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/framework/operatelog/core/CrmContractParseFunction.java +++ b/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/framework/operatelog/core/CrmContractParseFunction.java @@ -6,7 +6,6 @@ import cn.iocoder.yudao.module.crm.service.contract.CrmContractService; import com.mzt.logapi.service.IParseFunction; import jakarta.annotation.Resource; import lombok.extern.slf4j.Slf4j; -import org.springframework.context.annotation.Lazy; import org.springframework.stereotype.Component; /** @@ -21,7 +20,6 @@ public class CrmContractParseFunction implements IParseFunction { public static final String NAME = "getContractById"; @Resource - @Lazy private CrmContractService contractService; @Override diff --git a/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/service/bi/BiRankingService.java b/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/service/bi/BiRankingService.java deleted file mode 100644 index 17c9722de..000000000 --- a/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/service/bi/BiRankingService.java +++ /dev/null @@ -1,31 +0,0 @@ -package cn.iocoder.yudao.module.crm.service.bi; - - -import cn.iocoder.yudao.module.crm.controller.admin.bi.vo.BiRanKingRespVO; -import cn.iocoder.yudao.module.crm.controller.admin.bi.vo.BiRankingReqVO; - -import java.util.List; - -/** - * BI 排行榜 Service 接口 - * - * @author anhaohao - */ -public interface BiRankingService { - - /** - * 合同金额排行榜 - * - * @param biRankingReqVO 参数 - * @return List - */ - List contractRanKing(BiRankingReqVO biRankingReqVO); - - /** - * 回款金额排行榜 - * - * @param biRankingReqVO 参数 - * @return List - */ - List receivablesRanKing(BiRankingReqVO biRankingReqVO); -} diff --git a/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/service/bi/BiRankingServiceImpl.java b/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/service/bi/BiRankingServiceImpl.java deleted file mode 100644 index 9a6534067..000000000 --- a/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/service/bi/BiRankingServiceImpl.java +++ /dev/null @@ -1,93 +0,0 @@ -package cn.iocoder.yudao.module.crm.service.bi; - -import cn.iocoder.yudao.framework.security.core.util.SecurityFrameworkUtils; - -import cn.iocoder.yudao.module.crm.controller.admin.bi.vo.BiRanKingRespVO; -import cn.iocoder.yudao.module.crm.controller.admin.bi.vo.BiRankingReqVO; -import cn.iocoder.yudao.module.crm.dal.mysql.bi.BiRankingMapper; -import cn.iocoder.yudao.module.system.api.dept.DeptApi; -import cn.iocoder.yudao.module.system.api.dept.dto.DeptRespDTO; -import cn.iocoder.yudao.module.system.api.user.AdminUserApi; -import cn.iocoder.yudao.module.system.api.user.dto.AdminUserRespDTO; -import jakarta.annotation.Resource; -import org.springframework.stereotype.Service; -import org.springframework.validation.annotation.Validated; - -import java.util.ArrayList; -import java.util.List; -import java.util.Map; -import java.util.function.Function; -import java.util.stream.Collectors; - -@Service(value = "biRankingService") -@Validated -public class BiRankingServiceImpl implements BiRankingService { - - @Resource - private BiRankingMapper biRankingMapper; - @Resource - private AdminUserApi adminUserApi; - @Resource - private DeptApi deptApi; - - @Override - public List contractRanKing(BiRankingReqVO biRankingReqVO) { - return processRanking(biRankingReqVO, biRankingMapper::contractRanKing); - } - - @Override - public List receivablesRanKing(BiRankingReqVO biRankingReqVO) { - return processRanking(biRankingReqVO, biRankingMapper::receivablesRanKing); - } - - /** - * 处理排行榜 - * - * @param biRankingReqVO 参数 - * @param rankingFunction 排行榜方法 - * @return List - */ - private List processRanking(BiRankingReqVO biRankingReqVO, Function> rankingFunction) { - analyzeAuth(biRankingReqVO); - if (biRankingReqVO.getUserIds().isEmpty()) { - return new ArrayList<>(); - } - List biRanKingRespVOS = rankingFunction.apply(biRankingReqVO); - return setName(biRanKingRespVOS); - } - - /** - * 设置用户名称 - * - * @param biRanKingRespVOS 排行榜数据 - * @return List - */ - private List setName(List biRanKingRespVOS) { - List userIds = biRanKingRespVOS.stream().map(BiRanKingRespVO::getOwnerUserId).collect(Collectors.toList()); - Map userMap = adminUserApi.getUserMap(userIds); - Map deptMap = deptApi.getDeptMap(userMap.values().stream().map(AdminUserRespDTO::getDeptId).collect(Collectors.toList())); - for (BiRanKingRespVO biRanKingRespVO : biRanKingRespVOS) { - AdminUserRespDTO adminUserRespDTO = userMap.get(biRanKingRespVO.getOwnerUserId()); - if (adminUserRespDTO != null) { - biRanKingRespVO.setNickname(adminUserRespDTO.getNickname()); - DeptRespDTO deptRespDTO = deptMap.get(adminUserRespDTO.getDeptId()); - if (deptRespDTO != null) { - biRanKingRespVO.setDeptName(deptRespDTO.getName()); - } - } - } - return biRanKingRespVOS; - } - - /** - * 分析权限 - * - * @param biRankingReqVO 参数 - */ - public void analyzeAuth(BiRankingReqVO biRankingReqVO) { - Long deptId = biRankingReqVO.getDeptId() == null ? adminUserApi.getUser(SecurityFrameworkUtils.getLoginUserId()).getDeptId() : biRankingReqVO.getDeptId(); - List deptIds = deptApi.getChildDeptList(deptId).stream().map(DeptRespDTO::getId).collect(Collectors.toList()); - deptIds.add(deptId); - biRankingReqVO.setUserIds(adminUserApi.getUserListByDeptIds(deptIds).stream().map(AdminUserRespDTO::getId).collect(Collectors.toList())); - } -} \ No newline at end of file diff --git a/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/service/bi/CrmBiRankingService.java b/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/service/bi/CrmBiRankingService.java new file mode 100644 index 000000000..72d1d6f97 --- /dev/null +++ b/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/service/bi/CrmBiRankingService.java @@ -0,0 +1,32 @@ +package cn.iocoder.yudao.module.crm.service.bi; + + +import cn.iocoder.yudao.module.crm.controller.admin.bi.vo.CrmBiRanKRespVO; +import cn.iocoder.yudao.module.crm.controller.admin.bi.vo.CrmBiRankReqVO; + +import java.util.List; + +/** + * CRM BI 排行榜 Service 接口 + * + * @author anhaohao + */ +public interface CrmBiRankingService { + + /** + * 获得合同金额排行榜 + * + * @param rankReqVO 排行参数 + * @return 合同金额排行榜 + */ + List getContractPriceRank(CrmBiRankReqVO rankReqVO); + + /** + * 获得回款金额排行榜 + * + * @param rankReqVO 排行参数 + * @return 回款金额排行榜 + */ + List getReceivablePriceRank(CrmBiRankReqVO rankReqVO); + +} diff --git a/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/service/bi/CrmBiRankingServiceImpl.java b/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/service/bi/CrmBiRankingServiceImpl.java new file mode 100644 index 000000000..84f47ddc9 --- /dev/null +++ b/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/service/bi/CrmBiRankingServiceImpl.java @@ -0,0 +1,104 @@ +package cn.iocoder.yudao.module.crm.service.bi; + +import cn.hutool.core.collection.CollUtil; +import cn.iocoder.yudao.framework.common.util.collection.MapUtils; +import cn.iocoder.yudao.module.crm.controller.admin.bi.vo.CrmBiRanKRespVO; +import cn.iocoder.yudao.module.crm.controller.admin.bi.vo.CrmBiRankReqVO; +import cn.iocoder.yudao.module.crm.dal.mysql.bi.CrmBiRankingMapper; +import cn.iocoder.yudao.module.system.api.dept.DeptApi; +import cn.iocoder.yudao.module.system.api.dept.dto.DeptRespDTO; +import cn.iocoder.yudao.module.system.api.user.AdminUserApi; +import cn.iocoder.yudao.module.system.api.user.dto.AdminUserRespDTO; +import jakarta.annotation.Resource; +import org.springframework.stereotype.Service; +import org.springframework.validation.annotation.Validated; + +import java.util.Collections; +import java.util.Comparator; +import java.util.List; +import java.util.Map; +import java.util.function.Function; + +import static cn.iocoder.yudao.framework.common.util.collection.CollectionUtils.convertList; +import static cn.iocoder.yudao.framework.common.util.collection.CollectionUtils.convertSet; + +/** + * CRM BI 排行榜 Service 实现类 + * + * @author anhaohao + */ +@Service +@Validated +public class CrmBiRankingServiceImpl implements CrmBiRankingService { + + @Resource + private CrmBiRankingMapper biRankingMapper; + + @Resource + private AdminUserApi adminUserApi; + @Resource + private DeptApi deptApi; + + @Override + public List getContractPriceRank(CrmBiRankReqVO rankReqVO) { + return getRank(rankReqVO, biRankingMapper::selectContractPriceRank); + } + + @Override + public List getReceivablePriceRank(CrmBiRankReqVO rankReqVO) { + return getRank(rankReqVO, biRankingMapper::selectReceivablePriceRank); + } + + /** + * 获得排行版数据 + * + * @param rankReqVO 参数 + * @param rankFunction 排行榜方法 + * @return 排行版数据 + */ + private List getRank(CrmBiRankReqVO rankReqVO, Function> rankFunction) { + // 1. 获得用户编号数组 + rankReqVO.setUserIds(getUserIds(rankReqVO.getDeptId())); + if (CollUtil.isEmpty(rankReqVO.getUserIds())) { + return Collections.emptyList(); + } + // 2. 获得排行数据 + List ranks = rankFunction.apply(rankReqVO); + if (CollUtil.isEmpty(ranks)) { + return Collections.emptyList(); + } + ranks.sort(Comparator.comparing(CrmBiRanKRespVO::getCount).reversed()); + // 3. 拼接用户信息 + appendUserInfo(ranks); + return ranks; + } + + /** + * 拼接用户信息(昵称、部门) + * + * @param ranks 排行榜数据 + */ + private void appendUserInfo(List ranks) { + Map userMap = adminUserApi.getUserMap(convertSet(ranks, CrmBiRanKRespVO::getOwnerUserId)); + Map deptMap = deptApi.getDeptMap(convertSet(userMap.values(), AdminUserRespDTO::getDeptId)); + ranks.forEach(rank -> MapUtils.findAndThen(userMap, rank.getOwnerUserId(), user -> { + rank.setNickname(user.getNickname()); + MapUtils.findAndThen(deptMap, user.getDeptId(), dept -> rank.setDeptName(dept.getName())); + })); + } + + /** + * 获得部门下的用户编号数组,包括子部门的 + * + * @param deptId 部门编号 + * @return 用户编号数组 + */ + public List getUserIds(Long deptId) { + // 1. 获得部门列表 + List deptIds = convertList(deptApi.getChildDeptList(deptId), DeptRespDTO::getId); + deptIds.add(deptId); + // 2. 获得用户编号 + return convertList(adminUserApi.getUserListByDeptIds(deptIds), AdminUserRespDTO::getId); + } + +} \ No newline at end of file diff --git a/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/service/business/CrmBusinessServiceImpl.java b/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/service/business/CrmBusinessServiceImpl.java index 877971435..aa0839d12 100644 --- a/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/service/business/CrmBusinessServiceImpl.java +++ b/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/service/business/CrmBusinessServiceImpl.java @@ -57,7 +57,7 @@ public class CrmBusinessServiceImpl implements CrmBusinessService { @Resource private CrmBusinessProductService businessProductService; @Resource - @Lazy + @Lazy // 延迟加载,避免循环依赖 private CrmContractService contractService; @Resource private CrmPermissionService permissionService; diff --git a/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/service/contact/CrmContactServiceImpl.java b/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/service/contact/CrmContactServiceImpl.java index 4c1a7fd95..52f2d6cf7 100644 --- a/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/service/contact/CrmContactServiceImpl.java +++ b/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/service/contact/CrmContactServiceImpl.java @@ -25,7 +25,6 @@ import com.mzt.logapi.context.LogRecordContext; import com.mzt.logapi.service.impl.DiffParseFunction; import com.mzt.logapi.starter.annotation.LogRecord; 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; @@ -57,7 +56,6 @@ public class CrmContactServiceImpl implements CrmContactService { @Resource private CrmPermissionService permissionService; @Resource - @Lazy private CrmContractService contractService; @Resource private CrmContactBusinessService contactBusinessService; diff --git a/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/service/receivable/CrmReceivablePlanServiceImpl.java b/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/service/receivable/CrmReceivablePlanServiceImpl.java index c4008590c..9ac2e7f43 100644 --- a/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/service/receivable/CrmReceivablePlanServiceImpl.java +++ b/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/service/receivable/CrmReceivablePlanServiceImpl.java @@ -50,7 +50,6 @@ public class CrmReceivablePlanServiceImpl implements CrmReceivablePlanService { private CrmReceivablePlanMapper receivablePlanMapper; @Resource - @Lazy private CrmContractService contractService; @Resource private CrmCustomerService customerService; diff --git a/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/service/receivable/CrmReceivableServiceImpl.java b/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/service/receivable/CrmReceivableServiceImpl.java index b0777787f..effe0d720 100644 --- a/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/service/receivable/CrmReceivableServiceImpl.java +++ b/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/service/receivable/CrmReceivableServiceImpl.java @@ -51,7 +51,6 @@ public class CrmReceivableServiceImpl implements CrmReceivableService { private CrmReceivableMapper receivableMapper; @Resource - @Lazy private CrmContractService contractService; @Resource private CrmCustomerService customerService; diff --git a/yudao-module-crm/yudao-module-crm-biz/src/main/resources/mapper/bi/BiRankingMapper.xml b/yudao-module-crm/yudao-module-crm-biz/src/main/resources/mapper/bi/BiRankingMapper.xml deleted file mode 100644 index 9ebcbda0e..000000000 --- a/yudao-module-crm/yudao-module-crm-biz/src/main/resources/mapper/bi/BiRankingMapper.xml +++ /dev/null @@ -1,35 +0,0 @@ - - - - - - - - - diff --git a/yudao-module-crm/yudao-module-crm-biz/src/main/resources/mapper/bi/CrmBiRankingMapper.xml b/yudao-module-crm/yudao-module-crm-biz/src/main/resources/mapper/bi/CrmBiRankingMapper.xml new file mode 100644 index 000000000..ef90bb564 --- /dev/null +++ b/yudao-module-crm/yudao-module-crm-biz/src/main/resources/mapper/bi/CrmBiRankingMapper.xml @@ -0,0 +1,33 @@ + + + + + + + + + diff --git a/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/controller/admin/auth/vo/AuthPermissionInfoRespVO.java b/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/controller/admin/auth/vo/AuthPermissionInfoRespVO.java index 54aaa4dc7..c26acb8ca 100644 --- a/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/controller/admin/auth/vo/AuthPermissionInfoRespVO.java +++ b/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/controller/admin/auth/vo/AuthPermissionInfoRespVO.java @@ -44,6 +44,9 @@ public class AuthPermissionInfoRespVO { @Schema(description = "用户头像", requiredMode = Schema.RequiredMode.REQUIRED, example = "https://www.iocoder.cn/xx.jpg") private String avatar; + @Schema(description = "部门编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "2048") + private Long deptId; + } @Schema(description = "管理后台 - 登录用户的菜单信息 Response VO") diff --git a/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/convert/auth/AuthConvert.java b/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/convert/auth/AuthConvert.java index 8343547d9..18463e7f6 100644 --- a/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/convert/auth/AuthConvert.java +++ b/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/convert/auth/AuthConvert.java @@ -1,6 +1,7 @@ package cn.iocoder.yudao.module.system.convert.auth; import cn.hutool.core.collection.CollUtil; +import cn.iocoder.yudao.framework.common.util.object.BeanUtils; import cn.iocoder.yudao.module.system.api.sms.dto.code.SmsCodeSendReqDTO; import cn.iocoder.yudao.module.system.api.sms.dto.code.SmsCodeUseReqDTO; import cn.iocoder.yudao.module.system.api.social.dto.SocialUserBindReqDTO; @@ -29,7 +30,7 @@ public interface AuthConvert { default AuthPermissionInfoRespVO convert(AdminUserDO user, List roleList, List menuList) { return AuthPermissionInfoRespVO.builder() - .user(AuthPermissionInfoRespVO.UserVO.builder().id(user.getId()).nickname(user.getNickname()).avatar(user.getAvatar()).build()) + .user(BeanUtils.toBean(user, AuthPermissionInfoRespVO.UserVO.class)) .roles(convertSet(roleList, RoleDO::getCode)) // 权限标识信息 .permissions(convertSet(menuList, MenuDO::getPermission)) diff --git a/yudao-server/pom.xml b/yudao-server/pom.xml index 7c288f725..ff17b298d 100644 --- a/yudao-server/pom.xml +++ b/yudao-server/pom.xml @@ -46,11 +46,11 @@ - - - - - + + cn.iocoder.boot + yudao-module-bpm-biz + ${revision} + From 59e6f23788af5cd79888eaeada5519b5f952a2ed Mon Sep 17 00:00:00 2001 From: puhui999 Date: Sat, 3 Feb 2024 12:29:28 +0800 Subject: [PATCH 058/119] =?UTF-8?q?CRM-CONTRACT:=20=E5=AE=8C=E5=96=84=20TO?= =?UTF-8?q?DO?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../common/util/number/MoneyUtils.java | 16 ++++ .../admin/definition/BpmModelController.java | 2 +- .../module/crm/enums/ErrorCodeConstants.java | 1 + .../module/crm/enums/LogRecordConstants.java | 2 + .../admin/contract/CrmContractController.java | 14 ++- .../contract/vo/CrmContractSaveReqVO.java | 3 - .../business/CrmBusinessProductDO.java | 7 ++ .../dal/dataobject/product/CrmProductDO.java | 2 +- .../dal/mysql/customer/CrmCustomerMapper.java | 3 +- .../business/CrmBusinessProductService.java | 17 +++- .../CrmBusinessProductServiceImpl.java | 7 +- .../business/CrmBusinessServiceImpl.java | 2 +- .../service/contract/CrmContractService.java | 5 +- .../contract/CrmContractServiceImpl.java | 92 +++++++++++-------- .../listener/CrmContractResultListener.java | 28 ++++++ .../customer/CrmCustomerServiceImpl.java | 41 ++++++--- 16 files changed, 171 insertions(+), 71 deletions(-) diff --git a/yudao-framework/yudao-common/src/main/java/cn/iocoder/yudao/framework/common/util/number/MoneyUtils.java b/yudao-framework/yudao-common/src/main/java/cn/iocoder/yudao/framework/common/util/number/MoneyUtils.java index e0b739920..ccfeb3917 100644 --- a/yudao-framework/yudao-common/src/main/java/cn/iocoder/yudao/framework/common/util/number/MoneyUtils.java +++ b/yudao-framework/yudao-common/src/main/java/cn/iocoder/yudao/framework/common/util/number/MoneyUtils.java @@ -35,6 +35,22 @@ public class MoneyUtils { return calculateRatePrice(price, rate, 0, RoundingMode.FLOOR).intValue(); } + /** + * 计算百分比金额 + * + * @param price 金额(单位分) + * @param count 数量 + * @param percent 折扣(单位分),列如 60.2%,则传入 6020 + * @return 商品总价 + */ + public static Integer calculator(Integer price, Integer count, Integer percent) { + price = price * count; + if (percent == null) { + return price; + } + return MoneyUtils.calculateRatePriceFloor(price, (double) (percent / 100)); + } + /** * 计算百分比金额 * diff --git a/yudao-module-bpm/yudao-module-bpm-biz/src/main/java/cn/iocoder/yudao/module/bpm/controller/admin/definition/BpmModelController.java b/yudao-module-bpm/yudao-module-bpm-biz/src/main/java/cn/iocoder/yudao/module/bpm/controller/admin/definition/BpmModelController.java index 861698ac0..32b073c4b 100644 --- a/yudao-module-bpm/yudao-module-bpm-biz/src/main/java/cn/iocoder/yudao/module/bpm/controller/admin/definition/BpmModelController.java +++ b/yudao-module-bpm/yudao-module-bpm-biz/src/main/java/cn/iocoder/yudao/module/bpm/controller/admin/definition/BpmModelController.java @@ -43,7 +43,7 @@ public class BpmModelController { return success(model); } - // TODO @puhui999:这个接口的目的是啥呀? + // TODO @puhui999:这个接口的目的是啥呀?业务表单预览流程🤣 @GetMapping("/get-by-key") @Operation(summary = "获得模型") @Parameter(name = "key", description = "流程标识", required = true, example = "oa_leave") diff --git a/yudao-module-crm/yudao-module-crm-api/src/main/java/cn/iocoder/yudao/module/crm/enums/ErrorCodeConstants.java b/yudao-module-crm/yudao-module-crm-api/src/main/java/cn/iocoder/yudao/module/crm/enums/ErrorCodeConstants.java index 9190880fa..d536d8a40 100644 --- a/yudao-module-crm/yudao-module-crm-api/src/main/java/cn/iocoder/yudao/module/crm/enums/ErrorCodeConstants.java +++ b/yudao-module-crm/yudao-module-crm-api/src/main/java/cn/iocoder/yudao/module/crm/enums/ErrorCodeConstants.java @@ -12,6 +12,7 @@ public interface ErrorCodeConstants { // ========== 合同管理 1-020-000-000 ========== ErrorCode CONTRACT_NOT_EXISTS = new ErrorCode(1_020_000_000, "合同不存在"); ErrorCode CONTRACT_UPDATE_FAIL_EDITING_PROHIBITED = new ErrorCode(1_020_000_001, "更新合同失败,原因:禁止编辑"); + ErrorCode CONTRACT_SUBMIT_FAIL_NOT_DRAFT = new ErrorCode(1_020_000_002, "合同提交审核失败,原因:合同没处在未提交状态"); // ========== 线索管理 1-020-001-000 ========== ErrorCode CLUE_NOT_EXISTS = new ErrorCode(1_020_001_000, "线索不存在"); diff --git a/yudao-module-crm/yudao-module-crm-api/src/main/java/cn/iocoder/yudao/module/crm/enums/LogRecordConstants.java b/yudao-module-crm/yudao-module-crm-api/src/main/java/cn/iocoder/yudao/module/crm/enums/LogRecordConstants.java index a0b4559ef..d22e87bed 100644 --- a/yudao-module-crm/yudao-module-crm-api/src/main/java/cn/iocoder/yudao/module/crm/enums/LogRecordConstants.java +++ b/yudao-module-crm/yudao-module-crm-api/src/main/java/cn/iocoder/yudao/module/crm/enums/LogRecordConstants.java @@ -39,6 +39,8 @@ public interface LogRecordConstants { String CRM_CUSTOMER_POOL_SUCCESS = "将客户【{{#customerName}}】放入了公海"; String CRM_CUSTOMER_RECEIVE_SUB_TYPE = "{{#ownerUserName != null ? '分配客户' : '领取客户'}}"; String CRM_CUSTOMER_RECEIVE_SUCCESS = "{{#ownerUserName != null ? '将客户【' + #customer.name + '】分配给【' + #ownerUserName + '】' : '领取客户【' + #customer.name + '】'}}"; + String CRM_CUSTOMER_IMPORT_SUB_TYPE = "{{#isUpdate ? '导入并更新客户' : '导入客户'}}"; + String CRM_CUSTOMER_IMPORT_SUCCESS = "{{#isUpdate ? '导入并更新了客户【'+ #customer.name +'】' : '导入了客户【'+ #customer.name +'】'}}"; // ======================= CRM_CUSTOMER_LIMIT_CONFIG 客户限制配置 ======================= diff --git a/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/controller/admin/contract/CrmContractController.java b/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/controller/admin/contract/CrmContractController.java index 28c71c4e2..d9b181029 100644 --- a/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/controller/admin/contract/CrmContractController.java +++ b/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/controller/admin/contract/CrmContractController.java @@ -132,21 +132,19 @@ public class CrmContractController { return CrmContractConvert.INSTANCE.convertPage(pageResult, userMap, customerList); } - // TODO @puhui999:transferContract - @PutMapping("/transfer") + @PutMapping("/transfer-contract") @Operation(summary = "合同转移") @PreAuthorize("@ss.hasPermission('crm:contract:update')") - public CommonResult transfer(@Valid @RequestBody CrmContractTransferReqVO reqVO) { + public CommonResult transferContract(@Valid @RequestBody CrmContractTransferReqVO reqVO) { contractService.transferContract(reqVO, getLoginUserId()); return success(true); } - // TODO @puhui999:方法名不对哈;要不改成 submit?提交审核的意思 - @PutMapping("/approve") - @Operation(summary = "发起合同审批流程") + @PutMapping("/submit") + @Operation(summary = "提交合同审批") @PreAuthorize("@ss.hasPermission('crm:contract:update')") - public CommonResult transfer(@RequestParam("id") Long id) { - contractService.handleApprove(id, getLoginUserId()); + public CommonResult submitContract(@RequestParam("id") Long id) { + contractService.submitContract(id, getLoginUserId()); return success(true); } diff --git a/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/controller/admin/contract/vo/CrmContractSaveReqVO.java b/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/controller/admin/contract/vo/CrmContractSaveReqVO.java index f1ab8c581..a2908a3ac 100644 --- a/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/controller/admin/contract/vo/CrmContractSaveReqVO.java +++ b/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/controller/admin/contract/vo/CrmContractSaveReqVO.java @@ -89,9 +89,6 @@ public class CrmContractSaveReqVO { @DiffLogField(name = "备注") private String remark; - // TODO @puhui999:这个字段,按道理不用传递? - @Schema(description = "审批状态", example = "1") - private Integer auditStatus; @Schema(description = "产品列表") private List productItems; diff --git a/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/dal/dataobject/business/CrmBusinessProductDO.java b/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/dal/dataobject/business/CrmBusinessProductDO.java index 83121dbdd..2d801ff5b 100644 --- a/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/dal/dataobject/business/CrmBusinessProductDO.java +++ b/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/dal/dataobject/business/CrmBusinessProductDO.java @@ -1,6 +1,7 @@ package cn.iocoder.yudao.module.crm.dal.dataobject.business; import cn.iocoder.yudao.framework.mybatis.core.dataobject.BaseDO; +import cn.iocoder.yudao.module.crm.dal.dataobject.contract.CrmContractDO; import cn.iocoder.yudao.module.crm.dal.dataobject.product.CrmProductDO; import cn.iocoder.yudao.module.crm.enums.DictTypeConstants; import com.baomidou.mybatisplus.annotation.KeySequence; @@ -40,6 +41,12 @@ public class CrmBusinessProductDO extends BaseDO { * 关联 {@link CrmProductDO#getId()} */ private Long productId; + /** + * 合同编号 + * + * 关联 {@link CrmContractDO#getId()} + */ + private Long contractId; /** * 产品单价 diff --git a/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/dal/dataobject/product/CrmProductDO.java b/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/dal/dataobject/product/CrmProductDO.java index 6523782dd..a3c56ccc9 100644 --- a/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/dal/dataobject/product/CrmProductDO.java +++ b/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/dal/dataobject/product/CrmProductDO.java @@ -45,7 +45,7 @@ public class CrmProductDO extends BaseDO { /** * 价格,单位:分 */ - private Long price; + private Integer price; /** * 状态 * diff --git a/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/dal/mysql/customer/CrmCustomerMapper.java b/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/dal/mysql/customer/CrmCustomerMapper.java index 14732641d..29cd47c66 100644 --- a/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/dal/mysql/customer/CrmCustomerMapper.java +++ b/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/dal/mysql/customer/CrmCustomerMapper.java @@ -101,10 +101,9 @@ public interface CrmCustomerMapper extends BaseMapperX { return selectJoinPage(pageReqVO, CrmCustomerDO.class, query); } - default List selectListByLockAndDealStatusAndNotPool(Boolean lockStatus, Boolean dealStatus) { + default List selectListByLockAndNotPool(Boolean lockStatus) { return selectList(new LambdaQueryWrapper() .eq(CrmCustomerDO::getLockStatus, lockStatus) - .eq(CrmCustomerDO::getDealStatus, dealStatus) .gt(CrmCustomerDO::getOwnerUserId, 0)); } diff --git a/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/service/business/CrmBusinessProductService.java b/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/service/business/CrmBusinessProductService.java index 010be4a92..f5a040488 100644 --- a/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/service/business/CrmBusinessProductService.java +++ b/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/service/business/CrmBusinessProductService.java @@ -5,6 +5,7 @@ import cn.iocoder.yudao.module.crm.dal.dataobject.business.CrmBusinessProductDO; import java.util.List; // TODO @lzxhqs:方法名上,带下 BusinessProduct;主要考虑不精简的原因,是因为一个逻辑,可能会出现一些超越它自身方法,省略不容易懂; + /** * 商机产品关联表 Service 接口 * @@ -14,31 +15,45 @@ public interface CrmBusinessProductService { /** * 批量新增商机产品关联数据 + * * @param list 商机产品集合 */ void insertBatch(List list); /** * 根据商机id获取商机产品关联数据集合 + * * @param businessId 商机id */ List selectListByBusinessId(Long businessId); /** * 批量更新商机产品表 + * * @param list 商机产品数据集合 */ void updateBatch(List list); /** * 批量删除 + * * @param list 需要删除的商机产品集合 */ void deleteBatch(List list); /** - *根据商机id删除商机产品关联数据 + * 根据商机id删除商机产品关联数据 + * * @param businessId 商机id */ void deleteByBusinessId(Long businessId); + + /** + * 获得合同关联的商品列表 + * + * @param contractId 合同编号 + * @return 关联的商品列表 + */ + List selectListByContractId(Long contractId); + } diff --git a/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/service/business/CrmBusinessProductServiceImpl.java b/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/service/business/CrmBusinessProductServiceImpl.java index afad6ae31..0b65019b1 100644 --- a/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/service/business/CrmBusinessProductServiceImpl.java +++ b/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/service/business/CrmBusinessProductServiceImpl.java @@ -28,7 +28,7 @@ public class CrmBusinessProductServiceImpl implements CrmBusinessProductService @Override public List selectListByBusinessId(Long businessId) { - return businessProductMapper.selectList(CrmBusinessProductDO::getBusinessId,businessId); + return businessProductMapper.selectList(CrmBusinessProductDO::getBusinessId, businessId); } @Override @@ -47,4 +47,9 @@ public class CrmBusinessProductServiceImpl implements CrmBusinessProductService businessProductMapper.deleteByBusinessId(businessId); } + @Override + public List selectListByContractId(Long contractId) { + return businessProductMapper.selectList(CrmBusinessProductDO::getContractId, contractId); + } + } diff --git a/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/service/business/CrmBusinessServiceImpl.java b/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/service/business/CrmBusinessServiceImpl.java index 877971435..3b6b46aed 100644 --- a/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/service/business/CrmBusinessServiceImpl.java +++ b/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/service/business/CrmBusinessServiceImpl.java @@ -196,7 +196,7 @@ public class CrmBusinessServiceImpl implements CrmBusinessService { */ private void validateContractExists(Long businessId) { // TODO @lzxhqs:保持风格的统一,selectCountByBusinessId 改成 getContractCountByBusinessId;另外,可以不用声明 count,因为就一次性使用,直接把 197 和 198 合并成一行; - Long count = contractService.selectCountByBusinessId(businessId); + Long count = contractService.getContractCountByBusinessId(businessId); if (count > 0) { throw exception(BUSINESS_CONTRACT_EXISTS); } diff --git a/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/service/contract/CrmContractService.java b/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/service/contract/CrmContractService.java index 10ea9235d..cb06e99e0 100644 --- a/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/service/contract/CrmContractService.java +++ b/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/service/contract/CrmContractService.java @@ -64,7 +64,7 @@ public interface CrmContractService { * @param id 合同编号 * @param userId 用户编号 */ - void handleApprove(Long id, Long userId); + void submitContract(Long id, Long userId); /** * 更新合同流程审批结果 @@ -125,13 +125,12 @@ public interface CrmContractService { */ Long getContractCountByCustomerId(Long customerId); - // TODO @puhui999:要不改成 getContractCountByBusinessId /** * 根据商机ID获取关联客户的合同数量 * * @param businessId 商机编号 * @return 数量 */ - Long selectCountByBusinessId(Long businessId); + Long getContractCountByBusinessId(Long businessId); } diff --git a/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/service/contract/CrmContractServiceImpl.java b/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/service/contract/CrmContractServiceImpl.java index 130f0f709..5c0b2ede1 100644 --- a/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/service/contract/CrmContractServiceImpl.java +++ b/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/service/contract/CrmContractServiceImpl.java @@ -2,10 +2,12 @@ package cn.iocoder.yudao.module.crm.service.contract; import cn.hutool.core.collection.CollUtil; import cn.hutool.core.collection.ListUtil; +import cn.hutool.core.lang.Assert; import cn.hutool.core.util.ObjUtil; 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.bpm.api.listener.dto.BpmResultListenerRespDTO; import cn.iocoder.yudao.module.bpm.api.task.BpmProcessInstanceApi; import cn.iocoder.yudao.module.bpm.api.task.dto.BpmProcessInstanceCreateReqDTO; import cn.iocoder.yudao.module.crm.controller.admin.contract.vo.CrmContractPageReqVO; @@ -87,8 +89,10 @@ public class CrmContractServiceImpl implements CrmContractService { CrmContractDO contract = BeanUtils.toBean(createReqVO, CrmContractDO.class).setId(null); contractMapper.insert(contract); // 1.2 插入商机关联商品 - List businessProduct = convertBusinessProductList(createReqVO); - businessProductService.insertBatch(businessProduct); + if (CollUtil.isNotEmpty(createReqVO.getProductItems())) { // 如果有的话 + List businessProduct = convertBusinessProductList(createReqVO, contract.getId()); + businessProductService.insertBatch(businessProduct); + } // 2. 创建数据权限 crmPermissionService.createPermission(new CrmPermissionCreateReqBO().setUserId(userId) @@ -106,9 +110,11 @@ public class CrmContractServiceImpl implements CrmContractService { success = CRM_CONTRACT_UPDATE_SUCCESS) @CrmPermission(bizType = CrmBizTypeEnum.CRM_CONTRACT, bizId = "#updateReqVO.id", level = CrmPermissionLevelEnum.WRITE) public void updateContract(CrmContractSaveReqVO updateReqVO) { - // TODO @合同待定:只有草稿、审批中,可以编辑; - if (ObjUtil.notEqual(updateReqVO.getAuditStatus(), CrmAuditStatusEnum.DRAFT.getStatus()) || - ObjUtil.notEqual(updateReqVO.getAuditStatus(), CrmAuditStatusEnum.PROCESS.getStatus())) { + Assert.notNull(updateReqVO.getId(), "合同编号不能为空"); + CrmContractDO contract = validateContractExists(updateReqVO.getId()); + // 只有草稿、审批中,可以编辑; + if (ObjUtil.notEqual(contract.getAuditStatus(), CrmAuditStatusEnum.DRAFT.getStatus()) || + ObjUtil.notEqual(contract.getAuditStatus(), CrmAuditStatusEnum.PROCESS.getStatus())) { throw exception(CONTRACT_UPDATE_FAIL_EDITING_PROHIBITED); } validateRelationDataExists(updateReqVO); @@ -117,21 +123,41 @@ public class CrmContractServiceImpl implements CrmContractService { // 更新合同 CrmContractDO updateObj = BeanUtils.toBean(updateReqVO, CrmContractDO.class); contractMapper.updateById(updateObj); - - // TODO puhui999: @芋艿:合同变更关联的商机后商品怎么处理? - // TODO @puhui999:和商品 spu、sku 编辑一样;新增的插入;修改的更新;删除的删除 - //List businessProduct = convertBusinessProductList(updateReqVO); - //businessProductService.selectListByBusinessId() - //diffList() + // 更新合同关联商品 + updateContractProduct(updateReqVO, updateObj.getId()); // 3. 记录操作日志上下文 LogRecordContext.putVariable(DiffParseFunction.OLD_OBJECT, BeanUtils.toBean(oldContract, CrmContractSaveReqVO.class)); LogRecordContext.putVariable("contractName", oldContract.getName()); } + private void updateContractProduct(CrmContractSaveReqVO updateReqVO, Long contractId) { + if (CollUtil.isEmpty(updateReqVO.getProductItems())) { + return; + } + List newProductList = convertBusinessProductList(updateReqVO, contractId); + List oldProductList = businessProductService.selectListByContractId(contractId); + List> diffList = diffList(oldProductList, newProductList, (oldObj, newObj) -> { + if (ObjUtil.notEqual(oldObj.getProductId(), newObj.getProductId())) { + return false; + } + newObj.setId(oldObj.getId()); // 设置一下老的编号更新时需要使用 + return true; + }); + if (CollUtil.isNotEmpty(diffList.getFirst())) { + businessProductService.insertBatch(diffList.getFirst()); + } + if (CollUtil.isNotEmpty(diffList.get(1))) { + businessProductService.updateBatch(diffList.get(1)); + } + if (CollUtil.isNotEmpty(diffList.get(2))) { + businessProductService.deleteBatch(diffList.get(2)); + } + } + // TODO @合同待定:缺一个取消合同的接口;只有草稿、审批中可以取消;CrmAuditStatusEnum - private List convertBusinessProductList(CrmContractSaveReqVO reqVO) { + private List convertBusinessProductList(CrmContractSaveReqVO reqVO, Long contractId) { // 校验商品存在 Set productIds = convertSet(reqVO.getProductItems(), CrmContractSaveReqVO.CrmContractProductItem::getId); List productList = productService.getProductList(productIds); @@ -140,29 +166,14 @@ public class CrmContractServiceImpl implements CrmContractService { } Map productMap = convertMap(productList, CrmProductDO::getId); return convertList(reqVO.getProductItems(), productItem -> { - // TODO @puhui999:这里可以改成直接 return,不用弄一个 businessProduct 变量哈; - CrmBusinessProductDO businessProduct = BeanUtils.toBean(productMap.get(productItem.getId()), CrmBusinessProductDO.class); - businessProduct.setId(null).setBusinessId(reqVO.getBusinessId()).setProductId(productItem.getId()) - .setCount(productItem.getCount()).setDiscountPercent(productItem.getDiscountPercent()).setTotalPrice(calculator(businessProduct)); - return businessProduct; + CrmProductDO product = productMap.get(productItem.getId()); + return BeanUtils.toBean(product, CrmBusinessProductDO.class) + .setId(null).setBusinessId(reqVO.getBusinessId()).setProductId(productItem.getId()).setContractId(contractId) + .setCount(productItem.getCount()).setDiscountPercent(productItem.getDiscountPercent()) + .setTotalPrice(MoneyUtils.calculator(product.getPrice(), productItem.getCount(), productItem.getDiscountPercent())); }); } - /** - * 计算商品总价 - * - * @param businessProduct 关联商品 - * @return 商品总价 - */ - // TODO @puhui999:这个逻辑的计算,是不是可以封装到 calculateRatePriceFloor 里; - private Integer calculator(CrmBusinessProductDO businessProduct) { - int price = businessProduct.getPrice() * businessProduct.getCount(); - if (businessProduct.getDiscountPercent() == null) { - return price; - } - return MoneyUtils.calculateRatePriceFloor(price, (double) (businessProduct.getDiscountPercent() / 100)); - } - /** * 校验关联数据是否存在 * @@ -235,9 +246,12 @@ public class CrmContractServiceImpl implements CrmContractService { @Override @Transactional(rollbackFor = Exception.class) - public void handleApprove(Long id, Long userId) { - // TODO @puhui999:需要做状态检查 - + public void submitContract(Long id, Long userId) { + // 1. 校验合同是否在审批 + CrmContractDO contract = validateContractExists(id); + if (ObjUtil.notEqual(contract.getAuditStatus(), CrmAuditStatusEnum.DRAFT.getStatus())) { + throw exception(CONTRACT_SUBMIT_FAIL_NOT_DRAFT); + } // 创建合同审批流程实例 String processInstanceId = bpmProcessInstanceApi.createProcessInstance(userId, new BpmProcessInstanceCreateReqDTO() .setProcessDefinitionKey(CONTRACT_APPROVE).setBusinessKey(String.valueOf(id))); @@ -247,6 +261,12 @@ public class CrmContractServiceImpl implements CrmContractService { .setAuditStatus(CrmAuditStatusEnum.PROCESS.getStatus())); } + @Override + public void updateContractAuditStatus(BpmResultListenerRespDTO event) { + contractMapper.updateById(new CrmContractDO().setId(Long.parseLong(event.getBusinessKey())) + .setAuditStatus(event.getResult())); + } + //======================= 查询相关 ======================= @Override @@ -285,7 +305,7 @@ public class CrmContractServiceImpl implements CrmContractService { } @Override - public Long selectCountByBusinessId(Long businessId) { + public Long getContractCountByBusinessId(Long businessId) { return contractMapper.selectCountByBusinessId(businessId); } // TODO @合同待定:需要新增一个 ContractConfigDO 表,合同配置,重点是到期提醒; diff --git a/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/service/contract/listener/CrmContractResultListener.java b/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/service/contract/listener/CrmContractResultListener.java index f175bd43d..783579fc6 100644 --- a/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/service/contract/listener/CrmContractResultListener.java +++ b/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/service/contract/listener/CrmContractResultListener.java @@ -1,7 +1,11 @@ package cn.iocoder.yudao.module.crm.service.contract.listener; +import cn.hutool.core.util.ObjUtil; +import cn.iocoder.yudao.framework.common.util.object.ObjectUtils; import cn.iocoder.yudao.module.bpm.api.listener.BpmResultListenerApi; import cn.iocoder.yudao.module.bpm.api.listener.dto.BpmResultListenerRespDTO; +import cn.iocoder.yudao.module.bpm.enums.task.BpmProcessInstanceResultEnum; +import cn.iocoder.yudao.module.crm.enums.common.CrmAuditStatusEnum; import cn.iocoder.yudao.module.crm.service.contract.CrmContractService; import cn.iocoder.yudao.module.crm.service.contract.CrmContractServiceImpl; import jakarta.annotation.Resource; @@ -25,7 +29,31 @@ public class CrmContractResultListener implements BpmResultListenerApi { @Override public void onEvent(BpmResultListenerRespDTO event) { + boolean currentTaskFinish = isEndResult(event.getResult()); + if (!currentTaskFinish) { + return; + } + if (ObjUtil.equal(event.getResult(), BpmProcessInstanceResultEnum.APPROVE.getResult())) { + event.setResult(CrmAuditStatusEnum.APPROVE.getStatus()); + } + if (ObjUtil.equal(event.getResult(), BpmProcessInstanceResultEnum.REJECT.getResult())) { + event.setResult(CrmAuditStatusEnum.REJECT.getStatus()); + } + if (ObjUtil.equal(event.getResult(), BpmProcessInstanceResultEnum.CANCEL.getResult())) { + event.setResult(CrmAuditStatusEnum.CANCEL.getStatus()); + } contractService.updateContractAuditStatus(event); } + /** + * 判断该结果是否处于 End 最终结果 + * + * @param result 结果 + * @return 是否 + */ + public static boolean isEndResult(Integer result) { + return ObjectUtils.equalsAny(result, BpmProcessInstanceResultEnum.APPROVE.getResult(), + BpmProcessInstanceResultEnum.REJECT.getResult(), BpmProcessInstanceResultEnum.CANCEL.getResult()); + } + } diff --git a/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/service/customer/CrmCustomerServiceImpl.java b/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/service/customer/CrmCustomerServiceImpl.java index a7ddb2da9..6a38973c8 100644 --- a/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/service/customer/CrmCustomerServiceImpl.java +++ b/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/service/customer/CrmCustomerServiceImpl.java @@ -93,8 +93,7 @@ public class CrmCustomerServiceImpl implements CrmCustomerService { validateCustomerExceedOwnerLimit(createReqVO.getOwnerUserId(), 1); // 2. 插入客户 - CrmCustomerDO customer = BeanUtils.toBean(createReqVO, CrmCustomerDO.class).setOwnerUserId(userId) - .setLockStatus(false).setDealStatus(false).setContactLastTime(LocalDateTime.now()); + CrmCustomerDO customer = initCustomer(createReqVO, userId); customerMapper.insert(customer); // 3. 创建数据权限 @@ -232,7 +231,6 @@ public class CrmCustomerServiceImpl implements CrmCustomerService { return customer.getId(); } - // TODO @puhui999:操作日志 @Override public CrmCustomerImportRespVO importCustomerList(List importCustomers, Boolean isUpdateSupport, Long userId) { @@ -253,14 +251,14 @@ public class CrmCustomerServiceImpl implements CrmCustomerService { // 判断如果不存在,在进行插入 CrmCustomerDO existCustomer = customerMapper.selectByCustomerName(importCustomer.getName()); if (existCustomer == null) { - // TODO @puhui999:可以搞个 initCustomer 方法;这样可以把 create 和导入复用下这个方法; - CrmCustomerDO customer = BeanUtils.toBean(importCustomer, CrmCustomerDO.class).setOwnerUserId(userId) - .setLockStatus(false).setDealStatus(false).setContactLastTime(LocalDateTime.now()); + CrmCustomerDO customer = initCustomer(importCustomer, userId); customerMapper.insert(customer); respVO.getCreateCustomerNames().add(importCustomer.getName()); // 创建数据权限 permissionService.createPermission(new CrmPermissionCreateReqBO().setBizType(CrmBizTypeEnum.CRM_CUSTOMER.getType()) .setBizId(customer.getId()).setUserId(userId).setLevel(CrmPermissionLevelEnum.OWNER.getLevel())); // 设置当前操作的人为负责人 + // 记录操作日志 + getSelf().importCustomerLog(customer, false); return; } // 如果存在,判断是否允许更新 @@ -273,10 +271,25 @@ public class CrmCustomerServiceImpl implements CrmCustomerService { updateCustomer.setId(existCustomer.getId()); customerMapper.updateById(updateCustomer); respVO.getUpdateCustomerNames().add(importCustomer.getName()); + // 记录操作日志 + getSelf().importCustomerLog(updateCustomer, true); }); return respVO; } + private static CrmCustomerDO initCustomer(Object customer, Long userId) { + return BeanUtils.toBean(customer, CrmCustomerDO.class).setOwnerUserId(userId) + .setLockStatus(false).setDealStatus(false).setContactLastTime(LocalDateTime.now()); + } + + @LogRecord(type = CRM_CUSTOMER_TYPE, subType = CRM_CUSTOMER_IMPORT_SUB_TYPE, bizNo = "{{#customer.id}}", + success = CRM_CUSTOMER_IMPORT_SUCCESS) + public void importCustomerLog(CrmCustomerDO customer, boolean isUpdate) { + // 记录操作日志上下文 + LogRecordContext.putVariable("customer", customer); + LogRecordContext.putVariable("isUpdate", isUpdate); + } + private void validateCustomerForCreate(CrmCustomerImportExcelVO importCustomer) { // 校验客户名称不能为空 if (StrUtil.isEmptyIfStr(importCustomer.getName())) { @@ -367,15 +380,15 @@ public class CrmCustomerServiceImpl implements CrmCustomerService { if (poolConfig == null || !poolConfig.getEnabled()) { return 0; } - // 1.1 获取没有锁定的不在公海的客户且没有成交的 - List notDealCustomerList = customerMapper.selectListByLockAndDealStatusAndNotPool(Boolean.FALSE, Boolean.FALSE); - // 1.2 获取没有锁定的不在公海的客户且成交的 - // TODO @puhui999:下面也搞到 sql 里去哈;写 or 查询,问题不大的; - List dealCustomerList = customerMapper.selectListByLockAndDealStatusAndNotPool(Boolean.FALSE, Boolean.TRUE); + // 1.1 获取没有锁定的不在公海的客户 + List customerList = customerMapper.selectListByLockAndNotPool(Boolean.FALSE); List poolCustomerList = new ArrayList<>(); - poolCustomerList.addAll(filterList(notDealCustomerList, customer -> - (poolConfig.getDealExpireDays() - LocalDateTimeUtils.between(customer.getCreateTime())) <= 0)); - poolCustomerList.addAll(filterList(dealCustomerList, customer -> { + poolCustomerList.addAll(filterList(customerList, customer -> + !customer.getDealStatus() && (poolConfig.getDealExpireDays() - LocalDateTimeUtils.between(customer.getCreateTime())) <= 0)); + poolCustomerList.addAll(filterList(customerList, customer -> { + if (!customer.getDealStatus()) { // 这里只处理成交的 + return false; + } LocalDateTime lastTime = ObjUtil.defaultIfNull(customer.getContactLastTime(), customer.getCreateTime()); return (poolConfig.getContactExpireDays() - LocalDateTimeUtils.between(lastTime)) <= 0; })); From 6a63f2f078759025905e160893a672119d78b1ee Mon Sep 17 00:00:00 2001 From: puhui999 Date: Sat, 3 Feb 2024 14:08:06 +0800 Subject: [PATCH 059/119] =?UTF-8?q?CRM-CONTRACT:=20=E5=AE=8C=E5=96=84?= =?UTF-8?q?=E5=90=88=E5=90=8C=E7=BC=96=E8=BE=91=E5=9B=9E=E6=98=BE?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../admin/contract/CrmContractController.java | 25 +++++++++++-- .../admin/contract/vo/CrmContractRespVO.java | 35 +++++++++++++++++++ .../contract/vo/CrmContractSaveReqVO.java | 2 +- .../dal/mysql/product/CrmProductMapper.java | 8 +++++ .../business/CrmBusinessProductService.java | 12 +++---- .../CrmBusinessProductServiceImpl.java | 12 +++---- .../business/CrmBusinessServiceImpl.java | 12 +++---- .../contract/CrmContractServiceImpl.java | 16 +++++---- .../service/product/CrmProductService.java | 9 +++++ .../product/CrmProductServiceImpl.java | 8 +++++ 10 files changed, 110 insertions(+), 29 deletions(-) diff --git a/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/controller/admin/contract/CrmContractController.java b/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/controller/admin/contract/CrmContractController.java index d9b181029..e6180d83d 100644 --- a/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/controller/admin/contract/CrmContractController.java +++ b/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/controller/admin/contract/CrmContractController.java @@ -10,10 +10,14 @@ import cn.iocoder.yudao.framework.excel.core.util.ExcelUtils; import cn.iocoder.yudao.framework.operatelog.core.annotations.OperateLog; import cn.iocoder.yudao.module.crm.controller.admin.contract.vo.*; import cn.iocoder.yudao.module.crm.convert.contract.CrmContractConvert; +import cn.iocoder.yudao.module.crm.dal.dataobject.business.CrmBusinessProductDO; import cn.iocoder.yudao.module.crm.dal.dataobject.contract.CrmContractDO; import cn.iocoder.yudao.module.crm.dal.dataobject.customer.CrmCustomerDO; +import cn.iocoder.yudao.module.crm.dal.dataobject.product.CrmProductDO; +import cn.iocoder.yudao.module.crm.service.business.CrmBusinessProductService; import cn.iocoder.yudao.module.crm.service.contract.CrmContractService; import cn.iocoder.yudao.module.crm.service.customer.CrmCustomerService; +import cn.iocoder.yudao.module.crm.service.product.CrmProductService; import cn.iocoder.yudao.module.system.api.user.AdminUserApi; import cn.iocoder.yudao.module.system.api.user.dto.AdminUserRespDTO; import io.swagger.v3.oas.annotations.Operation; @@ -32,8 +36,8 @@ import java.util.Map; import java.util.stream.Stream; import static cn.iocoder.yudao.framework.common.pojo.CommonResult.success; -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.*; +import static cn.iocoder.yudao.framework.common.util.collection.MapUtils.findAndThen; import static cn.iocoder.yudao.framework.operatelog.core.enums.OperateTypeEnum.EXPORT; import static cn.iocoder.yudao.framework.security.core.util.SecurityFrameworkUtils.getLoginUserId; @@ -47,6 +51,10 @@ public class CrmContractController { private CrmContractService contractService; @Resource private CrmCustomerService customerService; + @Resource + private CrmBusinessProductService businessProductService; + @Resource + private CrmProductService productService; @Resource private AdminUserApi adminUserApi; @@ -81,7 +89,18 @@ public class CrmContractController { @PreAuthorize("@ss.hasPermission('crm:contract:query')") public CommonResult getContract(@RequestParam("id") Long id) { CrmContractDO contract = contractService.getContract(id); - return success(BeanUtils.toBean(contract, CrmContractRespVO.class)); + CrmContractRespVO respVO = BeanUtils.toBean(contract, CrmContractRespVO.class); + List businessProductList = businessProductService.getBusinessProductListByContractId(id); + Map businessProductMap = convertMap(businessProductList, CrmBusinessProductDO::getProductId); + List productList = productService.getProductListByIds(convertSet(businessProductList, CrmBusinessProductDO::getProductId)); + respVO.setProductItems(convertList(productList, product -> { + CrmContractRespVO.CrmContractProductItemRespVO productItemRespVO = BeanUtils.toBean(product, CrmContractRespVO.CrmContractProductItemRespVO.class); + findAndThen(businessProductMap, product.getId(), businessProduct -> { + productItemRespVO.setCount(businessProduct.getCount()).setDiscountPercent(businessProduct.getDiscountPercent()); + }); + return productItemRespVO; + })); + return success(respVO); } @GetMapping("/page") diff --git a/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/controller/admin/contract/vo/CrmContractRespVO.java b/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/controller/admin/contract/vo/CrmContractRespVO.java index 1164f4a0c..9e6c39a3a 100644 --- a/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/controller/admin/contract/vo/CrmContractRespVO.java +++ b/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/controller/admin/contract/vo/CrmContractRespVO.java @@ -3,10 +3,13 @@ package cn.iocoder.yudao.module.crm.controller.admin.contract.vo; import com.alibaba.excel.annotation.ExcelIgnoreUnannotated; import com.alibaba.excel.annotation.ExcelProperty; import io.swagger.v3.oas.annotations.media.Schema; +import lombok.AllArgsConstructor; import lombok.Data; +import lombok.NoArgsConstructor; import org.springframework.format.annotation.DateTimeFormat; import java.time.LocalDateTime; +import java.util.List; import static cn.iocoder.yudao.framework.common.util.date.DateUtils.FORMAT_YEAR_MONTH_DAY_HOUR_MINUTE_SECOND; @@ -113,4 +116,36 @@ public class CrmContractRespVO { @ExcelProperty("审批状态") private Integer auditStatus; + @Schema(description = "产品列表") + private List productItems; + + @Schema(description = "产品列表") + @Data + @NoArgsConstructor + @AllArgsConstructor + public static class CrmContractProductItemRespVO { + + @Schema(description = "产品编号", example = "20529") + private Long id; + + @Schema(description = "产品名称", requiredMode = Schema.RequiredMode.REQUIRED, example = "8911") + private String name; + + @Schema(description = "产品编码", requiredMode = Schema.RequiredMode.REQUIRED, example = "8911") + private String no; + + @Schema(description = "单位", requiredMode = Schema.RequiredMode.REQUIRED, example = "8911") + private Integer unit; + + @Schema(description = "价格,单位:分", requiredMode = Schema.RequiredMode.REQUIRED, example = "8911") + private Integer price; + + @Schema(description = "产品数量", requiredMode = Schema.RequiredMode.REQUIRED, example = "8911") + private Integer count; + + @Schema(description = "产品折扣") + private Integer discountPercent; + + } + } diff --git a/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/controller/admin/contract/vo/CrmContractSaveReqVO.java b/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/controller/admin/contract/vo/CrmContractSaveReqVO.java index a2908a3ac..20b20580e 100644 --- a/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/controller/admin/contract/vo/CrmContractSaveReqVO.java +++ b/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/controller/admin/contract/vo/CrmContractSaveReqVO.java @@ -93,7 +93,7 @@ public class CrmContractSaveReqVO { @Schema(description = "产品列表") private List productItems; - @Schema(description = "商品属性") + @Schema(description = "产品列表") @Data @NoArgsConstructor @AllArgsConstructor diff --git a/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/dal/mysql/product/CrmProductMapper.java b/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/dal/mysql/product/CrmProductMapper.java index 30a07eec2..3d696de7e 100644 --- a/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/dal/mysql/product/CrmProductMapper.java +++ b/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/dal/mysql/product/CrmProductMapper.java @@ -2,6 +2,7 @@ package cn.iocoder.yudao.module.crm.dal.mysql.product; import cn.iocoder.yudao.framework.common.pojo.PageResult; import cn.iocoder.yudao.framework.mybatis.core.mapper.BaseMapperX; +import cn.iocoder.yudao.framework.mybatis.core.query.LambdaQueryWrapperX; import cn.iocoder.yudao.framework.mybatis.core.query.MPJLambdaWrapperX; import cn.iocoder.yudao.module.crm.controller.admin.product.vo.product.CrmProductPageReqVO; import cn.iocoder.yudao.module.crm.dal.dataobject.product.CrmProductDO; @@ -9,6 +10,9 @@ import cn.iocoder.yudao.module.crm.enums.common.CrmBizTypeEnum; import cn.iocoder.yudao.module.crm.util.CrmQueryWrapperUtils; import org.apache.ibatis.annotations.Mapper; +import java.util.Collection; +import java.util.List; + /** * CRM 产品 Mapper * @@ -34,4 +38,8 @@ public interface CrmProductMapper extends BaseMapperX { return selectOne(CrmProductDO::getNo, no); } + default List selectListByIds(Collection ids) { + return selectList(new LambdaQueryWrapperX().in(CrmProductDO::getId, ids)); + } + } diff --git a/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/service/business/CrmBusinessProductService.java b/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/service/business/CrmBusinessProductService.java index f5a040488..f819b5907 100644 --- a/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/service/business/CrmBusinessProductService.java +++ b/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/service/business/CrmBusinessProductService.java @@ -18,35 +18,35 @@ public interface CrmBusinessProductService { * * @param list 商机产品集合 */ - void insertBatch(List list); + void createBusinessProductBatch(List list); /** * 根据商机id获取商机产品关联数据集合 * * @param businessId 商机id */ - List selectListByBusinessId(Long businessId); + List getBusinessProductListByBusinessId(Long businessId); /** * 批量更新商机产品表 * * @param list 商机产品数据集合 */ - void updateBatch(List list); + void updateBusinessProductBatch(List list); /** * 批量删除 * * @param list 需要删除的商机产品集合 */ - void deleteBatch(List list); + void deleteBusinessProductBatch(List list); /** * 根据商机id删除商机产品关联数据 * * @param businessId 商机id */ - void deleteByBusinessId(Long businessId); + void deleteBusinessProductByBusinessId(Long businessId); /** * 获得合同关联的商品列表 @@ -54,6 +54,6 @@ public interface CrmBusinessProductService { * @param contractId 合同编号 * @return 关联的商品列表 */ - List selectListByContractId(Long contractId); + List getBusinessProductListByContractId(Long contractId); } diff --git a/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/service/business/CrmBusinessProductServiceImpl.java b/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/service/business/CrmBusinessProductServiceImpl.java index 0b65019b1..88115a86a 100644 --- a/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/service/business/CrmBusinessProductServiceImpl.java +++ b/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/service/business/CrmBusinessProductServiceImpl.java @@ -22,33 +22,33 @@ public class CrmBusinessProductServiceImpl implements CrmBusinessProductService private CrmBusinessProductMapper businessProductMapper; @Override - public void insertBatch(List list) { + public void createBusinessProductBatch(List list) { businessProductMapper.insertBatch(list); } @Override - public List selectListByBusinessId(Long businessId) { + public List getBusinessProductListByBusinessId(Long businessId) { return businessProductMapper.selectList(CrmBusinessProductDO::getBusinessId, businessId); } @Override - public void updateBatch(List list) { + public void updateBusinessProductBatch(List list) { businessProductMapper.updateBatch(list); } // TODO @lzxhqs:这个方法,可以直接调用 deleteList 方法,然后传递 ids 就好了; @Override - public void deleteBatch(List list) { + public void deleteBusinessProductBatch(List list) { businessProductMapper.deleteBatchIds(CollectionUtils.convertList(list, CrmBusinessProductDO::getId)); } @Override - public void deleteByBusinessId(Long businessId) { + public void deleteBusinessProductByBusinessId(Long businessId) { businessProductMapper.deleteByBusinessId(businessId); } @Override - public List selectListByContractId(Long contractId) { + public List getBusinessProductListByContractId(Long contractId) { return businessProductMapper.selectList(CrmBusinessProductDO::getContractId, contractId); } diff --git a/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/service/business/CrmBusinessServiceImpl.java b/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/service/business/CrmBusinessServiceImpl.java index 3b6b46aed..f40a15bc1 100644 --- a/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/service/business/CrmBusinessServiceImpl.java +++ b/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/service/business/CrmBusinessServiceImpl.java @@ -120,20 +120,20 @@ public class CrmBusinessServiceImpl implements CrmBusinessService { CrmBusinessProductConvert.INSTANCE.convert(product).setBusinessId(businessId)); if (Boolean.TRUE.equals(updateFlag)) { // 根据商机 id从商机产品关联表中获取已存在的数据集合 - List oldProducts = businessProductService.selectListByBusinessId(businessId); + List oldProducts = businessProductService.getBusinessProductListByBusinessId(businessId); List> diffList = CollectionUtils.diffList(oldProducts, list, (oldValue, newValue) -> ObjectUtil.equal(oldValue.getProductId(), newValue.getProductId())); if (CollUtil.isNotEmpty(diffList.getFirst())) { - businessProductService.insertBatch(diffList.getFirst()); + businessProductService.createBusinessProductBatch(diffList.getFirst()); } if (CollUtil.isNotEmpty(diffList.get(1))) { - businessProductService.updateBatch(diffList.get(1)); + businessProductService.updateBusinessProductBatch(diffList.get(1)); } if (CollUtil.isNotEmpty(diffList.get(2))) { - businessProductService.deleteBatch(diffList.get(2)); + businessProductService.deleteBusinessProductBatch(diffList.get(2)); } } else { - businessProductService.insertBatch(list); + businessProductService.createBusinessProductBatch(list); } } @@ -154,7 +154,7 @@ public class CrmBusinessServiceImpl implements CrmBusinessService { if (CollUtil.isNotEmpty(updateReqVO.getProducts())) { createBusinessProducts(updateReqVO.getProducts(), updateReqVO.getId(), true); } else { - businessProductService.deleteByBusinessId(updateReqVO.getId()); + businessProductService.deleteBusinessProductByBusinessId(updateReqVO.getId()); } // TODO @商机待定:如果状态发生变化,插入商机状态变更记录表 diff --git a/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/service/contract/CrmContractServiceImpl.java b/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/service/contract/CrmContractServiceImpl.java index 5c0b2ede1..87f1c20e4 100644 --- a/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/service/contract/CrmContractServiceImpl.java +++ b/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/service/contract/CrmContractServiceImpl.java @@ -7,6 +7,7 @@ import cn.hutool.core.util.ObjUtil; 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.framework.common.util.object.ObjectUtils; import cn.iocoder.yudao.module.bpm.api.listener.dto.BpmResultListenerRespDTO; import cn.iocoder.yudao.module.bpm.api.task.BpmProcessInstanceApi; import cn.iocoder.yudao.module.bpm.api.task.dto.BpmProcessInstanceCreateReqDTO; @@ -91,7 +92,8 @@ public class CrmContractServiceImpl implements CrmContractService { // 1.2 插入商机关联商品 if (CollUtil.isNotEmpty(createReqVO.getProductItems())) { // 如果有的话 List businessProduct = convertBusinessProductList(createReqVO, contract.getId()); - businessProductService.insertBatch(businessProduct); + businessProductService.createBusinessProductBatch(businessProduct); + // 更新合同商品总金额 } // 2. 创建数据权限 @@ -113,8 +115,8 @@ public class CrmContractServiceImpl implements CrmContractService { Assert.notNull(updateReqVO.getId(), "合同编号不能为空"); CrmContractDO contract = validateContractExists(updateReqVO.getId()); // 只有草稿、审批中,可以编辑; - if (ObjUtil.notEqual(contract.getAuditStatus(), CrmAuditStatusEnum.DRAFT.getStatus()) || - ObjUtil.notEqual(contract.getAuditStatus(), CrmAuditStatusEnum.PROCESS.getStatus())) { + if (!ObjectUtils.equalsAny(contract.getAuditStatus(), CrmAuditStatusEnum.DRAFT.getStatus(), + CrmAuditStatusEnum.PROCESS.getStatus())) { throw exception(CONTRACT_UPDATE_FAIL_EDITING_PROHIBITED); } validateRelationDataExists(updateReqVO); @@ -136,7 +138,7 @@ public class CrmContractServiceImpl implements CrmContractService { return; } List newProductList = convertBusinessProductList(updateReqVO, contractId); - List oldProductList = businessProductService.selectListByContractId(contractId); + List oldProductList = businessProductService.getBusinessProductListByContractId(contractId); List> diffList = diffList(oldProductList, newProductList, (oldObj, newObj) -> { if (ObjUtil.notEqual(oldObj.getProductId(), newObj.getProductId())) { return false; @@ -145,13 +147,13 @@ public class CrmContractServiceImpl implements CrmContractService { return true; }); if (CollUtil.isNotEmpty(diffList.getFirst())) { - businessProductService.insertBatch(diffList.getFirst()); + businessProductService.createBusinessProductBatch(diffList.getFirst()); } if (CollUtil.isNotEmpty(diffList.get(1))) { - businessProductService.updateBatch(diffList.get(1)); + businessProductService.updateBusinessProductBatch(diffList.get(1)); } if (CollUtil.isNotEmpty(diffList.get(2))) { - businessProductService.deleteBatch(diffList.get(2)); + businessProductService.deleteBusinessProductBatch(diffList.get(2)); } } diff --git a/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/service/product/CrmProductService.java b/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/service/product/CrmProductService.java index e4eabd15a..6d2dd4943 100644 --- a/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/service/product/CrmProductService.java +++ b/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/service/product/CrmProductService.java @@ -69,4 +69,13 @@ public interface CrmProductService { * @return 产品 */ CrmProductDO getProductByCategoryId(Long categoryId); + + /** + * 获得产品列表 + * + * @param ids 产品编号 + * @return 产品列表 + */ + List getProductListByIds(Collection ids); + } diff --git a/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/service/product/CrmProductServiceImpl.java b/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/service/product/CrmProductServiceImpl.java index 80c38af3c..55f8a3593 100644 --- a/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/service/product/CrmProductServiceImpl.java +++ b/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/service/product/CrmProductServiceImpl.java @@ -155,4 +155,12 @@ public class CrmProductServiceImpl implements CrmProductService { return productMapper.selectOne(new LambdaQueryWrapper().eq(CrmProductDO::getCategoryId, categoryId)); } + @Override + public List getProductListByIds(Collection ids) { + if (CollUtil.isEmpty(ids)) { + return Collections.emptyList(); + } + return productMapper.selectListByIds(ids); + } + } From b2370564a42d71d343a1086922bc79886e1b121c Mon Sep 17 00:00:00 2001 From: kyle <573984425@qq.com> Date: Wed, 31 Jan 2024 18:59:41 +0800 Subject: [PATCH 060/119] =?UTF-8?q?feat:=20=E6=B7=BB=E5=8A=A0=E6=9F=A5?= =?UTF-8?q?=E6=89=BE=E7=94=A8=E6=88=B7=E7=9A=84=E5=A4=84=E7=90=86=E5=99=A8?= =?UTF-8?q?=EF=BC=8C=E7=94=A8=E4=BA=8E=E5=9C=A8bpmn=E4=B8=AD=E8=BE=85?= =?UTF-8?q?=E5=8A=A9=E6=9F=A5=E6=89=BE=E7=94=A8=E6=88=B7?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../flowable/core/enums/ProcessConstants.java | 22 ++++++ .../core/handler/MultiInstanceHandler.java | 67 +++++++++++++++++++ .../BpmProcessDefinitionServiceImpl.java | 11 ++- 3 files changed, 93 insertions(+), 7 deletions(-) create mode 100644 yudao-framework/yudao-spring-boot-starter-flowable/src/main/java/cn/iocoder/yudao/framework/flowable/core/enums/ProcessConstants.java create mode 100644 yudao-module-bpm/yudao-module-bpm-biz/src/main/java/cn/iocoder/yudao/module/bpm/framework/flowable/core/handler/MultiInstanceHandler.java diff --git a/yudao-framework/yudao-spring-boot-starter-flowable/src/main/java/cn/iocoder/yudao/framework/flowable/core/enums/ProcessConstants.java b/yudao-framework/yudao-spring-boot-starter-flowable/src/main/java/cn/iocoder/yudao/framework/flowable/core/enums/ProcessConstants.java new file mode 100644 index 000000000..f3dd4077f --- /dev/null +++ b/yudao-framework/yudao-spring-boot-starter-flowable/src/main/java/cn/iocoder/yudao/framework/flowable/core/enums/ProcessConstants.java @@ -0,0 +1,22 @@ +package cn.iocoder.yudao.framework.flowable.core.enums; + +/** + * 流程常量信息 + */ +public interface ProcessConstants { + + String BPMN_FILE_SUFFIX = ".bpmn"; + + /** + * nameapace + * bpmn中的命名空间 + * 这个东西有可能导致无法切换工作流程的实现 + */ + String NAMESPASE = "http://flowable.org/bpmn"; + + /** + * 自定义属性 dataType + */ + String PROCESS_CUSTOM_DATA_TYPE = "dataType"; + +} diff --git a/yudao-module-bpm/yudao-module-bpm-biz/src/main/java/cn/iocoder/yudao/module/bpm/framework/flowable/core/handler/MultiInstanceHandler.java b/yudao-module-bpm/yudao-module-bpm-biz/src/main/java/cn/iocoder/yudao/module/bpm/framework/flowable/core/handler/MultiInstanceHandler.java new file mode 100644 index 000000000..15b1c6660 --- /dev/null +++ b/yudao-module-bpm/yudao-module-bpm-biz/src/main/java/cn/iocoder/yudao/module/bpm/framework/flowable/core/handler/MultiInstanceHandler.java @@ -0,0 +1,67 @@ +package cn.iocoder.yudao.module.bpm.framework.flowable.core.handler; + +import cn.hutool.core.collection.CollUtil; +import cn.hutool.core.util.ObjectUtil; +import cn.iocoder.yudao.framework.flowable.core.enums.ProcessConstants; +import cn.iocoder.yudao.module.system.api.permission.PermissionApi; +import cn.iocoder.yudao.module.system.api.user.AdminUserApi; +import cn.iocoder.yudao.module.system.api.user.dto.AdminUserRespDTO; +import jakarta.annotation.Resource; +import lombok.AllArgsConstructor; +import org.flowable.bpmn.model.FlowElement; +import org.flowable.bpmn.model.UserTask; +import org.flowable.engine.delegate.DelegateExecution; +import org.springframework.stereotype.Component; + +import java.util.ArrayList; +import java.util.LinkedHashSet; +import java.util.List; +import java.util.Set; +import java.util.stream.Collectors; + +import static cn.iocoder.yudao.framework.common.util.collection.CollectionUtils.convertList; + +/** + * 多实例处理类 + */ +@AllArgsConstructor +@Component("multiInstanceHandler") +public class MultiInstanceHandler { + + @Resource + private AdminUserApi userApi; + + @Resource + private PermissionApi permissionApi; + + public Set getUserIds(DelegateExecution execution) { + Set candidateUserIds = new LinkedHashSet<>(); + FlowElement flowElement = execution.getCurrentFlowElement(); + if (ObjectUtil.isNotEmpty(flowElement) && flowElement instanceof UserTask userTask) { + String dataType = userTask.getAttributeValue(ProcessConstants.NAMESPASE, ProcessConstants.PROCESS_CUSTOM_DATA_TYPE); + if ("USERS".equals(dataType) && CollUtil.isNotEmpty(userTask.getCandidateUsers())) { + // 添加候选用户id + candidateUserIds.addAll(userTask.getCandidateUsers()); + } else if (CollUtil.isNotEmpty(userTask.getCandidateGroups())) { + // 获取组的ID,角色ID集合或部门ID集合 + List groups = userTask.getCandidateGroups().stream() + // 例如部门DEPT100,100才是部门id + .map(item -> Long.parseLong(item.substring(4))) + .collect(Collectors.toList()); + List userIds = new ArrayList<>(); + if ("ROLES".equals(dataType)) { + // 通过角色id,获取所有用户id集合 + Set userRoleIdListByRoleIds = permissionApi.getUserRoleIdListByRoleIds(groups); + userIds = new ArrayList<>(userRoleIdListByRoleIds); + } else if ("DEPTS".equals(dataType)) { + // 通过部门id,获取所有用户id集合 + List userListByDeptIds = userApi.getUserListByDeptIds(groups); + userIds = convertList(userListByDeptIds, AdminUserRespDTO::getId); + } + // 添加候选用户id + userIds.forEach(id -> candidateUserIds.add(String.valueOf(id))); + } + } + return candidateUserIds; + } +} diff --git a/yudao-module-bpm/yudao-module-bpm-biz/src/main/java/cn/iocoder/yudao/module/bpm/service/definition/BpmProcessDefinitionServiceImpl.java b/yudao-module-bpm/yudao-module-bpm-biz/src/main/java/cn/iocoder/yudao/module/bpm/service/definition/BpmProcessDefinitionServiceImpl.java index 28487b562..1be0432a0 100644 --- a/yudao-module-bpm/yudao-module-bpm-biz/src/main/java/cn/iocoder/yudao/module/bpm/service/definition/BpmProcessDefinitionServiceImpl.java +++ b/yudao-module-bpm/yudao-module-bpm-biz/src/main/java/cn/iocoder/yudao/module/bpm/service/definition/BpmProcessDefinitionServiceImpl.java @@ -5,8 +5,8 @@ import cn.hutool.core.util.ObjectUtil; import cn.hutool.core.util.StrUtil; import cn.iocoder.yudao.framework.common.pojo.PageResult; import cn.iocoder.yudao.framework.common.util.object.PageUtils; +import cn.iocoder.yudao.framework.flowable.core.enums.ProcessConstants; import cn.iocoder.yudao.framework.flowable.core.util.BpmnModelUtils; -import cn.iocoder.yudao.framework.flowable.core.util.FlowableUtils; import cn.iocoder.yudao.framework.tenant.core.context.TenantContextHolder; import cn.iocoder.yudao.module.bpm.controller.admin.definition.vo.process.BpmProcessDefinitionListReqVO; import cn.iocoder.yudao.module.bpm.controller.admin.definition.vo.process.BpmProcessDefinitionPageItemRespVO; @@ -17,6 +17,8 @@ import cn.iocoder.yudao.module.bpm.dal.dataobject.definition.BpmFormDO; import cn.iocoder.yudao.module.bpm.dal.dataobject.definition.BpmProcessDefinitionExtDO; import cn.iocoder.yudao.module.bpm.dal.mysql.definition.BpmProcessDefinitionExtMapper; import cn.iocoder.yudao.module.bpm.service.definition.dto.BpmProcessDefinitionCreateReqDTO; +import jakarta.annotation.Resource; +import jakarta.validation.Valid; import lombok.extern.slf4j.Slf4j; import org.flowable.bpmn.converter.BpmnXMLConverter; import org.flowable.bpmn.model.BpmnModel; @@ -29,13 +31,10 @@ import org.flowable.engine.repository.ProcessDefinitionQuery; import org.springframework.stereotype.Service; import org.springframework.validation.annotation.Validated; -import jakarta.annotation.Resource; -import jakarta.validation.Valid; import java.util.*; 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.convertMap; import static cn.iocoder.yudao.module.bpm.enums.ErrorCodeConstants.PROCESS_DEFINITION_KEY_NOT_MATCH; import static cn.iocoder.yudao.module.bpm.enums.ErrorCodeConstants.PROCESS_DEFINITION_NAME_NOT_MATCH; import static java.util.Collections.emptyList; @@ -53,8 +52,6 @@ import static java.util.Collections.emptyList; @Slf4j public class BpmProcessDefinitionServiceImpl implements BpmProcessDefinitionService { - private static final String BPMN_FILE_SUFFIX = ".bpmn"; - @Resource private RepositoryService repositoryService; @@ -125,7 +122,7 @@ public class BpmProcessDefinitionServiceImpl implements BpmProcessDefinitionServ // 创建 Deployment 部署 Deployment deploy = repositoryService.createDeployment() .key(createReqDTO.getKey()).name(createReqDTO.getName()).category(createReqDTO.getCategory()) - .addBytes(createReqDTO.getKey() + BPMN_FILE_SUFFIX, createReqDTO.getBpmnBytes()) + .addBytes(createReqDTO.getKey() + ProcessConstants.BPMN_FILE_SUFFIX, createReqDTO.getBpmnBytes()) .tenantId(TenantContextHolder.getTenantIdStr()) .deploy(); From 66615f9e14aae4c41b27b5795181a21cc60a9641 Mon Sep 17 00:00:00 2001 From: kyle <573984425@qq.com> Date: Wed, 31 Jan 2024 19:37:03 +0800 Subject: [PATCH 061/119] =?UTF-8?q?chore:=20=E6=95=B4=E7=90=86=E4=BB=A3?= =?UTF-8?q?=E7=A0=81?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../BpmProcessInstanceCopyController.java | 4 +- .../vo/task/BpmProcessInstanceCopyVO.java | 65 ------------------- .../core/handler/MultiInstanceHandler.java | 7 ++ 3 files changed, 9 insertions(+), 67 deletions(-) delete mode 100644 yudao-module-bpm/yudao-module-bpm-biz/src/main/java/cn/iocoder/yudao/module/bpm/controller/admin/task/vo/task/BpmProcessInstanceCopyVO.java diff --git a/yudao-module-bpm/yudao-module-bpm-biz/src/main/java/cn/iocoder/yudao/module/bpm/controller/admin/task/BpmProcessInstanceCopyController.java b/yudao-module-bpm/yudao-module-bpm-biz/src/main/java/cn/iocoder/yudao/module/bpm/controller/admin/task/BpmProcessInstanceCopyController.java index fe3511af7..e1ad107ab 100644 --- a/yudao-module-bpm/yudao-module-bpm-biz/src/main/java/cn/iocoder/yudao/module/bpm/controller/admin/task/BpmProcessInstanceCopyController.java +++ b/yudao-module-bpm/yudao-module-bpm-biz/src/main/java/cn/iocoder/yudao/module/bpm/controller/admin/task/BpmProcessInstanceCopyController.java @@ -49,7 +49,7 @@ public class BpmProcessInstanceCopyController { @PostMapping("/create") @Operation(summary = "抄送流程") @PreAuthorize("@ss.hasPermission('bpm:process-instance-cc:create')") - public CommonResult createProcessInstanceCC(@Valid @RequestBody BpmProcessInstanceCopyCreateReqVO createReqVO) { + public CommonResult createProcessInstanceCopy(@Valid @RequestBody BpmProcessInstanceCopyCreateReqVO createReqVO) { processInstanceCopyService.createProcessInstanceCopy(getLoginUserId(), createReqVO); return success(true); } @@ -57,7 +57,7 @@ public class BpmProcessInstanceCopyController { @GetMapping("/my-page") @Operation(summary = "获得抄送流程分页列表") @PreAuthorize("@ss.hasPermission('bpm:process-instance-cc:query')") - public CommonResult> getProcessInstanceCCPage( + public CommonResult> getProcessInstanceCopyPage( @Valid BpmProcessInstanceCopyMyPageReqVO pageReqVO) { PageResult pageResult = processInstanceCopyService.getMyProcessInstanceCopyPage(getLoginUserId(), pageReqVO); if (CollUtil.isEmpty(pageResult.getList())) { diff --git a/yudao-module-bpm/yudao-module-bpm-biz/src/main/java/cn/iocoder/yudao/module/bpm/controller/admin/task/vo/task/BpmProcessInstanceCopyVO.java b/yudao-module-bpm/yudao-module-bpm-biz/src/main/java/cn/iocoder/yudao/module/bpm/controller/admin/task/vo/task/BpmProcessInstanceCopyVO.java deleted file mode 100644 index 977ec41d8..000000000 --- a/yudao-module-bpm/yudao-module-bpm-biz/src/main/java/cn/iocoder/yudao/module/bpm/controller/admin/task/vo/task/BpmProcessInstanceCopyVO.java +++ /dev/null @@ -1,65 +0,0 @@ -package cn.iocoder.yudao.module.bpm.controller.admin.task.vo.task; - -import io.swagger.v3.oas.annotations.media.Schema; -import lombok.Data; - -import java.time.LocalDateTime; - -// TODO @kyle:1)明确是 Req 还是 Resp;2)注释可以合并到 swagger 里;3)example 写一下,这样一些 mock 接口平台可以读取 example -/** - * 流程抄送视图对象 - */ -@Data -public class BpmProcessInstanceCopyVO { - - /** - * 编号 - */ - @Schema(description = "抄送主键") - private Long id; - - /** - * 发起人Id - */ - @Schema(description = "发起人Id") - private Long startUserId; - - @Schema(description = "发起人别名") - private String startUserNickname; - - /** - * 流程主键 - */ - @Schema(description = "流程实例的主键") - private String processInstanceId; - - @Schema(description = "流程实例的名字") - private String processInstanceName; - - /** - * 任务主键 - */ - @Schema(description = "发起抄送的任务编号") - private String taskId; - - @Schema(description = "发起抄送的任务名称") - private String taskName; - /** - * 用户主键 - */ - @Schema(description = "用户编号") - private Long userId; - - @Schema(description = "用户别名") - private Long userNickname; - - @Schema(description = "抄送原因") - private String reason; - - @Schema(description = "抄送人") - private String creator; - - @Schema(description = "抄送时间") - private LocalDateTime createTime; - -} diff --git a/yudao-module-bpm/yudao-module-bpm-biz/src/main/java/cn/iocoder/yudao/module/bpm/framework/flowable/core/handler/MultiInstanceHandler.java b/yudao-module-bpm/yudao-module-bpm-biz/src/main/java/cn/iocoder/yudao/module/bpm/framework/flowable/core/handler/MultiInstanceHandler.java index 15b1c6660..5870f377a 100644 --- a/yudao-module-bpm/yudao-module-bpm-biz/src/main/java/cn/iocoder/yudao/module/bpm/framework/flowable/core/handler/MultiInstanceHandler.java +++ b/yudao-module-bpm/yudao-module-bpm-biz/src/main/java/cn/iocoder/yudao/module/bpm/framework/flowable/core/handler/MultiInstanceHandler.java @@ -34,6 +34,13 @@ public class MultiInstanceHandler { @Resource private PermissionApi permissionApi; + /** + * 流程发起人那种情况不需要处理, + * 由 flowable 完成 + * + * @param execution flowable的执行对象 + * @return 用户ID + */ public Set getUserIds(DelegateExecution execution) { Set candidateUserIds = new LinkedHashSet<>(); FlowElement flowElement = execution.getCurrentFlowElement(); From 9fbbce4e8dd30c3660e98a6c5f830c50ab1125d7 Mon Sep 17 00:00:00 2001 From: YunaiV Date: Sat, 3 Feb 2024 16:12:27 +0800 Subject: [PATCH 062/119] =?UTF-8?q?=F0=9F=93=96=20BPMN=EF=BC=9Acode=20revi?= =?UTF-8?q?ew=20bpmn=20=E4=B8=AD=E8=BE=85=E5=8A=A9=E6=9F=A5=E6=89=BE?= =?UTF-8?q?=E4=BB=A3=E7=A0=81?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../{ProcessConstants.java => BpmnModelConstants.java} | 8 ++++---- .../flowable/core/handler/MultiInstanceHandler.java | 6 ++++-- .../definition/BpmProcessDefinitionServiceImpl.java | 4 ++-- 3 files changed, 10 insertions(+), 8 deletions(-) rename yudao-framework/yudao-spring-boot-starter-flowable/src/main/java/cn/iocoder/yudao/framework/flowable/core/enums/{ProcessConstants.java => BpmnModelConstants.java} (70%) diff --git a/yudao-framework/yudao-spring-boot-starter-flowable/src/main/java/cn/iocoder/yudao/framework/flowable/core/enums/ProcessConstants.java b/yudao-framework/yudao-spring-boot-starter-flowable/src/main/java/cn/iocoder/yudao/framework/flowable/core/enums/BpmnModelConstants.java similarity index 70% rename from yudao-framework/yudao-spring-boot-starter-flowable/src/main/java/cn/iocoder/yudao/framework/flowable/core/enums/ProcessConstants.java rename to yudao-framework/yudao-spring-boot-starter-flowable/src/main/java/cn/iocoder/yudao/framework/flowable/core/enums/BpmnModelConstants.java index f3dd4077f..c3cce4272 100644 --- a/yudao-framework/yudao-spring-boot-starter-flowable/src/main/java/cn/iocoder/yudao/framework/flowable/core/enums/ProcessConstants.java +++ b/yudao-framework/yudao-spring-boot-starter-flowable/src/main/java/cn/iocoder/yudao/framework/flowable/core/enums/BpmnModelConstants.java @@ -3,16 +3,16 @@ package cn.iocoder.yudao.framework.flowable.core.enums; /** * 流程常量信息 */ -public interface ProcessConstants { +public interface BpmnModelConstants { String BPMN_FILE_SUFFIX = ".bpmn"; /** - * nameapace - * bpmn中的命名空间 + * BPMN 中的命名空间 + * * 这个东西有可能导致无法切换工作流程的实现 */ - String NAMESPASE = "http://flowable.org/bpmn"; + String NAMESPACE = "http://flowable.org/bpmn"; /** * 自定义属性 dataType diff --git a/yudao-module-bpm/yudao-module-bpm-biz/src/main/java/cn/iocoder/yudao/module/bpm/framework/flowable/core/handler/MultiInstanceHandler.java b/yudao-module-bpm/yudao-module-bpm-biz/src/main/java/cn/iocoder/yudao/module/bpm/framework/flowable/core/handler/MultiInstanceHandler.java index 5870f377a..ee81a9cf4 100644 --- a/yudao-module-bpm/yudao-module-bpm-biz/src/main/java/cn/iocoder/yudao/module/bpm/framework/flowable/core/handler/MultiInstanceHandler.java +++ b/yudao-module-bpm/yudao-module-bpm-biz/src/main/java/cn/iocoder/yudao/module/bpm/framework/flowable/core/handler/MultiInstanceHandler.java @@ -2,7 +2,7 @@ package cn.iocoder.yudao.module.bpm.framework.flowable.core.handler; import cn.hutool.core.collection.CollUtil; import cn.hutool.core.util.ObjectUtil; -import cn.iocoder.yudao.framework.flowable.core.enums.ProcessConstants; +import cn.iocoder.yudao.framework.flowable.core.enums.BpmnModelConstants; import cn.iocoder.yudao.module.system.api.permission.PermissionApi; import cn.iocoder.yudao.module.system.api.user.AdminUserApi; import cn.iocoder.yudao.module.system.api.user.dto.AdminUserRespDTO; @@ -21,6 +21,7 @@ import java.util.stream.Collectors; import static cn.iocoder.yudao.framework.common.util.collection.CollectionUtils.convertList; +// TODO @芋艿:bpmn 分配人融合时,需要搞下这块; /** * 多实例处理类 */ @@ -45,7 +46,7 @@ public class MultiInstanceHandler { Set candidateUserIds = new LinkedHashSet<>(); FlowElement flowElement = execution.getCurrentFlowElement(); if (ObjectUtil.isNotEmpty(flowElement) && flowElement instanceof UserTask userTask) { - String dataType = userTask.getAttributeValue(ProcessConstants.NAMESPASE, ProcessConstants.PROCESS_CUSTOM_DATA_TYPE); + String dataType = userTask.getAttributeValue(BpmnModelConstants.NAMESPACE, BpmnModelConstants.PROCESS_CUSTOM_DATA_TYPE); if ("USERS".equals(dataType) && CollUtil.isNotEmpty(userTask.getCandidateUsers())) { // 添加候选用户id candidateUserIds.addAll(userTask.getCandidateUsers()); @@ -71,4 +72,5 @@ public class MultiInstanceHandler { } return candidateUserIds; } + } diff --git a/yudao-module-bpm/yudao-module-bpm-biz/src/main/java/cn/iocoder/yudao/module/bpm/service/definition/BpmProcessDefinitionServiceImpl.java b/yudao-module-bpm/yudao-module-bpm-biz/src/main/java/cn/iocoder/yudao/module/bpm/service/definition/BpmProcessDefinitionServiceImpl.java index 1be0432a0..c9b3872cd 100644 --- a/yudao-module-bpm/yudao-module-bpm-biz/src/main/java/cn/iocoder/yudao/module/bpm/service/definition/BpmProcessDefinitionServiceImpl.java +++ b/yudao-module-bpm/yudao-module-bpm-biz/src/main/java/cn/iocoder/yudao/module/bpm/service/definition/BpmProcessDefinitionServiceImpl.java @@ -5,7 +5,7 @@ import cn.hutool.core.util.ObjectUtil; import cn.hutool.core.util.StrUtil; import cn.iocoder.yudao.framework.common.pojo.PageResult; import cn.iocoder.yudao.framework.common.util.object.PageUtils; -import cn.iocoder.yudao.framework.flowable.core.enums.ProcessConstants; +import cn.iocoder.yudao.framework.flowable.core.enums.BpmnModelConstants; import cn.iocoder.yudao.framework.flowable.core.util.BpmnModelUtils; import cn.iocoder.yudao.framework.tenant.core.context.TenantContextHolder; import cn.iocoder.yudao.module.bpm.controller.admin.definition.vo.process.BpmProcessDefinitionListReqVO; @@ -122,7 +122,7 @@ public class BpmProcessDefinitionServiceImpl implements BpmProcessDefinitionServ // 创建 Deployment 部署 Deployment deploy = repositoryService.createDeployment() .key(createReqDTO.getKey()).name(createReqDTO.getName()).category(createReqDTO.getCategory()) - .addBytes(createReqDTO.getKey() + ProcessConstants.BPMN_FILE_SUFFIX, createReqDTO.getBpmnBytes()) + .addBytes(createReqDTO.getKey() + BpmnModelConstants.BPMN_FILE_SUFFIX, createReqDTO.getBpmnBytes()) .tenantId(TenantContextHolder.getTenantIdStr()) .deploy(); From 53badfc3673d97beb6ee7dafa7bdc78659e202ca Mon Sep 17 00:00:00 2001 From: puhui999 Date: Sat, 3 Feb 2024 20:49:13 +0800 Subject: [PATCH 063/119] =?UTF-8?q?CRM-CONTRACT:=20=E5=AE=8C=E5=96=84?= =?UTF-8?q?=E5=90=88=E5=90=8C=E7=BC=96=E8=BE=91=E5=9B=9E=E6=98=BE?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../admin/business/CrmBusinessController.java | 4 +- .../admin/clue/CrmClueController.java | 4 +- .../admin/contact/CrmContactController.java | 10 ++--- .../admin/contract/CrmContractController.java | 45 +++++++++++++------ .../admin/contract/vo/CrmContractRespVO.java | 16 +++++-- .../admin/customer/CrmCustomerController.java | 4 +- .../followup/CrmFollowUpRecordController.java | 2 +- .../convert/contract/CrmContractConvert.java | 17 ++++--- .../service/contact/CrmContactService.java | 4 +- .../contact/CrmContactServiceImpl.java | 4 +- 10 files changed, 70 insertions(+), 40 deletions(-) diff --git a/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/controller/admin/business/CrmBusinessController.java b/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/controller/admin/business/CrmBusinessController.java index 90b00dd48..85fe5b3f3 100644 --- a/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/controller/admin/business/CrmBusinessController.java +++ b/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/controller/admin/business/CrmBusinessController.java @@ -166,10 +166,10 @@ public class CrmBusinessController { return CrmBusinessConvert.INSTANCE.convertPage(pageResult, customerList, statusTypeList, statusList); } - @PutMapping("/transfer") + @PutMapping("/transfer-business") @Operation(summary = "商机转移") @PreAuthorize("@ss.hasPermission('crm:business:update')") - public CommonResult transfer(@Valid @RequestBody CrmBusinessTransferReqVO reqVO) { + public CommonResult transferBusiness(@Valid @RequestBody CrmBusinessTransferReqVO reqVO) { businessService.transferBusiness(reqVO, getLoginUserId()); return success(true); } diff --git a/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/controller/admin/clue/CrmClueController.java b/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/controller/admin/clue/CrmClueController.java index dca364cba..a2ddf3742 100644 --- a/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/controller/admin/clue/CrmClueController.java +++ b/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/controller/admin/clue/CrmClueController.java @@ -88,10 +88,10 @@ public class CrmClueController { ExcelUtils.write(response, "线索.xls", "数据", CrmClueRespVO.class, datas); } - @PutMapping("/transfer") + @PutMapping("/transfer-clue") @Operation(summary = "线索转移") @PreAuthorize("@ss.hasPermission('crm:clue:update')") - public CommonResult transfer(@Valid @RequestBody CrmClueTransferReqVO reqVO) { + public CommonResult transferClue(@Valid @RequestBody CrmClueTransferReqVO reqVO) { clueService.transferClue(reqVO, getLoginUserId()); return success(true); } diff --git a/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/controller/admin/contact/CrmContactController.java b/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/controller/admin/contact/CrmContactController.java index e3998834d..c00d57a6c 100644 --- a/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/controller/admin/contact/CrmContactController.java +++ b/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/controller/admin/contact/CrmContactController.java @@ -102,7 +102,7 @@ public class CrmContactController { List customerList = customerService.getCustomerList( Collections.singletonList(contact.getCustomerId())); // 3. 直属上级 - List parentContactList = contactService.getContactList( + List parentContactList = contactService.getContactListByIds( Collections.singletonList(contact.getParentId()), getLoginUserId()); return success(CrmContactConvert.INSTANCE.convert(contact, userMap, customerList, parentContactList)); } @@ -112,7 +112,7 @@ public class CrmContactController { @Parameter(name = "ids", description = "编号", required = true, example = "[1024]") @PreAuthorize("@ss.hasPermission('crm:contact:query')") public CommonResult> getContactListByIds(@RequestParam("ids") List ids) { - return success(BeanUtils.toBean(contactService.getContactList(ids, getLoginUserId()), CrmContactRespVO.class)); + return success(BeanUtils.toBean(contactService.getContactListByIds(ids, getLoginUserId()), CrmContactRespVO.class)); } @GetMapping("/simple-all-list") @@ -170,15 +170,15 @@ public class CrmContactController { Map userMap = adminUserApi.getUserMap(convertListByFlatMap(contactList, contact -> Stream.of(NumberUtils.parseLong(contact.getCreator()), contact.getOwnerUserId()))); // 3. 直属上级 - List parentContactList = contactService.getContactList( + List parentContactList = contactService.getContactListByIds( convertSet(contactList, CrmContactDO::getParentId), getLoginUserId()); return CrmContactConvert.INSTANCE.convertPage(pageResult, userMap, crmCustomerDOList, parentContactList); } - @PutMapping("/transfer") + @PutMapping("/transfer-contact") @Operation(summary = "联系人转移") @PreAuthorize("@ss.hasPermission('crm:contact:update')") - public CommonResult transfer(@Valid @RequestBody CrmContactTransferReqVO reqVO) { + public CommonResult transferContact(@Valid @RequestBody CrmContactTransferReqVO reqVO) { contactService.transferContact(reqVO, getLoginUserId()); return success(true); } diff --git a/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/controller/admin/contract/CrmContractController.java b/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/controller/admin/contract/CrmContractController.java index e6180d83d..43bd49ea2 100644 --- a/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/controller/admin/contract/CrmContractController.java +++ b/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/controller/admin/contract/CrmContractController.java @@ -10,11 +10,15 @@ import cn.iocoder.yudao.framework.excel.core.util.ExcelUtils; import cn.iocoder.yudao.framework.operatelog.core.annotations.OperateLog; import cn.iocoder.yudao.module.crm.controller.admin.contract.vo.*; import cn.iocoder.yudao.module.crm.convert.contract.CrmContractConvert; +import cn.iocoder.yudao.module.crm.dal.dataobject.business.CrmBusinessDO; import cn.iocoder.yudao.module.crm.dal.dataobject.business.CrmBusinessProductDO; +import cn.iocoder.yudao.module.crm.dal.dataobject.contact.CrmContactDO; import cn.iocoder.yudao.module.crm.dal.dataobject.contract.CrmContractDO; import cn.iocoder.yudao.module.crm.dal.dataobject.customer.CrmCustomerDO; import cn.iocoder.yudao.module.crm.dal.dataobject.product.CrmProductDO; import cn.iocoder.yudao.module.crm.service.business.CrmBusinessProductService; +import cn.iocoder.yudao.module.crm.service.business.CrmBusinessService; +import cn.iocoder.yudao.module.crm.service.contact.CrmContactService; import cn.iocoder.yudao.module.crm.service.contract.CrmContractService; import cn.iocoder.yudao.module.crm.service.customer.CrmCustomerService; import cn.iocoder.yudao.module.crm.service.product.CrmProductService; @@ -26,11 +30,13 @@ import io.swagger.v3.oas.annotations.tags.Tag; import jakarta.annotation.Resource; import jakarta.servlet.http.HttpServletResponse; import jakarta.validation.Valid; +import org.springframework.context.annotation.Lazy; import org.springframework.security.access.prepost.PreAuthorize; import org.springframework.validation.annotation.Validated; import org.springframework.web.bind.annotation.*; import java.io.IOException; +import java.util.Collections; import java.util.List; import java.util.Map; import java.util.stream.Stream; @@ -52,6 +58,11 @@ public class CrmContractController { @Resource private CrmCustomerService customerService; @Resource + private CrmContactService contactService; + @Resource + private CrmBusinessService businessService; + @Resource + @Lazy private CrmBusinessProductService businessProductService; @Resource private CrmProductService productService; @@ -89,7 +100,8 @@ public class CrmContractController { @PreAuthorize("@ss.hasPermission('crm:contract:query')") public CommonResult getContract(@RequestParam("id") Long id) { CrmContractDO contract = contractService.getContract(id); - CrmContractRespVO respVO = BeanUtils.toBean(contract, CrmContractRespVO.class); + List respVOList = buildContractDetail(Collections.singletonList(contract)); + CrmContractRespVO respVO = respVOList.getFirst(); List businessProductList = businessProductService.getBusinessProductListByContractId(id); Map businessProductMap = convertMap(businessProductList, CrmBusinessProductDO::getProductId); List productList = productService.getProductListByIds(convertSet(businessProductList, CrmBusinessProductDO::getProductId)); @@ -108,15 +120,15 @@ public class CrmContractController { @PreAuthorize("@ss.hasPermission('crm:contract:query')") public CommonResult> getContractPage(@Valid CrmContractPageReqVO pageVO) { PageResult pageResult = contractService.getContractPage(pageVO, getLoginUserId()); - return success(buildContractDetailPage(pageResult)); + return success(BeanUtils.toBean(pageResult, CrmContractRespVO.class).setList(buildContractDetail(pageResult.getList()))); } @GetMapping("/page-by-customer") - @Operation(summary = "获得联系人分页,基于指定客户") + @Operation(summary = "获得合同分页,基于指定客户") public CommonResult> getContractPageByCustomer(@Valid CrmContractPageReqVO pageVO) { Assert.notNull(pageVO.getCustomerId(), "客户编号不能为空"); PageResult pageResult = contractService.getContractPageByCustomerId(pageVO); - return success(buildContractDetailPage(pageResult)); + return success(BeanUtils.toBean(pageResult, CrmContractRespVO.class).setList(buildContractDetail(pageResult.getList()))); } @GetMapping("/export-excel") @@ -132,23 +144,28 @@ public class CrmContractController { } /** - * 构建详细的合同分页结果 + * 构建详细的合同结果 * - * @param pageResult 简单的合同分页结果 - * @return 详细的合同分页结果 + * @param contractList 原始合同信息 + * @return 细的合同结果 */ - private PageResult buildContractDetailPage(PageResult pageResult) { - List contactList = pageResult.getList(); - if (CollUtil.isEmpty(contactList)) { - return PageResult.empty(pageResult.getTotal()); + private List buildContractDetail(List contractList) { + if (CollUtil.isEmpty(contractList)) { + return Collections.emptyList(); } // 1. 获取客户列表 List customerList = customerService.getCustomerList( - convertSet(contactList, CrmContractDO::getCustomerId)); + convertSet(contractList, CrmContractDO::getCustomerId)); // 2. 获取创建人、负责人列表 - Map userMap = adminUserApi.getUserMap(convertListByFlatMap(contactList, + Map userMap = adminUserApi.getUserMap(convertListByFlatMap(contractList, contact -> Stream.of(NumberUtils.parseLong(contact.getCreator()), contact.getOwnerUserId()))); - return CrmContractConvert.INSTANCE.convertPage(pageResult, userMap, customerList); + // 3. 获取联系人 + Map contactMap = convertMap(contactService.getContactListByIds(convertSet(contractList, + CrmContractDO::getContactId)), CrmContactDO::getId); + // 4. 获取商机 + Map businessMap = convertMap(businessService.getBusinessList(convertSet(contractList, + CrmContractDO::getBusinessId)), CrmBusinessDO::getId); + return CrmContractConvert.INSTANCE.convertList(contractList, userMap, customerList, contactMap, businessMap); } @PutMapping("/transfer-contract") diff --git a/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/controller/admin/contract/vo/CrmContractRespVO.java b/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/controller/admin/contract/vo/CrmContractRespVO.java index 9e6c39a3a..238789794 100644 --- a/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/controller/admin/contract/vo/CrmContractRespVO.java +++ b/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/controller/admin/contract/vo/CrmContractRespVO.java @@ -29,10 +29,16 @@ public class CrmContractRespVO { @Schema(description = "客户编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "18336") @ExcelProperty("客户编号") private Long customerId; + @Schema(description = "客户名称", requiredMode = Schema.RequiredMode.REQUIRED, example = "18336") + @ExcelProperty("客户名称") + private String customerName; @Schema(description = "商机编号", example = "10864") @ExcelProperty("商机编号") private Long businessId; + @Schema(description = "商机名称", example = "10864") + @ExcelProperty("商机名称") + private String businessName; @Schema(description = "工作流编号", example = "1043") @ExcelProperty("工作流编号") @@ -77,10 +83,16 @@ public class CrmContractRespVO { @Schema(description = "联系人编号", example = "18546") @ExcelProperty("联系人编号") private Long contactId; + @Schema(description = "联系人编号", example = "18546") + @ExcelProperty("联系人编号") + private String contactName; @Schema(description = "公司签约人", example = "14036") @ExcelProperty("公司签约人") private Long signUserId; + @Schema(description = "公司签约人", example = "14036") + @ExcelProperty("公司签约人") + private String signUserName; @Schema(description = "最后跟进时间") @ExcelProperty("最后跟进时间") @@ -104,10 +116,6 @@ public class CrmContractRespVO { @ExcelProperty("创建人名字") private String creatorName; - @Schema(description = "客户名字", example = "test") - @ExcelProperty("客户名字") - private String customerName; - @Schema(description = "负责人", example = "test") @ExcelProperty("负责人") private String ownerUserName; diff --git a/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/controller/admin/customer/CrmCustomerController.java b/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/controller/admin/customer/CrmCustomerController.java index 09057fd78..d8c2f0289 100644 --- a/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/controller/admin/customer/CrmCustomerController.java +++ b/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/controller/admin/customer/CrmCustomerController.java @@ -232,10 +232,10 @@ public class CrmCustomerController { return success(customerService.importCustomerList(list, updateSupport, getLoginUserId())); } - @PutMapping("/transfer") + @PutMapping("/transfer-customer") @Operation(summary = "转移客户") @PreAuthorize("@ss.hasPermission('crm:customer:update')") - public CommonResult transfer(@Valid @RequestBody CrmCustomerTransferReqVO reqVO) { + public CommonResult transferCustomer(@Valid @RequestBody CrmCustomerTransferReqVO reqVO) { customerService.transferCustomer(reqVO, getLoginUserId()); return success(true); } diff --git a/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/controller/admin/followup/CrmFollowUpRecordController.java b/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/controller/admin/followup/CrmFollowUpRecordController.java index 735f2e887..f0b726353 100644 --- a/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/controller/admin/followup/CrmFollowUpRecordController.java +++ b/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/controller/admin/followup/CrmFollowUpRecordController.java @@ -75,7 +75,7 @@ public class CrmFollowUpRecordController { public CommonResult> getFollowUpRecordPage(@Valid CrmFollowUpRecordPageReqVO pageReqVO) { PageResult pageResult = followUpRecordService.getFollowUpRecordPage(pageReqVO); /// 拼接数据 - Map contactMap = convertMap(contactService.getContactList( + Map contactMap = convertMap(contactService.getContactListByIds( convertSetByFlatMap(pageResult.getList(), item -> item.getContactIds().stream())), CrmContactDO::getId); Map businessMap = convertMap(businessService.getBusinessList( convertSetByFlatMap(pageResult.getList(), item -> item.getBusinessIds().stream())), CrmBusinessDO::getId); diff --git a/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/convert/contract/CrmContractConvert.java b/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/convert/contract/CrmContractConvert.java index 599d998a6..c9247e6a5 100644 --- a/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/convert/contract/CrmContractConvert.java +++ b/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/convert/contract/CrmContractConvert.java @@ -1,9 +1,10 @@ package cn.iocoder.yudao.module.crm.convert.contract; -import cn.iocoder.yudao.framework.common.pojo.PageResult; import cn.iocoder.yudao.framework.common.util.object.BeanUtils; import cn.iocoder.yudao.module.crm.controller.admin.contract.vo.CrmContractRespVO; import cn.iocoder.yudao.module.crm.controller.admin.contract.vo.CrmContractTransferReqVO; +import cn.iocoder.yudao.module.crm.dal.dataobject.business.CrmBusinessDO; +import cn.iocoder.yudao.module.crm.dal.dataobject.contact.CrmContactDO; import cn.iocoder.yudao.module.crm.dal.dataobject.contract.CrmContractDO; import cn.iocoder.yudao.module.crm.dal.dataobject.customer.CrmCustomerDO; import cn.iocoder.yudao.module.crm.service.permission.bo.CrmPermissionTransferReqBO; @@ -31,17 +32,21 @@ public interface CrmContractConvert { @Mapping(target = "bizId", source = "reqVO.id") CrmPermissionTransferReqBO convert(CrmContractTransferReqVO reqVO, Long userId); - default PageResult convertPage(PageResult pageResult, Map userMap, - List customerList) { - PageResult voPageResult = BeanUtils.toBean(pageResult, CrmContractRespVO.class); + default List convertList(List contractList, Map userMap, + List customerList, Map contactMap, + Map businessMap) { + List respVOList = BeanUtils.toBean(contractList, CrmContractRespVO.class); // 拼接关联字段 Map customerMap = convertMap(customerList, CrmCustomerDO::getId); - voPageResult.getList().forEach(contract -> { + respVOList.forEach(contract -> { findAndThen(userMap, contract.getOwnerUserId(), user -> contract.setOwnerUserName(user.getNickname())); findAndThen(userMap, Long.parseLong(contract.getCreator()), user -> contract.setCreatorName(user.getNickname())); + findAndThen(userMap, contract.getSignUserId(), user -> contract.setSignUserName(user.getNickname())); findAndThen(customerMap, contract.getCustomerId(), customer -> contract.setCustomerName(customer.getName())); + findAndThen(contactMap, contract.getContactId(), contact -> contract.setContactName(contact.getName())); + findAndThen(businessMap, contract.getBusinessId(), business -> contract.setBusinessName(business.getName())); }); - return voPageResult; + return respVOList; } } diff --git a/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/service/contact/CrmContactService.java b/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/service/contact/CrmContactService.java index a43ed2e65..d7688b8fb 100644 --- a/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/service/contact/CrmContactService.java +++ b/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/service/contact/CrmContactService.java @@ -80,7 +80,7 @@ public interface CrmContactService { * @param userId 用户编号 * @return 联系人列表 */ - List getContactList(Collection ids, Long userId); + List getContactListByIds(Collection ids, Long userId); /** * 获得联系人列表 @@ -88,7 +88,7 @@ public interface CrmContactService { * @param ids 编号 * @return 联系人列表 */ - List getContactList(Collection ids); + List getContactListByIds(Collection ids); /** * 获得联系人列表 diff --git a/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/service/contact/CrmContactServiceImpl.java b/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/service/contact/CrmContactServiceImpl.java index 4c1a7fd95..08ce78b81 100644 --- a/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/service/contact/CrmContactServiceImpl.java +++ b/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/service/contact/CrmContactServiceImpl.java @@ -210,7 +210,7 @@ public class CrmContactServiceImpl implements CrmContactService { } @Override - public List getContactList(Collection ids, Long userId) { + public List getContactListByIds(Collection ids, Long userId) { if (CollUtil.isEmpty(ids)) { return ListUtil.empty(); } @@ -218,7 +218,7 @@ public class CrmContactServiceImpl implements CrmContactService { } @Override - public List getContactList(Collection ids) { + public List getContactListByIds(Collection ids) { if (CollUtil.isEmpty(ids)) { return ListUtil.empty(); } From ba6218b8351b5950fe4f86b23647d4a6ed0c2b6f Mon Sep 17 00:00:00 2001 From: puhui999 Date: Sat, 3 Feb 2024 22:13:02 +0800 Subject: [PATCH 064/119] =?UTF-8?q?CRM-=E5=90=88=E5=90=8C:=20transfer?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../crm/controller/admin/business/CrmBusinessController.java | 2 +- .../module/crm/controller/admin/clue/CrmClueController.java | 2 +- .../crm/controller/admin/contact/CrmContactController.java | 2 +- .../crm/controller/admin/contract/CrmContractController.java | 2 +- .../crm/controller/admin/customer/CrmCustomerController.java | 2 +- 5 files changed, 5 insertions(+), 5 deletions(-) diff --git a/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/controller/admin/business/CrmBusinessController.java b/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/controller/admin/business/CrmBusinessController.java index 85fe5b3f3..c85c151f5 100644 --- a/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/controller/admin/business/CrmBusinessController.java +++ b/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/controller/admin/business/CrmBusinessController.java @@ -166,7 +166,7 @@ public class CrmBusinessController { return CrmBusinessConvert.INSTANCE.convertPage(pageResult, customerList, statusTypeList, statusList); } - @PutMapping("/transfer-business") + @PutMapping("/transfer") @Operation(summary = "商机转移") @PreAuthorize("@ss.hasPermission('crm:business:update')") public CommonResult transferBusiness(@Valid @RequestBody CrmBusinessTransferReqVO reqVO) { diff --git a/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/controller/admin/clue/CrmClueController.java b/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/controller/admin/clue/CrmClueController.java index a2ddf3742..8be62ae26 100644 --- a/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/controller/admin/clue/CrmClueController.java +++ b/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/controller/admin/clue/CrmClueController.java @@ -88,7 +88,7 @@ public class CrmClueController { ExcelUtils.write(response, "线索.xls", "数据", CrmClueRespVO.class, datas); } - @PutMapping("/transfer-clue") + @PutMapping("/transfer") @Operation(summary = "线索转移") @PreAuthorize("@ss.hasPermission('crm:clue:update')") public CommonResult transferClue(@Valid @RequestBody CrmClueTransferReqVO reqVO) { diff --git a/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/controller/admin/contact/CrmContactController.java b/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/controller/admin/contact/CrmContactController.java index c00d57a6c..766adb02d 100644 --- a/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/controller/admin/contact/CrmContactController.java +++ b/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/controller/admin/contact/CrmContactController.java @@ -175,7 +175,7 @@ public class CrmContactController { return CrmContactConvert.INSTANCE.convertPage(pageResult, userMap, crmCustomerDOList, parentContactList); } - @PutMapping("/transfer-contact") + @PutMapping("/transfer") @Operation(summary = "联系人转移") @PreAuthorize("@ss.hasPermission('crm:contact:update')") public CommonResult transferContact(@Valid @RequestBody CrmContactTransferReqVO reqVO) { diff --git a/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/controller/admin/contract/CrmContractController.java b/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/controller/admin/contract/CrmContractController.java index 43bd49ea2..c050f6f57 100644 --- a/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/controller/admin/contract/CrmContractController.java +++ b/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/controller/admin/contract/CrmContractController.java @@ -168,7 +168,7 @@ public class CrmContractController { return CrmContractConvert.INSTANCE.convertList(contractList, userMap, customerList, contactMap, businessMap); } - @PutMapping("/transfer-contract") + @PutMapping("/transfer") @Operation(summary = "合同转移") @PreAuthorize("@ss.hasPermission('crm:contract:update')") public CommonResult transferContract(@Valid @RequestBody CrmContractTransferReqVO reqVO) { diff --git a/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/controller/admin/customer/CrmCustomerController.java b/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/controller/admin/customer/CrmCustomerController.java index d8c2f0289..407b2d0c8 100644 --- a/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/controller/admin/customer/CrmCustomerController.java +++ b/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/controller/admin/customer/CrmCustomerController.java @@ -232,7 +232,7 @@ public class CrmCustomerController { return success(customerService.importCustomerList(list, updateSupport, getLoginUserId())); } - @PutMapping("/transfer-customer") + @PutMapping("/transfer") @Operation(summary = "转移客户") @PreAuthorize("@ss.hasPermission('crm:customer:update')") public CommonResult transferCustomer(@Valid @RequestBody CrmCustomerTransferReqVO reqVO) { From 3347d3320dd75e91db3191239f5ee055f96617a9 Mon Sep 17 00:00:00 2001 From: YunaiV Date: Sun, 4 Feb 2024 09:41:50 +0800 Subject: [PATCH 065/119] =?UTF-8?q?=F0=9F=93=96=20CRM=EF=BC=9Acode=20revie?= =?UTF-8?q?w=20=E5=90=88=E5=90=8C=E7=9A=84=E4=BB=A3=E7=A0=81=E5=AE=9E?= =?UTF-8?q?=E7=8E=B0?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../api/listener/BpmResultListenerApi.java | 1 + .../dto/BpmResultListenerRespDTO.java | 1 + .../admin/definition/BpmModelController.java | 3 +- .../listener/BpmServiceResultListener.java | 1 + .../BpmProcessInstanceEventListener.java | 1 + .../admin/contract/CrmContractController.java | 18 +++++--- .../admin/contract/vo/CrmContractRespVO.java | 14 +++---- .../admin/customer/CrmCustomerController.java | 1 + .../business/CrmBusinessProductDO.java | 1 + .../dal/mysql/product/CrmProductMapper.java | 1 + .../business/CrmBusinessProductService.java | 20 ++++----- .../CrmBusinessProductServiceImpl.java | 12 +++--- .../business/CrmBusinessServiceImpl.java | 4 +- .../service/contract/CrmContractService.java | 1 + .../contract/CrmContractServiceImpl.java | 21 ++++++---- .../listener/CrmContractResultListener.java | 1 + .../customer/CrmCustomerServiceImpl.java | 42 +++++++++++++------ 17 files changed, 88 insertions(+), 55 deletions(-) diff --git a/yudao-module-bpm/yudao-module-bpm-api/src/main/java/cn/iocoder/yudao/module/bpm/api/listener/BpmResultListenerApi.java b/yudao-module-bpm/yudao-module-bpm-api/src/main/java/cn/iocoder/yudao/module/bpm/api/listener/BpmResultListenerApi.java index 65b038311..d519ed9ed 100644 --- a/yudao-module-bpm/yudao-module-bpm-api/src/main/java/cn/iocoder/yudao/module/bpm/api/listener/BpmResultListenerApi.java +++ b/yudao-module-bpm/yudao-module-bpm-api/src/main/java/cn/iocoder/yudao/module/bpm/api/listener/BpmResultListenerApi.java @@ -2,6 +2,7 @@ package cn.iocoder.yudao.module.bpm.api.listener; import cn.iocoder.yudao.module.bpm.api.listener.dto.BpmResultListenerRespDTO; +// TODO @芋艿:后续改成支持 RPC /** * 业务流程实例的结果发生变化的监听器 Api * diff --git a/yudao-module-bpm/yudao-module-bpm-api/src/main/java/cn/iocoder/yudao/module/bpm/api/listener/dto/BpmResultListenerRespDTO.java b/yudao-module-bpm/yudao-module-bpm-api/src/main/java/cn/iocoder/yudao/module/bpm/api/listener/dto/BpmResultListenerRespDTO.java index 75f9d02f0..30721785d 100644 --- a/yudao-module-bpm/yudao-module-bpm-api/src/main/java/cn/iocoder/yudao/module/bpm/api/listener/dto/BpmResultListenerRespDTO.java +++ b/yudao-module-bpm/yudao-module-bpm-api/src/main/java/cn/iocoder/yudao/module/bpm/api/listener/dto/BpmResultListenerRespDTO.java @@ -2,6 +2,7 @@ package cn.iocoder.yudao.module.bpm.api.listener.dto; import lombok.Data; +// TODO @芋艿:后续改成支持 RPC /** * 业务流程实例的结果 Response DTO * diff --git a/yudao-module-bpm/yudao-module-bpm-biz/src/main/java/cn/iocoder/yudao/module/bpm/controller/admin/definition/BpmModelController.java b/yudao-module-bpm/yudao-module-bpm-biz/src/main/java/cn/iocoder/yudao/module/bpm/controller/admin/definition/BpmModelController.java index 32b073c4b..a789bd495 100644 --- a/yudao-module-bpm/yudao-module-bpm-biz/src/main/java/cn/iocoder/yudao/module/bpm/controller/admin/definition/BpmModelController.java +++ b/yudao-module-bpm/yudao-module-bpm-biz/src/main/java/cn/iocoder/yudao/module/bpm/controller/admin/definition/BpmModelController.java @@ -43,7 +43,8 @@ public class BpmModelController { return success(model); } - // TODO @puhui999:这个接口的目的是啥呀?业务表单预览流程🤣 + // TODO @puhui999:这个接口的目的是啥呀?业务表单预览流程🤣; + // TODO @puhui999:捉摸是不是搞成前端跳转过去,不另外做 bpmn 组件哈; @GetMapping("/get-by-key") @Operation(summary = "获得模型") @Parameter(name = "key", description = "流程标识", required = true, example = "oa_leave") diff --git a/yudao-module-bpm/yudao-module-bpm-biz/src/main/java/cn/iocoder/yudao/module/bpm/framework/bpm/listener/BpmServiceResultListener.java b/yudao-module-bpm/yudao-module-bpm-biz/src/main/java/cn/iocoder/yudao/module/bpm/framework/bpm/listener/BpmServiceResultListener.java index 3081fb360..34a045a23 100644 --- a/yudao-module-bpm/yudao-module-bpm-biz/src/main/java/cn/iocoder/yudao/module/bpm/framework/bpm/listener/BpmServiceResultListener.java +++ b/yudao-module-bpm/yudao-module-bpm-biz/src/main/java/cn/iocoder/yudao/module/bpm/framework/bpm/listener/BpmServiceResultListener.java @@ -11,6 +11,7 @@ import org.springframework.stereotype.Component; import java.util.List; +// TODO @芋艿:后续改成支持 RPC /** * 业务流程结果监听器实现类 * diff --git a/yudao-module-bpm/yudao-module-bpm-biz/src/main/java/cn/iocoder/yudao/module/bpm/framework/flowable/core/listener/BpmProcessInstanceEventListener.java b/yudao-module-bpm/yudao-module-bpm-biz/src/main/java/cn/iocoder/yudao/module/bpm/framework/flowable/core/listener/BpmProcessInstanceEventListener.java index 441dc034d..9f37c9ae7 100644 --- a/yudao-module-bpm/yudao-module-bpm-biz/src/main/java/cn/iocoder/yudao/module/bpm/framework/flowable/core/listener/BpmProcessInstanceEventListener.java +++ b/yudao-module-bpm/yudao-module-bpm-biz/src/main/java/cn/iocoder/yudao/module/bpm/framework/flowable/core/listener/BpmProcessInstanceEventListener.java @@ -50,4 +50,5 @@ public class BpmProcessInstanceEventListener extends AbstractFlowableEngineEvent protected void processCompleted(FlowableEngineEntityEvent event) { processInstanceService.updateProcessInstanceExtComplete((ProcessInstance)event.getEntity()); } + } diff --git a/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/controller/admin/contract/CrmContractController.java b/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/controller/admin/contract/CrmContractController.java index c050f6f57..aaaccbd81 100644 --- a/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/controller/admin/contract/CrmContractController.java +++ b/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/controller/admin/contract/CrmContractController.java @@ -99,9 +99,17 @@ public class CrmContractController { @Parameter(name = "id", description = "编号", required = true, example = "1024") @PreAuthorize("@ss.hasPermission('crm:contract:query')") public CommonResult getContract(@RequestParam("id") Long id) { + // 1. 查询合同 CrmContractDO contract = contractService.getContract(id); - List respVOList = buildContractDetail(Collections.singletonList(contract)); - CrmContractRespVO respVO = respVOList.getFirst(); + if (contract == null) { + return success(null); + } + + // 2.1 拼接合同信息 + List respVOList = buildContractDetailList(Collections.singletonList(contract)); + // 2.2 拼接产品信息 + // TODO @puhui999:下面这块也可以搞到 convert 里哈;可以在 ContractDetailList 加个开关,是不是查询商品信息;ps:jdk21 的方法不太能去用,因为 jdk8 项目要兼容; + CrmContractRespVO respVO = respVOList.get(0); List businessProductList = businessProductService.getBusinessProductListByContractId(id); Map businessProductMap = convertMap(businessProductList, CrmBusinessProductDO::getProductId); List productList = productService.getProductListByIds(convertSet(businessProductList, CrmBusinessProductDO::getProductId)); @@ -120,7 +128,7 @@ public class CrmContractController { @PreAuthorize("@ss.hasPermission('crm:contract:query')") public CommonResult> getContractPage(@Valid CrmContractPageReqVO pageVO) { PageResult pageResult = contractService.getContractPage(pageVO, getLoginUserId()); - return success(BeanUtils.toBean(pageResult, CrmContractRespVO.class).setList(buildContractDetail(pageResult.getList()))); + return success(BeanUtils.toBean(pageResult, CrmContractRespVO.class).setList(buildContractDetailList(pageResult.getList()))); } @GetMapping("/page-by-customer") @@ -128,7 +136,7 @@ public class CrmContractController { public CommonResult> getContractPageByCustomer(@Valid CrmContractPageReqVO pageVO) { Assert.notNull(pageVO.getCustomerId(), "客户编号不能为空"); PageResult pageResult = contractService.getContractPageByCustomerId(pageVO); - return success(BeanUtils.toBean(pageResult, CrmContractRespVO.class).setList(buildContractDetail(pageResult.getList()))); + return success(BeanUtils.toBean(pageResult, CrmContractRespVO.class).setList(buildContractDetailList(pageResult.getList()))); } @GetMapping("/export-excel") @@ -149,7 +157,7 @@ public class CrmContractController { * @param contractList 原始合同信息 * @return 细的合同结果 */ - private List buildContractDetail(List contractList) { + private List buildContractDetailList(List contractList) { if (CollUtil.isEmpty(contractList)) { return Collections.emptyList(); } diff --git a/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/controller/admin/contract/vo/CrmContractRespVO.java b/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/controller/admin/contract/vo/CrmContractRespVO.java index 238789794..9de416257 100644 --- a/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/controller/admin/contract/vo/CrmContractRespVO.java +++ b/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/controller/admin/contract/vo/CrmContractRespVO.java @@ -133,25 +133,25 @@ public class CrmContractRespVO { @AllArgsConstructor public static class CrmContractProductItemRespVO { - @Schema(description = "产品编号", example = "20529") + @Schema(description = "产品编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "20529") private Long id; - @Schema(description = "产品名称", requiredMode = Schema.RequiredMode.REQUIRED, example = "8911") + @Schema(description = "产品名称", requiredMode = Schema.RequiredMode.REQUIRED, example = "我是产品") private String name; - @Schema(description = "产品编码", requiredMode = Schema.RequiredMode.REQUIRED, example = "8911") + @Schema(description = "产品编码", requiredMode = Schema.RequiredMode.REQUIRED, example = "N881") private String no; - @Schema(description = "单位", requiredMode = Schema.RequiredMode.REQUIRED, example = "8911") + @Schema(description = "单位", requiredMode = Schema.RequiredMode.REQUIRED, example = "10") private Integer unit; - @Schema(description = "价格,单位:分", requiredMode = Schema.RequiredMode.REQUIRED, example = "8911") + @Schema(description = "价格,单位:分", requiredMode = Schema.RequiredMode.REQUIRED, example = "100") private Integer price; - @Schema(description = "产品数量", requiredMode = Schema.RequiredMode.REQUIRED, example = "8911") + @Schema(description = "产品数量", requiredMode = Schema.RequiredMode.REQUIRED, example = "20") private Integer count; - @Schema(description = "产品折扣") + @Schema(description = "产品折扣", example = "99") private Integer discountPercent; } diff --git a/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/controller/admin/customer/CrmCustomerController.java b/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/controller/admin/customer/CrmCustomerController.java index 407b2d0c8..ddd2a7f70 100644 --- a/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/controller/admin/customer/CrmCustomerController.java +++ b/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/controller/admin/customer/CrmCustomerController.java @@ -188,6 +188,7 @@ public class CrmCustomerController { new CrmCustomerRespVO().setId(customer.getId()).setName(customer.getName()))); } + // TODO @puhui999:公海的导出,前端可以接下 @GetMapping("/export-excel") @Operation(summary = "导出客户 Excel") @PreAuthorize("@ss.hasPermission('crm:customer:export')") diff --git a/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/dal/dataobject/business/CrmBusinessProductDO.java b/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/dal/dataobject/business/CrmBusinessProductDO.java index 2d801ff5b..77c5ba779 100644 --- a/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/dal/dataobject/business/CrmBusinessProductDO.java +++ b/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/dal/dataobject/business/CrmBusinessProductDO.java @@ -41,6 +41,7 @@ public class CrmBusinessProductDO extends BaseDO { * 关联 {@link CrmProductDO#getId()} */ private Long productId; + // TODO 芋艿:需要在看下 CRM /** * 合同编号 * diff --git a/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/dal/mysql/product/CrmProductMapper.java b/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/dal/mysql/product/CrmProductMapper.java index 3d696de7e..8a7fa600b 100644 --- a/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/dal/mysql/product/CrmProductMapper.java +++ b/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/dal/mysql/product/CrmProductMapper.java @@ -38,6 +38,7 @@ public interface CrmProductMapper extends BaseMapperX { return selectOne(CrmProductDO::getNo, no); } + // TODO @puhui999:selectBatchIds default List selectListByIds(Collection ids) { return selectList(new LambdaQueryWrapperX().in(CrmProductDO::getId, ids)); } diff --git a/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/service/business/CrmBusinessProductService.java b/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/service/business/CrmBusinessProductService.java index f819b5907..a68ac37b9 100644 --- a/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/service/business/CrmBusinessProductService.java +++ b/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/service/business/CrmBusinessProductService.java @@ -4,8 +4,6 @@ import cn.iocoder.yudao.module.crm.dal.dataobject.business.CrmBusinessProductDO; import java.util.List; -// TODO @lzxhqs:方法名上,带下 BusinessProduct;主要考虑不精简的原因,是因为一个逻辑,可能会出现一些超越它自身方法,省略不容易懂; - /** * 商机产品关联表 Service 接口 * @@ -20,13 +18,6 @@ public interface CrmBusinessProductService { */ void createBusinessProductBatch(List list); - /** - * 根据商机id获取商机产品关联数据集合 - * - * @param businessId 商机id - */ - List getBusinessProductListByBusinessId(Long businessId); - /** * 批量更新商机产品表 * @@ -42,14 +33,21 @@ public interface CrmBusinessProductService { void deleteBusinessProductBatch(List list); /** - * 根据商机id删除商机产品关联数据 + * 根据商机编号,删除商机产品关联数据 * * @param businessId 商机id */ void deleteBusinessProductByBusinessId(Long businessId); /** - * 获得合同关联的商品列表 + * 根据商机编号,获取商机产品关联数据集合 + * + * @param businessId 商机编号 + */ + List getBusinessProductListByBusinessId(Long businessId); + + /** + * 根据合同编号,获得合同关联的商品列表 * * @param contractId 合同编号 * @return 关联的商品列表 diff --git a/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/service/business/CrmBusinessProductServiceImpl.java b/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/service/business/CrmBusinessProductServiceImpl.java index 88115a86a..0762d4555 100644 --- a/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/service/business/CrmBusinessProductServiceImpl.java +++ b/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/service/business/CrmBusinessProductServiceImpl.java @@ -26,17 +26,12 @@ public class CrmBusinessProductServiceImpl implements CrmBusinessProductService businessProductMapper.insertBatch(list); } - @Override - public List getBusinessProductListByBusinessId(Long businessId) { - return businessProductMapper.selectList(CrmBusinessProductDO::getBusinessId, businessId); - } - @Override public void updateBusinessProductBatch(List list) { businessProductMapper.updateBatch(list); } - // TODO @lzxhqs:这个方法,可以直接调用 deleteList 方法,然后传递 ids 就好了; + // TODO @puhui999:这个方法,可以直接调用 deleteList 方法,然后传递 ids 就好了; @Override public void deleteBusinessProductBatch(List list) { businessProductMapper.deleteBatchIds(CollectionUtils.convertList(list, CrmBusinessProductDO::getId)); @@ -52,4 +47,9 @@ public class CrmBusinessProductServiceImpl implements CrmBusinessProductService return businessProductMapper.selectList(CrmBusinessProductDO::getContractId, contractId); } + @Override + public List getBusinessProductListByBusinessId(Long businessId) { + return businessProductMapper.selectList(CrmBusinessProductDO::getBusinessId, businessId); + } + } diff --git a/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/service/business/CrmBusinessServiceImpl.java b/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/service/business/CrmBusinessServiceImpl.java index 1daad016a..df7348cfe 100644 --- a/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/service/business/CrmBusinessServiceImpl.java +++ b/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/service/business/CrmBusinessServiceImpl.java @@ -195,9 +195,7 @@ public class CrmBusinessServiceImpl implements CrmBusinessService { * @author lzxhqs */ private void validateContractExists(Long businessId) { - // TODO @lzxhqs:保持风格的统一,selectCountByBusinessId 改成 getContractCountByBusinessId;另外,可以不用声明 count,因为就一次性使用,直接把 197 和 198 合并成一行; - Long count = contractService.getContractCountByBusinessId(businessId); - if (count > 0) { + if (contractService.getContractCountByBusinessId(businessId) > 0) { throw exception(BUSINESS_CONTRACT_EXISTS); } } diff --git a/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/service/contract/CrmContractService.java b/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/service/contract/CrmContractService.java index cb06e99e0..3e79b73ed 100644 --- a/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/service/contract/CrmContractService.java +++ b/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/service/contract/CrmContractService.java @@ -72,6 +72,7 @@ public interface CrmContractService { * @param event 审批结果 */ void updateContractAuditStatus(BpmResultListenerRespDTO event); + /** * 获得合同 * diff --git a/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/service/contract/CrmContractServiceImpl.java b/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/service/contract/CrmContractServiceImpl.java index 87f1c20e4..4af609edd 100644 --- a/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/service/contract/CrmContractServiceImpl.java +++ b/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/service/contract/CrmContractServiceImpl.java @@ -113,24 +113,24 @@ public class CrmContractServiceImpl implements CrmContractService { @CrmPermission(bizType = CrmBizTypeEnum.CRM_CONTRACT, bizId = "#updateReqVO.id", level = CrmPermissionLevelEnum.WRITE) public void updateContract(CrmContractSaveReqVO updateReqVO) { Assert.notNull(updateReqVO.getId(), "合同编号不能为空"); + // 1.1 校验存在 CrmContractDO contract = validateContractExists(updateReqVO.getId()); - // 只有草稿、审批中,可以编辑; + // 1.2 只有草稿、审批中,可以编辑; if (!ObjectUtils.equalsAny(contract.getAuditStatus(), CrmAuditStatusEnum.DRAFT.getStatus(), CrmAuditStatusEnum.PROCESS.getStatus())) { throw exception(CONTRACT_UPDATE_FAIL_EDITING_PROHIBITED); } validateRelationDataExists(updateReqVO); - // 校验存在 - CrmContractDO oldContract = validateContractExists(updateReqVO.getId()); - // 更新合同 + + // 2.1 更新合同 CrmContractDO updateObj = BeanUtils.toBean(updateReqVO, CrmContractDO.class); contractMapper.updateById(updateObj); - // 更新合同关联商品 + // 2.2 更新合同关联商品 updateContractProduct(updateReqVO, updateObj.getId()); // 3. 记录操作日志上下文 - LogRecordContext.putVariable(DiffParseFunction.OLD_OBJECT, BeanUtils.toBean(oldContract, CrmContractSaveReqVO.class)); - LogRecordContext.putVariable("contractName", oldContract.getName()); + LogRecordContext.putVariable(DiffParseFunction.OLD_OBJECT, BeanUtils.toBean(contract, CrmContractSaveReqVO.class)); + LogRecordContext.putVariable("contractName", contract.getName()); } private void updateContractProduct(CrmContractSaveReqVO updateReqVO, Long contractId) { @@ -248,23 +248,26 @@ public class CrmContractServiceImpl implements CrmContractService { @Override @Transactional(rollbackFor = Exception.class) + // TODO @puhui999:操作日志; public void submitContract(Long id, Long userId) { // 1. 校验合同是否在审批 CrmContractDO contract = validateContractExists(id); if (ObjUtil.notEqual(contract.getAuditStatus(), CrmAuditStatusEnum.DRAFT.getStatus())) { throw exception(CONTRACT_SUBMIT_FAIL_NOT_DRAFT); } - // 创建合同审批流程实例 + + // 2. 创建合同审批流程实例 String processInstanceId = bpmProcessInstanceApi.createProcessInstance(userId, new BpmProcessInstanceCreateReqDTO() .setProcessDefinitionKey(CONTRACT_APPROVE).setBusinessKey(String.valueOf(id))); - // 更新合同工作流编号 + // 3. 更新合同工作流编号 contractMapper.updateById(new CrmContractDO().setId(id).setProcessInstanceId(processInstanceId) .setAuditStatus(CrmAuditStatusEnum.PROCESS.getStatus())); } @Override public void updateContractAuditStatus(BpmResultListenerRespDTO event) { + // TODO @puhui999:可能要判断下状态是否符合预期 contractMapper.updateById(new CrmContractDO().setId(Long.parseLong(event.getBusinessKey())) .setAuditStatus(event.getResult())); } diff --git a/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/service/contract/listener/CrmContractResultListener.java b/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/service/contract/listener/CrmContractResultListener.java index 783579fc6..dc278f337 100644 --- a/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/service/contract/listener/CrmContractResultListener.java +++ b/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/service/contract/listener/CrmContractResultListener.java @@ -11,6 +11,7 @@ import cn.iocoder.yudao.module.crm.service.contract.CrmContractServiceImpl; import jakarta.annotation.Resource; import org.springframework.stereotype.Component; +// TODO @芋艿:后续改成支持 RPC /** * 合同审批的结果的监听器实现类 * diff --git a/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/service/customer/CrmCustomerServiceImpl.java b/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/service/customer/CrmCustomerServiceImpl.java index 6a38973c8..eeea1efdf 100644 --- a/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/service/customer/CrmCustomerServiceImpl.java +++ b/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/service/customer/CrmCustomerServiceImpl.java @@ -105,6 +105,18 @@ public class CrmCustomerServiceImpl implements CrmCustomerService { return customer.getId(); } + /** + * 初始化客户的通用字段 + * + * @param customer 客户信息 + * @param ownerUserId 负责人编号 + * @return 客户信息 DO + */ + private static CrmCustomerDO initCustomer(Object customer, Long ownerUserId) { + return BeanUtils.toBean(customer, CrmCustomerDO.class).setOwnerUserId(ownerUserId) + .setLockStatus(false).setDealStatus(false).setContactLastTime(LocalDateTime.now()); + } + @Override @Transactional(rollbackFor = Exception.class) @LogRecord(type = CRM_CUSTOMER_TYPE, subType = CRM_CUSTOMER_UPDATE_SUB_TYPE, bizNo = "{{#updateReqVO.id}}", @@ -248,44 +260,47 @@ public class CrmCustomerServiceImpl implements CrmCustomerService { respVO.getFailureCustomerNames().put(importCustomer.getName(), ex.getMessage()); return; } - // 判断如果不存在,在进行插入 + // 情况一:判断如果不存在,在进行插入 CrmCustomerDO existCustomer = customerMapper.selectByCustomerName(importCustomer.getName()); if (existCustomer == null) { + // 1.1 插入客户信息 CrmCustomerDO customer = initCustomer(importCustomer, userId); customerMapper.insert(customer); respVO.getCreateCustomerNames().add(importCustomer.getName()); - // 创建数据权限 + // 1.2 创建数据权限 permissionService.createPermission(new CrmPermissionCreateReqBO().setBizType(CrmBizTypeEnum.CRM_CUSTOMER.getType()) .setBizId(customer.getId()).setUserId(userId).setLevel(CrmPermissionLevelEnum.OWNER.getLevel())); // 设置当前操作的人为负责人 - // 记录操作日志 + // 1.3 记录操作日志 getSelf().importCustomerLog(customer, false); return; } - // 如果存在,判断是否允许更新 + + // 情况二:如果存在,判断是否允许更新 if (!isUpdateSupport) { respVO.getFailureCustomerNames().put(importCustomer.getName(), StrUtil.format(CUSTOMER_NAME_EXISTS.getMsg(), importCustomer.getName())); return; } - CrmCustomerDO updateCustomer = BeanUtils.toBean(importCustomer, CrmCustomerDO.class); - updateCustomer.setId(existCustomer.getId()); + // 2.1 更新客户信息 + CrmCustomerDO updateCustomer = BeanUtils.toBean(importCustomer, CrmCustomerDO.class) + .setId(existCustomer.getId()); customerMapper.updateById(updateCustomer); respVO.getUpdateCustomerNames().add(importCustomer.getName()); - // 记录操作日志 + // 2.2 记录操作日志 getSelf().importCustomerLog(updateCustomer, true); }); return respVO; } - private static CrmCustomerDO initCustomer(Object customer, Long userId) { - return BeanUtils.toBean(customer, CrmCustomerDO.class).setOwnerUserId(userId) - .setLockStatus(false).setDealStatus(false).setContactLastTime(LocalDateTime.now()); - } - + /** + * 记录导入客户时的操作日志 + * + * @param customer 客户信息 + * @param isUpdate 是否更新;true - 更新,false - 新增 + */ @LogRecord(type = CRM_CUSTOMER_TYPE, subType = CRM_CUSTOMER_IMPORT_SUB_TYPE, bizNo = "{{#customer.id}}", success = CRM_CUSTOMER_IMPORT_SUCCESS) public void importCustomerLog(CrmCustomerDO customer, boolean isUpdate) { - // 记录操作日志上下文 LogRecordContext.putVariable("customer", customer); LogRecordContext.putVariable("isUpdate", isUpdate); } @@ -382,6 +397,7 @@ public class CrmCustomerServiceImpl implements CrmCustomerService { } // 1.1 获取没有锁定的不在公海的客户 List customerList = customerMapper.selectListByLockAndNotPool(Boolean.FALSE); + // TODO @puhui999:下面也搞到 sql 里去哈;写 or 查询,问题不大的;低 393 到 402;原因是,避免无用的太多数据查询到 java 进程里; List poolCustomerList = new ArrayList<>(); poolCustomerList.addAll(filterList(customerList, customer -> !customer.getDealStatus() && (poolConfig.getDealExpireDays() - LocalDateTimeUtils.between(customer.getCreateTime())) <= 0)); From bf8ec2214419ee2dde01e762a62325839587fbaf Mon Sep 17 00:00:00 2001 From: YunaiV Date: Sun, 4 Feb 2024 12:57:26 +0800 Subject: [PATCH 066/119] =?UTF-8?q?=F0=9F=93=96=20CRM=EF=BC=9Acode=20revie?= =?UTF-8?q?w=20=E5=90=88=E5=90=8C=E7=9A=84=E4=BB=A3=E7=A0=81=E5=AE=9E?= =?UTF-8?q?=E7=8E=B0?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../admin/definition/BpmModelController.java | 11 -------- .../service/definition/BpmModelService.java | 8 ------ .../definition/BpmModelServiceImpl.java | 13 --------- .../admin/contract/vo/CrmContractExcelVO.java | 1 + .../admin/contract/vo/CrmContractRespVO.java | 5 ++++ .../dataobject/contract/CrmContractDO.java | 27 ++++++++++++++----- 6 files changed, 26 insertions(+), 39 deletions(-) diff --git a/yudao-module-bpm/yudao-module-bpm-biz/src/main/java/cn/iocoder/yudao/module/bpm/controller/admin/definition/BpmModelController.java b/yudao-module-bpm/yudao-module-bpm-biz/src/main/java/cn/iocoder/yudao/module/bpm/controller/admin/definition/BpmModelController.java index a789bd495..4e7195ccd 100644 --- a/yudao-module-bpm/yudao-module-bpm-biz/src/main/java/cn/iocoder/yudao/module/bpm/controller/admin/definition/BpmModelController.java +++ b/yudao-module-bpm/yudao-module-bpm-biz/src/main/java/cn/iocoder/yudao/module/bpm/controller/admin/definition/BpmModelController.java @@ -43,17 +43,6 @@ public class BpmModelController { return success(model); } - // TODO @puhui999:这个接口的目的是啥呀?业务表单预览流程🤣; - // TODO @puhui999:捉摸是不是搞成前端跳转过去,不另外做 bpmn 组件哈; - @GetMapping("/get-by-key") - @Operation(summary = "获得模型") - @Parameter(name = "key", description = "流程标识", required = true, example = "oa_leave") - @PreAuthorize("@ss.hasPermission('bpm:model:query')") - public CommonResult getModelByKey(@RequestParam("key") String key) { - BpmModelRespVO model = modelService.getBpmnModelByKey(key); - return success(model); - } - @PostMapping("/create") @Operation(summary = "新建模型") @PreAuthorize("@ss.hasPermission('bpm:model:create')") diff --git a/yudao-module-bpm/yudao-module-bpm-biz/src/main/java/cn/iocoder/yudao/module/bpm/service/definition/BpmModelService.java b/yudao-module-bpm/yudao-module-bpm-biz/src/main/java/cn/iocoder/yudao/module/bpm/service/definition/BpmModelService.java index 4c3b0ba10..bddd79081 100644 --- a/yudao-module-bpm/yudao-module-bpm-biz/src/main/java/cn/iocoder/yudao/module/bpm/service/definition/BpmModelService.java +++ b/yudao-module-bpm/yudao-module-bpm-biz/src/main/java/cn/iocoder/yudao/module/bpm/service/definition/BpmModelService.java @@ -37,14 +37,6 @@ public interface BpmModelService { */ BpmModelRespVO getModel(String id); - /** - * 获得流程模块 - * - * @param key 流程标识 - * @return 流程模型 - */ - BpmModelRespVO getBpmnModelByKey(String key); - /** * 修改流程模型 * diff --git a/yudao-module-bpm/yudao-module-bpm-biz/src/main/java/cn/iocoder/yudao/module/bpm/service/definition/BpmModelServiceImpl.java b/yudao-module-bpm/yudao-module-bpm-biz/src/main/java/cn/iocoder/yudao/module/bpm/service/definition/BpmModelServiceImpl.java index e23ac90e5..08f8acf6b 100644 --- a/yudao-module-bpm/yudao-module-bpm-biz/src/main/java/cn/iocoder/yudao/module/bpm/service/definition/BpmModelServiceImpl.java +++ b/yudao-module-bpm/yudao-module-bpm-biz/src/main/java/cn/iocoder/yudao/module/bpm/service/definition/BpmModelServiceImpl.java @@ -134,19 +134,6 @@ public class BpmModelServiceImpl implements BpmModelService { return modelRespVO; } - @Override - public BpmModelRespVO getBpmnModelByKey(String key) { - Model model = getModelByKey(key); - if (model == null) { - return null; - } - BpmModelRespVO modelRespVO = BpmModelConvert.INSTANCE.convert(model); - // 拼接 bpmn XML - byte[] bpmnBytes = repositoryService.getModelEditorSource(model.getId()); - modelRespVO.setBpmnXml(StrUtil.utf8Str(bpmnBytes)); - return modelRespVO; - } - @Override @Transactional(rollbackFor = Exception.class) // 因为进行多个操作,所以开启事务 public void updateModel(@Valid BpmModelUpdateReqVO updateReqVO) { diff --git a/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/controller/admin/contract/vo/CrmContractExcelVO.java b/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/controller/admin/contract/vo/CrmContractExcelVO.java index 72f9f3cfa..841e56426 100644 --- a/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/controller/admin/contract/vo/CrmContractExcelVO.java +++ b/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/controller/admin/contract/vo/CrmContractExcelVO.java @@ -5,6 +5,7 @@ import lombok.Data; import java.time.LocalDateTime; +// TODO @puhui999:合并到 RespVO 里哈; /** * CRM 合同 Excel VO * diff --git a/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/controller/admin/contract/vo/CrmContractRespVO.java b/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/controller/admin/contract/vo/CrmContractRespVO.java index 9de416257..6b60afc2a 100644 --- a/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/controller/admin/contract/vo/CrmContractRespVO.java +++ b/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/controller/admin/contract/vo/CrmContractRespVO.java @@ -116,6 +116,11 @@ public class CrmContractRespVO { @ExcelProperty("创建人名字") private String creatorName; + @Schema(description = "更新时间", requiredMode = Schema.RequiredMode.REQUIRED) + @ExcelProperty("更新时间") + @DateTimeFormat(pattern = FORMAT_YEAR_MONTH_DAY_HOUR_MINUTE_SECOND) + private LocalDateTime updateTime; + @Schema(description = "负责人", example = "test") @ExcelProperty("负责人") private String ownerUserName; diff --git a/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/dal/dataobject/contract/CrmContractDO.java b/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/dal/dataobject/contract/CrmContractDO.java index e70e7a3cb..0c01a3394 100644 --- a/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/dal/dataobject/contract/CrmContractDO.java +++ b/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/dal/dataobject/contract/CrmContractDO.java @@ -1,6 +1,9 @@ package cn.iocoder.yudao.module.crm.dal.dataobject.contract; import cn.iocoder.yudao.framework.mybatis.core.dataobject.BaseDO; +import cn.iocoder.yudao.module.crm.dal.dataobject.business.CrmBusinessDO; +import cn.iocoder.yudao.module.crm.dal.dataobject.contact.CrmContactDO; +import cn.iocoder.yudao.module.crm.dal.dataobject.customer.CrmCustomerDO; import cn.iocoder.yudao.module.crm.enums.common.CrmAuditStatusEnum; import com.baomidou.mybatisplus.annotation.KeySequence; import com.baomidou.mybatisplus.annotation.TableId; @@ -30,30 +33,36 @@ public class CrmContractDO extends BaseDO { */ @TableId private Long id; + /** + * 合同编号 + */ + private String no; /** * 合同名称 */ private String name; /** * 客户编号 + * + * 关联 {@link CrmCustomerDO#getId()} */ private Long customerId; /** * 商机编号 + * + * 关联 {@link CrmBusinessDO#getId()} */ private Long businessId; /** * 工作流编号 + * + * 关联 ProcessInstance 的 id 属性 */ private String processInstanceId; /** * 下单日期 */ private LocalDateTime orderDate; - /** - * 合同编号 - */ - private String no; /** * 开始时间 */ @@ -63,7 +72,7 @@ public class CrmContractDO extends BaseDO { */ private LocalDateTime endTime; /** - * 合同金额 + * 合同金额,单位:分 */ private Integer price; /** @@ -71,15 +80,19 @@ public class CrmContractDO extends BaseDO { */ private Integer discountPercent; /** - * 产品总金额 + * 产品总金额,单位:分 */ private Integer productPrice; /** - * 联系人编号 + * 客户签约人 + * + * 关联 {@link CrmContactDO#getId()} */ private Long contactId; /** * 公司签约人 + * + * 关联 AdminUserDO 的 id 字段 */ private Long signUserId; /** From 478db1bd39b7fd6c13e0c08afd11c5009650358f Mon Sep 17 00:00:00 2001 From: owen Date: Sun, 4 Feb 2024 19:44:25 +0800 Subject: [PATCH 067/119] =?UTF-8?q?=E5=9F=BA=E7=A1=80=E8=AE=BE=E6=96=BD?= =?UTF-8?q?=EF=BC=9A=E5=A2=9E=E5=8A=A0=E5=89=8D=E7=AB=AF=E7=9B=B4=E8=BF=9E?= =?UTF-8?q?=E4=B8=8A=E4=BC=A0=E6=96=87=E4=BB=B6=E5=88=B0S3=E6=9C=8D?= =?UTF-8?q?=E5=8A=A1=E7=9A=84=E5=8A=9F=E8=83=BD?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../file/core/client/FileClient.java | 14 ++++++-- .../file/core/client/s3/S3FileClient.java | 16 +++++++++ .../controller/admin/file/FileController.java | 29 ++++++++++------ .../admin/file/vo/file/FileCreateReqVO.java | 33 +++++++++++++++++++ .../file/vo/file/FilePresignedUrlRespVO.java | 20 +++++++++++ .../infra/service/file/FileService.java | 26 ++++++++++++--- .../infra/service/file/FileServiceImpl.java | 22 +++++++++++-- 7 files changed, 142 insertions(+), 18 deletions(-) create mode 100644 yudao-module-infra/yudao-module-infra-biz/src/main/java/cn/iocoder/yudao/module/infra/controller/admin/file/vo/file/FileCreateReqVO.java create mode 100644 yudao-module-infra/yudao-module-infra-biz/src/main/java/cn/iocoder/yudao/module/infra/controller/admin/file/vo/file/FilePresignedUrlRespVO.java diff --git a/yudao-framework/yudao-spring-boot-starter-file/src/main/java/cn/iocoder/yudao/framework/file/core/client/FileClient.java b/yudao-framework/yudao-spring-boot-starter-file/src/main/java/cn/iocoder/yudao/framework/file/core/client/FileClient.java index fb576d508..6663eb663 100644 --- a/yudao-framework/yudao-spring-boot-starter-file/src/main/java/cn/iocoder/yudao/framework/file/core/client/FileClient.java +++ b/yudao-framework/yudao-spring-boot-starter-file/src/main/java/cn/iocoder/yudao/framework/file/core/client/FileClient.java @@ -18,11 +18,11 @@ public interface FileClient { * 上传文件 * * @param content 文件流 - * @param path 相对路径 + * @param path 相对路径 * @return 完整路径,即 HTTP 访问地址 * @throws Exception 上传文件时,抛出 Exception 异常 */ - String upload(byte[] content, String path, String type) throws Exception; + String upload(byte[] content, String path, String type) throws Exception; /** * 删除文件 @@ -40,4 +40,14 @@ public interface FileClient { */ byte[] getContent(String path) throws Exception; + /** + * 获得文件预签名地址 + * + * @param fileName 文件名称 + * @return 文件预签名地址 + */ + default String getPresignedObjectUrl(String fileName) throws Exception { + throw new UnsupportedOperationException("不支持的操作"); + } + } diff --git a/yudao-framework/yudao-spring-boot-starter-file/src/main/java/cn/iocoder/yudao/framework/file/core/client/s3/S3FileClient.java b/yudao-framework/yudao-spring-boot-starter-file/src/main/java/cn/iocoder/yudao/framework/file/core/client/s3/S3FileClient.java index 49238f8f9..5d9d19c35 100644 --- a/yudao-framework/yudao-spring-boot-starter-file/src/main/java/cn/iocoder/yudao/framework/file/core/client/s3/S3FileClient.java +++ b/yudao-framework/yudao-spring-boot-starter-file/src/main/java/cn/iocoder/yudao/framework/file/core/client/s3/S3FileClient.java @@ -5,8 +5,10 @@ import cn.hutool.core.util.StrUtil; import cn.hutool.http.HttpUtil; import cn.iocoder.yudao.framework.file.core.client.AbstractFileClient; import io.minio.*; +import io.minio.http.Method; import java.io.ByteArrayInputStream; +import java.util.concurrent.TimeUnit; import static cn.iocoder.yudao.framework.file.core.client.s3.S3FileClientConfig.ENDPOINT_ALIYUN; import static cn.iocoder.yudao.framework.file.core.client.s3.S3FileClientConfig.ENDPOINT_TENCENT; @@ -117,4 +119,18 @@ public class S3FileClient extends AbstractFileClient { return IoUtil.readBytes(response); } + @Override + public String getPresignedObjectUrl(String fileName) throws Exception { + return client.getPresignedObjectUrl(GetPresignedObjectUrlArgs.builder() + .method(Method.PUT) + .bucket(config.getBucket()) + .object(fileName) + /** + * 过期时间(秒数)取值范围:1秒 ~ 7天 + * {@link GetPresignedObjectUrlArgs.Builder#validateExpiry(int)} + */ + .expiry(10, TimeUnit.MINUTES) + .build() + ); + } } diff --git a/yudao-module-infra/yudao-module-infra-biz/src/main/java/cn/iocoder/yudao/module/infra/controller/admin/file/FileController.java b/yudao-module-infra/yudao-module-infra-biz/src/main/java/cn/iocoder/yudao/module/infra/controller/admin/file/FileController.java index 3d3cd7ed6..0ebaffb05 100644 --- a/yudao-module-infra/yudao-module-infra-biz/src/main/java/cn/iocoder/yudao/module/infra/controller/admin/file/FileController.java +++ b/yudao-module-infra/yudao-module-infra-biz/src/main/java/cn/iocoder/yudao/module/infra/controller/admin/file/FileController.java @@ -8,14 +8,17 @@ import cn.iocoder.yudao.framework.common.pojo.PageResult; import cn.iocoder.yudao.framework.common.util.object.BeanUtils; import cn.iocoder.yudao.framework.common.util.servlet.ServletUtils; import cn.iocoder.yudao.framework.operatelog.core.annotations.OperateLog; -import cn.iocoder.yudao.module.infra.controller.admin.file.vo.file.FilePageReqVO; -import cn.iocoder.yudao.module.infra.controller.admin.file.vo.file.FileRespVO; -import cn.iocoder.yudao.module.infra.controller.admin.file.vo.file.FileUploadReqVO; +import cn.iocoder.yudao.module.infra.controller.admin.file.vo.file.*; import cn.iocoder.yudao.module.infra.dal.dataobject.file.FileDO; import cn.iocoder.yudao.module.infra.service.file.FileService; import io.swagger.v3.oas.annotations.Operation; import io.swagger.v3.oas.annotations.Parameter; import io.swagger.v3.oas.annotations.tags.Tag; +import jakarta.annotation.Resource; +import jakarta.annotation.security.PermitAll; +import jakarta.servlet.http.HttpServletRequest; +import jakarta.servlet.http.HttpServletResponse; +import jakarta.validation.Valid; import lombok.extern.slf4j.Slf4j; import org.springframework.http.HttpStatus; import org.springframework.security.access.prepost.PreAuthorize; @@ -23,12 +26,6 @@ import org.springframework.validation.annotation.Validated; import org.springframework.web.bind.annotation.*; import org.springframework.web.multipart.MultipartFile; -import jakarta.annotation.Resource; -import jakarta.annotation.security.PermitAll; -import jakarta.servlet.http.HttpServletRequest; -import jakarta.servlet.http.HttpServletResponse; -import jakarta.validation.Valid; - import static cn.iocoder.yudao.framework.common.pojo.CommonResult.success; @Tag(name = "管理后台 - 文件存储") @@ -50,6 +47,18 @@ public class FileController { return success(fileService.createFile(file.getOriginalFilename(), path, IoUtil.readBytes(file.getInputStream()))); } + @GetMapping("/presigned-url") + @Operation(summary = "获取文件预签名地址") + public CommonResult getFilePresignedUrl(@RequestParam("fileName") String fileName) throws Exception { + return success(fileService.getFilePresignedUrl(fileName)); + } + + @PostMapping("/create") + @Operation(summary = "创建文件") + public CommonResult createFile(@Valid @RequestBody FileCreateReqVO createReqVO) { + return success(fileService.createFile(createReqVO)); + } + @DeleteMapping("/delete") @Operation(summary = "删除文件") @Parameter(name = "id", description = "编号", required = true) @@ -62,7 +71,7 @@ public class FileController { @GetMapping("/{configId}/get/**") @PermitAll @Operation(summary = "下载文件") - @Parameter(name = "configId", description = "配置编号", required = true) + @Parameter(name = "configId", description = "配置编号", required = true) public void getFileContent(HttpServletRequest request, HttpServletResponse response, @PathVariable("configId") Long configId) throws Exception { diff --git a/yudao-module-infra/yudao-module-infra-biz/src/main/java/cn/iocoder/yudao/module/infra/controller/admin/file/vo/file/FileCreateReqVO.java b/yudao-module-infra/yudao-module-infra-biz/src/main/java/cn/iocoder/yudao/module/infra/controller/admin/file/vo/file/FileCreateReqVO.java new file mode 100644 index 000000000..3486e573a --- /dev/null +++ b/yudao-module-infra/yudao-module-infra-biz/src/main/java/cn/iocoder/yudao/module/infra/controller/admin/file/vo/file/FileCreateReqVO.java @@ -0,0 +1,33 @@ +package cn.iocoder.yudao.module.infra.controller.admin.file.vo.file; + +import io.swagger.v3.oas.annotations.media.Schema; +import jakarta.validation.constraints.NotNull; +import lombok.Data; + +@Schema(description = "管理后台 - 文件创建 Request VO") +@Data +public class FileCreateReqVO { + + @NotNull(message = "文件配置编号不能为空") + @Schema(description = "文件配置编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "11") + private Long configId; + + @NotNull(message = "文件路径不能为空") + @Schema(description = "文件路径", requiredMode = Schema.RequiredMode.REQUIRED, example = "yudao.jpg") + private String path; + + @NotNull(message = "原文件名不能为空") + @Schema(description = "原文件名", requiredMode = Schema.RequiredMode.REQUIRED, example = "yudao.jpg") + private String name; + + @NotNull(message = "文件 URL不能为空") + @Schema(description = "文件 URL", requiredMode = Schema.RequiredMode.REQUIRED, example = "https://www.iocoder.cn/yudao.jpg") + private String url; + + @Schema(description = "文件MIME类型", example = "application/octet-stream") + private String type; + + @Schema(description = "文件大小", example = "2048", requiredMode = Schema.RequiredMode.REQUIRED) + private Integer size; + +} diff --git a/yudao-module-infra/yudao-module-infra-biz/src/main/java/cn/iocoder/yudao/module/infra/controller/admin/file/vo/file/FilePresignedUrlRespVO.java b/yudao-module-infra/yudao-module-infra-biz/src/main/java/cn/iocoder/yudao/module/infra/controller/admin/file/vo/file/FilePresignedUrlRespVO.java new file mode 100644 index 000000000..2db39ef7b --- /dev/null +++ b/yudao-module-infra/yudao-module-infra-biz/src/main/java/cn/iocoder/yudao/module/infra/controller/admin/file/vo/file/FilePresignedUrlRespVO.java @@ -0,0 +1,20 @@ +package cn.iocoder.yudao.module.infra.controller.admin.file.vo.file; + +import io.swagger.v3.oas.annotations.media.Schema; +import lombok.AllArgsConstructor; +import lombok.Data; +import lombok.NoArgsConstructor; + +@AllArgsConstructor +@NoArgsConstructor +@Schema(description = "管理后台 - 文件预签名地址 Response VO") +@Data +public class FilePresignedUrlRespVO { + + @Schema(description = "配置编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "11") + private Long configId; + + @Schema(description = "文件 URL", requiredMode = Schema.RequiredMode.REQUIRED, example = "https://www.iocoder.cn/yudao.jpg") + private String url; + +} diff --git a/yudao-module-infra/yudao-module-infra-biz/src/main/java/cn/iocoder/yudao/module/infra/service/file/FileService.java b/yudao-module-infra/yudao-module-infra-biz/src/main/java/cn/iocoder/yudao/module/infra/service/file/FileService.java index 24baf4218..b6d40dcb5 100644 --- a/yudao-module-infra/yudao-module-infra-biz/src/main/java/cn/iocoder/yudao/module/infra/service/file/FileService.java +++ b/yudao-module-infra/yudao-module-infra-biz/src/main/java/cn/iocoder/yudao/module/infra/service/file/FileService.java @@ -1,7 +1,9 @@ package cn.iocoder.yudao.module.infra.service.file; -import cn.iocoder.yudao.module.infra.controller.admin.file.vo.file.FilePageReqVO; import cn.iocoder.yudao.framework.common.pojo.PageResult; +import cn.iocoder.yudao.module.infra.controller.admin.file.vo.file.FileCreateReqVO; +import cn.iocoder.yudao.module.infra.controller.admin.file.vo.file.FilePageReqVO; +import cn.iocoder.yudao.module.infra.controller.admin.file.vo.file.FilePresignedUrlRespVO; import cn.iocoder.yudao.module.infra.dal.dataobject.file.FileDO; /** @@ -22,13 +24,21 @@ public interface FileService { /** * 保存文件,并返回文件的访问路径 * - * @param name 文件名称 - * @param path 文件路径 + * @param name 文件名称 + * @param path 文件路径 * @param content 文件内容 * @return 文件路径 */ String createFile(String name, String path, byte[] content); + /** + * 创建文件 + * + * @param createReqVO 创建信息 + * @return 编号 + */ + Long createFile(FileCreateReqVO createReqVO); + /** * 删除文件 * @@ -40,9 +50,17 @@ public interface FileService { * 获得文件内容 * * @param configId 配置编号 - * @param path 文件路径 + * @param path 文件路径 * @return 文件内容 */ byte[] getFileContent(Long configId, String path) throws Exception; + /** + * 生成文件预签名地址信息 + * + * @param fileName 文件名称 + * @return 预签名地址信息 + */ + FilePresignedUrlRespVO getFilePresignedUrl(String fileName) throws Exception; + } diff --git a/yudao-module-infra/yudao-module-infra-biz/src/main/java/cn/iocoder/yudao/module/infra/service/file/FileServiceImpl.java b/yudao-module-infra/yudao-module-infra-biz/src/main/java/cn/iocoder/yudao/module/infra/service/file/FileServiceImpl.java index 82ba6d4ff..e5b84b00e 100644 --- a/yudao-module-infra/yudao-module-infra-biz/src/main/java/cn/iocoder/yudao/module/infra/service/file/FileServiceImpl.java +++ b/yudao-module-infra/yudao-module-infra-biz/src/main/java/cn/iocoder/yudao/module/infra/service/file/FileServiceImpl.java @@ -4,16 +4,18 @@ import cn.hutool.core.lang.Assert; import cn.hutool.core.util.StrUtil; import cn.iocoder.yudao.framework.common.pojo.PageResult; import cn.iocoder.yudao.framework.common.util.io.FileUtils; +import cn.iocoder.yudao.framework.common.util.object.BeanUtils; import cn.iocoder.yudao.framework.file.core.client.FileClient; import cn.iocoder.yudao.framework.file.core.utils.FileTypeUtils; +import cn.iocoder.yudao.module.infra.controller.admin.file.vo.file.FileCreateReqVO; import cn.iocoder.yudao.module.infra.controller.admin.file.vo.file.FilePageReqVO; +import cn.iocoder.yudao.module.infra.controller.admin.file.vo.file.FilePresignedUrlRespVO; import cn.iocoder.yudao.module.infra.dal.dataobject.file.FileDO; import cn.iocoder.yudao.module.infra.dal.mysql.file.FileMapper; +import jakarta.annotation.Resource; import lombok.SneakyThrows; import org.springframework.stereotype.Service; -import jakarta.annotation.Resource; - import static cn.iocoder.yudao.framework.common.exception.util.ServiceExceptionUtil.exception; import static cn.iocoder.yudao.module.infra.enums.ErrorCodeConstants.FILE_NOT_EXISTS; @@ -66,6 +68,15 @@ public class FileServiceImpl implements FileService { return url; } + @Override + public Long createFile(FileCreateReqVO createReqVO) { + // 插入 + FileDO file = BeanUtils.toBean(createReqVO, FileDO.class); + fileMapper.insert(file); + // 返回 + return file.getId(); + } + @Override public void deleteFile(Long id) throws Exception { // 校验存在 @@ -95,4 +106,11 @@ public class FileServiceImpl implements FileService { return client.getContent(path); } + @Override + public FilePresignedUrlRespVO getFilePresignedUrl(String fileName) throws Exception { + FileClient fileClient = fileConfigService.getMasterFileClient(); + String url = fileClient.getPresignedObjectUrl(fileName); + return new FilePresignedUrlRespVO(fileClient.getId(), url); + } + } From e66ded2860fce310eea7c657bf103b81a248ba83 Mon Sep 17 00:00:00 2001 From: YunaiV Date: Sun, 4 Feb 2024 19:57:47 +0800 Subject: [PATCH 068/119] =?UTF-8?q?=E2=9C=A8=20ERP=EF=BC=9A=E5=88=9D?= =?UTF-8?q?=E5=A7=8B=E5=8C=96=20product=20=E4=BF=A1=E6=81=AF=E3=80=81?= =?UTF-8?q?=E5=88=86=E7=B1=BB=E3=80=81=E5=8D=95=E4=BD=8D=E7=9A=84=E5=AE=9E?= =?UTF-8?q?=E7=8E=B0?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../yudao/module/erp/ErrorCodeConstants.java | 26 ++++ .../product/ErpProductCategoryController.java | 90 ++++++++++++ .../admin/product/ErpProductController.java | 93 ++++++++++++ .../product/ErpProductUnitController.java | 93 ++++++++++++ .../category/ErpProductCategoryListReqVO.java | 16 +++ .../vo/category/ErpProductCategoryRespVO.java | 47 ++++++ .../category/ErpProductCategorySaveReqVO.java | 35 +++++ .../product/vo/product/ProductPageReqVO.java | 29 ++++ .../product/vo/product/ProductRespVO.java | 72 ++++++++++ .../product/vo/product/ProductSaveReqVO.java | 57 ++++++++ .../vo/unit/ErpProductUnitPageReqVO.java | 30 ++++ .../product/vo/unit/ErpProductUnitRespVO.java | 33 +++++ .../vo/unit/ErpProductUnitSaveReqVO.java | 23 +++ .../product/ErpProductCategoryDO.java | 54 +++++++ .../dal/dataobject/product/ErpProductDO.java | 86 +++++++++++ .../dataobject/product/ErpProductUnitDO.java | 39 +++++ .../product/ErpProductCategoryMapper.java | 34 +++++ .../dal/mysql/product/ErpProductMapper.java | 26 ++++ .../mysql/product/ErpProductUnitMapper.java | 26 ++++ .../product/ErpProductCategoryService.java | 55 +++++++ .../ErpProductCategoryServiceImpl.java | 134 ++++++++++++++++++ .../service/product/ErpProductService.java | 54 +++++++ .../product/ErpProductServiceImpl.java | 72 ++++++++++ .../product/ErpProductUnitService.java | 54 +++++++ .../product/ErpProductUnitServiceImpl.java | 72 ++++++++++ .../mapper/product/ErpProductUnitMapper.xml | 12 ++ .../ErpProductUnitServiceImplTest.java | 131 +++++++++++++++++ .../product/ProductServiceImplTest.java | 131 +++++++++++++++++ 28 files changed, 1624 insertions(+) create mode 100644 yudao-module-erp/yudao-module-erp-api/src/main/java/cn/iocoder/yudao/module/erp/ErrorCodeConstants.java create mode 100644 yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/controller/admin/product/ErpProductCategoryController.java create mode 100644 yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/controller/admin/product/ErpProductController.java create mode 100644 yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/controller/admin/product/ErpProductUnitController.java create mode 100644 yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/controller/admin/product/vo/category/ErpProductCategoryListReqVO.java create mode 100644 yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/controller/admin/product/vo/category/ErpProductCategoryRespVO.java create mode 100644 yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/controller/admin/product/vo/category/ErpProductCategorySaveReqVO.java create mode 100644 yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/controller/admin/product/vo/product/ProductPageReqVO.java create mode 100644 yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/controller/admin/product/vo/product/ProductRespVO.java create mode 100644 yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/controller/admin/product/vo/product/ProductSaveReqVO.java create mode 100644 yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/controller/admin/product/vo/unit/ErpProductUnitPageReqVO.java create mode 100644 yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/controller/admin/product/vo/unit/ErpProductUnitRespVO.java create mode 100644 yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/controller/admin/product/vo/unit/ErpProductUnitSaveReqVO.java create mode 100644 yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/dal/dataobject/product/ErpProductCategoryDO.java create mode 100644 yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/dal/dataobject/product/ErpProductDO.java create mode 100644 yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/dal/dataobject/product/ErpProductUnitDO.java create mode 100644 yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/dal/mysql/product/ErpProductCategoryMapper.java create mode 100644 yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/dal/mysql/product/ErpProductMapper.java create mode 100644 yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/dal/mysql/product/ErpProductUnitMapper.java create mode 100644 yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/service/product/ErpProductCategoryService.java create mode 100644 yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/service/product/ErpProductCategoryServiceImpl.java create mode 100644 yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/service/product/ErpProductService.java create mode 100644 yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/service/product/ErpProductServiceImpl.java create mode 100644 yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/service/product/ErpProductUnitService.java create mode 100644 yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/service/product/ErpProductUnitServiceImpl.java create mode 100644 yudao-module-erp/yudao-module-erp-biz/src/main/resources/mapper/product/ErpProductUnitMapper.xml create mode 100644 yudao-module-erp/yudao-module-erp-biz/src/test/java/cn/iocoder/yudao/module/erp/service/product/ErpProductUnitServiceImplTest.java create mode 100644 yudao-module-erp/yudao-module-erp-biz/src/test/java/cn/iocoder/yudao/module/erp/service/product/ProductServiceImplTest.java diff --git a/yudao-module-erp/yudao-module-erp-api/src/main/java/cn/iocoder/yudao/module/erp/ErrorCodeConstants.java b/yudao-module-erp/yudao-module-erp-api/src/main/java/cn/iocoder/yudao/module/erp/ErrorCodeConstants.java new file mode 100644 index 000000000..9363bab11 --- /dev/null +++ b/yudao-module-erp/yudao-module-erp-api/src/main/java/cn/iocoder/yudao/module/erp/ErrorCodeConstants.java @@ -0,0 +1,26 @@ +package cn.iocoder.yudao.module.erp; + +import cn.iocoder.yudao.framework.common.exception.ErrorCode; + +/** + * ERP 错误码枚举类 + *

+ * erp 系统,使用 1-030-000-000 段 + */ +public interface ErrorCodeConstants { + + // ========== ERP 产品 1-030-500-000 ========== + ErrorCode PRODUCT_NOT_EXISTS = new ErrorCode(1_030_500_000, "产品不存在"); + + // ========== ERP 产品分类 1-030-501-000 ========== + ErrorCode PRODUCT_CATEGORY_NOT_EXISTS = new ErrorCode(1_030_501_000, "产品分类不存在"); + ErrorCode PRODUCT_CATEGORY_EXITS_CHILDREN = new ErrorCode(1_030_501_001, "存在存在子产品分类,无法删除"); + ErrorCode PRODUCT_CATEGORY_PARENT_NOT_EXITS = new ErrorCode(1_030_501_002,"父级产品分类不存在"); + ErrorCode PRODUCT_CATEGORY_PARENT_ERROR = new ErrorCode(1_030_501_003, "不能设置自己为父产品分类"); + ErrorCode PRODUCT_CATEGORY_NAME_DUPLICATE = new ErrorCode(1_030_501_004, "已经存在该分类名称的产品分类"); + ErrorCode PRODUCT_CATEGORY_PARENT_IS_CHILD = new ErrorCode(1_030_501_005, "不能设置自己的子分类为父分类"); + + // ========== ERP 产品单位 1-030-502-000 ========== + ErrorCode PRODUCT_UNIT_NOT_EXISTS = new ErrorCode(1_030_502_000, "产品单位不存在"); + +} diff --git a/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/controller/admin/product/ErpProductCategoryController.java b/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/controller/admin/product/ErpProductCategoryController.java new file mode 100644 index 000000000..f542d6983 --- /dev/null +++ b/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/controller/admin/product/ErpProductCategoryController.java @@ -0,0 +1,90 @@ +package cn.iocoder.yudao.module.erp.controller.admin.product; + +import cn.iocoder.yudao.framework.common.pojo.CommonResult; +import cn.iocoder.yudao.framework.common.util.object.BeanUtils; +import cn.iocoder.yudao.framework.excel.core.util.ExcelUtils; +import cn.iocoder.yudao.framework.operatelog.core.annotations.OperateLog; +import cn.iocoder.yudao.module.erp.controller.admin.product.vo.category.ErpProductCategoryListReqVO; +import cn.iocoder.yudao.module.erp.controller.admin.product.vo.category.ErpProductCategoryRespVO; +import cn.iocoder.yudao.module.erp.controller.admin.product.vo.category.ErpProductCategorySaveReqVO; +import cn.iocoder.yudao.module.erp.dal.dataobject.product.ErpProductCategoryDO; +import cn.iocoder.yudao.module.erp.service.product.ErpProductCategoryService; +import io.swagger.v3.oas.annotations.Operation; +import io.swagger.v3.oas.annotations.Parameter; +import io.swagger.v3.oas.annotations.tags.Tag; +import jakarta.annotation.Resource; +import jakarta.servlet.http.HttpServletResponse; +import jakarta.validation.Valid; +import org.springframework.security.access.prepost.PreAuthorize; +import org.springframework.validation.annotation.Validated; +import org.springframework.web.bind.annotation.*; + +import java.io.IOException; +import java.util.List; + +import static cn.iocoder.yudao.framework.common.pojo.CommonResult.success; +import static cn.iocoder.yudao.framework.operatelog.core.enums.OperateTypeEnum.EXPORT; + +@Tag(name = "管理后台 - ERP 产品分类") +@RestController +@RequestMapping("/erp/product-category") +@Validated +public class ErpProductCategoryController { + + @Resource + private ErpProductCategoryService productCategoryService; + + @PostMapping("/create") + @Operation(summary = "创建ERP 产品分类") + @PreAuthorize("@ss.hasPermission('erp:product-category:create')") + public CommonResult createProductCategory(@Valid @RequestBody ErpProductCategorySaveReqVO createReqVO) { + return success(productCategoryService.createProductCategory(createReqVO)); + } + + @PutMapping("/update") + @Operation(summary = "更新ERP 产品分类") + @PreAuthorize("@ss.hasPermission('erp:product-category:update')") + public CommonResult updateProductCategory(@Valid @RequestBody ErpProductCategorySaveReqVO updateReqVO) { + productCategoryService.updateProductCategory(updateReqVO); + return success(true); + } + + @DeleteMapping("/delete") + @Operation(summary = "删除ERP 产品分类") + @Parameter(name = "id", description = "编号", required = true) + @PreAuthorize("@ss.hasPermission('erp:product-category:delete')") + public CommonResult deleteProductCategory(@RequestParam("id") Long id) { + productCategoryService.deleteProductCategory(id); + return success(true); + } + + @GetMapping("/get") + @Operation(summary = "获得ERP 产品分类") + @Parameter(name = "id", description = "编号", required = true, example = "1024") + @PreAuthorize("@ss.hasPermission('erp:product-category:query')") + public CommonResult getProductCategory(@RequestParam("id") Long id) { + ErpProductCategoryDO productCategory = productCategoryService.getProductCategory(id); + return success(BeanUtils.toBean(productCategory, ErpProductCategoryRespVO.class)); + } + + @GetMapping("/list") + @Operation(summary = "获得ERP 产品分类列表") + @PreAuthorize("@ss.hasPermission('erp:product-category:query')") + public CommonResult> getProductCategoryList(@Valid ErpProductCategoryListReqVO listReqVO) { + List list = productCategoryService.getProductCategoryList(listReqVO); + return success(BeanUtils.toBean(list, ErpProductCategoryRespVO.class)); + } + + @GetMapping("/export-excel") + @Operation(summary = "导出ERP 产品分类 Excel") + @PreAuthorize("@ss.hasPermission('erp:product-category:export')") + @OperateLog(type = EXPORT) + public void exportProductCategoryExcel(@Valid ErpProductCategoryListReqVO listReqVO, + HttpServletResponse response) throws IOException { + List list = productCategoryService.getProductCategoryList(listReqVO); + // 导出 Excel + ExcelUtils.write(response, "ERP 产品分类.xls", "数据", ErpProductCategoryRespVO.class, + BeanUtils.toBean(list, ErpProductCategoryRespVO.class)); + } + +} \ No newline at end of file diff --git a/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/controller/admin/product/ErpProductController.java b/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/controller/admin/product/ErpProductController.java new file mode 100644 index 000000000..098eb8679 --- /dev/null +++ b/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/controller/admin/product/ErpProductController.java @@ -0,0 +1,93 @@ +package cn.iocoder.yudao.module.erp.controller.admin.product; + +import cn.iocoder.yudao.framework.common.pojo.CommonResult; +import cn.iocoder.yudao.framework.common.pojo.PageParam; +import cn.iocoder.yudao.framework.common.pojo.PageResult; +import cn.iocoder.yudao.framework.common.util.object.BeanUtils; +import cn.iocoder.yudao.framework.excel.core.util.ExcelUtils; +import cn.iocoder.yudao.framework.operatelog.core.annotations.OperateLog; +import cn.iocoder.yudao.module.erp.controller.admin.product.vo.product.ProductPageReqVO; +import cn.iocoder.yudao.module.erp.controller.admin.product.vo.product.ProductRespVO; +import cn.iocoder.yudao.module.erp.controller.admin.product.vo.product.ProductSaveReqVO; +import cn.iocoder.yudao.module.erp.dal.dataobject.product.ErpProductDO; +import cn.iocoder.yudao.module.erp.service.product.ErpProductService; +import io.swagger.v3.oas.annotations.Operation; +import io.swagger.v3.oas.annotations.Parameter; +import io.swagger.v3.oas.annotations.tags.Tag; +import jakarta.annotation.Resource; +import jakarta.servlet.http.HttpServletResponse; +import jakarta.validation.Valid; +import org.springframework.security.access.prepost.PreAuthorize; +import org.springframework.validation.annotation.Validated; +import org.springframework.web.bind.annotation.*; + +import java.io.IOException; +import java.util.List; + +import static cn.iocoder.yudao.framework.common.pojo.CommonResult.success; +import static cn.iocoder.yudao.framework.operatelog.core.enums.OperateTypeEnum.EXPORT; + +@Tag(name = "管理后台 - ERP 产品") +@RestController +@RequestMapping("/erp/product") +@Validated +public class ErpProductController { + + @Resource + private ErpProductService productService; + + @PostMapping("/create") + @Operation(summary = "创建产品") + @PreAuthorize("@ss.hasPermission('erp:product:create')") + public CommonResult createProduct(@Valid @RequestBody ProductSaveReqVO createReqVO) { + return success(productService.createProduct(createReqVO)); + } + + @PutMapping("/update") + @Operation(summary = "更新产品") + @PreAuthorize("@ss.hasPermission('erp:product:update')") + public CommonResult updateProduct(@Valid @RequestBody ProductSaveReqVO updateReqVO) { + productService.updateProduct(updateReqVO); + return success(true); + } + + @DeleteMapping("/delete") + @Operation(summary = "删除产品") + @Parameter(name = "id", description = "编号", required = true) + @PreAuthorize("@ss.hasPermission('erp:product:delete')") + public CommonResult deleteProduct(@RequestParam("id") Long id) { + productService.deleteProduct(id); + return success(true); + } + + @GetMapping("/get") + @Operation(summary = "获得产品") + @Parameter(name = "id", description = "编号", required = true, example = "1024") + @PreAuthorize("@ss.hasPermission('erp:product:query')") + public CommonResult getProduct(@RequestParam("id") Long id) { + ErpProductDO product = productService.getProduct(id); + return success(BeanUtils.toBean(product, ProductRespVO.class)); + } + + @GetMapping("/page") + @Operation(summary = "获得产品分页") + @PreAuthorize("@ss.hasPermission('erp:product:query')") + public CommonResult> getProductPage(@Valid ProductPageReqVO pageReqVO) { + PageResult pageResult = productService.getProductPage(pageReqVO); + return success(BeanUtils.toBean(pageResult, ProductRespVO.class)); + } + + @GetMapping("/export-excel") + @Operation(summary = "导出产品 Excel") + @PreAuthorize("@ss.hasPermission('erp:product:export')") + @OperateLog(type = EXPORT) + public void exportProductExcel(@Valid ProductPageReqVO pageReqVO, + HttpServletResponse response) throws IOException { + pageReqVO.setPageSize(PageParam.PAGE_SIZE_NONE); + List list = productService.getProductPage(pageReqVO).getList(); + // 导出 Excel + ExcelUtils.write(response, "产品.xls", "数据", ProductRespVO.class, + BeanUtils.toBean(list, ProductRespVO.class)); + } + +} \ No newline at end of file diff --git a/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/controller/admin/product/ErpProductUnitController.java b/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/controller/admin/product/ErpProductUnitController.java new file mode 100644 index 000000000..34d97ff2e --- /dev/null +++ b/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/controller/admin/product/ErpProductUnitController.java @@ -0,0 +1,93 @@ +package cn.iocoder.yudao.module.erp.controller.admin.product; + +import cn.iocoder.yudao.framework.common.pojo.CommonResult; +import cn.iocoder.yudao.framework.common.pojo.PageParam; +import cn.iocoder.yudao.framework.common.pojo.PageResult; +import cn.iocoder.yudao.framework.common.util.object.BeanUtils; +import cn.iocoder.yudao.framework.excel.core.util.ExcelUtils; +import cn.iocoder.yudao.framework.operatelog.core.annotations.OperateLog; +import cn.iocoder.yudao.module.erp.controller.admin.product.vo.unit.ErpProductUnitPageReqVO; +import cn.iocoder.yudao.module.erp.controller.admin.product.vo.unit.ErpProductUnitRespVO; +import cn.iocoder.yudao.module.erp.controller.admin.product.vo.unit.ErpProductUnitSaveReqVO; +import cn.iocoder.yudao.module.erp.dal.dataobject.product.ErpProductUnitDO; +import cn.iocoder.yudao.module.erp.service.product.ErpProductUnitService; +import io.swagger.v3.oas.annotations.Operation; +import io.swagger.v3.oas.annotations.Parameter; +import io.swagger.v3.oas.annotations.tags.Tag; +import jakarta.annotation.Resource; +import jakarta.servlet.http.HttpServletResponse; +import jakarta.validation.Valid; +import org.springframework.security.access.prepost.PreAuthorize; +import org.springframework.validation.annotation.Validated; +import org.springframework.web.bind.annotation.*; + +import java.io.IOException; +import java.util.List; + +import static cn.iocoder.yudao.framework.common.pojo.CommonResult.success; +import static cn.iocoder.yudao.framework.operatelog.core.enums.OperateTypeEnum.EXPORT; + +@Tag(name = "管理后台 - ERP 产品单位") +@RestController +@RequestMapping("/erp/product-unit") +@Validated +public class ErpProductUnitController { + + @Resource + private ErpProductUnitService productUnitService; + + @PostMapping("/create") + @Operation(summary = "创建产品单位") + @PreAuthorize("@ss.hasPermission('erp:product-unit:create')") + public CommonResult createProductUnit(@Valid @RequestBody ErpProductUnitSaveReqVO createReqVO) { + return success(productUnitService.createProductUnit(createReqVO)); + } + + @PutMapping("/update") + @Operation(summary = "更新产品单位") + @PreAuthorize("@ss.hasPermission('erp:product-unit:update')") + public CommonResult updateProductUnit(@Valid @RequestBody ErpProductUnitSaveReqVO updateReqVO) { + productUnitService.updateProductUnit(updateReqVO); + return success(true); + } + + @DeleteMapping("/delete") + @Operation(summary = "删除产品单位") + @Parameter(name = "id", description = "编号", required = true) + @PreAuthorize("@ss.hasPermission('erp:product-unit:delete')") + public CommonResult deleteProductUnit(@RequestParam("id") Long id) { + productUnitService.deleteProductUnit(id); + return success(true); + } + + @GetMapping("/get") + @Operation(summary = "获得产品单位") + @Parameter(name = "id", description = "编号", required = true, example = "1024") + @PreAuthorize("@ss.hasPermission('erp:product-unit:query')") + public CommonResult getProductUnit(@RequestParam("id") Long id) { + ErpProductUnitDO productUnit = productUnitService.getProductUnit(id); + return success(BeanUtils.toBean(productUnit, ErpProductUnitRespVO.class)); + } + + @GetMapping("/page") + @Operation(summary = "获得产品单位分页") + @PreAuthorize("@ss.hasPermission('erp:product-unit:query')") + public CommonResult> getProductUnitPage(@Valid ErpProductUnitPageReqVO pageReqVO) { + PageResult pageResult = productUnitService.getProductUnitPage(pageReqVO); + return success(BeanUtils.toBean(pageResult, ErpProductUnitRespVO.class)); + } + + @GetMapping("/export-excel") + @Operation(summary = "导出产品单位 Excel") + @PreAuthorize("@ss.hasPermission('erp:product-unit:export')") + @OperateLog(type = EXPORT) + public void exportProductUnitExcel(@Valid ErpProductUnitPageReqVO pageReqVO, + HttpServletResponse response) throws IOException { + pageReqVO.setPageSize(PageParam.PAGE_SIZE_NONE); + List list = productUnitService.getProductUnitPage(pageReqVO).getList(); + // 导出 Excel + ExcelUtils.write(response, "产品单位.xls", "数据", ErpProductUnitRespVO.class, + BeanUtils.toBean(list, ErpProductUnitRespVO.class)); + } + +} \ No newline at end of file diff --git a/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/controller/admin/product/vo/category/ErpProductCategoryListReqVO.java b/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/controller/admin/product/vo/category/ErpProductCategoryListReqVO.java new file mode 100644 index 000000000..b9b530e7d --- /dev/null +++ b/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/controller/admin/product/vo/category/ErpProductCategoryListReqVO.java @@ -0,0 +1,16 @@ +package cn.iocoder.yudao.module.erp.controller.admin.product.vo.category; + +import io.swagger.v3.oas.annotations.media.Schema; +import lombok.Data; + +@Schema(description = "管理后台 - ERP 产品分类列表 Request VO") +@Data +public class ErpProductCategoryListReqVO { + + @Schema(description = "分类名称", example = "芋艿") + private String name; + + @Schema(description = "开启状态", example = "1") + private Integer status; + +} \ No newline at end of file diff --git a/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/controller/admin/product/vo/category/ErpProductCategoryRespVO.java b/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/controller/admin/product/vo/category/ErpProductCategoryRespVO.java new file mode 100644 index 000000000..23d7d9e8f --- /dev/null +++ b/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/controller/admin/product/vo/category/ErpProductCategoryRespVO.java @@ -0,0 +1,47 @@ +package cn.iocoder.yudao.module.erp.controller.admin.product.vo.category; + +import cn.iocoder.yudao.framework.excel.core.annotations.DictFormat; +import cn.iocoder.yudao.framework.excel.core.convert.DictConvert; +import cn.iocoder.yudao.module.system.enums.DictTypeConstants; +import com.alibaba.excel.annotation.ExcelIgnoreUnannotated; +import com.alibaba.excel.annotation.ExcelProperty; +import io.swagger.v3.oas.annotations.media.Schema; +import lombok.Data; + +import java.time.LocalDateTime; + +@Schema(description = "管理后台 - ERP 产品分类 Response VO") +@Data +@ExcelIgnoreUnannotated +public class ErpProductCategoryRespVO { + + @Schema(description = "分类编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "5860") + @ExcelProperty("分类编号") + private Long id; + + @Schema(description = "父分类编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "21829") + @ExcelProperty("父分类编号") + private Long parentId; + + @Schema(description = "分类名称", requiredMode = Schema.RequiredMode.REQUIRED, example = "芋艿") + @ExcelProperty("分类名称") + private String name; + + @Schema(description = "分类编码", requiredMode = Schema.RequiredMode.REQUIRED, example = "S110") + @ExcelProperty("分类编码") + private String code; + + @Schema(description = "分类排序", example = "10") + @ExcelProperty("分类排序") + private Integer sort; + + @Schema(description = "开启状态", requiredMode = Schema.RequiredMode.REQUIRED, example = "1") + @ExcelProperty(value = "开启状态", converter = DictConvert.class) + @DictFormat(DictTypeConstants.COMMON_STATUS) + private Integer status; + + @Schema(description = "创建时间", requiredMode = Schema.RequiredMode.REQUIRED) + @ExcelProperty("创建时间") + private LocalDateTime createTime; + +} \ No newline at end of file diff --git a/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/controller/admin/product/vo/category/ErpProductCategorySaveReqVO.java b/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/controller/admin/product/vo/category/ErpProductCategorySaveReqVO.java new file mode 100644 index 000000000..a3c82dc93 --- /dev/null +++ b/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/controller/admin/product/vo/category/ErpProductCategorySaveReqVO.java @@ -0,0 +1,35 @@ +package cn.iocoder.yudao.module.erp.controller.admin.product.vo.category; + +import io.swagger.v3.oas.annotations.media.Schema; +import jakarta.validation.constraints.NotEmpty; +import jakarta.validation.constraints.NotNull; +import lombok.Data; + +@Schema(description = "管理后台 - ERP 产品分类新增/修改 Request VO") +@Data +public class ErpProductCategorySaveReqVO { + + @Schema(description = "分类编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "5860") + private Long id; + + @Schema(description = "父分类编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "21829") + @NotNull(message = "父分类编号不能为空") + private Long parentId; + + @Schema(description = "分类名称", requiredMode = Schema.RequiredMode.REQUIRED, example = "芋艿") + @NotEmpty(message = "分类名称不能为空") + private String name; + + @Schema(description = "分类编码", requiredMode = Schema.RequiredMode.REQUIRED, example = "S110") + @NotEmpty(message = "分类编码不能为空") + private String code; + + @Schema(description = "分类排序", requiredMode = Schema.RequiredMode.REQUIRED, example = "10") + @NotNull(message = "分类排序不能为空") + private Integer sort; + + @Schema(description = "开启状态", requiredMode = Schema.RequiredMode.REQUIRED, example = "1") + @NotNull(message = "开启状态不能为空") + private Integer status; + +} \ No newline at end of file diff --git a/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/controller/admin/product/vo/product/ProductPageReqVO.java b/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/controller/admin/product/vo/product/ProductPageReqVO.java new file mode 100644 index 000000000..eb560603b --- /dev/null +++ b/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/controller/admin/product/vo/product/ProductPageReqVO.java @@ -0,0 +1,29 @@ +package cn.iocoder.yudao.module.erp.controller.admin.product.vo.product; + +import lombok.*; +import java.util.*; +import io.swagger.v3.oas.annotations.media.Schema; +import cn.iocoder.yudao.framework.common.pojo.PageParam; +import java.math.BigDecimal; +import org.springframework.format.annotation.DateTimeFormat; +import java.time.LocalDateTime; + +import static cn.iocoder.yudao.framework.common.util.date.DateUtils.FORMAT_YEAR_MONTH_DAY_HOUR_MINUTE_SECOND; + +@Schema(description = "管理后台 - ERP 产品分页 Request VO") +@Data +@EqualsAndHashCode(callSuper = true) +@ToString(callSuper = true) +public class ProductPageReqVO extends PageParam { + + @Schema(description = "产品名称", example = "李四") + private String name; + + @Schema(description = "产品分类编号", example = "11161") + private Long categoryId; + + @Schema(description = "创建时间") + @DateTimeFormat(pattern = FORMAT_YEAR_MONTH_DAY_HOUR_MINUTE_SECOND) + private LocalDateTime[] createTime; + +} \ No newline at end of file diff --git a/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/controller/admin/product/vo/product/ProductRespVO.java b/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/controller/admin/product/vo/product/ProductRespVO.java new file mode 100644 index 000000000..d96cbad98 --- /dev/null +++ b/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/controller/admin/product/vo/product/ProductRespVO.java @@ -0,0 +1,72 @@ +package cn.iocoder.yudao.module.erp.controller.admin.product.vo.product; + +import com.alibaba.excel.annotation.ExcelIgnoreUnannotated; +import com.alibaba.excel.annotation.ExcelProperty; +import io.swagger.v3.oas.annotations.media.Schema; +import lombok.Data; + +import java.math.BigDecimal; +import java.time.LocalDateTime; + +@Schema(description = "管理后台 - ERP 产品 Response VO") +@Data +@ExcelIgnoreUnannotated +public class ProductRespVO { + + @Schema(description = "产品编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "15672") + @ExcelProperty("产品编号") + private Long id; + + @Schema(description = "产品名称", requiredMode = Schema.RequiredMode.REQUIRED, example = "李四") + @ExcelProperty("产品名称") + private String name; + + @Schema(description = "产品条码", requiredMode = Schema.RequiredMode.REQUIRED, example = "X110") + @ExcelProperty("产品条码") + private String barCode; + + @Schema(description = "产品分类编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "11161") + @ExcelProperty("产品分类编号") + private Long categoryId; + + @Schema(description = "单位编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "8869") + @ExcelProperty("单位编号") + private Integer unitId; + + @Schema(description = "产品状态", requiredMode = Schema.RequiredMode.REQUIRED, example = "2") + @ExcelProperty("产品状态") + private Integer status; + + @Schema(description = "产品规格", example = "红色") + @ExcelProperty("产品规格") + private String standard; + + @Schema(description = "产品备注", example = "你猜") + @ExcelProperty("产品备注") + private String remark; + + @Schema(description = "保质期天数", example = "10") + @ExcelProperty("保质期天数") + private Integer expiryDay; + + @Schema(description = "基础重量(kg)", example = "1.00") + @ExcelProperty("基础重量(kg)") + private BigDecimal weight; + + @Schema(description = "采购价格,单位:元", example = "10.30") + @ExcelProperty("采购价格,单位:元") + private BigDecimal purchasePrice; + + @Schema(description = "销售价格,单位:元", example = "74.32") + @ExcelProperty("销售价格,单位:元") + private BigDecimal salePrice; + + @Schema(description = "最低价格,单位:元", example = "161.87") + @ExcelProperty("最低价格,单位:元") + private BigDecimal minPrice; + + @Schema(description = "创建时间", requiredMode = Schema.RequiredMode.REQUIRED) + @ExcelProperty("创建时间") + private LocalDateTime createTime; + +} \ No newline at end of file diff --git a/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/controller/admin/product/vo/product/ProductSaveReqVO.java b/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/controller/admin/product/vo/product/ProductSaveReqVO.java new file mode 100644 index 000000000..e881bf46b --- /dev/null +++ b/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/controller/admin/product/vo/product/ProductSaveReqVO.java @@ -0,0 +1,57 @@ +package cn.iocoder.yudao.module.erp.controller.admin.product.vo.product; + +import io.swagger.v3.oas.annotations.media.Schema; +import lombok.*; +import java.util.*; +import jakarta.validation.constraints.*; +import java.math.BigDecimal; + +@Schema(description = "管理后台 - ERP 产品新增/修改 Request VO") +@Data +public class ProductSaveReqVO { + + @Schema(description = "产品编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "15672") + private Long id; + + @Schema(description = "产品名称", requiredMode = Schema.RequiredMode.REQUIRED, example = "李四") + @NotEmpty(message = "产品名称不能为空") + private String name; + + @Schema(description = "产品条码", requiredMode = Schema.RequiredMode.REQUIRED, example = "X110") + @NotEmpty(message = "产品条码不能为空") + private String barCode; + + @Schema(description = "产品分类编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "11161") + @NotNull(message = "产品分类编号不能为空") + private Long categoryId; + + @Schema(description = "单位编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "8869") + @NotNull(message = "单位编号不能为空") + private Integer unitId; + + @Schema(description = "产品状态", requiredMode = Schema.RequiredMode.REQUIRED, example = "2") + @NotNull(message = "产品状态不能为空") + private Integer status; + + @Schema(description = "产品规格", example = "红色") + private String standard; + + @Schema(description = "产品备注", example = "你猜") + private String remark; + + @Schema(description = "保质期天数", example = "10") + private Integer expiryDay; + + @Schema(description = "基础重量(kg)", example = "1.00") + private BigDecimal weight; + + @Schema(description = "采购价格,单位:元", example = "10.30") + private BigDecimal purchasePrice; + + @Schema(description = "销售价格,单位:元", example = "74.32") + private BigDecimal salePrice; + + @Schema(description = "最低价格,单位:元", example = "161.87") + private BigDecimal minPrice; + +} \ No newline at end of file diff --git a/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/controller/admin/product/vo/unit/ErpProductUnitPageReqVO.java b/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/controller/admin/product/vo/unit/ErpProductUnitPageReqVO.java new file mode 100644 index 000000000..cef41c7ec --- /dev/null +++ b/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/controller/admin/product/vo/unit/ErpProductUnitPageReqVO.java @@ -0,0 +1,30 @@ +package cn.iocoder.yudao.module.erp.controller.admin.product.vo.unit; + +import cn.iocoder.yudao.framework.common.pojo.PageParam; +import io.swagger.v3.oas.annotations.media.Schema; +import lombok.Data; +import lombok.EqualsAndHashCode; +import lombok.ToString; +import org.springframework.format.annotation.DateTimeFormat; + +import java.time.LocalDateTime; + +import static cn.iocoder.yudao.framework.common.util.date.DateUtils.FORMAT_YEAR_MONTH_DAY_HOUR_MINUTE_SECOND; + +@Schema(description = "管理后台 - ERP 产品单位分页 Request VO") +@Data +@EqualsAndHashCode(callSuper = true) +@ToString(callSuper = true) +public class ErpProductUnitPageReqVO extends PageParam { + + @Schema(description = "单位名字", example = "芋艿") + private String name; + + @Schema(description = "单位状态", example = "1") + private Integer status; + + @Schema(description = "创建时间") + @DateTimeFormat(pattern = FORMAT_YEAR_MONTH_DAY_HOUR_MINUTE_SECOND) + private LocalDateTime[] createTime; + +} \ No newline at end of file diff --git a/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/controller/admin/product/vo/unit/ErpProductUnitRespVO.java b/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/controller/admin/product/vo/unit/ErpProductUnitRespVO.java new file mode 100644 index 000000000..e1287b0f5 --- /dev/null +++ b/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/controller/admin/product/vo/unit/ErpProductUnitRespVO.java @@ -0,0 +1,33 @@ +package cn.iocoder.yudao.module.erp.controller.admin.product.vo.unit; + +import com.alibaba.excel.annotation.ExcelIgnoreUnannotated; +import com.alibaba.excel.annotation.ExcelProperty; +import io.swagger.v3.oas.annotations.media.Schema; +import jakarta.validation.constraints.NotNull; +import lombok.Data; + +import java.time.LocalDateTime; + +@Schema(description = "管理后台 - ERP 产品单位 Response VO") +@Data +@ExcelIgnoreUnannotated +public class ErpProductUnitRespVO { + + @Schema(description = "单位编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "31254") + @ExcelProperty("单位编号") + private Long id; + + @Schema(description = "单位名字", requiredMode = Schema.RequiredMode.REQUIRED, example = "芋艿") + @ExcelProperty("单位名字") + private String name; + + @Schema(description = "单位状态", requiredMode = Schema.RequiredMode.REQUIRED, example = "1") + @ExcelProperty("单位状态") + @NotNull(message = "分类排序不能为空") + private Integer status; + + @Schema(description = "创建时间", requiredMode = Schema.RequiredMode.REQUIRED) + @ExcelProperty("创建时间") + private LocalDateTime createTime; + +} \ No newline at end of file diff --git a/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/controller/admin/product/vo/unit/ErpProductUnitSaveReqVO.java b/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/controller/admin/product/vo/unit/ErpProductUnitSaveReqVO.java new file mode 100644 index 000000000..eccf291b0 --- /dev/null +++ b/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/controller/admin/product/vo/unit/ErpProductUnitSaveReqVO.java @@ -0,0 +1,23 @@ +package cn.iocoder.yudao.module.erp.controller.admin.product.vo.unit; + +import io.swagger.v3.oas.annotations.media.Schema; +import jakarta.validation.constraints.NotEmpty; +import jakarta.validation.constraints.NotNull; +import lombok.Data; + +@Schema(description = "管理后台 - ERP 产品单位新增/修改 Request VO") +@Data +public class ErpProductUnitSaveReqVO { + + @Schema(description = "单位编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "31254") + private Long id; + + @Schema(description = "单位名字", requiredMode = Schema.RequiredMode.REQUIRED, example = "芋艿") + @NotEmpty(message = "单位名字不能为空") + private String name; + + @Schema(description = "单位状态", requiredMode = Schema.RequiredMode.REQUIRED, example = "1") + @NotNull(message = "单位状态不能为空") + private Integer status; + +} \ No newline at end of file diff --git a/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/dal/dataobject/product/ErpProductCategoryDO.java b/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/dal/dataobject/product/ErpProductCategoryDO.java new file mode 100644 index 000000000..4c6225158 --- /dev/null +++ b/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/dal/dataobject/product/ErpProductCategoryDO.java @@ -0,0 +1,54 @@ +package cn.iocoder.yudao.module.erp.dal.dataobject.product; + +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.*; + +/** + * ERP 产品分类 DO + * + * @author 芋道源码 + */ +@TableName("erp_product_category") +@KeySequence("erp_product_category_seq") // 用于 Oracle、PostgreSQL、Kingbase、DB2、H2 数据库的主键自增。如果是 MySQL 等数据库,可不写。 +@Data +@EqualsAndHashCode(callSuper = true) +@ToString(callSuper = true) +@Builder +@NoArgsConstructor +@AllArgsConstructor +public class ErpProductCategoryDO extends BaseDO { + + public static final Long PARENT_ID_ROOT = 0L; + + /** + * 分类编号 + */ + @TableId + private Long id; + /** + * 父分类编号 + */ + private Long parentId; + /** + * 分类名称 + */ + private String name; + /** + * 分类编码 + */ + private String code; + /** + * 分类排序 + */ + private Integer sort; + /** + * 开启状态 + * + * 枚举 {@link cn.iocoder.yudao.framework.common.enums.CommonStatusEnum} + */ + private Integer status; + +} \ No newline at end of file diff --git a/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/dal/dataobject/product/ErpProductDO.java b/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/dal/dataobject/product/ErpProductDO.java new file mode 100644 index 000000000..c6d947956 --- /dev/null +++ b/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/dal/dataobject/product/ErpProductDO.java @@ -0,0 +1,86 @@ +package cn.iocoder.yudao.module.erp.dal.dataobject.product; + +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.*; + +import java.math.BigDecimal; + +/** + * ERP 产品 DO + * + * @author 芋道源码 + */ +@TableName("erp_product") +@KeySequence("erp_product_seq") // 用于 Oracle、PostgreSQL、Kingbase、DB2、H2 数据库的主键自增。如果是 MySQL 等数据库,可不写。 +@Data +@EqualsAndHashCode(callSuper = true) +@ToString(callSuper = true) +@Builder +@NoArgsConstructor +@AllArgsConstructor +public class ErpProductDO extends BaseDO { + + /** + * 产品编号 + */ + @TableId + private Long id; + /** + * 产品名称 + */ + private String name; + /** + * 产品条码 + */ + private String barCode; + /** + * 产品分类编号 + * + * 关联 {@link ErpProductCategoryDO#getId()} + */ + private Long categoryId; + /** + * 单位编号 + * + * TODO 芋艿,关联 + */ + private Integer unitId; + /** + * 产品状态 + * + * 枚举 {@link cn.iocoder.yudao.framework.common.enums.CommonStatusEnum} + */ + private Integer status; + /** + * 产品规格 + */ + private String standard; + /** + * 产品备注 + */ + private String remark; + /** + * 保质期天数 + */ + private Integer expiryDay; + /** + * 基础重量(kg) + */ + private BigDecimal weight; + /** + * 采购价格,单位:元 + */ + private BigDecimal purchasePrice; + /** + * 销售价格,单位:元 + */ + private BigDecimal salePrice; + /** + * 最低价格,单位:元 + */ + private BigDecimal minPrice; + +} \ No newline at end of file diff --git a/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/dal/dataobject/product/ErpProductUnitDO.java b/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/dal/dataobject/product/ErpProductUnitDO.java new file mode 100644 index 000000000..73c96c290 --- /dev/null +++ b/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/dal/dataobject/product/ErpProductUnitDO.java @@ -0,0 +1,39 @@ +package cn.iocoder.yudao.module.erp.dal.dataobject.product; + +import lombok.*; +import java.util.*; +import java.time.LocalDateTime; +import java.time.LocalDateTime; +import com.baomidou.mybatisplus.annotation.*; +import cn.iocoder.yudao.framework.mybatis.core.dataobject.BaseDO; + +/** + * ERP 产品单位 DO + * + * @author 芋道源码 + */ +@TableName("erp_product_unit") +@KeySequence("erp_product_unit_seq") // 用于 Oracle、PostgreSQL、Kingbase、DB2、H2 数据库的主键自增。如果是 MySQL 等数据库,可不写。 +@Data +@EqualsAndHashCode(callSuper = true) +@ToString(callSuper = true) +@Builder +@NoArgsConstructor +@AllArgsConstructor +public class ErpProductUnitDO extends BaseDO { + + /** + * 单位编号 + */ + @TableId + private Long id; + /** + * 单位名字 + */ + private String name; + /** + * 单位状态 + */ + private Integer status; + +} \ No newline at end of file diff --git a/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/dal/mysql/product/ErpProductCategoryMapper.java b/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/dal/mysql/product/ErpProductCategoryMapper.java new file mode 100644 index 000000000..70bbc6429 --- /dev/null +++ b/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/dal/mysql/product/ErpProductCategoryMapper.java @@ -0,0 +1,34 @@ +package cn.iocoder.yudao.module.erp.dal.mysql.product; + +import cn.iocoder.yudao.framework.mybatis.core.mapper.BaseMapperX; +import cn.iocoder.yudao.framework.mybatis.core.query.LambdaQueryWrapperX; +import cn.iocoder.yudao.module.erp.controller.admin.product.vo.category.ErpProductCategoryListReqVO; +import cn.iocoder.yudao.module.erp.dal.dataobject.product.ErpProductCategoryDO; +import org.apache.ibatis.annotations.Mapper; + +import java.util.List; + +/** + * ERP 产品分类 Mapper + * + * @author 芋道源码 + */ +@Mapper +public interface ErpProductCategoryMapper extends BaseMapperX { + + default List selectList(ErpProductCategoryListReqVO reqVO) { + return selectList(new LambdaQueryWrapperX() + .likeIfPresent(ErpProductCategoryDO::getName, reqVO.getName()) + .eqIfPresent(ErpProductCategoryDO::getStatus, reqVO.getStatus()) + .orderByDesc(ErpProductCategoryDO::getId)); + } + + default ErpProductCategoryDO selectByParentIdAndName(Long parentId, String name) { + return selectOne(ErpProductCategoryDO::getParentId, parentId, ErpProductCategoryDO::getName, name); + } + + default Long selectCountByParentId(Long parentId) { + return selectCount(ErpProductCategoryDO::getParentId, parentId); + } + +} \ No newline at end of file diff --git a/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/dal/mysql/product/ErpProductMapper.java b/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/dal/mysql/product/ErpProductMapper.java new file mode 100644 index 000000000..8ecad6c54 --- /dev/null +++ b/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/dal/mysql/product/ErpProductMapper.java @@ -0,0 +1,26 @@ +package cn.iocoder.yudao.module.erp.dal.mysql.product; + +import cn.iocoder.yudao.framework.common.pojo.PageResult; +import cn.iocoder.yudao.framework.mybatis.core.query.LambdaQueryWrapperX; +import cn.iocoder.yudao.framework.mybatis.core.mapper.BaseMapperX; +import cn.iocoder.yudao.module.erp.controller.admin.product.vo.product.ProductPageReqVO; +import cn.iocoder.yudao.module.erp.dal.dataobject.product.ErpProductDO; +import org.apache.ibatis.annotations.Mapper; + +/** + * ERP 产品 Mapper + * + * @author 芋道源码 + */ +@Mapper +public interface ErpProductMapper extends BaseMapperX { + + default PageResult selectPage(ProductPageReqVO reqVO) { + return selectPage(reqVO, new LambdaQueryWrapperX() + .likeIfPresent(ErpProductDO::getName, reqVO.getName()) + .eqIfPresent(ErpProductDO::getCategoryId, reqVO.getCategoryId()) + .betweenIfPresent(ErpProductDO::getCreateTime, reqVO.getCreateTime()) + .orderByDesc(ErpProductDO::getId)); + } + +} \ No newline at end of file diff --git a/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/dal/mysql/product/ErpProductUnitMapper.java b/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/dal/mysql/product/ErpProductUnitMapper.java new file mode 100644 index 000000000..b24af15d3 --- /dev/null +++ b/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/dal/mysql/product/ErpProductUnitMapper.java @@ -0,0 +1,26 @@ +package cn.iocoder.yudao.module.erp.dal.mysql.product; + +import cn.iocoder.yudao.framework.common.pojo.PageResult; +import cn.iocoder.yudao.framework.mybatis.core.query.LambdaQueryWrapperX; +import cn.iocoder.yudao.framework.mybatis.core.mapper.BaseMapperX; +import cn.iocoder.yudao.module.erp.controller.admin.product.vo.unit.ErpProductUnitPageReqVO; +import cn.iocoder.yudao.module.erp.dal.dataobject.product.ErpProductUnitDO; +import org.apache.ibatis.annotations.Mapper; + +/** + * ERP 产品单位 Mapper + * + * @author 芋道源码 + */ +@Mapper +public interface ErpProductUnitMapper extends BaseMapperX { + + default PageResult selectPage(ErpProductUnitPageReqVO reqVO) { + return selectPage(reqVO, new LambdaQueryWrapperX() + .likeIfPresent(ErpProductUnitDO::getName, reqVO.getName()) + .eqIfPresent(ErpProductUnitDO::getStatus, reqVO.getStatus()) + .betweenIfPresent(ErpProductUnitDO::getCreateTime, reqVO.getCreateTime()) + .orderByDesc(ErpProductUnitDO::getId)); + } + +} \ No newline at end of file diff --git a/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/service/product/ErpProductCategoryService.java b/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/service/product/ErpProductCategoryService.java new file mode 100644 index 000000000..c5b1e9d21 --- /dev/null +++ b/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/service/product/ErpProductCategoryService.java @@ -0,0 +1,55 @@ +package cn.iocoder.yudao.module.erp.service.product; + +import cn.iocoder.yudao.module.erp.controller.admin.product.vo.category.ErpProductCategoryListReqVO; +import cn.iocoder.yudao.module.erp.controller.admin.product.vo.category.ErpProductCategorySaveReqVO; +import cn.iocoder.yudao.module.erp.dal.dataobject.product.ErpProductCategoryDO; +import jakarta.validation.Valid; + +import java.util.List; + +/** + * ERP 产品分类 Service 接口 + * + * @author 芋道源码 + */ +public interface ErpProductCategoryService { + + /** + * 创建产品分类 + * + * @param createReqVO 创建信息 + * @return 编号 + */ + Long createProductCategory(@Valid ErpProductCategorySaveReqVO createReqVO); + + /** + * 更新产品分类 + * + * @param updateReqVO 更新信息 + */ + void updateProductCategory(@Valid ErpProductCategorySaveReqVO updateReqVO); + + /** + * 删除产品分类 + * + * @param id 编号 + */ + void deleteProductCategory(Long id); + + /** + * 获得产品分类 + * + * @param id 编号 + * @return ERP 产品分类 + */ + ErpProductCategoryDO getProductCategory(Long id); + + /** + * 获得产品分类列表 + * + * @param listReqVO 查询条件 + * @return ERP 产品分类列表 + */ + List getProductCategoryList(ErpProductCategoryListReqVO listReqVO); + +} \ No newline at end of file diff --git a/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/service/product/ErpProductCategoryServiceImpl.java b/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/service/product/ErpProductCategoryServiceImpl.java new file mode 100644 index 000000000..6253914be --- /dev/null +++ b/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/service/product/ErpProductCategoryServiceImpl.java @@ -0,0 +1,134 @@ +package cn.iocoder.yudao.module.erp.service.product; + +import cn.iocoder.yudao.framework.common.util.object.BeanUtils; +import cn.iocoder.yudao.module.erp.controller.admin.product.vo.category.ErpProductCategoryListReqVO; +import cn.iocoder.yudao.module.erp.controller.admin.product.vo.category.ErpProductCategorySaveReqVO; +import cn.iocoder.yudao.module.erp.dal.dataobject.product.ErpProductCategoryDO; +import cn.iocoder.yudao.module.erp.dal.mysql.product.ErpProductCategoryMapper; +import jakarta.annotation.Resource; +import org.springframework.stereotype.Service; +import org.springframework.validation.annotation.Validated; + +import java.util.List; +import java.util.Objects; + +import static cn.iocoder.yudao.framework.common.exception.util.ServiceExceptionUtil.exception; +import static cn.iocoder.yudao.module.erp.ErrorCodeConstants.*; + +/** + * ERP 产品分类 Service 实现类 + * + * @author 芋道源码 + */ +@Service +@Validated +public class ErpProductCategoryServiceImpl implements ErpProductCategoryService { + + @Resource + private ErpProductCategoryMapper productCategoryMapper; + + @Override + public Long createProductCategory(ErpProductCategorySaveReqVO createReqVO) { + // 校验父分类编号的有效性 + validateParentProductCategory(null, createReqVO.getParentId()); + // 校验分类名称的唯一性 + validateProductCategoryNameUnique(null, createReqVO.getParentId(), createReqVO.getName()); + + // 插入 + ErpProductCategoryDO category = BeanUtils.toBean(createReqVO, ErpProductCategoryDO.class); + productCategoryMapper.insert(category); + // 返回 + return category.getId(); + } + + @Override + public void updateProductCategory(ErpProductCategorySaveReqVO updateReqVO) { + // 校验存在 + validateProductCategoryExists(updateReqVO.getId()); + // 校验父分类编号的有效性 + validateParentProductCategory(updateReqVO.getId(), updateReqVO.getParentId()); + // 校验分类名称的唯一性 + validateProductCategoryNameUnique(updateReqVO.getId(), updateReqVO.getParentId(), updateReqVO.getName()); + + // 更新 + ErpProductCategoryDO updateObj = BeanUtils.toBean(updateReqVO, ErpProductCategoryDO.class); + productCategoryMapper.updateById(updateObj); + } + + @Override + public void deleteProductCategory(Long id) { + // 校验存在 + validateProductCategoryExists(id); + // 校验是否有子产品分类 + if (productCategoryMapper.selectCountByParentId(id) > 0) { + throw exception(PRODUCT_CATEGORY_EXITS_CHILDREN); + } + // 删除 + productCategoryMapper.deleteById(id); + } + + private void validateProductCategoryExists(Long id) { + if (productCategoryMapper.selectById(id) == null) { + throw exception(PRODUCT_CATEGORY_NOT_EXISTS); + } + } + + private void validateParentProductCategory(Long id, Long parentId) { + if (parentId == null || ErpProductCategoryDO.PARENT_ID_ROOT.equals(parentId)) { + return; + } + // 1. 不能设置自己为父产品分类 + if (Objects.equals(id, parentId)) { + throw exception(PRODUCT_CATEGORY_PARENT_ERROR); + } + // 2. 父产品分类不存在 + ErpProductCategoryDO parentCategory = productCategoryMapper.selectById(parentId); + if (parentCategory == null) { + throw exception(PRODUCT_CATEGORY_PARENT_NOT_EXITS); + } + // 3. 递归校验父产品分类,如果父产品分类是自己的子产品分类,则报错,避免形成环路 + if (id == null) { // id 为空,说明新增,不需要考虑环路 + return; + } + for (int i = 0; i < Short.MAX_VALUE; i++) { + // 3.1 校验环路 + parentId = parentCategory.getParentId(); + if (Objects.equals(id, parentId)) { + throw exception(PRODUCT_CATEGORY_PARENT_IS_CHILD); + } + // 3.2 继续递归下一级父产品分类 + if (parentId == null || ErpProductCategoryDO.PARENT_ID_ROOT.equals(parentId)) { + break; + } + parentCategory = productCategoryMapper.selectById(parentId); + if (parentCategory == null) { + break; + } + } + } + + private void validateProductCategoryNameUnique(Long id, Long parentId, String name) { + ErpProductCategoryDO productCategory = productCategoryMapper.selectByParentIdAndName(parentId, name); + if (productCategory == null) { + return; + } + // 如果 id 为空,说明不用比较是否为相同 id 的产品分类 + if (id == null) { + throw exception(PRODUCT_CATEGORY_NAME_DUPLICATE); + } + if (!Objects.equals(productCategory.getId(), id)) { + throw exception(PRODUCT_CATEGORY_NAME_DUPLICATE); + } + } + + @Override + public ErpProductCategoryDO getProductCategory(Long id) { + return productCategoryMapper.selectById(id); + } + + @Override + public List getProductCategoryList(ErpProductCategoryListReqVO listReqVO) { + return productCategoryMapper.selectList(listReqVO); + } + +} \ No newline at end of file diff --git a/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/service/product/ErpProductService.java b/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/service/product/ErpProductService.java new file mode 100644 index 000000000..1087ab70d --- /dev/null +++ b/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/service/product/ErpProductService.java @@ -0,0 +1,54 @@ +package cn.iocoder.yudao.module.erp.service.product; + +import cn.iocoder.yudao.module.erp.controller.admin.product.vo.product.ProductPageReqVO; +import cn.iocoder.yudao.module.erp.controller.admin.product.vo.product.ProductSaveReqVO; +import jakarta.validation.*; +import cn.iocoder.yudao.module.erp.dal.dataobject.product.ErpProductDO; +import cn.iocoder.yudao.framework.common.pojo.PageResult; + +/** + * ERP 产品 Service 接口 + * + * @author 芋道源码 + */ +public interface ErpProductService { + + /** + * 创建产品 + * + * @param createReqVO 创建信息 + * @return 编号 + */ + Long createProduct(@Valid ProductSaveReqVO createReqVO); + + /** + * 更新产品 + * + * @param updateReqVO 更新信息 + */ + void updateProduct(@Valid ProductSaveReqVO updateReqVO); + + /** + * 删除产品 + * + * @param id 编号 + */ + void deleteProduct(Long id); + + /** + * 获得产品 + * + * @param id 编号 + * @return 产品 + */ + ErpProductDO getProduct(Long id); + + /** + * 获得产品分页 + * + * @param pageReqVO 分页查询 + * @return 产品分页 + */ + PageResult getProductPage(ProductPageReqVO pageReqVO); + +} \ No newline at end of file diff --git a/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/service/product/ErpProductServiceImpl.java b/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/service/product/ErpProductServiceImpl.java new file mode 100644 index 000000000..9fbe1f6e4 --- /dev/null +++ b/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/service/product/ErpProductServiceImpl.java @@ -0,0 +1,72 @@ +package cn.iocoder.yudao.module.erp.service.product; + +import cn.iocoder.yudao.module.erp.controller.admin.product.vo.product.ProductPageReqVO; +import cn.iocoder.yudao.module.erp.controller.admin.product.vo.product.ProductSaveReqVO; +import org.springframework.stereotype.Service; +import jakarta.annotation.Resource; +import org.springframework.validation.annotation.Validated; + +import cn.iocoder.yudao.module.erp.dal.dataobject.product.ErpProductDO; +import cn.iocoder.yudao.framework.common.pojo.PageResult; +import cn.iocoder.yudao.framework.common.util.object.BeanUtils; + +import cn.iocoder.yudao.module.erp.dal.mysql.product.ErpProductMapper; + +import static cn.iocoder.yudao.framework.common.exception.util.ServiceExceptionUtil.exception; +import static cn.iocoder.yudao.module.erp.ErrorCodeConstants.PRODUCT_NOT_EXISTS; + +/** + * ERP 产品 Service 实现类 + * + * @author 芋道源码 + */ +@Service +@Validated +public class ErpProductServiceImpl implements ErpProductService { + + @Resource + private ErpProductMapper productMapper; + + @Override + public Long createProduct(ProductSaveReqVO createReqVO) { + // 插入 + ErpProductDO product = BeanUtils.toBean(createReqVO, ErpProductDO.class); + productMapper.insert(product); + // 返回 + return product.getId(); + } + + @Override + public void updateProduct(ProductSaveReqVO updateReqVO) { + // 校验存在 + validateProductExists(updateReqVO.getId()); + // 更新 + ErpProductDO updateObj = BeanUtils.toBean(updateReqVO, ErpProductDO.class); + productMapper.updateById(updateObj); + } + + @Override + public void deleteProduct(Long id) { + // 校验存在 + validateProductExists(id); + // 删除 + productMapper.deleteById(id); + } + + private void validateProductExists(Long id) { + if (productMapper.selectById(id) == null) { + throw exception(PRODUCT_NOT_EXISTS); + } + } + + @Override + public ErpProductDO getProduct(Long id) { + return productMapper.selectById(id); + } + + @Override + public PageResult getProductPage(ProductPageReqVO pageReqVO) { + return productMapper.selectPage(pageReqVO); + } + +} \ No newline at end of file diff --git a/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/service/product/ErpProductUnitService.java b/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/service/product/ErpProductUnitService.java new file mode 100644 index 000000000..68599baf1 --- /dev/null +++ b/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/service/product/ErpProductUnitService.java @@ -0,0 +1,54 @@ +package cn.iocoder.yudao.module.erp.service.product; + +import cn.iocoder.yudao.module.erp.controller.admin.product.vo.unit.ErpProductUnitPageReqVO; +import cn.iocoder.yudao.module.erp.controller.admin.product.vo.unit.ErpProductUnitSaveReqVO; +import jakarta.validation.*; +import cn.iocoder.yudao.module.erp.dal.dataobject.product.ErpProductUnitDO; +import cn.iocoder.yudao.framework.common.pojo.PageResult; + +/** + * ERP 产品单位 Service 接口 + * + * @author 芋道源码 + */ +public interface ErpProductUnitService { + + /** + * 创建产品单位 + * + * @param createReqVO 创建信息 + * @return 编号 + */ + Long createProductUnit(@Valid ErpProductUnitSaveReqVO createReqVO); + + /** + * 更新产品单位 + * + * @param updateReqVO 更新信息 + */ + void updateProductUnit(@Valid ErpProductUnitSaveReqVO updateReqVO); + + /** + * 删除产品单位 + * + * @param id 编号 + */ + void deleteProductUnit(Long id); + + /** + * 获得产品单位 + * + * @param id 编号 + * @return 产品单位 + */ + ErpProductUnitDO getProductUnit(Long id); + + /** + * 获得产品单位分页 + * + * @param pageReqVO 分页查询 + * @return 产品单位分页 + */ + PageResult getProductUnitPage(ErpProductUnitPageReqVO pageReqVO); + +} \ No newline at end of file diff --git a/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/service/product/ErpProductUnitServiceImpl.java b/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/service/product/ErpProductUnitServiceImpl.java new file mode 100644 index 000000000..6800bda31 --- /dev/null +++ b/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/service/product/ErpProductUnitServiceImpl.java @@ -0,0 +1,72 @@ +package cn.iocoder.yudao.module.erp.service.product; + +import cn.iocoder.yudao.module.erp.controller.admin.product.vo.unit.ErpProductUnitPageReqVO; +import cn.iocoder.yudao.module.erp.controller.admin.product.vo.unit.ErpProductUnitSaveReqVO; +import org.springframework.stereotype.Service; +import jakarta.annotation.Resource; +import org.springframework.validation.annotation.Validated; + +import cn.iocoder.yudao.module.erp.dal.dataobject.product.ErpProductUnitDO; +import cn.iocoder.yudao.framework.common.pojo.PageResult; +import cn.iocoder.yudao.framework.common.util.object.BeanUtils; + +import cn.iocoder.yudao.module.erp.dal.mysql.product.ErpProductUnitMapper; + +import static cn.iocoder.yudao.framework.common.exception.util.ServiceExceptionUtil.exception; +import static cn.iocoder.yudao.module.erp.ErrorCodeConstants.PRODUCT_UNIT_NOT_EXISTS; + +/** + * ERP 产品单位 Service 实现类 + * + * @author 芋道源码 + */ +@Service +@Validated +public class ErpProductUnitServiceImpl implements ErpProductUnitService { + + @Resource + private ErpProductUnitMapper productUnitMapper; + + @Override + public Long createProductUnit(ErpProductUnitSaveReqVO createReqVO) { + // 插入 + ErpProductUnitDO unit = BeanUtils.toBean(createReqVO, ErpProductUnitDO.class); + productUnitMapper.insert(unit); + // 返回 + return unit.getId(); + } + + @Override + public void updateProductUnit(ErpProductUnitSaveReqVO updateReqVO) { + // 校验存在 + validateProductUnitExists(updateReqVO.getId()); + // 更新 + ErpProductUnitDO updateObj = BeanUtils.toBean(updateReqVO, ErpProductUnitDO.class); + productUnitMapper.updateById(updateObj); + } + + @Override + public void deleteProductUnit(Long id) { + // 校验存在 + validateProductUnitExists(id); + // 删除 + productUnitMapper.deleteById(id); + } + + private void validateProductUnitExists(Long id) { + if (productUnitMapper.selectById(id) == null) { + throw exception(PRODUCT_UNIT_NOT_EXISTS); + } + } + + @Override + public ErpProductUnitDO getProductUnit(Long id) { + return productUnitMapper.selectById(id); + } + + @Override + public PageResult getProductUnitPage(ErpProductUnitPageReqVO pageReqVO) { + return productUnitMapper.selectPage(pageReqVO); + } + +} \ No newline at end of file diff --git a/yudao-module-erp/yudao-module-erp-biz/src/main/resources/mapper/product/ErpProductUnitMapper.xml b/yudao-module-erp/yudao-module-erp-biz/src/main/resources/mapper/product/ErpProductUnitMapper.xml new file mode 100644 index 000000000..4666e48d4 --- /dev/null +++ b/yudao-module-erp/yudao-module-erp-biz/src/main/resources/mapper/product/ErpProductUnitMapper.xml @@ -0,0 +1,12 @@ + + + + + + + \ No newline at end of file diff --git a/yudao-module-erp/yudao-module-erp-biz/src/test/java/cn/iocoder/yudao/module/erp/service/product/ErpProductUnitServiceImplTest.java b/yudao-module-erp/yudao-module-erp-biz/src/test/java/cn/iocoder/yudao/module/erp/service/product/ErpProductUnitServiceImplTest.java new file mode 100644 index 000000000..c4023df0e --- /dev/null +++ b/yudao-module-erp/yudao-module-erp-biz/src/test/java/cn/iocoder/yudao/module/erp/service/product/ErpProductUnitServiceImplTest.java @@ -0,0 +1,131 @@ +package cn.iocoder.yudao.module.erp.service.product; + +import cn.iocoder.yudao.module.erp.controller.admin.product.vo.unit.ErpProductUnitPageReqVO; +import cn.iocoder.yudao.module.erp.controller.admin.product.vo.unit.ErpProductUnitSaveReqVO; +import org.junit.jupiter.api.Disabled; +import org.junit.jupiter.api.Test; + +import jakarta.annotation.Resource; + +import cn.iocoder.yudao.framework.test.core.ut.BaseDbUnitTest; + +import cn.iocoder.yudao.module.erp.dal.dataobject.product.ErpProductUnitDO; +import cn.iocoder.yudao.module.erp.dal.mysql.product.ErpProductUnitMapper; +import cn.iocoder.yudao.framework.common.pojo.PageResult; + +import org.springframework.context.annotation.Import; + +import static cn.iocoder.yudao.framework.test.core.util.AssertUtils.*; +import static cn.iocoder.yudao.framework.test.core.util.RandomUtils.*; +import static cn.iocoder.yudao.framework.common.util.date.LocalDateTimeUtils.*; +import static cn.iocoder.yudao.framework.common.util.object.ObjectUtils.*; +import static org.junit.jupiter.api.Assertions.*; + +/** + * {@link ErpProductUnitServiceImpl} 的单元测试类 + * + * @author 芋道源码 + */ +@Import(ErpProductUnitServiceImpl.class) +public class ErpProductUnitServiceImplTest extends BaseDbUnitTest { + + @Resource + private ErpProductUnitServiceImpl productUnitService; + + @Resource + private ErpProductUnitMapper productUnitMapper; + + @Test + public void testCreateProductUnit_success() { + // 准备参数 + ErpProductUnitSaveReqVO createReqVO = randomPojo(ErpProductUnitSaveReqVO.class).setId(null); + + // 调用 + Long productUnitId = productUnitService.createProductUnit(createReqVO); + // 断言 + assertNotNull(productUnitId); + // 校验记录的属性是否正确 + ErpProductUnitDO productUnit = productUnitMapper.selectById(productUnitId); + assertPojoEquals(createReqVO, productUnit, "id"); + } + + @Test + public void testUpdateProductUnit_success() { + // mock 数据 + ErpProductUnitDO dbProductUnit = randomPojo(ErpProductUnitDO.class); + productUnitMapper.insert(dbProductUnit);// @Sql: 先插入出一条存在的数据 + // 准备参数 + ErpProductUnitSaveReqVO updateReqVO = randomPojo(ErpProductUnitSaveReqVO.class, o -> { + o.setId(dbProductUnit.getId()); // 设置更新的 ID + }); + + // 调用 + productUnitService.updateProductUnit(updateReqVO); + // 校验是否更新正确 + ErpProductUnitDO productUnit = productUnitMapper.selectById(updateReqVO.getId()); // 获取最新的 + assertPojoEquals(updateReqVO, productUnit); + } + + @Test + public void testUpdateProductUnit_notExists() { + // 准备参数 + ErpProductUnitSaveReqVO updateReqVO = randomPojo(ErpProductUnitSaveReqVO.class); + + // 调用, 并断言异常 + assertServiceException(() -> productUnitService.updateProductUnit(updateReqVO), PRODUCT_UNIT_NOT_EXISTS); + } + + @Test + public void testDeleteProductUnit_success() { + // mock 数据 + ErpProductUnitDO dbProductUnit = randomPojo(ErpProductUnitDO.class); + productUnitMapper.insert(dbProductUnit);// @Sql: 先插入出一条存在的数据 + // 准备参数 + Long id = dbProductUnit.getId(); + + // 调用 + productUnitService.deleteProductUnit(id); + // 校验数据不存在了 + assertNull(productUnitMapper.selectById(id)); + } + + @Test + public void testDeleteProductUnit_notExists() { + // 准备参数 + Long id = randomLongId(); + + // 调用, 并断言异常 + assertServiceException(() -> productUnitService.deleteProductUnit(id), PRODUCT_UNIT_NOT_EXISTS); + } + + @Test + @Disabled // TODO 请修改 null 为需要的值,然后删除 @Disabled 注解 + public void testGetProductUnitPage() { + // mock 数据 + ErpProductUnitDO dbProductUnit = randomPojo(ErpProductUnitDO.class, o -> { // 等会查询到 + o.setName(null); + o.setStatus(null); + o.setCreateTime(null); + }); + productUnitMapper.insert(dbProductUnit); + // 测试 name 不匹配 + productUnitMapper.insert(cloneIgnoreId(dbProductUnit, o -> o.setName(null))); + // 测试 status 不匹配 + productUnitMapper.insert(cloneIgnoreId(dbProductUnit, o -> o.setStatus(null))); + // 测试 createTime 不匹配 + productUnitMapper.insert(cloneIgnoreId(dbProductUnit, o -> o.setCreateTime(null))); + // 准备参数 + ErpProductUnitPageReqVO reqVO = new ErpProductUnitPageReqVO(); + reqVO.setName(null); + reqVO.setStatus(null); + reqVO.setCreateTime(buildBetweenTime(2023, 2, 1, 2023, 2, 28)); + + // 调用 + PageResult pageResult = productUnitService.getProductUnitPage(reqVO); + // 断言 + assertEquals(1, pageResult.getTotal()); + assertEquals(1, pageResult.getList().size()); + assertPojoEquals(dbProductUnit, pageResult.getList().get(0)); + } + +} \ No newline at end of file diff --git a/yudao-module-erp/yudao-module-erp-biz/src/test/java/cn/iocoder/yudao/module/erp/service/product/ProductServiceImplTest.java b/yudao-module-erp/yudao-module-erp-biz/src/test/java/cn/iocoder/yudao/module/erp/service/product/ProductServiceImplTest.java new file mode 100644 index 000000000..03298bcc3 --- /dev/null +++ b/yudao-module-erp/yudao-module-erp-biz/src/test/java/cn/iocoder/yudao/module/erp/service/product/ProductServiceImplTest.java @@ -0,0 +1,131 @@ +package cn.iocoder.yudao.module.erp.service.product; + +import cn.iocoder.yudao.module.erp.controller.admin.product.vo.product.ProductPageReqVO; +import cn.iocoder.yudao.module.erp.controller.admin.product.vo.product.ProductSaveReqVO; +import org.junit.jupiter.api.Disabled; +import org.junit.jupiter.api.Test; + +import jakarta.annotation.Resource; + +import cn.iocoder.yudao.framework.test.core.ut.BaseDbUnitTest; + +import cn.iocoder.yudao.module.erp.dal.dataobject.product.ErpProductDO; +import cn.iocoder.yudao.module.erp.dal.mysql.product.ErpProductMapper; +import cn.iocoder.yudao.framework.common.pojo.PageResult; + +import org.springframework.context.annotation.Import; + +import static cn.iocoder.yudao.framework.test.core.util.AssertUtils.*; +import static cn.iocoder.yudao.framework.test.core.util.RandomUtils.*; +import static cn.iocoder.yudao.framework.common.util.date.LocalDateTimeUtils.*; +import static cn.iocoder.yudao.framework.common.util.object.ObjectUtils.*; +import static org.junit.jupiter.api.Assertions.*; + +/** + * {@link ErpProductServiceImpl} 的单元测试类 + * + * @author 芋道源码 + */ +@Import(ErpProductServiceImpl.class) +public class ProductServiceImplTest extends BaseDbUnitTest { + + @Resource + private ErpProductServiceImpl productService; + + @Resource + private ErpProductMapper productMapper; + + @Test + public void testCreateProduct_success() { + // 准备参数 + ProductSaveReqVO createReqVO = randomPojo(ProductSaveReqVO.class).setId(null); + + // 调用 + Long productId = productService.createProduct(createReqVO); + // 断言 + assertNotNull(productId); + // 校验记录的属性是否正确 + ErpProductDO product = productMapper.selectById(productId); + assertPojoEquals(createReqVO, product, "id"); + } + + @Test + public void testUpdateProduct_success() { + // mock 数据 + ErpProductDO dbProduct = randomPojo(ErpProductDO.class); + productMapper.insert(dbProduct);// @Sql: 先插入出一条存在的数据 + // 准备参数 + ProductSaveReqVO updateReqVO = randomPojo(ProductSaveReqVO.class, o -> { + o.setId(dbProduct.getId()); // 设置更新的 ID + }); + + // 调用 + productService.updateProduct(updateReqVO); + // 校验是否更新正确 + ErpProductDO product = productMapper.selectById(updateReqVO.getId()); // 获取最新的 + assertPojoEquals(updateReqVO, product); + } + + @Test + public void testUpdateProduct_notExists() { + // 准备参数 + ProductSaveReqVO updateReqVO = randomPojo(ProductSaveReqVO.class); + + // 调用, 并断言异常 + assertServiceException(() -> productService.updateProduct(updateReqVO), PRODUCT_NOT_EXISTS); + } + + @Test + public void testDeleteProduct_success() { + // mock 数据 + ErpProductDO dbProduct = randomPojo(ErpProductDO.class); + productMapper.insert(dbProduct);// @Sql: 先插入出一条存在的数据 + // 准备参数 + Long id = dbProduct.getId(); + + // 调用 + productService.deleteProduct(id); + // 校验数据不存在了 + assertNull(productMapper.selectById(id)); + } + + @Test + public void testDeleteProduct_notExists() { + // 准备参数 + Long id = randomLongId(); + + // 调用, 并断言异常 + assertServiceException(() -> productService.deleteProduct(id), PRODUCT_NOT_EXISTS); + } + + @Test + @Disabled // TODO 请修改 null 为需要的值,然后删除 @Disabled 注解 + public void testGetProductPage() { + // mock 数据 + ErpProductDO dbProduct = randomPojo(ErpProductDO.class, o -> { // 等会查询到 + o.setName(null); + o.setCategoryId(null); + o.setCreateTime(null); + }); + productMapper.insert(dbProduct); + // 测试 name 不匹配 + productMapper.insert(cloneIgnoreId(dbProduct, o -> o.setName(null))); + // 测试 categoryId 不匹配 + productMapper.insert(cloneIgnoreId(dbProduct, o -> o.setCategoryId(null))); + // 测试 createTime 不匹配 + productMapper.insert(cloneIgnoreId(dbProduct, o -> o.setCreateTime(null))); + // 准备参数 + ProductPageReqVO reqVO = new ProductPageReqVO(); + reqVO.setName(null); + reqVO.setCategoryId(null); + reqVO.setCreateTime(buildBetweenTime(2023, 2, 1, 2023, 2, 28)); + + // 调用 + PageResult pageResult = productService.getProductPage(reqVO); + // 断言 + assertEquals(1, pageResult.getTotal()); + assertEquals(1, pageResult.getList().size()); + assertPojoEquals(dbProduct, pageResult.getList().get(0)); + } + +} \ No newline at end of file From 5804957149768fcf47f008eaebfa0456842e0e45 Mon Sep 17 00:00:00 2001 From: owen Date: Sun, 4 Feb 2024 20:57:06 +0800 Subject: [PATCH 069/119] =?UTF-8?q?=E5=9F=BA=E7=A1=80=E8=AE=BE=E6=96=BD?= =?UTF-8?q?=EF=BC=9A=E5=89=8D=E7=AB=AF=E7=9B=B4=E8=BF=9E=E4=B8=8A=E4=BC=A0?= =?UTF-8?q?=EF=BC=8C=E4=BC=98=E5=85=88=E4=BD=BF=E7=94=A8=E8=87=AA=E5=AE=9A?= =?UTF-8?q?=E4=B9=89=E5=9F=9F=E5=90=8D?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../file/core/client/FileClient.java | 4 ++- .../core/client/s3/FilePresignedUrlBO.java | 27 +++++++++++++++++++ .../file/core/client/s3/S3FileClient.java | 5 ++-- .../file/vo/file/FilePresignedUrlRespVO.java | 3 +++ .../infra/service/file/FileServiceImpl.java | 5 ++-- 5 files changed, 39 insertions(+), 5 deletions(-) create mode 100644 yudao-framework/yudao-spring-boot-starter-file/src/main/java/cn/iocoder/yudao/framework/file/core/client/s3/FilePresignedUrlBO.java diff --git a/yudao-framework/yudao-spring-boot-starter-file/src/main/java/cn/iocoder/yudao/framework/file/core/client/FileClient.java b/yudao-framework/yudao-spring-boot-starter-file/src/main/java/cn/iocoder/yudao/framework/file/core/client/FileClient.java index 6663eb663..81b7049db 100644 --- a/yudao-framework/yudao-spring-boot-starter-file/src/main/java/cn/iocoder/yudao/framework/file/core/client/FileClient.java +++ b/yudao-framework/yudao-spring-boot-starter-file/src/main/java/cn/iocoder/yudao/framework/file/core/client/FileClient.java @@ -1,5 +1,7 @@ package cn.iocoder.yudao.framework.file.core.client; +import cn.iocoder.yudao.framework.file.core.client.s3.FilePresignedUrlBO; + /** * 文件客户端 * @@ -46,7 +48,7 @@ public interface FileClient { * @param fileName 文件名称 * @return 文件预签名地址 */ - default String getPresignedObjectUrl(String fileName) throws Exception { + default FilePresignedUrlBO getPresignedObjectUrl(String fileName) throws Exception { throw new UnsupportedOperationException("不支持的操作"); } diff --git a/yudao-framework/yudao-spring-boot-starter-file/src/main/java/cn/iocoder/yudao/framework/file/core/client/s3/FilePresignedUrlBO.java b/yudao-framework/yudao-spring-boot-starter-file/src/main/java/cn/iocoder/yudao/framework/file/core/client/s3/FilePresignedUrlBO.java new file mode 100644 index 000000000..ce5f748d8 --- /dev/null +++ b/yudao-framework/yudao-spring-boot-starter-file/src/main/java/cn/iocoder/yudao/framework/file/core/client/s3/FilePresignedUrlBO.java @@ -0,0 +1,27 @@ +package cn.iocoder.yudao.framework.file.core.client.s3; + +import lombok.AllArgsConstructor; +import lombok.Data; +import lombok.NoArgsConstructor; + +/** + * 文件预签名地址 BO + * + * @author owen + */ +@AllArgsConstructor +@NoArgsConstructor +@Data +public class FilePresignedUrlBO { + + /** + * 文件上传 URL(用于上传) + */ + private String uploadUrl; + + /** + * 文件 URL(用于读取、下载等) + */ + private String url; + +} diff --git a/yudao-framework/yudao-spring-boot-starter-file/src/main/java/cn/iocoder/yudao/framework/file/core/client/s3/S3FileClient.java b/yudao-framework/yudao-spring-boot-starter-file/src/main/java/cn/iocoder/yudao/framework/file/core/client/s3/S3FileClient.java index 5d9d19c35..8144ec7a8 100644 --- a/yudao-framework/yudao-spring-boot-starter-file/src/main/java/cn/iocoder/yudao/framework/file/core/client/s3/S3FileClient.java +++ b/yudao-framework/yudao-spring-boot-starter-file/src/main/java/cn/iocoder/yudao/framework/file/core/client/s3/S3FileClient.java @@ -120,8 +120,8 @@ public class S3FileClient extends AbstractFileClient { } @Override - public String getPresignedObjectUrl(String fileName) throws Exception { - return client.getPresignedObjectUrl(GetPresignedObjectUrlArgs.builder() + public FilePresignedUrlBO getPresignedObjectUrl(String fileName) throws Exception { + String uploadUrl = client.getPresignedObjectUrl(GetPresignedObjectUrlArgs.builder() .method(Method.PUT) .bucket(config.getBucket()) .object(fileName) @@ -132,5 +132,6 @@ public class S3FileClient extends AbstractFileClient { .expiry(10, TimeUnit.MINUTES) .build() ); + return new FilePresignedUrlBO(uploadUrl, config.getDomain() + "/" + fileName); } } diff --git a/yudao-module-infra/yudao-module-infra-biz/src/main/java/cn/iocoder/yudao/module/infra/controller/admin/file/vo/file/FilePresignedUrlRespVO.java b/yudao-module-infra/yudao-module-infra-biz/src/main/java/cn/iocoder/yudao/module/infra/controller/admin/file/vo/file/FilePresignedUrlRespVO.java index 2db39ef7b..7115db129 100644 --- a/yudao-module-infra/yudao-module-infra-biz/src/main/java/cn/iocoder/yudao/module/infra/controller/admin/file/vo/file/FilePresignedUrlRespVO.java +++ b/yudao-module-infra/yudao-module-infra-biz/src/main/java/cn/iocoder/yudao/module/infra/controller/admin/file/vo/file/FilePresignedUrlRespVO.java @@ -14,6 +14,9 @@ public class FilePresignedUrlRespVO { @Schema(description = "配置编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "11") private Long configId; + @Schema(description = "文件上传 URL", requiredMode = Schema.RequiredMode.REQUIRED, example = "https://www.iocoder.cn/yudao.jpg") + private String uploadUrl; + @Schema(description = "文件 URL", requiredMode = Schema.RequiredMode.REQUIRED, example = "https://www.iocoder.cn/yudao.jpg") private String url; diff --git a/yudao-module-infra/yudao-module-infra-biz/src/main/java/cn/iocoder/yudao/module/infra/service/file/FileServiceImpl.java b/yudao-module-infra/yudao-module-infra-biz/src/main/java/cn/iocoder/yudao/module/infra/service/file/FileServiceImpl.java index e5b84b00e..8b4922a78 100644 --- a/yudao-module-infra/yudao-module-infra-biz/src/main/java/cn/iocoder/yudao/module/infra/service/file/FileServiceImpl.java +++ b/yudao-module-infra/yudao-module-infra-biz/src/main/java/cn/iocoder/yudao/module/infra/service/file/FileServiceImpl.java @@ -6,6 +6,7 @@ import cn.iocoder.yudao.framework.common.pojo.PageResult; import cn.iocoder.yudao.framework.common.util.io.FileUtils; import cn.iocoder.yudao.framework.common.util.object.BeanUtils; import cn.iocoder.yudao.framework.file.core.client.FileClient; +import cn.iocoder.yudao.framework.file.core.client.s3.FilePresignedUrlBO; import cn.iocoder.yudao.framework.file.core.utils.FileTypeUtils; import cn.iocoder.yudao.module.infra.controller.admin.file.vo.file.FileCreateReqVO; import cn.iocoder.yudao.module.infra.controller.admin.file.vo.file.FilePageReqVO; @@ -109,8 +110,8 @@ public class FileServiceImpl implements FileService { @Override public FilePresignedUrlRespVO getFilePresignedUrl(String fileName) throws Exception { FileClient fileClient = fileConfigService.getMasterFileClient(); - String url = fileClient.getPresignedObjectUrl(fileName); - return new FilePresignedUrlRespVO(fileClient.getId(), url); + FilePresignedUrlBO bo = fileClient.getPresignedObjectUrl(fileName); + return BeanUtils.toBean(bo, FilePresignedUrlRespVO.class, f -> f.setConfigId(fileClient.getId())); } } From 3213cad31750787918207f2e21984e92b0469700 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E5=AE=89=E6=B5=A9=E6=B5=A9?= <1036606149@qq.com> Date: Sun, 4 Feb 2024 23:54:58 +0800 Subject: [PATCH 070/119] =?UTF-8?q?=E6=96=B0=E5=A2=9E=EF=BC=9ACRM=20?= =?UTF-8?q?=E5=95=86=E4=B8=9A=E6=99=BA=E8=83=BD=EF=BC=8C=E5=85=B6=E4=BB=96?= =?UTF-8?q?=E6=8E=92=E5=90=8D=E6=8E=A5=E5=8F=A3?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../admin/bi/CrmBiRankController.java | 42 +++++++ .../crm/dal/mysql/bi/CrmBiRankingMapper.java | 47 ++++++++ .../crm/service/bi/CrmBiRankingService.java | 47 ++++++++ .../service/bi/CrmBiRankingServiceImpl.java | 30 +++++ .../mapper/bi/CrmBiRankingMapper.xml | 109 ++++++++++++++++-- 5 files changed, 266 insertions(+), 9 deletions(-) diff --git a/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/controller/admin/bi/CrmBiRankController.java b/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/controller/admin/bi/CrmBiRankController.java index a188232ef..21463aed0 100644 --- a/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/controller/admin/bi/CrmBiRankController.java +++ b/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/controller/admin/bi/CrmBiRankController.java @@ -42,4 +42,46 @@ public class CrmBiRankController { return success(rankingService.getReceivablePriceRank(rankingReqVO)); } + @GetMapping("/get-contract-count-rank") + @Operation(summary = "获得签约合同数量排行榜") + @PreAuthorize("@ss.hasPermission('crm:bi-rank:query')") + public CommonResult> getContractCountRank(@Valid CrmBiRankReqVO rankingReqVO) { + return success(rankingService.getContractCountRank(rankingReqVO)); + } + + @GetMapping("/get-product-sales-rank") + @Operation(summary = "获得产品销量排行榜") + @PreAuthorize("@ss.hasPermission('crm:bi-rank:query')") + public CommonResult> getProductSalesRank(@Valid CrmBiRankReqVO rankingReqVO) { + return success(rankingService.getProductSalesRank(rankingReqVO)); + } + + @GetMapping("/get-customer-count-rank") + @Operation(summary = "获得新增客户数排行榜") + @PreAuthorize("@ss.hasPermission('crm:bi-rank:query')") + public CommonResult> getCustomerCountRank(@Valid CrmBiRankReqVO rankingReqVO) { + return success(rankingService.getCustomerCountRank(rankingReqVO)); + } + + @GetMapping("/get-contacts-count-rank") + @Operation(summary = "获得新增联系人数排行榜") + @PreAuthorize("@ss.hasPermission('crm:bi-rank:query')") + public CommonResult> getContactsCountRank(@Valid CrmBiRankReqVO rankingReqVO) { + return success(rankingService.getContactsCountRank(rankingReqVO)); + } + + @GetMapping("/get-follow-count-rank") + @Operation(summary = "获得跟进次数排行榜") + @PreAuthorize("@ss.hasPermission('crm:bi-rank:query')") + public CommonResult> getFollowCountRank(@Valid CrmBiRankReqVO rankingReqVO) { + return success(rankingService.getFollowCountRank(rankingReqVO)); + } + + @GetMapping("/get-follow-customer-count-rank") + @Operation(summary = "获得跟进客户数排行榜") + @PreAuthorize("@ss.hasPermission('crm:bi-rank:query')") + public CommonResult> getFollowCustomerCountRank(@Valid CrmBiRankReqVO rankingReqVO) { + return success(rankingService.getFollowCustomerCountRank(rankingReqVO)); + } + } diff --git a/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/dal/mysql/bi/CrmBiRankingMapper.java b/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/dal/mysql/bi/CrmBiRankingMapper.java index 91b7a191b..75dbc7a8a 100644 --- a/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/dal/mysql/bi/CrmBiRankingMapper.java +++ b/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/dal/mysql/bi/CrmBiRankingMapper.java @@ -30,4 +30,51 @@ public interface CrmBiRankingMapper { */ List selectReceivablePriceRank(CrmBiRankReqVO rankReqVO); + /** + * 查询签约合同数量排行榜 + * + * @param rankReqVO 参数 + * @return 签约合同数量排行榜 + */ + List selectContractCountRank(CrmBiRankReqVO rankReqVO); + + /** + * 查询产品销量排行榜 + * + * @param rankReqVO 参数 + * @return 产品销量排行榜 + */ + List selectProductSalesRank(CrmBiRankReqVO rankReqVO); + + /** + * 查询新增客户数排行榜 + * + * @param rankReqVO 参数 + * @return 新增客户数排行榜 + */ + List selectCustomerCountRank(CrmBiRankReqVO rankReqVO); + + /** + * 查询联系人数量排行榜 + * + * @param rankReqVO 参数 + * @return 联系人数量排行榜 + */ + List selectContactsCountRank(CrmBiRankReqVO rankReqVO); + + /** + * 查询跟进次数排行榜 + * + * @param rankReqVO 参数 + * @return 跟进次数排行榜 + */ + List selectFollowCountRank(CrmBiRankReqVO rankReqVO); + + /** + * 查询跟进客户数排行榜 + * + * @param rankReqVO 参数 + * @return 跟进客户数排行榜 + */ + List selectFollowCustomerCountRank(CrmBiRankReqVO rankReqVO); } diff --git a/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/service/bi/CrmBiRankingService.java b/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/service/bi/CrmBiRankingService.java index 72d1d6f97..5520911a3 100644 --- a/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/service/bi/CrmBiRankingService.java +++ b/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/service/bi/CrmBiRankingService.java @@ -29,4 +29,51 @@ public interface CrmBiRankingService { */ List getReceivablePriceRank(CrmBiRankReqVO rankReqVO); + /** + * 获得签约合同数量排行榜 + * + * @param rankReqVO 排行参数 + * @return 签约合同数量排行榜 + */ + List getContractCountRank(CrmBiRankReqVO rankReqVO); + + /** + * 获得产品销量排行榜 + * + * @param rankReqVO 排行参数 + * @return 产品销量排行榜 + */ + List getProductSalesRank(CrmBiRankReqVO rankReqVO); + + /** + * 获得新增客户数排行榜 + * + * @param rankReqVO 排行参数 + * @return 新增客户数排行榜 + */ + List getCustomerCountRank(CrmBiRankReqVO rankReqVO); + + /** + * 获得联系人数量排行榜 + * + * @param rankReqVO 排行参数 + * @return 联系人数量排行榜 + */ + List getContactsCountRank(CrmBiRankReqVO rankReqVO); + + /** + * 获得跟进次数排行榜 + * + * @param rankReqVO 排行参数 + * @return 跟进次数排行榜 + */ + List getFollowCountRank(CrmBiRankReqVO rankReqVO); + + /** + * 获得跟进客户数排行榜 + * + * @param rankReqVO 排行参数 + * @return 跟进客户数排行榜 + */ + List getFollowCustomerCountRank(CrmBiRankReqVO rankReqVO); } diff --git a/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/service/bi/CrmBiRankingServiceImpl.java b/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/service/bi/CrmBiRankingServiceImpl.java index 84f47ddc9..60e1b4ecb 100644 --- a/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/service/bi/CrmBiRankingServiceImpl.java +++ b/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/service/bi/CrmBiRankingServiceImpl.java @@ -49,6 +49,36 @@ public class CrmBiRankingServiceImpl implements CrmBiRankingService { return getRank(rankReqVO, biRankingMapper::selectReceivablePriceRank); } + @Override + public List getContractCountRank(CrmBiRankReqVO rankReqVO) { + return getRank(rankReqVO, biRankingMapper::selectContractCountRank); + } + + @Override + public List getProductSalesRank(CrmBiRankReqVO rankReqVO) { + return getRank(rankReqVO, biRankingMapper::selectProductSalesRank); + } + + @Override + public List getCustomerCountRank(CrmBiRankReqVO rankReqVO) { + return getRank(rankReqVO, biRankingMapper::selectCustomerCountRank); + } + + @Override + public List getContactsCountRank(CrmBiRankReqVO rankReqVO) { + return getRank(rankReqVO, biRankingMapper::selectContactsCountRank); + } + + @Override + public List getFollowCountRank(CrmBiRankReqVO rankReqVO) { + return getRank(rankReqVO, biRankingMapper::selectFollowCountRank); + } + + @Override + public List getFollowCustomerCountRank(CrmBiRankReqVO rankReqVO) { + return getRank(rankReqVO, biRankingMapper::selectFollowCustomerCountRank); + } + /** * 获得排行版数据 * diff --git a/yudao-module-crm/yudao-module-crm-biz/src/main/resources/mapper/bi/CrmBiRankingMapper.xml b/yudao-module-crm/yudao-module-crm-biz/src/main/resources/mapper/bi/CrmBiRankingMapper.xml index ef90bb564..f8e5737a5 100644 --- a/yudao-module-crm/yudao-module-crm-biz/src/main/resources/mapper/bi/CrmBiRankingMapper.xml +++ b/yudao-module-crm/yudao-module-crm-biz/src/main/resources/mapper/bi/CrmBiRankingMapper.xml @@ -9,10 +9,11 @@ WHERE deleted = 0 AND audit_status = 20 and owner_user_id in - - #{userId} - - AND order_date between #{times[0],javaType=java.time.LocalDateTime} and #{times[1],javaType=java.time.LocalDateTime} + + #{userId} + + AND order_date between #{times[0],javaType=java.time.LocalDateTime} and + #{times[1],javaType=java.time.LocalDateTime} GROUP BY owner_user_id @@ -22,12 +23,102 @@ FROM crm_receivable WHERE deleted = 0 AND audit_status = 20 - and owner_user_id in - - #{userId} - - AND return_time between #{times[0],javaType=java.time.LocalDateTime} and #{times[1],javaType=java.time.LocalDateTime} + AND owner_user_id in + + #{userId} + + AND return_time between #{times[0],javaType=java.time.LocalDateTime} and + #{times[1],javaType=java.time.LocalDateTime} GROUP BY owner_user_id + + + + + + + + + + + + + From 84f3b230d20b8db543861835500197b55318b7f8 Mon Sep 17 00:00:00 2001 From: puhui999 Date: Mon, 5 Feb 2024 00:14:50 +0800 Subject: [PATCH 071/119] =?UTF-8?q?CRM-=E5=90=88=E5=90=8C:=20=E6=96=B0?= =?UTF-8?q?=E5=A2=9E=E5=90=88=E5=90=8C=E5=85=B3=E8=81=94=E5=95=86=E5=93=81?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../CrmBusinessStatusTypeController.java | 4 +- .../vo/business/CrmBusinessSaveReqVO.java | 31 +++-- .../product/CrmBusinessProductPageReqVO.java | 15 --- .../vo/product/CrmBusinessProductRespVO.java | 11 -- .../product/CrmBusinessProductSaveReqVO.java | 49 -------- .../admin/contract/CrmContractController.java | 68 +++++----- .../CrmBusinessStatusConvert.java | 2 +- .../CrmBusinessStatusTypeConvert.java | 2 +- .../CrmBusinessProductConvert.java | 21 ---- .../convert/contract/CrmContractConvert.java | 21 +++- .../business/CrmBusinessProductDO.java | 18 --- .../contract/CrmContractProductDO.java | 63 ++++++++++ .../dal/dataobject/contract/package-info.java | 4 - .../business/CrmBusinessProductMapper.java | 7 ++ .../contract/CrmContractProductMapper.java | 31 +++++ .../dal/mysql/product/CrmProductMapper.java | 9 -- .../business/CrmBusinessProductService.java | 57 --------- .../CrmBusinessProductServiceImpl.java | 55 -------- .../business/CrmBusinessServiceImpl.java | 119 +++++++++--------- .../service/contract/CrmContractService.java | 9 ++ .../contract/CrmContractServiceImpl.java | 51 ++++---- .../product/CrmProductServiceImpl.java | 2 +- .../ErpProductUnitServiceImplTest.java | 25 ++-- .../product/ProductServiceImplTest.java | 25 ++-- 24 files changed, 302 insertions(+), 397 deletions(-) delete mode 100644 yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/controller/admin/business/vo/product/CrmBusinessProductPageReqVO.java delete mode 100644 yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/controller/admin/business/vo/product/CrmBusinessProductRespVO.java delete mode 100644 yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/controller/admin/business/vo/product/CrmBusinessProductSaveReqVO.java rename yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/convert/{businessstatus => business}/CrmBusinessStatusConvert.java (92%) rename yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/convert/{businessstatustype => business}/CrmBusinessStatusTypeConvert.java (96%) delete mode 100644 yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/convert/businessproduct/CrmBusinessProductConvert.java create mode 100644 yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/dal/dataobject/contract/CrmContractProductDO.java delete mode 100644 yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/dal/dataobject/contract/package-info.java create mode 100644 yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/dal/mysql/contract/CrmContractProductMapper.java delete mode 100644 yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/service/business/CrmBusinessProductService.java delete mode 100644 yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/service/business/CrmBusinessProductServiceImpl.java diff --git a/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/controller/admin/business/CrmBusinessStatusTypeController.java b/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/controller/admin/business/CrmBusinessStatusTypeController.java index 925fa4953..337590044 100644 --- a/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/controller/admin/business/CrmBusinessStatusTypeController.java +++ b/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/controller/admin/business/CrmBusinessStatusTypeController.java @@ -14,8 +14,8 @@ import cn.iocoder.yudao.module.crm.controller.admin.business.vo.type.CrmBusiness import cn.iocoder.yudao.module.crm.controller.admin.business.vo.type.CrmBusinessStatusTypeQueryVO; import cn.iocoder.yudao.module.crm.controller.admin.business.vo.type.CrmBusinessStatusTypeRespVO; import cn.iocoder.yudao.module.crm.controller.admin.business.vo.type.CrmBusinessStatusTypeSaveReqVO; -import cn.iocoder.yudao.module.crm.convert.businessstatus.CrmBusinessStatusConvert; -import cn.iocoder.yudao.module.crm.convert.businessstatustype.CrmBusinessStatusTypeConvert; +import cn.iocoder.yudao.module.crm.convert.business.CrmBusinessStatusConvert; +import cn.iocoder.yudao.module.crm.convert.business.CrmBusinessStatusTypeConvert; import cn.iocoder.yudao.module.crm.dal.dataobject.business.CrmBusinessStatusDO; import cn.iocoder.yudao.module.crm.dal.dataobject.business.CrmBusinessStatusTypeDO; import cn.iocoder.yudao.module.crm.service.business.CrmBusinessStatusService; diff --git a/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/controller/admin/business/vo/business/CrmBusinessSaveReqVO.java b/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/controller/admin/business/vo/business/CrmBusinessSaveReqVO.java index 672450c4a..c3b167ef1 100644 --- a/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/controller/admin/business/vo/business/CrmBusinessSaveReqVO.java +++ b/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/controller/admin/business/vo/business/CrmBusinessSaveReqVO.java @@ -1,18 +1,18 @@ package cn.iocoder.yudao.module.crm.controller.admin.business.vo.business; import cn.iocoder.yudao.framework.common.validation.InEnum; -import cn.iocoder.yudao.module.crm.controller.admin.business.vo.product.CrmBusinessProductSaveReqVO; import cn.iocoder.yudao.module.crm.enums.business.CrmBizEndStatus; import cn.iocoder.yudao.module.crm.framework.operatelog.core.CrmCustomerParseFunction; import com.mzt.logapi.starter.annotation.DiffLogField; import io.swagger.v3.oas.annotations.media.Schema; import jakarta.validation.constraints.NotNull; +import lombok.AllArgsConstructor; import lombok.Data; +import lombok.NoArgsConstructor; import org.springframework.format.annotation.DateTimeFormat; import java.math.BigDecimal; import java.time.LocalDateTime; -import java.util.ArrayList; import java.util.List; import static cn.iocoder.yudao.framework.common.util.date.DateUtils.FORMAT_YEAR_MONTH_DAY_HOUR_MINUTE_SECOND; @@ -58,7 +58,6 @@ public class CrmBusinessSaveReqVO { @DiffLogField(name = "商机金额") private Integer price; - // TODO @lzxhqs:折扣使用 Integer 类型,存储时,默认 * 100;展示的时候,前端需要 / 100;避免精度丢失问题 @Schema(description = "整单折扣") @DiffLogField(name = "整单折扣") private Integer discountPercent; @@ -75,11 +74,29 @@ public class CrmBusinessSaveReqVO { @InEnum(CrmBizEndStatus.class) private Integer endStatus; - // TODO @lzxhqs:不设置默认 new ArrayList<>();一般 pojo 不设置默认值哈 - @Schema(description = "商机产品列表") - private List products = new ArrayList<>(); - @Schema(description = "联系人编号", example = "110") private Long contactId; // 使用场景,在【联系人详情】添加商机时,如果需要关联两者,需要传递 contactId 字段 + @Schema(description = "产品列表") + private List productItems; + + @Schema(description = "产品列表") + @Data + @NoArgsConstructor + @AllArgsConstructor + public static class CrmBusinessProductItem { + + @Schema(description = "产品编号", example = "20529") + @NotNull(message = "产品编号不能为空") + private Long id; + + @Schema(description = "产品数量", requiredMode = Schema.RequiredMode.REQUIRED, example = "8911") + @NotNull(message = "产品数量不能为空") + private Integer count; + + @Schema(description = "产品折扣") + private Integer discountPercent; + + } + } diff --git a/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/controller/admin/business/vo/product/CrmBusinessProductPageReqVO.java b/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/controller/admin/business/vo/product/CrmBusinessProductPageReqVO.java deleted file mode 100644 index 4804768a5..000000000 --- a/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/controller/admin/business/vo/product/CrmBusinessProductPageReqVO.java +++ /dev/null @@ -1,15 +0,0 @@ -package cn.iocoder.yudao.module.crm.controller.admin.business.vo.product; - -import cn.iocoder.yudao.framework.common.pojo.PageParam; -import io.swagger.v3.oas.annotations.media.Schema; -import lombok.Data; -import lombok.EqualsAndHashCode; -import lombok.ToString; - -// TODO @lzxhqs:这个类,如果没用到,可以考虑删除哈 -@Schema(description = "管理后台 - 商机产品分页 Request VO") -@Data -@EqualsAndHashCode(callSuper = true) -@ToString(callSuper = true) -public class CrmBusinessProductPageReqVO extends PageParam { -} diff --git a/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/controller/admin/business/vo/product/CrmBusinessProductRespVO.java b/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/controller/admin/business/vo/product/CrmBusinessProductRespVO.java deleted file mode 100644 index d4996816f..000000000 --- a/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/controller/admin/business/vo/product/CrmBusinessProductRespVO.java +++ /dev/null @@ -1,11 +0,0 @@ -package cn.iocoder.yudao.module.crm.controller.admin.business.vo.product; - -import com.alibaba.excel.annotation.ExcelIgnoreUnannotated; -import io.swagger.v3.oas.annotations.media.Schema; -import lombok.Data; - -@Schema(description = "管理后台 - 商机产品关联 Response VO") -@Data -@ExcelIgnoreUnannotated -public class CrmBusinessProductRespVO { -} diff --git a/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/controller/admin/business/vo/product/CrmBusinessProductSaveReqVO.java b/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/controller/admin/business/vo/product/CrmBusinessProductSaveReqVO.java deleted file mode 100644 index f28f0f350..000000000 --- a/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/controller/admin/business/vo/product/CrmBusinessProductSaveReqVO.java +++ /dev/null @@ -1,49 +0,0 @@ -package cn.iocoder.yudao.module.crm.controller.admin.business.vo.product; - -import io.swagger.v3.oas.annotations.media.Schema; -import jakarta.validation.constraints.NotEmpty; -import jakarta.validation.constraints.NotNull; -import lombok.Data; - -import java.math.BigDecimal; - -@Schema(description = "管理后台 - CRM 商机产品关联表 创建/更新 Request VO") -@Data -public class CrmBusinessProductSaveReqVO { - - @Schema(description = "主键", requiredMode = Schema.RequiredMode.REQUIRED, example = "32129") - private Long id; - - @Schema(description = "商机编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "30320") - @NotNull(message = "商机编号不能为空") - private Long businessId; - - @Schema(description = "产品编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "30320") - @NotNull(message = "产品编号不能为空") - private Long productId; - - @Schema(description = "产品单价", requiredMode = Schema.RequiredMode.REQUIRED, example = "30320") - @NotNull(message = "产品单价不能为空") - private BigDecimal price; - - @Schema(description = "销售价格", requiredMode = Schema.RequiredMode.REQUIRED, example = "30320") - @NotNull(message = "销售价格不能为空") - private BigDecimal salesPrice; - - @Schema(description = "数量", requiredMode = Schema.RequiredMode.REQUIRED, example = "30320") - @NotNull(message = "数量不能为空") - private BigDecimal num; - - @Schema(description = "折扣", requiredMode = Schema.RequiredMode.REQUIRED, example = "30320") - @NotNull(message = "折扣不能为空") - private BigDecimal discount; - - @Schema(description = "小计(折扣后价格)", requiredMode = Schema.RequiredMode.REQUIRED, example = "30320") - @NotNull(message = "小计(折扣后价格)不能为空") - private BigDecimal subtotal; - - @Schema(description = "单位", requiredMode = Schema.RequiredMode.REQUIRED, example = "30320") - @NotEmpty(message = "单位不能为空") - private String unit; - -} diff --git a/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/controller/admin/contract/CrmContractController.java b/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/controller/admin/contract/CrmContractController.java index aaaccbd81..982ec274c 100644 --- a/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/controller/admin/contract/CrmContractController.java +++ b/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/controller/admin/contract/CrmContractController.java @@ -11,12 +11,11 @@ import cn.iocoder.yudao.framework.operatelog.core.annotations.OperateLog; import cn.iocoder.yudao.module.crm.controller.admin.contract.vo.*; import cn.iocoder.yudao.module.crm.convert.contract.CrmContractConvert; import cn.iocoder.yudao.module.crm.dal.dataobject.business.CrmBusinessDO; -import cn.iocoder.yudao.module.crm.dal.dataobject.business.CrmBusinessProductDO; import cn.iocoder.yudao.module.crm.dal.dataobject.contact.CrmContactDO; import cn.iocoder.yudao.module.crm.dal.dataobject.contract.CrmContractDO; +import cn.iocoder.yudao.module.crm.dal.dataobject.contract.CrmContractProductDO; import cn.iocoder.yudao.module.crm.dal.dataobject.customer.CrmCustomerDO; import cn.iocoder.yudao.module.crm.dal.dataobject.product.CrmProductDO; -import cn.iocoder.yudao.module.crm.service.business.CrmBusinessProductService; import cn.iocoder.yudao.module.crm.service.business.CrmBusinessService; import cn.iocoder.yudao.module.crm.service.contact.CrmContactService; import cn.iocoder.yudao.module.crm.service.contract.CrmContractService; @@ -30,7 +29,6 @@ import io.swagger.v3.oas.annotations.tags.Tag; import jakarta.annotation.Resource; import jakarta.servlet.http.HttpServletResponse; import jakarta.validation.Valid; -import org.springframework.context.annotation.Lazy; import org.springframework.security.access.prepost.PreAuthorize; import org.springframework.validation.annotation.Validated; import org.springframework.web.bind.annotation.*; @@ -43,7 +41,6 @@ import java.util.stream.Stream; import static cn.iocoder.yudao.framework.common.pojo.CommonResult.success; import static cn.iocoder.yudao.framework.common.util.collection.CollectionUtils.*; -import static cn.iocoder.yudao.framework.common.util.collection.MapUtils.findAndThen; import static cn.iocoder.yudao.framework.operatelog.core.enums.OperateTypeEnum.EXPORT; import static cn.iocoder.yudao.framework.security.core.util.SecurityFrameworkUtils.getLoginUserId; @@ -62,11 +59,7 @@ public class CrmContractController { @Resource private CrmBusinessService businessService; @Resource - @Lazy - private CrmBusinessProductService businessProductService; - @Resource private CrmProductService productService; - @Resource private AdminUserApi adminUserApi; @@ -105,22 +98,9 @@ public class CrmContractController { return success(null); } - // 2.1 拼接合同信息 + // 2. 拼接合同信息 List respVOList = buildContractDetailList(Collections.singletonList(contract)); - // 2.2 拼接产品信息 - // TODO @puhui999:下面这块也可以搞到 convert 里哈;可以在 ContractDetailList 加个开关,是不是查询商品信息;ps:jdk21 的方法不太能去用,因为 jdk8 项目要兼容; - CrmContractRespVO respVO = respVOList.get(0); - List businessProductList = businessProductService.getBusinessProductListByContractId(id); - Map businessProductMap = convertMap(businessProductList, CrmBusinessProductDO::getProductId); - List productList = productService.getProductListByIds(convertSet(businessProductList, CrmBusinessProductDO::getProductId)); - respVO.setProductItems(convertList(productList, product -> { - CrmContractRespVO.CrmContractProductItemRespVO productItemRespVO = BeanUtils.toBean(product, CrmContractRespVO.CrmContractProductItemRespVO.class); - findAndThen(businessProductMap, product.getId(), businessProduct -> { - productItemRespVO.setCount(businessProduct.getCount()).setDiscountPercent(businessProduct.getDiscountPercent()); - }); - return productItemRespVO; - })); - return success(respVO); + return success(respVOList.get(0)); } @GetMapping("/page") @@ -151,6 +131,22 @@ public class CrmContractController { BeanUtils.toBean(pageResult.getList(), CrmContractExcelVO.class)); } + @PutMapping("/transfer") + @Operation(summary = "合同转移") + @PreAuthorize("@ss.hasPermission('crm:contract:update')") + public CommonResult transferContract(@Valid @RequestBody CrmContractTransferReqVO reqVO) { + contractService.transferContract(reqVO, getLoginUserId()); + return success(true); + } + + @PutMapping("/submit") + @Operation(summary = "提交合同审批") + @PreAuthorize("@ss.hasPermission('crm:contract:update')") + public CommonResult submitContract(@RequestParam("id") Long id) { + contractService.submitContract(id, getLoginUserId()); + return success(true); + } + /** * 构建详细的合同结果 * @@ -173,23 +169,15 @@ public class CrmContractController { // 4. 获取商机 Map businessMap = convertMap(businessService.getBusinessList(convertSet(contractList, CrmContractDO::getBusinessId)), CrmBusinessDO::getId); - return CrmContractConvert.INSTANCE.convertList(contractList, userMap, customerList, contactMap, businessMap); - } - - @PutMapping("/transfer") - @Operation(summary = "合同转移") - @PreAuthorize("@ss.hasPermission('crm:contract:update')") - public CommonResult transferContract(@Valid @RequestBody CrmContractTransferReqVO reqVO) { - contractService.transferContract(reqVO, getLoginUserId()); - return success(true); - } - - @PutMapping("/submit") - @Operation(summary = "提交合同审批") - @PreAuthorize("@ss.hasPermission('crm:contract:update')") - public CommonResult submitContract(@RequestParam("id") Long id) { - contractService.submitContract(id, getLoginUserId()); - return success(true); + // 5. 获取合同关联的商品 + Map contractProductMap = null; + List productList = null; + if (contractList.size() == 1) { + List contractProductList = contractService.getContractProductListByContractId(contractList.get(0).getId()); + contractProductMap = convertMap(contractProductList, CrmContractProductDO::getProductId); + productList = productService.getProductListByIds(convertSet(contractProductList, CrmContractProductDO::getProductId)); + } + return CrmContractConvert.INSTANCE.convertList(contractList, userMap, customerList, contactMap, businessMap, contractProductMap, productList); } } diff --git a/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/convert/businessstatus/CrmBusinessStatusConvert.java b/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/convert/business/CrmBusinessStatusConvert.java similarity index 92% rename from yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/convert/businessstatus/CrmBusinessStatusConvert.java rename to yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/convert/business/CrmBusinessStatusConvert.java index df2532b27..52186e3d9 100644 --- a/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/convert/businessstatus/CrmBusinessStatusConvert.java +++ b/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/convert/business/CrmBusinessStatusConvert.java @@ -1,4 +1,4 @@ -package cn.iocoder.yudao.module.crm.convert.businessstatus; +package cn.iocoder.yudao.module.crm.convert.business; import cn.iocoder.yudao.framework.common.pojo.PageResult; import cn.iocoder.yudao.module.crm.controller.admin.business.vo.status.CrmBusinessStatusRespVO; diff --git a/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/convert/businessstatustype/CrmBusinessStatusTypeConvert.java b/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/convert/business/CrmBusinessStatusTypeConvert.java similarity index 96% rename from yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/convert/businessstatustype/CrmBusinessStatusTypeConvert.java rename to yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/convert/business/CrmBusinessStatusTypeConvert.java index be203b580..4876fb537 100644 --- a/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/convert/businessstatustype/CrmBusinessStatusTypeConvert.java +++ b/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/convert/business/CrmBusinessStatusTypeConvert.java @@ -1,4 +1,4 @@ -package cn.iocoder.yudao.module.crm.convert.businessstatustype; +package cn.iocoder.yudao.module.crm.convert.business; import cn.iocoder.yudao.framework.common.pojo.PageResult; import cn.iocoder.yudao.module.crm.controller.admin.business.vo.type.CrmBusinessStatusTypeRespVO; diff --git a/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/convert/businessproduct/CrmBusinessProductConvert.java b/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/convert/businessproduct/CrmBusinessProductConvert.java deleted file mode 100644 index 2fcd54d84..000000000 --- a/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/convert/businessproduct/CrmBusinessProductConvert.java +++ /dev/null @@ -1,21 +0,0 @@ -package cn.iocoder.yudao.module.crm.convert.businessproduct; - -import cn.iocoder.yudao.module.crm.controller.admin.business.vo.product.CrmBusinessProductSaveReqVO; -import cn.iocoder.yudao.module.crm.dal.dataobject.business.CrmBusinessProductDO; -import org.mapstruct.Mapper; -import org.mapstruct.factory.Mappers; - -// TODO @lzxhqs:看看是不是用 BeanUtils 替代了 -/** - * @author lzxhqs - * @version 1.0 - * @title CrmBusinessProductConvert - * @description - * @create 2024/1/12 - */ -@Mapper -public interface CrmBusinessProductConvert { - CrmBusinessProductConvert INSTANCE = Mappers.getMapper(CrmBusinessProductConvert.class); - - CrmBusinessProductDO convert(CrmBusinessProductSaveReqVO product); -} diff --git a/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/convert/contract/CrmContractConvert.java b/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/convert/contract/CrmContractConvert.java index c9247e6a5..444876040 100644 --- a/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/convert/contract/CrmContractConvert.java +++ b/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/convert/contract/CrmContractConvert.java @@ -1,12 +1,16 @@ package cn.iocoder.yudao.module.crm.convert.contract; +import cn.hutool.core.collection.CollUtil; +import cn.iocoder.yudao.framework.common.util.collection.CollectionUtils; import cn.iocoder.yudao.framework.common.util.object.BeanUtils; import cn.iocoder.yudao.module.crm.controller.admin.contract.vo.CrmContractRespVO; import cn.iocoder.yudao.module.crm.controller.admin.contract.vo.CrmContractTransferReqVO; import cn.iocoder.yudao.module.crm.dal.dataobject.business.CrmBusinessDO; import cn.iocoder.yudao.module.crm.dal.dataobject.contact.CrmContactDO; import cn.iocoder.yudao.module.crm.dal.dataobject.contract.CrmContractDO; +import cn.iocoder.yudao.module.crm.dal.dataobject.contract.CrmContractProductDO; import cn.iocoder.yudao.module.crm.dal.dataobject.customer.CrmCustomerDO; +import cn.iocoder.yudao.module.crm.dal.dataobject.product.CrmProductDO; import cn.iocoder.yudao.module.crm.service.permission.bo.CrmPermissionTransferReqBO; import cn.iocoder.yudao.module.system.api.user.dto.AdminUserRespDTO; import org.mapstruct.Mapper; @@ -34,7 +38,8 @@ public interface CrmContractConvert { default List convertList(List contractList, Map userMap, List customerList, Map contactMap, - Map businessMap) { + Map businessMap, Map contractProductMap, + List productList) { List respVOList = BeanUtils.toBean(contractList, CrmContractRespVO.class); // 拼接关联字段 Map customerMap = convertMap(customerList, CrmCustomerDO::getId); @@ -46,7 +51,21 @@ public interface CrmContractConvert { findAndThen(contactMap, contract.getContactId(), contact -> contract.setContactName(contact.getName())); findAndThen(businessMap, contract.getBusinessId(), business -> contract.setBusinessName(business.getName())); }); + if (CollUtil.isNotEmpty(respVOList) && respVOList.size() == 1) { + setContractRespVOProductItems(respVOList.get(0), contractProductMap, productList); + } return respVOList; } + default void setContractRespVOProductItems(CrmContractRespVO respVO, Map contractProductMap, + List productList) { + respVO.setProductItems(CollectionUtils.convertList(productList, product -> { + CrmContractRespVO.CrmContractProductItemRespVO productItemRespVO = BeanUtils.toBean(product, CrmContractRespVO.CrmContractProductItemRespVO.class); + findAndThen(contractProductMap, product.getId(), contractProduct -> { + productItemRespVO.setCount(contractProduct.getCount()).setDiscountPercent(contractProduct.getDiscountPercent()); + }); + return productItemRespVO; + })); + } + } diff --git a/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/dal/dataobject/business/CrmBusinessProductDO.java b/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/dal/dataobject/business/CrmBusinessProductDO.java index 77c5ba779..79d6a2a7b 100644 --- a/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/dal/dataobject/business/CrmBusinessProductDO.java +++ b/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/dal/dataobject/business/CrmBusinessProductDO.java @@ -1,9 +1,7 @@ package cn.iocoder.yudao.module.crm.dal.dataobject.business; import cn.iocoder.yudao.framework.mybatis.core.dataobject.BaseDO; -import cn.iocoder.yudao.module.crm.dal.dataobject.contract.CrmContractDO; import cn.iocoder.yudao.module.crm.dal.dataobject.product.CrmProductDO; -import cn.iocoder.yudao.module.crm.enums.DictTypeConstants; import com.baomidou.mybatisplus.annotation.KeySequence; import com.baomidou.mybatisplus.annotation.TableId; import com.baomidou.mybatisplus.annotation.TableName; @@ -41,19 +39,10 @@ public class CrmBusinessProductDO extends BaseDO { * 关联 {@link CrmProductDO#getId()} */ private Long productId; - // TODO 芋艿:需要在看下 CRM - /** - * 合同编号 - * - * 关联 {@link CrmContractDO#getId()} - */ - private Long contractId; - /** * 产品单价 */ private Integer price; - /** * 销售价格, 单位:分 */ @@ -71,11 +60,4 @@ public class CrmBusinessProductDO extends BaseDO { */ private Integer totalPrice; - /** - * 单位 - * - * 字典 {@link DictTypeConstants#CRM_PRODUCT_UNIT} - */ - private Integer unit; - } diff --git a/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/dal/dataobject/contract/CrmContractProductDO.java b/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/dal/dataobject/contract/CrmContractProductDO.java new file mode 100644 index 000000000..f0f506857 --- /dev/null +++ b/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/dal/dataobject/contract/CrmContractProductDO.java @@ -0,0 +1,63 @@ +package cn.iocoder.yudao.module.crm.dal.dataobject.contract; + +import cn.iocoder.yudao.framework.mybatis.core.dataobject.BaseDO; +import cn.iocoder.yudao.module.crm.dal.dataobject.product.CrmProductDO; +import com.baomidou.mybatisplus.annotation.KeySequence; +import com.baomidou.mybatisplus.annotation.TableId; +import com.baomidou.mybatisplus.annotation.TableName; +import lombok.*; + +/** + * 合同产品关联表 DO + * + * @author HUIHUI + */ +@TableName("crm_contract_product") +@KeySequence("crm_contract_product_seq") // 用于 Oracle、PostgreSQL、Kingbase、DB2、H2 数据库的主键自增。如果是 MySQL 等数据库,可不写。 +@Data +@EqualsAndHashCode(callSuper = true) +@ToString(callSuper = true) +@Builder +@NoArgsConstructor +@AllArgsConstructor +public class CrmContractProductDO extends BaseDO { + + /** + * 主键 + */ + @TableId + private Long id; + /** + * 产品编号 + * + * 关联 {@link CrmProductDO#getId()} + */ + private Long productId; + /** + * 合同编号 + * + * 关联 {@link CrmContractDO#getId()} + */ + private Long contractId; + /** + * 产品单价 + */ + private Integer price; + /** + * 销售价格, 单位:分 + */ + private Integer salesPrice; + /** + * 数量 + */ + private Integer count; + /** + * 折扣 + */ + private Integer discountPercent; + /** + * 总计价格(折扣后价格) + */ + private Integer totalPrice; + +} diff --git a/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/dal/dataobject/contract/package-info.java b/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/dal/dataobject/contract/package-info.java deleted file mode 100644 index a981b5dfc..000000000 --- a/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/dal/dataobject/contract/package-info.java +++ /dev/null @@ -1,4 +0,0 @@ -/** - * 合同 - */ -package cn.iocoder.yudao.module.crm.dal.dataobject.contract; diff --git a/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/dal/mysql/business/CrmBusinessProductMapper.java b/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/dal/mysql/business/CrmBusinessProductMapper.java index 1730067fe..35fccdbdf 100644 --- a/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/dal/mysql/business/CrmBusinessProductMapper.java +++ b/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/dal/mysql/business/CrmBusinessProductMapper.java @@ -2,9 +2,12 @@ package cn.iocoder.yudao.module.crm.dal.mysql.business; import cn.iocoder.yudao.framework.mybatis.core.mapper.BaseMapperX; +import cn.iocoder.yudao.framework.mybatis.core.query.LambdaQueryWrapperX; import cn.iocoder.yudao.module.crm.dal.dataobject.business.CrmBusinessProductDO; import org.apache.ibatis.annotations.Mapper; +import java.util.List; + /** * 商机产品 Mapper * @@ -21,4 +24,8 @@ public interface CrmBusinessProductMapper extends BaseMapperX selectListByBusinessId(Long businessId) { + return selectList(new LambdaQueryWrapperX().eq(CrmBusinessProductDO::getBusinessId, businessId)); + } + } diff --git a/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/dal/mysql/contract/CrmContractProductMapper.java b/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/dal/mysql/contract/CrmContractProductMapper.java new file mode 100644 index 000000000..fd6347a9e --- /dev/null +++ b/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/dal/mysql/contract/CrmContractProductMapper.java @@ -0,0 +1,31 @@ +package cn.iocoder.yudao.module.crm.dal.mysql.contract; + + +import cn.iocoder.yudao.framework.mybatis.core.mapper.BaseMapperX; +import cn.iocoder.yudao.framework.mybatis.core.query.LambdaQueryWrapperX; +import cn.iocoder.yudao.module.crm.dal.dataobject.contract.CrmContractProductDO; +import org.apache.ibatis.annotations.Mapper; + +import java.util.List; + +/** + * 合同产品 Mapper + * + * @author HUIHUI + */ +@Mapper +public interface CrmContractProductMapper extends BaseMapperX { + + default void deleteByContractId(Long contractId) { // TODO @lzxhqs:第一个方法,和类之间最好空一行; + delete(CrmContractProductDO::getContractId, contractId); + } + + default CrmContractProductDO selectByContractId(Long contractId) { + return selectOne(CrmContractProductDO::getContractId, contractId); + } + + default List selectListByContractId(Long contractId) { + return selectList(new LambdaQueryWrapperX().eq(CrmContractProductDO::getContractId, contractId)); + } + +} diff --git a/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/dal/mysql/product/CrmProductMapper.java b/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/dal/mysql/product/CrmProductMapper.java index 8a7fa600b..30a07eec2 100644 --- a/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/dal/mysql/product/CrmProductMapper.java +++ b/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/dal/mysql/product/CrmProductMapper.java @@ -2,7 +2,6 @@ package cn.iocoder.yudao.module.crm.dal.mysql.product; import cn.iocoder.yudao.framework.common.pojo.PageResult; import cn.iocoder.yudao.framework.mybatis.core.mapper.BaseMapperX; -import cn.iocoder.yudao.framework.mybatis.core.query.LambdaQueryWrapperX; import cn.iocoder.yudao.framework.mybatis.core.query.MPJLambdaWrapperX; import cn.iocoder.yudao.module.crm.controller.admin.product.vo.product.CrmProductPageReqVO; import cn.iocoder.yudao.module.crm.dal.dataobject.product.CrmProductDO; @@ -10,9 +9,6 @@ import cn.iocoder.yudao.module.crm.enums.common.CrmBizTypeEnum; import cn.iocoder.yudao.module.crm.util.CrmQueryWrapperUtils; import org.apache.ibatis.annotations.Mapper; -import java.util.Collection; -import java.util.List; - /** * CRM 产品 Mapper * @@ -38,9 +34,4 @@ public interface CrmProductMapper extends BaseMapperX { return selectOne(CrmProductDO::getNo, no); } - // TODO @puhui999:selectBatchIds - default List selectListByIds(Collection ids) { - return selectList(new LambdaQueryWrapperX().in(CrmProductDO::getId, ids)); - } - } diff --git a/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/service/business/CrmBusinessProductService.java b/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/service/business/CrmBusinessProductService.java deleted file mode 100644 index a68ac37b9..000000000 --- a/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/service/business/CrmBusinessProductService.java +++ /dev/null @@ -1,57 +0,0 @@ -package cn.iocoder.yudao.module.crm.service.business; - -import cn.iocoder.yudao.module.crm.dal.dataobject.business.CrmBusinessProductDO; - -import java.util.List; - -/** - * 商机产品关联表 Service 接口 - * - * @author lzxhqs - */ -public interface CrmBusinessProductService { - - /** - * 批量新增商机产品关联数据 - * - * @param list 商机产品集合 - */ - void createBusinessProductBatch(List list); - - /** - * 批量更新商机产品表 - * - * @param list 商机产品数据集合 - */ - void updateBusinessProductBatch(List list); - - /** - * 批量删除 - * - * @param list 需要删除的商机产品集合 - */ - void deleteBusinessProductBatch(List list); - - /** - * 根据商机编号,删除商机产品关联数据 - * - * @param businessId 商机id - */ - void deleteBusinessProductByBusinessId(Long businessId); - - /** - * 根据商机编号,获取商机产品关联数据集合 - * - * @param businessId 商机编号 - */ - List getBusinessProductListByBusinessId(Long businessId); - - /** - * 根据合同编号,获得合同关联的商品列表 - * - * @param contractId 合同编号 - * @return 关联的商品列表 - */ - List getBusinessProductListByContractId(Long contractId); - -} diff --git a/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/service/business/CrmBusinessProductServiceImpl.java b/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/service/business/CrmBusinessProductServiceImpl.java deleted file mode 100644 index 0762d4555..000000000 --- a/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/service/business/CrmBusinessProductServiceImpl.java +++ /dev/null @@ -1,55 +0,0 @@ -package cn.iocoder.yudao.module.crm.service.business; - -import cn.iocoder.yudao.framework.common.util.collection.CollectionUtils; -import cn.iocoder.yudao.module.crm.dal.dataobject.business.CrmBusinessProductDO; -import cn.iocoder.yudao.module.crm.dal.mysql.business.CrmBusinessProductMapper; -import jakarta.annotation.Resource; -import org.springframework.stereotype.Service; -import org.springframework.validation.annotation.Validated; - -import java.util.List; - -/** - * 商机产品关联表 Service 实现类 - * - * @author lzxhqs - */ -@Service -@Validated -public class CrmBusinessProductServiceImpl implements CrmBusinessProductService { - - @Resource - private CrmBusinessProductMapper businessProductMapper; - - @Override - public void createBusinessProductBatch(List list) { - businessProductMapper.insertBatch(list); - } - - @Override - public void updateBusinessProductBatch(List list) { - businessProductMapper.updateBatch(list); - } - - // TODO @puhui999:这个方法,可以直接调用 deleteList 方法,然后传递 ids 就好了; - @Override - public void deleteBusinessProductBatch(List list) { - businessProductMapper.deleteBatchIds(CollectionUtils.convertList(list, CrmBusinessProductDO::getId)); - } - - @Override - public void deleteBusinessProductByBusinessId(Long businessId) { - businessProductMapper.deleteByBusinessId(businessId); - } - - @Override - public List getBusinessProductListByContractId(Long contractId) { - return businessProductMapper.selectList(CrmBusinessProductDO::getContractId, contractId); - } - - @Override - public List getBusinessProductListByBusinessId(Long businessId) { - return businessProductMapper.selectList(CrmBusinessProductDO::getBusinessId, businessId); - } - -} diff --git a/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/service/business/CrmBusinessServiceImpl.java b/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/service/business/CrmBusinessServiceImpl.java index df7348cfe..7de0ca424 100644 --- a/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/service/business/CrmBusinessServiceImpl.java +++ b/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/service/business/CrmBusinessServiceImpl.java @@ -5,17 +5,18 @@ import cn.hutool.core.collection.ListUtil; import cn.hutool.core.util.ObjectUtil; import cn.iocoder.yudao.framework.common.pojo.PageResult; import cn.iocoder.yudao.framework.common.util.collection.CollectionUtils; +import cn.iocoder.yudao.framework.common.util.number.MoneyUtils; import cn.iocoder.yudao.framework.common.util.object.BeanUtils; import cn.iocoder.yudao.module.crm.controller.admin.business.vo.business.CrmBusinessPageReqVO; import cn.iocoder.yudao.module.crm.controller.admin.business.vo.business.CrmBusinessSaveReqVO; import cn.iocoder.yudao.module.crm.controller.admin.business.vo.business.CrmBusinessTransferReqVO; -import cn.iocoder.yudao.module.crm.controller.admin.business.vo.product.CrmBusinessProductSaveReqVO; import cn.iocoder.yudao.module.crm.convert.business.CrmBusinessConvert; -import cn.iocoder.yudao.module.crm.convert.businessproduct.CrmBusinessProductConvert; import cn.iocoder.yudao.module.crm.dal.dataobject.business.CrmBusinessDO; import cn.iocoder.yudao.module.crm.dal.dataobject.business.CrmBusinessProductDO; import cn.iocoder.yudao.module.crm.dal.dataobject.contact.CrmContactBusinessDO; +import cn.iocoder.yudao.module.crm.dal.dataobject.product.CrmProductDO; import cn.iocoder.yudao.module.crm.dal.mysql.business.CrmBusinessMapper; +import cn.iocoder.yudao.module.crm.dal.mysql.business.CrmBusinessProductMapper; import cn.iocoder.yudao.module.crm.enums.common.CrmBizTypeEnum; import cn.iocoder.yudao.module.crm.enums.permission.CrmPermissionLevelEnum; import cn.iocoder.yudao.module.crm.framework.permission.core.annotations.CrmPermission; @@ -24,6 +25,7 @@ import cn.iocoder.yudao.module.crm.service.contract.CrmContractService; import cn.iocoder.yudao.module.crm.service.followup.bo.CrmUpdateFollowUpReqBO; import cn.iocoder.yudao.module.crm.service.permission.CrmPermissionService; import cn.iocoder.yudao.module.crm.service.permission.bo.CrmPermissionCreateReqBO; +import cn.iocoder.yudao.module.crm.service.product.CrmProductService; import com.mzt.logapi.context.LogRecordContext; import com.mzt.logapi.service.impl.DiffParseFunction; import com.mzt.logapi.starter.annotation.LogRecord; @@ -35,11 +37,12 @@ import org.springframework.validation.annotation.Validated; import java.util.Collection; import java.util.List; +import java.util.Map; +import java.util.Set; import static cn.iocoder.yudao.framework.common.exception.util.ServiceExceptionUtil.exception; -import static cn.iocoder.yudao.framework.common.util.collection.CollectionUtils.convertSet; -import static cn.iocoder.yudao.module.crm.enums.ErrorCodeConstants.BUSINESS_CONTRACT_EXISTS; -import static cn.iocoder.yudao.module.crm.enums.ErrorCodeConstants.BUSINESS_NOT_EXISTS; +import static cn.iocoder.yudao.framework.common.util.collection.CollectionUtils.*; +import static cn.iocoder.yudao.module.crm.enums.ErrorCodeConstants.*; import static cn.iocoder.yudao.module.crm.enums.LogRecordConstants.*; /** @@ -53,9 +56,9 @@ public class CrmBusinessServiceImpl implements CrmBusinessService { @Resource private CrmBusinessMapper businessMapper; - @Resource - private CrmBusinessProductService businessProductService; + private CrmBusinessProductMapper businessProductMapper; + @Resource @Lazy // 延迟加载,避免循环依赖 private CrmContractService contractService; @@ -63,6 +66,8 @@ public class CrmBusinessServiceImpl implements CrmBusinessService { private CrmPermissionService permissionService; @Resource private CrmContactBusinessService contactBusinessService; + @Resource + private CrmProductService productService; @Override @Transactional(rollbackFor = Exception.class) @@ -71,12 +76,15 @@ public class CrmBusinessServiceImpl implements CrmBusinessService { public Long createBusiness(CrmBusinessSaveReqVO createReqVO, Long userId) { createReqVO.setId(null); // 1. 插入商机 - CrmBusinessDO business = BeanUtils.toBean(createReqVO, CrmBusinessDO.class) - .setOwnerUserId(userId); + CrmBusinessDO business = BeanUtils.toBean(createReqVO, CrmBusinessDO.class).setOwnerUserId(userId); businessMapper.insert(business); - // TODO 商机待定:插入商机与产品的关联表;校验商品存在 - if (CollUtil.isNotEmpty(createReqVO.getProducts())) { - createBusinessProducts(createReqVO.getProducts(), business.getId(), false); + // 1.2 插入商机关联商品 + if (CollUtil.isNotEmpty(createReqVO.getProductItems())) { // 如果有的话 + List productList = convertBusinessProductList(createReqVO, business.getId()); + businessProductMapper.insertBatch(productList); + // 更新合同商品总金额 + businessMapper.updateById(new CrmBusinessDO().setId(business.getId()).setProductPrice( + getSumValue(productList, CrmBusinessProductDO::getTotalPrice, Integer::sum))); } // TODO 商机待定:在联系人的详情页,如果直接【新建商机】,则需要关联下。这里要搞个 CrmContactBusinessDO 表 createContactBusiness(business.getId(), createReqVO.getContactId()); @@ -92,13 +100,6 @@ public class CrmBusinessServiceImpl implements CrmBusinessService { } // TODO @lzxhqs:CrmContactBusinessService 调用这个;这样逻辑才能收敛哈; - /** - * @param businessId 商机id - * @param contactId 联系人id - * @throws - * @description 联系人与商机的关联 - * @author lzxhqs - */ private void createContactBusiness(Long businessId, Long contactId) { CrmContactBusinessDO contactBusiness = new CrmContactBusinessDO(); contactBusiness.setBusinessId(businessId); @@ -106,37 +107,6 @@ public class CrmBusinessServiceImpl implements CrmBusinessService { contactBusinessService.insert(contactBusiness); } - // TODO @lzxhqs:这个方法注释格式不对;删除@description,然后把 插入商机产品关联表 作为方法注释; - /** - * 插入商机产品关联表 - * - * @param products 产品集合 - * @param businessId 商机id - * @param updateFlag 更新标识 true 代表更新 - * @author lzxhqs - */ - private void createBusinessProducts(List products, Long businessId, Boolean updateFlag) { - List list = CollectionUtils.convertList(products, product -> - CrmBusinessProductConvert.INSTANCE.convert(product).setBusinessId(businessId)); - if (Boolean.TRUE.equals(updateFlag)) { -// 根据商机 id从商机产品关联表中获取已存在的数据集合 - List oldProducts = businessProductService.getBusinessProductListByBusinessId(businessId); - List> diffList = CollectionUtils.diffList(oldProducts, list, (oldValue, newValue) -> - ObjectUtil.equal(oldValue.getProductId(), newValue.getProductId())); - if (CollUtil.isNotEmpty(diffList.getFirst())) { - businessProductService.createBusinessProductBatch(diffList.getFirst()); - } - if (CollUtil.isNotEmpty(diffList.get(1))) { - businessProductService.updateBusinessProductBatch(diffList.get(1)); - } - if (CollUtil.isNotEmpty(diffList.get(2))) { - businessProductService.deleteBusinessProductBatch(diffList.get(2)); - } - } else { - businessProductService.createBusinessProductBatch(list); - } - } - @Override @Transactional(rollbackFor = Exception.class) @LogRecord(type = CRM_BUSINESS_TYPE, subType = CRM_BUSINESS_UPDATE_SUB_TYPE, bizNo = "{{#updateReqVO.id}}", @@ -146,16 +116,12 @@ public class CrmBusinessServiceImpl implements CrmBusinessService { // 1. 校验存在 CrmBusinessDO oldBusiness = validateBusinessExists(updateReqVO.getId()); - // 2. 更新商机 + // 2.1 更新商机 CrmBusinessDO updateObj = BeanUtils.toBean(updateReqVO, CrmBusinessDO.class); businessMapper.updateById(updateObj); - // TODO 商机待定:插入商机与产品的关联表;校验商品存在 - // TODO @lzxhqs:createBusinessProducts 可以抽成两个方法,一个新增;一个修改,修改需要把 businessProductService.deleteByBusinessId(updateReqVO.getId()); 一起处理进去; - if (CollUtil.isNotEmpty(updateReqVO.getProducts())) { - createBusinessProducts(updateReqVO.getProducts(), updateReqVO.getId(), true); - } else { - businessProductService.deleteBusinessProductByBusinessId(updateReqVO.getId()); - } + // 2.2 更新商机关联商品 + List productList = convertBusinessProductList(updateReqVO, updateObj.getId()); + updateBusinessProduct(productList, updateObj.getId()); // TODO @商机待定:如果状态发生变化,插入商机状态变更记录表 // 3. 记录操作日志上下文 @@ -188,6 +154,43 @@ public class CrmBusinessServiceImpl implements CrmBusinessService { LogRecordContext.putVariable("businessName", business.getName()); } + private void updateBusinessProduct(List newProductList, Long businessId) { + List oldProducts = businessProductMapper.selectListByBusinessId(businessId); + List> diffList = CollectionUtils.diffList(oldProducts, newProductList, (oldValue, newValue) -> { + boolean condition = ObjectUtil.equal(oldValue.getProductId(), newValue.getProductId()); + if (condition) { + newValue.setId(oldValue.getId()); // 更新需要原始编号 + } + return condition; + }); + if (CollUtil.isNotEmpty(diffList.get(0))) { + businessProductMapper.insertBatch(diffList.get(0)); + } + if (CollUtil.isNotEmpty(diffList.get(1))) { + businessProductMapper.updateBatch(diffList.get(1)); + } + if (CollUtil.isNotEmpty(diffList.get(2))) { + businessProductMapper.deleteBatchIds(convertSet(diffList.get(2), CrmBusinessProductDO::getId)); + } + } + + private List convertBusinessProductList(CrmBusinessSaveReqVO reqVO, Long businessId) { + // 校验商品存在 + Set productIds = convertSet(reqVO.getProductItems(), CrmBusinessSaveReqVO.CrmBusinessProductItem::getId); + List productList = productService.getProductList(productIds); + if (CollUtil.isEmpty(productIds) || productList.size() != productIds.size()) { + throw exception(PRODUCT_NOT_EXISTS); + } + Map productMap = convertMap(productList, CrmProductDO::getId); + return convertList(reqVO.getProductItems(), productItem -> { + CrmProductDO product = productMap.get(productItem.getId()); + return BeanUtils.toBean(product, CrmBusinessProductDO.class) + .setId(null).setProductId(productItem.getId()).setBusinessId(businessId) + .setCount(productItem.getCount()).setDiscountPercent(productItem.getDiscountPercent()) + .setTotalPrice(MoneyUtils.calculator(product.getPrice(), productItem.getCount(), productItem.getDiscountPercent())); + }); + } + /** * 删除校验合同是关联合同 * diff --git a/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/service/contract/CrmContractService.java b/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/service/contract/CrmContractService.java index 3e79b73ed..0bd527ae0 100644 --- a/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/service/contract/CrmContractService.java +++ b/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/service/contract/CrmContractService.java @@ -6,6 +6,7 @@ import cn.iocoder.yudao.module.crm.controller.admin.contract.vo.CrmContractPageR import cn.iocoder.yudao.module.crm.controller.admin.contract.vo.CrmContractSaveReqVO; import cn.iocoder.yudao.module.crm.controller.admin.contract.vo.CrmContractTransferReqVO; import cn.iocoder.yudao.module.crm.dal.dataobject.contract.CrmContractDO; +import cn.iocoder.yudao.module.crm.dal.dataobject.contract.CrmContractProductDO; import cn.iocoder.yudao.module.crm.dal.dataobject.customer.CrmCustomerDO; import cn.iocoder.yudao.module.crm.service.followup.bo.CrmUpdateFollowUpReqBO; import jakarta.validation.Valid; @@ -134,4 +135,12 @@ public interface CrmContractService { */ Long getContractCountByBusinessId(Long businessId); + /** + * 获取合同商品列表 + * + * @param contactId 合同编号 + * @return 合同商品列表 + */ + List getContractProductListByContractId(Long contactId); + } diff --git a/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/service/contract/CrmContractServiceImpl.java b/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/service/contract/CrmContractServiceImpl.java index 4af609edd..0cf9065e4 100644 --- a/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/service/contract/CrmContractServiceImpl.java +++ b/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/service/contract/CrmContractServiceImpl.java @@ -15,15 +15,15 @@ import cn.iocoder.yudao.module.crm.controller.admin.contract.vo.CrmContractPageR import cn.iocoder.yudao.module.crm.controller.admin.contract.vo.CrmContractSaveReqVO; import cn.iocoder.yudao.module.crm.controller.admin.contract.vo.CrmContractTransferReqVO; import cn.iocoder.yudao.module.crm.convert.contract.CrmContractConvert; -import cn.iocoder.yudao.module.crm.dal.dataobject.business.CrmBusinessProductDO; import cn.iocoder.yudao.module.crm.dal.dataobject.contract.CrmContractDO; +import cn.iocoder.yudao.module.crm.dal.dataobject.contract.CrmContractProductDO; import cn.iocoder.yudao.module.crm.dal.dataobject.product.CrmProductDO; import cn.iocoder.yudao.module.crm.dal.mysql.contract.CrmContractMapper; +import cn.iocoder.yudao.module.crm.dal.mysql.contract.CrmContractProductMapper; import cn.iocoder.yudao.module.crm.enums.common.CrmAuditStatusEnum; import cn.iocoder.yudao.module.crm.enums.common.CrmBizTypeEnum; import cn.iocoder.yudao.module.crm.enums.permission.CrmPermissionLevelEnum; import cn.iocoder.yudao.module.crm.framework.permission.core.annotations.CrmPermission; -import cn.iocoder.yudao.module.crm.service.business.CrmBusinessProductService; import cn.iocoder.yudao.module.crm.service.business.CrmBusinessService; import cn.iocoder.yudao.module.crm.service.customer.CrmCustomerService; import cn.iocoder.yudao.module.crm.service.followup.bo.CrmUpdateFollowUpReqBO; @@ -63,12 +63,12 @@ public class CrmContractServiceImpl implements CrmContractService { @Resource private CrmContractMapper contractMapper; + @Resource + private CrmContractProductMapper contractProductMapper; @Resource private CrmPermissionService crmPermissionService; @Resource - private CrmBusinessProductService businessProductService; - @Resource private CrmProductService productService; @Resource private CrmCustomerService customerService; @@ -89,11 +89,14 @@ public class CrmContractServiceImpl implements CrmContractService { // 1.1 插入合同 CrmContractDO contract = BeanUtils.toBean(createReqVO, CrmContractDO.class).setId(null); contractMapper.insert(contract); - // 1.2 插入商机关联商品 + // 1.2 插入合同关联商品 if (CollUtil.isNotEmpty(createReqVO.getProductItems())) { // 如果有的话 - List businessProduct = convertBusinessProductList(createReqVO, contract.getId()); - businessProductService.createBusinessProductBatch(businessProduct); + List productList = convertContractProductList(createReqVO, contract.getId()); + contractProductMapper.insertBatch(productList); // 更新合同商品总金额 + contractMapper.updateById(new CrmContractDO().setId(contract.getId()).setProductPrice( + getSumValue(productList, CrmContractProductDO::getTotalPrice, Integer::sum))); + // TODO @puhui999: 如果存在合同关联了商机则更新商机商品关联 } // 2. 创建数据权限 @@ -137,29 +140,29 @@ public class CrmContractServiceImpl implements CrmContractService { if (CollUtil.isEmpty(updateReqVO.getProductItems())) { return; } - List newProductList = convertBusinessProductList(updateReqVO, contractId); - List oldProductList = businessProductService.getBusinessProductListByContractId(contractId); - List> diffList = diffList(oldProductList, newProductList, (oldObj, newObj) -> { - if (ObjUtil.notEqual(oldObj.getProductId(), newObj.getProductId())) { - return false; + List newProductList = convertContractProductList(updateReqVO, contractId); + List oldProductList = contractProductMapper.selectListByContractId(contractId); + List> diffList = diffList(oldProductList, newProductList, (oldObj, newObj) -> { + boolean equal = ObjUtil.equal(oldObj.getProductId(), newObj.getProductId()); + if (equal) { + newObj.setId(oldObj.getId()); // 设置一下老的编号更新时需要使用 } - newObj.setId(oldObj.getId()); // 设置一下老的编号更新时需要使用 - return true; + return equal; }); - if (CollUtil.isNotEmpty(diffList.getFirst())) { - businessProductService.createBusinessProductBatch(diffList.getFirst()); + if (CollUtil.isNotEmpty(diffList.get(0))) { + contractProductMapper.insertBatch(diffList.get(0)); } if (CollUtil.isNotEmpty(diffList.get(1))) { - businessProductService.updateBusinessProductBatch(diffList.get(1)); + contractProductMapper.updateBatch(diffList.get(1)); } if (CollUtil.isNotEmpty(diffList.get(2))) { - businessProductService.deleteBusinessProductBatch(diffList.get(2)); + contractProductMapper.deleteBatchIds(convertList(diffList.get(2), CrmContractProductDO::getId)); } } // TODO @合同待定:缺一个取消合同的接口;只有草稿、审批中可以取消;CrmAuditStatusEnum - private List convertBusinessProductList(CrmContractSaveReqVO reqVO, Long contractId) { + private List convertContractProductList(CrmContractSaveReqVO reqVO, Long contractId) { // 校验商品存在 Set productIds = convertSet(reqVO.getProductItems(), CrmContractSaveReqVO.CrmContractProductItem::getId); List productList = productService.getProductList(productIds); @@ -169,8 +172,8 @@ public class CrmContractServiceImpl implements CrmContractService { Map productMap = convertMap(productList, CrmProductDO::getId); return convertList(reqVO.getProductItems(), productItem -> { CrmProductDO product = productMap.get(productItem.getId()); - return BeanUtils.toBean(product, CrmBusinessProductDO.class) - .setId(null).setBusinessId(reqVO.getBusinessId()).setProductId(productItem.getId()).setContractId(contractId) + return BeanUtils.toBean(product, CrmContractProductDO.class) + .setId(null).setProductId(productItem.getId()).setContractId(contractId) .setCount(productItem.getCount()).setDiscountPercent(productItem.getDiscountPercent()) .setTotalPrice(MoneyUtils.calculator(product.getPrice(), productItem.getCount(), productItem.getDiscountPercent())); }); @@ -313,5 +316,11 @@ public class CrmContractServiceImpl implements CrmContractService { public Long getContractCountByBusinessId(Long businessId) { return contractMapper.selectCountByBusinessId(businessId); } + + @Override + public List getContractProductListByContractId(Long contactId) { + return contractProductMapper.selectListByContractId(contactId); + } + // TODO @合同待定:需要新增一个 ContractConfigDO 表,合同配置,重点是到期提醒; } diff --git a/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/service/product/CrmProductServiceImpl.java b/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/service/product/CrmProductServiceImpl.java index 55f8a3593..95205524e 100644 --- a/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/service/product/CrmProductServiceImpl.java +++ b/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/service/product/CrmProductServiceImpl.java @@ -160,7 +160,7 @@ public class CrmProductServiceImpl implements CrmProductService { if (CollUtil.isEmpty(ids)) { return Collections.emptyList(); } - return productMapper.selectListByIds(ids); + return productMapper.selectBatchIds(ids); } } diff --git a/yudao-module-erp/yudao-module-erp-biz/src/test/java/cn/iocoder/yudao/module/erp/service/product/ErpProductUnitServiceImplTest.java b/yudao-module-erp/yudao-module-erp-biz/src/test/java/cn/iocoder/yudao/module/erp/service/product/ErpProductUnitServiceImplTest.java index c4023df0e..669d88569 100644 --- a/yudao-module-erp/yudao-module-erp-biz/src/test/java/cn/iocoder/yudao/module/erp/service/product/ErpProductUnitServiceImplTest.java +++ b/yudao-module-erp/yudao-module-erp-biz/src/test/java/cn/iocoder/yudao/module/erp/service/product/ErpProductUnitServiceImplTest.java @@ -1,24 +1,23 @@ package cn.iocoder.yudao.module.erp.service.product; +import cn.iocoder.yudao.framework.common.pojo.PageResult; +import cn.iocoder.yudao.framework.test.core.ut.BaseDbUnitTest; import cn.iocoder.yudao.module.erp.controller.admin.product.vo.unit.ErpProductUnitPageReqVO; import cn.iocoder.yudao.module.erp.controller.admin.product.vo.unit.ErpProductUnitSaveReqVO; -import org.junit.jupiter.api.Disabled; -import org.junit.jupiter.api.Test; - -import jakarta.annotation.Resource; - -import cn.iocoder.yudao.framework.test.core.ut.BaseDbUnitTest; - import cn.iocoder.yudao.module.erp.dal.dataobject.product.ErpProductUnitDO; import cn.iocoder.yudao.module.erp.dal.mysql.product.ErpProductUnitMapper; -import cn.iocoder.yudao.framework.common.pojo.PageResult; - +import jakarta.annotation.Resource; +import org.junit.jupiter.api.Disabled; +import org.junit.jupiter.api.Test; import org.springframework.context.annotation.Import; -import static cn.iocoder.yudao.framework.test.core.util.AssertUtils.*; -import static cn.iocoder.yudao.framework.test.core.util.RandomUtils.*; -import static cn.iocoder.yudao.framework.common.util.date.LocalDateTimeUtils.*; -import static cn.iocoder.yudao.framework.common.util.object.ObjectUtils.*; +import static cn.iocoder.yudao.framework.common.util.date.LocalDateTimeUtils.buildBetweenTime; +import static cn.iocoder.yudao.framework.common.util.object.ObjectUtils.cloneIgnoreId; +import static cn.iocoder.yudao.framework.test.core.util.AssertUtils.assertPojoEquals; +import static cn.iocoder.yudao.framework.test.core.util.AssertUtils.assertServiceException; +import static cn.iocoder.yudao.framework.test.core.util.RandomUtils.randomLongId; +import static cn.iocoder.yudao.framework.test.core.util.RandomUtils.randomPojo; +import static cn.iocoder.yudao.module.erp.ErrorCodeConstants.PRODUCT_UNIT_NOT_EXISTS; import static org.junit.jupiter.api.Assertions.*; /** diff --git a/yudao-module-erp/yudao-module-erp-biz/src/test/java/cn/iocoder/yudao/module/erp/service/product/ProductServiceImplTest.java b/yudao-module-erp/yudao-module-erp-biz/src/test/java/cn/iocoder/yudao/module/erp/service/product/ProductServiceImplTest.java index 03298bcc3..89a7020ef 100644 --- a/yudao-module-erp/yudao-module-erp-biz/src/test/java/cn/iocoder/yudao/module/erp/service/product/ProductServiceImplTest.java +++ b/yudao-module-erp/yudao-module-erp-biz/src/test/java/cn/iocoder/yudao/module/erp/service/product/ProductServiceImplTest.java @@ -1,24 +1,23 @@ package cn.iocoder.yudao.module.erp.service.product; +import cn.iocoder.yudao.framework.common.pojo.PageResult; +import cn.iocoder.yudao.framework.test.core.ut.BaseDbUnitTest; import cn.iocoder.yudao.module.erp.controller.admin.product.vo.product.ProductPageReqVO; import cn.iocoder.yudao.module.erp.controller.admin.product.vo.product.ProductSaveReqVO; -import org.junit.jupiter.api.Disabled; -import org.junit.jupiter.api.Test; - -import jakarta.annotation.Resource; - -import cn.iocoder.yudao.framework.test.core.ut.BaseDbUnitTest; - import cn.iocoder.yudao.module.erp.dal.dataobject.product.ErpProductDO; import cn.iocoder.yudao.module.erp.dal.mysql.product.ErpProductMapper; -import cn.iocoder.yudao.framework.common.pojo.PageResult; - +import jakarta.annotation.Resource; +import org.junit.jupiter.api.Disabled; +import org.junit.jupiter.api.Test; import org.springframework.context.annotation.Import; -import static cn.iocoder.yudao.framework.test.core.util.AssertUtils.*; -import static cn.iocoder.yudao.framework.test.core.util.RandomUtils.*; -import static cn.iocoder.yudao.framework.common.util.date.LocalDateTimeUtils.*; -import static cn.iocoder.yudao.framework.common.util.object.ObjectUtils.*; +import static cn.iocoder.yudao.framework.common.util.date.LocalDateTimeUtils.buildBetweenTime; +import static cn.iocoder.yudao.framework.common.util.object.ObjectUtils.cloneIgnoreId; +import static cn.iocoder.yudao.framework.test.core.util.AssertUtils.assertPojoEquals; +import static cn.iocoder.yudao.framework.test.core.util.AssertUtils.assertServiceException; +import static cn.iocoder.yudao.framework.test.core.util.RandomUtils.randomLongId; +import static cn.iocoder.yudao.framework.test.core.util.RandomUtils.randomPojo; +import static cn.iocoder.yudao.module.erp.ErrorCodeConstants.PRODUCT_NOT_EXISTS; import static org.junit.jupiter.api.Assertions.*; /** From a36ae0c469f9ab634c7fcc80e370fd3194d1a98c Mon Sep 17 00:00:00 2001 From: YunaiV Date: Mon, 5 Feb 2024 00:15:51 +0800 Subject: [PATCH 072/119] =?UTF-8?q?=E2=9C=A8=20ERP=EF=BC=9A=E5=AE=8C?= =?UTF-8?q?=E6=88=90=20product=20=E4=BF=A1=E6=81=AF=E3=80=81=E5=88=86?= =?UTF-8?q?=E7=B1=BB=E3=80=81=E5=8D=95=E4=BD=8D=E7=9A=84=E5=AE=9E=E7=8E=B0?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../yudao/module/erp/ErrorCodeConstants.java | 3 + .../product/ErpProductCategoryController.java | 29 +++++--- .../admin/product/ErpProductController.java | 35 ++++++++-- .../product/ErpProductUnitController.java | 9 +++ .../product/vo/product/ProductRespVO.java | 10 ++- .../product/vo/product/ProductSaveReqVO.java | 9 +-- .../vo/unit/ErpProductUnitPageReqVO.java | 9 --- .../product/vo/unit/ErpProductUnitRespVO.java | 5 +- .../vo/unit/ErpProductUnitSaveReqVO.java | 3 + .../dal/dataobject/product/ErpProductDO.java | 4 +- .../dal/mysql/product/ErpProductMapper.java | 8 +++ .../mysql/product/ErpProductUnitMapper.java | 11 ++- .../product/ErpProductCategoryService.java | 26 ++++++- .../ErpProductCategoryServiceImpl.java | 21 +++++- .../service/product/ErpProductService.java | 16 +++++ .../product/ErpProductServiceImpl.java | 10 +++ .../product/ErpProductUnitService.java | 36 +++++++++- .../product/ErpProductUnitServiceImpl.java | 69 +++++++++++++++---- 18 files changed, 257 insertions(+), 56 deletions(-) diff --git a/yudao-module-erp/yudao-module-erp-api/src/main/java/cn/iocoder/yudao/module/erp/ErrorCodeConstants.java b/yudao-module-erp/yudao-module-erp-api/src/main/java/cn/iocoder/yudao/module/erp/ErrorCodeConstants.java index 9363bab11..db3a3a37d 100644 --- a/yudao-module-erp/yudao-module-erp-api/src/main/java/cn/iocoder/yudao/module/erp/ErrorCodeConstants.java +++ b/yudao-module-erp/yudao-module-erp-api/src/main/java/cn/iocoder/yudao/module/erp/ErrorCodeConstants.java @@ -19,8 +19,11 @@ public interface ErrorCodeConstants { ErrorCode PRODUCT_CATEGORY_PARENT_ERROR = new ErrorCode(1_030_501_003, "不能设置自己为父产品分类"); ErrorCode PRODUCT_CATEGORY_NAME_DUPLICATE = new ErrorCode(1_030_501_004, "已经存在该分类名称的产品分类"); ErrorCode PRODUCT_CATEGORY_PARENT_IS_CHILD = new ErrorCode(1_030_501_005, "不能设置自己的子分类为父分类"); + ErrorCode PRODUCT_CATEGORY_EXITS_PRODUCT = new ErrorCode(1_030_502_002, "存在产品使用该分类,无法删除"); // ========== ERP 产品单位 1-030-502-000 ========== ErrorCode PRODUCT_UNIT_NOT_EXISTS = new ErrorCode(1_030_502_000, "产品单位不存在"); + ErrorCode PRODUCT_UNIT_NAME_DUPLICATE = new ErrorCode(1_030_502_001, "已存在该名字的产品单位"); + ErrorCode PRODUCT_UNIT_EXITS_PRODUCT = new ErrorCode(1_030_502_002, "存在产品使用该单位,无法删除"); } diff --git a/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/controller/admin/product/ErpProductCategoryController.java b/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/controller/admin/product/ErpProductCategoryController.java index f542d6983..85f51c1c6 100644 --- a/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/controller/admin/product/ErpProductCategoryController.java +++ b/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/controller/admin/product/ErpProductCategoryController.java @@ -1,5 +1,6 @@ package cn.iocoder.yudao.module.erp.controller.admin.product; +import cn.iocoder.yudao.framework.common.enums.CommonStatusEnum; import cn.iocoder.yudao.framework.common.pojo.CommonResult; import cn.iocoder.yudao.framework.common.util.object.BeanUtils; import cn.iocoder.yudao.framework.excel.core.util.ExcelUtils; @@ -23,6 +24,7 @@ import java.io.IOException; import java.util.List; 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.operatelog.core.enums.OperateTypeEnum.EXPORT; @Tag(name = "管理后台 - ERP 产品分类") @@ -35,14 +37,14 @@ public class ErpProductCategoryController { private ErpProductCategoryService productCategoryService; @PostMapping("/create") - @Operation(summary = "创建ERP 产品分类") + @Operation(summary = "创建产品分类") @PreAuthorize("@ss.hasPermission('erp:product-category:create')") public CommonResult createProductCategory(@Valid @RequestBody ErpProductCategorySaveReqVO createReqVO) { return success(productCategoryService.createProductCategory(createReqVO)); } @PutMapping("/update") - @Operation(summary = "更新ERP 产品分类") + @Operation(summary = "更新产品分类") @PreAuthorize("@ss.hasPermission('erp:product-category:update')") public CommonResult updateProductCategory(@Valid @RequestBody ErpProductCategorySaveReqVO updateReqVO) { productCategoryService.updateProductCategory(updateReqVO); @@ -50,7 +52,7 @@ public class ErpProductCategoryController { } @DeleteMapping("/delete") - @Operation(summary = "删除ERP 产品分类") + @Operation(summary = "删除产品分类") @Parameter(name = "id", description = "编号", required = true) @PreAuthorize("@ss.hasPermission('erp:product-category:delete')") public CommonResult deleteProductCategory(@RequestParam("id") Long id) { @@ -59,31 +61,40 @@ public class ErpProductCategoryController { } @GetMapping("/get") - @Operation(summary = "获得ERP 产品分类") + @Operation(summary = "获得产品分类") @Parameter(name = "id", description = "编号", required = true, example = "1024") @PreAuthorize("@ss.hasPermission('erp:product-category:query')") public CommonResult getProductCategory(@RequestParam("id") Long id) { - ErpProductCategoryDO productCategory = productCategoryService.getProductCategory(id); - return success(BeanUtils.toBean(productCategory, ErpProductCategoryRespVO.class)); + ErpProductCategoryDO category = productCategoryService.getProductCategory(id); + return success(BeanUtils.toBean(category, ErpProductCategoryRespVO.class)); } @GetMapping("/list") - @Operation(summary = "获得ERP 产品分类列表") + @Operation(summary = "获得产品分类列表") @PreAuthorize("@ss.hasPermission('erp:product-category:query')") public CommonResult> getProductCategoryList(@Valid ErpProductCategoryListReqVO listReqVO) { List list = productCategoryService.getProductCategoryList(listReqVO); return success(BeanUtils.toBean(list, ErpProductCategoryRespVO.class)); } + @GetMapping("/simple-list") + @Operation(summary = "获得产品分类精简列表", description = "只包含被开启的分类,主要用于前端的下拉选项") + public CommonResult> getProductCategorySimpleList() { + List list = productCategoryService.getProductCategoryList( + new ErpProductCategoryListReqVO().setStatus(CommonStatusEnum.ENABLE.getStatus())); + return success(convertList(list, category -> new ErpProductCategoryRespVO() + .setId(category.getId()).setName(category.getName()).setParentId(category.getParentId()))); + } + @GetMapping("/export-excel") - @Operation(summary = "导出ERP 产品分类 Excel") + @Operation(summary = "导出产品分类 Excel") @PreAuthorize("@ss.hasPermission('erp:product-category:export')") @OperateLog(type = EXPORT) public void exportProductCategoryExcel(@Valid ErpProductCategoryListReqVO listReqVO, HttpServletResponse response) throws IOException { List list = productCategoryService.getProductCategoryList(listReqVO); // 导出 Excel - ExcelUtils.write(response, "ERP 产品分类.xls", "数据", ErpProductCategoryRespVO.class, + ExcelUtils.write(response, "产品分类.xls", "数据", ErpProductCategoryRespVO.class, BeanUtils.toBean(list, ErpProductCategoryRespVO.class)); } diff --git a/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/controller/admin/product/ErpProductController.java b/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/controller/admin/product/ErpProductController.java index 098eb8679..30135a6fe 100644 --- a/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/controller/admin/product/ErpProductController.java +++ b/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/controller/admin/product/ErpProductController.java @@ -1,16 +1,22 @@ package cn.iocoder.yudao.module.erp.controller.admin.product; +import cn.hutool.core.collection.CollUtil; import cn.iocoder.yudao.framework.common.pojo.CommonResult; import cn.iocoder.yudao.framework.common.pojo.PageParam; import cn.iocoder.yudao.framework.common.pojo.PageResult; +import cn.iocoder.yudao.framework.common.util.collection.MapUtils; import cn.iocoder.yudao.framework.common.util.object.BeanUtils; import cn.iocoder.yudao.framework.excel.core.util.ExcelUtils; import cn.iocoder.yudao.framework.operatelog.core.annotations.OperateLog; import cn.iocoder.yudao.module.erp.controller.admin.product.vo.product.ProductPageReqVO; import cn.iocoder.yudao.module.erp.controller.admin.product.vo.product.ProductRespVO; import cn.iocoder.yudao.module.erp.controller.admin.product.vo.product.ProductSaveReqVO; +import cn.iocoder.yudao.module.erp.dal.dataobject.product.ErpProductCategoryDO; import cn.iocoder.yudao.module.erp.dal.dataobject.product.ErpProductDO; +import cn.iocoder.yudao.module.erp.dal.dataobject.product.ErpProductUnitDO; +import cn.iocoder.yudao.module.erp.service.product.ErpProductCategoryService; import cn.iocoder.yudao.module.erp.service.product.ErpProductService; +import cn.iocoder.yudao.module.erp.service.product.ErpProductUnitService; import io.swagger.v3.oas.annotations.Operation; import io.swagger.v3.oas.annotations.Parameter; import io.swagger.v3.oas.annotations.tags.Tag; @@ -22,9 +28,10 @@ import org.springframework.validation.annotation.Validated; import org.springframework.web.bind.annotation.*; import java.io.IOException; -import java.util.List; +import java.util.Map; import static cn.iocoder.yudao.framework.common.pojo.CommonResult.success; +import static cn.iocoder.yudao.framework.common.util.collection.CollectionUtils.convertSet; import static cn.iocoder.yudao.framework.operatelog.core.enums.OperateTypeEnum.EXPORT; @Tag(name = "管理后台 - ERP 产品") @@ -35,6 +42,10 @@ public class ErpProductController { @Resource private ErpProductService productService; + @Resource + private ErpProductCategoryService productCategoryService; + @Resource + private ErpProductUnitService productUnitService; @PostMapping("/create") @Operation(summary = "创建产品") @@ -74,7 +85,7 @@ public class ErpProductController { @PreAuthorize("@ss.hasPermission('erp:product:query')") public CommonResult> getProductPage(@Valid ProductPageReqVO pageReqVO) { PageResult pageResult = productService.getProductPage(pageReqVO); - return success(BeanUtils.toBean(pageResult, ProductRespVO.class)); + return success(buildProductDetailPage(pageResult)); } @GetMapping("/export-excel") @@ -84,10 +95,26 @@ public class ErpProductController { public void exportProductExcel(@Valid ProductPageReqVO pageReqVO, HttpServletResponse response) throws IOException { pageReqVO.setPageSize(PageParam.PAGE_SIZE_NONE); - List list = productService.getProductPage(pageReqVO).getList(); + PageResult pageResult = productService.getProductPage(pageReqVO); // 导出 Excel ExcelUtils.write(response, "产品.xls", "数据", ProductRespVO.class, - BeanUtils.toBean(list, ProductRespVO.class)); + buildProductDetailPage(pageResult).getList()); + } + + private PageResult buildProductDetailPage(PageResult pageResult) { + if (CollUtil.isEmpty(pageResult.getList())) { + return PageResult.empty(pageResult.getTotal()); + } + Map categoryMap = productCategoryService.getProductCategoryMap( + convertSet(pageResult.getList(), ErpProductDO::getCategoryId)); + Map unitMap = productUnitService.getProductUnitMap( + convertSet(pageResult.getList(), ErpProductDO::getUnitId)); + return BeanUtils.toBean(pageResult, ProductRespVO.class, product -> { + MapUtils.findAndThen(categoryMap, product.getCategoryId(), + category -> product.setCategoryName(category.getName())); + MapUtils.findAndThen(unitMap, product.getUnitId(), + unit -> product.setUnitName(unit.getName())); + }); } } \ No newline at end of file diff --git a/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/controller/admin/product/ErpProductUnitController.java b/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/controller/admin/product/ErpProductUnitController.java index 34d97ff2e..0be3db01c 100644 --- a/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/controller/admin/product/ErpProductUnitController.java +++ b/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/controller/admin/product/ErpProductUnitController.java @@ -1,5 +1,6 @@ package cn.iocoder.yudao.module.erp.controller.admin.product; +import cn.iocoder.yudao.framework.common.enums.CommonStatusEnum; import cn.iocoder.yudao.framework.common.pojo.CommonResult; import cn.iocoder.yudao.framework.common.pojo.PageParam; import cn.iocoder.yudao.framework.common.pojo.PageResult; @@ -25,6 +26,7 @@ import java.io.IOException; import java.util.List; 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.operatelog.core.enums.OperateTypeEnum.EXPORT; @Tag(name = "管理后台 - ERP 产品单位") @@ -77,6 +79,13 @@ public class ErpProductUnitController { return success(BeanUtils.toBean(pageResult, ErpProductUnitRespVO.class)); } + @GetMapping("/simple-list") + @Operation(summary = "获得产品单位精简列表", description = "只包含被开启的单位,主要用于前端的下拉选项") + public CommonResult> getProductUnitSimpleList() { + List list = productUnitService.getProductUnitListByStatus(CommonStatusEnum.ENABLE.getStatus()); + return success(convertList(list, unit -> new ErpProductUnitRespVO().setId(unit.getId()).setName(unit.getName()))); + } + @GetMapping("/export-excel") @Operation(summary = "导出产品单位 Excel") @PreAuthorize("@ss.hasPermission('erp:product-unit:export')") diff --git a/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/controller/admin/product/vo/product/ProductRespVO.java b/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/controller/admin/product/vo/product/ProductRespVO.java index d96cbad98..f6f255c09 100644 --- a/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/controller/admin/product/vo/product/ProductRespVO.java +++ b/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/controller/admin/product/vo/product/ProductRespVO.java @@ -26,12 +26,16 @@ public class ProductRespVO { private String barCode; @Schema(description = "产品分类编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "11161") - @ExcelProperty("产品分类编号") private Long categoryId; + @Schema(description = "产品分类", requiredMode = Schema.RequiredMode.REQUIRED, example = "水果") + @ExcelProperty("产品分类") + private String categoryName; @Schema(description = "单位编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "8869") - @ExcelProperty("单位编号") - private Integer unitId; + private Long unitId; + @Schema(description = "单位", requiredMode = Schema.RequiredMode.REQUIRED, example = "个") + @ExcelProperty("单位") + private String unitName; @Schema(description = "产品状态", requiredMode = Schema.RequiredMode.REQUIRED, example = "2") @ExcelProperty("产品状态") diff --git a/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/controller/admin/product/vo/product/ProductSaveReqVO.java b/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/controller/admin/product/vo/product/ProductSaveReqVO.java index e881bf46b..6cf806e3e 100644 --- a/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/controller/admin/product/vo/product/ProductSaveReqVO.java +++ b/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/controller/admin/product/vo/product/ProductSaveReqVO.java @@ -1,9 +1,10 @@ package cn.iocoder.yudao.module.erp.controller.admin.product.vo.product; import io.swagger.v3.oas.annotations.media.Schema; -import lombok.*; -import java.util.*; -import jakarta.validation.constraints.*; +import jakarta.validation.constraints.NotEmpty; +import jakarta.validation.constraints.NotNull; +import lombok.Data; + import java.math.BigDecimal; @Schema(description = "管理后台 - ERP 产品新增/修改 Request VO") @@ -27,7 +28,7 @@ public class ProductSaveReqVO { @Schema(description = "单位编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "8869") @NotNull(message = "单位编号不能为空") - private Integer unitId; + private Long unitId; @Schema(description = "产品状态", requiredMode = Schema.RequiredMode.REQUIRED, example = "2") @NotNull(message = "产品状态不能为空") diff --git a/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/controller/admin/product/vo/unit/ErpProductUnitPageReqVO.java b/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/controller/admin/product/vo/unit/ErpProductUnitPageReqVO.java index cef41c7ec..87119c126 100644 --- a/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/controller/admin/product/vo/unit/ErpProductUnitPageReqVO.java +++ b/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/controller/admin/product/vo/unit/ErpProductUnitPageReqVO.java @@ -5,11 +5,6 @@ import io.swagger.v3.oas.annotations.media.Schema; import lombok.Data; import lombok.EqualsAndHashCode; import lombok.ToString; -import org.springframework.format.annotation.DateTimeFormat; - -import java.time.LocalDateTime; - -import static cn.iocoder.yudao.framework.common.util.date.DateUtils.FORMAT_YEAR_MONTH_DAY_HOUR_MINUTE_SECOND; @Schema(description = "管理后台 - ERP 产品单位分页 Request VO") @Data @@ -23,8 +18,4 @@ public class ErpProductUnitPageReqVO extends PageParam { @Schema(description = "单位状态", example = "1") private Integer status; - @Schema(description = "创建时间") - @DateTimeFormat(pattern = FORMAT_YEAR_MONTH_DAY_HOUR_MINUTE_SECOND) - private LocalDateTime[] createTime; - } \ No newline at end of file diff --git a/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/controller/admin/product/vo/unit/ErpProductUnitRespVO.java b/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/controller/admin/product/vo/unit/ErpProductUnitRespVO.java index e1287b0f5..06f604920 100644 --- a/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/controller/admin/product/vo/unit/ErpProductUnitRespVO.java +++ b/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/controller/admin/product/vo/unit/ErpProductUnitRespVO.java @@ -1,9 +1,10 @@ package cn.iocoder.yudao.module.erp.controller.admin.product.vo.unit; +import cn.iocoder.yudao.framework.excel.core.annotations.DictFormat; +import cn.iocoder.yudao.module.system.enums.DictTypeConstants; import com.alibaba.excel.annotation.ExcelIgnoreUnannotated; import com.alibaba.excel.annotation.ExcelProperty; import io.swagger.v3.oas.annotations.media.Schema; -import jakarta.validation.constraints.NotNull; import lombok.Data; import java.time.LocalDateTime; @@ -23,7 +24,7 @@ public class ErpProductUnitRespVO { @Schema(description = "单位状态", requiredMode = Schema.RequiredMode.REQUIRED, example = "1") @ExcelProperty("单位状态") - @NotNull(message = "分类排序不能为空") + @DictFormat(DictTypeConstants.COMMON_STATUS) private Integer status; @Schema(description = "创建时间", requiredMode = Schema.RequiredMode.REQUIRED) diff --git a/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/controller/admin/product/vo/unit/ErpProductUnitSaveReqVO.java b/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/controller/admin/product/vo/unit/ErpProductUnitSaveReqVO.java index eccf291b0..e413ec1bf 100644 --- a/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/controller/admin/product/vo/unit/ErpProductUnitSaveReqVO.java +++ b/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/controller/admin/product/vo/unit/ErpProductUnitSaveReqVO.java @@ -1,5 +1,7 @@ package cn.iocoder.yudao.module.erp.controller.admin.product.vo.unit; +import cn.iocoder.yudao.framework.common.enums.CommonStatusEnum; +import cn.iocoder.yudao.framework.common.validation.InEnum; import io.swagger.v3.oas.annotations.media.Schema; import jakarta.validation.constraints.NotEmpty; import jakarta.validation.constraints.NotNull; @@ -18,6 +20,7 @@ public class ErpProductUnitSaveReqVO { @Schema(description = "单位状态", requiredMode = Schema.RequiredMode.REQUIRED, example = "1") @NotNull(message = "单位状态不能为空") + @InEnum(CommonStatusEnum.class) private Integer status; } \ No newline at end of file diff --git a/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/dal/dataobject/product/ErpProductDO.java b/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/dal/dataobject/product/ErpProductDO.java index c6d947956..31e4aa2d9 100644 --- a/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/dal/dataobject/product/ErpProductDO.java +++ b/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/dal/dataobject/product/ErpProductDO.java @@ -45,9 +45,9 @@ public class ErpProductDO extends BaseDO { /** * 单位编号 * - * TODO 芋艿,关联 + * 关联 {@link ErpProductUnitDO#getId()} */ - private Integer unitId; + private Long unitId; /** * 产品状态 * diff --git a/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/dal/mysql/product/ErpProductMapper.java b/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/dal/mysql/product/ErpProductMapper.java index 8ecad6c54..81bca5cf9 100644 --- a/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/dal/mysql/product/ErpProductMapper.java +++ b/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/dal/mysql/product/ErpProductMapper.java @@ -23,4 +23,12 @@ public interface ErpProductMapper extends BaseMapperX { .orderByDesc(ErpProductDO::getId)); } + default Long selectCountByCategoryId(Long categoryId) { + return selectCount(ErpProductDO::getCategoryId, categoryId); + } + + default Long selectCountByUnitId(Long unitId) { + return selectCount(ErpProductDO::getUnitId, unitId); + } + } \ No newline at end of file diff --git a/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/dal/mysql/product/ErpProductUnitMapper.java b/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/dal/mysql/product/ErpProductUnitMapper.java index b24af15d3..45db6a829 100644 --- a/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/dal/mysql/product/ErpProductUnitMapper.java +++ b/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/dal/mysql/product/ErpProductUnitMapper.java @@ -7,6 +7,8 @@ import cn.iocoder.yudao.module.erp.controller.admin.product.vo.unit.ErpProductUn import cn.iocoder.yudao.module.erp.dal.dataobject.product.ErpProductUnitDO; import org.apache.ibatis.annotations.Mapper; +import java.util.List; + /** * ERP 产品单位 Mapper * @@ -19,8 +21,15 @@ public interface ErpProductUnitMapper extends BaseMapperX { return selectPage(reqVO, new LambdaQueryWrapperX() .likeIfPresent(ErpProductUnitDO::getName, reqVO.getName()) .eqIfPresent(ErpProductUnitDO::getStatus, reqVO.getStatus()) - .betweenIfPresent(ErpProductUnitDO::getCreateTime, reqVO.getCreateTime()) .orderByDesc(ErpProductUnitDO::getId)); } + default ErpProductUnitDO selectByName(String name) { + return selectOne(ErpProductUnitDO::getName, name); + } + + default List selectListByStatus(Integer status) { + return selectList(ErpProductUnitDO::getStatus, status); + } + } \ No newline at end of file diff --git a/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/service/product/ErpProductCategoryService.java b/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/service/product/ErpProductCategoryService.java index c5b1e9d21..2b11faf61 100644 --- a/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/service/product/ErpProductCategoryService.java +++ b/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/service/product/ErpProductCategoryService.java @@ -5,7 +5,11 @@ import cn.iocoder.yudao.module.erp.controller.admin.product.vo.category.ErpProdu import cn.iocoder.yudao.module.erp.dal.dataobject.product.ErpProductCategoryDO; import jakarta.validation.Valid; +import java.util.Collection; import java.util.List; +import java.util.Map; + +import static cn.iocoder.yudao.framework.common.util.collection.CollectionUtils.convertMap; /** * ERP 产品分类 Service 接口 @@ -40,7 +44,7 @@ public interface ErpProductCategoryService { * 获得产品分类 * * @param id 编号 - * @return ERP 产品分类 + * @return 产品分类 */ ErpProductCategoryDO getProductCategory(Long id); @@ -48,8 +52,26 @@ public interface ErpProductCategoryService { * 获得产品分类列表 * * @param listReqVO 查询条件 - * @return ERP 产品分类列表 + * @return 产品分类列表 */ List getProductCategoryList(ErpProductCategoryListReqVO listReqVO); + /** + * 获得产品分类列表 + * + * @param ids 编号数组 + * @return 产品分类列表 + */ + List getProductCategoryList(Collection ids); + + /** + * 获得产品分类 Map + * + * @param ids 编号数组 + * @return 产品分类 Map + */ + default Map getProductCategoryMap(Collection ids) { + return convertMap(getProductCategoryList(ids), ErpProductCategoryDO::getId); + } + } \ No newline at end of file diff --git a/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/service/product/ErpProductCategoryServiceImpl.java b/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/service/product/ErpProductCategoryServiceImpl.java index 6253914be..28d8b3172 100644 --- a/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/service/product/ErpProductCategoryServiceImpl.java +++ b/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/service/product/ErpProductCategoryServiceImpl.java @@ -6,9 +6,11 @@ import cn.iocoder.yudao.module.erp.controller.admin.product.vo.category.ErpProdu import cn.iocoder.yudao.module.erp.dal.dataobject.product.ErpProductCategoryDO; import cn.iocoder.yudao.module.erp.dal.mysql.product.ErpProductCategoryMapper; import jakarta.annotation.Resource; +import org.springframework.context.annotation.Lazy; import org.springframework.stereotype.Service; import org.springframework.validation.annotation.Validated; +import java.util.Collection; import java.util.List; import java.util.Objects; @@ -27,6 +29,10 @@ public class ErpProductCategoryServiceImpl implements ErpProductCategoryService @Resource private ErpProductCategoryMapper productCategoryMapper; + @Resource + @Lazy // 延迟加载,避免循环依赖 + private ErpProductService productService; + @Override public Long createProductCategory(ErpProductCategorySaveReqVO createReqVO) { // 校验父分类编号的有效性 @@ -57,13 +63,17 @@ public class ErpProductCategoryServiceImpl implements ErpProductCategoryService @Override public void deleteProductCategory(Long id) { - // 校验存在 + // 1.1 校验存在 validateProductCategoryExists(id); - // 校验是否有子产品分类 + // 1.2 校验是否有子产品分类 if (productCategoryMapper.selectCountByParentId(id) > 0) { throw exception(PRODUCT_CATEGORY_EXITS_CHILDREN); } - // 删除 + // 1.3 校验是否有产品 + if (productService.getProductCountByCategoryId(id) > 0) { + throw exception(PRODUCT_CATEGORY_EXITS_PRODUCT); + } + // 2. 删除 productCategoryMapper.deleteById(id); } @@ -131,4 +141,9 @@ public class ErpProductCategoryServiceImpl implements ErpProductCategoryService return productCategoryMapper.selectList(listReqVO); } + @Override + public List getProductCategoryList(Collection ids) { + return productCategoryMapper.selectBatchIds(ids); + } + } \ No newline at end of file diff --git a/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/service/product/ErpProductService.java b/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/service/product/ErpProductService.java index 1087ab70d..3a2e08ce6 100644 --- a/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/service/product/ErpProductService.java +++ b/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/service/product/ErpProductService.java @@ -51,4 +51,20 @@ public interface ErpProductService { */ PageResult getProductPage(ProductPageReqVO pageReqVO); + /** + * 基于产品分类编号,获得产品数量 + * + * @param categoryId 产品分类编号 + * @return 产品数量 + */ + Long getProductCountByCategoryId(Long categoryId); + + /** + * 基于产品单位编号,获得产品数量 + * + * @param unitId 产品单位编号 + * @return 产品数量 + */ + Long getProductCountByUnitId(Long unitId); + } \ No newline at end of file diff --git a/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/service/product/ErpProductServiceImpl.java b/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/service/product/ErpProductServiceImpl.java index 9fbe1f6e4..3efb981e3 100644 --- a/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/service/product/ErpProductServiceImpl.java +++ b/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/service/product/ErpProductServiceImpl.java @@ -69,4 +69,14 @@ public class ErpProductServiceImpl implements ErpProductService { return productMapper.selectPage(pageReqVO); } + @Override + public Long getProductCountByCategoryId(Long categoryId) { + return productMapper.selectCountByCategoryId(categoryId); + } + + @Override + public Long getProductCountByUnitId(Long unitId) { + return productMapper.selectCountByUnitId(unitId); + } + } \ No newline at end of file diff --git a/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/service/product/ErpProductUnitService.java b/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/service/product/ErpProductUnitService.java index 68599baf1..340278ab9 100644 --- a/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/service/product/ErpProductUnitService.java +++ b/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/service/product/ErpProductUnitService.java @@ -1,10 +1,16 @@ package cn.iocoder.yudao.module.erp.service.product; +import cn.iocoder.yudao.framework.common.pojo.PageResult; import cn.iocoder.yudao.module.erp.controller.admin.product.vo.unit.ErpProductUnitPageReqVO; import cn.iocoder.yudao.module.erp.controller.admin.product.vo.unit.ErpProductUnitSaveReqVO; -import jakarta.validation.*; import cn.iocoder.yudao.module.erp.dal.dataobject.product.ErpProductUnitDO; -import cn.iocoder.yudao.framework.common.pojo.PageResult; +import jakarta.validation.Valid; + +import java.util.Collection; +import java.util.List; +import java.util.Map; + +import static cn.iocoder.yudao.framework.common.util.collection.CollectionUtils.convertMap; /** * ERP 产品单位 Service 接口 @@ -51,4 +57,30 @@ public interface ErpProductUnitService { */ PageResult getProductUnitPage(ErpProductUnitPageReqVO pageReqVO); + /** + * 获得指定状态的产品单位列表 + * + * @param status 状态 + * @return 产品单位列表 + */ + List getProductUnitListByStatus(Integer status); + + /** + * 获得产品单位列表 + * + * @param ids 编号数组 + * @return 产品单位列表 + */ + List getProductUnitList(Collection ids); + + /** + * 获得产品单位 Map + * + * @param ids 编号数组 + * @return 产品单位 Map + */ + default Map getProductUnitMap(Collection ids) { + return convertMap(getProductUnitList(ids), ErpProductUnitDO::getId); + } + } \ No newline at end of file diff --git a/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/service/product/ErpProductUnitServiceImpl.java b/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/service/product/ErpProductUnitServiceImpl.java index 6800bda31..1ab412b11 100644 --- a/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/service/product/ErpProductUnitServiceImpl.java +++ b/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/service/product/ErpProductUnitServiceImpl.java @@ -1,19 +1,22 @@ package cn.iocoder.yudao.module.erp.service.product; -import cn.iocoder.yudao.module.erp.controller.admin.product.vo.unit.ErpProductUnitPageReqVO; -import cn.iocoder.yudao.module.erp.controller.admin.product.vo.unit.ErpProductUnitSaveReqVO; -import org.springframework.stereotype.Service; -import jakarta.annotation.Resource; -import org.springframework.validation.annotation.Validated; - -import cn.iocoder.yudao.module.erp.dal.dataobject.product.ErpProductUnitDO; import cn.iocoder.yudao.framework.common.pojo.PageResult; import cn.iocoder.yudao.framework.common.util.object.BeanUtils; - +import cn.iocoder.yudao.module.erp.controller.admin.product.vo.unit.ErpProductUnitPageReqVO; +import cn.iocoder.yudao.module.erp.controller.admin.product.vo.unit.ErpProductUnitSaveReqVO; +import cn.iocoder.yudao.module.erp.dal.dataobject.product.ErpProductUnitDO; import cn.iocoder.yudao.module.erp.dal.mysql.product.ErpProductUnitMapper; +import com.google.common.annotations.VisibleForTesting; +import jakarta.annotation.Resource; +import org.springframework.context.annotation.Lazy; +import org.springframework.stereotype.Service; +import org.springframework.validation.annotation.Validated; + +import java.util.Collection; +import java.util.List; import static cn.iocoder.yudao.framework.common.exception.util.ServiceExceptionUtil.exception; -import static cn.iocoder.yudao.module.erp.ErrorCodeConstants.PRODUCT_UNIT_NOT_EXISTS; +import static cn.iocoder.yudao.module.erp.ErrorCodeConstants.*; /** * ERP 产品单位 Service 实现类 @@ -27,29 +30,55 @@ public class ErpProductUnitServiceImpl implements ErpProductUnitService { @Resource private ErpProductUnitMapper productUnitMapper; + @Resource + @Lazy // 延迟加载,避免循环依赖 + private ErpProductService productService; + @Override public Long createProductUnit(ErpProductUnitSaveReqVO createReqVO) { - // 插入 + // 1. 校验名字唯一 + validateProductUnitNameUnique(null, createReqVO.getName()); + // 2. 插入 ErpProductUnitDO unit = BeanUtils.toBean(createReqVO, ErpProductUnitDO.class); productUnitMapper.insert(unit); - // 返回 return unit.getId(); } @Override public void updateProductUnit(ErpProductUnitSaveReqVO updateReqVO) { - // 校验存在 + // 1.1 校验存在 validateProductUnitExists(updateReqVO.getId()); - // 更新 + // 1.2 校验名字唯一 + validateProductUnitNameUnique(updateReqVO.getId(), updateReqVO.getName()); + // 2. 更新 ErpProductUnitDO updateObj = BeanUtils.toBean(updateReqVO, ErpProductUnitDO.class); productUnitMapper.updateById(updateObj); } + @VisibleForTesting + void validateProductUnitNameUnique(Long id, String name) { + ErpProductUnitDO unit = productUnitMapper.selectByName(name); + if (unit == null) { + return; + } + // 如果 id 为空,说明不用比较是否为相同 id 的字典类型 + if (id == null) { + throw exception(PRODUCT_UNIT_NAME_DUPLICATE); + } + if (!unit.getId().equals(id)) { + throw exception(PRODUCT_UNIT_NAME_DUPLICATE); + } + } + @Override public void deleteProductUnit(Long id) { - // 校验存在 + // 1.1 校验存在 validateProductUnitExists(id); - // 删除 + // 1.2 校验商品是否使用 + if (productService.getProductCountByUnitId(id) > 0) { + throw exception(PRODUCT_UNIT_EXITS_PRODUCT); + } + // 2. 删除 productUnitMapper.deleteById(id); } @@ -69,4 +98,14 @@ public class ErpProductUnitServiceImpl implements ErpProductUnitService { return productUnitMapper.selectPage(pageReqVO); } + @Override + public List getProductUnitListByStatus(Integer status) { + return productUnitMapper.selectListByStatus(status); + } + + @Override + public List getProductUnitList(Collection ids) { + return productUnitMapper.selectBatchIds(ids); + } + } \ No newline at end of file From b7654eafeafd5100b6ee3543b07bd3a7ddb23e69 Mon Sep 17 00:00:00 2001 From: YunaiV Date: Mon, 5 Feb 2024 01:36:34 +0800 Subject: [PATCH 073/119] =?UTF-8?q?=E2=9C=A8=20ERP=EF=BC=9A=E5=AE=8C?= =?UTF-8?q?=E6=88=90=20stock=20=E4=BB=93=E5=BA=93=E4=BF=A1=E6=81=AF?= =?UTF-8?q?=E7=9A=84=E5=AE=9E=E7=8E=B0?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../yudao/module/erp/ErrorCodeConstants.java | 3 + .../admin/stock/ErpWarehouseController.java | 106 +++++++++++++++ .../vo/warehouse/ErpWarehousePageReqVO.java | 24 ++++ .../vo/warehouse/ErpWarehouseRespVO.java | 64 +++++++++ .../vo/warehouse/ErpWarehouseSaveReqVO.java | 47 +++++++ .../dal/dataobject/stock/ErpWarehouseDO.java | 70 ++++++++++ .../dal/mysql/stock/ErpWarehouseMapper.java | 29 ++++ .../service/stock/ErpWarehouseService.java | 62 +++++++++ .../stock/ErpWarehouseServiceImpl.java | 88 ++++++++++++ .../mapper/stock/ErpWarehouseMapper.xml | 12 ++ .../stock/ErpWarehouseServiceImplTest.java | 126 ++++++++++++++++++ 11 files changed, 631 insertions(+) create mode 100644 yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/controller/admin/stock/ErpWarehouseController.java create mode 100644 yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/controller/admin/stock/vo/warehouse/ErpWarehousePageReqVO.java create mode 100644 yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/controller/admin/stock/vo/warehouse/ErpWarehouseRespVO.java create mode 100644 yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/controller/admin/stock/vo/warehouse/ErpWarehouseSaveReqVO.java create mode 100644 yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/dal/dataobject/stock/ErpWarehouseDO.java create mode 100644 yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/dal/mysql/stock/ErpWarehouseMapper.java create mode 100644 yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/service/stock/ErpWarehouseService.java create mode 100644 yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/service/stock/ErpWarehouseServiceImpl.java create mode 100644 yudao-module-erp/yudao-module-erp-biz/src/main/resources/mapper/stock/ErpWarehouseMapper.xml create mode 100644 yudao-module-erp/yudao-module-erp-biz/src/test/java/cn/iocoder/yudao/module/erp/service/stock/ErpWarehouseServiceImplTest.java diff --git a/yudao-module-erp/yudao-module-erp-api/src/main/java/cn/iocoder/yudao/module/erp/ErrorCodeConstants.java b/yudao-module-erp/yudao-module-erp-api/src/main/java/cn/iocoder/yudao/module/erp/ErrorCodeConstants.java index db3a3a37d..f174ed854 100644 --- a/yudao-module-erp/yudao-module-erp-api/src/main/java/cn/iocoder/yudao/module/erp/ErrorCodeConstants.java +++ b/yudao-module-erp/yudao-module-erp-api/src/main/java/cn/iocoder/yudao/module/erp/ErrorCodeConstants.java @@ -9,6 +9,9 @@ import cn.iocoder.yudao.framework.common.exception.ErrorCode; */ public interface ErrorCodeConstants { + // ========== ERP 仓库 1-030-400-000 ========== + ErrorCode WAREHOUSE_NOT_EXISTS = new ErrorCode(1_030_400_000, "仓库不存在"); + // ========== ERP 产品 1-030-500-000 ========== ErrorCode PRODUCT_NOT_EXISTS = new ErrorCode(1_030_500_000, "产品不存在"); diff --git a/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/controller/admin/stock/ErpWarehouseController.java b/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/controller/admin/stock/ErpWarehouseController.java new file mode 100644 index 000000000..8877780d8 --- /dev/null +++ b/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/controller/admin/stock/ErpWarehouseController.java @@ -0,0 +1,106 @@ +package cn.iocoder.yudao.module.erp.controller.admin.stock; + +import cn.iocoder.yudao.framework.common.pojo.CommonResult; +import cn.iocoder.yudao.framework.common.pojo.PageParam; +import cn.iocoder.yudao.framework.common.pojo.PageResult; +import cn.iocoder.yudao.framework.common.util.object.BeanUtils; +import cn.iocoder.yudao.framework.excel.core.util.ExcelUtils; +import cn.iocoder.yudao.framework.operatelog.core.annotations.OperateLog; +import cn.iocoder.yudao.module.erp.controller.admin.stock.vo.ErpWarehouseSaveReqVO; +import cn.iocoder.yudao.module.erp.controller.admin.stock.vo.warehouse.ErpWarehousePageReqVO; +import cn.iocoder.yudao.module.erp.controller.admin.stock.vo.warehouse.ErpWarehouseRespVO; +import cn.iocoder.yudao.module.erp.dal.dataobject.stock.ErpWarehouseDO; +import cn.iocoder.yudao.module.erp.service.stock.ErpWarehouseService; +import io.swagger.v3.oas.annotations.Operation; +import io.swagger.v3.oas.annotations.Parameter; +import io.swagger.v3.oas.annotations.Parameters; +import io.swagger.v3.oas.annotations.tags.Tag; +import jakarta.annotation.Resource; +import jakarta.servlet.http.HttpServletResponse; +import jakarta.validation.Valid; +import org.springframework.security.access.prepost.PreAuthorize; +import org.springframework.validation.annotation.Validated; +import org.springframework.web.bind.annotation.*; + +import java.io.IOException; +import java.util.List; + +import static cn.iocoder.yudao.framework.common.pojo.CommonResult.success; +import static cn.iocoder.yudao.framework.operatelog.core.enums.OperateTypeEnum.EXPORT; + +@Tag(name = "管理后台 - ERP 仓库") +@RestController +@RequestMapping("/erp/warehouse") +@Validated +public class ErpWarehouseController { + + @Resource + private ErpWarehouseService warehouseService; + + @PostMapping("/create") + @Operation(summary = "创建仓库") + @PreAuthorize("@ss.hasPermission('erp:warehouse:create')") + public CommonResult createWarehouse(@Valid @RequestBody ErpWarehouseSaveReqVO createReqVO) { + return success(warehouseService.createWarehouse(createReqVO)); + } + + @PutMapping("/update") + @Operation(summary = "更新仓库") + @PreAuthorize("@ss.hasPermission('erp:warehouse:update')") + public CommonResult updateWarehouse(@Valid @RequestBody ErpWarehouseSaveReqVO updateReqVO) { + warehouseService.updateWarehouse(updateReqVO); + return success(true); + } + + @PutMapping("/update-default-status") + @Operation(summary = "更新仓库默认状态") + @Parameters({ + @Parameter(name = "id", description = "编号", required = true), + @Parameter(name = "status", description = "状态", required = true) + }) + public CommonResult updateWarehouseDefaultStatus(@RequestParam("id") Long id, + @RequestParam("defaultStatus") Boolean defaultStatus) { + warehouseService.updateWarehouseDefaultStatus(id, defaultStatus); + return success(true); + } + + @DeleteMapping("/delete") + @Operation(summary = "删除仓库") + @Parameter(name = "id", description = "编号", required = true) + @PreAuthorize("@ss.hasPermission('erp:warehouse:delete')") + public CommonResult deleteWarehouse(@RequestParam("id") Long id) { + warehouseService.deleteWarehouse(id); + return success(true); + } + + @GetMapping("/get") + @Operation(summary = "获得仓库") + @Parameter(name = "id", description = "编号", required = true, example = "1024") + @PreAuthorize("@ss.hasPermission('erp:warehouse:query')") + public CommonResult getWarehouse(@RequestParam("id") Long id) { + ErpWarehouseDO warehouse = warehouseService.getWarehouse(id); + return success(BeanUtils.toBean(warehouse, ErpWarehouseRespVO.class)); + } + + @GetMapping("/page") + @Operation(summary = "获得仓库分页") + @PreAuthorize("@ss.hasPermission('erp:warehouse:query')") + public CommonResult> getWarehousePage(@Valid ErpWarehousePageReqVO pageReqVO) { + PageResult pageResult = warehouseService.getWarehousePage(pageReqVO); + return success(BeanUtils.toBean(pageResult, ErpWarehouseRespVO.class)); + } + + @GetMapping("/export-excel") + @Operation(summary = "导出仓库 Excel") + @PreAuthorize("@ss.hasPermission('erp:warehouse:export')") + @OperateLog(type = EXPORT) + public void exportWarehouseExcel(@Valid ErpWarehousePageReqVO pageReqVO, + HttpServletResponse response) throws IOException { + pageReqVO.setPageSize(PageParam.PAGE_SIZE_NONE); + List list = warehouseService.getWarehousePage(pageReqVO).getList(); + // 导出 Excel + ExcelUtils.write(response, "仓库.xls", "数据", ErpWarehouseRespVO.class, + BeanUtils.toBean(list, ErpWarehouseRespVO.class)); + } + +} \ No newline at end of file diff --git a/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/controller/admin/stock/vo/warehouse/ErpWarehousePageReqVO.java b/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/controller/admin/stock/vo/warehouse/ErpWarehousePageReqVO.java new file mode 100644 index 000000000..2accf9a0f --- /dev/null +++ b/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/controller/admin/stock/vo/warehouse/ErpWarehousePageReqVO.java @@ -0,0 +1,24 @@ +package cn.iocoder.yudao.module.erp.controller.admin.stock.vo.warehouse; + +import cn.iocoder.yudao.framework.common.enums.CommonStatusEnum; +import cn.iocoder.yudao.framework.common.pojo.PageParam; +import cn.iocoder.yudao.framework.common.validation.InEnum; +import io.swagger.v3.oas.annotations.media.Schema; +import lombok.Data; +import lombok.EqualsAndHashCode; +import lombok.ToString; + +@Schema(description = "管理后台 - ERP 仓库分页 Request VO") +@Data +@EqualsAndHashCode(callSuper = true) +@ToString(callSuper = true) +public class ErpWarehousePageReqVO extends PageParam { + + @Schema(description = "仓库名称", example = "李四") + private String name; + + @Schema(description = "开启状态", example = "1") + @InEnum(CommonStatusEnum.class) + private Integer status; + +} \ No newline at end of file diff --git a/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/controller/admin/stock/vo/warehouse/ErpWarehouseRespVO.java b/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/controller/admin/stock/vo/warehouse/ErpWarehouseRespVO.java new file mode 100644 index 000000000..188d42699 --- /dev/null +++ b/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/controller/admin/stock/vo/warehouse/ErpWarehouseRespVO.java @@ -0,0 +1,64 @@ +package cn.iocoder.yudao.module.erp.controller.admin.stock.vo.warehouse; + +import cn.iocoder.yudao.framework.excel.core.annotations.DictFormat; +import cn.iocoder.yudao.framework.excel.core.convert.DictConvert; +import cn.iocoder.yudao.module.system.enums.DictTypeConstants; +import com.alibaba.excel.annotation.ExcelIgnoreUnannotated; +import com.alibaba.excel.annotation.ExcelProperty; +import io.swagger.v3.oas.annotations.media.Schema; +import lombok.Data; + +import java.math.BigDecimal; +import java.time.LocalDateTime; + +@Schema(description = "管理后台 - ERP 仓库 Response VO") +@Data +@ExcelIgnoreUnannotated +public class ErpWarehouseRespVO { + + @Schema(description = "仓库编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "11614") + @ExcelProperty("仓库编号") + private Long id; + + @Schema(description = "仓库名称", requiredMode = Schema.RequiredMode.REQUIRED, example = "李四") + @ExcelProperty("仓库名称") + private String name; + + @Schema(description = "仓库地址", example = "上海陆家嘴") + @ExcelProperty("仓库地址") + private String address; + + @Schema(description = "排序", requiredMode = Schema.RequiredMode.REQUIRED, example = "10") + @ExcelProperty("排序") + private Long sort; + + @Schema(description = "备注", example = "随便") + @ExcelProperty("备注") + private String remark; + + @Schema(description = "负责人", example = "芋头") + @ExcelProperty("负责人") + private String principal; + + @Schema(description = "仓储费,单位:元", example = "13973") + @ExcelProperty("仓储费,单位:元") + private BigDecimal warehousePrice; + + @Schema(description = "搬运费,单位:元", example = "9903") + @ExcelProperty("搬运费,单位:元") + private BigDecimal truckagePrice; + + @Schema(description = "开启状态", requiredMode = Schema.RequiredMode.REQUIRED, example = "1") + @ExcelProperty(value = "开启状态", converter = DictConvert.class) + @DictFormat(DictTypeConstants.COMMON_STATUS) + private Integer status; + + @Schema(description = "是否默认", example = "1") + @ExcelProperty("是否默认") + private Boolean defaultStatus; + + @Schema(description = "创建时间", requiredMode = Schema.RequiredMode.REQUIRED) + @ExcelProperty("创建时间") + private LocalDateTime createTime; + +} \ No newline at end of file diff --git a/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/controller/admin/stock/vo/warehouse/ErpWarehouseSaveReqVO.java b/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/controller/admin/stock/vo/warehouse/ErpWarehouseSaveReqVO.java new file mode 100644 index 000000000..8a6f1ce78 --- /dev/null +++ b/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/controller/admin/stock/vo/warehouse/ErpWarehouseSaveReqVO.java @@ -0,0 +1,47 @@ +package cn.iocoder.yudao.module.erp.controller.admin.stock.vo; + +import cn.iocoder.yudao.framework.common.enums.CommonStatusEnum; +import cn.iocoder.yudao.framework.common.validation.InEnum; +import io.swagger.v3.oas.annotations.media.Schema; +import jakarta.validation.constraints.NotEmpty; +import jakarta.validation.constraints.NotNull; +import lombok.Data; + +import java.math.BigDecimal; + +@Schema(description = "管理后台 - ERP 仓库新增/修改 Request VO") +@Data +public class ErpWarehouseSaveReqVO { + + @Schema(description = "仓库编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "11614") + private Long id; + + @Schema(description = "仓库名称", requiredMode = Schema.RequiredMode.REQUIRED, example = "李四") + @NotEmpty(message = "仓库名称不能为空") + private String name; + + @Schema(description = "仓库地址", example = "上海陆家嘴") + private String address; + + @Schema(description = "排序", requiredMode = Schema.RequiredMode.REQUIRED, example = "10") + @NotNull(message = "排序不能为空") + private Long sort; + + @Schema(description = "备注", example = "随便") + private String remark; + + @Schema(description = "负责人", example = "芋头") + private String principal; + + @Schema(description = "仓储费,单位:元", example = "13973") + private BigDecimal warehousePrice; + + @Schema(description = "搬运费,单位:元", example = "9903") + private BigDecimal truckagePrice; + + @Schema(description = "开启状态", requiredMode = Schema.RequiredMode.REQUIRED, example = "2") + @NotNull(message = "开启状态不能为空") + @InEnum(CommonStatusEnum.class) + private Integer status; + +} \ No newline at end of file diff --git a/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/dal/dataobject/stock/ErpWarehouseDO.java b/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/dal/dataobject/stock/ErpWarehouseDO.java new file mode 100644 index 000000000..4f206173f --- /dev/null +++ b/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/dal/dataobject/stock/ErpWarehouseDO.java @@ -0,0 +1,70 @@ +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.*; + +import java.math.BigDecimal; + +/** + * ERP 仓库 DO + * + * @author 芋道源码 + */ +@TableName("erp_warehouse") +@KeySequence("erp_warehouse_seq") // 用于 Oracle、PostgreSQL、Kingbase、DB2、H2 数据库的主键自增。如果是 MySQL 等数据库,可不写。 +@Data +@EqualsAndHashCode(callSuper = true) +@ToString(callSuper = true) +@Builder +@NoArgsConstructor +@AllArgsConstructor +public class ErpWarehouseDO extends BaseDO { + + /** + * 仓库编号 + */ + @TableId + private Long id; + /** + * 仓库名称 + */ + private String name; + /** + * 仓库地址 + */ + private String address; + /** + * 排序 + */ + private Long sort; + /** + * 备注 + */ + private String remark; + /** + * 负责人 + */ + private String principal; + /** + * 仓储费,单位:元 + */ + private BigDecimal warehousePrice; + /** + * 搬运费,单位:元 + */ + private BigDecimal truckagePrice; + /** + * 开启状态 + * + * 枚举 {@link cn.iocoder.yudao.framework.common.enums.CommonStatusEnum} + */ + private Integer status; + /** + * 是否默认 + */ + private Boolean defaultStatus; + +} \ No newline at end of file diff --git a/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/dal/mysql/stock/ErpWarehouseMapper.java b/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/dal/mysql/stock/ErpWarehouseMapper.java new file mode 100644 index 000000000..7d3bf0d3e --- /dev/null +++ b/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/dal/mysql/stock/ErpWarehouseMapper.java @@ -0,0 +1,29 @@ +package cn.iocoder.yudao.module.erp.dal.mysql.stock; + +import cn.iocoder.yudao.framework.common.pojo.PageResult; +import cn.iocoder.yudao.framework.mybatis.core.query.LambdaQueryWrapperX; +import cn.iocoder.yudao.framework.mybatis.core.mapper.BaseMapperX; +import cn.iocoder.yudao.module.erp.controller.admin.stock.vo.warehouse.ErpWarehousePageReqVO; +import cn.iocoder.yudao.module.erp.dal.dataobject.stock.ErpWarehouseDO; +import org.apache.ibatis.annotations.Mapper; + +/** + * ERP 仓库 Mapper + * + * @author 芋道源码 + */ +@Mapper +public interface ErpWarehouseMapper extends BaseMapperX { + + default PageResult selectPage(ErpWarehousePageReqVO reqVO) { + return selectPage(reqVO, new LambdaQueryWrapperX() + .likeIfPresent(ErpWarehouseDO::getName, reqVO.getName()) + .eqIfPresent(ErpWarehouseDO::getStatus, reqVO.getStatus()) + .orderByDesc(ErpWarehouseDO::getId)); + } + + default ErpWarehouseDO selectByDefaultStatus() { + return selectOne(ErpWarehouseDO::getDefaultStatus, true); + } + +} \ No newline at end of file diff --git a/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/service/stock/ErpWarehouseService.java b/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/service/stock/ErpWarehouseService.java new file mode 100644 index 000000000..47e4dbed2 --- /dev/null +++ b/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/service/stock/ErpWarehouseService.java @@ -0,0 +1,62 @@ +package cn.iocoder.yudao.module.erp.service.stock; + +import cn.iocoder.yudao.framework.common.pojo.PageResult; +import cn.iocoder.yudao.module.erp.controller.admin.stock.vo.ErpWarehouseSaveReqVO; +import cn.iocoder.yudao.module.erp.controller.admin.stock.vo.warehouse.ErpWarehousePageReqVO; +import cn.iocoder.yudao.module.erp.dal.dataobject.stock.ErpWarehouseDO; +import jakarta.validation.Valid; + +/** + * ERP 仓库 Service 接口 + * + * @author 芋道源码 + */ +public interface ErpWarehouseService { + + /** + * 创建仓库 + * + * @param createReqVO 创建信息 + * @return 编号 + */ + Long createWarehouse(@Valid ErpWarehouseSaveReqVO createReqVO); + + /** + * 更新ERP 仓库 + * + * @param updateReqVO 更新信息 + */ + void updateWarehouse(@Valid ErpWarehouseSaveReqVO updateReqVO); + + /** + * 更新仓库默认状态 + * + * @param id 编号 + * @param defaultStatus 默认状态 + */ + void updateWarehouseDefaultStatus(Long id, Boolean defaultStatus); + + /** + * 删除仓库 + * + * @param id 编号 + */ + void deleteWarehouse(Long id); + + /** + * 获得仓库 + * + * @param id 编号 + * @return 仓库 + */ + ErpWarehouseDO getWarehouse(Long id); + + /** + * 获得仓库分页 + * + * @param pageReqVO 分页查询 + * @return 仓库分页 + */ + PageResult getWarehousePage(ErpWarehousePageReqVO pageReqVO); + +} \ No newline at end of file diff --git a/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/service/stock/ErpWarehouseServiceImpl.java b/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/service/stock/ErpWarehouseServiceImpl.java new file mode 100644 index 000000000..e4c34ade4 --- /dev/null +++ b/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/service/stock/ErpWarehouseServiceImpl.java @@ -0,0 +1,88 @@ +package cn.iocoder.yudao.module.erp.service.stock; + +import cn.iocoder.yudao.framework.common.pojo.PageResult; +import cn.iocoder.yudao.framework.common.util.object.BeanUtils; +import cn.iocoder.yudao.module.erp.controller.admin.stock.vo.ErpWarehouseSaveReqVO; +import cn.iocoder.yudao.module.erp.controller.admin.stock.vo.warehouse.ErpWarehousePageReqVO; +import cn.iocoder.yudao.module.erp.dal.dataobject.stock.ErpWarehouseDO; +import cn.iocoder.yudao.module.erp.dal.mysql.stock.ErpWarehouseMapper; +import jakarta.annotation.Resource; +import org.springframework.stereotype.Service; +import org.springframework.transaction.annotation.Transactional; +import org.springframework.validation.annotation.Validated; + +import static cn.iocoder.yudao.framework.common.exception.util.ServiceExceptionUtil.exception; +import static cn.iocoder.yudao.module.erp.ErrorCodeConstants.WAREHOUSE_NOT_EXISTS; + +/** + * ERP 仓库 Service 实现类 + * + * @author 芋道源码 + */ +@Service +@Validated +public class ErpWarehouseServiceImpl implements ErpWarehouseService { + + @Resource + private ErpWarehouseMapper warehouseMapper; + + @Override + public Long createWarehouse(ErpWarehouseSaveReqVO createReqVO) { + // 插入 + ErpWarehouseDO warehouse = BeanUtils.toBean(createReqVO, ErpWarehouseDO.class); + warehouseMapper.insert(warehouse); + // 返回 + return warehouse.getId(); + } + + @Override + public void updateWarehouse(ErpWarehouseSaveReqVO updateReqVO) { + // 校验存在 + validateWarehouseExists(updateReqVO.getId()); + // 更新 + ErpWarehouseDO updateObj = BeanUtils.toBean(updateReqVO, ErpWarehouseDO.class); + warehouseMapper.updateById(updateObj); + } + + @Override + @Transactional(rollbackFor = Exception.class) + public void updateWarehouseDefaultStatus(Long id, Boolean defaultStatus) { + // 1. 校验存在 + validateWarehouseExists(id); + + // 2.1 如果开启,则需要关闭所有其它的默认 + if (defaultStatus) { + ErpWarehouseDO warehouse = warehouseMapper.selectByDefaultStatus(); + if (warehouse != null) { + warehouseMapper.updateById(new ErpWarehouseDO().setId(warehouse.getId()).setDefaultStatus(false)); + } + } + // 2.2 更新对应的默认状态 + warehouseMapper.updateById(new ErpWarehouseDO().setId(id).setDefaultStatus(defaultStatus)); + } + + @Override + public void deleteWarehouse(Long id) { + // 校验存在 + validateWarehouseExists(id); + // 删除 + warehouseMapper.deleteById(id); + } + + private void validateWarehouseExists(Long id) { + if (warehouseMapper.selectById(id) == null) { + throw exception(WAREHOUSE_NOT_EXISTS); + } + } + + @Override + public ErpWarehouseDO getWarehouse(Long id) { + return warehouseMapper.selectById(id); + } + + @Override + public PageResult getWarehousePage(ErpWarehousePageReqVO pageReqVO) { + return warehouseMapper.selectPage(pageReqVO); + } + +} \ No newline at end of file diff --git a/yudao-module-erp/yudao-module-erp-biz/src/main/resources/mapper/stock/ErpWarehouseMapper.xml b/yudao-module-erp/yudao-module-erp-biz/src/main/resources/mapper/stock/ErpWarehouseMapper.xml new file mode 100644 index 000000000..be2bc61cb --- /dev/null +++ b/yudao-module-erp/yudao-module-erp-biz/src/main/resources/mapper/stock/ErpWarehouseMapper.xml @@ -0,0 +1,12 @@ + + + + + + + \ No newline at end of file diff --git a/yudao-module-erp/yudao-module-erp-biz/src/test/java/cn/iocoder/yudao/module/erp/service/stock/ErpWarehouseServiceImplTest.java b/yudao-module-erp/yudao-module-erp-biz/src/test/java/cn/iocoder/yudao/module/erp/service/stock/ErpWarehouseServiceImplTest.java new file mode 100644 index 000000000..fa74620e2 --- /dev/null +++ b/yudao-module-erp/yudao-module-erp-biz/src/test/java/cn/iocoder/yudao/module/erp/service/stock/ErpWarehouseServiceImplTest.java @@ -0,0 +1,126 @@ +package cn.iocoder.yudao.module.erp.service.stock; + +import cn.iocoder.yudao.module.erp.controller.admin.stock.vo.warehouse.ErpWarehousePageReqVO; +import cn.iocoder.yudao.module.erp.controller.admin.stock.vo.warehouse.ErpWarehouseSaveReqVO; +import org.junit.jupiter.api.Disabled; +import org.junit.jupiter.api.Test; + +import jakarta.annotation.Resource; + +import cn.iocoder.yudao.framework.test.core.ut.BaseDbUnitTest; + +import cn.iocoder.yudao.module.erp.dal.dataobject.stock.ErpWarehouseDO; +import cn.iocoder.yudao.module.erp.dal.mysql.stock.ErpWarehouseMapper; +import cn.iocoder.yudao.framework.common.pojo.PageResult; + +import org.springframework.context.annotation.Import; + +import static cn.iocoder.yudao.framework.test.core.util.AssertUtils.*; +import static cn.iocoder.yudao.framework.test.core.util.RandomUtils.*; +import static cn.iocoder.yudao.framework.common.util.object.ObjectUtils.*; +import static org.junit.jupiter.api.Assertions.*; + +/** + * {@link ErpWarehouseServiceImpl} 的单元测试类 + * + * @author 芋道源码 + */ +@Import(ErpWarehouseServiceImpl.class) +public class ErpWarehouseServiceImplTest extends BaseDbUnitTest { + + @Resource + private ErpWarehouseServiceImpl warehouseService; + + @Resource + private ErpWarehouseMapper warehouseMapper; + + @Test + public void testCreateWarehouse_success() { + // 准备参数 + ErpWarehouseSaveReqVO createReqVO = randomPojo(ErpWarehouseSaveReqVO.class).setId(null); + + // 调用 + Long warehouseId = warehouseService.createWarehouse(createReqVO); + // 断言 + assertNotNull(warehouseId); + // 校验记录的属性是否正确 + ErpWarehouseDO warehouse = warehouseMapper.selectById(warehouseId); + assertPojoEquals(createReqVO, warehouse, "id"); + } + + @Test + public void testUpdateWarehouse_success() { + // mock 数据 + ErpWarehouseDO dbWarehouse = randomPojo(ErpWarehouseDO.class); + warehouseMapper.insert(dbWarehouse);// @Sql: 先插入出一条存在的数据 + // 准备参数 + ErpWarehouseSaveReqVO updateReqVO = randomPojo(ErpWarehouseSaveReqVO.class, o -> { + o.setId(dbWarehouse.getId()); // 设置更新的 ID + }); + + // 调用 + warehouseService.updateWarehouse(updateReqVO); + // 校验是否更新正确 + ErpWarehouseDO warehouse = warehouseMapper.selectById(updateReqVO.getId()); // 获取最新的 + assertPojoEquals(updateReqVO, warehouse); + } + + @Test + public void testUpdateWarehouse_notExists() { + // 准备参数 + ErpWarehouseSaveReqVO updateReqVO = randomPojo(ErpWarehouseSaveReqVO.class); + + // 调用, 并断言异常 + assertServiceException(() -> warehouseService.updateWarehouse(updateReqVO), WAREHOUSE_NOT_EXISTS); + } + + @Test + public void testDeleteWarehouse_success() { + // mock 数据 + ErpWarehouseDO dbWarehouse = randomPojo(ErpWarehouseDO.class); + warehouseMapper.insert(dbWarehouse);// @Sql: 先插入出一条存在的数据 + // 准备参数 + Long id = dbWarehouse.getId(); + + // 调用 + warehouseService.deleteWarehouse(id); + // 校验数据不存在了 + assertNull(warehouseMapper.selectById(id)); + } + + @Test + public void testDeleteWarehouse_notExists() { + // 准备参数 + Long id = randomLongId(); + + // 调用, 并断言异常 + assertServiceException(() -> warehouseService.deleteWarehouse(id), WAREHOUSE_NOT_EXISTS); + } + + @Test + @Disabled // TODO 请修改 null 为需要的值,然后删除 @Disabled 注解 + public void testGetWarehousePage() { + // mock 数据 + ErpWarehouseDO dbWarehouse = randomPojo(ErpWarehouseDO.class, o -> { // 等会查询到 + o.setName(null); + o.setStatus(null); + }); + warehouseMapper.insert(dbWarehouse); + // 测试 name 不匹配 + warehouseMapper.insert(cloneIgnoreId(dbWarehouse, o -> o.setName(null))); + // 测试 status 不匹配 + warehouseMapper.insert(cloneIgnoreId(dbWarehouse, o -> o.setStatus(null))); + // 准备参数 + ErpWarehousePageReqVO reqVO = new ErpWarehousePageReqVO(); + reqVO.setName(null); + reqVO.setStatus(null); + + // 调用 + PageResult pageResult = warehouseService.getWarehousePage(reqVO); + // 断言 + assertEquals(1, pageResult.getTotal()); + assertEquals(1, pageResult.getList().size()); + assertPojoEquals(dbWarehouse, pageResult.getList().get(0)); + } + +} \ No newline at end of file From 5a2554205d4ae8b94e91b7ab6cfa43844bc95f3d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E6=9D=A8=E5=AE=87=E5=BA=86?= Date: Sun, 4 Feb 2024 18:59:53 +0000 Subject: [PATCH 074/119] =?UTF-8?q?=E8=A7=A3=E5=86=B3=E5=BD=93=E6=9F=90?= =?UTF-8?q?=E5=9C=B0=E5=8C=BA=E6=9C=89=E4=BA=BA=E4=B8=8B=E5=8D=95=E4=BD=86?= =?UTF-8?q?=E6=97=A0=E4=BA=BA=E6=94=AF=E4=BB=98=E6=97=B6=E7=9A=84=E7=A9=BA?= =?UTF-8?q?=E6=8C=87=E9=92=88=E5=BC=82=E5=B8=B8?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Signed-off-by: 杨宇庆 --- .../statistics/service/member/MemberStatisticsServiceImpl.java | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/yudao-module-mall/yudao-module-statistics-biz/src/main/java/cn/iocoder/yudao/module/statistics/service/member/MemberStatisticsServiceImpl.java b/yudao-module-mall/yudao-module-statistics-biz/src/main/java/cn/iocoder/yudao/module/statistics/service/member/MemberStatisticsServiceImpl.java index 7b159059f..60e9b3c18 100644 --- a/yudao-module-mall/yudao-module-statistics-biz/src/main/java/cn/iocoder/yudao/module/statistics/service/member/MemberStatisticsServiceImpl.java +++ b/yudao-module-mall/yudao-module-statistics-biz/src/main/java/cn/iocoder/yudao/module/statistics/service/member/MemberStatisticsServiceImpl.java @@ -1,6 +1,7 @@ package cn.iocoder.yudao.module.statistics.service.member; import cn.hutool.core.date.LocalDateTimeUtil; +import cn.hutool.core.util.ObjUtil; import cn.iocoder.yudao.framework.common.enums.UserTypeEnum; import cn.iocoder.yudao.framework.ip.core.Area; import cn.iocoder.yudao.framework.ip.core.enums.AreaTypeEnum; @@ -71,7 +72,7 @@ public class MemberStatisticsServiceImpl implements MemberStatisticsService { (a, b) -> new MemberAreaStatisticsRespBO() .setOrderCreateUserCount(a.getOrderCreateUserCount() + b.getOrderCreateUserCount()) .setOrderPayUserCount(a.getOrderPayUserCount() + b.getOrderPayUserCount()) - .setOrderPayPrice(a.getOrderPayPrice() + b.getOrderPayPrice())); + .setOrderPayPrice(ObjUtil.defaultIfNull(a.getOrderPayPrice(), 0) + ObjUtil.defaultIfNull(b.getOrderPayPrice(), 0))); // 拼接数据 List areaList = AreaUtils.getByType(AreaTypeEnum.PROVINCE, area -> area); areaList.add(new Area().setId(null).setName("未知")); From 4f236c62eed1b62e1cdedd1c051e71ec8b3fb3cf Mon Sep 17 00:00:00 2001 From: YunaiV Date: Mon, 5 Feb 2024 19:04:44 +0800 Subject: [PATCH 075/119] =?UTF-8?q?=E2=9C=A8=20=E5=85=A8=E5=B1=80=EF=BC=9A?= =?UTF-8?q?=E4=BF=AE=E6=94=B9=20Vue3=20+=20EP=20=E7=89=88=E6=9C=AC?= =?UTF-8?q?=E7=9A=84=E4=BB=A3=E7=A0=81=E7=94=9F=E6=88=90=E7=9A=84=E6=B3=A8?= =?UTF-8?q?=E9=87=8A=E7=9B=B8=E5=85=B3?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../src/main/resources/codegen/vue3/api/api.ts.vm | 7 +++---- .../src/main/resources/codegen/vue3/views/form.vue.vm | 2 +- .../src/main/resources/codegen/vue3/views/index.vue.vm | 3 +-- 3 files changed, 5 insertions(+), 7 deletions(-) diff --git a/yudao-module-infra/yudao-module-infra-biz/src/main/resources/codegen/vue3/api/api.ts.vm b/yudao-module-infra/yudao-module-infra-biz/src/main/resources/codegen/vue3/api/api.ts.vm index 7c2ab277b..c3044fb87 100644 --- a/yudao-module-infra/yudao-module-infra-biz/src/main/resources/codegen/vue3/api/api.ts.vm +++ b/yudao-module-infra/yudao-module-infra-biz/src/main/resources/codegen/vue3/api/api.ts.vm @@ -5,13 +5,12 @@ import request from '@/config/axios' export interface ${simpleClassName}VO { #foreach ($column in $columns) #if ($column.createOperation || $column.updateOperation) - // ${column.columnComment} #if(${column.javaType.toLowerCase()} == "long" || ${column.javaType.toLowerCase()} == "integer" || ${column.javaType.toLowerCase()} == "short" || ${column.javaType.toLowerCase()} == "double" || ${column.javaType.toLowerCase()} == "bigdecimal") - ${column.javaField}: number + ${column.javaField}: number // ${column.columnComment} #elseif(${column.javaType.toLowerCase()} == "date" || ${column.javaType.toLowerCase()} == "localdate" || ${column.javaType.toLowerCase()} == "localdatetime") - ${column.javaField}: Date + ${column.javaField}: Date // ${column.columnComment} #else - ${column.javaField}: ${column.javaType.toLowerCase()} + ${column.javaField}: ${column.javaType.toLowerCase()} // ${column.columnComment} #end #end #end diff --git a/yudao-module-infra/yudao-module-infra-biz/src/main/resources/codegen/vue3/views/form.vue.vm b/yudao-module-infra/yudao-module-infra-biz/src/main/resources/codegen/vue3/views/form.vue.vm index 14a72d264..8e3596b4f 100644 --- a/yudao-module-infra/yudao-module-infra-biz/src/main/resources/codegen/vue3/views/form.vue.vm +++ b/yudao-module-infra/yudao-module-infra-biz/src/main/resources/codegen/vue3/views/form.vue.vm @@ -244,7 +244,7 @@ const submitForm = async () => { // 提交请求 formLoading.value = true try { - const data = formData.value as unknown as ${simpleClassName}Api.${simpleClassName}VO + const data = formData.value as unknown as ${simpleClassName}VO ## 特殊:主子表专属逻辑 #if ( $table.templateType == 10 || $table.templateType == 12 ) #if ( $subTables && $subTables.size() > 0 ) diff --git a/yudao-module-infra/yudao-module-infra-biz/src/main/resources/codegen/vue3/views/index.vue.vm b/yudao-module-infra/yudao-module-infra-biz/src/main/resources/codegen/vue3/views/index.vue.vm index a76dbaa82..361d379fa 100644 --- a/yudao-module-infra/yudao-module-infra-biz/src/main/resources/codegen/vue3/views/index.vue.vm +++ b/yudao-module-infra/yudao-module-infra-biz/src/main/resources/codegen/vue3/views/index.vue.vm @@ -259,8 +259,7 @@ const loading = ref(true) // 列表的加载中 const list = ref<${simpleClassName}VO[]>([]) // 列表的数据 ## 特殊:树表专属逻辑(树不需要分页接口) #if ( $table.templateType != 2 ) -// 列表的总页数 -const total = ref(0) +const total = ref(0) // 列表的总页数 #end const queryParams = reactive({ ## 特殊:树表专属逻辑(树不需要分页接口) From db79926c31b9756dc40dc754a1ab62fdc764b3c7 Mon Sep 17 00:00:00 2001 From: YunaiV Date: Mon, 5 Feb 2024 19:24:33 +0800 Subject: [PATCH 076/119] =?UTF-8?q?=E2=9C=A8=20ERP=EF=BC=9A=E5=AE=8C?= =?UTF-8?q?=E6=88=90=20stock=20=E4=BA=A7=E5=93=81=E5=BA=93=E5=AD=98?= =?UTF-8?q?=E3=80=81=E5=BA=93=E5=AD=98=E6=98=8E=E7=BB=86=E7=9A=84=E5=AE=9E?= =?UTF-8?q?=E7=8E=B0?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../yudao/module/erp/ErrorCodeConstants.java | 32 ------ .../module/erp/enums/DictTypeConstants.java | 2 + .../module/erp/enums/ErrorCodeConstants.java | 24 +++- .../stock/ErpStockRecordBizTypeEnum.java | 41 +++++++ .../admin/product/ErpProductController.java | 58 ++++------ ...ageReqVO.java => ErpProductPageReqVO.java} | 4 +- ...oductRespVO.java => ErpProductRespVO.java} | 2 +- .../admin/stock/ErpStockController.java | 97 ++++++++++++++++ .../admin/stock/ErpStockRecordController.java | 105 ++++++++++++++++++ .../admin/stock/ErpWarehouseController.java | 8 ++ .../stock/vo/stock/ErpStockPageReqVO.java | 21 ++++ .../admin/stock/vo/stock/ErpStockRespVO.java | 49 ++++++++ .../stockrecord/ErpStockRecordPageReqVO.java | 36 ++++++ .../vo/stockrecord/ErpStockRecordRespVO.java | 87 +++++++++++++++ .../erp/dal/dataobject/stock/ErpStockDO.java | 49 ++++++++ .../dataobject/stock/ErpStockRecordDO.java | 81 ++++++++++++++ .../dal/mysql/product/ErpProductMapper.java | 10 +- .../erp/dal/mysql/stock/ErpStockMapper.java | 25 +++++ .../dal/mysql/stock/ErpStockRecordMapper.java | 28 +++++ .../dal/mysql/stock/ErpWarehouseMapper.java | 6 + .../ErpProductCategoryServiceImpl.java | 2 +- .../service/product/ErpProductService.java | 45 +++++++- .../product/ErpProductServiceImpl.java | 62 +++++++++-- .../product/ErpProductUnitServiceImpl.java | 2 +- .../service/stock/ErpStockRecordService.java | 30 +++++ .../stock/ErpStockRecordServiceImpl.java | 33 ++++++ .../erp/service/stock/ErpStockService.java | 30 +++++ .../service/stock/ErpStockServiceImpl.java | 33 ++++++ .../service/stock/ErpWarehouseService.java | 32 ++++++ .../stock/ErpWarehouseServiceImpl.java | 15 ++- .../product/ProductServiceImplTest.java | 6 +- 31 files changed, 954 insertions(+), 101 deletions(-) delete mode 100644 yudao-module-erp/yudao-module-erp-api/src/main/java/cn/iocoder/yudao/module/erp/ErrorCodeConstants.java create mode 100644 yudao-module-erp/yudao-module-erp-api/src/main/java/cn/iocoder/yudao/module/erp/enums/stock/ErpStockRecordBizTypeEnum.java rename yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/controller/admin/product/vo/product/{ProductPageReqVO.java => ErpProductPageReqVO.java} (89%) rename yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/controller/admin/product/vo/product/{ProductRespVO.java => ErpProductRespVO.java} (98%) create mode 100644 yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/controller/admin/stock/ErpStockController.java create mode 100644 yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/controller/admin/stock/ErpStockRecordController.java create mode 100644 yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/controller/admin/stock/vo/stock/ErpStockPageReqVO.java create mode 100644 yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/controller/admin/stock/vo/stock/ErpStockRespVO.java create mode 100644 yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/controller/admin/stock/vo/stockrecord/ErpStockRecordPageReqVO.java create mode 100644 yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/controller/admin/stock/vo/stockrecord/ErpStockRecordRespVO.java create mode 100644 yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/dal/dataobject/stock/ErpStockDO.java create mode 100644 yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/dal/dataobject/stock/ErpStockRecordDO.java create mode 100644 yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/dal/mysql/stock/ErpStockMapper.java create mode 100644 yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/dal/mysql/stock/ErpStockRecordMapper.java create mode 100644 yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/service/stock/ErpStockRecordService.java create mode 100644 yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/service/stock/ErpStockRecordServiceImpl.java create mode 100644 yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/service/stock/ErpStockService.java create mode 100644 yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/service/stock/ErpStockServiceImpl.java diff --git a/yudao-module-erp/yudao-module-erp-api/src/main/java/cn/iocoder/yudao/module/erp/ErrorCodeConstants.java b/yudao-module-erp/yudao-module-erp-api/src/main/java/cn/iocoder/yudao/module/erp/ErrorCodeConstants.java deleted file mode 100644 index f174ed854..000000000 --- a/yudao-module-erp/yudao-module-erp-api/src/main/java/cn/iocoder/yudao/module/erp/ErrorCodeConstants.java +++ /dev/null @@ -1,32 +0,0 @@ -package cn.iocoder.yudao.module.erp; - -import cn.iocoder.yudao.framework.common.exception.ErrorCode; - -/** - * ERP 错误码枚举类 - *

- * erp 系统,使用 1-030-000-000 段 - */ -public interface ErrorCodeConstants { - - // ========== ERP 仓库 1-030-400-000 ========== - ErrorCode WAREHOUSE_NOT_EXISTS = new ErrorCode(1_030_400_000, "仓库不存在"); - - // ========== ERP 产品 1-030-500-000 ========== - ErrorCode PRODUCT_NOT_EXISTS = new ErrorCode(1_030_500_000, "产品不存在"); - - // ========== ERP 产品分类 1-030-501-000 ========== - ErrorCode PRODUCT_CATEGORY_NOT_EXISTS = new ErrorCode(1_030_501_000, "产品分类不存在"); - ErrorCode PRODUCT_CATEGORY_EXITS_CHILDREN = new ErrorCode(1_030_501_001, "存在存在子产品分类,无法删除"); - ErrorCode PRODUCT_CATEGORY_PARENT_NOT_EXITS = new ErrorCode(1_030_501_002,"父级产品分类不存在"); - ErrorCode PRODUCT_CATEGORY_PARENT_ERROR = new ErrorCode(1_030_501_003, "不能设置自己为父产品分类"); - ErrorCode PRODUCT_CATEGORY_NAME_DUPLICATE = new ErrorCode(1_030_501_004, "已经存在该分类名称的产品分类"); - ErrorCode PRODUCT_CATEGORY_PARENT_IS_CHILD = new ErrorCode(1_030_501_005, "不能设置自己的子分类为父分类"); - ErrorCode PRODUCT_CATEGORY_EXITS_PRODUCT = new ErrorCode(1_030_502_002, "存在产品使用该分类,无法删除"); - - // ========== ERP 产品单位 1-030-502-000 ========== - ErrorCode PRODUCT_UNIT_NOT_EXISTS = new ErrorCode(1_030_502_000, "产品单位不存在"); - ErrorCode PRODUCT_UNIT_NAME_DUPLICATE = new ErrorCode(1_030_502_001, "已存在该名字的产品单位"); - ErrorCode PRODUCT_UNIT_EXITS_PRODUCT = new ErrorCode(1_030_502_002, "存在产品使用该单位,无法删除"); - -} diff --git a/yudao-module-erp/yudao-module-erp-api/src/main/java/cn/iocoder/yudao/module/erp/enums/DictTypeConstants.java b/yudao-module-erp/yudao-module-erp-api/src/main/java/cn/iocoder/yudao/module/erp/enums/DictTypeConstants.java index 87b498543..af7033895 100644 --- a/yudao-module-erp/yudao-module-erp-api/src/main/java/cn/iocoder/yudao/module/erp/enums/DictTypeConstants.java +++ b/yudao-module-erp/yudao-module-erp-api/src/main/java/cn/iocoder/yudao/module/erp/enums/DictTypeConstants.java @@ -7,4 +7,6 @@ package cn.iocoder.yudao.module.erp.enums; */ public interface DictTypeConstants { + String STOCK_RECORD_BIZ_TYPE = "erp_stock_record_biz_type"; // 库存明细的业务类型 + } diff --git a/yudao-module-erp/yudao-module-erp-api/src/main/java/cn/iocoder/yudao/module/erp/enums/ErrorCodeConstants.java b/yudao-module-erp/yudao-module-erp-api/src/main/java/cn/iocoder/yudao/module/erp/enums/ErrorCodeConstants.java index 7b11fa0a5..51cae4ad9 100644 --- a/yudao-module-erp/yudao-module-erp-api/src/main/java/cn/iocoder/yudao/module/erp/enums/ErrorCodeConstants.java +++ b/yudao-module-erp/yudao-module-erp-api/src/main/java/cn/iocoder/yudao/module/erp/enums/ErrorCodeConstants.java @@ -9,7 +9,27 @@ import cn.iocoder.yudao.framework.common.exception.ErrorCode; */ public interface ErrorCodeConstants { - // ========== 销售订单(1-030-000-000) ========== - ErrorCode SALE_ORDER_NOT_EXISTS = new ErrorCode(1_030_000_000, "销售订单不存在"); + // ========== 销售订单(1-020-000-000) ========== + ErrorCode SALE_ORDER_NOT_EXISTS = new ErrorCode(1_020_000_000, "销售订单不存在"); + + // ========== ERP 仓库 1-030-400-000 ========== + ErrorCode WAREHOUSE_NOT_EXISTS = new ErrorCode(1_030_400_000, "仓库不存在"); + + // ========== ERP 产品 1-030-500-000 ========== + ErrorCode PRODUCT_NOT_EXISTS = new ErrorCode(1_030_500_000, "产品不存在"); + + // ========== ERP 产品分类 1-030-501-000 ========== + ErrorCode PRODUCT_CATEGORY_NOT_EXISTS = new ErrorCode(1_030_501_000, "产品分类不存在"); + ErrorCode PRODUCT_CATEGORY_EXITS_CHILDREN = new ErrorCode(1_030_501_001, "存在存在子产品分类,无法删除"); + ErrorCode PRODUCT_CATEGORY_PARENT_NOT_EXITS = new ErrorCode(1_030_501_002,"父级产品分类不存在"); + ErrorCode PRODUCT_CATEGORY_PARENT_ERROR = new ErrorCode(1_030_501_003, "不能设置自己为父产品分类"); + ErrorCode PRODUCT_CATEGORY_NAME_DUPLICATE = new ErrorCode(1_030_501_004, "已经存在该分类名称的产品分类"); + ErrorCode PRODUCT_CATEGORY_PARENT_IS_CHILD = new ErrorCode(1_030_501_005, "不能设置自己的子分类为父分类"); + ErrorCode PRODUCT_CATEGORY_EXITS_PRODUCT = new ErrorCode(1_030_502_002, "存在产品使用该分类,无法删除"); + + // ========== ERP 产品单位 1-030-502-000 ========== + ErrorCode PRODUCT_UNIT_NOT_EXISTS = new ErrorCode(1_030_502_000, "产品单位不存在"); + ErrorCode PRODUCT_UNIT_NAME_DUPLICATE = new ErrorCode(1_030_502_001, "已存在该名字的产品单位"); + ErrorCode PRODUCT_UNIT_EXITS_PRODUCT = new ErrorCode(1_030_502_002, "存在产品使用该单位,无法删除"); } diff --git a/yudao-module-erp/yudao-module-erp-api/src/main/java/cn/iocoder/yudao/module/erp/enums/stock/ErpStockRecordBizTypeEnum.java b/yudao-module-erp/yudao-module-erp-api/src/main/java/cn/iocoder/yudao/module/erp/enums/stock/ErpStockRecordBizTypeEnum.java new file mode 100644 index 000000000..fb16934d9 --- /dev/null +++ b/yudao-module-erp/yudao-module-erp-api/src/main/java/cn/iocoder/yudao/module/erp/enums/stock/ErpStockRecordBizTypeEnum.java @@ -0,0 +1,41 @@ +package cn.iocoder.yudao.module.erp.enums.stock; + +import cn.iocoder.yudao.framework.common.core.IntArrayValuable; +import lombok.Getter; +import lombok.RequiredArgsConstructor; + +import java.util.Arrays; + +/** + * ERP 库存明细 - 业务类型枚举 + * + * @author 芋道源码 + */ +@RequiredArgsConstructor +@Getter +public enum ErpStockRecordBizTypeEnum implements IntArrayValuable { + + OTHER_IN(10, "其它入库"), + OTHER_IN_CANCEL(11, "其它入库(作废)"), + + OTHER_OUT(20, "其它出库"), + OTHER_OUT_CANCEL(21, "其它出库(作废)"), + ; + + public static final int[] ARRAYS = Arrays.stream(values()).mapToInt(ErpStockRecordBizTypeEnum::getType).toArray(); + + /** + * 类型 + */ + private final Integer type; + /** + * 名字 + */ + private final String name; + + @Override + public int[] array() { + return ARRAYS; + } + +} diff --git a/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/controller/admin/product/ErpProductController.java b/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/controller/admin/product/ErpProductController.java index 30135a6fe..63977890c 100644 --- a/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/controller/admin/product/ErpProductController.java +++ b/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/controller/admin/product/ErpProductController.java @@ -1,22 +1,17 @@ package cn.iocoder.yudao.module.erp.controller.admin.product; -import cn.hutool.core.collection.CollUtil; +import cn.iocoder.yudao.framework.common.enums.CommonStatusEnum; import cn.iocoder.yudao.framework.common.pojo.CommonResult; import cn.iocoder.yudao.framework.common.pojo.PageParam; import cn.iocoder.yudao.framework.common.pojo.PageResult; -import cn.iocoder.yudao.framework.common.util.collection.MapUtils; import cn.iocoder.yudao.framework.common.util.object.BeanUtils; import cn.iocoder.yudao.framework.excel.core.util.ExcelUtils; import cn.iocoder.yudao.framework.operatelog.core.annotations.OperateLog; -import cn.iocoder.yudao.module.erp.controller.admin.product.vo.product.ProductPageReqVO; -import cn.iocoder.yudao.module.erp.controller.admin.product.vo.product.ProductRespVO; +import cn.iocoder.yudao.module.erp.controller.admin.product.vo.product.ErpProductPageReqVO; +import cn.iocoder.yudao.module.erp.controller.admin.product.vo.product.ErpProductRespVO; import cn.iocoder.yudao.module.erp.controller.admin.product.vo.product.ProductSaveReqVO; -import cn.iocoder.yudao.module.erp.dal.dataobject.product.ErpProductCategoryDO; import cn.iocoder.yudao.module.erp.dal.dataobject.product.ErpProductDO; -import cn.iocoder.yudao.module.erp.dal.dataobject.product.ErpProductUnitDO; -import cn.iocoder.yudao.module.erp.service.product.ErpProductCategoryService; import cn.iocoder.yudao.module.erp.service.product.ErpProductService; -import cn.iocoder.yudao.module.erp.service.product.ErpProductUnitService; import io.swagger.v3.oas.annotations.Operation; import io.swagger.v3.oas.annotations.Parameter; import io.swagger.v3.oas.annotations.tags.Tag; @@ -28,10 +23,9 @@ import org.springframework.validation.annotation.Validated; import org.springframework.web.bind.annotation.*; import java.io.IOException; -import java.util.Map; +import java.util.List; import static cn.iocoder.yudao.framework.common.pojo.CommonResult.success; -import static cn.iocoder.yudao.framework.common.util.collection.CollectionUtils.convertSet; import static cn.iocoder.yudao.framework.operatelog.core.enums.OperateTypeEnum.EXPORT; @Tag(name = "管理后台 - ERP 产品") @@ -42,10 +36,6 @@ public class ErpProductController { @Resource private ErpProductService productService; - @Resource - private ErpProductCategoryService productCategoryService; - @Resource - private ErpProductUnitService productUnitService; @PostMapping("/create") @Operation(summary = "创建产品") @@ -75,46 +65,36 @@ public class ErpProductController { @Operation(summary = "获得产品") @Parameter(name = "id", description = "编号", required = true, example = "1024") @PreAuthorize("@ss.hasPermission('erp:product:query')") - public CommonResult getProduct(@RequestParam("id") Long id) { + public CommonResult getProduct(@RequestParam("id") Long id) { ErpProductDO product = productService.getProduct(id); - return success(BeanUtils.toBean(product, ProductRespVO.class)); + return success(BeanUtils.toBean(product, ErpProductRespVO.class)); } @GetMapping("/page") @Operation(summary = "获得产品分页") @PreAuthorize("@ss.hasPermission('erp:product:query')") - public CommonResult> getProductPage(@Valid ProductPageReqVO pageReqVO) { - PageResult pageResult = productService.getProductPage(pageReqVO); - return success(buildProductDetailPage(pageResult)); + public CommonResult> getProductPage(@Valid ErpProductPageReqVO pageReqVO) { + return success(productService.getProductVOPage(pageReqVO)); + } + + @GetMapping("/simple-list") + @Operation(summary = "获得产品精简列表", description = "只包含被开启的产品,主要用于前端的下拉选项") + public CommonResult> getProductSimpleList() { + List list = productService.getProductListByStatus(CommonStatusEnum.ENABLE.getStatus()); + return success(BeanUtils.toBean(list, ErpProductRespVO.class)); } @GetMapping("/export-excel") @Operation(summary = "导出产品 Excel") @PreAuthorize("@ss.hasPermission('erp:product:export')") @OperateLog(type = EXPORT) - public void exportProductExcel(@Valid ProductPageReqVO pageReqVO, + public void exportProductExcel(@Valid ErpProductPageReqVO pageReqVO, HttpServletResponse response) throws IOException { pageReqVO.setPageSize(PageParam.PAGE_SIZE_NONE); - PageResult pageResult = productService.getProductPage(pageReqVO); + PageResult pageResult = productService.getProductVOPage(pageReqVO); // 导出 Excel - ExcelUtils.write(response, "产品.xls", "数据", ProductRespVO.class, - buildProductDetailPage(pageResult).getList()); - } - - private PageResult buildProductDetailPage(PageResult pageResult) { - if (CollUtil.isEmpty(pageResult.getList())) { - return PageResult.empty(pageResult.getTotal()); - } - Map categoryMap = productCategoryService.getProductCategoryMap( - convertSet(pageResult.getList(), ErpProductDO::getCategoryId)); - Map unitMap = productUnitService.getProductUnitMap( - convertSet(pageResult.getList(), ErpProductDO::getUnitId)); - return BeanUtils.toBean(pageResult, ProductRespVO.class, product -> { - MapUtils.findAndThen(categoryMap, product.getCategoryId(), - category -> product.setCategoryName(category.getName())); - MapUtils.findAndThen(unitMap, product.getUnitId(), - unit -> product.setUnitName(unit.getName())); - }); + ExcelUtils.write(response, "产品.xls", "数据", ErpProductRespVO.class, + pageResult.getList()); } } \ No newline at end of file diff --git a/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/controller/admin/product/vo/product/ProductPageReqVO.java b/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/controller/admin/product/vo/product/ErpProductPageReqVO.java similarity index 89% rename from yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/controller/admin/product/vo/product/ProductPageReqVO.java rename to yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/controller/admin/product/vo/product/ErpProductPageReqVO.java index eb560603b..de4f8142a 100644 --- a/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/controller/admin/product/vo/product/ProductPageReqVO.java +++ b/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/controller/admin/product/vo/product/ErpProductPageReqVO.java @@ -1,10 +1,8 @@ package cn.iocoder.yudao.module.erp.controller.admin.product.vo.product; import lombok.*; -import java.util.*; import io.swagger.v3.oas.annotations.media.Schema; import cn.iocoder.yudao.framework.common.pojo.PageParam; -import java.math.BigDecimal; import org.springframework.format.annotation.DateTimeFormat; import java.time.LocalDateTime; @@ -14,7 +12,7 @@ import static cn.iocoder.yudao.framework.common.util.date.DateUtils.FORMAT_YEAR_ @Data @EqualsAndHashCode(callSuper = true) @ToString(callSuper = true) -public class ProductPageReqVO extends PageParam { +public class ErpProductPageReqVO extends PageParam { @Schema(description = "产品名称", example = "李四") private String name; diff --git a/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/controller/admin/product/vo/product/ProductRespVO.java b/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/controller/admin/product/vo/product/ErpProductRespVO.java similarity index 98% rename from yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/controller/admin/product/vo/product/ProductRespVO.java rename to yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/controller/admin/product/vo/product/ErpProductRespVO.java index f6f255c09..9be9bc255 100644 --- a/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/controller/admin/product/vo/product/ProductRespVO.java +++ b/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/controller/admin/product/vo/product/ErpProductRespVO.java @@ -11,7 +11,7 @@ import java.time.LocalDateTime; @Schema(description = "管理后台 - ERP 产品 Response VO") @Data @ExcelIgnoreUnannotated -public class ProductRespVO { +public class ErpProductRespVO { @Schema(description = "产品编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "15672") @ExcelProperty("产品编号") diff --git a/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/controller/admin/stock/ErpStockController.java b/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/controller/admin/stock/ErpStockController.java new file mode 100644 index 000000000..18bf063d3 --- /dev/null +++ b/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/controller/admin/stock/ErpStockController.java @@ -0,0 +1,97 @@ +package cn.iocoder.yudao.module.erp.controller.admin.stock; + +import cn.hutool.core.collection.CollUtil; +import cn.iocoder.yudao.framework.common.pojo.CommonResult; +import cn.iocoder.yudao.framework.common.pojo.PageParam; +import cn.iocoder.yudao.framework.common.pojo.PageResult; +import cn.iocoder.yudao.framework.common.util.collection.MapUtils; +import cn.iocoder.yudao.framework.common.util.object.BeanUtils; +import cn.iocoder.yudao.framework.excel.core.util.ExcelUtils; +import cn.iocoder.yudao.framework.operatelog.core.annotations.OperateLog; +import cn.iocoder.yudao.module.erp.controller.admin.product.vo.product.ErpProductRespVO; +import cn.iocoder.yudao.module.erp.controller.admin.stock.vo.stock.ErpStockPageReqVO; +import cn.iocoder.yudao.module.erp.controller.admin.stock.vo.stock.ErpStockRespVO; +import cn.iocoder.yudao.module.erp.dal.dataobject.stock.ErpStockDO; +import cn.iocoder.yudao.module.erp.dal.dataobject.stock.ErpWarehouseDO; +import cn.iocoder.yudao.module.erp.service.product.ErpProductService; +import cn.iocoder.yudao.module.erp.service.stock.ErpStockService; +import cn.iocoder.yudao.module.erp.service.stock.ErpWarehouseService; +import io.swagger.v3.oas.annotations.Operation; +import io.swagger.v3.oas.annotations.Parameter; +import io.swagger.v3.oas.annotations.tags.Tag; +import jakarta.annotation.Resource; +import jakarta.servlet.http.HttpServletResponse; +import jakarta.validation.Valid; +import org.springframework.security.access.prepost.PreAuthorize; +import org.springframework.validation.annotation.Validated; +import org.springframework.web.bind.annotation.GetMapping; +import org.springframework.web.bind.annotation.RequestMapping; +import org.springframework.web.bind.annotation.RequestParam; +import org.springframework.web.bind.annotation.RestController; + +import java.io.IOException; +import java.util.List; +import java.util.Map; + +import static cn.iocoder.yudao.framework.common.pojo.CommonResult.success; +import static cn.iocoder.yudao.framework.common.util.collection.CollectionUtils.convertSet; +import static cn.iocoder.yudao.framework.operatelog.core.enums.OperateTypeEnum.EXPORT; + +@Tag(name = "管理后台 - ERP 产品库存") +@RestController +@RequestMapping("/erp/stock") +@Validated +public class ErpStockController { + + @Resource + private ErpStockService stockService; + @Resource + private ErpProductService productService; + @Resource + private ErpWarehouseService warehouseService; + + @GetMapping("/get") + @Operation(summary = "获得产品库存") + @Parameter(name = "id", description = "编号", required = true, example = "1024") + @PreAuthorize("@ss.hasPermission('erp:stock:query')") + public CommonResult getStock(@RequestParam("id") Long id) { + ErpStockDO stock = stockService.getStock(id); + return success(BeanUtils.toBean(stock, ErpStockRespVO.class)); + } + + @GetMapping("/page") + @Operation(summary = "获得产品库存分页") + @PreAuthorize("@ss.hasPermission('erp:stock:query')") + public CommonResult> getStockPage(@Valid ErpStockPageReqVO pageReqVO) { + PageResult pageResult = stockService.getStockPage(pageReqVO); + return success(buildStockVOPageResult(pageResult)); + } + + @GetMapping("/export-excel") + @Operation(summary = "导出产品库存 Excel") + @PreAuthorize("@ss.hasPermission('erp:stock:export')") + @OperateLog(type = EXPORT) + public void exportStockExcel(@Valid ErpStockPageReqVO pageReqVO, + HttpServletResponse response) throws IOException { + pageReqVO.setPageSize(PageParam.PAGE_SIZE_NONE); + List list = buildStockVOPageResult(stockService.getStockPage(pageReqVO)).getList(); + // 导出 Excel + ExcelUtils.write(response, "产品库存.xls", "数据", ErpStockRespVO.class, list); + } + + private PageResult buildStockVOPageResult(PageResult pageResult) { + if (CollUtil.isEmpty(pageResult.getList())) { + return PageResult.empty(pageResult.getTotal()); + } + Map productMap = productService.getProductVOMap( + convertSet(pageResult.getList(), ErpStockDO::getProductId)); + Map warehouseMap = warehouseService.getWarehouseMap( + convertSet(pageResult.getList(), ErpStockDO::getWarehouseId)); + return BeanUtils.toBean(pageResult, ErpStockRespVO.class, stock -> { + MapUtils.findAndThen(productMap, stock.getProductId(), product -> stock.setProductName(product.getName()) + .setCategoryName(product.getCategoryName()).setUnitName(product.getUnitName())); + MapUtils.findAndThen(warehouseMap, stock.getWarehouseId(), warehouse -> stock.setWarehouseName(warehouse.getName())); + }); + } + +} \ No newline at end of file diff --git a/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/controller/admin/stock/ErpStockRecordController.java b/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/controller/admin/stock/ErpStockRecordController.java new file mode 100644 index 000000000..e92856378 --- /dev/null +++ b/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/controller/admin/stock/ErpStockRecordController.java @@ -0,0 +1,105 @@ +package cn.iocoder.yudao.module.erp.controller.admin.stock; + +import cn.hutool.core.collection.CollUtil; +import cn.iocoder.yudao.framework.common.pojo.CommonResult; +import cn.iocoder.yudao.framework.common.pojo.PageParam; +import cn.iocoder.yudao.framework.common.pojo.PageResult; +import cn.iocoder.yudao.framework.common.util.collection.MapUtils; +import cn.iocoder.yudao.framework.common.util.object.BeanUtils; +import cn.iocoder.yudao.framework.excel.core.util.ExcelUtils; +import cn.iocoder.yudao.framework.operatelog.core.annotations.OperateLog; +import cn.iocoder.yudao.module.erp.controller.admin.product.vo.product.ErpProductRespVO; +import cn.iocoder.yudao.module.erp.controller.admin.stock.vo.stockrecord.ErpStockRecordPageReqVO; +import cn.iocoder.yudao.module.erp.controller.admin.stock.vo.stockrecord.ErpStockRecordRespVO; +import cn.iocoder.yudao.module.erp.dal.dataobject.stock.ErpStockRecordDO; +import cn.iocoder.yudao.module.erp.dal.dataobject.stock.ErpWarehouseDO; +import cn.iocoder.yudao.module.erp.service.product.ErpProductService; +import cn.iocoder.yudao.module.erp.service.stock.ErpStockRecordService; +import cn.iocoder.yudao.module.erp.service.stock.ErpWarehouseService; +import cn.iocoder.yudao.module.system.api.user.AdminUserApi; +import cn.iocoder.yudao.module.system.api.user.dto.AdminUserRespDTO; +import io.swagger.v3.oas.annotations.Operation; +import io.swagger.v3.oas.annotations.Parameter; +import io.swagger.v3.oas.annotations.tags.Tag; +import jakarta.annotation.Resource; +import jakarta.servlet.http.HttpServletResponse; +import jakarta.validation.Valid; +import org.springframework.security.access.prepost.PreAuthorize; +import org.springframework.validation.annotation.Validated; +import org.springframework.web.bind.annotation.GetMapping; +import org.springframework.web.bind.annotation.RequestMapping; +import org.springframework.web.bind.annotation.RequestParam; +import org.springframework.web.bind.annotation.RestController; + +import java.io.IOException; +import java.util.List; +import java.util.Map; + +import static cn.iocoder.yudao.framework.common.pojo.CommonResult.success; +import static cn.iocoder.yudao.framework.common.util.collection.CollectionUtils.convertSet; +import static cn.iocoder.yudao.framework.operatelog.core.enums.OperateTypeEnum.EXPORT; + +@Tag(name = "管理后台 - ERP 产品库存明细") +@RestController +@RequestMapping("/erp/stock-record") +@Validated +public class ErpStockRecordController { + + @Resource + private ErpStockRecordService stockRecordService; + @Resource + private ErpProductService productService; + @Resource + private ErpWarehouseService warehouseService; + + @Resource + private AdminUserApi adminUserApi; + + @GetMapping("/get") + @Operation(summary = "获得产品库存明细") + @Parameter(name = "id", description = "编号", required = true, example = "1024") + @PreAuthorize("@ss.hasPermission('erp:stock-record:query')") + public CommonResult getStockRecord(@RequestParam("id") Long id) { + ErpStockRecordDO stockRecord = stockRecordService.getStockRecord(id); + return success(BeanUtils.toBean(stockRecord, ErpStockRecordRespVO.class)); + } + + @GetMapping("/page") + @Operation(summary = "获得产品库存明细分页") + @PreAuthorize("@ss.hasPermission('erp:stock-record:query')") + public CommonResult> getStockRecordPage(@Valid ErpStockRecordPageReqVO pageReqVO) { + PageResult pageResult = stockRecordService.getStockRecordPage(pageReqVO); + return success(buildStockRecrodVOPageResult(pageResult)); + } + + @GetMapping("/export-excel") + @Operation(summary = "导出产品库存明细 Excel") + @PreAuthorize("@ss.hasPermission('erp:stock-record:export')") + @OperateLog(type = EXPORT) + public void exportStockRecordExcel(@Valid ErpStockRecordPageReqVO pageReqVO, + HttpServletResponse response) throws IOException { + pageReqVO.setPageSize(PageParam.PAGE_SIZE_NONE); + List list = buildStockRecrodVOPageResult(stockRecordService.getStockRecordPage(pageReqVO)).getList(); + // 导出 Excel + ExcelUtils.write(response, "产品库存明细.xls", "数据", ErpStockRecordRespVO.class, list); + } + + private PageResult buildStockRecrodVOPageResult(PageResult pageResult) { + if (CollUtil.isEmpty(pageResult.getList())) { + return PageResult.empty(pageResult.getTotal()); + } + Map productMap = productService.getProductVOMap( + convertSet(pageResult.getList(), ErpStockRecordDO::getProductId)); + Map warehouseMap = warehouseService.getWarehouseMap( + convertSet(pageResult.getList(), ErpStockRecordDO::getWarehouseId)); + Map userMap = adminUserApi.getUserMap( + convertSet(pageResult.getList(), erpStockRecordDO -> Long.parseLong(erpStockRecordDO.getCreator()))); + return BeanUtils.toBean(pageResult, ErpStockRecordRespVO.class, stock -> { + MapUtils.findAndThen(productMap, stock.getProductId(), product -> stock.setProductName(product.getName()) + .setCategoryName(product.getCategoryName()).setUnitName(product.getUnitName())); + MapUtils.findAndThen(warehouseMap, stock.getWarehouseId(), warehouse -> stock.setWarehouseName(warehouse.getName())); + MapUtils.findAndThen(userMap, Long.parseLong(stock.getCreator()), user -> stock.setCreatorName(user.getNickname())); + }); + } + +} \ No newline at end of file diff --git a/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/controller/admin/stock/ErpWarehouseController.java b/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/controller/admin/stock/ErpWarehouseController.java index 8877780d8..32c33075d 100644 --- a/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/controller/admin/stock/ErpWarehouseController.java +++ b/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/controller/admin/stock/ErpWarehouseController.java @@ -1,5 +1,6 @@ package cn.iocoder.yudao.module.erp.controller.admin.stock; +import cn.iocoder.yudao.framework.common.enums.CommonStatusEnum; import cn.iocoder.yudao.framework.common.pojo.CommonResult; import cn.iocoder.yudao.framework.common.pojo.PageParam; import cn.iocoder.yudao.framework.common.pojo.PageResult; @@ -90,6 +91,13 @@ public class ErpWarehouseController { return success(BeanUtils.toBean(pageResult, ErpWarehouseRespVO.class)); } + @GetMapping("/simple-list") + @Operation(summary = "获得仓库精简列表", description = "只包含被开启的仓库,主要用于前端的下拉选项") + public CommonResult> getWarehouseSimpleList() { + List list = warehouseService.getWarehouseListByStatus(CommonStatusEnum.ENABLE.getStatus()); + return success(BeanUtils.toBean(list, ErpWarehouseRespVO.class)); + } + @GetMapping("/export-excel") @Operation(summary = "导出仓库 Excel") @PreAuthorize("@ss.hasPermission('erp:warehouse:export')") diff --git a/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/controller/admin/stock/vo/stock/ErpStockPageReqVO.java b/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/controller/admin/stock/vo/stock/ErpStockPageReqVO.java new file mode 100644 index 000000000..f7f3fa343 --- /dev/null +++ b/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/controller/admin/stock/vo/stock/ErpStockPageReqVO.java @@ -0,0 +1,21 @@ +package cn.iocoder.yudao.module.erp.controller.admin.stock.vo.stock; + +import cn.iocoder.yudao.framework.common.pojo.PageParam; +import io.swagger.v3.oas.annotations.media.Schema; +import lombok.Data; +import lombok.EqualsAndHashCode; +import lombok.ToString; + +@Schema(description = "管理后台 - ERP 库存分页 Request VO") +@Data +@EqualsAndHashCode(callSuper = true) +@ToString(callSuper = true) +public class ErpStockPageReqVO extends PageParam { + + @Schema(description = "产品编号", example = "19614") + private Long productId; + + @Schema(description = "仓库编号", example = "2802") + private Long warehouseId; + +} \ No newline at end of file diff --git a/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/controller/admin/stock/vo/stock/ErpStockRespVO.java b/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/controller/admin/stock/vo/stock/ErpStockRespVO.java new file mode 100644 index 000000000..06366a0dd --- /dev/null +++ b/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/controller/admin/stock/vo/stock/ErpStockRespVO.java @@ -0,0 +1,49 @@ +package cn.iocoder.yudao.module.erp.controller.admin.stock.vo.stock; + +import com.alibaba.excel.annotation.ExcelIgnoreUnannotated; +import com.alibaba.excel.annotation.ExcelProperty; +import io.swagger.v3.oas.annotations.media.Schema; +import lombok.Data; + +import java.math.BigDecimal; + +@Schema(description = "管理后台 - ERP 库存 Response VO") +@Data +@ExcelIgnoreUnannotated +public class ErpStockRespVO { + + @Schema(description = "编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "17086") + @ExcelProperty("编号") + private Long id; + + @Schema(description = "产品编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "19614") + private Long productId; + + @Schema(description = "仓库编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "2802") + private Long warehouseId; + + @Schema(description = "库存数量", requiredMode = Schema.RequiredMode.REQUIRED, example = "21935") + @ExcelProperty("库存数量") + private BigDecimal count; + + // ========== 产品信息 ========== + + @Schema(description = "产品名称", requiredMode = Schema.RequiredMode.REQUIRED, example = "苹果") + @ExcelProperty("产品名称") + private String productName; + + @Schema(description = "产品分类", requiredMode = Schema.RequiredMode.REQUIRED, example = "水果") + @ExcelProperty("产品分类") + private String categoryName; + + @Schema(description = "单位", requiredMode = Schema.RequiredMode.REQUIRED, example = "个") + @ExcelProperty("单位") + private String unitName; + + // ========== 仓库信息 ========== + + @Schema(description = "仓库名称", requiredMode = Schema.RequiredMode.REQUIRED, example = "李四") + @ExcelProperty("仓库名称") + private String warehouseName; + +} \ No newline at end of file diff --git a/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/controller/admin/stock/vo/stockrecord/ErpStockRecordPageReqVO.java b/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/controller/admin/stock/vo/stockrecord/ErpStockRecordPageReqVO.java new file mode 100644 index 000000000..b9030f821 --- /dev/null +++ b/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/controller/admin/stock/vo/stockrecord/ErpStockRecordPageReqVO.java @@ -0,0 +1,36 @@ +package cn.iocoder.yudao.module.erp.controller.admin.stock.vo.stockrecord; + +import cn.iocoder.yudao.framework.common.pojo.PageParam; +import io.swagger.v3.oas.annotations.media.Schema; +import lombok.Data; +import lombok.EqualsAndHashCode; +import lombok.ToString; +import org.springframework.format.annotation.DateTimeFormat; + +import java.time.LocalDateTime; + +import static cn.iocoder.yudao.framework.common.util.date.DateUtils.FORMAT_YEAR_MONTH_DAY_HOUR_MINUTE_SECOND; + +@Schema(description = "管理后台 - ERP 产品库存明细分页 Request VO") +@Data +@EqualsAndHashCode(callSuper = true) +@ToString(callSuper = true) +public class ErpStockRecordPageReqVO extends PageParam { + + @Schema(description = "产品编号", example = "10625") + private Long productId; + + @Schema(description = "仓库编号", example = "32407") + private Long warehouseId; + + @Schema(description = "业务类型", example = "10") + private Integer bizType; + + @Schema(description = "业务单号", example = "Z110") + private String bizNo; + + @Schema(description = "创建时间") + @DateTimeFormat(pattern = FORMAT_YEAR_MONTH_DAY_HOUR_MINUTE_SECOND) + private LocalDateTime[] createTime; + +} \ No newline at end of file diff --git a/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/controller/admin/stock/vo/stockrecord/ErpStockRecordRespVO.java b/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/controller/admin/stock/vo/stockrecord/ErpStockRecordRespVO.java new file mode 100644 index 000000000..0073fafba --- /dev/null +++ b/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/controller/admin/stock/vo/stockrecord/ErpStockRecordRespVO.java @@ -0,0 +1,87 @@ +package cn.iocoder.yudao.module.erp.controller.admin.stock.vo.stockrecord; + +import cn.iocoder.yudao.framework.excel.core.annotations.DictFormat; +import cn.iocoder.yudao.framework.excel.core.convert.DictConvert; +import cn.iocoder.yudao.module.erp.enums.DictTypeConstants; +import com.alibaba.excel.annotation.ExcelIgnoreUnannotated; +import com.alibaba.excel.annotation.ExcelProperty; +import io.swagger.v3.oas.annotations.media.Schema; +import lombok.Data; + +import java.math.BigDecimal; +import java.time.LocalDateTime; + +@Schema(description = "管理后台 - ERP 产品库存明细 Response VO") +@Data +@ExcelIgnoreUnannotated +public class ErpStockRecordRespVO { + + @Schema(description = "编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "18909") + @ExcelProperty("编号") + private Long id; + + @Schema(description = "产品编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "10625") + private Long productId; + + @Schema(description = "仓库编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "32407") + private Long warehouseId; + + @Schema(description = "出入库数量", requiredMode = Schema.RequiredMode.REQUIRED, example = "11084") + @ExcelProperty("出入库数量") + private BigDecimal count; + + @Schema(description = "总库存量", requiredMode = Schema.RequiredMode.REQUIRED, example = "4307") + @ExcelProperty("总库存量") + private BigDecimal totalCount; + + @Schema(description = "业务类型", requiredMode = Schema.RequiredMode.REQUIRED, example = "10") + @ExcelProperty(value = "业务类型", converter = DictConvert.class) + @DictFormat(DictTypeConstants.STOCK_RECORD_BIZ_TYPE) + private Integer bizType; + + @Schema(description = "业务编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "27093") + @ExcelProperty("业务编号") + private Long bizId; + + @Schema(description = "业务项编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "23516") + @ExcelProperty("业务项编号") + private Long bizItemId; + + @Schema(description = "业务单号", requiredMode = Schema.RequiredMode.REQUIRED, example = "Z110") + @ExcelProperty("业务单号") + private String bizNo; + + @Schema(description = "创建时间", requiredMode = Schema.RequiredMode.REQUIRED) + @ExcelProperty("创建时间") + private LocalDateTime createTime; + + @Schema(description = "创建人", requiredMode = Schema.RequiredMode.REQUIRED, example = "25682") + private String creator; + + // ========== 产品信息 ========== + + @Schema(description = "产品名称", requiredMode = Schema.RequiredMode.REQUIRED, example = "苹果") + @ExcelProperty("产品名称") + private String productName; + + @Schema(description = "产品分类", requiredMode = Schema.RequiredMode.REQUIRED, example = "水果") + @ExcelProperty("产品分类") + private String categoryName; + + @Schema(description = "单位", requiredMode = Schema.RequiredMode.REQUIRED, example = "个") + @ExcelProperty("单位") + private String unitName; + + // ========== 仓库信息 ========== + + @Schema(description = "仓库名称", requiredMode = Schema.RequiredMode.REQUIRED, example = "李四") + @ExcelProperty("仓库名称") + private String warehouseName; + + // ========== 用户信息 ========== + + @Schema(description = "创建人", requiredMode = Schema.RequiredMode.REQUIRED, example = "张三") + @ExcelProperty("创建人") + private String creatorName; + +} \ No newline at end of file diff --git a/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/dal/dataobject/stock/ErpStockDO.java b/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/dal/dataobject/stock/ErpStockDO.java new file mode 100644 index 000000000..558c6c6e5 --- /dev/null +++ b/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/dal/dataobject/stock/ErpStockDO.java @@ -0,0 +1,49 @@ +package cn.iocoder.yudao.module.erp.dal.dataobject.stock; + +import cn.iocoder.yudao.framework.mybatis.core.dataobject.BaseDO; +import cn.iocoder.yudao.module.erp.dal.dataobject.product.ErpProductDO; +import com.baomidou.mybatisplus.annotation.KeySequence; +import com.baomidou.mybatisplus.annotation.TableId; +import com.baomidou.mybatisplus.annotation.TableName; +import lombok.*; + +import java.math.BigDecimal; + +/** + * ERP 产品库存 DO + * + * @author 芋道源码 + */ +@TableName("erp_stock") +@KeySequence("erp_stock_seq") // 用于 Oracle、PostgreSQL、Kingbase、DB2、H2 数据库的主键自增。如果是 MySQL 等数据库,可不写。 +@Data +@EqualsAndHashCode(callSuper = true) +@ToString(callSuper = true) +@Builder +@NoArgsConstructor +@AllArgsConstructor +public class ErpStockDO extends BaseDO { + + /** + * 编号 + */ + @TableId + private Long id; + /** + * 产品编号 + * + * 关联 {@link ErpProductDO#getId()} + */ + private Long productId; + /** + * 仓库编号 + * + * 关联 {@link ErpWarehouseDO#getId()} + */ + private Long warehouseId; + /** + * 库存数量 + */ + private BigDecimal count; + +} \ No newline at end of file diff --git a/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/dal/dataobject/stock/ErpStockRecordDO.java b/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/dal/dataobject/stock/ErpStockRecordDO.java new file mode 100644 index 000000000..be010eb04 --- /dev/null +++ b/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/dal/dataobject/stock/ErpStockRecordDO.java @@ -0,0 +1,81 @@ +package cn.iocoder.yudao.module.erp.dal.dataobject.stock; + +import cn.iocoder.yudao.framework.mybatis.core.dataobject.BaseDO; +import cn.iocoder.yudao.module.erp.dal.dataobject.product.ErpProductDO; +import com.baomidou.mybatisplus.annotation.KeySequence; +import com.baomidou.mybatisplus.annotation.TableId; +import com.baomidou.mybatisplus.annotation.TableName; +import lombok.*; + +import java.math.BigDecimal; + +/** + * ERP 产品库存明细 DO + * + * @author 芋道源码 + */ +@TableName("erp_stock_record") +@KeySequence("erp_stock_record_seq") // 用于 Oracle、PostgreSQL、Kingbase、DB2、H2 数据库的主键自增。如果是 MySQL 等数据库,可不写。 +@Data +@EqualsAndHashCode(callSuper = true) +@ToString(callSuper = true) +@Builder +@NoArgsConstructor +@AllArgsConstructor +public class ErpStockRecordDO extends BaseDO { + + /** + * 编号 + */ + @TableId + private Long id; + /** + * 产品编号 + * + * 关联 {@link ErpProductDO#getId()} + */ + private Long productId; + /** + * 仓库编号 + * + * 关联 {@link ErpWarehouseDO#getId()} + */ + private Long warehouseId; + /** + * 出入库数量 + * + * 正数,表示入库;负数,表示出库 + */ + private BigDecimal count; + /** + * 总库存量 + * + * 出入库之后,目前的库存量 + */ + private BigDecimal totalCount; + /** + * 业务类型 + * + * 枚举 {@link cn.iocoder.yudao.module.erp.enums.stock.ErpStockRecordBizTypeEnum} + */ + private Integer bizType; + /** + * 业务编号 + * + * 例如说:TODO + */ + private Long bizId; + /** + * 业务项编号 + * + * 例如说:TODO + */ + private Long bizItemId; + /** + * 业务单号 + * + * 例如说:TODO + */ + private String bizNo; + +} \ No newline at end of file diff --git a/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/dal/mysql/product/ErpProductMapper.java b/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/dal/mysql/product/ErpProductMapper.java index 81bca5cf9..ff491fe22 100644 --- a/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/dal/mysql/product/ErpProductMapper.java +++ b/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/dal/mysql/product/ErpProductMapper.java @@ -3,10 +3,12 @@ package cn.iocoder.yudao.module.erp.dal.mysql.product; import cn.iocoder.yudao.framework.common.pojo.PageResult; import cn.iocoder.yudao.framework.mybatis.core.query.LambdaQueryWrapperX; import cn.iocoder.yudao.framework.mybatis.core.mapper.BaseMapperX; -import cn.iocoder.yudao.module.erp.controller.admin.product.vo.product.ProductPageReqVO; +import cn.iocoder.yudao.module.erp.controller.admin.product.vo.product.ErpProductPageReqVO; import cn.iocoder.yudao.module.erp.dal.dataobject.product.ErpProductDO; import org.apache.ibatis.annotations.Mapper; +import java.util.List; + /** * ERP 产品 Mapper * @@ -15,7 +17,7 @@ import org.apache.ibatis.annotations.Mapper; @Mapper public interface ErpProductMapper extends BaseMapperX { - default PageResult selectPage(ProductPageReqVO reqVO) { + default PageResult selectPage(ErpProductPageReqVO reqVO) { return selectPage(reqVO, new LambdaQueryWrapperX() .likeIfPresent(ErpProductDO::getName, reqVO.getName()) .eqIfPresent(ErpProductDO::getCategoryId, reqVO.getCategoryId()) @@ -31,4 +33,8 @@ public interface ErpProductMapper extends BaseMapperX { return selectCount(ErpProductDO::getUnitId, unitId); } + default List selectListByStatus(Integer status) { + return selectList(ErpProductDO::getStatus, status); + } + } \ No newline at end of file diff --git a/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/dal/mysql/stock/ErpStockMapper.java b/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/dal/mysql/stock/ErpStockMapper.java new file mode 100644 index 000000000..c634f9780 --- /dev/null +++ b/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/dal/mysql/stock/ErpStockMapper.java @@ -0,0 +1,25 @@ +package cn.iocoder.yudao.module.erp.dal.mysql.stock; + +import cn.iocoder.yudao.framework.common.pojo.PageResult; +import cn.iocoder.yudao.framework.mybatis.core.mapper.BaseMapperX; +import cn.iocoder.yudao.framework.mybatis.core.query.LambdaQueryWrapperX; +import cn.iocoder.yudao.module.erp.controller.admin.stock.vo.stock.ErpStockPageReqVO; +import cn.iocoder.yudao.module.erp.dal.dataobject.stock.ErpStockDO; +import org.apache.ibatis.annotations.Mapper; + +/** + * ERP 产品库存 Mapper + * + * @author 芋道源码 + */ +@Mapper +public interface ErpStockMapper extends BaseMapperX { + + default PageResult selectPage(ErpStockPageReqVO reqVO) { + return selectPage(reqVO, new LambdaQueryWrapperX() + .eqIfPresent(ErpStockDO::getProductId, reqVO.getProductId()) + .eqIfPresent(ErpStockDO::getWarehouseId, reqVO.getWarehouseId()) + .orderByDesc(ErpStockDO::getId)); + } + +} \ No newline at end of file diff --git a/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/dal/mysql/stock/ErpStockRecordMapper.java b/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/dal/mysql/stock/ErpStockRecordMapper.java new file mode 100644 index 000000000..6c5c48fd0 --- /dev/null +++ b/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/dal/mysql/stock/ErpStockRecordMapper.java @@ -0,0 +1,28 @@ +package cn.iocoder.yudao.module.erp.dal.mysql.stock; + +import cn.iocoder.yudao.framework.common.pojo.PageResult; +import cn.iocoder.yudao.framework.mybatis.core.mapper.BaseMapperX; +import cn.iocoder.yudao.framework.mybatis.core.query.LambdaQueryWrapperX; +import cn.iocoder.yudao.module.erp.controller.admin.stock.vo.stockrecord.ErpStockRecordPageReqVO; +import cn.iocoder.yudao.module.erp.dal.dataobject.stock.ErpStockRecordDO; +import org.apache.ibatis.annotations.Mapper; + +/** + * ERP 产品库存明细 Mapper + * + * @author 芋道源码 + */ +@Mapper +public interface ErpStockRecordMapper extends BaseMapperX { + + default PageResult selectPage(ErpStockRecordPageReqVO reqVO) { + return selectPage(reqVO, new LambdaQueryWrapperX() + .eqIfPresent(ErpStockRecordDO::getProductId, reqVO.getProductId()) + .eqIfPresent(ErpStockRecordDO::getWarehouseId, reqVO.getWarehouseId()) + .eqIfPresent(ErpStockRecordDO::getBizType, reqVO.getBizType()) + .likeIfPresent(ErpStockRecordDO::getBizNo, reqVO.getBizNo()) + .betweenIfPresent(ErpStockRecordDO::getCreateTime, reqVO.getCreateTime()) + .orderByDesc(ErpStockRecordDO::getId)); + } + +} \ No newline at end of file diff --git a/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/dal/mysql/stock/ErpWarehouseMapper.java b/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/dal/mysql/stock/ErpWarehouseMapper.java index 7d3bf0d3e..0442011f2 100644 --- a/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/dal/mysql/stock/ErpWarehouseMapper.java +++ b/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/dal/mysql/stock/ErpWarehouseMapper.java @@ -7,6 +7,8 @@ import cn.iocoder.yudao.module.erp.controller.admin.stock.vo.warehouse.ErpWareho import cn.iocoder.yudao.module.erp.dal.dataobject.stock.ErpWarehouseDO; import org.apache.ibatis.annotations.Mapper; +import java.util.List; + /** * ERP 仓库 Mapper * @@ -26,4 +28,8 @@ public interface ErpWarehouseMapper extends BaseMapperX { return selectOne(ErpWarehouseDO::getDefaultStatus, true); } + default List selectListByStatus(Integer status) { + return selectList(ErpWarehouseDO::getStatus, status); + } + } \ No newline at end of file diff --git a/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/service/product/ErpProductCategoryServiceImpl.java b/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/service/product/ErpProductCategoryServiceImpl.java index 28d8b3172..bad19a0ee 100644 --- a/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/service/product/ErpProductCategoryServiceImpl.java +++ b/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/service/product/ErpProductCategoryServiceImpl.java @@ -15,7 +15,7 @@ import java.util.List; import java.util.Objects; import static cn.iocoder.yudao.framework.common.exception.util.ServiceExceptionUtil.exception; -import static cn.iocoder.yudao.module.erp.ErrorCodeConstants.*; +import static cn.iocoder.yudao.module.erp.enums.ErrorCodeConstants.*; /** * ERP 产品分类 Service 实现类 diff --git a/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/service/product/ErpProductService.java b/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/service/product/ErpProductService.java index 3a2e08ce6..9fa18a073 100644 --- a/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/service/product/ErpProductService.java +++ b/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/service/product/ErpProductService.java @@ -1,10 +1,17 @@ package cn.iocoder.yudao.module.erp.service.product; -import cn.iocoder.yudao.module.erp.controller.admin.product.vo.product.ProductPageReqVO; -import cn.iocoder.yudao.module.erp.controller.admin.product.vo.product.ProductSaveReqVO; -import jakarta.validation.*; -import cn.iocoder.yudao.module.erp.dal.dataobject.product.ErpProductDO; import cn.iocoder.yudao.framework.common.pojo.PageResult; +import cn.iocoder.yudao.module.erp.controller.admin.product.vo.product.ErpProductPageReqVO; +import cn.iocoder.yudao.module.erp.controller.admin.product.vo.product.ErpProductRespVO; +import cn.iocoder.yudao.module.erp.controller.admin.product.vo.product.ProductSaveReqVO; +import cn.iocoder.yudao.module.erp.dal.dataobject.product.ErpProductDO; +import jakarta.validation.Valid; + +import java.util.Collection; +import java.util.List; +import java.util.Map; + +import static cn.iocoder.yudao.framework.common.util.collection.CollectionUtils.convertMap; /** * ERP 产品 Service 接口 @@ -44,12 +51,38 @@ public interface ErpProductService { ErpProductDO getProduct(Long id); /** - * 获得产品分页 + * 获得指定状态的产品列表 + * + * @param status 状态 + * @return 产品列表 + */ + List getProductListByStatus(Integer status); + + /** + * 获得产品 VO 列表 + * + * @param ids 编号数组 + * @return 产品 VO 列表 + */ + List getProductVOList(Collection ids); + + /** + * 获得产品 VO Map + * + * @param ids 编号数组 + * @return 产品 VO Map + */ + default Map getProductVOMap(Collection ids) { + return convertMap(getProductVOList(ids), ErpProductRespVO::getId); + } + + /** + * 获得产品 VO 分页 * * @param pageReqVO 分页查询 * @return 产品分页 */ - PageResult getProductPage(ProductPageReqVO pageReqVO); + PageResult getProductVOPage(ErpProductPageReqVO pageReqVO); /** * 基于产品分类编号,获得产品数量 diff --git a/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/service/product/ErpProductServiceImpl.java b/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/service/product/ErpProductServiceImpl.java index 3efb981e3..58c7b7c3b 100644 --- a/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/service/product/ErpProductServiceImpl.java +++ b/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/service/product/ErpProductServiceImpl.java @@ -1,19 +1,28 @@ package cn.iocoder.yudao.module.erp.service.product; -import cn.iocoder.yudao.module.erp.controller.admin.product.vo.product.ProductPageReqVO; +import cn.hutool.core.collection.CollUtil; +import cn.iocoder.yudao.framework.common.pojo.PageResult; +import cn.iocoder.yudao.framework.common.util.collection.MapUtils; +import cn.iocoder.yudao.framework.common.util.object.BeanUtils; +import cn.iocoder.yudao.module.erp.controller.admin.product.vo.product.ErpProductPageReqVO; +import cn.iocoder.yudao.module.erp.controller.admin.product.vo.product.ErpProductRespVO; import cn.iocoder.yudao.module.erp.controller.admin.product.vo.product.ProductSaveReqVO; -import org.springframework.stereotype.Service; +import cn.iocoder.yudao.module.erp.dal.dataobject.product.ErpProductCategoryDO; +import cn.iocoder.yudao.module.erp.dal.dataobject.product.ErpProductDO; +import cn.iocoder.yudao.module.erp.dal.dataobject.product.ErpProductUnitDO; +import cn.iocoder.yudao.module.erp.dal.mysql.product.ErpProductMapper; import jakarta.annotation.Resource; +import org.springframework.stereotype.Service; import org.springframework.validation.annotation.Validated; -import cn.iocoder.yudao.module.erp.dal.dataobject.product.ErpProductDO; -import cn.iocoder.yudao.framework.common.pojo.PageResult; -import cn.iocoder.yudao.framework.common.util.object.BeanUtils; - -import cn.iocoder.yudao.module.erp.dal.mysql.product.ErpProductMapper; +import java.util.Collection; +import java.util.Collections; +import java.util.List; +import java.util.Map; import static cn.iocoder.yudao.framework.common.exception.util.ServiceExceptionUtil.exception; -import static cn.iocoder.yudao.module.erp.ErrorCodeConstants.PRODUCT_NOT_EXISTS; +import static cn.iocoder.yudao.framework.common.util.collection.CollectionUtils.convertSet; +import static cn.iocoder.yudao.module.erp.enums.ErrorCodeConstants.PRODUCT_NOT_EXISTS; /** * ERP 产品 Service 实现类 @@ -27,6 +36,11 @@ public class ErpProductServiceImpl implements ErpProductService { @Resource private ErpProductMapper productMapper; + @Resource + private ErpProductCategoryService productCategoryService; + @Resource + private ErpProductUnitService productUnitService; + @Override public Long createProduct(ProductSaveReqVO createReqVO) { // 插入 @@ -65,8 +79,36 @@ public class ErpProductServiceImpl implements ErpProductService { } @Override - public PageResult getProductPage(ProductPageReqVO pageReqVO) { - return productMapper.selectPage(pageReqVO); + public List getProductListByStatus(Integer status) { + return productMapper.selectListByStatus(status); + } + + @Override + public List getProductVOList(Collection ids) { + List list = productMapper.selectBatchIds(ids); + return buildProductVOList(list); + } + + @Override + public PageResult getProductVOPage(ErpProductPageReqVO pageReqVO) { + PageResult pageResult = productMapper.selectPage(pageReqVO); + return new PageResult<>(buildProductVOList(pageResult.getList()), pageResult.getTotal()); + } + + private List buildProductVOList(List list) { + if (CollUtil.isEmpty(list)) { + return Collections.emptyList(); + } + Map categoryMap = productCategoryService.getProductCategoryMap( + convertSet(list, ErpProductDO::getCategoryId)); + Map unitMap = productUnitService.getProductUnitMap( + convertSet(list, ErpProductDO::getUnitId)); + return BeanUtils.toBean(list, ErpProductRespVO.class, product -> { + MapUtils.findAndThen(categoryMap, product.getCategoryId(), + category -> product.setCategoryName(category.getName())); + MapUtils.findAndThen(unitMap, product.getUnitId(), + unit -> product.setUnitName(unit.getName())); + }); } @Override diff --git a/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/service/product/ErpProductUnitServiceImpl.java b/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/service/product/ErpProductUnitServiceImpl.java index 1ab412b11..87d78a54f 100644 --- a/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/service/product/ErpProductUnitServiceImpl.java +++ b/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/service/product/ErpProductUnitServiceImpl.java @@ -16,7 +16,7 @@ import java.util.Collection; import java.util.List; import static cn.iocoder.yudao.framework.common.exception.util.ServiceExceptionUtil.exception; -import static cn.iocoder.yudao.module.erp.ErrorCodeConstants.*; +import static cn.iocoder.yudao.module.erp.enums.ErrorCodeConstants.*; /** * ERP 产品单位 Service 实现类 diff --git a/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/service/stock/ErpStockRecordService.java b/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/service/stock/ErpStockRecordService.java new file mode 100644 index 000000000..8b90a0e4c --- /dev/null +++ b/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/service/stock/ErpStockRecordService.java @@ -0,0 +1,30 @@ +package cn.iocoder.yudao.module.erp.service.stock; + +import cn.iocoder.yudao.framework.common.pojo.PageResult; +import cn.iocoder.yudao.module.erp.controller.admin.stock.vo.stockrecord.ErpStockRecordPageReqVO; +import cn.iocoder.yudao.module.erp.dal.dataobject.stock.ErpStockRecordDO; + +/** + * ERP 产品库存明细 Service 接口 + * + * @author 芋道源码 + */ +public interface ErpStockRecordService { + + /** + * 获得产品库存明细 + * + * @param id 编号 + * @return 产品库存明细 + */ + ErpStockRecordDO getStockRecord(Long id); + + /** + * 获得产品库存明细分页 + * + * @param pageReqVO 分页查询 + * @return 产品库存明细分页 + */ + PageResult getStockRecordPage(ErpStockRecordPageReqVO pageReqVO); + +} \ No newline at end of file diff --git a/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/service/stock/ErpStockRecordServiceImpl.java b/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/service/stock/ErpStockRecordServiceImpl.java new file mode 100644 index 000000000..0adc7c864 --- /dev/null +++ b/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/service/stock/ErpStockRecordServiceImpl.java @@ -0,0 +1,33 @@ +package cn.iocoder.yudao.module.erp.service.stock; + +import cn.iocoder.yudao.framework.common.pojo.PageResult; +import cn.iocoder.yudao.module.erp.controller.admin.stock.vo.stockrecord.ErpStockRecordPageReqVO; +import cn.iocoder.yudao.module.erp.dal.dataobject.stock.ErpStockRecordDO; +import cn.iocoder.yudao.module.erp.dal.mysql.stock.ErpStockRecordMapper; +import jakarta.annotation.Resource; +import org.springframework.stereotype.Service; +import org.springframework.validation.annotation.Validated; + +/** + * ERP 产品库存明细 Service 实现类 + * + * @author 芋道源码 + */ +@Service +@Validated +public class ErpStockRecordServiceImpl implements ErpStockRecordService { + + @Resource + private ErpStockRecordMapper stockRecordMapper; + + @Override + public ErpStockRecordDO getStockRecord(Long id) { + return stockRecordMapper.selectById(id); + } + + @Override + public PageResult getStockRecordPage(ErpStockRecordPageReqVO pageReqVO) { + return stockRecordMapper.selectPage(pageReqVO); + } + +} \ No newline at end of file diff --git a/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/service/stock/ErpStockService.java b/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/service/stock/ErpStockService.java new file mode 100644 index 000000000..041aca6d5 --- /dev/null +++ b/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/service/stock/ErpStockService.java @@ -0,0 +1,30 @@ +package cn.iocoder.yudao.module.erp.service.stock; + +import cn.iocoder.yudao.framework.common.pojo.PageResult; +import cn.iocoder.yudao.module.erp.controller.admin.stock.vo.stock.ErpStockPageReqVO; +import cn.iocoder.yudao.module.erp.dal.dataobject.stock.ErpStockDO; + +/** + * ERP 产品库存 Service 接口 + * + * @author 芋道源码 + */ +public interface ErpStockService { + + /** + * 获得产品库存 + * + * @param id 编号 + * @return 库存 + */ + ErpStockDO getStock(Long id); + + /** + * 获得产品库存分页 + * + * @param pageReqVO 分页查询 + * @return 库存分页 + */ + PageResult getStockPage(ErpStockPageReqVO pageReqVO); + +} \ No newline at end of file diff --git a/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/service/stock/ErpStockServiceImpl.java b/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/service/stock/ErpStockServiceImpl.java new file mode 100644 index 000000000..7ee4a3fc0 --- /dev/null +++ b/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/service/stock/ErpStockServiceImpl.java @@ -0,0 +1,33 @@ +package cn.iocoder.yudao.module.erp.service.stock; + +import cn.iocoder.yudao.framework.common.pojo.PageResult; +import cn.iocoder.yudao.module.erp.controller.admin.stock.vo.stock.ErpStockPageReqVO; +import cn.iocoder.yudao.module.erp.dal.dataobject.stock.ErpStockDO; +import cn.iocoder.yudao.module.erp.dal.mysql.stock.ErpStockMapper; +import jakarta.annotation.Resource; +import org.springframework.stereotype.Service; +import org.springframework.validation.annotation.Validated; + +/** + * ERP 产品库存 Service 实现类 + * + * @author 芋道源码 + */ +@Service +@Validated +public class ErpStockServiceImpl implements ErpStockService { + + @Resource + private ErpStockMapper stockMapper; + + @Override + public ErpStockDO getStock(Long id) { + return stockMapper.selectById(id); + } + + @Override + public PageResult getStockPage(ErpStockPageReqVO pageReqVO) { + return stockMapper.selectPage(pageReqVO); + } + +} \ No newline at end of file diff --git a/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/service/stock/ErpWarehouseService.java b/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/service/stock/ErpWarehouseService.java index 47e4dbed2..6f9d3c8fa 100644 --- a/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/service/stock/ErpWarehouseService.java +++ b/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/service/stock/ErpWarehouseService.java @@ -6,6 +6,12 @@ import cn.iocoder.yudao.module.erp.controller.admin.stock.vo.warehouse.ErpWareho import cn.iocoder.yudao.module.erp.dal.dataobject.stock.ErpWarehouseDO; import jakarta.validation.Valid; +import java.util.Collection; +import java.util.List; +import java.util.Map; + +import static cn.iocoder.yudao.framework.common.util.collection.CollectionUtils.convertMap; + /** * ERP 仓库 Service 接口 * @@ -51,6 +57,32 @@ public interface ErpWarehouseService { */ ErpWarehouseDO getWarehouse(Long id); + /** + * 获得指定状态的仓库列表 + * + * @param status 状态 + * @return 仓库列表 + */ + List getWarehouseListByStatus(Integer status); + + /** + * 获得仓库列表 + * + * @param ids 编号数组 + * @return 仓库列表 + */ + List getWarehouseList(Collection ids); + + /** + * 获得仓库 Map + * + * @param ids 编号数组 + * @return 仓库 Map + */ + default Map getWarehouseMap(Collection ids) { + return convertMap(getWarehouseList(ids), ErpWarehouseDO::getId); + } + /** * 获得仓库分页 * diff --git a/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/service/stock/ErpWarehouseServiceImpl.java b/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/service/stock/ErpWarehouseServiceImpl.java index e4c34ade4..e2f6d7667 100644 --- a/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/service/stock/ErpWarehouseServiceImpl.java +++ b/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/service/stock/ErpWarehouseServiceImpl.java @@ -11,8 +11,11 @@ import org.springframework.stereotype.Service; import org.springframework.transaction.annotation.Transactional; import org.springframework.validation.annotation.Validated; +import java.util.Collection; +import java.util.List; + import static cn.iocoder.yudao.framework.common.exception.util.ServiceExceptionUtil.exception; -import static cn.iocoder.yudao.module.erp.ErrorCodeConstants.WAREHOUSE_NOT_EXISTS; +import static cn.iocoder.yudao.module.erp.enums.ErrorCodeConstants.WAREHOUSE_NOT_EXISTS; /** * ERP 仓库 Service 实现类 @@ -80,6 +83,16 @@ public class ErpWarehouseServiceImpl implements ErpWarehouseService { return warehouseMapper.selectById(id); } + @Override + public List getWarehouseListByStatus(Integer status) { + return warehouseMapper.selectListByStatus(status); + } + + @Override + public List getWarehouseList(Collection ids) { + return warehouseMapper.selectBatchIds(ids); + } + @Override public PageResult getWarehousePage(ErpWarehousePageReqVO pageReqVO) { return warehouseMapper.selectPage(pageReqVO); diff --git a/yudao-module-erp/yudao-module-erp-biz/src/test/java/cn/iocoder/yudao/module/erp/service/product/ProductServiceImplTest.java b/yudao-module-erp/yudao-module-erp-biz/src/test/java/cn/iocoder/yudao/module/erp/service/product/ProductServiceImplTest.java index 03298bcc3..5045dbfb0 100644 --- a/yudao-module-erp/yudao-module-erp-biz/src/test/java/cn/iocoder/yudao/module/erp/service/product/ProductServiceImplTest.java +++ b/yudao-module-erp/yudao-module-erp-biz/src/test/java/cn/iocoder/yudao/module/erp/service/product/ProductServiceImplTest.java @@ -1,6 +1,6 @@ package cn.iocoder.yudao.module.erp.service.product; -import cn.iocoder.yudao.module.erp.controller.admin.product.vo.product.ProductPageReqVO; +import cn.iocoder.yudao.module.erp.controller.admin.product.vo.product.ErpProductPageReqVO; import cn.iocoder.yudao.module.erp.controller.admin.product.vo.product.ProductSaveReqVO; import org.junit.jupiter.api.Disabled; import org.junit.jupiter.api.Test; @@ -115,13 +115,13 @@ public class ProductServiceImplTest extends BaseDbUnitTest { // 测试 createTime 不匹配 productMapper.insert(cloneIgnoreId(dbProduct, o -> o.setCreateTime(null))); // 准备参数 - ProductPageReqVO reqVO = new ProductPageReqVO(); + ErpProductPageReqVO reqVO = new ErpProductPageReqVO(); reqVO.setName(null); reqVO.setCategoryId(null); reqVO.setCreateTime(buildBetweenTime(2023, 2, 1, 2023, 2, 28)); // 调用 - PageResult pageResult = productService.getProductPage(reqVO); + PageResult pageResult = productService.getProductVOPage(reqVO); // 断言 assertEquals(1, pageResult.getTotal()); assertEquals(1, pageResult.getList().size()); From 46d26659bf49b6457be3cad084979e90c43d2d54 Mon Sep 17 00:00:00 2001 From: YunaiV Date: Tue, 6 Feb 2024 15:58:29 +0800 Subject: [PATCH 077/119] =?UTF-8?q?=E2=9C=A8=20ERP=EF=BC=9A=E5=88=9D?= =?UTF-8?q?=E5=A7=8B=E5=8C=96=E5=85=B6=E5=AE=83=E5=85=A5=E5=BA=93=E7=9A=84?= =?UTF-8?q?=E8=A1=A8=E5=8D=95=2050%?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../module/erp/enums/DictTypeConstants.java | 1 + .../module/erp/enums/ErpAuditStatus.java | 39 +++++ .../module/erp/enums/ErrorCodeConstants.java | 5 + .../admin/product/ErpProductController.java | 9 +- .../admin/stock/ErpStockController.java | 13 +- .../admin/stock/ErpStockInController.java | 145 ++++++++++++++++ .../admin/stock/ErpStockRecordController.java | 4 +- .../stock/vo/in/ErpStockInPageReqVO.java | 42 +++++ .../admin/stock/vo/in/ErpStockInRespVO.java | 106 ++++++++++++ .../stock/vo/in/ErpStockInSaveReqVO.java | 69 ++++++++ .../ErpStockRecordPageReqVO.java | 2 +- .../ErpStockRecordRespVO.java | 2 +- .../dal/dataobject/stock/ErpStockInDO.java | 69 ++++++++ .../dataobject/stock/ErpStockInItemDO.java | 73 ++++++++ .../dal/mysql/stock/ErpStockInItemMapper.java | 30 ++++ .../erp/dal/mysql/stock/ErpStockInMapper.java | 29 ++++ .../erp/dal/mysql/stock/ErpStockMapper.java | 5 + .../dal/mysql/stock/ErpStockRecordMapper.java | 2 +- .../service/product/ErpProductService.java | 14 +- .../product/ErpProductServiceImpl.java | 34 +++- .../erp/service/stock/ErpStockInService.java | 76 ++++++++ .../service/stock/ErpStockInServiceImpl.java | 162 ++++++++++++++++++ .../service/stock/ErpStockRecordService.java | 2 +- .../stock/ErpStockRecordServiceImpl.java | 2 +- .../erp/service/stock/ErpStockService.java | 9 + .../service/stock/ErpStockServiceImpl.java | 5 + .../service/stock/ErpWarehouseService.java | 8 + .../stock/ErpWarehouseServiceImpl.java | 27 ++- 28 files changed, 960 insertions(+), 24 deletions(-) create mode 100644 yudao-module-erp/yudao-module-erp-api/src/main/java/cn/iocoder/yudao/module/erp/enums/ErpAuditStatus.java create mode 100644 yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/controller/admin/stock/ErpStockInController.java create mode 100644 yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/controller/admin/stock/vo/in/ErpStockInPageReqVO.java create mode 100644 yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/controller/admin/stock/vo/in/ErpStockInRespVO.java create mode 100644 yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/controller/admin/stock/vo/in/ErpStockInSaveReqVO.java rename yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/controller/admin/stock/vo/{stockrecord => record}/ErpStockRecordPageReqVO.java (93%) rename yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/controller/admin/stock/vo/{stockrecord => record}/ErpStockRecordRespVO.java (97%) create mode 100644 yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/dal/dataobject/stock/ErpStockInDO.java create mode 100644 yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/dal/dataobject/stock/ErpStockInItemDO.java create mode 100644 yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/dal/mysql/stock/ErpStockInItemMapper.java create mode 100644 yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/dal/mysql/stock/ErpStockInMapper.java create mode 100644 yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/service/stock/ErpStockInService.java create mode 100644 yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/service/stock/ErpStockInServiceImpl.java diff --git a/yudao-module-erp/yudao-module-erp-api/src/main/java/cn/iocoder/yudao/module/erp/enums/DictTypeConstants.java b/yudao-module-erp/yudao-module-erp-api/src/main/java/cn/iocoder/yudao/module/erp/enums/DictTypeConstants.java index af7033895..36d4df852 100644 --- a/yudao-module-erp/yudao-module-erp-api/src/main/java/cn/iocoder/yudao/module/erp/enums/DictTypeConstants.java +++ b/yudao-module-erp/yudao-module-erp-api/src/main/java/cn/iocoder/yudao/module/erp/enums/DictTypeConstants.java @@ -7,6 +7,7 @@ package cn.iocoder.yudao.module.erp.enums; */ public interface DictTypeConstants { + String AUDIT_STATUS = "erp_audit_status"; // 审核状态 String STOCK_RECORD_BIZ_TYPE = "erp_stock_record_biz_type"; // 库存明细的业务类型 } diff --git a/yudao-module-erp/yudao-module-erp-api/src/main/java/cn/iocoder/yudao/module/erp/enums/ErpAuditStatus.java b/yudao-module-erp/yudao-module-erp-api/src/main/java/cn/iocoder/yudao/module/erp/enums/ErpAuditStatus.java new file mode 100644 index 000000000..a10147a70 --- /dev/null +++ b/yudao-module-erp/yudao-module-erp-api/src/main/java/cn/iocoder/yudao/module/erp/enums/ErpAuditStatus.java @@ -0,0 +1,39 @@ +package cn.iocoder.yudao.module.erp.enums; + +import cn.iocoder.yudao.framework.common.core.IntArrayValuable; +import lombok.Getter; +import lombok.RequiredArgsConstructor; + +import java.util.Arrays; + +/** + * ERP 审核状态枚举 + * + * TODO 芋艿:目前只有待审批、已审批两个状态,未来接入工作流后,会丰富下:待提交(草稿)=》已提交(待审核)=》审核通过、审核不通过;另外,工作流需要支持“反审核”,把工作流退回到原点; + * + * @author 芋道源码 + */ +@RequiredArgsConstructor +@Getter +public enum ErpAuditStatus implements IntArrayValuable { + + PROCESS(10, "未审核"), // 审核中 + APPROVE(20, "已审核"); // 审核通过 + + public static final int[] ARRAYS = Arrays.stream(values()).mapToInt(ErpAuditStatus::getStatus).toArray(); + + /** + * 状态 + */ + private final Integer status; + /** + * 状态名 + */ + private final String name; + + @Override + public int[] array() { + return ARRAYS; + } + +} diff --git a/yudao-module-erp/yudao-module-erp-api/src/main/java/cn/iocoder/yudao/module/erp/enums/ErrorCodeConstants.java b/yudao-module-erp/yudao-module-erp-api/src/main/java/cn/iocoder/yudao/module/erp/enums/ErrorCodeConstants.java index 51cae4ad9..e4db13763 100644 --- a/yudao-module-erp/yudao-module-erp-api/src/main/java/cn/iocoder/yudao/module/erp/enums/ErrorCodeConstants.java +++ b/yudao-module-erp/yudao-module-erp-api/src/main/java/cn/iocoder/yudao/module/erp/enums/ErrorCodeConstants.java @@ -14,9 +14,14 @@ public interface ErrorCodeConstants { // ========== ERP 仓库 1-030-400-000 ========== ErrorCode WAREHOUSE_NOT_EXISTS = new ErrorCode(1_030_400_000, "仓库不存在"); + ErrorCode WAREHOUSE_NOT_ENABLE = new ErrorCode(1_030_500_001, "仓库({})未启用"); + + // ========== ERP 其它入库单 1-030-401-000 ========== + ErrorCode STOCK_IN_NOT_EXISTS = new ErrorCode(1_030_401_000, "其它入库单不存在"); // ========== ERP 产品 1-030-500-000 ========== ErrorCode PRODUCT_NOT_EXISTS = new ErrorCode(1_030_500_000, "产品不存在"); + ErrorCode PRODUCT_NOT_ENABLE = new ErrorCode(1_030_500_001, "产品({})未启用"); // ========== ERP 产品分类 1-030-501-000 ========== ErrorCode PRODUCT_CATEGORY_NOT_EXISTS = new ErrorCode(1_030_501_000, "产品分类不存在"); diff --git a/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/controller/admin/product/ErpProductController.java b/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/controller/admin/product/ErpProductController.java index 63977890c..cde7bd704 100644 --- a/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/controller/admin/product/ErpProductController.java +++ b/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/controller/admin/product/ErpProductController.java @@ -26,6 +26,7 @@ import java.io.IOException; import java.util.List; 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.operatelog.core.enums.OperateTypeEnum.EXPORT; @Tag(name = "管理后台 - ERP 产品") @@ -80,8 +81,12 @@ public class ErpProductController { @GetMapping("/simple-list") @Operation(summary = "获得产品精简列表", description = "只包含被开启的产品,主要用于前端的下拉选项") public CommonResult> getProductSimpleList() { - List list = productService.getProductListByStatus(CommonStatusEnum.ENABLE.getStatus()); - return success(BeanUtils.toBean(list, ErpProductRespVO.class)); + List list = productService.getProductVOListByStatus(CommonStatusEnum.ENABLE.getStatus()); + return success(convertList(list, product -> new ErpProductRespVO().setId(product.getId()) + .setName(product.getName()).setBarCode(product.getBarCode()) + .setCategoryId(product.getCategoryId()).setCategoryName(product.getCategoryName()) + .setUnitId(product.getUnitId()).setUnitName(product.getUnitName()) + .setPurchasePrice(product.getPurchasePrice()).setSalePrice(product.getSalePrice()).setMinPrice(product.getMinPrice()))); } @GetMapping("/export-excel") diff --git a/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/controller/admin/stock/ErpStockController.java b/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/controller/admin/stock/ErpStockController.java index 18bf063d3..224468657 100644 --- a/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/controller/admin/stock/ErpStockController.java +++ b/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/controller/admin/stock/ErpStockController.java @@ -18,6 +18,7 @@ import cn.iocoder.yudao.module.erp.service.stock.ErpStockService; import cn.iocoder.yudao.module.erp.service.stock.ErpWarehouseService; import io.swagger.v3.oas.annotations.Operation; import io.swagger.v3.oas.annotations.Parameter; +import io.swagger.v3.oas.annotations.Parameters; import io.swagger.v3.oas.annotations.tags.Tag; import jakarta.annotation.Resource; import jakarta.servlet.http.HttpServletResponse; @@ -52,10 +53,16 @@ public class ErpStockController { @GetMapping("/get") @Operation(summary = "获得产品库存") - @Parameter(name = "id", description = "编号", required = true, example = "1024") + @Parameters({ + @Parameter(name = "id", description = "编号", example = "1"), // 方案一:传递 id + @Parameter(name = "productId", description = "产品编号", example = "10"), // 方案二:传递 productId + warehouseId + @Parameter(name = "warehouseId", description = "仓库编号", example = "2") + }) @PreAuthorize("@ss.hasPermission('erp:stock:query')") - public CommonResult getStock(@RequestParam("id") Long id) { - ErpStockDO stock = stockService.getStock(id); + public CommonResult getStock(@RequestParam(value = "id", required = false) Long id, + @RequestParam(value = "productId", required = false) Long productId, + @RequestParam(value = "warehouseId", required = false) Long warehouseId) { + ErpStockDO stock = id != null ? stockService.getStock(id) : stockService.getStock(productId, warehouseId); return success(BeanUtils.toBean(stock, ErpStockRespVO.class)); } diff --git a/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/controller/admin/stock/ErpStockInController.java b/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/controller/admin/stock/ErpStockInController.java new file mode 100644 index 000000000..192fbf50a --- /dev/null +++ b/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/controller/admin/stock/ErpStockInController.java @@ -0,0 +1,145 @@ +package cn.iocoder.yudao.module.erp.controller.admin.stock; + +import cn.hutool.core.collection.CollUtil; +import cn.iocoder.yudao.framework.common.pojo.CommonResult; +import cn.iocoder.yudao.framework.common.pojo.PageParam; +import cn.iocoder.yudao.framework.common.pojo.PageResult; +import cn.iocoder.yudao.framework.common.util.collection.MapUtils; +import cn.iocoder.yudao.framework.common.util.object.BeanUtils; +import cn.iocoder.yudao.framework.excel.core.util.ExcelUtils; +import cn.iocoder.yudao.framework.operatelog.core.annotations.OperateLog; +import cn.iocoder.yudao.module.erp.controller.admin.product.vo.product.ErpProductRespVO; +import cn.iocoder.yudao.module.erp.controller.admin.stock.vo.in.ErpStockInPageReqVO; +import cn.iocoder.yudao.module.erp.controller.admin.stock.vo.in.ErpStockInRespVO; +import cn.iocoder.yudao.module.erp.controller.admin.stock.vo.in.ErpStockInSaveReqVO; +import cn.iocoder.yudao.module.erp.dal.dataobject.stock.ErpStockDO; +import cn.iocoder.yudao.module.erp.dal.dataobject.stock.ErpStockInDO; +import cn.iocoder.yudao.module.erp.dal.dataobject.stock.ErpStockInItemDO; +import cn.iocoder.yudao.module.erp.service.product.ErpProductService; +import cn.iocoder.yudao.module.erp.service.stock.ErpStockInService; +import cn.iocoder.yudao.module.erp.service.stock.ErpStockService; +import cn.iocoder.yudao.module.system.api.user.AdminUserApi; +import cn.iocoder.yudao.module.system.api.user.dto.AdminUserRespDTO; +import io.swagger.v3.oas.annotations.Operation; +import io.swagger.v3.oas.annotations.Parameter; +import io.swagger.v3.oas.annotations.tags.Tag; +import jakarta.annotation.Resource; +import jakarta.servlet.http.HttpServletResponse; +import jakarta.validation.Valid; +import org.springframework.security.access.prepost.PreAuthorize; +import org.springframework.validation.annotation.Validated; +import org.springframework.web.bind.annotation.*; + +import java.io.IOException; +import java.math.BigDecimal; +import java.util.List; +import java.util.Map; + +import static cn.iocoder.yudao.framework.common.pojo.CommonResult.success; +import static cn.iocoder.yudao.framework.common.util.collection.CollectionUtils.convertMultiMap; +import static cn.iocoder.yudao.framework.common.util.collection.CollectionUtils.convertSet; +import static cn.iocoder.yudao.framework.operatelog.core.enums.OperateTypeEnum.EXPORT; + +@Tag(name = "管理后台 - ERP 其它入库单") +@RestController +@RequestMapping("/erp/stock-in") +@Validated +public class ErpStockInController { + + @Resource + private ErpStockInService stockInService; + @Resource + private ErpStockService stockService; + @Resource + private ErpProductService productService; + + @Resource + private AdminUserApi adminUserApi; + + @PostMapping("/create") + @Operation(summary = "创建其它入库单") + @PreAuthorize("@ss.hasPermission('erp:stock-in:create')") + public CommonResult createStockIn(@Valid @RequestBody ErpStockInSaveReqVO createReqVO) { + return success(stockInService.createStockIn(createReqVO)); + } + + @PutMapping("/update") + @Operation(summary = "更新其它入库单") + @PreAuthorize("@ss.hasPermission('erp:stock-in:update')") + public CommonResult updateStockIn(@Valid @RequestBody ErpStockInSaveReqVO updateReqVO) { + stockInService.updateStockIn(updateReqVO); + return success(true); + } + + @DeleteMapping("/delete") + @Operation(summary = "删除其它入库单") + @Parameter(name = "id", description = "编号", required = true) + @PreAuthorize("@ss.hasPermission('erp:stock-in:delete')") + public CommonResult deleteStockIn(@RequestParam("id") Long id) { + stockInService.deleteStockIn(id); + return success(true); + } + + @GetMapping("/get") + @Operation(summary = "获得其它入库单") + @Parameter(name = "id", description = "编号", required = true, example = "1024") + @PreAuthorize("@ss.hasPermission('erp:stock-in:query')") + public CommonResult getStockIn(@RequestParam("id") Long id) { + ErpStockInDO stockIn = stockInService.getStockIn(id); + if (stockIn == null) { + return success(null); + } + List stockInItems = stockInService.getStockInItemListByInId(id); + + return success(BeanUtils.toBean(stockIn, ErpStockInRespVO.class, stockInVO -> + stockInVO.setItems(BeanUtils.toBean(stockInItems, ErpStockInRespVO.Item.class, item -> { + ErpStockDO stock = stockService.getStock(item.getProductId(), item.getWarehouseId()); + item.setStockCount(stock != null ? stock.getCount() : BigDecimal.ZERO); + })))); + } + + @GetMapping("/page") + @Operation(summary = "获得其它入库单分页") + @PreAuthorize("@ss.hasPermission('erp:stock-in:query')") + public CommonResult> getStockInPage(@Valid ErpStockInPageReqVO pageReqVO) { + PageResult pageResult = stockInService.getStockInPage(pageReqVO); + return success(buildStockInVOPageResult(pageResult)); + } + + @GetMapping("/export-excel") + @Operation(summary = "导出其它入库单 Excel") + @PreAuthorize("@ss.hasPermission('erp:stock-in:export')") + @OperateLog(type = EXPORT) + public void exportStockInExcel(@Valid ErpStockInPageReqVO pageReqVO, + HttpServletResponse response) throws IOException { + pageReqVO.setPageSize(PageParam.PAGE_SIZE_NONE); + List list = buildStockInVOPageResult(stockInService.getStockInPage(pageReqVO)).getList(); + // 导出 Excel + ExcelUtils.write(response, "其它入库单.xls", "数据", ErpStockInRespVO.class, list); + } + + private PageResult buildStockInVOPageResult(PageResult pageResult) { + if (CollUtil.isEmpty(pageResult.getList())) { + return PageResult.empty(pageResult.getTotal()); + } + // 1.1 入库项 + List stockInItemList = stockInService.getStockInItemListByInIds( + convertSet(pageResult.getList(), ErpStockInDO::getId)); + Map> stockInItemMap = convertMultiMap(stockInItemList, ErpStockInItemDO::getInId); + // 1.2 商品信息 + Map productMap = productService.getProductVOMap( + convertSet(stockInItemList, ErpStockInItemDO::getProductId)); + // 1.3 管理员信息 + Map userMap = adminUserApi.getUserMap( + convertSet(pageResult.getList(), erpStockRecordDO -> Long.parseLong(erpStockRecordDO.getCreator()))); + // 2. 开始拼接 + return BeanUtils.toBean(pageResult, ErpStockInRespVO.class, stockIn -> { + stockIn.setItems(BeanUtils.toBean(stockInItemMap.get(stockIn.getId()), ErpStockInRespVO.Item.class, + item -> MapUtils.findAndThen(productMap, item.getProductId(), + product -> item.setProductName(product.getName()).setProductUnitName(product.getUnitName())))); + stockIn.setProductNames(CollUtil.join(stockIn.getItems(), ",", ErpStockInRespVO.Item::getProductName)); + MapUtils.findAndThen(userMap, Long.parseLong(stockIn.getCreator()), user -> stockIn.setCreatorName(user.getNickname())); + }); + } + +} \ No newline at end of file diff --git a/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/controller/admin/stock/ErpStockRecordController.java b/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/controller/admin/stock/ErpStockRecordController.java index e92856378..09f9feaf9 100644 --- a/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/controller/admin/stock/ErpStockRecordController.java +++ b/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/controller/admin/stock/ErpStockRecordController.java @@ -9,8 +9,8 @@ import cn.iocoder.yudao.framework.common.util.object.BeanUtils; import cn.iocoder.yudao.framework.excel.core.util.ExcelUtils; import cn.iocoder.yudao.framework.operatelog.core.annotations.OperateLog; import cn.iocoder.yudao.module.erp.controller.admin.product.vo.product.ErpProductRespVO; -import cn.iocoder.yudao.module.erp.controller.admin.stock.vo.stockrecord.ErpStockRecordPageReqVO; -import cn.iocoder.yudao.module.erp.controller.admin.stock.vo.stockrecord.ErpStockRecordRespVO; +import cn.iocoder.yudao.module.erp.controller.admin.stock.vo.record.ErpStockRecordPageReqVO; +import cn.iocoder.yudao.module.erp.controller.admin.stock.vo.record.ErpStockRecordRespVO; import cn.iocoder.yudao.module.erp.dal.dataobject.stock.ErpStockRecordDO; import cn.iocoder.yudao.module.erp.dal.dataobject.stock.ErpWarehouseDO; import cn.iocoder.yudao.module.erp.service.product.ErpProductService; diff --git a/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/controller/admin/stock/vo/in/ErpStockInPageReqVO.java b/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/controller/admin/stock/vo/in/ErpStockInPageReqVO.java new file mode 100644 index 000000000..05f1915ce --- /dev/null +++ b/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/controller/admin/stock/vo/in/ErpStockInPageReqVO.java @@ -0,0 +1,42 @@ +package cn.iocoder.yudao.module.erp.controller.admin.stock.vo.in; + +import cn.iocoder.yudao.framework.common.pojo.PageParam; +import cn.iocoder.yudao.framework.common.validation.InEnum; +import cn.iocoder.yudao.module.erp.enums.ErpAuditStatus; +import io.swagger.v3.oas.annotations.media.Schema; +import lombok.Data; +import lombok.EqualsAndHashCode; +import lombok.ToString; +import org.springframework.format.annotation.DateTimeFormat; + +import java.time.LocalDateTime; + +import static cn.iocoder.yudao.framework.common.util.date.DateUtils.FORMAT_YEAR_MONTH_DAY_HOUR_MINUTE_SECOND; + +@Schema(description = "管理后台 - ERP 其它入库单分页 Request VO") +@Data +@EqualsAndHashCode(callSuper = true) +@ToString(callSuper = true) +public class ErpStockInPageReqVO extends PageParam { + + @Schema(description = "入库单号", example = "S123") + private String no; + + @Schema(description = "供应商编号", example = "3113") + private Long supplierId; + + @Schema(description = "入库时间") + @DateTimeFormat(pattern = FORMAT_YEAR_MONTH_DAY_HOUR_MINUTE_SECOND) + private LocalDateTime[] inTime; + + @Schema(description = "状态", example = "10") + @InEnum(ErpAuditStatus.class) + private Integer status; + + @Schema(description = "备注", example = "随便") + private String remark; + + @Schema(description = "创建者") + private String creator; + +} \ No newline at end of file diff --git a/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/controller/admin/stock/vo/in/ErpStockInRespVO.java b/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/controller/admin/stock/vo/in/ErpStockInRespVO.java new file mode 100644 index 000000000..429ec77a4 --- /dev/null +++ b/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/controller/admin/stock/vo/in/ErpStockInRespVO.java @@ -0,0 +1,106 @@ +package cn.iocoder.yudao.module.erp.controller.admin.stock.vo.in; + +import cn.iocoder.yudao.framework.excel.core.annotations.DictFormat; +import cn.iocoder.yudao.framework.excel.core.convert.DictConvert; +import com.alibaba.excel.annotation.ExcelIgnoreUnannotated; +import com.alibaba.excel.annotation.ExcelProperty; +import io.swagger.v3.oas.annotations.media.Schema; +import lombok.Data; + +import java.math.BigDecimal; +import java.time.LocalDateTime; +import java.util.List; + +import static cn.iocoder.yudao.module.erp.enums.DictTypeConstants.AUDIT_STATUS; + +@Schema(description = "管理后台 - ERP 其它入库单 Response VO") +@Data +@ExcelIgnoreUnannotated +public class ErpStockInRespVO { + + @Schema(description = "入库编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "11756") + @ExcelProperty("入库编号") + private Long id; + + @Schema(description = "入库单号", requiredMode = Schema.RequiredMode.REQUIRED, example = "S123") + @ExcelProperty("入库单号") + private String no; + + @Schema(description = "供应商编号", example = "3113") + @ExcelProperty("供应商编号") + private Long supplierId; + + @Schema(description = "入库时间", requiredMode = Schema.RequiredMode.REQUIRED) + @ExcelProperty("入库时间") + private LocalDateTime inTime; + + @Schema(description = "合计数量", requiredMode = Schema.RequiredMode.REQUIRED, example = "15663") + @ExcelProperty("合计数量") + private BigDecimal totalCount; + + @Schema(description = "合计金额,单位:元", requiredMode = Schema.RequiredMode.REQUIRED, example = "24906") + @ExcelProperty("合计金额") + private BigDecimal totalPrice; + + @Schema(description = "状态", requiredMode = Schema.RequiredMode.REQUIRED, example = "10") + @ExcelProperty(value = "状态", converter = DictConvert.class) + @DictFormat(AUDIT_STATUS) + private Integer status; + + @Schema(description = "备注", example = "随便") + @ExcelProperty("备注") + private String remark; + + @Schema(description = "附件 URL", example = "https://www.iocoder.cn/1.doc") + private String fileUrl; + + @Schema(description = "审核人", example = "芋道") + private String creator; + @Schema(description = "审核人名称", example = "芋道") + private String creatorName; + + @Schema(description = "创建时间", requiredMode = Schema.RequiredMode.REQUIRED) + @ExcelProperty("创建时间") + private LocalDateTime createTime; + + @Schema(description = "入库项列表", requiredMode = Schema.RequiredMode.REQUIRED) + private List items; + + @Schema(description = "产品信息", requiredMode = Schema.RequiredMode.REQUIRED) + @ExcelProperty("产品信息") + private String productNames; + + @Data + public static class Item { + + @Schema(description = "入库项编号", example = "11756") + private Long id; + + @Schema(description = "仓库编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "3113") + private Long warehouseId; + + @Schema(description = "产品编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "3113") + private Long productId; + + @Schema(description = "产品单价", requiredMode = Schema.RequiredMode.REQUIRED, example = "100.00") + private BigDecimal productPrice; + + @Schema(description = "产品数量", requiredMode = Schema.RequiredMode.REQUIRED, example = "100.00") + private BigDecimal count; + + @Schema(description = "备注", example = "随便") + private String remark; + + // ========== 关联字段 ========== + + @Schema(description = "产品名称", requiredMode = Schema.RequiredMode.REQUIRED, example = "巧克力") + private String productName; + @Schema(description = "产品单位名称", requiredMode = Schema.RequiredMode.REQUIRED, example = "盒") + private String productUnitName; + + @Schema(description = "库存数量", requiredMode = Schema.RequiredMode.REQUIRED, example = "100.00") + private BigDecimal stockCount; // 该字段仅仅在“详情”和“编辑”时使用 + + } + +} \ No newline at end of file diff --git a/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/controller/admin/stock/vo/in/ErpStockInSaveReqVO.java b/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/controller/admin/stock/vo/in/ErpStockInSaveReqVO.java new file mode 100644 index 000000000..c3cc6be95 --- /dev/null +++ b/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/controller/admin/stock/vo/in/ErpStockInSaveReqVO.java @@ -0,0 +1,69 @@ +package cn.iocoder.yudao.module.erp.controller.admin.stock.vo.in; + +import io.swagger.v3.oas.annotations.media.Schema; +import jakarta.validation.Valid; +import jakarta.validation.constraints.NotEmpty; +import jakarta.validation.constraints.NotNull; +import lombok.Data; + +import java.math.BigDecimal; +import java.time.LocalDateTime; +import java.util.List; + +@Schema(description = "管理后台 - ERP 其它入库单新增/修改 Request VO") +@Data +public class ErpStockInSaveReqVO { + + @Schema(description = "入库编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "11756") + private Long id; + + @Schema(description = "入库单号", requiredMode = Schema.RequiredMode.REQUIRED, example = "S123") + @NotEmpty(message = "入库单号不能为空") + private String no; + + @Schema(description = "供应商编号", example = "3113") + private Long supplierId; + + @Schema(description = "入库时间", requiredMode = Schema.RequiredMode.REQUIRED) + @NotNull(message = "入库时间不能为空") + private LocalDateTime inTime; + + @Schema(description = "备注", example = "随便") + private String remark; + + @Schema(description = "附件 URL", example = "https://www.iocoder.cn/1.doc") + private String fileUrl; + + @Schema(description = "入库项列表", requiredMode = Schema.RequiredMode.REQUIRED) + @NotEmpty(message = "入库项列表不能为空") + @Valid + private List items; + + @Data + public static class Item { + + @Schema(description = "入库项编号", example = "11756") + private Long id; + + @Schema(description = "仓库编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "3113") + @NotNull(message = "仓库编号不能为空") + private Long warehouseId; + + @Schema(description = "产品编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "3113") + @NotNull(message = "产品编号不能为空") + private Long productId; + + @Schema(description = "产品单价", requiredMode = Schema.RequiredMode.REQUIRED, example = "100.00") + @NotNull(message = "产品单价不能为空") + private BigDecimal productPrice; + + @Schema(description = "产品数量", requiredMode = Schema.RequiredMode.REQUIRED, example = "100.00") + @NotNull(message = "产品数量不能为空") + private BigDecimal count; + + @Schema(description = "备注", example = "随便") + private String remark; + + } + +} \ No newline at end of file diff --git a/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/controller/admin/stock/vo/stockrecord/ErpStockRecordPageReqVO.java b/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/controller/admin/stock/vo/record/ErpStockRecordPageReqVO.java similarity index 93% rename from yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/controller/admin/stock/vo/stockrecord/ErpStockRecordPageReqVO.java rename to yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/controller/admin/stock/vo/record/ErpStockRecordPageReqVO.java index b9030f821..c478e4fef 100644 --- a/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/controller/admin/stock/vo/stockrecord/ErpStockRecordPageReqVO.java +++ b/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/controller/admin/stock/vo/record/ErpStockRecordPageReqVO.java @@ -1,4 +1,4 @@ -package cn.iocoder.yudao.module.erp.controller.admin.stock.vo.stockrecord; +package cn.iocoder.yudao.module.erp.controller.admin.stock.vo.record; import cn.iocoder.yudao.framework.common.pojo.PageParam; import io.swagger.v3.oas.annotations.media.Schema; diff --git a/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/controller/admin/stock/vo/stockrecord/ErpStockRecordRespVO.java b/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/controller/admin/stock/vo/record/ErpStockRecordRespVO.java similarity index 97% rename from yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/controller/admin/stock/vo/stockrecord/ErpStockRecordRespVO.java rename to yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/controller/admin/stock/vo/record/ErpStockRecordRespVO.java index 0073fafba..ff4b3e12a 100644 --- a/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/controller/admin/stock/vo/stockrecord/ErpStockRecordRespVO.java +++ b/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/controller/admin/stock/vo/record/ErpStockRecordRespVO.java @@ -1,4 +1,4 @@ -package cn.iocoder.yudao.module.erp.controller.admin.stock.vo.stockrecord; +package cn.iocoder.yudao.module.erp.controller.admin.stock.vo.record; import cn.iocoder.yudao.framework.excel.core.annotations.DictFormat; import cn.iocoder.yudao.framework.excel.core.convert.DictConvert; diff --git a/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/dal/dataobject/stock/ErpStockInDO.java b/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/dal/dataobject/stock/ErpStockInDO.java new file mode 100644 index 000000000..4eaa316e9 --- /dev/null +++ b/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/dal/dataobject/stock/ErpStockInDO.java @@ -0,0 +1,69 @@ +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.*; + +import java.math.BigDecimal; +import java.time.LocalDateTime; + +/** + * ERP 其它入库单 DO + * + * @author 芋道源码 + */ +@TableName("erp_stock_in") +@KeySequence("erp_stock_in_seq") // 用于 Oracle、PostgreSQL、Kingbase、DB2、H2 数据库的主键自增。如果是 MySQL 等数据库,可不写。 +@Data +@EqualsAndHashCode(callSuper = true) +@ToString(callSuper = true) +@Builder +@NoArgsConstructor +@AllArgsConstructor +public class ErpStockInDO extends BaseDO { + + /** + * 入库编号 + */ + @TableId + private Long id; + /** + * 入库单号 + */ + private String no; + /** + * 供应商编号 + * + * TODO 芋艿:待关联 + */ + private Long supplierId; + /** + * 入库时间 + */ + private LocalDateTime inTime; + /** + * 合计数量 + */ + private BigDecimal totalCount; + /** + * 合计金额,单位:元 + */ + private BigDecimal totalPrice; + /** + * 状态 + * + * 枚举 {@link cn.iocoder.yudao.module.erp.enums.ErpAuditStatus} + */ + private Integer status; + /** + * 备注 + */ + private String remark; + /** + * 附件 URL + */ + private String fileUrl; + +} \ No newline at end of file diff --git a/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/dal/dataobject/stock/ErpStockInItemDO.java b/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/dal/dataobject/stock/ErpStockInItemDO.java new file mode 100644 index 000000000..3e3ca9c5c --- /dev/null +++ b/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/dal/dataobject/stock/ErpStockInItemDO.java @@ -0,0 +1,73 @@ +package cn.iocoder.yudao.module.erp.dal.dataobject.stock; + +import cn.iocoder.yudao.framework.mybatis.core.dataobject.BaseDO; +import cn.iocoder.yudao.module.erp.dal.dataobject.product.ErpProductDO; +import com.baomidou.mybatisplus.annotation.KeySequence; +import com.baomidou.mybatisplus.annotation.TableId; +import com.baomidou.mybatisplus.annotation.TableName; +import lombok.*; + +import java.math.BigDecimal; + +/** + * ERP 其它入库单项 DO + * + * @author 芋道源码 + */ +@TableName("erp_stock_in_item") +@KeySequence("erp_stock_in_item_seq") // 用于 Oracle、PostgreSQL、Kingbase、DB2、H2 数据库的主键自增。如果是 MySQL 等数据库,可不写。 +@Data +@EqualsAndHashCode(callSuper = true) +@ToString(callSuper = true) +@Builder +@NoArgsConstructor +@AllArgsConstructor +public class ErpStockInItemDO extends BaseDO { + + /** + * 入库项编号 + */ + @TableId + private Long id; + /** + * 入库编号 + * + * 关联 {@link ErpStockInDO#getId()} + */ + private Long inId; + /** + * 仓库编号 + * + * 关联 {@link ErpWarehouseDO#getId()} + */ + private Long warehouseId; + /** + * 产品编号 + * + * 关联 {@link ErpProductDO#getId()} + */ + private Long productId; + /** + * 产品单位编号 + * + * 冗余 {@link ErpProductDO#getUnitId()} + */ + private Long productUnitId; + /** + * 产品单价 + */ + private BigDecimal productPrice; + /** + * 产品数量 + */ + private BigDecimal count; + /** + * 合计金额,单位:元 + */ + private BigDecimal totalPrice; + /** + * 备注 + */ + private String remark; + +} \ No newline at end of file diff --git a/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/dal/mysql/stock/ErpStockInItemMapper.java b/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/dal/mysql/stock/ErpStockInItemMapper.java new file mode 100644 index 000000000..2731aa7bb --- /dev/null +++ b/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/dal/mysql/stock/ErpStockInItemMapper.java @@ -0,0 +1,30 @@ +package cn.iocoder.yudao.module.erp.dal.mysql.stock; + +import cn.iocoder.yudao.framework.mybatis.core.mapper.BaseMapperX; +import cn.iocoder.yudao.module.erp.dal.dataobject.stock.ErpStockInItemDO; +import org.apache.ibatis.annotations.Mapper; + +import java.util.Collection; +import java.util.List; + +/** + * ERP 其它入库单项 Mapper + * + * @author 芋道源码 + */ +@Mapper +public interface ErpStockInItemMapper extends BaseMapperX { + + default List selectListByInId(Long inId) { + return selectList(ErpStockInItemDO::getInId, inId); + } + + default List selectListByInIds(Collection inIds) { + return selectList(ErpStockInItemDO::getInId, inIds); + } + + default int deleteByInId(Long inId) { + return delete(ErpStockInItemDO::getInId, inId); + } + +} \ No newline at end of file diff --git a/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/dal/mysql/stock/ErpStockInMapper.java b/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/dal/mysql/stock/ErpStockInMapper.java new file mode 100644 index 000000000..782112129 --- /dev/null +++ b/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/dal/mysql/stock/ErpStockInMapper.java @@ -0,0 +1,29 @@ +package cn.iocoder.yudao.module.erp.dal.mysql.stock; + +import cn.iocoder.yudao.framework.common.pojo.PageResult; +import cn.iocoder.yudao.framework.mybatis.core.mapper.BaseMapperX; +import cn.iocoder.yudao.framework.mybatis.core.query.LambdaQueryWrapperX; +import cn.iocoder.yudao.module.erp.controller.admin.stock.vo.in.ErpStockInPageReqVO; +import cn.iocoder.yudao.module.erp.dal.dataobject.stock.ErpStockInDO; +import org.apache.ibatis.annotations.Mapper; + +/** + * ERP 其它入库单 Mapper + * + * @author 芋道源码 + */ +@Mapper +public interface ErpStockInMapper extends BaseMapperX { + + default PageResult selectPage(ErpStockInPageReqVO reqVO) { + return selectPage(reqVO, new LambdaQueryWrapperX() + .eqIfPresent(ErpStockInDO::getNo, reqVO.getNo()) + .eqIfPresent(ErpStockInDO::getSupplierId, reqVO.getSupplierId()) + .betweenIfPresent(ErpStockInDO::getInTime, reqVO.getInTime()) + .eqIfPresent(ErpStockInDO::getStatus, reqVO.getStatus()) + .likeIfPresent(ErpStockInDO::getRemark, reqVO.getRemark()) + .eqIfPresent(ErpStockInDO::getCreator, reqVO.getCreator()) + .orderByDesc(ErpStockInDO::getId)); + } + +} \ No newline at end of file diff --git a/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/dal/mysql/stock/ErpStockMapper.java b/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/dal/mysql/stock/ErpStockMapper.java index c634f9780..5afe42da0 100644 --- a/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/dal/mysql/stock/ErpStockMapper.java +++ b/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/dal/mysql/stock/ErpStockMapper.java @@ -22,4 +22,9 @@ public interface ErpStockMapper extends BaseMapperX { .orderByDesc(ErpStockDO::getId)); } + default ErpStockDO selectByProductIdAndWarehouseId(Long productId, Long warehouseId) { + return selectOne(ErpStockDO::getProductId, productId, + ErpStockDO::getWarehouseId, warehouseId); + } + } \ No newline at end of file diff --git a/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/dal/mysql/stock/ErpStockRecordMapper.java b/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/dal/mysql/stock/ErpStockRecordMapper.java index 6c5c48fd0..bfd8b6751 100644 --- a/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/dal/mysql/stock/ErpStockRecordMapper.java +++ b/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/dal/mysql/stock/ErpStockRecordMapper.java @@ -3,7 +3,7 @@ package cn.iocoder.yudao.module.erp.dal.mysql.stock; import cn.iocoder.yudao.framework.common.pojo.PageResult; import cn.iocoder.yudao.framework.mybatis.core.mapper.BaseMapperX; import cn.iocoder.yudao.framework.mybatis.core.query.LambdaQueryWrapperX; -import cn.iocoder.yudao.module.erp.controller.admin.stock.vo.stockrecord.ErpStockRecordPageReqVO; +import cn.iocoder.yudao.module.erp.controller.admin.stock.vo.record.ErpStockRecordPageReqVO; import cn.iocoder.yudao.module.erp.dal.dataobject.stock.ErpStockRecordDO; import org.apache.ibatis.annotations.Mapper; diff --git a/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/service/product/ErpProductService.java b/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/service/product/ErpProductService.java index 9fa18a073..778c7f29a 100644 --- a/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/service/product/ErpProductService.java +++ b/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/service/product/ErpProductService.java @@ -42,6 +42,14 @@ public interface ErpProductService { */ void deleteProduct(Long id); + /** + * 校验产品们的有效性 + * + * @param ids 编号数组 + * @return 产品列表 + */ + List validProductList(Collection ids); + /** * 获得产品 * @@ -51,12 +59,12 @@ public interface ErpProductService { ErpProductDO getProduct(Long id); /** - * 获得指定状态的产品列表 + * 获得指定状态的产品 VO 列表 * * @param status 状态 - * @return 产品列表 + * @return 产品 VO 列表 */ - List getProductListByStatus(Integer status); + List getProductVOListByStatus(Integer status); /** * 获得产品 VO 列表 diff --git a/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/service/product/ErpProductServiceImpl.java b/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/service/product/ErpProductServiceImpl.java index 58c7b7c3b..074fd3c29 100644 --- a/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/service/product/ErpProductServiceImpl.java +++ b/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/service/product/ErpProductServiceImpl.java @@ -1,6 +1,7 @@ package cn.iocoder.yudao.module.erp.service.product; import cn.hutool.core.collection.CollUtil; +import cn.iocoder.yudao.framework.common.enums.CommonStatusEnum; import cn.iocoder.yudao.framework.common.pojo.PageResult; import cn.iocoder.yudao.framework.common.util.collection.MapUtils; import cn.iocoder.yudao.framework.common.util.object.BeanUtils; @@ -15,14 +16,11 @@ import jakarta.annotation.Resource; import org.springframework.stereotype.Service; import org.springframework.validation.annotation.Validated; -import java.util.Collection; -import java.util.Collections; -import java.util.List; -import java.util.Map; +import java.util.*; import static cn.iocoder.yudao.framework.common.exception.util.ServiceExceptionUtil.exception; -import static cn.iocoder.yudao.framework.common.util.collection.CollectionUtils.convertSet; -import static cn.iocoder.yudao.module.erp.enums.ErrorCodeConstants.PRODUCT_NOT_EXISTS; +import static cn.iocoder.yudao.framework.common.util.collection.CollectionUtils.*; +import static cn.iocoder.yudao.module.erp.enums.ErrorCodeConstants.*; /** * ERP 产品 Service 实现类 @@ -67,6 +65,25 @@ public class ErpProductServiceImpl implements ErpProductService { productMapper.deleteById(id); } + @Override + public List validProductList(Collection ids) { + if (CollUtil.isEmpty(ids)) { + return Collections.emptyList(); + } + List list = productMapper.selectBatchIds(ids); + Map productMap = convertMap(list, ErpProductDO::getId); + for (Long id : ids) { + ErpProductDO product = productMap.get(id); + if (productMap.get(id) == null) { + throw exception(PRODUCT_NOT_EXISTS); + } + if (CommonStatusEnum.isDisable(product.getStatus())) { + throw exception(PRODUCT_NOT_ENABLE, product.getName()); + } + } + return list; + } + private void validateProductExists(Long id) { if (productMapper.selectById(id) == null) { throw exception(PRODUCT_NOT_EXISTS); @@ -79,8 +96,9 @@ public class ErpProductServiceImpl implements ErpProductService { } @Override - public List getProductListByStatus(Integer status) { - return productMapper.selectListByStatus(status); + public List getProductVOListByStatus(Integer status) { + List list = productMapper.selectListByStatus(status); + return buildProductVOList(list); } @Override diff --git a/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/service/stock/ErpStockInService.java b/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/service/stock/ErpStockInService.java new file mode 100644 index 000000000..92555135f --- /dev/null +++ b/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/service/stock/ErpStockInService.java @@ -0,0 +1,76 @@ +package cn.iocoder.yudao.module.erp.service.stock; + +import cn.iocoder.yudao.framework.common.pojo.PageResult; +import cn.iocoder.yudao.module.erp.controller.admin.stock.vo.in.ErpStockInPageReqVO; +import cn.iocoder.yudao.module.erp.controller.admin.stock.vo.in.ErpStockInSaveReqVO; +import cn.iocoder.yudao.module.erp.dal.dataobject.stock.ErpStockInDO; +import cn.iocoder.yudao.module.erp.dal.dataobject.stock.ErpStockInItemDO; +import jakarta.validation.Valid; + +import java.util.Collection; +import java.util.List; + +/** + * ERP 其它入库单 Service 接口 + * + * @author 芋道源码 + */ +public interface ErpStockInService { + + /** + * 创建其它入库单 + * + * @param createReqVO 创建信息 + * @return 编号 + */ + Long createStockIn(@Valid ErpStockInSaveReqVO createReqVO); + + /** + * 更新其它入库单 + * + * @param updateReqVO 更新信息 + */ + void updateStockIn(@Valid ErpStockInSaveReqVO updateReqVO); + + /** + * 删除其它入库单 + * + * @param id 编号 + */ + void deleteStockIn(Long id); + + /** + * 获得其它入库单 + * + * @param id 编号 + * @return 其它入库单 + */ + ErpStockInDO getStockIn(Long id); + + /** + * 获得其它入库单分页 + * + * @param pageReqVO 分页查询 + * @return 其它入库单分页 + */ + PageResult getStockInPage(ErpStockInPageReqVO pageReqVO); + + // ==================== 入库项 ==================== + + /** + * 获得其它入库单项列表 + * + * @param inId 入库编号 + * @return 其它入库单项列表 + */ + List getStockInItemListByInId(Long inId); + + /** + * 获得其它入库单项 List + * + * @param inIds 入库编号数组 + * @return 其它入库单项 List + */ + List getStockInItemListByInIds(Collection inIds); + +} \ No newline at end of file diff --git a/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/service/stock/ErpStockInServiceImpl.java b/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/service/stock/ErpStockInServiceImpl.java new file mode 100644 index 000000000..4945d8111 --- /dev/null +++ b/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/service/stock/ErpStockInServiceImpl.java @@ -0,0 +1,162 @@ +package cn.iocoder.yudao.module.erp.service.stock; + +import cn.hutool.core.collection.CollUtil; +import cn.iocoder.yudao.framework.common.pojo.PageResult; +import cn.iocoder.yudao.framework.common.util.object.BeanUtils; +import cn.iocoder.yudao.module.erp.controller.admin.stock.vo.in.ErpStockInPageReqVO; +import cn.iocoder.yudao.module.erp.controller.admin.stock.vo.in.ErpStockInSaveReqVO; +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.ErpStockInItemDO; +import cn.iocoder.yudao.module.erp.dal.mysql.stock.ErpStockInItemMapper; +import cn.iocoder.yudao.module.erp.dal.mysql.stock.ErpStockInMapper; +import cn.iocoder.yudao.module.erp.enums.ErpAuditStatus; +import cn.iocoder.yudao.module.erp.service.product.ErpProductService; +import jakarta.annotation.Resource; +import org.springframework.stereotype.Service; +import org.springframework.transaction.annotation.Transactional; +import org.springframework.validation.annotation.Validated; + +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.exception.util.ServiceExceptionUtil.exception; +import static cn.iocoder.yudao.framework.common.util.collection.CollectionUtils.*; +import static cn.iocoder.yudao.module.erp.enums.ErrorCodeConstants.STOCK_IN_NOT_EXISTS; + + +/** + * ERP 其它入库单 Service 实现类 + * + * @author 芋道源码 + */ +@Service +@Validated +public class ErpStockInServiceImpl implements ErpStockInService { + + @Resource + private ErpStockInMapper stockInMapper; + @Resource + private ErpStockInItemMapper stockInItemMapper; + + @Resource + private ErpProductService productService; + @Resource + private ErpWarehouseService warehouseService; + + @Override + @Transactional(rollbackFor = Exception.class) + public Long createStockIn(ErpStockInSaveReqVO createReqVO) { + // 1.1 校验入库项的有效性 + List stockInItems = validateStockInItems(createReqVO.getItems()); + // 1.2 TODO 芋艿:校验供应商 + + // 2.1 插入入库单 + ErpStockInDO stockIn = BeanUtils.toBean(createReqVO, ErpStockInDO.class, in -> in + .setStatus(ErpAuditStatus.PROCESS.getStatus()) + .setTotalCount(getSumValue(stockInItems, ErpStockInItemDO::getCount, BigDecimal::add)) + .setTotalPrice(getSumValue(stockInItems, ErpStockInItemDO::getTotalPrice, BigDecimal::add))); + stockInMapper.insert(stockIn); + // 2. 插入子表 + stockInItems.forEach(o -> o.setInId(stockIn.getId())); + stockInItemMapper.insertBatch(stockInItems); + return stockIn.getId(); + } + + @Override + @Transactional(rollbackFor = Exception.class) + public void updateStockIn(ErpStockInSaveReqVO updateReqVO) { + // 1.1 校验存在 + validateStockInExists(updateReqVO.getId()); + // 1.2 TODO 芋艿:校验供应商 + // 1.3 校验入库项的有效性 + List stockInItems = validateStockInItems(updateReqVO.getItems()); + + // 2.1 更新入库单 + ErpStockInDO updateObj = BeanUtils.toBean(updateReqVO, ErpStockInDO.class, in -> in + .setTotalCount(getSumValue(stockInItems, ErpStockInItemDO::getCount, BigDecimal::add)) + .setTotalPrice(getSumValue(stockInItems, ErpStockInItemDO::getTotalPrice, BigDecimal::add))); + stockInMapper.updateById(updateObj); + // 2.2 更新入库单项 + updateStockInItemList(updateReqVO.getId(), stockInItems); + } + + private List validateStockInItems(List list) { + // 1.1 校验产品存在 + List productList = productService.validProductList(convertSet(list, ErpStockInSaveReqVO.Item::getProductId)); + Map productMap = convertMap(productList, ErpProductDO::getId); + // 1.2 校验仓库存在 + warehouseService.validWarehouseList(convertSet(list, ErpStockInSaveReqVO.Item::getWarehouseId)); + // 2. 转化为 ErpStockInItemDO 列表 + return convertList(list, o -> BeanUtils.toBean(o, ErpStockInItemDO.class, item -> item + .setProductUnitId(productMap.get(item.getProductId()).getUnitId()) + .setTotalPrice(item.getProductPrice().multiply(item.getCount())))); + } + + private void updateStockInItemList(Long id, List newList) { + // 第一步,对比新老数据,获得添加、修改、删除的列表 + List oldList = stockInItemMapper.selectListByInId(id); + List> diffList = diffList(oldList, newList, // id 不同,就认为是不同的记录 + (oldVal, newVal) -> oldVal.getId().equals(newVal.getId())); + + // 第二步,批量添加、修改、删除 + if (CollUtil.isNotEmpty(diffList.get(0))) { + diffList.get(0).forEach(o -> o.setInId(id)); + stockInItemMapper.insertBatch(diffList.get(0)); + } + if (CollUtil.isNotEmpty(diffList.get(1))) { + stockInItemMapper.updateBatch(diffList.get(1)); + } + if (CollUtil.isNotEmpty(diffList.get(2))) { + stockInItemMapper.deleteBatchIds(convertList(diffList.get(2), ErpStockInItemDO::getId)); + } + } + + @Override + @Transactional(rollbackFor = Exception.class) + public void deleteStockIn(Long id) { + // 1. 校验存在 + validateStockInExists(id); + // TODO 芋艿:校验一下; + + // 2.1 删除 + stockInMapper.deleteById(id); + // 2.2 删除子表 + stockInItemMapper.deleteByInId(id); + } + + private void validateStockInExists(Long id) { + if (stockInMapper.selectById(id) == null) { + throw exception(STOCK_IN_NOT_EXISTS); + } + } + + @Override + public ErpStockInDO getStockIn(Long id) { + return stockInMapper.selectById(id); + } + + @Override + public PageResult getStockInPage(ErpStockInPageReqVO pageReqVO) { + return stockInMapper.selectPage(pageReqVO); + } + + // ==================== 子表(ERP 其它入库单项) ==================== + + @Override + public List getStockInItemListByInId(Long inId) { + return stockInItemMapper.selectListByInId(inId); + } + + @Override + public List getStockInItemListByInIds(Collection inIds) { + if (CollUtil.isEmpty(inIds)) { + return Collections.emptyList(); + } + return stockInItemMapper.selectListByInIds(inIds); + } + +} \ No newline at end of file diff --git a/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/service/stock/ErpStockRecordService.java b/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/service/stock/ErpStockRecordService.java index 8b90a0e4c..08acb89b5 100644 --- a/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/service/stock/ErpStockRecordService.java +++ b/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/service/stock/ErpStockRecordService.java @@ -1,7 +1,7 @@ package cn.iocoder.yudao.module.erp.service.stock; import cn.iocoder.yudao.framework.common.pojo.PageResult; -import cn.iocoder.yudao.module.erp.controller.admin.stock.vo.stockrecord.ErpStockRecordPageReqVO; +import cn.iocoder.yudao.module.erp.controller.admin.stock.vo.record.ErpStockRecordPageReqVO; import cn.iocoder.yudao.module.erp.dal.dataobject.stock.ErpStockRecordDO; /** diff --git a/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/service/stock/ErpStockRecordServiceImpl.java b/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/service/stock/ErpStockRecordServiceImpl.java index 0adc7c864..6f50b91cc 100644 --- a/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/service/stock/ErpStockRecordServiceImpl.java +++ b/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/service/stock/ErpStockRecordServiceImpl.java @@ -1,7 +1,7 @@ package cn.iocoder.yudao.module.erp.service.stock; import cn.iocoder.yudao.framework.common.pojo.PageResult; -import cn.iocoder.yudao.module.erp.controller.admin.stock.vo.stockrecord.ErpStockRecordPageReqVO; +import cn.iocoder.yudao.module.erp.controller.admin.stock.vo.record.ErpStockRecordPageReqVO; import cn.iocoder.yudao.module.erp.dal.dataobject.stock.ErpStockRecordDO; import cn.iocoder.yudao.module.erp.dal.mysql.stock.ErpStockRecordMapper; import jakarta.annotation.Resource; diff --git a/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/service/stock/ErpStockService.java b/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/service/stock/ErpStockService.java index 041aca6d5..f9cd26158 100644 --- a/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/service/stock/ErpStockService.java +++ b/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/service/stock/ErpStockService.java @@ -19,6 +19,15 @@ public interface ErpStockService { */ ErpStockDO getStock(Long id); + /** + * 基于产品 + 仓库,获得产品库存 + * + * @param productId 产品编号 + * @param warehouseId 仓库编号 + * @return 产品库存 + */ + ErpStockDO getStock(Long productId, Long warehouseId); + /** * 获得产品库存分页 * diff --git a/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/service/stock/ErpStockServiceImpl.java b/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/service/stock/ErpStockServiceImpl.java index 7ee4a3fc0..423774265 100644 --- a/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/service/stock/ErpStockServiceImpl.java +++ b/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/service/stock/ErpStockServiceImpl.java @@ -25,6 +25,11 @@ public class ErpStockServiceImpl implements ErpStockService { return stockMapper.selectById(id); } + @Override + public ErpStockDO getStock(Long productId, Long warehouseId) { + return stockMapper.selectByProductIdAndWarehouseId(productId, warehouseId); + } + @Override public PageResult getStockPage(ErpStockPageReqVO pageReqVO) { return stockMapper.selectPage(pageReqVO); diff --git a/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/service/stock/ErpWarehouseService.java b/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/service/stock/ErpWarehouseService.java index 6f9d3c8fa..872a698de 100644 --- a/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/service/stock/ErpWarehouseService.java +++ b/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/service/stock/ErpWarehouseService.java @@ -57,6 +57,14 @@ public interface ErpWarehouseService { */ ErpWarehouseDO getWarehouse(Long id); + /** + * 校验仓库列表的有效性 + * + * @param ids 编号数组 + * @return 仓库列表 + */ + List validWarehouseList(Collection ids); + /** * 获得指定状态的仓库列表 * diff --git a/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/service/stock/ErpWarehouseServiceImpl.java b/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/service/stock/ErpWarehouseServiceImpl.java index e2f6d7667..fb4829146 100644 --- a/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/service/stock/ErpWarehouseServiceImpl.java +++ b/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/service/stock/ErpWarehouseServiceImpl.java @@ -1,9 +1,12 @@ package cn.iocoder.yudao.module.erp.service.stock; +import cn.hutool.core.collection.CollUtil; +import cn.iocoder.yudao.framework.common.enums.CommonStatusEnum; import cn.iocoder.yudao.framework.common.pojo.PageResult; import cn.iocoder.yudao.framework.common.util.object.BeanUtils; import cn.iocoder.yudao.module.erp.controller.admin.stock.vo.ErpWarehouseSaveReqVO; import cn.iocoder.yudao.module.erp.controller.admin.stock.vo.warehouse.ErpWarehousePageReqVO; +import cn.iocoder.yudao.module.erp.dal.dataobject.product.ErpProductDO; import cn.iocoder.yudao.module.erp.dal.dataobject.stock.ErpWarehouseDO; import cn.iocoder.yudao.module.erp.dal.mysql.stock.ErpWarehouseMapper; import jakarta.annotation.Resource; @@ -12,10 +15,13 @@ import org.springframework.transaction.annotation.Transactional; import org.springframework.validation.annotation.Validated; import java.util.Collection; +import java.util.Collections; import java.util.List; +import java.util.Map; import static cn.iocoder.yudao.framework.common.exception.util.ServiceExceptionUtil.exception; -import static cn.iocoder.yudao.module.erp.enums.ErrorCodeConstants.WAREHOUSE_NOT_EXISTS; +import static cn.iocoder.yudao.framework.common.util.collection.CollectionUtils.convertMap; +import static cn.iocoder.yudao.module.erp.enums.ErrorCodeConstants.*; /** * ERP 仓库 Service 实现类 @@ -83,6 +89,25 @@ public class ErpWarehouseServiceImpl implements ErpWarehouseService { return warehouseMapper.selectById(id); } + @Override + public List validWarehouseList(Collection ids) { + if (CollUtil.isEmpty(ids)) { + return Collections.emptyList(); + } + List list = warehouseMapper.selectBatchIds(ids); + Map warehouseMap = convertMap(list, ErpWarehouseDO::getId); + for (Long id : ids) { + ErpWarehouseDO warehouse = warehouseMap.get(id); + if (warehouseMap.get(id) == null) { + throw exception(WAREHOUSE_NOT_EXISTS); + } + if (CommonStatusEnum.isDisable(warehouse.getStatus())) { + throw exception(WAREHOUSE_NOT_ENABLE, warehouse.getName()); + } + } + return list; + } + @Override public List getWarehouseListByStatus(Integer status) { return warehouseMapper.selectListByStatus(status); From bfe3dc95fe7c6b428c91012782adff5ae43a38c4 Mon Sep 17 00:00:00 2001 From: YunaiV Date: Tue, 6 Feb 2024 17:59:44 +0800 Subject: [PATCH 078/119] =?UTF-8?q?=E2=9C=A8=20ERP=EF=BC=9A=E5=A2=9E?= =?UTF-8?q?=E5=8A=A0=E4=BE=9B=E5=BA=94=E5=95=86=E7=9A=84=E5=AE=9E=E7=8E=B0?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../module/erp/enums/ErrorCodeConstants.java | 10 +- .../admin/purchase/ErpSupplierController.java | 102 ++++++++++++++++++ .../vo/supplier/ErpSupplierPageReqVO.java | 24 +++++ .../vo/supplier/ErpSupplierRespVO.java | 84 +++++++++++++++ .../vo/supplier/ErpSupplierSaveReqVO.java | 71 ++++++++++++ .../admin/stock/ErpStockInController.java | 12 ++- .../stock/vo/in/ErpStockInPageReqVO.java | 6 ++ .../admin/stock/vo/in/ErpStockInRespVO.java | 4 +- .../dataobject/supplier/ErpSupplierDO.java | 90 ++++++++++++++++ .../dal/mysql/purchase/ErpSupplierMapper.java | 32 ++++++ .../erp/dal/mysql/stock/ErpStockInMapper.java | 14 ++- .../product/ErpProductServiceImpl.java | 2 + .../service/purchase/ErpSupplierService.java | 94 ++++++++++++++++ .../purchase/ErpSupplierServiceImpl.java | 94 ++++++++++++++++ .../service/stock/ErpStockInServiceImpl.java | 9 +- .../mapper/supplier/ErpSupplierMapper.xml | 12 +++ .../src/main/resources/application-local.yaml | 1 + 17 files changed, 650 insertions(+), 11 deletions(-) create mode 100644 yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/controller/admin/purchase/ErpSupplierController.java create mode 100644 yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/controller/admin/purchase/vo/supplier/ErpSupplierPageReqVO.java create mode 100644 yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/controller/admin/purchase/vo/supplier/ErpSupplierRespVO.java create mode 100644 yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/controller/admin/purchase/vo/supplier/ErpSupplierSaveReqVO.java create mode 100644 yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/dal/dataobject/supplier/ErpSupplierDO.java create mode 100644 yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/dal/mysql/purchase/ErpSupplierMapper.java create mode 100644 yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/service/purchase/ErpSupplierService.java create mode 100644 yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/service/purchase/ErpSupplierServiceImpl.java create mode 100644 yudao-module-erp/yudao-module-erp-biz/src/main/resources/mapper/supplier/ErpSupplierMapper.xml diff --git a/yudao-module-erp/yudao-module-erp-api/src/main/java/cn/iocoder/yudao/module/erp/enums/ErrorCodeConstants.java b/yudao-module-erp/yudao-module-erp-api/src/main/java/cn/iocoder/yudao/module/erp/enums/ErrorCodeConstants.java index e4db13763..1cc2807ad 100644 --- a/yudao-module-erp/yudao-module-erp-api/src/main/java/cn/iocoder/yudao/module/erp/enums/ErrorCodeConstants.java +++ b/yudao-module-erp/yudao-module-erp-api/src/main/java/cn/iocoder/yudao/module/erp/enums/ErrorCodeConstants.java @@ -9,12 +9,16 @@ import cn.iocoder.yudao.framework.common.exception.ErrorCode; */ public interface ErrorCodeConstants { - // ========== 销售订单(1-020-000-000) ========== - ErrorCode SALE_ORDER_NOT_EXISTS = new ErrorCode(1_020_000_000, "销售订单不存在"); + // ========== ERP 供应商(1-030-100-000) ========== + ErrorCode SUPPLIER_NOT_EXISTS = new ErrorCode(1_030_100_000, "供应商不存在"); + ErrorCode SUPPLIER_NOT_ENABLE = new ErrorCode(1_030_100_000, "供应商({})未启用"); + + // ========== 销售订单(1-030-200-000) ========== + ErrorCode SALE_ORDER_NOT_EXISTS = new ErrorCode(1_020_200_000, "销售订单不存在"); // ========== ERP 仓库 1-030-400-000 ========== ErrorCode WAREHOUSE_NOT_EXISTS = new ErrorCode(1_030_400_000, "仓库不存在"); - ErrorCode WAREHOUSE_NOT_ENABLE = new ErrorCode(1_030_500_001, "仓库({})未启用"); + ErrorCode WAREHOUSE_NOT_ENABLE = new ErrorCode(1_030_400_001, "仓库({})未启用"); // ========== ERP 其它入库单 1-030-401-000 ========== ErrorCode STOCK_IN_NOT_EXISTS = new ErrorCode(1_030_401_000, "其它入库单不存在"); diff --git a/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/controller/admin/purchase/ErpSupplierController.java b/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/controller/admin/purchase/ErpSupplierController.java new file mode 100644 index 000000000..60893ea57 --- /dev/null +++ b/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/controller/admin/purchase/ErpSupplierController.java @@ -0,0 +1,102 @@ +package cn.iocoder.yudao.module.erp.controller.admin.purchase; + +import cn.iocoder.yudao.framework.common.enums.CommonStatusEnum; +import cn.iocoder.yudao.framework.common.pojo.CommonResult; +import cn.iocoder.yudao.framework.common.pojo.PageParam; +import cn.iocoder.yudao.framework.common.pojo.PageResult; +import cn.iocoder.yudao.framework.common.util.object.BeanUtils; +import cn.iocoder.yudao.framework.excel.core.util.ExcelUtils; +import cn.iocoder.yudao.framework.operatelog.core.annotations.OperateLog; +import cn.iocoder.yudao.module.erp.controller.admin.purchase.vo.supplier.ErpSupplierPageReqVO; +import cn.iocoder.yudao.module.erp.controller.admin.purchase.vo.supplier.ErpSupplierRespVO; +import cn.iocoder.yudao.module.erp.controller.admin.purchase.vo.supplier.ErpSupplierSaveReqVO; +import cn.iocoder.yudao.module.erp.dal.dataobject.supplier.ErpSupplierDO; +import cn.iocoder.yudao.module.erp.service.purchase.ErpSupplierService; +import io.swagger.v3.oas.annotations.Operation; +import io.swagger.v3.oas.annotations.Parameter; +import io.swagger.v3.oas.annotations.tags.Tag; +import jakarta.annotation.Resource; +import jakarta.servlet.http.HttpServletResponse; +import jakarta.validation.Valid; +import org.springframework.security.access.prepost.PreAuthorize; +import org.springframework.validation.annotation.Validated; +import org.springframework.web.bind.annotation.*; + +import java.io.IOException; +import java.util.List; + +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.operatelog.core.enums.OperateTypeEnum.EXPORT; + +@Tag(name = "管理后台 - ERP 供应商") +@RestController +@RequestMapping("/erp/supplier") +@Validated +public class ErpSupplierController { + + @Resource + private ErpSupplierService supplierService; + + @PostMapping("/create") + @Operation(summary = "创建供应商") + @PreAuthorize("@ss.hasPermission('erp:supplier:create')") + public CommonResult createSupplier(@Valid @RequestBody ErpSupplierSaveReqVO createReqVO) { + return success(supplierService.createSupplier(createReqVO)); + } + + @PutMapping("/update") + @Operation(summary = "更新供应商") + @PreAuthorize("@ss.hasPermission('erp:supplier:update')") + public CommonResult updateSupplier(@Valid @RequestBody ErpSupplierSaveReqVO updateReqVO) { + supplierService.updateSupplier(updateReqVO); + return success(true); + } + + @DeleteMapping("/delete") + @Operation(summary = "删除供应商") + @Parameter(name = "id", description = "编号", required = true) + @PreAuthorize("@ss.hasPermission('erp:supplier:delete')") + public CommonResult deleteSupplier(@RequestParam("id") Long id) { + supplierService.deleteSupplier(id); + return success(true); + } + + @GetMapping("/get") + @Operation(summary = "获得供应商") + @Parameter(name = "id", description = "编号", required = true, example = "1024") + @PreAuthorize("@ss.hasPermission('erp:supplier:query')") + public CommonResult getSupplier(@RequestParam("id") Long id) { + ErpSupplierDO supplier = supplierService.getSupplier(id); + return success(BeanUtils.toBean(supplier, ErpSupplierRespVO.class)); + } + + @GetMapping("/page") + @Operation(summary = "获得供应商分页") + @PreAuthorize("@ss.hasPermission('erp:supplier:query')") + public CommonResult> getSupplierPage(@Valid ErpSupplierPageReqVO pageReqVO) { + PageResult pageResult = supplierService.getSupplierPage(pageReqVO); + return success(BeanUtils.toBean(pageResult, ErpSupplierRespVO.class)); + } + + @GetMapping("/simple-list") + @Operation(summary = "获得供应商精简列表", description = "只包含被开启的供应商,主要用于前端的下拉选项") + public CommonResult> getSupplierSimpleList() { + List list = supplierService.getSupplierListByStatus(CommonStatusEnum.ENABLE.getStatus()); + return success(convertList(list, supplier -> new ErpSupplierRespVO().setId(supplier.getId()).setName(supplier.getName()))); + } + + @GetMapping("/export-excel") + @Operation(summary = "导出供应商 Excel") + @PreAuthorize("@ss.hasPermission('erp:supplier:export')") + @OperateLog(type = EXPORT) + public void exportSupplierExcel(@Valid ErpSupplierPageReqVO pageReqVO, + HttpServletResponse response) throws IOException { + pageReqVO.setPageSize(PageParam.PAGE_SIZE_NONE); + List list = supplierService.getSupplierPage(pageReqVO).getList(); + // 导出 Excel + ExcelUtils.write(response, "供应商.xls", "数据", ErpSupplierRespVO.class, + BeanUtils.toBean(list, ErpSupplierRespVO.class)); + } + +} \ No newline at end of file diff --git a/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/controller/admin/purchase/vo/supplier/ErpSupplierPageReqVO.java b/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/controller/admin/purchase/vo/supplier/ErpSupplierPageReqVO.java new file mode 100644 index 000000000..229ab63d9 --- /dev/null +++ b/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/controller/admin/purchase/vo/supplier/ErpSupplierPageReqVO.java @@ -0,0 +1,24 @@ +package cn.iocoder.yudao.module.erp.controller.admin.purchase.vo.supplier; + +import cn.iocoder.yudao.framework.common.pojo.PageParam; +import io.swagger.v3.oas.annotations.media.Schema; +import lombok.Data; +import lombok.EqualsAndHashCode; +import lombok.ToString; + +@Schema(description = "管理后台 - ERP 供应商分页 Request VO") +@Data +@EqualsAndHashCode(callSuper = true) +@ToString(callSuper = true) +public class ErpSupplierPageReqVO extends PageParam { + + @Schema(description = "供应商名称", example = "芋道源码") + private String name; + + @Schema(description = "手机号码", example = "15601691300") + private String mobile; + + @Schema(description = "联系电话", example = "18818288888") + private String telephone; + +} \ No newline at end of file diff --git a/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/controller/admin/purchase/vo/supplier/ErpSupplierRespVO.java b/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/controller/admin/purchase/vo/supplier/ErpSupplierRespVO.java new file mode 100644 index 000000000..5ba5892c1 --- /dev/null +++ b/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/controller/admin/purchase/vo/supplier/ErpSupplierRespVO.java @@ -0,0 +1,84 @@ +package cn.iocoder.yudao.module.erp.controller.admin.purchase.vo.supplier; + +import cn.iocoder.yudao.framework.excel.core.annotations.DictFormat; +import cn.iocoder.yudao.framework.excel.core.convert.DictConvert; +import cn.iocoder.yudao.module.system.enums.DictTypeConstants; +import com.alibaba.excel.annotation.ExcelIgnoreUnannotated; +import com.alibaba.excel.annotation.ExcelProperty; +import io.swagger.v3.oas.annotations.media.Schema; +import lombok.Data; + +import java.math.BigDecimal; +import java.time.LocalDateTime; + +@Schema(description = "管理后台 - ERP 供应商 Response VO") +@Data +@ExcelIgnoreUnannotated +public class ErpSupplierRespVO { + + @Schema(description = "供应商编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "17791") + @ExcelProperty("供应商编号") + private Long id; + + @Schema(description = "供应商名称", requiredMode = Schema.RequiredMode.REQUIRED, example = "芋道源码") + @ExcelProperty("供应商名称") + private String name; + + @Schema(description = "联系人", example = "芋艿") + @ExcelProperty("联系人") + private String contact; + + @Schema(description = "手机号码", example = "15601691300") + @ExcelProperty("手机号码") + private String mobile; + + @Schema(description = "联系电话", example = "18818288888") + @ExcelProperty("联系电话") + private String telephone; + + @Schema(description = "电子邮箱", example = "76853@qq.com") + @ExcelProperty("电子邮箱") + private String email; + + @Schema(description = "传真", example = "20 7123 4567") + @ExcelProperty("传真") + private String fax; + + @Schema(description = "备注", example = "你猜") + @ExcelProperty("备注") + private String remark; + + @Schema(description = "开启状态", requiredMode = Schema.RequiredMode.REQUIRED, example = "1") + @ExcelProperty(value = "开启状态", converter = DictConvert.class) + @DictFormat(DictTypeConstants.COMMON_STATUS) + private Integer status; + + @Schema(description = "排序", requiredMode = Schema.RequiredMode.REQUIRED, example = "10") + @ExcelProperty("排序") + private Integer sort; + + @Schema(description = "纳税人识别号", example = "91130803MA098BY05W") + @ExcelProperty("纳税人识别号") + private String taxNo; + + @Schema(description = "税率", example = "10") + @ExcelProperty("税率") + private BigDecimal taxPercent; + + @Schema(description = "开户行", example = "张三") + @ExcelProperty("开户行") + private String bankName; + + @Schema(description = "开户账号", example = "622908212277228617") + @ExcelProperty("开户账号") + private String bankAccount; + + @Schema(description = "开户地址", example = "兴业银行浦东支行") + @ExcelProperty("开户地址") + private String bankAddress; + + @Schema(description = "创建时间", requiredMode = Schema.RequiredMode.REQUIRED) + @ExcelProperty("创建时间") + private LocalDateTime createTime; + +} \ No newline at end of file diff --git a/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/controller/admin/purchase/vo/supplier/ErpSupplierSaveReqVO.java b/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/controller/admin/purchase/vo/supplier/ErpSupplierSaveReqVO.java new file mode 100644 index 000000000..2291de050 --- /dev/null +++ b/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/controller/admin/purchase/vo/supplier/ErpSupplierSaveReqVO.java @@ -0,0 +1,71 @@ +package cn.iocoder.yudao.module.erp.controller.admin.purchase.vo.supplier; + +import cn.iocoder.yudao.framework.common.enums.CommonStatusEnum; +import cn.iocoder.yudao.framework.common.validation.InEnum; +import cn.iocoder.yudao.framework.common.validation.Mobile; +import cn.iocoder.yudao.framework.common.validation.Telephone; +import io.swagger.v3.oas.annotations.media.Schema; +import jakarta.validation.constraints.Email; +import jakarta.validation.constraints.NotEmpty; +import jakarta.validation.constraints.NotNull; +import lombok.Data; + +import java.math.BigDecimal; + +@Schema(description = "管理后台 - ERP 供应商新增/修改 Request VO") +@Data +public class ErpSupplierSaveReqVO { + + @Schema(description = "供应商编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "17791") + private Long id; + + @Schema(description = "供应商名称", requiredMode = Schema.RequiredMode.REQUIRED, example = "芋道源码") + @NotEmpty(message = "供应商名称不能为空") + private String name; + + @Schema(description = "联系人", example = "芋艿") + private String contact; + + @Schema(description = "手机号码", example = "15601691300") + @Mobile + private String mobile; + + @Schema(description = "联系电话", example = "18818288888") + @Telephone + private String telephone; + + @Schema(description = "电子邮箱", example = "76853@qq.com") + @Email + private String email; + + @Schema(description = "传真", example = "20 7123 4567") + private String fax; + + @Schema(description = "备注", example = "你猜") + private String remark; + + @Schema(description = "开启状态", requiredMode = Schema.RequiredMode.REQUIRED, example = "1") + @NotNull(message = "开启状态不能为空") + @InEnum(value = CommonStatusEnum.class) + private Integer status; + + @Schema(description = "排序", requiredMode = Schema.RequiredMode.REQUIRED, example = "10") + @NotNull(message = "排序不能为空") + private Integer sort; + + @Schema(description = "纳税人识别号", example = "91130803MA098BY05W") + private String taxNo; + + @Schema(description = "税率", example = "10") + private BigDecimal taxPercent; + + @Schema(description = "开户行", example = "张三") + private String bankName; + + @Schema(description = "开户账号", example = "622908212277228617") + private String bankAccount; + + @Schema(description = "开户地址", example = "兴业银行浦东支行") + private String bankAddress; + +} \ No newline at end of file diff --git a/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/controller/admin/stock/ErpStockInController.java b/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/controller/admin/stock/ErpStockInController.java index 192fbf50a..1351516ed 100644 --- a/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/controller/admin/stock/ErpStockInController.java +++ b/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/controller/admin/stock/ErpStockInController.java @@ -15,7 +15,9 @@ import cn.iocoder.yudao.module.erp.controller.admin.stock.vo.in.ErpStockInSaveRe import cn.iocoder.yudao.module.erp.dal.dataobject.stock.ErpStockDO; import cn.iocoder.yudao.module.erp.dal.dataobject.stock.ErpStockInDO; import cn.iocoder.yudao.module.erp.dal.dataobject.stock.ErpStockInItemDO; +import cn.iocoder.yudao.module.erp.dal.dataobject.supplier.ErpSupplierDO; import cn.iocoder.yudao.module.erp.service.product.ErpProductService; +import cn.iocoder.yudao.module.erp.service.purchase.ErpSupplierService; import cn.iocoder.yudao.module.erp.service.stock.ErpStockInService; import cn.iocoder.yudao.module.erp.service.stock.ErpStockService; import cn.iocoder.yudao.module.system.api.user.AdminUserApi; @@ -52,6 +54,8 @@ public class ErpStockInController { private ErpStockService stockService; @Resource private ErpProductService productService; + @Resource + private ErpSupplierService supplierService; @Resource private AdminUserApi adminUserApi; @@ -90,7 +94,7 @@ public class ErpStockInController { return success(null); } List stockInItems = stockInService.getStockInItemListByInId(id); - + // TODO 芋艿:有个锤子; return success(BeanUtils.toBean(stockIn, ErpStockInRespVO.class, stockInVO -> stockInVO.setItems(BeanUtils.toBean(stockInItems, ErpStockInRespVO.Item.class, item -> { ErpStockDO stock = stockService.getStock(item.getProductId(), item.getWarehouseId()); @@ -129,7 +133,10 @@ public class ErpStockInController { // 1.2 商品信息 Map productMap = productService.getProductVOMap( convertSet(stockInItemList, ErpStockInItemDO::getProductId)); - // 1.3 管理员信息 + // 1.3 供应商信息 + Map supplierMap = supplierService.getSupplierMap( + convertSet(pageResult.getList(), ErpStockInDO::getSupplierId)); + // 1.4 管理员信息 Map userMap = adminUserApi.getUserMap( convertSet(pageResult.getList(), erpStockRecordDO -> Long.parseLong(erpStockRecordDO.getCreator()))); // 2. 开始拼接 @@ -138,6 +145,7 @@ public class ErpStockInController { item -> MapUtils.findAndThen(productMap, item.getProductId(), product -> item.setProductName(product.getName()).setProductUnitName(product.getUnitName())))); stockIn.setProductNames(CollUtil.join(stockIn.getItems(), ",", ErpStockInRespVO.Item::getProductName)); + MapUtils.findAndThen(supplierMap, stockIn.getSupplierId(), supplier -> stockIn.setSupplierName(supplier.getName())); MapUtils.findAndThen(userMap, Long.parseLong(stockIn.getCreator()), user -> stockIn.setCreatorName(user.getNickname())); }); } diff --git a/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/controller/admin/stock/vo/in/ErpStockInPageReqVO.java b/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/controller/admin/stock/vo/in/ErpStockInPageReqVO.java index 05f1915ce..02e3db37a 100644 --- a/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/controller/admin/stock/vo/in/ErpStockInPageReqVO.java +++ b/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/controller/admin/stock/vo/in/ErpStockInPageReqVO.java @@ -39,4 +39,10 @@ public class ErpStockInPageReqVO extends PageParam { @Schema(description = "创建者") private String creator; + @Schema(description = "产品编号", example = "1") + private Long productId; + + @Schema(description = "仓库编号", example = "1") + private Long warehouseId; + } \ No newline at end of file diff --git a/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/controller/admin/stock/vo/in/ErpStockInRespVO.java b/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/controller/admin/stock/vo/in/ErpStockInRespVO.java index 429ec77a4..07897ad30 100644 --- a/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/controller/admin/stock/vo/in/ErpStockInRespVO.java +++ b/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/controller/admin/stock/vo/in/ErpStockInRespVO.java @@ -27,8 +27,10 @@ public class ErpStockInRespVO { private String no; @Schema(description = "供应商编号", example = "3113") - @ExcelProperty("供应商编号") private Long supplierId; + @Schema(description = "供应商名称", example = "芋道") + @ExcelProperty("供应商名称") + private String supplierName; @Schema(description = "入库时间", requiredMode = Schema.RequiredMode.REQUIRED) @ExcelProperty("入库时间") diff --git a/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/dal/dataobject/supplier/ErpSupplierDO.java b/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/dal/dataobject/supplier/ErpSupplierDO.java new file mode 100644 index 000000000..108922a22 --- /dev/null +++ b/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/dal/dataobject/supplier/ErpSupplierDO.java @@ -0,0 +1,90 @@ +package cn.iocoder.yudao.module.erp.dal.dataobject.supplier; + +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.*; + +import java.math.BigDecimal; + +/** + * ERP 供应商 DO + * + * @author 芋道源码 + */ +@TableName("erp_supplier") +@KeySequence("erp_supplier_seq") // 用于 Oracle、PostgreSQL、Kingbase、DB2、H2 数据库的主键自增。如果是 MySQL 等数据库,可不写。 +@Data +@EqualsAndHashCode(callSuper = true) +@ToString(callSuper = true) +@Builder +@NoArgsConstructor +@AllArgsConstructor +public class ErpSupplierDO extends BaseDO { + + /** + * 供应商编号 + */ + @TableId + private Long id; + /** + * 供应商名称 + */ + private String name; + /** + * 联系人 + */ + private String contact; + /** + * 手机号码 + */ + private String mobile; + /** + * 联系电话 + */ + private String telephone; + /** + * 电子邮箱 + */ + private String email; + /** + * 传真 + */ + private String fax; + /** + * 备注 + */ + private String remark; + /** + * 开启状态 + * + * 枚举 {@link cn.iocoder.yudao.framework.common.enums.CommonStatusEnum} + */ + private Integer status; + /** + * 排序 + */ + private Integer sort; + /** + * 纳税人识别号 + */ + private String taxNo; + /** + * 税率 + */ + private BigDecimal taxPercent; + /** + * 开户行 + */ + private String bankName; + /** + * 开户账号 + */ + private String bankAccount; + /** + * 开户地址 + */ + private String bankAddress; + +} \ No newline at end of file diff --git a/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/dal/mysql/purchase/ErpSupplierMapper.java b/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/dal/mysql/purchase/ErpSupplierMapper.java new file mode 100644 index 000000000..93f3d6994 --- /dev/null +++ b/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/dal/mysql/purchase/ErpSupplierMapper.java @@ -0,0 +1,32 @@ +package cn.iocoder.yudao.module.erp.dal.mysql.purchase; + +import cn.iocoder.yudao.framework.common.pojo.PageResult; +import cn.iocoder.yudao.framework.mybatis.core.query.LambdaQueryWrapperX; +import cn.iocoder.yudao.framework.mybatis.core.mapper.BaseMapperX; +import cn.iocoder.yudao.module.erp.controller.admin.purchase.vo.supplier.ErpSupplierPageReqVO; +import cn.iocoder.yudao.module.erp.dal.dataobject.supplier.ErpSupplierDO; +import org.apache.ibatis.annotations.Mapper; + +import java.util.List; + +/** + * ERP 供应商 Mapper + * + * @author 芋道源码 + */ +@Mapper +public interface ErpSupplierMapper extends BaseMapperX { + + default PageResult selectPage(ErpSupplierPageReqVO reqVO) { + return selectPage(reqVO, new LambdaQueryWrapperX() + .likeIfPresent(ErpSupplierDO::getName, reqVO.getName()) + .likeIfPresent(ErpSupplierDO::getMobile, reqVO.getMobile()) + .likeIfPresent(ErpSupplierDO::getTelephone, reqVO.getTelephone()) + .orderByDesc(ErpSupplierDO::getId)); + } + + default List selectListByStatus(Integer status) { + return selectList(ErpSupplierDO::getStatus, status); + } + +} \ No newline at end of file diff --git a/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/dal/mysql/stock/ErpStockInMapper.java b/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/dal/mysql/stock/ErpStockInMapper.java index 782112129..0b3e71a5f 100644 --- a/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/dal/mysql/stock/ErpStockInMapper.java +++ b/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/dal/mysql/stock/ErpStockInMapper.java @@ -2,9 +2,10 @@ package cn.iocoder.yudao.module.erp.dal.mysql.stock; import cn.iocoder.yudao.framework.common.pojo.PageResult; import cn.iocoder.yudao.framework.mybatis.core.mapper.BaseMapperX; -import cn.iocoder.yudao.framework.mybatis.core.query.LambdaQueryWrapperX; +import cn.iocoder.yudao.framework.mybatis.core.query.MPJLambdaWrapperX; import cn.iocoder.yudao.module.erp.controller.admin.stock.vo.in.ErpStockInPageReqVO; import cn.iocoder.yudao.module.erp.dal.dataobject.stock.ErpStockInDO; +import cn.iocoder.yudao.module.erp.dal.dataobject.stock.ErpStockInItemDO; import org.apache.ibatis.annotations.Mapper; /** @@ -16,14 +17,21 @@ import org.apache.ibatis.annotations.Mapper; public interface ErpStockInMapper extends BaseMapperX { default PageResult selectPage(ErpStockInPageReqVO reqVO) { - return selectPage(reqVO, new LambdaQueryWrapperX() + MPJLambdaWrapperX query = new MPJLambdaWrapperX() .eqIfPresent(ErpStockInDO::getNo, reqVO.getNo()) .eqIfPresent(ErpStockInDO::getSupplierId, reqVO.getSupplierId()) .betweenIfPresent(ErpStockInDO::getInTime, reqVO.getInTime()) .eqIfPresent(ErpStockInDO::getStatus, reqVO.getStatus()) .likeIfPresent(ErpStockInDO::getRemark, reqVO.getRemark()) .eqIfPresent(ErpStockInDO::getCreator, reqVO.getCreator()) - .orderByDesc(ErpStockInDO::getId)); + .orderByDesc(ErpStockInDO::getId); + if (reqVO.getWarehouseId() != null || reqVO.getProductId() != null) { + query.leftJoin(ErpStockInItemDO.class, ErpStockInItemDO::getInId, ErpStockInDO::getId) + .eq(reqVO.getWarehouseId() != null, ErpStockInItemDO::getWarehouseId, reqVO.getWarehouseId()) + .eq(reqVO.getProductId() != null, ErpStockInItemDO::getProductId, reqVO.getProductId()) + .groupBy(ErpStockInDO::getId); // 避免 1 对多查询,产生相同的 1 + } + return selectJoinPage(reqVO, ErpStockInDO.class, query); } } \ No newline at end of file diff --git a/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/service/product/ErpProductServiceImpl.java b/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/service/product/ErpProductServiceImpl.java index 074fd3c29..53794043f 100644 --- a/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/service/product/ErpProductServiceImpl.java +++ b/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/service/product/ErpProductServiceImpl.java @@ -41,6 +41,7 @@ public class ErpProductServiceImpl implements ErpProductService { @Override public Long createProduct(ProductSaveReqVO createReqVO) { + // TODO 芋艿:校验分类 // 插入 ErpProductDO product = BeanUtils.toBean(createReqVO, ErpProductDO.class); productMapper.insert(product); @@ -50,6 +51,7 @@ public class ErpProductServiceImpl implements ErpProductService { @Override public void updateProduct(ProductSaveReqVO updateReqVO) { + // TODO 芋艿:校验分类 // 校验存在 validateProductExists(updateReqVO.getId()); // 更新 diff --git a/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/service/purchase/ErpSupplierService.java b/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/service/purchase/ErpSupplierService.java new file mode 100644 index 000000000..a2f6547c2 --- /dev/null +++ b/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/service/purchase/ErpSupplierService.java @@ -0,0 +1,94 @@ +package cn.iocoder.yudao.module.erp.service.purchase; + +import cn.iocoder.yudao.framework.common.pojo.PageResult; +import cn.iocoder.yudao.module.erp.controller.admin.purchase.vo.supplier.ErpSupplierPageReqVO; +import cn.iocoder.yudao.module.erp.controller.admin.purchase.vo.supplier.ErpSupplierSaveReqVO; +import cn.iocoder.yudao.module.erp.dal.dataobject.supplier.ErpSupplierDO; +import jakarta.validation.Valid; + +import java.util.Collection; +import java.util.List; +import java.util.Map; + +import static cn.iocoder.yudao.framework.common.util.collection.CollectionUtils.convertMap; + +/** + * ERP 供应商 Service 接口 + * + * @author 芋道源码 + */ +public interface ErpSupplierService { + + /** + * 创建供应商 + * + * @param createReqVO 创建信息 + * @return 编号 + */ + Long createSupplier(@Valid ErpSupplierSaveReqVO createReqVO); + + /** + * 更新供应商 + * + * @param updateReqVO 更新信息 + */ + void updateSupplier(@Valid ErpSupplierSaveReqVO updateReqVO); + + /** + * 删除供应商 + * + * @param id 编号 + */ + void deleteSupplier(Long id); + + /** + * 获得供应商 + * + * @param id 编号 + * @return 供应商 + */ + ErpSupplierDO getSupplier(Long id); + + /** + * 校验供应商 + * + * @param id 编号 + * @return 供应商 + */ + ErpSupplierDO validateSupplier(Long id); + + /** + * 获得供应商列表 + * + * @param ids 编号列表 + * @return 供应商列表 + */ + List getSupplierList(Collection ids); + + /** + * 获得供应商 Map + * + * @param ids 编号列表 + * @return 供应商 Map + */ + default Map getSupplierMap(Collection ids) { + return convertMap(getSupplierList(ids), ErpSupplierDO::getId); + } + + /** + * 获得供应商分页 + * + * @param pageReqVO 分页查询 + * @return 供应商分页 + */ + PageResult getSupplierPage(ErpSupplierPageReqVO pageReqVO); + + /** + * 获得指定状态的供应商列表 + * + * @param status 状态 + * @return 供应商列表 + */ + List getSupplierListByStatus(Integer status); + +} \ No newline at end of file diff --git a/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/service/purchase/ErpSupplierServiceImpl.java b/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/service/purchase/ErpSupplierServiceImpl.java new file mode 100644 index 000000000..09c789c57 --- /dev/null +++ b/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/service/purchase/ErpSupplierServiceImpl.java @@ -0,0 +1,94 @@ +package cn.iocoder.yudao.module.erp.service.purchase; + +import cn.iocoder.yudao.framework.common.enums.CommonStatusEnum; +import cn.iocoder.yudao.framework.common.pojo.PageResult; +import cn.iocoder.yudao.framework.common.util.object.BeanUtils; +import cn.iocoder.yudao.module.erp.controller.admin.purchase.vo.supplier.ErpSupplierPageReqVO; +import cn.iocoder.yudao.module.erp.controller.admin.purchase.vo.supplier.ErpSupplierSaveReqVO; +import cn.iocoder.yudao.module.erp.dal.dataobject.supplier.ErpSupplierDO; +import cn.iocoder.yudao.module.erp.dal.mysql.purchase.ErpSupplierMapper; +import jakarta.annotation.Resource; +import org.springframework.stereotype.Service; +import org.springframework.validation.annotation.Validated; + +import java.util.Collection; +import java.util.List; + +import static cn.iocoder.yudao.framework.common.exception.util.ServiceExceptionUtil.exception; +import static cn.iocoder.yudao.module.erp.enums.ErrorCodeConstants.*; + +/** + * ERP 供应商 Service 实现类 + * + * @author 芋道源码 + */ +@Service +@Validated +public class ErpSupplierServiceImpl implements ErpSupplierService { + + @Resource + private ErpSupplierMapper supplierMapper; + + @Override + public Long createSupplier(ErpSupplierSaveReqVO createReqVO) { + ErpSupplierDO supplier = BeanUtils.toBean(createReqVO, ErpSupplierDO.class); + supplierMapper.insert(supplier); + return supplier.getId(); + } + + @Override + public void updateSupplier(ErpSupplierSaveReqVO updateReqVO) { + // 校验存在 + validateSupplierExists(updateReqVO.getId()); + // 更新 + ErpSupplierDO updateObj = BeanUtils.toBean(updateReqVO, ErpSupplierDO.class); + supplierMapper.updateById(updateObj); + } + + @Override + public void deleteSupplier(Long id) { + // 校验存在 + validateSupplierExists(id); + // 删除 + supplierMapper.deleteById(id); + } + + private void validateSupplierExists(Long id) { + if (supplierMapper.selectById(id) == null) { + throw exception(SUPPLIER_NOT_EXISTS); + } + } + + @Override + public ErpSupplierDO getSupplier(Long id) { + return supplierMapper.selectById(id); + } + + @Override + public ErpSupplierDO validateSupplier(Long id) { + ErpSupplierDO supplier = supplierMapper.selectById(id); + if (supplier == null) { + throw exception(WAREHOUSE_NOT_EXISTS); + } + if (CommonStatusEnum.isDisable(supplier.getStatus())) { + throw exception(WAREHOUSE_NOT_ENABLE, supplier.getName()); + } + return supplier; + } + + @Override + public List getSupplierList(Collection ids) { + return supplierMapper.selectBatchIds(ids); + } + + @Override + public PageResult getSupplierPage(ErpSupplierPageReqVO pageReqVO) { + return supplierMapper.selectPage(pageReqVO); + } + + @Override + public List getSupplierListByStatus(Integer status) { + return supplierMapper.selectListByStatus(status); + } + +} \ No newline at end of file diff --git a/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/service/stock/ErpStockInServiceImpl.java b/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/service/stock/ErpStockInServiceImpl.java index 4945d8111..0cf716018 100644 --- a/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/service/stock/ErpStockInServiceImpl.java +++ b/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/service/stock/ErpStockInServiceImpl.java @@ -12,6 +12,7 @@ import cn.iocoder.yudao.module.erp.dal.mysql.stock.ErpStockInItemMapper; import cn.iocoder.yudao.module.erp.dal.mysql.stock.ErpStockInMapper; import cn.iocoder.yudao.module.erp.enums.ErpAuditStatus; import cn.iocoder.yudao.module.erp.service.product.ErpProductService; +import cn.iocoder.yudao.module.erp.service.purchase.ErpSupplierService; import jakarta.annotation.Resource; import org.springframework.stereotype.Service; import org.springframework.transaction.annotation.Transactional; @@ -46,13 +47,16 @@ public class ErpStockInServiceImpl implements ErpStockInService { private ErpProductService productService; @Resource private ErpWarehouseService warehouseService; + @Resource + private ErpSupplierService supplierService; @Override @Transactional(rollbackFor = Exception.class) public Long createStockIn(ErpStockInSaveReqVO createReqVO) { // 1.1 校验入库项的有效性 List stockInItems = validateStockInItems(createReqVO.getItems()); - // 1.2 TODO 芋艿:校验供应商 + // 1.2 校验供应商 + supplierService.validateSupplier(createReqVO.getSupplierId()); // 2.1 插入入库单 ErpStockInDO stockIn = BeanUtils.toBean(createReqVO, ErpStockInDO.class, in -> in @@ -71,7 +75,8 @@ public class ErpStockInServiceImpl implements ErpStockInService { public void updateStockIn(ErpStockInSaveReqVO updateReqVO) { // 1.1 校验存在 validateStockInExists(updateReqVO.getId()); - // 1.2 TODO 芋艿:校验供应商 + // 1.2 校验供应商 + supplierService.validateSupplier(updateReqVO.getSupplierId()); // 1.3 校验入库项的有效性 List stockInItems = validateStockInItems(updateReqVO.getItems()); diff --git a/yudao-module-erp/yudao-module-erp-biz/src/main/resources/mapper/supplier/ErpSupplierMapper.xml b/yudao-module-erp/yudao-module-erp-biz/src/main/resources/mapper/supplier/ErpSupplierMapper.xml new file mode 100644 index 000000000..54849af3f --- /dev/null +++ b/yudao-module-erp/yudao-module-erp-biz/src/main/resources/mapper/supplier/ErpSupplierMapper.xml @@ -0,0 +1,12 @@ + + + + + + + \ No newline at end of file diff --git a/yudao-server/src/main/resources/application-local.yaml b/yudao-server/src/main/resources/application-local.yaml index f5e300c51..cddf42014 100644 --- a/yudao-server/src/main/resources/application-local.yaml +++ b/yudao-server/src/main/resources/application-local.yaml @@ -188,6 +188,7 @@ logging: cn.iocoder.yudao.module.promotion.dal.mysql: debug cn.iocoder.yudao.module.statistics.dal.mysql: debug cn.iocoder.yudao.module.crm.dal.mysql: debug + cn.iocoder.yudao.module.erp.dal.mysql: debug org.springframework.context.support.PostProcessorRegistrationDelegate: ERROR # TODO 芋艿:先禁用,Spring Boot 3.X 存在部分错误的 WARN 提示 debug: false From 6fc8c4809f8ce9800f3206d69c13d90806a381c7 Mon Sep 17 00:00:00 2001 From: dhb52 Date: Tue, 6 Feb 2024 22:58:01 +0800 Subject: [PATCH 079/119] =?UTF-8?q?feat:=20=E5=90=88=E5=90=8C[=E5=AE=A1?= =?UTF-8?q?=E6=89=B9=E7=8A=B6=E6=80=81]=E6=9D=A1=E4=BB=B6=E7=AD=9B?= =?UTF-8?q?=E9=80=89?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../crm/controller/admin/contract/vo/CrmContractPageReqVO.java | 3 +++ .../yudao/module/crm/dal/mysql/contract/CrmContractMapper.java | 1 + 2 files changed, 4 insertions(+) diff --git a/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/controller/admin/contract/vo/CrmContractPageReqVO.java b/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/controller/admin/contract/vo/CrmContractPageReqVO.java index 94199ada6..2e14f1566 100644 --- a/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/controller/admin/contract/vo/CrmContractPageReqVO.java +++ b/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/controller/admin/contract/vo/CrmContractPageReqVO.java @@ -30,4 +30,7 @@ public class CrmContractPageReqVO extends PageParam { @InEnum(CrmSceneTypeEnum.class) private Integer sceneType; // 场景类型,为 null 时则表示全部 + @Schema(description = "审批状态", example = "20") + private Integer auditStatus; + } diff --git a/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/dal/mysql/contract/CrmContractMapper.java b/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/dal/mysql/contract/CrmContractMapper.java index a3e631201..e7c56a622 100644 --- a/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/dal/mysql/contract/CrmContractMapper.java +++ b/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/dal/mysql/contract/CrmContractMapper.java @@ -49,6 +49,7 @@ public interface CrmContractMapper extends BaseMapperX { .likeIfPresent(CrmContractDO::getName, pageReqVO.getName()) .eqIfPresent(CrmContractDO::getCustomerId, pageReqVO.getCustomerId()) .eqIfPresent(CrmContractDO::getBusinessId, pageReqVO.getBusinessId()) + .eqIfPresent(CrmContractDO::getAuditStatus, pageReqVO.getAuditStatus()) .orderByDesc(CrmContractDO::getId); return selectJoinPage(pageReqVO, CrmContractDO.class, mpjLambdaWrapperX); } From 593e1fd59c68422b582c21a27ab8b9e43fcb2bc6 Mon Sep 17 00:00:00 2001 From: YunaiV Date: Tue, 6 Feb 2024 23:28:57 +0800 Subject: [PATCH 080/119] =?UTF-8?q?=E2=9C=A8=20ERP=EF=BC=9A=E5=A2=9E?= =?UTF-8?q?=E5=8A=A0=E5=85=A5=E5=BA=93=E5=8D=95=E7=9A=84=E5=AE=A1=E6=89=B9?= =?UTF-8?q?=E5=8A=9F=E8=83=BD?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../util/collection/CollectionUtils.java | 15 +++-- .../common/util/number/NumberUtils.java | 20 ++++++ .../module/erp/enums/ErrorCodeConstants.java | 6 +- .../admin/stock/ErpStockInController.java | 28 +++++--- .../admin/stock/vo/in/ErpStockInRespVO.java | 2 + .../stock/vo/in/ErpStockInSaveReqVO.java | 3 +- .../erp/dal/mysql/stock/ErpStockInMapper.java | 6 ++ .../erp/service/stock/ErpStockInService.java | 12 +++- .../service/stock/ErpStockInServiceImpl.java | 67 ++++++++++++++----- 9 files changed, 125 insertions(+), 34 deletions(-) diff --git a/yudao-framework/yudao-common/src/main/java/cn/iocoder/yudao/framework/common/util/collection/CollectionUtils.java b/yudao-framework/yudao-common/src/main/java/cn/iocoder/yudao/framework/common/util/collection/CollectionUtils.java index 35ebc8ff3..2d9e4dd63 100644 --- a/yudao-framework/yudao-common/src/main/java/cn/iocoder/yudao/framework/common/util/collection/CollectionUtils.java +++ b/yudao-framework/yudao-common/src/main/java/cn/iocoder/yudao/framework/common/util/collection/CollectionUtils.java @@ -288,11 +288,16 @@ public class CollectionUtils { public static > V getSumValue(List from, Function valueFunc, BinaryOperator accumulator) { + return getSumValue(from, valueFunc, accumulator, null); + } + + public static > V getSumValue(List from, Function valueFunc, + BinaryOperator accumulator, V defaultValue) { if (CollUtil.isEmpty(from)) { - return null; + return defaultValue; } - assert from.size() > 0; // 断言,避免告警 - return from.stream().map(valueFunc).reduce(accumulator).get(); + assert !from.isEmpty(); // 断言,避免告警 + return from.stream().map(valueFunc).filter(Objects::nonNull).reduce(accumulator).orElse(defaultValue); } public static void addIfNotNull(Collection coll, T item) { @@ -302,8 +307,8 @@ public class CollectionUtils { coll.add(item); } - public static Collection singleton(T deptId) { - return deptId == null ? Collections.emptyList() : Collections.singleton(deptId); + public static Collection singleton(T obj) { + return obj == null ? Collections.emptyList() : Collections.singleton(obj); } } diff --git a/yudao-framework/yudao-common/src/main/java/cn/iocoder/yudao/framework/common/util/number/NumberUtils.java b/yudao-framework/yudao-common/src/main/java/cn/iocoder/yudao/framework/common/util/number/NumberUtils.java index 55ab367a3..ea131e86e 100644 --- a/yudao-framework/yudao-common/src/main/java/cn/iocoder/yudao/framework/common/util/number/NumberUtils.java +++ b/yudao-framework/yudao-common/src/main/java/cn/iocoder/yudao/framework/common/util/number/NumberUtils.java @@ -1,7 +1,10 @@ package cn.iocoder.yudao.framework.common.util.number; +import cn.hutool.core.util.NumberUtil; import cn.hutool.core.util.StrUtil; +import java.math.BigDecimal; + /** * 数字的工具类,补全 {@link cn.hutool.core.util.NumberUtil} 的功能 * @@ -37,4 +40,21 @@ public class NumberUtils { return distance; } + /** + * 提供精确的乘法运算 + * + * 和 hutool {@link NumberUtil#mul(BigDecimal...)} 的差别是,如果存在 null,则返回 null + * + * @param values 多个被乘值 + * @return 积 + */ + public static BigDecimal mul(BigDecimal... values) { + for (BigDecimal value : values) { + if (value == null) { + return null; + } + } + return NumberUtil.mul(values); + } + } diff --git a/yudao-module-erp/yudao-module-erp-api/src/main/java/cn/iocoder/yudao/module/erp/enums/ErrorCodeConstants.java b/yudao-module-erp/yudao-module-erp-api/src/main/java/cn/iocoder/yudao/module/erp/enums/ErrorCodeConstants.java index 1cc2807ad..5cfec682c 100644 --- a/yudao-module-erp/yudao-module-erp-api/src/main/java/cn/iocoder/yudao/module/erp/enums/ErrorCodeConstants.java +++ b/yudao-module-erp/yudao-module-erp-api/src/main/java/cn/iocoder/yudao/module/erp/enums/ErrorCodeConstants.java @@ -13,7 +13,7 @@ public interface ErrorCodeConstants { ErrorCode SUPPLIER_NOT_EXISTS = new ErrorCode(1_030_100_000, "供应商不存在"); ErrorCode SUPPLIER_NOT_ENABLE = new ErrorCode(1_030_100_000, "供应商({})未启用"); - // ========== 销售订单(1-030-200-000) ========== + // ========== ERP 销售订单(1-030-200-000) ========== ErrorCode SALE_ORDER_NOT_EXISTS = new ErrorCode(1_020_200_000, "销售订单不存在"); // ========== ERP 仓库 1-030-400-000 ========== @@ -22,6 +22,10 @@ public interface ErrorCodeConstants { // ========== ERP 其它入库单 1-030-401-000 ========== ErrorCode STOCK_IN_NOT_EXISTS = new ErrorCode(1_030_401_000, "其它入库单不存在"); + ErrorCode STOCK_IN_DELETE_FAIL_APPROVE = new ErrorCode(1_030_401_001, "其它入库单({})已审核,无法删除"); + ErrorCode STOCK_IN_PROCESS_FAIL = new ErrorCode(1_030_401_002, "反审核失败,只有已审核的入库单才能反审核"); + ErrorCode STOCK_IN_APPROVE_FAIL = new ErrorCode(1_030_401_003, "审核失败,只有未审核的入库单才能审核"); + // ========== ERP 产品 1-030-500-000 ========== ErrorCode PRODUCT_NOT_EXISTS = new ErrorCode(1_030_500_000, "产品不存在"); diff --git a/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/controller/admin/stock/ErpStockInController.java b/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/controller/admin/stock/ErpStockInController.java index 1351516ed..530d04350 100644 --- a/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/controller/admin/stock/ErpStockInController.java +++ b/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/controller/admin/stock/ErpStockInController.java @@ -75,12 +75,21 @@ public class ErpStockInController { return success(true); } + @PutMapping("/update-status") + @Operation(summary = "更新其它入库单的状态") + @PreAuthorize("@ss.hasPermission('erp:stock-in:update')") + public CommonResult updateStockInStatus(@RequestParam("id") Long id, + @RequestParam("status") Integer status) { + stockInService.updateStockInStatus(id, status); + return success(true); + } + @DeleteMapping("/delete") @Operation(summary = "删除其它入库单") - @Parameter(name = "id", description = "编号", required = true) + @Parameter(name = "ids", description = "编号数组", required = true) @PreAuthorize("@ss.hasPermission('erp:stock-in:delete')") - public CommonResult deleteStockIn(@RequestParam("id") Long id) { - stockInService.deleteStockIn(id); + public CommonResult deleteStockIn(@RequestParam("ids") List ids) { + stockInService.deleteStockIn(ids); return success(true); } @@ -93,12 +102,15 @@ public class ErpStockInController { if (stockIn == null) { return success(null); } - List stockInItems = stockInService.getStockInItemListByInId(id); - // TODO 芋艿:有个锤子; + List stockInItemList = stockInService.getStockInItemListByInId(id); + Map productMap = productService.getProductVOMap( + convertSet(stockInItemList, ErpStockInItemDO::getProductId)); return success(BeanUtils.toBean(stockIn, ErpStockInRespVO.class, stockInVO -> - stockInVO.setItems(BeanUtils.toBean(stockInItems, ErpStockInRespVO.Item.class, item -> { + stockInVO.setItems(BeanUtils.toBean(stockInItemList, ErpStockInRespVO.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())); })))); } @@ -142,8 +154,8 @@ public class ErpStockInController { // 2. 开始拼接 return BeanUtils.toBean(pageResult, ErpStockInRespVO.class, stockIn -> { stockIn.setItems(BeanUtils.toBean(stockInItemMap.get(stockIn.getId()), ErpStockInRespVO.Item.class, - item -> MapUtils.findAndThen(productMap, item.getProductId(), - product -> item.setProductName(product.getName()).setProductUnitName(product.getUnitName())))); + item -> MapUtils.findAndThen(productMap, item.getProductId(), product -> item.setProductName(product.getName()) + .setProductBarCode(product.getBarCode()).setProductUnitName(product.getUnitName())))); stockIn.setProductNames(CollUtil.join(stockIn.getItems(), ",", ErpStockInRespVO.Item::getProductName)); MapUtils.findAndThen(supplierMap, stockIn.getSupplierId(), supplier -> stockIn.setSupplierName(supplier.getName())); MapUtils.findAndThen(userMap, Long.parseLong(stockIn.getCreator()), user -> stockIn.setCreatorName(user.getNickname())); diff --git a/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/controller/admin/stock/vo/in/ErpStockInRespVO.java b/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/controller/admin/stock/vo/in/ErpStockInRespVO.java index 07897ad30..e6263db61 100644 --- a/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/controller/admin/stock/vo/in/ErpStockInRespVO.java +++ b/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/controller/admin/stock/vo/in/ErpStockInRespVO.java @@ -97,6 +97,8 @@ public class ErpStockInRespVO { @Schema(description = "产品名称", requiredMode = Schema.RequiredMode.REQUIRED, example = "巧克力") private String productName; + @Schema(description = "产品条码", requiredMode = Schema.RequiredMode.REQUIRED, example = "A9985") + private String productBarCode; @Schema(description = "产品单位名称", requiredMode = Schema.RequiredMode.REQUIRED, example = "盒") private String productUnitName; diff --git a/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/controller/admin/stock/vo/in/ErpStockInSaveReqVO.java b/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/controller/admin/stock/vo/in/ErpStockInSaveReqVO.java index c3cc6be95..e3a87da8a 100644 --- a/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/controller/admin/stock/vo/in/ErpStockInSaveReqVO.java +++ b/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/controller/admin/stock/vo/in/ErpStockInSaveReqVO.java @@ -53,8 +53,7 @@ public class ErpStockInSaveReqVO { @NotNull(message = "产品编号不能为空") private Long productId; - @Schema(description = "产品单价", requiredMode = Schema.RequiredMode.REQUIRED, example = "100.00") - @NotNull(message = "产品单价不能为空") + @Schema(description = "产品单价", example = "100.00") private BigDecimal productPrice; @Schema(description = "产品数量", requiredMode = Schema.RequiredMode.REQUIRED, example = "100.00") diff --git a/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/dal/mysql/stock/ErpStockInMapper.java b/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/dal/mysql/stock/ErpStockInMapper.java index 0b3e71a5f..eadf02c75 100644 --- a/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/dal/mysql/stock/ErpStockInMapper.java +++ b/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/dal/mysql/stock/ErpStockInMapper.java @@ -6,6 +6,7 @@ import cn.iocoder.yudao.framework.mybatis.core.query.MPJLambdaWrapperX; import cn.iocoder.yudao.module.erp.controller.admin.stock.vo.in.ErpStockInPageReqVO; import cn.iocoder.yudao.module.erp.dal.dataobject.stock.ErpStockInDO; import cn.iocoder.yudao.module.erp.dal.dataobject.stock.ErpStockInItemDO; +import com.baomidou.mybatisplus.core.conditions.update.LambdaUpdateWrapper; import org.apache.ibatis.annotations.Mapper; /** @@ -34,4 +35,9 @@ public interface ErpStockInMapper extends BaseMapperX { return selectJoinPage(reqVO, ErpStockInDO.class, query); } + default int updateByIdAndStatus(Long id, Integer status, ErpStockInDO updateObj) { + return update(updateObj, new LambdaUpdateWrapper() + .eq(ErpStockInDO::getId, id).eq(ErpStockInDO::getStatus, status)); + } + } \ No newline at end of file diff --git a/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/service/stock/ErpStockInService.java b/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/service/stock/ErpStockInService.java index 92555135f..4e51545e4 100644 --- a/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/service/stock/ErpStockInService.java +++ b/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/service/stock/ErpStockInService.java @@ -33,11 +33,19 @@ public interface ErpStockInService { void updateStockIn(@Valid ErpStockInSaveReqVO updateReqVO); /** - * 删除其它入库单 + * 更新其它入库单的状态 * * @param id 编号 + * @param status 状态 */ - void deleteStockIn(Long id); + void updateStockInStatus(Long id, Integer status); + + /** + * 删除其它入库单 + * + * @param ids 编号数组 + */ + void deleteStockIn(List ids); /** * 获得其它入库单 diff --git a/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/service/stock/ErpStockInServiceImpl.java b/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/service/stock/ErpStockInServiceImpl.java index 0cf716018..305676445 100644 --- a/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/service/stock/ErpStockInServiceImpl.java +++ b/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/service/stock/ErpStockInServiceImpl.java @@ -2,6 +2,7 @@ package cn.iocoder.yudao.module.erp.service.stock; import cn.hutool.core.collection.CollUtil; import cn.iocoder.yudao.framework.common.pojo.PageResult; +import cn.iocoder.yudao.framework.common.util.number.NumberUtils; import cn.iocoder.yudao.framework.common.util.object.BeanUtils; import cn.iocoder.yudao.module.erp.controller.admin.stock.vo.in.ErpStockInPageReqVO; import cn.iocoder.yudao.module.erp.controller.admin.stock.vo.in.ErpStockInSaveReqVO; @@ -26,9 +27,9 @@ import java.util.Map; 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.module.erp.enums.ErrorCodeConstants.STOCK_IN_NOT_EXISTS; - +import static cn.iocoder.yudao.module.erp.enums.ErrorCodeConstants.*; +// TODO 芋艿:记录操作日志 /** * ERP 其它入库单 Service 实现类 * @@ -62,9 +63,9 @@ public class ErpStockInServiceImpl implements ErpStockInService { ErpStockInDO stockIn = BeanUtils.toBean(createReqVO, ErpStockInDO.class, in -> in .setStatus(ErpAuditStatus.PROCESS.getStatus()) .setTotalCount(getSumValue(stockInItems, ErpStockInItemDO::getCount, BigDecimal::add)) - .setTotalPrice(getSumValue(stockInItems, ErpStockInItemDO::getTotalPrice, BigDecimal::add))); + .setTotalPrice(getSumValue(stockInItems, ErpStockInItemDO::getTotalPrice, BigDecimal::add, BigDecimal.ZERO))); stockInMapper.insert(stockIn); - // 2. 插入子表 + // 2.2 插入入库单项 stockInItems.forEach(o -> o.setInId(stockIn.getId())); stockInItemMapper.insertBatch(stockInItems); return stockIn.getId(); @@ -89,6 +90,28 @@ public class ErpStockInServiceImpl implements ErpStockInService { updateStockInItemList(updateReqVO.getId(), stockInItems); } + @Override + @Transactional(rollbackFor = Exception.class) + public void updateStockInStatus(Long id, Integer status) { + // 1.1 校验存在 + ErpStockInDO stockIn = validateStockInExists(id); + // 1.2 校验状态 + if (stockIn.getStatus().equals(status)) { + throw exception(ErpAuditStatus.PROCESS.getStatus().equals(status) ? + STOCK_IN_PROCESS_FAIL : STOCK_IN_APPROVE_FAIL); + } + + // 2. 更新状态 + int updateCount = stockInMapper.updateByIdAndStatus(id, stockIn.getStatus(), + new ErpStockInDO().setStatus(status)); + if (updateCount == 0) { + throw exception(ErpAuditStatus.PROCESS.getStatus().equals(status) ? + STOCK_IN_PROCESS_FAIL : STOCK_IN_APPROVE_FAIL); + } + + // 3. TODO 芋艿:调整库存记录 + } + private List validateStockInItems(List list) { // 1.1 校验产品存在 List productList = productService.validProductList(convertSet(list, ErpStockInSaveReqVO.Item::getProductId)); @@ -98,7 +121,7 @@ public class ErpStockInServiceImpl implements ErpStockInService { // 2. 转化为 ErpStockInItemDO 列表 return convertList(list, o -> BeanUtils.toBean(o, ErpStockInItemDO.class, item -> item .setProductUnitId(productMap.get(item.getProductId()).getUnitId()) - .setTotalPrice(item.getProductPrice().multiply(item.getCount())))); + .setTotalPrice(NumberUtils.mul(item.getProductPrice(), item.getCount())))); } private void updateStockInItemList(Long id, List newList) { @@ -122,21 +145,33 @@ public class ErpStockInServiceImpl implements ErpStockInService { @Override @Transactional(rollbackFor = Exception.class) - public void deleteStockIn(Long id) { - // 1. 校验存在 - validateStockInExists(id); - // TODO 芋艿:校验一下; + public void deleteStockIn(List ids) { + // 1. 校验不处于已审批 + List stockIns = stockInMapper.selectBatchIds(ids); + if (CollUtil.isEmpty(stockIns)) { + return; + } + stockIns.forEach(stockIn -> { + if (ErpAuditStatus.APPROVE.getStatus().equals(stockIn.getStatus())) { + throw exception(STOCK_IN_DELETE_FAIL_APPROVE, stockIn.getNo()); + } + }); - // 2.1 删除 - stockInMapper.deleteById(id); - // 2.2 删除子表 - stockInItemMapper.deleteByInId(id); + // 2. 遍历删除,并记录操作日志 + stockIns.forEach(stockIn -> { + // 2.1 删除入库单 + stockInMapper.deleteById(stockIn.getId()); + // 2.2 删除入库单项 + stockInItemMapper.deleteByInId(stockIn.getId()); + }); } - private void validateStockInExists(Long id) { - if (stockInMapper.selectById(id) == null) { + private ErpStockInDO validateStockInExists(Long id) { + ErpStockInDO stockIn = stockInMapper.selectById(id); + if (stockIn == null) { throw exception(STOCK_IN_NOT_EXISTS); } + return stockIn; } @Override @@ -149,7 +184,7 @@ public class ErpStockInServiceImpl implements ErpStockInService { return stockInMapper.selectPage(pageReqVO); } - // ==================== 子表(ERP 其它入库单项) ==================== + // ==================== 入库项 ==================== @Override public List getStockInItemListByInId(Long inId) { From f6d3290426fce784dded91579775a5af244208e0 Mon Sep 17 00:00:00 2001 From: YunaiV Date: Wed, 7 Feb 2024 00:37:42 +0800 Subject: [PATCH 081/119] =?UTF-8?q?=E2=9C=A8=20ERP=EF=BC=9A=E5=A2=9E?= =?UTF-8?q?=E5=8A=A0=E5=85=A5=E5=BA=93=E5=8D=95=E5=8F=B7=E7=9A=84=E8=87=AA?= =?UTF-8?q?=E5=8A=A8=E7=94=9F=E6=88=90?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../module/erp/enums/ErrorCodeConstants.java | 2 +- yudao-module-erp/yudao-module-erp-biz/pom.xml | 5 ++ .../stock/vo/in/ErpStockInSaveReqVO.java | 4 -- .../erp/dal/mysql/stock/ErpStockInMapper.java | 4 ++ .../erp/dal/redis/RedisKeyConstants.java | 18 +++++++ .../erp/dal/redis/no/ErpNoRedisDAO.java | 47 +++++++++++++++++++ .../service/stock/ErpStockInServiceImpl.java | 11 ++++- 7 files changed, 85 insertions(+), 6 deletions(-) create mode 100644 yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/dal/redis/RedisKeyConstants.java create mode 100644 yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/dal/redis/no/ErpNoRedisDAO.java diff --git a/yudao-module-erp/yudao-module-erp-api/src/main/java/cn/iocoder/yudao/module/erp/enums/ErrorCodeConstants.java b/yudao-module-erp/yudao-module-erp-api/src/main/java/cn/iocoder/yudao/module/erp/enums/ErrorCodeConstants.java index 5cfec682c..3f98d4314 100644 --- a/yudao-module-erp/yudao-module-erp-api/src/main/java/cn/iocoder/yudao/module/erp/enums/ErrorCodeConstants.java +++ b/yudao-module-erp/yudao-module-erp-api/src/main/java/cn/iocoder/yudao/module/erp/enums/ErrorCodeConstants.java @@ -25,7 +25,7 @@ public interface ErrorCodeConstants { ErrorCode STOCK_IN_DELETE_FAIL_APPROVE = new ErrorCode(1_030_401_001, "其它入库单({})已审核,无法删除"); ErrorCode STOCK_IN_PROCESS_FAIL = new ErrorCode(1_030_401_002, "反审核失败,只有已审核的入库单才能反审核"); ErrorCode STOCK_IN_APPROVE_FAIL = new ErrorCode(1_030_401_003, "审核失败,只有未审核的入库单才能审核"); - + ErrorCode STOCK_IN_NO_EXISTS = new ErrorCode(1_030_401_004, "生成入库单失败,请重新提交"); // ========== ERP 产品 1-030-500-000 ========== ErrorCode PRODUCT_NOT_EXISTS = new ErrorCode(1_030_500_000, "产品不存在"); diff --git a/yudao-module-erp/yudao-module-erp-biz/pom.xml b/yudao-module-erp/yudao-module-erp-biz/pom.xml index 83b3900cf..1d0b44162 100644 --- a/yudao-module-erp/yudao-module-erp-biz/pom.xml +++ b/yudao-module-erp/yudao-module-erp-biz/pom.xml @@ -51,6 +51,11 @@ yudao-spring-boot-starter-mybatis + + cn.iocoder.boot + yudao-spring-boot-starter-redis + + cn.iocoder.boot diff --git a/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/controller/admin/stock/vo/in/ErpStockInSaveReqVO.java b/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/controller/admin/stock/vo/in/ErpStockInSaveReqVO.java index e3a87da8a..0187872c8 100644 --- a/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/controller/admin/stock/vo/in/ErpStockInSaveReqVO.java +++ b/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/controller/admin/stock/vo/in/ErpStockInSaveReqVO.java @@ -17,10 +17,6 @@ public class ErpStockInSaveReqVO { @Schema(description = "入库编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "11756") private Long id; - @Schema(description = "入库单号", requiredMode = Schema.RequiredMode.REQUIRED, example = "S123") - @NotEmpty(message = "入库单号不能为空") - private String no; - @Schema(description = "供应商编号", example = "3113") private Long supplierId; diff --git a/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/dal/mysql/stock/ErpStockInMapper.java b/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/dal/mysql/stock/ErpStockInMapper.java index eadf02c75..9e7ea9bca 100644 --- a/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/dal/mysql/stock/ErpStockInMapper.java +++ b/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/dal/mysql/stock/ErpStockInMapper.java @@ -40,4 +40,8 @@ public interface ErpStockInMapper extends BaseMapperX { .eq(ErpStockInDO::getId, id).eq(ErpStockInDO::getStatus, status)); } + default ErpStockInDO selectByNo(String no) { + return selectOne(ErpStockInDO::getNo, no); + } + } \ No newline at end of file diff --git a/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/dal/redis/RedisKeyConstants.java b/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/dal/redis/RedisKeyConstants.java new file mode 100644 index 000000000..f0ba46807 --- /dev/null +++ b/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/dal/redis/RedisKeyConstants.java @@ -0,0 +1,18 @@ +package cn.iocoder.yudao.module.erp.dal.redis; + +/** + * ERP Redis Key 枚举类 + * + * @author 芋道源码 + */ +public interface RedisKeyConstants { + + /** + * 序号的缓存 + * + * KEY 格式:trade_no:{prefix} + * VALUE 数据格式:编号自增 + */ + String NO = "seq_no:"; + +} diff --git a/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/dal/redis/no/ErpNoRedisDAO.java b/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/dal/redis/no/ErpNoRedisDAO.java new file mode 100644 index 000000000..e211864cc --- /dev/null +++ b/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/dal/redis/no/ErpNoRedisDAO.java @@ -0,0 +1,47 @@ +package cn.iocoder.yudao.module.erp.dal.redis.no; + +import cn.hutool.core.date.DatePattern; +import cn.hutool.core.date.DateUtil; +import cn.iocoder.yudao.module.erp.dal.redis.RedisKeyConstants; +import jakarta.annotation.Resource; +import org.springframework.data.redis.core.StringRedisTemplate; +import org.springframework.stereotype.Repository; + +import java.time.Duration; +import java.time.LocalDateTime; + + +/** + * 订单序号的 Redis DAO + * + * @author HUIHUI + */ +@Repository +public class ErpNoRedisDAO { + + /** + * 其它入库 STOCK_IN + */ + public static final String STOCK_IN_NO_PREFIX = "QTRK"; + + @Resource + private StringRedisTemplate stringRedisTemplate; + + /** + * 生成序号,使用当前日期,格式为 {PREFIX} + yyyyMMdd + 6 位自增 + * 例如说:QTRK 202109 000001 (没有中间空格) + * + * @param prefix 前缀 + * @return 序号 + */ + public String generate(String prefix) { + // 递增序号 + String noPrefix = prefix + DateUtil.format(LocalDateTime.now(), DatePattern.PURE_DATE_PATTERN); + String key = RedisKeyConstants.NO + noPrefix; + Long no = stringRedisTemplate.opsForValue().increment(key); + // 设置过期时间 + stringRedisTemplate.expire(key, Duration.ofMinutes(1L)); + return noPrefix + String.format("%06d", no); + } + +} diff --git a/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/service/stock/ErpStockInServiceImpl.java b/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/service/stock/ErpStockInServiceImpl.java index 305676445..8f4835013 100644 --- a/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/service/stock/ErpStockInServiceImpl.java +++ b/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/service/stock/ErpStockInServiceImpl.java @@ -11,6 +11,7 @@ import cn.iocoder.yudao.module.erp.dal.dataobject.stock.ErpStockInDO; import cn.iocoder.yudao.module.erp.dal.dataobject.stock.ErpStockInItemDO; import cn.iocoder.yudao.module.erp.dal.mysql.stock.ErpStockInItemMapper; import cn.iocoder.yudao.module.erp.dal.mysql.stock.ErpStockInMapper; +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.product.ErpProductService; import cn.iocoder.yudao.module.erp.service.purchase.ErpSupplierService; @@ -44,6 +45,9 @@ public class ErpStockInServiceImpl implements ErpStockInService { @Resource private ErpStockInItemMapper stockInItemMapper; + @Resource + private ErpNoRedisDAO noRedisDAO; + @Resource private ErpProductService productService; @Resource @@ -58,10 +62,15 @@ public class ErpStockInServiceImpl implements ErpStockInService { List stockInItems = validateStockInItems(createReqVO.getItems()); // 1.2 校验供应商 supplierService.validateSupplier(createReqVO.getSupplierId()); + // 1.3 + String no = noRedisDAO.generate(ErpNoRedisDAO.STOCK_IN_NO_PREFIX); + if (stockInMapper.selectByNo(no) != null) { + throw exception(STOCK_IN_NO_EXISTS); + } // 2.1 插入入库单 ErpStockInDO stockIn = BeanUtils.toBean(createReqVO, ErpStockInDO.class, in -> in - .setStatus(ErpAuditStatus.PROCESS.getStatus()) + .setNo(no).setStatus(ErpAuditStatus.PROCESS.getStatus()) .setTotalCount(getSumValue(stockInItems, ErpStockInItemDO::getCount, BigDecimal::add)) .setTotalPrice(getSumValue(stockInItems, ErpStockInItemDO::getTotalPrice, BigDecimal::add, BigDecimal.ZERO))); stockInMapper.insert(stockIn); From 3479ef81234da086d606989ddcdec1e796a65ca2 Mon Sep 17 00:00:00 2001 From: YunaiV Date: Wed, 7 Feb 2024 10:34:23 +0800 Subject: [PATCH 082/119] =?UTF-8?q?=E2=9C=A8=20ERP=EF=BC=9A=E5=A2=9E?= =?UTF-8?q?=E5=8A=A0=E9=87=91=E9=A2=9D=E8=AE=A1=E7=AE=97=E7=9A=84=E5=9B=9B?= =?UTF-8?q?=E8=88=8D=E4=BA=94=E5=85=A5?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../common/util/number/MoneyUtils.java | 21 +++++++++++++++++++ .../service/stock/ErpStockInServiceImpl.java | 4 ++-- 2 files changed, 23 insertions(+), 2 deletions(-) diff --git a/yudao-framework/yudao-common/src/main/java/cn/iocoder/yudao/framework/common/util/number/MoneyUtils.java b/yudao-framework/yudao-common/src/main/java/cn/iocoder/yudao/framework/common/util/number/MoneyUtils.java index ccfeb3917..dbc16dc86 100644 --- a/yudao-framework/yudao-common/src/main/java/cn/iocoder/yudao/framework/common/util/number/MoneyUtils.java +++ b/yudao-framework/yudao-common/src/main/java/cn/iocoder/yudao/framework/common/util/number/MoneyUtils.java @@ -13,6 +13,11 @@ import java.math.RoundingMode; */ public class MoneyUtils { + /** + * 金额的小数位数 + */ + private static final int PRICE_SCALE = 2; + /** * 计算百分比金额,四舍五入 * @@ -86,4 +91,20 @@ public class MoneyUtils { return new Money(0, fen).toString(); } + /** + * 金额相乘,默认进行四舍五入 + * + * 位数:{@link #PRICE_SCALE} + * + * @param price 金额 + * @param count 数量 + * @return 金额相乘结果 + */ + public static BigDecimal priceMultiply(BigDecimal price, BigDecimal count) { + if (price == null || count == null) { + return null; + } + return price.multiply(count).setScale(PRICE_SCALE, RoundingMode.HALF_UP); + } + } diff --git a/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/service/stock/ErpStockInServiceImpl.java b/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/service/stock/ErpStockInServiceImpl.java index 8f4835013..55dbf8def 100644 --- a/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/service/stock/ErpStockInServiceImpl.java +++ b/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/service/stock/ErpStockInServiceImpl.java @@ -2,7 +2,7 @@ package cn.iocoder.yudao.module.erp.service.stock; import cn.hutool.core.collection.CollUtil; import cn.iocoder.yudao.framework.common.pojo.PageResult; -import cn.iocoder.yudao.framework.common.util.number.NumberUtils; +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.stock.vo.in.ErpStockInPageReqVO; import cn.iocoder.yudao.module.erp.controller.admin.stock.vo.in.ErpStockInSaveReqVO; @@ -130,7 +130,7 @@ public class ErpStockInServiceImpl implements ErpStockInService { // 2. 转化为 ErpStockInItemDO 列表 return convertList(list, o -> BeanUtils.toBean(o, ErpStockInItemDO.class, item -> item .setProductUnitId(productMap.get(item.getProductId()).getUnitId()) - .setTotalPrice(NumberUtils.mul(item.getProductPrice(), item.getCount())))); + .setTotalPrice(MoneyUtils.priceMultiply(item.getProductPrice(), item.getCount())))); } private void updateStockInItemList(Long id, List newList) { From dbc6134f805d82d4a3d6d214d71e8eda4064df7f Mon Sep 17 00:00:00 2001 From: YunaiV Date: Wed, 7 Feb 2024 12:24:56 +0800 Subject: [PATCH 083/119] =?UTF-8?q?=E2=9C=A8=20ERP=EF=BC=9A=E5=A2=9E?= =?UTF-8?q?=E5=8A=A0=E5=BA=93=E5=AD=98=E5=8F=98=E6=9B=B4=E8=AE=B0=E5=BD=95?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../module/erp/enums/ErrorCodeConstants.java | 6 ++ .../dataobject/stock/ErpStockRecordDO.java | 9 +-- .../erp/dal/mysql/stock/ErpStockMapper.java | 17 ++++++ .../service/stock/ErpStockInServiceImpl.java | 22 +++++-- .../service/stock/ErpStockRecordService.java | 9 +++ .../stock/ErpStockRecordServiceImpl.java | 20 +++++++ .../erp/service/stock/ErpStockService.java | 12 ++++ .../service/stock/ErpStockServiceImpl.java | 36 +++++++++++ .../stock/bo/ErpStockInCreateReqBO.java | 59 +++++++++++++++++++ 9 files changed, 181 insertions(+), 9 deletions(-) create mode 100644 yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/service/stock/bo/ErpStockInCreateReqBO.java diff --git a/yudao-module-erp/yudao-module-erp-api/src/main/java/cn/iocoder/yudao/module/erp/enums/ErrorCodeConstants.java b/yudao-module-erp/yudao-module-erp-api/src/main/java/cn/iocoder/yudao/module/erp/enums/ErrorCodeConstants.java index 3f98d4314..ba7d7685c 100644 --- a/yudao-module-erp/yudao-module-erp-api/src/main/java/cn/iocoder/yudao/module/erp/enums/ErrorCodeConstants.java +++ b/yudao-module-erp/yudao-module-erp-api/src/main/java/cn/iocoder/yudao/module/erp/enums/ErrorCodeConstants.java @@ -27,6 +27,12 @@ public interface ErrorCodeConstants { ErrorCode STOCK_IN_APPROVE_FAIL = new ErrorCode(1_030_401_003, "审核失败,只有未审核的入库单才能审核"); ErrorCode STOCK_IN_NO_EXISTS = new ErrorCode(1_030_401_004, "生成入库单失败,请重新提交"); + // ========== ERP 其它出库单 1-030-402-000 ========== + + // ========== ERP 产品库存 1-030-403-000 ========== + ErrorCode STOCK_COUNT_NEGATIVE = new ErrorCode(1_030_403_000, "操作失败,产品当前库存:{},小于变更数量:{}"); + ErrorCode STOCK_COUNT_NEGATIVE2 = new ErrorCode(1_030_403_000, "操作失败,库存不足"); + // ========== ERP 产品 1-030-500-000 ========== ErrorCode PRODUCT_NOT_EXISTS = new ErrorCode(1_030_500_000, "产品不存在"); ErrorCode PRODUCT_NOT_ENABLE = new ErrorCode(1_030_500_001, "产品({})未启用"); diff --git a/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/dal/dataobject/stock/ErpStockRecordDO.java b/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/dal/dataobject/stock/ErpStockRecordDO.java index be010eb04..7bc5e5a01 100644 --- a/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/dal/dataobject/stock/ErpStockRecordDO.java +++ b/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/dal/dataobject/stock/ErpStockRecordDO.java @@ -2,6 +2,7 @@ package cn.iocoder.yudao.module.erp.dal.dataobject.stock; import cn.iocoder.yudao.framework.mybatis.core.dataobject.BaseDO; import cn.iocoder.yudao.module.erp.dal.dataobject.product.ErpProductDO; +import cn.iocoder.yudao.module.erp.enums.stock.ErpStockRecordBizTypeEnum; import com.baomidou.mybatisplus.annotation.KeySequence; import com.baomidou.mybatisplus.annotation.TableId; import com.baomidou.mybatisplus.annotation.TableName; @@ -56,25 +57,25 @@ public class ErpStockRecordDO extends BaseDO { /** * 业务类型 * - * 枚举 {@link cn.iocoder.yudao.module.erp.enums.stock.ErpStockRecordBizTypeEnum} + * 枚举 {@link ErpStockRecordBizTypeEnum} */ private Integer bizType; /** * 业务编号 * - * 例如说:TODO + * 例如说:{@link ErpStockInDO#getId()} */ private Long bizId; /** * 业务项编号 * - * 例如说:TODO + * 例如说:{@link ErpStockInItemDO#getId()} */ private Long bizItemId; /** * 业务单号 * - * 例如说:TODO + * 例如说:{@link ErpStockInDO#getNo()} */ private String bizNo; diff --git a/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/dal/mysql/stock/ErpStockMapper.java b/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/dal/mysql/stock/ErpStockMapper.java index 5afe42da0..35fd85248 100644 --- a/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/dal/mysql/stock/ErpStockMapper.java +++ b/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/dal/mysql/stock/ErpStockMapper.java @@ -5,8 +5,11 @@ import cn.iocoder.yudao.framework.mybatis.core.mapper.BaseMapperX; import cn.iocoder.yudao.framework.mybatis.core.query.LambdaQueryWrapperX; import cn.iocoder.yudao.module.erp.controller.admin.stock.vo.stock.ErpStockPageReqVO; import cn.iocoder.yudao.module.erp.dal.dataobject.stock.ErpStockDO; +import com.baomidou.mybatisplus.core.conditions.update.LambdaUpdateWrapper; import org.apache.ibatis.annotations.Mapper; +import java.math.BigDecimal; + /** * ERP 产品库存 Mapper * @@ -27,4 +30,18 @@ public interface ErpStockMapper extends BaseMapperX { ErpStockDO::getWarehouseId, warehouseId); } + default int updateCountIncrement(Long id, BigDecimal count, boolean negativeEnable) { + LambdaUpdateWrapper updateWrapper = new LambdaUpdateWrapper() + .eq(ErpStockDO::getId, id); + if (count.compareTo(BigDecimal.ZERO) > 0) { + updateWrapper.setSql("count = count + " + count); + } else if (count.compareTo(BigDecimal.ZERO) < 0) { + if (!negativeEnable) { + updateWrapper.gt(ErpStockDO::getCount, count.abs()); + } + updateWrapper.setSql("count = count - " + count.abs()); + } + return update(null, updateWrapper); + } + } \ No newline at end of file diff --git a/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/service/stock/ErpStockInServiceImpl.java b/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/service/stock/ErpStockInServiceImpl.java index 55dbf8def..85aa6ff53 100644 --- a/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/service/stock/ErpStockInServiceImpl.java +++ b/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/service/stock/ErpStockInServiceImpl.java @@ -13,8 +13,10 @@ import cn.iocoder.yudao.module.erp.dal.mysql.stock.ErpStockInItemMapper; import cn.iocoder.yudao.module.erp.dal.mysql.stock.ErpStockInMapper; import cn.iocoder.yudao.module.erp.dal.redis.no.ErpNoRedisDAO; import cn.iocoder.yudao.module.erp.enums.ErpAuditStatus; +import cn.iocoder.yudao.module.erp.enums.stock.ErpStockRecordBizTypeEnum; import cn.iocoder.yudao.module.erp.service.product.ErpProductService; import cn.iocoder.yudao.module.erp.service.purchase.ErpSupplierService; +import cn.iocoder.yudao.module.erp.service.stock.bo.ErpStockInCreateReqBO; import jakarta.annotation.Resource; import org.springframework.stereotype.Service; import org.springframework.transaction.annotation.Transactional; @@ -54,6 +56,8 @@ public class ErpStockInServiceImpl implements ErpStockInService { private ErpWarehouseService warehouseService; @Resource private ErpSupplierService supplierService; + @Resource + private ErpStockRecordService stockRecordService; @Override @Transactional(rollbackFor = Exception.class) @@ -102,23 +106,31 @@ public class ErpStockInServiceImpl implements ErpStockInService { @Override @Transactional(rollbackFor = Exception.class) public void updateStockInStatus(Long id, Integer status) { + boolean approve = ErpAuditStatus.APPROVE.getStatus().equals(status); // 1.1 校验存在 ErpStockInDO stockIn = validateStockInExists(id); // 1.2 校验状态 if (stockIn.getStatus().equals(status)) { - throw exception(ErpAuditStatus.PROCESS.getStatus().equals(status) ? - STOCK_IN_PROCESS_FAIL : STOCK_IN_APPROVE_FAIL); + throw exception(approve ? STOCK_IN_APPROVE_FAIL : STOCK_IN_PROCESS_FAIL); } // 2. 更新状态 int updateCount = stockInMapper.updateByIdAndStatus(id, stockIn.getStatus(), new ErpStockInDO().setStatus(status)); if (updateCount == 0) { - throw exception(ErpAuditStatus.PROCESS.getStatus().equals(status) ? - STOCK_IN_PROCESS_FAIL : STOCK_IN_APPROVE_FAIL); + throw exception(approve ? STOCK_IN_APPROVE_FAIL : STOCK_IN_PROCESS_FAIL); } - // 3. TODO 芋艿:调整库存记录 + // 3. 变更库存 + List stockInItems = stockInItemMapper.selectListByInId(id); + Integer bizType = approve ? ErpStockRecordBizTypeEnum.OTHER_IN.getType() + : ErpStockRecordBizTypeEnum.OTHER_IN_CANCEL.getType(); + stockInItems.forEach(stockInItem -> { + BigDecimal count = approve ? stockInItem.getCount() : stockInItem.getCount().negate(); + stockRecordService.createStockRecord(new ErpStockInCreateReqBO( + stockInItem.getProductId(), stockInItem.getWarehouseId(), count, + bizType, stockInItem.getInId(), stockInItem.getId(), stockIn.getNo())); + }); } private List validateStockInItems(List list) { diff --git a/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/service/stock/ErpStockRecordService.java b/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/service/stock/ErpStockRecordService.java index 08acb89b5..0e20a55f2 100644 --- a/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/service/stock/ErpStockRecordService.java +++ b/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/service/stock/ErpStockRecordService.java @@ -3,6 +3,8 @@ package cn.iocoder.yudao.module.erp.service.stock; import cn.iocoder.yudao.framework.common.pojo.PageResult; import cn.iocoder.yudao.module.erp.controller.admin.stock.vo.record.ErpStockRecordPageReqVO; import cn.iocoder.yudao.module.erp.dal.dataobject.stock.ErpStockRecordDO; +import cn.iocoder.yudao.module.erp.service.stock.bo.ErpStockInCreateReqBO; +import jakarta.validation.Valid; /** * ERP 产品库存明细 Service 接口 @@ -27,4 +29,11 @@ public interface ErpStockRecordService { */ PageResult getStockRecordPage(ErpStockRecordPageReqVO pageReqVO); + /** + * 创建库存明细 + * + * @param createReqBO 创建库存明细 BO + */ + void createStockRecord(@Valid ErpStockInCreateReqBO createReqBO); + } \ No newline at end of file diff --git a/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/service/stock/ErpStockRecordServiceImpl.java b/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/service/stock/ErpStockRecordServiceImpl.java index 6f50b91cc..708a39f18 100644 --- a/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/service/stock/ErpStockRecordServiceImpl.java +++ b/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/service/stock/ErpStockRecordServiceImpl.java @@ -1,13 +1,18 @@ package cn.iocoder.yudao.module.erp.service.stock; import cn.iocoder.yudao.framework.common.pojo.PageResult; +import cn.iocoder.yudao.framework.common.util.object.BeanUtils; import cn.iocoder.yudao.module.erp.controller.admin.stock.vo.record.ErpStockRecordPageReqVO; import cn.iocoder.yudao.module.erp.dal.dataobject.stock.ErpStockRecordDO; import cn.iocoder.yudao.module.erp.dal.mysql.stock.ErpStockRecordMapper; +import cn.iocoder.yudao.module.erp.service.stock.bo.ErpStockInCreateReqBO; import jakarta.annotation.Resource; import org.springframework.stereotype.Service; +import org.springframework.transaction.annotation.Transactional; import org.springframework.validation.annotation.Validated; +import java.math.BigDecimal; + /** * ERP 产品库存明细 Service 实现类 * @@ -20,6 +25,9 @@ public class ErpStockRecordServiceImpl implements ErpStockRecordService { @Resource private ErpStockRecordMapper stockRecordMapper; + @Resource + private ErpStockService stockService; + @Override public ErpStockRecordDO getStockRecord(Long id) { return stockRecordMapper.selectById(id); @@ -30,4 +38,16 @@ public class ErpStockRecordServiceImpl implements ErpStockRecordService { return stockRecordMapper.selectPage(pageReqVO); } + @Override + @Transactional(rollbackFor = Exception.class) + public void createStockRecord(ErpStockInCreateReqBO createReqBO) { + // 1. 更新库存 + BigDecimal totalCount = stockService.updateStockCountIncrement( + createReqBO.getProductId(), createReqBO.getWarehouseId(), createReqBO.getCount()); + // 2. 创建库存明细 + ErpStockRecordDO stockRecord = BeanUtils.toBean(createReqBO, ErpStockRecordDO.class) + .setTotalCount(totalCount); + stockRecordMapper.insert(stockRecord); + } + } \ No newline at end of file diff --git a/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/service/stock/ErpStockService.java b/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/service/stock/ErpStockService.java index f9cd26158..91224c7fa 100644 --- a/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/service/stock/ErpStockService.java +++ b/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/service/stock/ErpStockService.java @@ -4,6 +4,8 @@ import cn.iocoder.yudao.framework.common.pojo.PageResult; import cn.iocoder.yudao.module.erp.controller.admin.stock.vo.stock.ErpStockPageReqVO; import cn.iocoder.yudao.module.erp.dal.dataobject.stock.ErpStockDO; +import java.math.BigDecimal; + /** * ERP 产品库存 Service 接口 * @@ -36,4 +38,14 @@ public interface ErpStockService { */ PageResult getStockPage(ErpStockPageReqVO pageReqVO); + /** + * 增量更新产品库存数量 + * + * @param productId 产品编号 + * @param warehouseId 仓库编号 + * @param count 增量数量:正数,表示增加;负数,表示减少 + * @return 更新后的库存 + */ + BigDecimal updateStockCountIncrement(Long productId, Long warehouseId, BigDecimal count); + } \ No newline at end of file diff --git a/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/service/stock/ErpStockServiceImpl.java b/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/service/stock/ErpStockServiceImpl.java index 423774265..c930cff36 100644 --- a/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/service/stock/ErpStockServiceImpl.java +++ b/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/service/stock/ErpStockServiceImpl.java @@ -8,6 +8,12 @@ import jakarta.annotation.Resource; import org.springframework.stereotype.Service; import org.springframework.validation.annotation.Validated; +import java.math.BigDecimal; + +import static cn.iocoder.yudao.framework.common.exception.util.ServiceExceptionUtil.exception; +import static cn.iocoder.yudao.module.erp.enums.ErrorCodeConstants.STOCK_COUNT_NEGATIVE; +import static cn.iocoder.yudao.module.erp.enums.ErrorCodeConstants.STOCK_COUNT_NEGATIVE2; + /** * ERP 产品库存 Service 实现类 * @@ -17,6 +23,13 @@ import org.springframework.validation.annotation.Validated; @Validated public class ErpStockServiceImpl implements ErpStockService { + /** + * 允许库存为负数 + * + * TODO 芋艿:后续做成 db 配置 + */ + private static final Boolean NEGATIVE_STOCK_COUNT_ENABLE = false; + @Resource private ErpStockMapper stockMapper; @@ -35,4 +48,27 @@ public class ErpStockServiceImpl implements ErpStockService { return stockMapper.selectPage(pageReqVO); } + @Override + public BigDecimal updateStockCountIncrement(Long productId, Long warehouseId, BigDecimal count) { + // 1.1 查询当前库存 + ErpStockDO stock = stockMapper.selectByProductIdAndWarehouseId(productId, warehouseId); + if (stock == null) { + stock = new ErpStockDO().setProductId(productId).setWarehouseId(warehouseId).setCount(BigDecimal.ZERO); + stockMapper.insert(stock); + } + // 1.2 校验库存是否充足 + if (!NEGATIVE_STOCK_COUNT_ENABLE && stock.getCount().add(count).compareTo(BigDecimal.ZERO) < 0) { + throw exception(STOCK_COUNT_NEGATIVE, stock.getCount(), count); + } + + // 2. 库存变更 + int updateCount = stockMapper.updateCountIncrement(stock.getId(), count, NEGATIVE_STOCK_COUNT_ENABLE); + if (updateCount == 0) { + throw exception(STOCK_COUNT_NEGATIVE2); // 此时不好去查询最新库存,所以直接抛出该提示,不提供具体库存数字 + } + + // 3. 返回最新库存 + return stock.getCount().add(count); + } + } \ No newline at end of file diff --git a/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/service/stock/bo/ErpStockInCreateReqBO.java b/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/service/stock/bo/ErpStockInCreateReqBO.java new file mode 100644 index 000000000..3211a2e76 --- /dev/null +++ b/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/service/stock/bo/ErpStockInCreateReqBO.java @@ -0,0 +1,59 @@ +package cn.iocoder.yudao.module.erp.service.stock.bo; + +import jakarta.validation.constraints.NotNull; +import lombok.AllArgsConstructor; +import lombok.Data; +import lombok.NoArgsConstructor; + +import java.math.BigDecimal; + +/** + * 库存明细的创建 Request BO + * + * @author 芋道源码 + */ +@Data +@NoArgsConstructor +@AllArgsConstructor +public class ErpStockInCreateReqBO { + + /** + * 产品编号 + */ + @NotNull(message = "产品编号不能为空") + private Long productId; + /** + * 仓库编号 + */ + @NotNull(message = "仓库编号不能为空") + private Long warehouseId; + /** + * 出入库数量 + * + * 正数,表示入库;负数,表示出库 + */ + @NotNull(message = "出入库数量不能为空") + private BigDecimal count; + + /** + * 业务类型 + */ + @NotNull(message = "业务类型不能为空") + private Integer bizType; + /** + * 业务编号 + */ + @NotNull(message = "业务编号不能为空") + private Long bizId; + /** + * 业务项编号 + */ + @NotNull(message = "业务项编号不能为空") + private Long bizItemId; + /** + * 业务单号 + */ + @NotNull(message = "业务单号不能为空") + private String bizNo; + +} From 256d2435079c64b807fa3383d4a85167229c4992 Mon Sep 17 00:00:00 2001 From: YunaiV Date: Wed, 7 Feb 2024 15:00:40 +0800 Subject: [PATCH 084/119] =?UTF-8?q?=E2=9C=A8=20ERP=EF=BC=9A=E5=88=9D?= =?UTF-8?q?=E5=A7=8B=E5=8C=96=E5=85=B6=E5=AE=83=E5=87=BA=E5=BA=93=E7=9A=84?= =?UTF-8?q?=E5=AE=9E=E7=8E=B0?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../module/erp/enums/ErrorCodeConstants.java | 7 + .../admin/stock/ErpStockOutController.java | 163 +++++++++++++ .../stock/vo/out/ErpStockOutPageReqVO.java | 48 ++++ .../admin/stock/vo/out/ErpStockOutRespVO.java | 110 +++++++++ .../stock/vo/out/ErpStockOutSaveReqVO.java | 64 +++++ .../dal/dataobject/stock/ErpStockInDO.java | 3 +- .../dal/dataobject/stock/ErpStockOutDO.java | 69 ++++++ .../dataobject/stock/ErpStockOutItemDO.java | 73 ++++++ .../mysql/stock/ErpStockOutItemMapper.java | 30 +++ .../dal/mysql/stock/ErpStockOutMapper.java | 47 ++++ .../erp/dal/redis/no/ErpNoRedisDAO.java | 6 +- .../service/stock/ErpStockInServiceImpl.java | 9 +- .../erp/service/stock/ErpStockOutService.java | 84 +++++++ .../service/stock/ErpStockOutServiceImpl.java | 227 ++++++++++++++++++ .../service/stock/ErpStockRecordService.java | 4 +- .../stock/ErpStockRecordServiceImpl.java | 4 +- ...BO.java => ErpStockRecordCreateReqBO.java} | 2 +- 17 files changed, 940 insertions(+), 10 deletions(-) create mode 100644 yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/controller/admin/stock/ErpStockOutController.java create mode 100644 yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/controller/admin/stock/vo/out/ErpStockOutPageReqVO.java create mode 100644 yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/controller/admin/stock/vo/out/ErpStockOutRespVO.java create mode 100644 yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/controller/admin/stock/vo/out/ErpStockOutSaveReqVO.java create mode 100644 yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/dal/dataobject/stock/ErpStockOutDO.java create mode 100644 yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/dal/dataobject/stock/ErpStockOutItemDO.java create mode 100644 yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/dal/mysql/stock/ErpStockOutItemMapper.java create mode 100644 yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/dal/mysql/stock/ErpStockOutMapper.java create mode 100644 yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/service/stock/ErpStockOutService.java create mode 100644 yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/service/stock/ErpStockOutServiceImpl.java rename yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/service/stock/bo/{ErpStockInCreateReqBO.java => ErpStockRecordCreateReqBO.java} (96%) diff --git a/yudao-module-erp/yudao-module-erp-api/src/main/java/cn/iocoder/yudao/module/erp/enums/ErrorCodeConstants.java b/yudao-module-erp/yudao-module-erp-api/src/main/java/cn/iocoder/yudao/module/erp/enums/ErrorCodeConstants.java index ba7d7685c..7bd87bdb9 100644 --- a/yudao-module-erp/yudao-module-erp-api/src/main/java/cn/iocoder/yudao/module/erp/enums/ErrorCodeConstants.java +++ b/yudao-module-erp/yudao-module-erp-api/src/main/java/cn/iocoder/yudao/module/erp/enums/ErrorCodeConstants.java @@ -26,8 +26,15 @@ public interface ErrorCodeConstants { ErrorCode STOCK_IN_PROCESS_FAIL = new ErrorCode(1_030_401_002, "反审核失败,只有已审核的入库单才能反审核"); ErrorCode STOCK_IN_APPROVE_FAIL = new ErrorCode(1_030_401_003, "审核失败,只有未审核的入库单才能审核"); ErrorCode STOCK_IN_NO_EXISTS = new ErrorCode(1_030_401_004, "生成入库单失败,请重新提交"); + ErrorCode STOCK_IN_UPDATE_FAIL_APPROVE = new ErrorCode(1_030_401_005, "其它入库单({})已审核,无法修改"); // ========== ERP 其它出库单 1-030-402-000 ========== + ErrorCode STOCK_OUT_NOT_EXISTS = new ErrorCode(1_030_402_000, "其它出库单不存在"); + ErrorCode STOCK_OUT_DELETE_FAIL_APPROVE = new ErrorCode(1_030_402_001, "其它出库单({})已审核,无法删除"); + ErrorCode STOCK_OUT_PROCESS_FAIL = new ErrorCode(1_030_402_002, "反审核失败,只有已审核的出库单才能反审核"); + ErrorCode STOCK_OUT_APPROVE_FAIL = new ErrorCode(1_030_402_003, "审核失败,只有未审核的出库单才能审核"); + ErrorCode STOCK_OUT_NO_EXISTS = new ErrorCode(1_030_402_004, "生成出库单失败,请重新提交"); + ErrorCode STOCK_OUT_UPDATE_FAIL_APPROVE = new ErrorCode(1_030_402_005, "其它出库单({})已审核,无法修改"); // ========== ERP 产品库存 1-030-403-000 ========== ErrorCode STOCK_COUNT_NEGATIVE = new ErrorCode(1_030_403_000, "操作失败,产品当前库存:{},小于变更数量:{}"); diff --git a/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/controller/admin/stock/ErpStockOutController.java b/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/controller/admin/stock/ErpStockOutController.java new file mode 100644 index 000000000..306d51277 --- /dev/null +++ b/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/controller/admin/stock/ErpStockOutController.java @@ -0,0 +1,163 @@ +package cn.iocoder.yudao.module.erp.controller.admin.stock; + +import cn.hutool.core.collection.CollUtil; +import cn.iocoder.yudao.framework.common.pojo.CommonResult; +import cn.iocoder.yudao.framework.common.pojo.PageParam; +import cn.iocoder.yudao.framework.common.pojo.PageResult; +import cn.iocoder.yudao.framework.common.util.collection.MapUtils; +import cn.iocoder.yudao.framework.common.util.object.BeanUtils; +import cn.iocoder.yudao.framework.excel.core.util.ExcelUtils; +import cn.iocoder.yudao.framework.operatelog.core.annotations.OperateLog; +import cn.iocoder.yudao.module.erp.controller.admin.product.vo.product.ErpProductRespVO; +import cn.iocoder.yudao.module.erp.controller.admin.stock.vo.out.ErpStockOutPageReqVO; +import cn.iocoder.yudao.module.erp.controller.admin.stock.vo.out.ErpStockOutRespVO; +import cn.iocoder.yudao.module.erp.controller.admin.stock.vo.out.ErpStockOutSaveReqVO; +import cn.iocoder.yudao.module.erp.dal.dataobject.stock.ErpStockDO; +import cn.iocoder.yudao.module.erp.dal.dataobject.stock.ErpStockOutDO; +import cn.iocoder.yudao.module.erp.dal.dataobject.stock.ErpStockOutItemDO; +import cn.iocoder.yudao.module.erp.service.product.ErpProductService; +import cn.iocoder.yudao.module.erp.service.stock.ErpStockOutService; +import cn.iocoder.yudao.module.erp.service.stock.ErpStockService; +import cn.iocoder.yudao.module.system.api.user.AdminUserApi; +import cn.iocoder.yudao.module.system.api.user.dto.AdminUserRespDTO; +import io.swagger.v3.oas.annotations.Operation; +import io.swagger.v3.oas.annotations.Parameter; +import io.swagger.v3.oas.annotations.tags.Tag; +import jakarta.annotation.Resource; +import jakarta.servlet.http.HttpServletResponse; +import jakarta.validation.Valid; +import org.springframework.security.access.prepost.PreAuthorize; +import org.springframework.validation.annotation.Validated; +import org.springframework.web.bind.annotation.*; + +import java.io.IOException; +import java.math.BigDecimal; +import java.util.List; +import java.util.Map; + +import static cn.iocoder.yudao.framework.common.pojo.CommonResult.success; +import static cn.iocoder.yudao.framework.common.util.collection.CollectionUtils.convertMultiMap; +import static cn.iocoder.yudao.framework.common.util.collection.CollectionUtils.convertSet; +import static cn.iocoder.yudao.framework.operatelog.core.enums.OperateTypeEnum.EXPORT; + +@Tag(name = "管理后台 - ERP 其它出库单") +@RestController +@RequestMapping("/erp/stock-out") +@Validated +public class ErpStockOutController { + + @Resource + private ErpStockOutService stockOutService; + @Resource + private ErpStockService stockService; + @Resource + private ErpProductService productService; +// @Resource +// private ErpSupplierService supplierService; + + @Resource + private AdminUserApi adminUserApi; + + @PostMapping("/create") + @Operation(summary = "创建其它出库单") + @PreAuthorize("@ss.hasPermission('erp:stock-out:create')") + public CommonResult createStockOut(@Valid @RequestBody ErpStockOutSaveReqVO createReqVO) { + return success(stockOutService.createStockOut(createReqVO)); + } + + @PutMapping("/update") + @Operation(summary = "更新其它出库单") + @PreAuthorize("@ss.hasPermission('erp:stock-out:update')") + public CommonResult updateStockOut(@Valid @RequestBody ErpStockOutSaveReqVO updateReqVO) { + stockOutService.updateStockOut(updateReqVO); + return success(true); + } + + @PutMapping("/update-status") + @Operation(summary = "更新其它出库单的状态") + @PreAuthorize("@ss.hasPermission('erp:stock-out:update')") + public CommonResult updateStockOutStatus(@RequestParam("id") Long id, + @RequestParam("status") Integer status) { + stockOutService.updateStockOutStatus(id, status); + return success(true); + } + + @DeleteMapping("/delete") + @Operation(summary = "删除其它出库单") + @Parameter(name = "ids", description = "编号数组", required = true) + @PreAuthorize("@ss.hasPermission('erp:stock-out:delete')") + public CommonResult deleteStockOut(@RequestParam("ids") List ids) { + stockOutService.deleteStockOut(ids); + return success(true); + } + + @GetMapping("/get") + @Operation(summary = "获得其它出库单") + @Parameter(name = "id", description = "编号", required = true, example = "1024") + @PreAuthorize("@ss.hasPermission('erp:stock-out:query')") + public CommonResult getStockOut(@RequestParam("id") Long id) { + ErpStockOutDO stockOut = stockOutService.getStockOut(id); + if (stockOut == null) { + return success(null); + } + List stockOutItemList = stockOutService.getStockOutItemListByOutId(id); + Map 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") + @Operation(summary = "获得其它出库单分页") + @PreAuthorize("@ss.hasPermission('erp:stock-out:query')") + public CommonResult> getStockOutPage(@Valid ErpStockOutPageReqVO pageReqVO) { + PageResult pageResult = stockOutService.getStockOutPage(pageReqVO); + return success(buildStockOutVOPageResult(pageResult)); + } + + @GetMapping("/export-excel") + @Operation(summary = "导出其它出库单 Excel") + @PreAuthorize("@ss.hasPermission('erp:stock-out:export')") + @OperateLog(type = EXPORT) + public void exportStockOutExcel(@Valid ErpStockOutPageReqVO pageReqVO, + HttpServletResponse response) throws IOException { + pageReqVO.setPageSize(PageParam.PAGE_SIZE_NONE); + List list = buildStockOutVOPageResult(stockOutService.getStockOutPage(pageReqVO)).getList(); + // 导出 Excel + ExcelUtils.write(response, "其它出库单.xls", "数据", ErpStockOutRespVO.class, list); + } + + private PageResult buildStockOutVOPageResult(PageResult pageResult) { + if (CollUtil.isEmpty(pageResult.getList())) { + return PageResult.empty(pageResult.getTotal()); + } + // 1.1 出库项 + List stockOutItemList = stockOutService.getStockOutItemListByOutIds( + convertSet(pageResult.getList(), ErpStockOutDO::getId)); + Map> stockOutItemMap = convertMultiMap(stockOutItemList, ErpStockOutItemDO::getOutId); + // 1.2 商品信息 + Map productMap = productService.getProductVOMap( + convertSet(stockOutItemList, ErpStockOutItemDO::getProductId)); + // 1.3 客户信息 TODO +// Map supplierMap = supplierService.getSupplierMap( +// convertSet(pageResult.getList(), ErpStockOutDO::getSupplierId)); + // 1.4 管理员信息 + Map userMap = adminUserApi.getUserMap( + convertSet(pageResult.getList(), erpStockRecordDO -> Long.parseLong(erpStockRecordDO.getCreator()))); + // 2. 开始拼接 + return BeanUtils.toBean(pageResult, ErpStockOutRespVO.class, stockOut -> { + stockOut.setItems(BeanUtils.toBean(stockOutItemMap.get(stockOut.getId()), ErpStockOutRespVO.Item.class, + item -> MapUtils.findAndThen(productMap, item.getProductId(), product -> item.setProductName(product.getName()) + .setProductBarCode(product.getBarCode()).setProductUnitName(product.getUnitName())))); + stockOut.setProductNames(CollUtil.join(stockOut.getItems(), ",", ErpStockOutRespVO.Item::getProductName)); +// MapUtils.findAndThen(supplierMap, stockOut.getSupplierId(), supplier -> stockOut.setSupplierName(supplier.getName())); + MapUtils.findAndThen(userMap, Long.parseLong(stockOut.getCreator()), user -> stockOut.setCreatorName(user.getNickname())); + }); + } + +} \ No newline at end of file diff --git a/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/controller/admin/stock/vo/out/ErpStockOutPageReqVO.java b/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/controller/admin/stock/vo/out/ErpStockOutPageReqVO.java new file mode 100644 index 000000000..5f6558b19 --- /dev/null +++ b/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/controller/admin/stock/vo/out/ErpStockOutPageReqVO.java @@ -0,0 +1,48 @@ +package cn.iocoder.yudao.module.erp.controller.admin.stock.vo.out; + +import cn.iocoder.yudao.framework.common.pojo.PageParam; +import cn.iocoder.yudao.framework.common.validation.InEnum; +import cn.iocoder.yudao.module.erp.enums.ErpAuditStatus; +import io.swagger.v3.oas.annotations.media.Schema; +import lombok.Data; +import lombok.EqualsAndHashCode; +import lombok.ToString; +import org.springframework.format.annotation.DateTimeFormat; + +import java.time.LocalDateTime; + +import static cn.iocoder.yudao.framework.common.util.date.DateUtils.FORMAT_YEAR_MONTH_DAY_HOUR_MINUTE_SECOND; + +@Schema(description = "管理后台 - ERP 其它出库单分页 Request VO") +@Data +@EqualsAndHashCode(callSuper = true) +@ToString(callSuper = true) +public class ErpStockOutPageReqVO extends PageParam { + + @Schema(description = "出库单号", example = "S123") + private String no; + + @Schema(description = "客户编号", example = "3113") + private Long customerId; + + @Schema(description = "出库时间") + @DateTimeFormat(pattern = FORMAT_YEAR_MONTH_DAY_HOUR_MINUTE_SECOND) + private LocalDateTime[] outTime; + + @Schema(description = "状态", example = "10") + @InEnum(ErpAuditStatus.class) + private Integer status; + + @Schema(description = "备注", example = "随便") + private String remark; + + @Schema(description = "创建者") + private String creator; + + @Schema(description = "产品编号", example = "1") + private Long productId; + + @Schema(description = "仓库编号", example = "1") + private Long warehouseId; + +} \ No newline at end of file diff --git a/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/controller/admin/stock/vo/out/ErpStockOutRespVO.java b/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/controller/admin/stock/vo/out/ErpStockOutRespVO.java new file mode 100644 index 000000000..e0128730e --- /dev/null +++ b/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/controller/admin/stock/vo/out/ErpStockOutRespVO.java @@ -0,0 +1,110 @@ +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.convert.DictConvert; +import com.alibaba.excel.annotation.ExcelIgnoreUnannotated; +import com.alibaba.excel.annotation.ExcelProperty; +import io.swagger.v3.oas.annotations.media.Schema; +import lombok.Data; + +import java.math.BigDecimal; +import java.time.LocalDateTime; +import java.util.List; + +import static cn.iocoder.yudao.module.erp.enums.DictTypeConstants.AUDIT_STATUS; + +@Schema(description = "管理后台 - ERP 其它出库单 Response VO") +@Data +@ExcelIgnoreUnannotated +public class ErpStockOutRespVO { + + @Schema(description = "出库编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "11756") + @ExcelProperty("出库编号") + private Long id; + + @Schema(description = "出库单号", requiredMode = Schema.RequiredMode.REQUIRED, example = "S123") + @ExcelProperty("出库单号") + private String no; + + @Schema(description = "客户编号", example = "3113") + private Long customerId; + @Schema(description = "客户名称", example = "芋道") + @ExcelProperty("客户名称") + private String customerName; + + @Schema(description = "出库时间", requiredMode = Schema.RequiredMode.REQUIRED) + @ExcelProperty("出库时间") + private LocalDateTime outTime; + + @Schema(description = "合计数量", requiredMode = Schema.RequiredMode.REQUIRED, example = "15663") + @ExcelProperty("合计数量") + private BigDecimal totalCount; + + @Schema(description = "合计金额,单位:元", requiredMode = Schema.RequiredMode.REQUIRED, example = "24906") + @ExcelProperty("合计金额") + private BigDecimal totalPrice; + + @Schema(description = "状态", requiredMode = Schema.RequiredMode.REQUIRED, example = "10") + @ExcelProperty(value = "状态", converter = DictConvert.class) + @DictFormat(AUDIT_STATUS) + private Integer status; + + @Schema(description = "备注", example = "随便") + @ExcelProperty("备注") + private String remark; + + @Schema(description = "附件 URL", example = "https://www.iocoder.cn/1.doc") + private String fileUrl; + + @Schema(description = "审核人", example = "芋道") + private String creator; + @Schema(description = "审核人名称", example = "芋道") + private String creatorName; + + @Schema(description = "创建时间", requiredMode = Schema.RequiredMode.REQUIRED) + @ExcelProperty("创建时间") + private LocalDateTime createTime; + + @Schema(description = "出库项列表", requiredMode = Schema.RequiredMode.REQUIRED) + private List items; + + @Schema(description = "产品信息", requiredMode = Schema.RequiredMode.REQUIRED) + @ExcelProperty("产品信息") + private String productNames; + + @Data + public static class Item { + + @Schema(description = "出库项编号", example = "11756") + private Long id; + + @Schema(description = "仓库编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "3113") + private Long warehouseId; + + @Schema(description = "产品编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "3113") + private Long productId; + + @Schema(description = "产品单价", requiredMode = Schema.RequiredMode.REQUIRED, example = "100.00") + private BigDecimal productPrice; + + @Schema(description = "产品数量", requiredMode = Schema.RequiredMode.REQUIRED, example = "100.00") + private BigDecimal count; + + @Schema(description = "备注", example = "随便") + private String remark; + + // ========== 关联字段 ========== + + @Schema(description = "产品名称", requiredMode = Schema.RequiredMode.REQUIRED, example = "巧克力") + private String productName; + @Schema(description = "产品条码", requiredMode = Schema.RequiredMode.REQUIRED, example = "A9985") + private String productBarCode; + @Schema(description = "产品单位名称", requiredMode = Schema.RequiredMode.REQUIRED, example = "盒") + private String productUnitName; + + @Schema(description = "库存数量", requiredMode = Schema.RequiredMode.REQUIRED, example = "100.00") + private BigDecimal stockCount; // 该字段仅仅在“详情”和“编辑”时使用 + + } + +} \ No newline at end of file diff --git a/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/controller/admin/stock/vo/out/ErpStockOutSaveReqVO.java b/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/controller/admin/stock/vo/out/ErpStockOutSaveReqVO.java new file mode 100644 index 000000000..5a903798e --- /dev/null +++ b/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/controller/admin/stock/vo/out/ErpStockOutSaveReqVO.java @@ -0,0 +1,64 @@ +package cn.iocoder.yudao.module.erp.controller.admin.stock.vo.out; + +import io.swagger.v3.oas.annotations.media.Schema; +import jakarta.validation.Valid; +import jakarta.validation.constraints.NotEmpty; +import jakarta.validation.constraints.NotNull; +import lombok.Data; + +import java.math.BigDecimal; +import java.time.LocalDateTime; +import java.util.List; + +@Schema(description = "管理后台 - ERP 其它出库单新增/修改 Request VO") +@Data +public class ErpStockOutSaveReqVO { + + @Schema(description = "出库编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "11756") + private Long id; + + @Schema(description = "客户编号", example = "3113") + private Long customerId; + + @Schema(description = "出库时间", requiredMode = Schema.RequiredMode.REQUIRED) + @NotNull(message = "出库时间不能为空") + private LocalDateTime outTime; + + @Schema(description = "备注", example = "随便") + private String remark; + + @Schema(description = "附件 URL", example = "https://www.iocoder.cn/1.doc") + private String fileUrl; + + @Schema(description = "出库项列表", requiredMode = Schema.RequiredMode.REQUIRED) + @NotEmpty(message = "出库项列表不能为空") + @Valid + private List items; + + @Data + public static class Item { + + @Schema(description = "出库项编号", example = "11756") + private Long id; + + @Schema(description = "仓库编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "3113") + @NotNull(message = "仓库编号不能为空") + private Long warehouseId; + + @Schema(description = "产品编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "3113") + @NotNull(message = "产品编号不能为空") + private Long productId; + + @Schema(description = "产品单价", example = "100.00") + private BigDecimal productPrice; + + @Schema(description = "产品数量", requiredMode = Schema.RequiredMode.REQUIRED, example = "100.00") + @NotNull(message = "产品数量不能为空") + private BigDecimal count; + + @Schema(description = "备注", example = "随便") + private String remark; + + } + +} \ No newline at end of file diff --git a/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/dal/dataobject/stock/ErpStockInDO.java b/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/dal/dataobject/stock/ErpStockInDO.java index 4eaa316e9..5115b9daf 100644 --- a/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/dal/dataobject/stock/ErpStockInDO.java +++ b/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/dal/dataobject/stock/ErpStockInDO.java @@ -1,6 +1,7 @@ package cn.iocoder.yudao.module.erp.dal.dataobject.stock; import cn.iocoder.yudao.framework.mybatis.core.dataobject.BaseDO; +import cn.iocoder.yudao.module.erp.dal.dataobject.supplier.ErpSupplierDO; import com.baomidou.mybatisplus.annotation.KeySequence; import com.baomidou.mybatisplus.annotation.TableId; import com.baomidou.mybatisplus.annotation.TableName; @@ -36,7 +37,7 @@ public class ErpStockInDO extends BaseDO { /** * 供应商编号 * - * TODO 芋艿:待关联 + * 关联 {@link ErpSupplierDO#getId()} */ private Long supplierId; /** diff --git a/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/dal/dataobject/stock/ErpStockOutDO.java b/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/dal/dataobject/stock/ErpStockOutDO.java new file mode 100644 index 000000000..e0b337adb --- /dev/null +++ b/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/dal/dataobject/stock/ErpStockOutDO.java @@ -0,0 +1,69 @@ +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.*; + +import java.math.BigDecimal; +import java.time.LocalDateTime; + +/** + * ERP 其它出库单 DO + * + * @author 芋道源码 + */ +@TableName("erp_stock_out") +@KeySequence("erp_stock_out_seq") // 用于 Oracle、PostgreSQL、Kingbase、DB2、H2 数据库的主键自增。如果是 MySQL 等数据库,可不写。 +@Data +@EqualsAndHashCode(callSuper = true) +@ToString(callSuper = true) +@Builder +@NoArgsConstructor +@AllArgsConstructor +public class ErpStockOutDO extends BaseDO { + + /** + * 出库编号 + */ + @TableId + private Long id; + /** + * 出库单号 + */ + private String no; + /** + * 客户编号 + * + * TODO 芋艿:待关联 + */ + private Long customerId; + /** + * 出库时间 + */ + private LocalDateTime outTime; + /** + * 合计数量 + */ + private BigDecimal totalCount; + /** + * 合计金额,单位:元 + */ + private BigDecimal totalPrice; + /** + * 状态 + * + * 枚举 {@link cn.iocoder.yudao.module.erp.enums.ErpAuditStatus} + */ + private Integer status; + /** + * 备注 + */ + private String remark; + /** + * 附件 URL + */ + private String fileUrl; + +} \ No newline at end of file diff --git a/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/dal/dataobject/stock/ErpStockOutItemDO.java b/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/dal/dataobject/stock/ErpStockOutItemDO.java new file mode 100644 index 000000000..065c5255a --- /dev/null +++ b/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/dal/dataobject/stock/ErpStockOutItemDO.java @@ -0,0 +1,73 @@ +package cn.iocoder.yudao.module.erp.dal.dataobject.stock; + +import cn.iocoder.yudao.framework.mybatis.core.dataobject.BaseDO; +import cn.iocoder.yudao.module.erp.dal.dataobject.product.ErpProductDO; +import com.baomidou.mybatisplus.annotation.KeySequence; +import com.baomidou.mybatisplus.annotation.TableId; +import com.baomidou.mybatisplus.annotation.TableName; +import lombok.*; + +import java.math.BigDecimal; + +/** + * ERP 其它出库单项 DO + * + * @author 芋道源码 + */ +@TableName("erp_stock_out_item") +@KeySequence("erp_stock_out_item_seq") // 用于 Oracle、PostgreSQL、Kingbase、DB2、H2 数据库的主键自增。如果是 MySQL 等数据库,可不写。 +@Data +@EqualsAndHashCode(callSuper = true) +@ToString(callSuper = true) +@Builder +@NoArgsConstructor +@AllArgsConstructor +public class ErpStockOutItemDO extends BaseDO { + + /** + * 出库项编号 + */ + @TableId + private Long id; + /** + * 出库编号 + * + * 关联 {@link ErpStockOutDO#getId()} + */ + private Long outId; + /** + * 仓库编号 + * + * 关联 {@link ErpWarehouseDO#getId()} + */ + private Long warehouseId; + /** + * 产品编号 + * + * 关联 {@link ErpProductDO#getId()} + */ + private Long productId; + /** + * 产品单位编号 + * + * 冗余 {@link ErpProductDO#getUnitId()} + */ + private Long productUnitId; + /** + * 产品单价 + */ + private BigDecimal productPrice; + /** + * 产品数量 + */ + private BigDecimal count; + /** + * 合计金额,单位:元 + */ + private BigDecimal totalPrice; + /** + * 备注 + */ + private String remark; + +} \ No newline at end of file diff --git a/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/dal/mysql/stock/ErpStockOutItemMapper.java b/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/dal/mysql/stock/ErpStockOutItemMapper.java new file mode 100644 index 000000000..3b27cd3dc --- /dev/null +++ b/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/dal/mysql/stock/ErpStockOutItemMapper.java @@ -0,0 +1,30 @@ +package cn.iocoder.yudao.module.erp.dal.mysql.stock; + +import cn.iocoder.yudao.framework.mybatis.core.mapper.BaseMapperX; +import cn.iocoder.yudao.module.erp.dal.dataobject.stock.ErpStockOutItemDO; +import org.apache.ibatis.annotations.Mapper; + +import java.util.Collection; +import java.util.List; + +/** + * ERP 其它出库单项 Mapper + * + * @author 芋道源码 + */ +@Mapper +public interface ErpStockOutItemMapper extends BaseMapperX { + + default List selectListByOutId(Long outId) { + return selectList(ErpStockOutItemDO::getOutId, outId); + } + + default List selectListByOutIds(Collection outIds) { + return selectList(ErpStockOutItemDO::getOutId, outIds); + } + + default int deleteByOutId(Long outId) { + return delete(ErpStockOutItemDO::getOutId, outId); + } + +} \ No newline at end of file diff --git a/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/dal/mysql/stock/ErpStockOutMapper.java b/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/dal/mysql/stock/ErpStockOutMapper.java new file mode 100644 index 000000000..f27e01310 --- /dev/null +++ b/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/dal/mysql/stock/ErpStockOutMapper.java @@ -0,0 +1,47 @@ +package cn.iocoder.yudao.module.erp.dal.mysql.stock; + +import cn.iocoder.yudao.framework.common.pojo.PageResult; +import cn.iocoder.yudao.framework.mybatis.core.mapper.BaseMapperX; +import cn.iocoder.yudao.framework.mybatis.core.query.MPJLambdaWrapperX; +import cn.iocoder.yudao.module.erp.controller.admin.stock.vo.out.ErpStockOutPageReqVO; +import cn.iocoder.yudao.module.erp.dal.dataobject.stock.ErpStockOutDO; +import cn.iocoder.yudao.module.erp.dal.dataobject.stock.ErpStockOutItemDO; +import com.baomidou.mybatisplus.core.conditions.update.LambdaUpdateWrapper; +import org.apache.ibatis.annotations.Mapper; + +/** + * ERP 其它出库单 Mapper + * + * @author 芋道源码 + */ +@Mapper +public interface ErpStockOutMapper extends BaseMapperX { + + default PageResult selectPage(ErpStockOutPageReqVO reqVO) { + MPJLambdaWrapperX query = new MPJLambdaWrapperX() + .eqIfPresent(ErpStockOutDO::getNo, reqVO.getNo()) + .eqIfPresent(ErpStockOutDO::getCustomerId, reqVO.getCustomerId()) + .betweenIfPresent(ErpStockOutDO::getOutTime, reqVO.getOutTime()) + .eqIfPresent(ErpStockOutDO::getStatus, reqVO.getStatus()) + .likeIfPresent(ErpStockOutDO::getRemark, reqVO.getRemark()) + .eqIfPresent(ErpStockOutDO::getCreator, reqVO.getCreator()) + .orderByDesc(ErpStockOutDO::getId); + if (reqVO.getWarehouseId() != null || reqVO.getProductId() != null) { + query.leftJoin(ErpStockOutItemDO.class, ErpStockOutItemDO::getOutId, ErpStockOutDO::getId) + .eq(reqVO.getWarehouseId() != null, ErpStockOutItemDO::getWarehouseId, reqVO.getWarehouseId()) + .eq(reqVO.getProductId() != null, ErpStockOutItemDO::getProductId, reqVO.getProductId()) + .groupBy(ErpStockOutDO::getId); // 避免 1 对多查询,产生相同的 1 + } + return selectJoinPage(reqVO, ErpStockOutDO.class, query); + } + + default int updateByIdAndStatus(Long id, Integer status, ErpStockOutDO updateObj) { + return update(updateObj, new LambdaUpdateWrapper() + .eq(ErpStockOutDO::getId, id).eq(ErpStockOutDO::getStatus, status)); + } + + default ErpStockOutDO selectByNo(String no) { + return selectOne(ErpStockOutDO::getNo, no); + } + +} \ No newline at end of file diff --git a/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/dal/redis/no/ErpNoRedisDAO.java b/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/dal/redis/no/ErpNoRedisDAO.java index e211864cc..04d2c25ca 100644 --- a/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/dal/redis/no/ErpNoRedisDAO.java +++ b/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/dal/redis/no/ErpNoRedisDAO.java @@ -20,9 +20,13 @@ import java.time.LocalDateTime; public class ErpNoRedisDAO { /** - * 其它入库 STOCK_IN + * 其它入库 {@link cn.iocoder.yudao.module.erp.dal.dataobject.stock.ErpStockInDO} */ public static final String STOCK_IN_NO_PREFIX = "QTRK"; + /** + * 其它出库 {@link cn.iocoder.yudao.module.erp.dal.dataobject.stock.ErpStockOutDO} + */ + public static final String STOCK_OUT_NO_PREFIX = "QCKD"; @Resource private StringRedisTemplate stringRedisTemplate; diff --git a/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/service/stock/ErpStockInServiceImpl.java b/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/service/stock/ErpStockInServiceImpl.java index 85aa6ff53..9e9280fcd 100644 --- a/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/service/stock/ErpStockInServiceImpl.java +++ b/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/service/stock/ErpStockInServiceImpl.java @@ -16,7 +16,7 @@ import cn.iocoder.yudao.module.erp.enums.ErpAuditStatus; import cn.iocoder.yudao.module.erp.enums.stock.ErpStockRecordBizTypeEnum; import cn.iocoder.yudao.module.erp.service.product.ErpProductService; import cn.iocoder.yudao.module.erp.service.purchase.ErpSupplierService; -import cn.iocoder.yudao.module.erp.service.stock.bo.ErpStockInCreateReqBO; +import cn.iocoder.yudao.module.erp.service.stock.bo.ErpStockRecordCreateReqBO; import jakarta.annotation.Resource; import org.springframework.stereotype.Service; import org.springframework.transaction.annotation.Transactional; @@ -88,7 +88,10 @@ public class ErpStockInServiceImpl implements ErpStockInService { @Transactional(rollbackFor = Exception.class) public void updateStockIn(ErpStockInSaveReqVO updateReqVO) { // 1.1 校验存在 - validateStockInExists(updateReqVO.getId()); + ErpStockInDO stockIn = validateStockInExists(updateReqVO.getId()); + if (ErpAuditStatus.APPROVE.getStatus().equals(stockIn.getStatus())) { + throw exception(STOCK_IN_UPDATE_FAIL_APPROVE, stockIn.getNo()); + } // 1.2 校验供应商 supplierService.validateSupplier(updateReqVO.getSupplierId()); // 1.3 校验入库项的有效性 @@ -127,7 +130,7 @@ public class ErpStockInServiceImpl implements ErpStockInService { : ErpStockRecordBizTypeEnum.OTHER_IN_CANCEL.getType(); stockInItems.forEach(stockInItem -> { BigDecimal count = approve ? stockInItem.getCount() : stockInItem.getCount().negate(); - stockRecordService.createStockRecord(new ErpStockInCreateReqBO( + stockRecordService.createStockRecord(new ErpStockRecordCreateReqBO( stockInItem.getProductId(), stockInItem.getWarehouseId(), count, bizType, stockInItem.getInId(), stockInItem.getId(), stockIn.getNo())); }); diff --git a/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/service/stock/ErpStockOutService.java b/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/service/stock/ErpStockOutService.java new file mode 100644 index 000000000..558fb6948 --- /dev/null +++ b/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/service/stock/ErpStockOutService.java @@ -0,0 +1,84 @@ +package cn.iocoder.yudao.module.erp.service.stock; + +import cn.iocoder.yudao.framework.common.pojo.PageResult; +import cn.iocoder.yudao.module.erp.controller.admin.stock.vo.out.ErpStockOutPageReqVO; +import cn.iocoder.yudao.module.erp.controller.admin.stock.vo.out.ErpStockOutSaveReqVO; +import cn.iocoder.yudao.module.erp.dal.dataobject.stock.ErpStockOutDO; +import cn.iocoder.yudao.module.erp.dal.dataobject.stock.ErpStockOutItemDO; +import jakarta.validation.Valid; + +import java.util.Collection; +import java.util.List; + +/** + * ERP 其它出库单 Service 接口 + * + * @author 芋道源码 + */ +public interface ErpStockOutService { + + /** + * 创建其它出库单 + * + * @param createReqVO 创建信息 + * @return 编号 + */ + Long createStockOut(@Valid ErpStockOutSaveReqVO createReqVO); + + /** + * 更新其它出库单 + * + * @param updateReqVO 更新信息 + */ + void updateStockOut(@Valid ErpStockOutSaveReqVO updateReqVO); + + /** + * 更新其它出库单的状态 + * + * @param id 编号 + * @param status 状态 + */ + void updateStockOutStatus(Long id, Integer status); + + /** + * 删除其它出库单 + * + * @param ids 编号数组 + */ + void deleteStockOut(List ids); + + /** + * 获得其它出库单 + * + * @param id 编号 + * @return 其它出库单 + */ + ErpStockOutDO getStockOut(Long id); + + /** + * 获得其它出库单分页 + * + * @param pageReqVO 分页查询 + * @return 其它出库单分页 + */ + PageResult getStockOutPage(ErpStockOutPageReqVO pageReqVO); + + // ==================== 出库项 ==================== + + /** + * 获得其它出库单项列表 + * + * @param outId 出库编号 + * @return 其它出库单项列表 + */ + List getStockOutItemListByOutId(Long outId); + + /** + * 获得其它出库单项 List + * + * @param outIds 出库编号数组 + * @return 其它出库单项 List + */ + List getStockOutItemListByOutIds(Collection outIds); + +} \ No newline at end of file diff --git a/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/service/stock/ErpStockOutServiceImpl.java b/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/service/stock/ErpStockOutServiceImpl.java new file mode 100644 index 000000000..67041209b --- /dev/null +++ b/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/service/stock/ErpStockOutServiceImpl.java @@ -0,0 +1,227 @@ +package cn.iocoder.yudao.module.erp.service.stock; + +import cn.hutool.core.collection.CollUtil; +import cn.iocoder.yudao.framework.common.pojo.PageResult; +import cn.iocoder.yudao.framework.common.util.number.MoneyUtils; +import cn.iocoder.yudao.framework.common.util.object.BeanUtils; +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.dal.dataobject.product.ErpProductDO; +import cn.iocoder.yudao.module.erp.dal.dataobject.stock.ErpStockOutDO; +import cn.iocoder.yudao.module.erp.dal.dataobject.stock.ErpStockOutItemDO; +import cn.iocoder.yudao.module.erp.dal.mysql.stock.ErpStockOutItemMapper; +import cn.iocoder.yudao.module.erp.dal.mysql.stock.ErpStockOutMapper; +import cn.iocoder.yudao.module.erp.dal.redis.no.ErpNoRedisDAO; +import cn.iocoder.yudao.module.erp.enums.ErpAuditStatus; +import cn.iocoder.yudao.module.erp.enums.stock.ErpStockRecordBizTypeEnum; +import cn.iocoder.yudao.module.erp.service.product.ErpProductService; +import cn.iocoder.yudao.module.erp.service.purchase.ErpSupplierService; +import cn.iocoder.yudao.module.erp.service.stock.bo.ErpStockRecordCreateReqBO; +import jakarta.annotation.Resource; +import org.springframework.stereotype.Service; +import org.springframework.transaction.annotation.Transactional; +import org.springframework.validation.annotation.Validated; + +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.exception.util.ServiceExceptionUtil.exception; +import static cn.iocoder.yudao.framework.common.util.collection.CollectionUtils.*; +import static cn.iocoder.yudao.module.erp.enums.ErrorCodeConstants.*; + +// TODO 芋艿:记录操作日志 + +/** + * ERP 其它出库单 Service 实现类 + * + * @author 芋道源码 + */ +@Service +@Validated +public class ErpStockOutServiceImpl implements ErpStockOutService { + + @Resource + private ErpStockOutMapper stockOutMapper; + @Resource + private ErpStockOutItemMapper stockOutItemMapper; + + @Resource + private ErpNoRedisDAO noRedisDAO; + + @Resource + private ErpProductService productService; + @Resource + private ErpWarehouseService warehouseService; + @Resource + private ErpSupplierService supplierService; + @Resource + private ErpStockRecordService stockRecordService; + + @Override + @Transactional(rollbackFor = Exception.class) + public Long createStockOut(ErpStockOutSaveReqVO createReqVO) { + // 1.1 校验出库项的有效性 + List stockOutItems = validateStockOutItems(createReqVO.getItems()); + // 1.2 校验客户 TODO +// supplierService.validateSupplier(createReqVO.getSupplierId()); + // 1.3 + String no = noRedisDAO.generate(ErpNoRedisDAO.STOCK_OUT_NO_PREFIX); + if (stockOutMapper.selectByNo(no) != null) { + throw exception(STOCK_OUT_NO_EXISTS); + } + + // 2.1 插入出库单 + ErpStockOutDO stockOut = BeanUtils.toBean(createReqVO, ErpStockOutDO.class, in -> in + .setNo(no).setStatus(ErpAuditStatus.PROCESS.getStatus()) + .setTotalCount(getSumValue(stockOutItems, ErpStockOutItemDO::getCount, BigDecimal::add)) + .setTotalPrice(getSumValue(stockOutItems, ErpStockOutItemDO::getTotalPrice, BigDecimal::add, BigDecimal.ZERO))); + stockOutMapper.insert(stockOut); + // 2.2 插入出库单项 + stockOutItems.forEach(o -> o.setOutId(stockOut.getId())); + stockOutItemMapper.insertBatch(stockOutItems); + return stockOut.getId(); + } + + @Override + @Transactional(rollbackFor = Exception.class) + public void updateStockOut(ErpStockOutSaveReqVO updateReqVO) { + // 1.1 校验存在 + ErpStockOutDO stockOut = validateStockOutExists(updateReqVO.getId()); + if (ErpAuditStatus.APPROVE.getStatus().equals(stockOut.getStatus())) { + throw exception(STOCK_OUT_UPDATE_FAIL_APPROVE, stockOut.getNo()); + } + // 1.2 校验客户 TODO +// supplierService.validateSupplier(updateReqVO.getSupplierId()); + // 1.3 校验出库项的有效性 + List stockOutItems = validateStockOutItems(updateReqVO.getItems()); + + // 2.1 更新出库单 + ErpStockOutDO updateObj = BeanUtils.toBean(updateReqVO, ErpStockOutDO.class, in -> in + .setTotalCount(getSumValue(stockOutItems, ErpStockOutItemDO::getCount, BigDecimal::add)) + .setTotalPrice(getSumValue(stockOutItems, ErpStockOutItemDO::getTotalPrice, BigDecimal::add))); + stockOutMapper.updateById(updateObj); + // 2.2 更新出库单项 + updateStockOutItemList(updateReqVO.getId(), stockOutItems); + } + + @Override + @Transactional(rollbackFor = Exception.class) + public void updateStockOutStatus(Long id, Integer status) { + boolean approve = ErpAuditStatus.APPROVE.getStatus().equals(status); + // 1.1 校验存在 + ErpStockOutDO stockOut = validateStockOutExists(id); + // 1.2 校验状态 + if (stockOut.getStatus().equals(status)) { + throw exception(approve ? STOCK_OUT_APPROVE_FAIL : STOCK_OUT_PROCESS_FAIL); + } + + // 2. 更新状态 + int updateCount = stockOutMapper.updateByIdAndStatus(id, stockOut.getStatus(), + new ErpStockOutDO().setStatus(status)); + if (updateCount == 0) { + throw exception(approve ? STOCK_OUT_APPROVE_FAIL : STOCK_OUT_PROCESS_FAIL); + } + + // 3. 变更库存 + List stockOutItems = stockOutItemMapper.selectListByOutId(id); + Integer bizType = approve ? ErpStockRecordBizTypeEnum.OTHER_OUT.getType() + : ErpStockRecordBizTypeEnum.OTHER_OUT_CANCEL.getType(); + stockOutItems.forEach(stockOutItem -> { + BigDecimal count = approve ? stockOutItem.getCount() : stockOutItem.getCount().negate(); + stockRecordService.createStockRecord(new ErpStockRecordCreateReqBO( + stockOutItem.getProductId(), stockOutItem.getWarehouseId(), count, + bizType, stockOutItem.getOutId(), stockOutItem.getId(), stockOut.getNo())); + }); + } + + private List validateStockOutItems(List list) { + // 1.1 校验产品存在 + List productList = productService.validProductList(convertSet(list, ErpStockOutSaveReqVO.Item::getProductId)); + Map productMap = convertMap(productList, ErpProductDO::getId); + // 1.2 校验仓库存在 + warehouseService.validWarehouseList(convertSet(list, ErpStockOutSaveReqVO.Item::getWarehouseId)); + // 2. 转化为 ErpStockOutItemDO 列表 + return convertList(list, o -> BeanUtils.toBean(o, ErpStockOutItemDO.class, item -> item + .setProductUnitId(productMap.get(item.getProductId()).getUnitId()) + .setTotalPrice(MoneyUtils.priceMultiply(item.getProductPrice(), item.getCount())))); + } + + private void updateStockOutItemList(Long id, List newList) { + // 第一步,对比新老数据,获得添加、修改、删除的列表 + List oldList = stockOutItemMapper.selectListByOutId(id); + List> diffList = diffList(oldList, newList, // id 不同,就认为是不同的记录 + (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))) { + stockOutItemMapper.updateBatch(diffList.get(1)); + } + if (CollUtil.isNotEmpty(diffList.get(2))) { + stockOutItemMapper.deleteBatchIds(convertList(diffList.get(2), ErpStockOutItemDO::getId)); + } + } + + @Override + @Transactional(rollbackFor = Exception.class) + public void deleteStockOut(List ids) { + // 1. 校验不处于已审批 + List stockOuts = stockOutMapper.selectBatchIds(ids); + if (CollUtil.isEmpty(stockOuts)) { + return; + } + stockOuts.forEach(stockOut -> { + if (ErpAuditStatus.APPROVE.getStatus().equals(stockOut.getStatus())) { + throw exception(STOCK_OUT_DELETE_FAIL_APPROVE, stockOut.getNo()); + } + }); + + // 2. 遍历删除,并记录操作日志 + stockOuts.forEach(stockOut -> { + // 2.1 删除出库单 + stockOutMapper.deleteById(stockOut.getId()); + // 2.2 删除出库单项 + stockOutItemMapper.deleteByOutId(stockOut.getId()); + }); + } + + private ErpStockOutDO validateStockOutExists(Long id) { + ErpStockOutDO stockOut = stockOutMapper.selectById(id); + if (stockOut == null) { + throw exception(STOCK_OUT_NOT_EXISTS); + } + return stockOut; + } + + @Override + public ErpStockOutDO getStockOut(Long id) { + return stockOutMapper.selectById(id); + } + + @Override + public PageResult getStockOutPage(ErpStockOutPageReqVO pageReqVO) { + return stockOutMapper.selectPage(pageReqVO); + } + + // ==================== 出库项 ==================== + + @Override + public List getStockOutItemListByOutId(Long inId) { + return stockOutItemMapper.selectListByOutId(inId); + } + + @Override + public List getStockOutItemListByOutIds(Collection inIds) { + if (CollUtil.isEmpty(inIds)) { + return Collections.emptyList(); + } + return stockOutItemMapper.selectListByOutIds(inIds); + } + +} \ No newline at end of file diff --git a/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/service/stock/ErpStockRecordService.java b/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/service/stock/ErpStockRecordService.java index 0e20a55f2..506b992a4 100644 --- a/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/service/stock/ErpStockRecordService.java +++ b/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/service/stock/ErpStockRecordService.java @@ -3,7 +3,7 @@ package cn.iocoder.yudao.module.erp.service.stock; import cn.iocoder.yudao.framework.common.pojo.PageResult; import cn.iocoder.yudao.module.erp.controller.admin.stock.vo.record.ErpStockRecordPageReqVO; import cn.iocoder.yudao.module.erp.dal.dataobject.stock.ErpStockRecordDO; -import cn.iocoder.yudao.module.erp.service.stock.bo.ErpStockInCreateReqBO; +import cn.iocoder.yudao.module.erp.service.stock.bo.ErpStockRecordCreateReqBO; import jakarta.validation.Valid; /** @@ -34,6 +34,6 @@ public interface ErpStockRecordService { * * @param createReqBO 创建库存明细 BO */ - void createStockRecord(@Valid ErpStockInCreateReqBO createReqBO); + void createStockRecord(@Valid ErpStockRecordCreateReqBO createReqBO); } \ No newline at end of file diff --git a/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/service/stock/ErpStockRecordServiceImpl.java b/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/service/stock/ErpStockRecordServiceImpl.java index 708a39f18..d84951c28 100644 --- a/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/service/stock/ErpStockRecordServiceImpl.java +++ b/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/service/stock/ErpStockRecordServiceImpl.java @@ -5,7 +5,7 @@ import cn.iocoder.yudao.framework.common.util.object.BeanUtils; import cn.iocoder.yudao.module.erp.controller.admin.stock.vo.record.ErpStockRecordPageReqVO; import cn.iocoder.yudao.module.erp.dal.dataobject.stock.ErpStockRecordDO; import cn.iocoder.yudao.module.erp.dal.mysql.stock.ErpStockRecordMapper; -import cn.iocoder.yudao.module.erp.service.stock.bo.ErpStockInCreateReqBO; +import cn.iocoder.yudao.module.erp.service.stock.bo.ErpStockRecordCreateReqBO; import jakarta.annotation.Resource; import org.springframework.stereotype.Service; import org.springframework.transaction.annotation.Transactional; @@ -40,7 +40,7 @@ public class ErpStockRecordServiceImpl implements ErpStockRecordService { @Override @Transactional(rollbackFor = Exception.class) - public void createStockRecord(ErpStockInCreateReqBO createReqBO) { + public void createStockRecord(ErpStockRecordCreateReqBO createReqBO) { // 1. 更新库存 BigDecimal totalCount = stockService.updateStockCountIncrement( createReqBO.getProductId(), createReqBO.getWarehouseId(), createReqBO.getCount()); diff --git a/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/service/stock/bo/ErpStockInCreateReqBO.java b/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/service/stock/bo/ErpStockRecordCreateReqBO.java similarity index 96% rename from yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/service/stock/bo/ErpStockInCreateReqBO.java rename to yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/service/stock/bo/ErpStockRecordCreateReqBO.java index 3211a2e76..7006f10b5 100644 --- a/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/service/stock/bo/ErpStockInCreateReqBO.java +++ b/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/service/stock/bo/ErpStockRecordCreateReqBO.java @@ -15,7 +15,7 @@ import java.math.BigDecimal; @Data @NoArgsConstructor @AllArgsConstructor -public class ErpStockInCreateReqBO { +public class ErpStockRecordCreateReqBO { /** * 产品编号 From 7495bb05d19819c5e026750c118b65ee6d336021 Mon Sep 17 00:00:00 2001 From: YunaiV Date: Wed, 7 Feb 2024 15:41:00 +0800 Subject: [PATCH 085/119] =?UTF-8?q?=E2=9C=A8=20ERP=EF=BC=9A=E5=A2=9E?= =?UTF-8?q?=E5=8A=A0=20ERP=20=E5=AE=A2=E6=88=B7=E7=9A=84=E5=AE=9E=E7=8E=B0?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../module/erp/enums/ErrorCodeConstants.java | 8 +- .../admin/purchase/ErpSupplierController.java | 2 +- .../admin/sale/ErpCustomerController.java | 102 ++++++++++++++ .../vo/customer/ErpCustomerPageReqVO.java | 28 ++++ .../sale/vo/customer/ErpCustomerRespVO.java | 84 +++++++++++ .../vo/customer/ErpCustomerSaveReqVO.java | 61 ++++++++ .../admin/stock/ErpStockInController.java | 4 +- .../admin/stock/ErpStockOutController.java | 16 ++- .../{supplier => purchase}/ErpSupplierDO.java | 2 +- .../dal/dataobject/sale/ErpCustomerDO.java | 90 ++++++++++++ .../dal/dataobject/stock/ErpStockInDO.java | 2 +- .../dal/mysql/purchase/ErpSupplierMapper.java | 2 +- .../erp/dal/mysql/sale/ErpCustomerMapper.java | 32 +++++ .../service/purchase/ErpSupplierService.java | 2 +- .../purchase/ErpSupplierServiceImpl.java | 2 +- .../erp/service/sale/ErpCustomerService.java | 94 +++++++++++++ .../service/sale/ErpCustomerServiceImpl.java | 97 +++++++++++++ .../service/stock/ErpStockOutServiceImpl.java | 12 +- .../mapper/sale/ErpCustomerMapper.xml | 12 ++ .../sale/ErpCustomerServiceImplTest.java | 131 ++++++++++++++++++ 20 files changed, 760 insertions(+), 23 deletions(-) create mode 100644 yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/controller/admin/sale/ErpCustomerController.java create mode 100644 yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/controller/admin/sale/vo/customer/ErpCustomerPageReqVO.java create mode 100644 yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/controller/admin/sale/vo/customer/ErpCustomerRespVO.java create mode 100644 yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/controller/admin/sale/vo/customer/ErpCustomerSaveReqVO.java rename yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/dal/dataobject/{supplier => purchase}/ErpSupplierDO.java (96%) create mode 100644 yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/dal/dataobject/sale/ErpCustomerDO.java create mode 100644 yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/dal/mysql/sale/ErpCustomerMapper.java create mode 100644 yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/service/sale/ErpCustomerService.java create mode 100644 yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/service/sale/ErpCustomerServiceImpl.java create mode 100644 yudao-module-erp/yudao-module-erp-biz/src/main/resources/mapper/sale/ErpCustomerMapper.xml create mode 100644 yudao-module-erp/yudao-module-erp-biz/src/test/java/cn/iocoder/yudao/module/erp/service/sale/ErpCustomerServiceImplTest.java diff --git a/yudao-module-erp/yudao-module-erp-api/src/main/java/cn/iocoder/yudao/module/erp/enums/ErrorCodeConstants.java b/yudao-module-erp/yudao-module-erp-api/src/main/java/cn/iocoder/yudao/module/erp/enums/ErrorCodeConstants.java index 7bd87bdb9..1926b34ac 100644 --- a/yudao-module-erp/yudao-module-erp-api/src/main/java/cn/iocoder/yudao/module/erp/enums/ErrorCodeConstants.java +++ b/yudao-module-erp/yudao-module-erp-api/src/main/java/cn/iocoder/yudao/module/erp/enums/ErrorCodeConstants.java @@ -13,8 +13,12 @@ public interface ErrorCodeConstants { ErrorCode SUPPLIER_NOT_EXISTS = new ErrorCode(1_030_100_000, "供应商不存在"); ErrorCode SUPPLIER_NOT_ENABLE = new ErrorCode(1_030_100_000, "供应商({})未启用"); - // ========== ERP 销售订单(1-030-200-000) ========== - ErrorCode SALE_ORDER_NOT_EXISTS = new ErrorCode(1_020_200_000, "销售订单不存在"); + // ========== ERP 客户(1-030-200-000)========== + ErrorCode CUSTOMER_NOT_EXISTS = new ErrorCode(1_020_200_000, "客户不存在"); + ErrorCode CUSTOMER_NOT_ENABLE = new ErrorCode(1_020_200_001, "客户({})未启用"); + + // ========== ERP 销售订单(1-030-201-000) ========== + ErrorCode SALE_ORDER_NOT_EXISTS = new ErrorCode(1_020_201_000, "销售订单不存在"); // ========== ERP 仓库 1-030-400-000 ========== ErrorCode WAREHOUSE_NOT_EXISTS = new ErrorCode(1_030_400_000, "仓库不存在"); diff --git a/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/controller/admin/purchase/ErpSupplierController.java b/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/controller/admin/purchase/ErpSupplierController.java index 60893ea57..88253286d 100644 --- a/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/controller/admin/purchase/ErpSupplierController.java +++ b/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/controller/admin/purchase/ErpSupplierController.java @@ -10,7 +10,7 @@ import cn.iocoder.yudao.framework.operatelog.core.annotations.OperateLog; import cn.iocoder.yudao.module.erp.controller.admin.purchase.vo.supplier.ErpSupplierPageReqVO; import cn.iocoder.yudao.module.erp.controller.admin.purchase.vo.supplier.ErpSupplierRespVO; import cn.iocoder.yudao.module.erp.controller.admin.purchase.vo.supplier.ErpSupplierSaveReqVO; -import cn.iocoder.yudao.module.erp.dal.dataobject.supplier.ErpSupplierDO; +import cn.iocoder.yudao.module.erp.dal.dataobject.purchase.ErpSupplierDO; import cn.iocoder.yudao.module.erp.service.purchase.ErpSupplierService; import io.swagger.v3.oas.annotations.Operation; import io.swagger.v3.oas.annotations.Parameter; diff --git a/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/controller/admin/sale/ErpCustomerController.java b/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/controller/admin/sale/ErpCustomerController.java new file mode 100644 index 000000000..2c2886460 --- /dev/null +++ b/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/controller/admin/sale/ErpCustomerController.java @@ -0,0 +1,102 @@ +package cn.iocoder.yudao.module.erp.controller.admin.sale; + +import cn.iocoder.yudao.framework.common.enums.CommonStatusEnum; +import cn.iocoder.yudao.framework.common.pojo.CommonResult; +import cn.iocoder.yudao.framework.common.pojo.PageParam; +import cn.iocoder.yudao.framework.common.pojo.PageResult; +import cn.iocoder.yudao.framework.common.util.object.BeanUtils; +import cn.iocoder.yudao.framework.excel.core.util.ExcelUtils; +import cn.iocoder.yudao.framework.operatelog.core.annotations.OperateLog; +import cn.iocoder.yudao.module.erp.controller.admin.sale.vo.customer.ErpCustomerPageReqVO; +import cn.iocoder.yudao.module.erp.controller.admin.sale.vo.customer.ErpCustomerRespVO; +import cn.iocoder.yudao.module.erp.controller.admin.sale.vo.customer.ErpCustomerSaveReqVO; +import cn.iocoder.yudao.module.erp.dal.dataobject.sale.ErpCustomerDO; +import cn.iocoder.yudao.module.erp.service.sale.ErpCustomerService; +import io.swagger.v3.oas.annotations.Operation; +import io.swagger.v3.oas.annotations.Parameter; +import io.swagger.v3.oas.annotations.tags.Tag; +import jakarta.annotation.Resource; +import jakarta.servlet.http.HttpServletResponse; +import jakarta.validation.Valid; +import org.springframework.security.access.prepost.PreAuthorize; +import org.springframework.validation.annotation.Validated; +import org.springframework.web.bind.annotation.*; + +import java.io.IOException; +import java.util.List; + +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.operatelog.core.enums.OperateTypeEnum.EXPORT; + +@Tag(name = "管理后台 - ERP 客户") +@RestController +@RequestMapping("/erp/customer") +@Validated +public class ErpCustomerController { + + @Resource + private ErpCustomerService customerService; + + @PostMapping("/create") + @Operation(summary = "创建客户") + @PreAuthorize("@ss.hasPermission('erp:customer:create')") + public CommonResult createCustomer(@Valid @RequestBody ErpCustomerSaveReqVO createReqVO) { + return success(customerService.createCustomer(createReqVO)); + } + + @PutMapping("/update") + @Operation(summary = "更新客户") + @PreAuthorize("@ss.hasPermission('erp:customer:update')") + public CommonResult updateCustomer(@Valid @RequestBody ErpCustomerSaveReqVO updateReqVO) { + customerService.updateCustomer(updateReqVO); + return success(true); + } + + @DeleteMapping("/delete") + @Operation(summary = "删除客户") + @Parameter(name = "id", description = "编号", required = true) + @PreAuthorize("@ss.hasPermission('erp:customer:delete')") + public CommonResult deleteCustomer(@RequestParam("id") Long id) { + customerService.deleteCustomer(id); + return success(true); + } + + @GetMapping("/get") + @Operation(summary = "获得客户") + @Parameter(name = "id", description = "编号", required = true, example = "1024") + @PreAuthorize("@ss.hasPermission('erp:customer:query')") + public CommonResult getCustomer(@RequestParam("id") Long id) { + ErpCustomerDO customer = customerService.getCustomer(id); + return success(BeanUtils.toBean(customer, ErpCustomerRespVO.class)); + } + + @GetMapping("/page") + @Operation(summary = "获得客户分页") + @PreAuthorize("@ss.hasPermission('erp:customer:query')") + public CommonResult> getCustomerPage(@Valid ErpCustomerPageReqVO pageReqVO) { + PageResult pageResult = customerService.getCustomerPage(pageReqVO); + return success(BeanUtils.toBean(pageResult, ErpCustomerRespVO.class)); + } + + @GetMapping("/simple-list") + @Operation(summary = "获得客户精简列表", description = "只包含被开启的客户,主要用于前端的下拉选项") + public CommonResult> getCustomerSimpleList() { + List list = customerService.getCustomerListByStatus(CommonStatusEnum.ENABLE.getStatus()); + return success(convertList(list, customer -> new ErpCustomerRespVO().setId(customer.getId()).setName(customer.getName()))); + } + + @GetMapping("/export-excel") + @Operation(summary = "导出客户 Excel") + @PreAuthorize("@ss.hasPermission('erp:customer:export')") + @OperateLog(type = EXPORT) + public void exportCustomerExcel(@Valid ErpCustomerPageReqVO pageReqVO, + HttpServletResponse response) throws IOException { + pageReqVO.setPageSize(PageParam.PAGE_SIZE_NONE); + List list = customerService.getCustomerPage(pageReqVO).getList(); + // 导出 Excel + ExcelUtils.write(response, "客户.xls", "数据", ErpCustomerRespVO.class, + BeanUtils.toBean(list, ErpCustomerRespVO.class)); + } + +} \ No newline at end of file diff --git a/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/controller/admin/sale/vo/customer/ErpCustomerPageReqVO.java b/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/controller/admin/sale/vo/customer/ErpCustomerPageReqVO.java new file mode 100644 index 000000000..e790cb958 --- /dev/null +++ b/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/controller/admin/sale/vo/customer/ErpCustomerPageReqVO.java @@ -0,0 +1,28 @@ +package cn.iocoder.yudao.module.erp.controller.admin.sale.vo.customer; + +import lombok.*; +import java.util.*; +import io.swagger.v3.oas.annotations.media.Schema; +import cn.iocoder.yudao.framework.common.pojo.PageParam; +import java.math.BigDecimal; +import org.springframework.format.annotation.DateTimeFormat; +import java.time.LocalDateTime; + +import static cn.iocoder.yudao.framework.common.util.date.DateUtils.FORMAT_YEAR_MONTH_DAY_HOUR_MINUTE_SECOND; + +@Schema(description = "管理后台 - ERP 客户分页 Request VO") +@Data +@EqualsAndHashCode(callSuper = true) +@ToString(callSuper = true) +public class ErpCustomerPageReqVO extends PageParam { + + @Schema(description = "客户名称", example = "张三") + private String name; + + @Schema(description = "手机号码", example = "15601691300") + private String mobile; + + @Schema(description = "联系电话", example = "15601691300") + private String telephone; + +} \ No newline at end of file diff --git a/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/controller/admin/sale/vo/customer/ErpCustomerRespVO.java b/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/controller/admin/sale/vo/customer/ErpCustomerRespVO.java new file mode 100644 index 000000000..f1a58a03d --- /dev/null +++ b/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/controller/admin/sale/vo/customer/ErpCustomerRespVO.java @@ -0,0 +1,84 @@ +package cn.iocoder.yudao.module.erp.controller.admin.sale.vo.customer; + +import io.swagger.v3.oas.annotations.media.Schema; +import lombok.*; +import java.util.*; +import java.util.*; +import java.math.BigDecimal; +import org.springframework.format.annotation.DateTimeFormat; +import java.time.LocalDateTime; +import com.alibaba.excel.annotation.*; +import cn.iocoder.yudao.framework.excel.core.annotations.DictFormat; +import cn.iocoder.yudao.framework.excel.core.convert.DictConvert; + +@Schema(description = "管理后台 - ERP 客户 Response VO") +@Data +@ExcelIgnoreUnannotated +public class ErpCustomerRespVO { + + @Schema(description = "客户编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "27520") + @ExcelProperty("客户编号") + private Long id; + + @Schema(description = "客户名称", requiredMode = Schema.RequiredMode.REQUIRED, example = "张三") + @ExcelProperty("客户名称") + private String name; + + @Schema(description = "联系人", example = "老王") + @ExcelProperty("联系人") + private String contact; + + @Schema(description = "手机号码", example = "15601691300") + @ExcelProperty("手机号码") + private String mobile; + + @Schema(description = "联系电话", example = "15601691300") + @ExcelProperty("联系电话") + private String telephone; + + @Schema(description = "电子邮箱", example = "7685323@qq.com") + @ExcelProperty("电子邮箱") + private String email; + + @Schema(description = "传真", example = "20 7123 4567") + @ExcelProperty("传真") + private String fax; + + @Schema(description = "备注", example = "你猜") + @ExcelProperty("备注") + private String remark; + + @Schema(description = "开启状态", requiredMode = Schema.RequiredMode.REQUIRED, example = "1") + @ExcelProperty(value = "开启状态", converter = DictConvert.class) + @DictFormat("common_status") // TODO 代码优化:建议设置到对应的 DictTypeConstants 枚举类中 + private Integer status; + + @Schema(description = "排序", requiredMode = Schema.RequiredMode.REQUIRED, example = "10") + @ExcelProperty("排序") + private Integer sort; + + @Schema(description = "纳税人识别号", example = "91130803MA098BY05W") + @ExcelProperty("纳税人识别号") + private String taxNo; + + @Schema(description = "税率", example = "10") + @ExcelProperty("税率") + private BigDecimal taxPercent; + + @Schema(description = "开户行", example = "芋艿") + @ExcelProperty("开户行") + private String bankName; + + @Schema(description = "开户账号", example = "622908212277228617") + @ExcelProperty("开户账号") + private String bankAccount; + + @Schema(description = "开户地址", example = "兴业银行浦东支行") + @ExcelProperty("开户地址") + private String bankAddress; + + @Schema(description = "创建时间", requiredMode = Schema.RequiredMode.REQUIRED) + @ExcelProperty("创建时间") + private LocalDateTime createTime; + +} \ No newline at end of file diff --git a/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/controller/admin/sale/vo/customer/ErpCustomerSaveReqVO.java b/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/controller/admin/sale/vo/customer/ErpCustomerSaveReqVO.java new file mode 100644 index 000000000..aef0b2df1 --- /dev/null +++ b/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/controller/admin/sale/vo/customer/ErpCustomerSaveReqVO.java @@ -0,0 +1,61 @@ +package cn.iocoder.yudao.module.erp.controller.admin.sale.vo.customer; + +import io.swagger.v3.oas.annotations.media.Schema; +import lombok.*; +import java.util.*; +import jakarta.validation.constraints.*; +import java.math.BigDecimal; + +@Schema(description = "管理后台 - ERP 客户新增/修改 Request VO") +@Data +public class ErpCustomerSaveReqVO { + + @Schema(description = "客户编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "27520") + private Long id; + + @Schema(description = "客户名称", requiredMode = Schema.RequiredMode.REQUIRED, example = "张三") + @NotEmpty(message = "客户名称不能为空") + private String name; + + @Schema(description = "联系人", example = "老王") + private String contact; + + @Schema(description = "手机号码", example = "15601691300") + private String mobile; + + @Schema(description = "联系电话", example = "15601691300") + private String telephone; + + @Schema(description = "电子邮箱", example = "7685323@qq.com") + private String email; + + @Schema(description = "传真", example = "20 7123 4567") + private String fax; + + @Schema(description = "备注", example = "你猜") + private String remark; + + @Schema(description = "开启状态", requiredMode = Schema.RequiredMode.REQUIRED, example = "1") + @NotNull(message = "开启状态不能为空") + private Integer status; + + @Schema(description = "排序", requiredMode = Schema.RequiredMode.REQUIRED, example = "10") + @NotNull(message = "排序不能为空") + private Integer sort; + + @Schema(description = "纳税人识别号", example = "91130803MA098BY05W") + private String taxNo; + + @Schema(description = "税率", example = "10") + private BigDecimal taxPercent; + + @Schema(description = "开户行", example = "芋艿") + private String bankName; + + @Schema(description = "开户账号", example = "622908212277228617") + private String bankAccount; + + @Schema(description = "开户地址", example = "兴业银行浦东支行") + private String bankAddress; + +} \ No newline at end of file diff --git a/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/controller/admin/stock/ErpStockInController.java b/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/controller/admin/stock/ErpStockInController.java index 530d04350..75120fce5 100644 --- a/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/controller/admin/stock/ErpStockInController.java +++ b/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/controller/admin/stock/ErpStockInController.java @@ -15,7 +15,7 @@ import cn.iocoder.yudao.module.erp.controller.admin.stock.vo.in.ErpStockInSaveRe import cn.iocoder.yudao.module.erp.dal.dataobject.stock.ErpStockDO; import cn.iocoder.yudao.module.erp.dal.dataobject.stock.ErpStockInDO; import cn.iocoder.yudao.module.erp.dal.dataobject.stock.ErpStockInItemDO; -import cn.iocoder.yudao.module.erp.dal.dataobject.supplier.ErpSupplierDO; +import cn.iocoder.yudao.module.erp.dal.dataobject.purchase.ErpSupplierDO; import cn.iocoder.yudao.module.erp.service.product.ErpProductService; import cn.iocoder.yudao.module.erp.service.purchase.ErpSupplierService; import cn.iocoder.yudao.module.erp.service.stock.ErpStockInService; @@ -77,7 +77,7 @@ public class ErpStockInController { @PutMapping("/update-status") @Operation(summary = "更新其它入库单的状态") - @PreAuthorize("@ss.hasPermission('erp:stock-in:update')") + @PreAuthorize("@ss.hasPermission('erp:stock-in:update-status')") public CommonResult updateStockInStatus(@RequestParam("id") Long id, @RequestParam("status") Integer status) { stockInService.updateStockInStatus(id, status); diff --git a/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/controller/admin/stock/ErpStockOutController.java b/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/controller/admin/stock/ErpStockOutController.java index 306d51277..504a06e98 100644 --- a/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/controller/admin/stock/ErpStockOutController.java +++ b/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/controller/admin/stock/ErpStockOutController.java @@ -12,10 +12,12 @@ import cn.iocoder.yudao.module.erp.controller.admin.product.vo.product.ErpProduc import cn.iocoder.yudao.module.erp.controller.admin.stock.vo.out.ErpStockOutPageReqVO; import cn.iocoder.yudao.module.erp.controller.admin.stock.vo.out.ErpStockOutRespVO; import cn.iocoder.yudao.module.erp.controller.admin.stock.vo.out.ErpStockOutSaveReqVO; +import cn.iocoder.yudao.module.erp.dal.dataobject.sale.ErpCustomerDO; import cn.iocoder.yudao.module.erp.dal.dataobject.stock.ErpStockDO; import cn.iocoder.yudao.module.erp.dal.dataobject.stock.ErpStockOutDO; import cn.iocoder.yudao.module.erp.dal.dataobject.stock.ErpStockOutItemDO; import cn.iocoder.yudao.module.erp.service.product.ErpProductService; +import cn.iocoder.yudao.module.erp.service.sale.ErpCustomerService; import cn.iocoder.yudao.module.erp.service.stock.ErpStockOutService; import cn.iocoder.yudao.module.erp.service.stock.ErpStockService; import cn.iocoder.yudao.module.system.api.user.AdminUserApi; @@ -52,8 +54,8 @@ public class ErpStockOutController { private ErpStockService stockService; @Resource private ErpProductService productService; -// @Resource -// private ErpSupplierService supplierService; + @Resource + private ErpCustomerService customerService; @Resource private AdminUserApi adminUserApi; @@ -75,7 +77,7 @@ public class ErpStockOutController { @PutMapping("/update-status") @Operation(summary = "更新其它出库单的状态") - @PreAuthorize("@ss.hasPermission('erp:stock-out:update')") + @PreAuthorize("@ss.hasPermission('erp:stock-out:update-status')") public CommonResult updateStockOutStatus(@RequestParam("id") Long id, @RequestParam("status") Integer status) { stockOutService.updateStockOutStatus(id, status); @@ -143,9 +145,9 @@ public class ErpStockOutController { // 1.2 商品信息 Map productMap = productService.getProductVOMap( convertSet(stockOutItemList, ErpStockOutItemDO::getProductId)); - // 1.3 客户信息 TODO -// Map supplierMap = supplierService.getSupplierMap( -// convertSet(pageResult.getList(), ErpStockOutDO::getSupplierId)); + // 1.3 客户信息 + Map customerMap = customerService.getCustomerMap( + convertSet(pageResult.getList(), ErpStockOutDO::getCustomerId)); // 1.4 管理员信息 Map userMap = adminUserApi.getUserMap( convertSet(pageResult.getList(), erpStockRecordDO -> Long.parseLong(erpStockRecordDO.getCreator()))); @@ -155,7 +157,7 @@ public class ErpStockOutController { item -> MapUtils.findAndThen(productMap, item.getProductId(), product -> item.setProductName(product.getName()) .setProductBarCode(product.getBarCode()).setProductUnitName(product.getUnitName())))); stockOut.setProductNames(CollUtil.join(stockOut.getItems(), ",", ErpStockOutRespVO.Item::getProductName)); -// MapUtils.findAndThen(supplierMap, stockOut.getSupplierId(), supplier -> stockOut.setSupplierName(supplier.getName())); + MapUtils.findAndThen(customerMap, stockOut.getCustomerId(), supplier -> stockOut.setCustomerName(supplier.getName())); MapUtils.findAndThen(userMap, Long.parseLong(stockOut.getCreator()), user -> stockOut.setCreatorName(user.getNickname())); }); } diff --git a/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/dal/dataobject/supplier/ErpSupplierDO.java b/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/dal/dataobject/purchase/ErpSupplierDO.java similarity index 96% rename from yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/dal/dataobject/supplier/ErpSupplierDO.java rename to yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/dal/dataobject/purchase/ErpSupplierDO.java index 108922a22..6e94c6669 100644 --- a/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/dal/dataobject/supplier/ErpSupplierDO.java +++ b/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/dal/dataobject/purchase/ErpSupplierDO.java @@ -1,4 +1,4 @@ -package cn.iocoder.yudao.module.erp.dal.dataobject.supplier; +package cn.iocoder.yudao.module.erp.dal.dataobject.purchase; import cn.iocoder.yudao.framework.mybatis.core.dataobject.BaseDO; import com.baomidou.mybatisplus.annotation.KeySequence; diff --git a/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/dal/dataobject/sale/ErpCustomerDO.java b/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/dal/dataobject/sale/ErpCustomerDO.java new file mode 100644 index 000000000..7bffcc17c --- /dev/null +++ b/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/dal/dataobject/sale/ErpCustomerDO.java @@ -0,0 +1,90 @@ +package cn.iocoder.yudao.module.erp.dal.dataobject.sale; + +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.*; + +import java.math.BigDecimal; + +/** + * ERP 客户 DO + * + * @author 芋道源码 + */ +@TableName("erp_customer") +@KeySequence("erp_customer_seq") // 用于 Oracle、PostgreSQL、Kingbase、DB2、H2 数据库的主键自增。如果是 MySQL 等数据库,可不写。 +@Data +@EqualsAndHashCode(callSuper = true) +@ToString(callSuper = true) +@Builder +@NoArgsConstructor +@AllArgsConstructor +public class ErpCustomerDO extends BaseDO { + + /** + * 客户编号 + */ + @TableId + private Long id; + /** + * 客户名称 + */ + private String name; + /** + * 联系人 + */ + private String contact; + /** + * 手机号码 + */ + private String mobile; + /** + * 联系电话 + */ + private String telephone; + /** + * 电子邮箱 + */ + private String email; + /** + * 传真 + */ + private String fax; + /** + * 备注 + */ + private String remark; + /** + * 开启状态 + * + * 枚举 {@link cn.iocoder.yudao.framework.common.enums.CommonStatusEnum} + */ + private Integer status; + /** + * 排序 + */ + private Integer sort; + /** + * 纳税人识别号 + */ + private String taxNo; + /** + * 税率 + */ + private BigDecimal taxPercent; + /** + * 开户行 + */ + private String bankName; + /** + * 开户账号 + */ + private String bankAccount; + /** + * 开户地址 + */ + private String bankAddress; + +} \ No newline at end of file diff --git a/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/dal/dataobject/stock/ErpStockInDO.java b/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/dal/dataobject/stock/ErpStockInDO.java index 5115b9daf..ee2512ab6 100644 --- a/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/dal/dataobject/stock/ErpStockInDO.java +++ b/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/dal/dataobject/stock/ErpStockInDO.java @@ -1,7 +1,7 @@ package cn.iocoder.yudao.module.erp.dal.dataobject.stock; import cn.iocoder.yudao.framework.mybatis.core.dataobject.BaseDO; -import cn.iocoder.yudao.module.erp.dal.dataobject.supplier.ErpSupplierDO; +import cn.iocoder.yudao.module.erp.dal.dataobject.purchase.ErpSupplierDO; import com.baomidou.mybatisplus.annotation.KeySequence; import com.baomidou.mybatisplus.annotation.TableId; import com.baomidou.mybatisplus.annotation.TableName; diff --git a/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/dal/mysql/purchase/ErpSupplierMapper.java b/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/dal/mysql/purchase/ErpSupplierMapper.java index 93f3d6994..c74f1e6f8 100644 --- a/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/dal/mysql/purchase/ErpSupplierMapper.java +++ b/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/dal/mysql/purchase/ErpSupplierMapper.java @@ -4,7 +4,7 @@ import cn.iocoder.yudao.framework.common.pojo.PageResult; import cn.iocoder.yudao.framework.mybatis.core.query.LambdaQueryWrapperX; import cn.iocoder.yudao.framework.mybatis.core.mapper.BaseMapperX; import cn.iocoder.yudao.module.erp.controller.admin.purchase.vo.supplier.ErpSupplierPageReqVO; -import cn.iocoder.yudao.module.erp.dal.dataobject.supplier.ErpSupplierDO; +import cn.iocoder.yudao.module.erp.dal.dataobject.purchase.ErpSupplierDO; import org.apache.ibatis.annotations.Mapper; import java.util.List; diff --git a/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/dal/mysql/sale/ErpCustomerMapper.java b/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/dal/mysql/sale/ErpCustomerMapper.java new file mode 100644 index 000000000..4970f9ad5 --- /dev/null +++ b/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/dal/mysql/sale/ErpCustomerMapper.java @@ -0,0 +1,32 @@ +package cn.iocoder.yudao.module.erp.dal.mysql.sale; + +import cn.iocoder.yudao.framework.common.pojo.PageResult; +import cn.iocoder.yudao.framework.mybatis.core.mapper.BaseMapperX; +import cn.iocoder.yudao.framework.mybatis.core.query.LambdaQueryWrapperX; +import cn.iocoder.yudao.module.erp.controller.admin.sale.vo.customer.ErpCustomerPageReqVO; +import cn.iocoder.yudao.module.erp.dal.dataobject.sale.ErpCustomerDO; +import org.apache.ibatis.annotations.Mapper; + +import java.util.List; + +/** + * ERP 客户 Mapper + * + * @author 芋道源码 + */ +@Mapper +public interface ErpCustomerMapper extends BaseMapperX { + + default PageResult selectPage(ErpCustomerPageReqVO reqVO) { + return selectPage(reqVO, new LambdaQueryWrapperX() + .likeIfPresent(ErpCustomerDO::getName, reqVO.getName()) + .eqIfPresent(ErpCustomerDO::getMobile, reqVO.getMobile()) + .eqIfPresent(ErpCustomerDO::getTelephone, reqVO.getTelephone()) + .orderByDesc(ErpCustomerDO::getId)); + } + + default List selectListByStatus(Integer status) { + return selectList(ErpCustomerDO::getStatus, status); + } + +} \ No newline at end of file diff --git a/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/service/purchase/ErpSupplierService.java b/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/service/purchase/ErpSupplierService.java index a2f6547c2..495474d13 100644 --- a/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/service/purchase/ErpSupplierService.java +++ b/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/service/purchase/ErpSupplierService.java @@ -3,7 +3,7 @@ package cn.iocoder.yudao.module.erp.service.purchase; import cn.iocoder.yudao.framework.common.pojo.PageResult; import cn.iocoder.yudao.module.erp.controller.admin.purchase.vo.supplier.ErpSupplierPageReqVO; import cn.iocoder.yudao.module.erp.controller.admin.purchase.vo.supplier.ErpSupplierSaveReqVO; -import cn.iocoder.yudao.module.erp.dal.dataobject.supplier.ErpSupplierDO; +import cn.iocoder.yudao.module.erp.dal.dataobject.purchase.ErpSupplierDO; import jakarta.validation.Valid; import java.util.Collection; diff --git a/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/service/purchase/ErpSupplierServiceImpl.java b/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/service/purchase/ErpSupplierServiceImpl.java index 09c789c57..c862a84da 100644 --- a/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/service/purchase/ErpSupplierServiceImpl.java +++ b/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/service/purchase/ErpSupplierServiceImpl.java @@ -5,7 +5,7 @@ import cn.iocoder.yudao.framework.common.pojo.PageResult; import cn.iocoder.yudao.framework.common.util.object.BeanUtils; import cn.iocoder.yudao.module.erp.controller.admin.purchase.vo.supplier.ErpSupplierPageReqVO; import cn.iocoder.yudao.module.erp.controller.admin.purchase.vo.supplier.ErpSupplierSaveReqVO; -import cn.iocoder.yudao.module.erp.dal.dataobject.supplier.ErpSupplierDO; +import cn.iocoder.yudao.module.erp.dal.dataobject.purchase.ErpSupplierDO; import cn.iocoder.yudao.module.erp.dal.mysql.purchase.ErpSupplierMapper; import jakarta.annotation.Resource; import org.springframework.stereotype.Service; diff --git a/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/service/sale/ErpCustomerService.java b/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/service/sale/ErpCustomerService.java new file mode 100644 index 000000000..d047300e8 --- /dev/null +++ b/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/service/sale/ErpCustomerService.java @@ -0,0 +1,94 @@ +package cn.iocoder.yudao.module.erp.service.sale; + +import cn.iocoder.yudao.framework.common.pojo.PageResult; +import cn.iocoder.yudao.module.erp.controller.admin.sale.vo.customer.ErpCustomerPageReqVO; +import cn.iocoder.yudao.module.erp.controller.admin.sale.vo.customer.ErpCustomerSaveReqVO; +import cn.iocoder.yudao.module.erp.dal.dataobject.sale.ErpCustomerDO; +import jakarta.validation.Valid; + +import java.util.Collection; +import java.util.List; +import java.util.Map; + +import static cn.iocoder.yudao.framework.common.util.collection.CollectionUtils.convertMap; + +/** + * ERP 客户 Service 接口 + * + * @author 芋道源码 + */ +public interface ErpCustomerService { + + /** + * 创建客户 + * + * @param createReqVO 创建信息 + * @return 编号 + */ + Long createCustomer(@Valid ErpCustomerSaveReqVO createReqVO); + + /** + * 更新客户 + * + * @param updateReqVO 更新信息 + */ + void updateCustomer(@Valid ErpCustomerSaveReqVO updateReqVO); + + /** + * 删除客户 + * + * @param id 编号 + */ + void deleteCustomer(Long id); + + /** + * 获得客户 + * + * @param id 编号 + * @return 客户 + */ + ErpCustomerDO getCustomer(Long id); + + /** + * 校验客户 + * + * @param id 编号 + * @return 客户 + */ + ErpCustomerDO validateCustomer(Long id); + + /** + * 获得客户列表 + * + * @param ids 编号列表 + * @return 客户列表 + */ + List getCustomerList(Collection ids); + + /** + * 获得客户 Map + * + * @param ids 编号列表 + * @return 客户 Map + */ + default Map getCustomerMap(Collection ids) { + return convertMap(getCustomerList(ids), ErpCustomerDO::getId); + } + + /** + * 获得客户分页 + * + * @param pageReqVO 分页查询 + * @return 客户分页 + */ + PageResult getCustomerPage(ErpCustomerPageReqVO pageReqVO); + + /** + * 获得指定状态的客户列表 + * + * @param status 状态 + * @return 客户列表 + */ + List getCustomerListByStatus(Integer status); + +} \ No newline at end of file diff --git a/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/service/sale/ErpCustomerServiceImpl.java b/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/service/sale/ErpCustomerServiceImpl.java new file mode 100644 index 000000000..73d2aa9d5 --- /dev/null +++ b/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/service/sale/ErpCustomerServiceImpl.java @@ -0,0 +1,97 @@ +package cn.iocoder.yudao.module.erp.service.sale; + +import cn.iocoder.yudao.framework.common.enums.CommonStatusEnum; +import cn.iocoder.yudao.framework.common.pojo.PageResult; +import cn.iocoder.yudao.framework.common.util.object.BeanUtils; +import cn.iocoder.yudao.module.erp.controller.admin.sale.vo.customer.ErpCustomerPageReqVO; +import cn.iocoder.yudao.module.erp.controller.admin.sale.vo.customer.ErpCustomerSaveReqVO; +import cn.iocoder.yudao.module.erp.dal.dataobject.sale.ErpCustomerDO; +import cn.iocoder.yudao.module.erp.dal.mysql.sale.ErpCustomerMapper; +import jakarta.annotation.Resource; +import org.springframework.stereotype.Service; +import org.springframework.validation.annotation.Validated; + +import java.util.Collection; +import java.util.List; + +import static cn.iocoder.yudao.framework.common.exception.util.ServiceExceptionUtil.exception; +import static cn.iocoder.yudao.module.erp.enums.ErrorCodeConstants.CUSTOMER_NOT_ENABLE; +import static cn.iocoder.yudao.module.erp.enums.ErrorCodeConstants.CUSTOMER_NOT_EXISTS; + +/** + * ERP 客户 Service 实现类 + * + * @author 芋道源码 + */ +@Service +@Validated +public class ErpCustomerServiceImpl implements ErpCustomerService { + + @Resource + private ErpCustomerMapper customerMapper; + + @Override + public Long createCustomer(ErpCustomerSaveReqVO createReqVO) { + // 插入 + ErpCustomerDO customer = BeanUtils.toBean(createReqVO, ErpCustomerDO.class); + customerMapper.insert(customer); + // 返回 + return customer.getId(); + } + + @Override + public void updateCustomer(ErpCustomerSaveReqVO updateReqVO) { + // 校验存在 + validateCustomerExists(updateReqVO.getId()); + // 更新 + ErpCustomerDO updateObj = BeanUtils.toBean(updateReqVO, ErpCustomerDO.class); + customerMapper.updateById(updateObj); + } + + @Override + public void deleteCustomer(Long id) { + // 校验存在 + validateCustomerExists(id); + // 删除 + customerMapper.deleteById(id); + } + + private void validateCustomerExists(Long id) { + if (customerMapper.selectById(id) == null) { + throw exception(CUSTOMER_NOT_EXISTS); + } + } + + @Override + public ErpCustomerDO getCustomer(Long id) { + return customerMapper.selectById(id); + } + + @Override + public ErpCustomerDO validateCustomer(Long id) { + ErpCustomerDO customer = customerMapper.selectById(id); + if (customer == null) { + throw exception(CUSTOMER_NOT_EXISTS); + } + if (CommonStatusEnum.isDisable(customer.getStatus())) { + throw exception(CUSTOMER_NOT_ENABLE, customer.getName()); + } + return customer; + } + + @Override + public List getCustomerList(Collection ids) { + return customerMapper.selectBatchIds(ids); + } + + @Override + public PageResult getCustomerPage(ErpCustomerPageReqVO pageReqVO) { + return customerMapper.selectPage(pageReqVO); + } + + @Override + public List getCustomerListByStatus(Integer status) { + return customerMapper.selectListByStatus(status); + } + +} \ No newline at end of file diff --git a/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/service/stock/ErpStockOutServiceImpl.java b/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/service/stock/ErpStockOutServiceImpl.java index 67041209b..36b5a30d8 100644 --- a/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/service/stock/ErpStockOutServiceImpl.java +++ b/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/service/stock/ErpStockOutServiceImpl.java @@ -15,7 +15,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.enums.stock.ErpStockRecordBizTypeEnum; import cn.iocoder.yudao.module.erp.service.product.ErpProductService; -import cn.iocoder.yudao.module.erp.service.purchase.ErpSupplierService; +import cn.iocoder.yudao.module.erp.service.sale.ErpCustomerService; import cn.iocoder.yudao.module.erp.service.stock.bo.ErpStockRecordCreateReqBO; import jakarta.annotation.Resource; import org.springframework.stereotype.Service; @@ -56,7 +56,7 @@ public class ErpStockOutServiceImpl implements ErpStockOutService { @Resource private ErpWarehouseService warehouseService; @Resource - private ErpSupplierService supplierService; + private ErpCustomerService customerService; @Resource private ErpStockRecordService stockRecordService; @@ -65,8 +65,8 @@ public class ErpStockOutServiceImpl implements ErpStockOutService { public Long createStockOut(ErpStockOutSaveReqVO createReqVO) { // 1.1 校验出库项的有效性 List stockOutItems = validateStockOutItems(createReqVO.getItems()); - // 1.2 校验客户 TODO -// supplierService.validateSupplier(createReqVO.getSupplierId()); + // 1.2 校验客户 + customerService.validateCustomer(createReqVO.getCustomerId()); // 1.3 String no = noRedisDAO.generate(ErpNoRedisDAO.STOCK_OUT_NO_PREFIX); if (stockOutMapper.selectByNo(no) != null) { @@ -93,8 +93,8 @@ public class ErpStockOutServiceImpl implements ErpStockOutService { if (ErpAuditStatus.APPROVE.getStatus().equals(stockOut.getStatus())) { throw exception(STOCK_OUT_UPDATE_FAIL_APPROVE, stockOut.getNo()); } - // 1.2 校验客户 TODO -// supplierService.validateSupplier(updateReqVO.getSupplierId()); + // 1.2 校验客户 + customerService.validateCustomer(updateReqVO.getCustomerId()); // 1.3 校验出库项的有效性 List stockOutItems = validateStockOutItems(updateReqVO.getItems()); diff --git a/yudao-module-erp/yudao-module-erp-biz/src/main/resources/mapper/sale/ErpCustomerMapper.xml b/yudao-module-erp/yudao-module-erp-biz/src/main/resources/mapper/sale/ErpCustomerMapper.xml new file mode 100644 index 000000000..c012f4467 --- /dev/null +++ b/yudao-module-erp/yudao-module-erp-biz/src/main/resources/mapper/sale/ErpCustomerMapper.xml @@ -0,0 +1,12 @@ + + + + + + + \ No newline at end of file diff --git a/yudao-module-erp/yudao-module-erp-biz/src/test/java/cn/iocoder/yudao/module/erp/service/sale/ErpCustomerServiceImplTest.java b/yudao-module-erp/yudao-module-erp-biz/src/test/java/cn/iocoder/yudao/module/erp/service/sale/ErpCustomerServiceImplTest.java new file mode 100644 index 000000000..caee693cc --- /dev/null +++ b/yudao-module-erp/yudao-module-erp-biz/src/test/java/cn/iocoder/yudao/module/erp/service/sale/ErpCustomerServiceImplTest.java @@ -0,0 +1,131 @@ +package cn.iocoder.yudao.module.erp.service.sale; + +import cn.iocoder.yudao.module.erp.controller.admin.sale.vo.customer.ErpCustomerPageReqVO; +import cn.iocoder.yudao.module.erp.controller.admin.sale.vo.customer.ErpCustomerSaveReqVO; +import org.junit.jupiter.api.Disabled; +import org.junit.jupiter.api.Test; + +import jakarta.annotation.Resource; + +import cn.iocoder.yudao.framework.test.core.ut.BaseDbUnitTest; + +import cn.iocoder.yudao.module.erp.dal.dataobject.sale.ErpCustomerDO; +import cn.iocoder.yudao.module.erp.dal.mysql.sale.ErpCustomerMapper; +import cn.iocoder.yudao.framework.common.pojo.PageResult; + +import org.springframework.context.annotation.Import; + +import static cn.iocoder.yudao.module.erp.enums.ErrorCodeConstants.*; +import static cn.iocoder.yudao.framework.test.core.util.AssertUtils.*; +import static cn.iocoder.yudao.framework.test.core.util.RandomUtils.*; +import static cn.iocoder.yudao.framework.common.util.object.ObjectUtils.*; +import static org.junit.jupiter.api.Assertions.*; + +/** + * {@link ErpCustomerServiceImpl} 的单元测试类 + * + * @author 芋道源码 + */ +@Import(ErpCustomerServiceImpl.class) +public class ErpCustomerServiceImplTest extends BaseDbUnitTest { + + @Resource + private ErpCustomerServiceImpl customerService; + + @Resource + private ErpCustomerMapper customerMapper; + + @Test + public void testCreateCustomer_success() { + // 准备参数 + ErpCustomerSaveReqVO createReqVO = randomPojo(ErpCustomerSaveReqVO.class).setId(null); + + // 调用 + Long customerId = customerService.createCustomer(createReqVO); + // 断言 + assertNotNull(customerId); + // 校验记录的属性是否正确 + ErpCustomerDO customer = customerMapper.selectById(customerId); + assertPojoEquals(createReqVO, customer, "id"); + } + + @Test + public void testUpdateCustomer_success() { + // mock 数据 + ErpCustomerDO dbCustomer = randomPojo(ErpCustomerDO.class); + customerMapper.insert(dbCustomer);// @Sql: 先插入出一条存在的数据 + // 准备参数 + ErpCustomerSaveReqVO updateReqVO = randomPojo(ErpCustomerSaveReqVO.class, o -> { + o.setId(dbCustomer.getId()); // 设置更新的 ID + }); + + // 调用 + customerService.updateCustomer(updateReqVO); + // 校验是否更新正确 + ErpCustomerDO customer = customerMapper.selectById(updateReqVO.getId()); // 获取最新的 + assertPojoEquals(updateReqVO, customer); + } + + @Test + public void testUpdateCustomer_notExists() { + // 准备参数 + ErpCustomerSaveReqVO updateReqVO = randomPojo(ErpCustomerSaveReqVO.class); + + // 调用, 并断言异常 + assertServiceException(() -> customerService.updateCustomer(updateReqVO), CUSTOMER_NOT_EXISTS); + } + + @Test + public void testDeleteCustomer_success() { + // mock 数据 + ErpCustomerDO dbCustomer = randomPojo(ErpCustomerDO.class); + customerMapper.insert(dbCustomer);// @Sql: 先插入出一条存在的数据 + // 准备参数 + Long id = dbCustomer.getId(); + + // 调用 + customerService.deleteCustomer(id); + // 校验数据不存在了 + assertNull(customerMapper.selectById(id)); + } + + @Test + public void testDeleteCustomer_notExists() { + // 准备参数 + Long id = randomLongId(); + + // 调用, 并断言异常 + assertServiceException(() -> customerService.deleteCustomer(id), CUSTOMER_NOT_EXISTS); + } + + @Test + @Disabled // TODO 请修改 null 为需要的值,然后删除 @Disabled 注解 + public void testGetCustomerPage() { + // mock 数据 + ErpCustomerDO dbCustomer = randomPojo(ErpCustomerDO.class, o -> { // 等会查询到 + o.setName(null); + o.setMobile(null); + o.setTelephone(null); + }); + customerMapper.insert(dbCustomer); + // 测试 name 不匹配 + customerMapper.insert(cloneIgnoreId(dbCustomer, o -> o.setName(null))); + // 测试 mobile 不匹配 + customerMapper.insert(cloneIgnoreId(dbCustomer, o -> o.setMobile(null))); + // 测试 telephone 不匹配 + customerMapper.insert(cloneIgnoreId(dbCustomer, o -> o.setTelephone(null))); + // 准备参数 + ErpCustomerPageReqVO reqVO = new ErpCustomerPageReqVO(); + reqVO.setName(null); + reqVO.setMobile(null); + reqVO.setTelephone(null); + + // 调用 + PageResult pageResult = customerService.getCustomerPage(reqVO); + // 断言 + assertEquals(1, pageResult.getTotal()); + assertEquals(1, pageResult.getList().size()); + assertPojoEquals(dbCustomer, pageResult.getList().get(0)); + } + +} \ No newline at end of file From f93963028fea115b34feb4b182fedffaa3d70cb4 Mon Sep 17 00:00:00 2001 From: YunaiV Date: Wed, 7 Feb 2024 17:01:33 +0800 Subject: [PATCH 086/119] =?UTF-8?q?=E2=9C=A8=20ERP=EF=BC=9A=E5=A2=9E?= =?UTF-8?q?=E5=8A=A0=20ERP=20=E8=B0=83=E6=8B=A8=E5=8D=95=E7=9A=84=E5=AE=9E?= =?UTF-8?q?=E7=8E=B0=2050%?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../admin/stock/ErpStockMoveController.java | 163 +++++++++++++ .../stock/vo/move/ErpStockMovePageReqVO.java | 45 ++++ .../stock/vo/move/ErpStockMoveRespVO.java | 107 ++++++++ .../stock/vo/move/ErpStockMoveSaveReqVO.java | 68 ++++++ .../dal/dataobject/stock/ErpStockMoveDO.java | 63 +++++ .../dataobject/stock/ErpStockMoveItemDO.java | 79 ++++++ .../mysql/stock/ErpStockMoveItemMapper.java | 30 +++ .../dal/mysql/stock/ErpStockMoveMapper.java | 46 ++++ .../service/stock/ErpStockMoveService.java | 84 +++++++ .../stock/ErpStockMoveServiceImpl.java | 229 ++++++++++++++++++ 10 files changed, 914 insertions(+) create mode 100644 yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/controller/admin/stock/ErpStockMoveController.java create mode 100644 yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/controller/admin/stock/vo/move/ErpStockMovePageReqVO.java create mode 100644 yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/controller/admin/stock/vo/move/ErpStockMoveRespVO.java create mode 100644 yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/controller/admin/stock/vo/move/ErpStockMoveSaveReqVO.java create mode 100644 yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/dal/dataobject/stock/ErpStockMoveDO.java create mode 100644 yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/dal/dataobject/stock/ErpStockMoveItemDO.java create mode 100644 yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/dal/mysql/stock/ErpStockMoveItemMapper.java create mode 100644 yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/dal/mysql/stock/ErpStockMoveMapper.java create mode 100644 yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/service/stock/ErpStockMoveService.java create mode 100644 yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/service/stock/ErpStockMoveServiceImpl.java diff --git a/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/controller/admin/stock/ErpStockMoveController.java b/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/controller/admin/stock/ErpStockMoveController.java new file mode 100644 index 000000000..e39b7bba7 --- /dev/null +++ b/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/controller/admin/stock/ErpStockMoveController.java @@ -0,0 +1,163 @@ +package cn.iocoder.yudao.module.erp.controller.admin.stock; + +import cn.hutool.core.collection.CollUtil; +import cn.iocoder.yudao.framework.common.pojo.CommonResult; +import cn.iocoder.yudao.framework.common.pojo.PageParam; +import cn.iocoder.yudao.framework.common.pojo.PageResult; +import cn.iocoder.yudao.framework.common.util.collection.MapUtils; +import cn.iocoder.yudao.framework.common.util.object.BeanUtils; +import cn.iocoder.yudao.framework.excel.core.util.ExcelUtils; +import cn.iocoder.yudao.framework.operatelog.core.annotations.OperateLog; +import cn.iocoder.yudao.module.erp.controller.admin.product.vo.product.ErpProductRespVO; +import cn.iocoder.yudao.module.erp.controller.admin.stock.vo.move.ErpStockMovePageReqVO; +import cn.iocoder.yudao.module.erp.controller.admin.stock.vo.move.ErpStockMoveRespVO; +import cn.iocoder.yudao.module.erp.controller.admin.stock.vo.move.ErpStockMoveSaveReqVO; +import cn.iocoder.yudao.module.erp.dal.dataobject.stock.ErpStockDO; +import cn.iocoder.yudao.module.erp.dal.dataobject.stock.ErpStockMoveDO; +import cn.iocoder.yudao.module.erp.dal.dataobject.stock.ErpStockMoveItemDO; +import cn.iocoder.yudao.module.erp.service.product.ErpProductService; +import cn.iocoder.yudao.module.erp.service.sale.ErpCustomerService; +import cn.iocoder.yudao.module.erp.service.stock.ErpStockMoveService; +import cn.iocoder.yudao.module.erp.service.stock.ErpStockService; +import cn.iocoder.yudao.module.system.api.user.AdminUserApi; +import cn.iocoder.yudao.module.system.api.user.dto.AdminUserRespDTO; +import io.swagger.v3.oas.annotations.Operation; +import io.swagger.v3.oas.annotations.Parameter; +import io.swagger.v3.oas.annotations.tags.Tag; +import jakarta.annotation.Resource; +import jakarta.servlet.http.HttpServletResponse; +import jakarta.validation.Valid; +import org.springframework.security.access.prepost.PreAuthorize; +import org.springframework.validation.annotation.Validated; +import org.springframework.web.bind.annotation.*; + +import java.io.IOException; +import java.math.BigDecimal; +import java.util.List; +import java.util.Map; + +import static cn.iocoder.yudao.framework.common.pojo.CommonResult.success; +import static cn.iocoder.yudao.framework.common.util.collection.CollectionUtils.convertMultiMap; +import static cn.iocoder.yudao.framework.common.util.collection.CollectionUtils.convertSet; +import static cn.iocoder.yudao.framework.operatelog.core.enums.OperateTypeEnum.EXPORT; + +@Tag(name = "管理后台 - ERP 库存调拨单") +@RestController +@RequestMapping("/erp/stock-move") +@Validated +public class ErpStockMoveController { + + @Resource + private ErpStockMoveService stockMoveService; + @Resource + private ErpStockService stockService; + @Resource + private ErpProductService productService; + @Resource + private ErpCustomerService customerService; + + @Resource + private AdminUserApi adminUserApi; + + @PostMapping("/create") + @Operation(summary = "创建库存调拨单") + @PreAuthorize("@ss.hasPermission('erp:stock-move:create')") + public CommonResult createStockMove(@Valid @RequestBody ErpStockMoveSaveReqVO createReqVO) { + return success(stockMoveService.createStockMove(createReqVO)); + } + + @PutMapping("/update") + @Operation(summary = "更新库存调拨单") + @PreAuthorize("@ss.hasPermission('erp:stock-move:update')") + public CommonResult updateStockMove(@Valid @RequestBody ErpStockMoveSaveReqVO updateReqVO) { + stockMoveService.updateStockMove(updateReqVO); + return success(true); + } + + @PutMapping("/update-status") + @Operation(summary = "更新库存调拨单的状态") + @PreAuthorize("@ss.hasPermission('erp:stock-move:update-status')") + public CommonResult updateStockMoveStatus(@RequestParam("id") Long id, + @RequestParam("status") Integer status) { + stockMoveService.updateStockMoveStatus(id, status); + return success(true); + } + + @DeleteMapping("/delete") + @Operation(summary = "删除库存调拨单") + @Parameter(name = "ids", description = "编号数组", required = true) + @PreAuthorize("@ss.hasPermission('erp:stock-move:delete')") + public CommonResult deleteStockMove(@RequestParam("ids") List ids) { + stockMoveService.deleteStockMove(ids); + return success(true); + } + + @GetMapping("/get") + @Operation(summary = "获得库存调拨单") + @Parameter(name = "id", description = "编号", required = true, example = "1024") + @PreAuthorize("@ss.hasPermission('erp:stock-move:query')") + public CommonResult getStockMove(@RequestParam("id") Long id) { + ErpStockMoveDO stockMove = stockMoveService.getStockMove(id); + if (stockMove == null) { + return success(null); + } + List stockMoveItemList = stockMoveService.getStockMoveItemListByMoveId(id); + Map productMap = productService.getProductVOMap( + convertSet(stockMoveItemList, ErpStockMoveItemDO::getProductId)); + return success(BeanUtils.toBean(stockMove, ErpStockMoveRespVO.class, stockMoveVO -> + stockMoveVO.setItems(BeanUtils.toBean(stockMoveItemList, ErpStockMoveRespVO.Item.class, item -> { + ErpStockDO stock = stockService.getStock(item.getProductId(), item.getFromWarehouseId()); + 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") + @Operation(summary = "获得库存调拨单分页") + @PreAuthorize("@ss.hasPermission('erp:stock-move:query')") + public CommonResult> getStockMovePage(@Valid ErpStockMovePageReqVO pageReqVO) { + PageResult pageResult = stockMoveService.getStockMovePage(pageReqVO); + return success(buildStockMoveVOPageResult(pageResult)); + } + + @GetMapping("/export-excel") + @Operation(summary = "导出库存调拨单 Excel") + @PreAuthorize("@ss.hasPermission('erp:stock-move:export')") + @OperateLog(type = EXPORT) + public void exportStockMoveExcel(@Valid ErpStockMovePageReqVO pageReqVO, + HttpServletResponse response) throws IOException { + pageReqVO.setPageSize(PageParam.PAGE_SIZE_NONE); + List list = buildStockMoveVOPageResult(stockMoveService.getStockMovePage(pageReqVO)).getList(); + // 导出 Excel + ExcelUtils.write(response, "库存调拨单.xls", "数据", ErpStockMoveRespVO.class, list); + } + + private PageResult buildStockMoveVOPageResult(PageResult pageResult) { + if (CollUtil.isEmpty(pageResult.getList())) { + return PageResult.empty(pageResult.getTotal()); + } + // 1.1 出库项 + List stockMoveItemList = stockMoveService.getStockMoveItemListByMoveIds( + convertSet(pageResult.getList(), ErpStockMoveDO::getId)); + Map> stockMoveItemMap = convertMultiMap(stockMoveItemList, ErpStockMoveItemDO::getMoveId); + // 1.2 商品信息 + Map productMap = productService.getProductVOMap( + convertSet(stockMoveItemList, ErpStockMoveItemDO::getProductId)); + // 1.3 TODO 芋艿:搞仓库信息 + // 1.4 管理员信息 + Map userMap = adminUserApi.getUserMap( + convertSet(pageResult.getList(), erpStockRecordDO -> Long.parseLong(erpStockRecordDO.getCreator()))); + // 2. 开始拼接 + return BeanUtils.toBean(pageResult, ErpStockMoveRespVO.class, stockMove -> { + stockMove.setItems(BeanUtils.toBean(stockMoveItemMap.get(stockMove.getId()), ErpStockMoveRespVO.Item.class, + item -> MapUtils.findAndThen(productMap, item.getProductId(), product -> item.setProductName(product.getName()) + .setProductBarCode(product.getBarCode()).setProductUnitName(product.getUnitName())))); + stockMove.setProductNames(CollUtil.join(stockMove.getItems(), ",", ErpStockMoveRespVO.Item::getProductName)); + // TODO 芋艿: +// MapUtils.findAndThen(customerMap, stockMove.getCustomerId(), supplier -> stockMove.setCustomerName(supplier.getName())); + MapUtils.findAndThen(userMap, Long.parseLong(stockMove.getCreator()), user -> stockMove.setCreatorName(user.getNickname())); + }); + } + +} \ No newline at end of file diff --git a/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/controller/admin/stock/vo/move/ErpStockMovePageReqVO.java b/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/controller/admin/stock/vo/move/ErpStockMovePageReqVO.java new file mode 100644 index 000000000..98a1fe95e --- /dev/null +++ b/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/controller/admin/stock/vo/move/ErpStockMovePageReqVO.java @@ -0,0 +1,45 @@ +package cn.iocoder.yudao.module.erp.controller.admin.stock.vo.move; + +import cn.iocoder.yudao.framework.common.pojo.PageParam; +import cn.iocoder.yudao.framework.common.validation.InEnum; +import cn.iocoder.yudao.module.erp.enums.ErpAuditStatus; +import io.swagger.v3.oas.annotations.media.Schema; +import lombok.Data; +import lombok.EqualsAndHashCode; +import lombok.ToString; +import org.springframework.format.annotation.DateTimeFormat; + +import java.time.LocalDateTime; + +import static cn.iocoder.yudao.framework.common.util.date.DateUtils.FORMAT_YEAR_MONTH_DAY_HOUR_MINUTE_SECOND; + +@Schema(description = "管理后台 - ERP 库存调拨单分页 Request VO") +@Data +@EqualsAndHashCode(callSuper = true) +@ToString(callSuper = true) +public class ErpStockMovePageReqVO extends PageParam { + + @Schema(description = "调拨单号", example = "S123") + private String no; + + @Schema(description = "调拨时间") + @DateTimeFormat(pattern = FORMAT_YEAR_MONTH_DAY_HOUR_MINUTE_SECOND) + private LocalDateTime[] moveTime; + + @Schema(description = "状态", example = "10") + @InEnum(ErpAuditStatus.class) + private Integer status; + + @Schema(description = "备注", example = "随便") + private String remark; + + @Schema(description = "创建者") + private String creator; + + @Schema(description = "产品编号", example = "1") + private Long productId; + + @Schema(description = "调出仓库编号", example = "1") + private Long fromWarehouseId; + +} \ No newline at end of file diff --git a/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/controller/admin/stock/vo/move/ErpStockMoveRespVO.java b/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/controller/admin/stock/vo/move/ErpStockMoveRespVO.java new file mode 100644 index 000000000..b09fb15a1 --- /dev/null +++ b/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/controller/admin/stock/vo/move/ErpStockMoveRespVO.java @@ -0,0 +1,107 @@ +package cn.iocoder.yudao.module.erp.controller.admin.stock.vo.move; + +import cn.iocoder.yudao.framework.excel.core.annotations.DictFormat; +import cn.iocoder.yudao.framework.excel.core.convert.DictConvert; +import com.alibaba.excel.annotation.ExcelIgnoreUnannotated; +import com.alibaba.excel.annotation.ExcelProperty; +import io.swagger.v3.oas.annotations.media.Schema; +import lombok.Data; + +import java.math.BigDecimal; +import java.time.LocalDateTime; +import java.util.List; + +import static cn.iocoder.yudao.module.erp.enums.DictTypeConstants.AUDIT_STATUS; + +@Schema(description = "管理后台 - ERP 库存调拨单 Response VO") +@Data +@ExcelIgnoreUnannotated +public class ErpStockMoveRespVO { + + @Schema(description = "调拨编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "11756") + @ExcelProperty("调拨编号") + private Long id; + + @Schema(description = "调拨单号", requiredMode = Schema.RequiredMode.REQUIRED, example = "S123") + @ExcelProperty("调拨单号") + private String no; + + @Schema(description = "调拨时间", requiredMode = Schema.RequiredMode.REQUIRED) + @ExcelProperty("调拨时间") + private LocalDateTime moveTime; + + @Schema(description = "合计数量", requiredMode = Schema.RequiredMode.REQUIRED, example = "15663") + @ExcelProperty("合计数量") + private BigDecimal totalCount; + + @Schema(description = "合计金额,单位:元", requiredMode = Schema.RequiredMode.REQUIRED, example = "24906") + @ExcelProperty("合计金额") + private BigDecimal totalPrice; + + @Schema(description = "状态", requiredMode = Schema.RequiredMode.REQUIRED, example = "10") + @ExcelProperty(value = "状态", converter = DictConvert.class) + @DictFormat(AUDIT_STATUS) + private Integer status; + + @Schema(description = "备注", example = "随便") + @ExcelProperty("备注") + private String remark; + + @Schema(description = "附件 URL", example = "https://www.iocoder.cn/1.doc") + private String fileUrl; + + @Schema(description = "审核人", example = "芋道") + private String creator; + @Schema(description = "审核人名称", example = "芋道") + private String creatorName; + + @Schema(description = "创建时间", requiredMode = Schema.RequiredMode.REQUIRED) + @ExcelProperty("创建时间") + private LocalDateTime createTime; + + @Schema(description = "调拨项列表", requiredMode = Schema.RequiredMode.REQUIRED) + private List items; + + @Schema(description = "产品信息", requiredMode = Schema.RequiredMode.REQUIRED) + @ExcelProperty("产品信息") + private String productNames; + + @Data + public static class Item { + + @Schema(description = "调拨项编号", example = "11756") + private Long id; + + @Schema(description = "调出仓库编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "3113") + private Long fromWarehouseId; + + @Schema(description = "调入仓库编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "888") + private Long toWarehouseId; + + @Schema(description = "产品编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "3113") + private Long productId; + + @Schema(description = "产品单价", requiredMode = Schema.RequiredMode.REQUIRED, example = "100.00") + private BigDecimal productPrice; + + @Schema(description = "产品数量", requiredMode = Schema.RequiredMode.REQUIRED, example = "100.00") + private BigDecimal count; + + @Schema(description = "备注", example = "随便") + private String remark; + + // ========== 关联字段 ========== + + @Schema(description = "产品名称", requiredMode = Schema.RequiredMode.REQUIRED, example = "巧克力") + private String productName; + @Schema(description = "产品条码", requiredMode = Schema.RequiredMode.REQUIRED, example = "A9985") + private String productBarCode; + @Schema(description = "产品单位名称", requiredMode = Schema.RequiredMode.REQUIRED, example = "盒") + private String productUnitName; + + @Schema(description = "库存数量", requiredMode = Schema.RequiredMode.REQUIRED, example = "100.00") + private BigDecimal stockCount; // 该字段仅仅在“详情”和“编辑”时使用 + + } + +} \ No newline at end of file diff --git a/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/controller/admin/stock/vo/move/ErpStockMoveSaveReqVO.java b/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/controller/admin/stock/vo/move/ErpStockMoveSaveReqVO.java new file mode 100644 index 000000000..699d0d2a5 --- /dev/null +++ b/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/controller/admin/stock/vo/move/ErpStockMoveSaveReqVO.java @@ -0,0 +1,68 @@ +package cn.iocoder.yudao.module.erp.controller.admin.stock.vo.move; + +import io.swagger.v3.oas.annotations.media.Schema; +import jakarta.validation.Valid; +import jakarta.validation.constraints.NotEmpty; +import jakarta.validation.constraints.NotNull; +import lombok.Data; + +import java.math.BigDecimal; +import java.time.LocalDateTime; +import java.util.List; + +@Schema(description = "管理后台 - ERP 库存调拨单新增/修改 Request VO") +@Data +public class ErpStockMoveSaveReqVO { + + @Schema(description = "调拨编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "11756") + private Long id; + + @Schema(description = "客户编号", example = "3113") + private Long customerId; + + @Schema(description = "调拨时间", requiredMode = Schema.RequiredMode.REQUIRED) + @NotNull(message = "调拨时间不能为空") + private LocalDateTime moveTime; + + @Schema(description = "备注", example = "随便") + private String remark; + + @Schema(description = "附件 URL", example = "https://www.iocoder.cn/1.doc") + private String fileUrl; + + @Schema(description = "调拨项列表", requiredMode = Schema.RequiredMode.REQUIRED) + @NotEmpty(message = "调拨项列表不能为空") + @Valid + private List items; + + @Data + public static class Item { + + @Schema(description = "调拨项编号", example = "11756") + private Long id; + + @Schema(description = "调出仓库编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "3113") + @NotNull(message = "调出仓库编号不能为空") + private Long fromWarehouseId; + + @Schema(description = "调入仓库编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "888") + @NotNull(message = "调入仓库编号不能为空") + private Long toWarehouseId; + + @Schema(description = "产品编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "3113") + @NotNull(message = "产品编号不能为空") + private Long productId; + + @Schema(description = "产品单价", example = "100.00") + private BigDecimal productPrice; + + @Schema(description = "产品数量", requiredMode = Schema.RequiredMode.REQUIRED, example = "100.00") + @NotNull(message = "产品数量不能为空") + private BigDecimal count; + + @Schema(description = "备注", example = "随便") + private String remark; + + } + +} \ No newline at end of file diff --git a/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/dal/dataobject/stock/ErpStockMoveDO.java b/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/dal/dataobject/stock/ErpStockMoveDO.java new file mode 100644 index 000000000..a07c9549d --- /dev/null +++ b/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/dal/dataobject/stock/ErpStockMoveDO.java @@ -0,0 +1,63 @@ +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.*; + +import java.math.BigDecimal; +import java.time.LocalDateTime; + +/** + * ERP 库存调拨单 DO + * + * @author 芋道源码 + */ +@TableName("erp_stock_in") +@KeySequence("erp_stock_in_seq") // 用于 Oracle、PostgreSQL、Kingbase、DB2、H2 数据库的主键自增。如果是 MySQL 等数据库,可不写。 +@Data +@EqualsAndHashCode(callSuper = true) +@ToString(callSuper = true) +@Builder +@NoArgsConstructor +@AllArgsConstructor +public class ErpStockMoveDO extends BaseDO { + + /** + * 调拨编号 + */ + @TableId + private Long id; + /** + * 调拨单号 + */ + private String no; + /** + * 调拨时间 + */ + private LocalDateTime moveTime; + /** + * 合计数量 + */ + private BigDecimal totalCount; + /** + * 合计金额,单位:元 + */ + private BigDecimal totalPrice; + /** + * 状态 + * + * 枚举 {@link cn.iocoder.yudao.module.erp.enums.ErpAuditStatus} + */ + private Integer status; + /** + * 备注 + */ + private String remark; + /** + * 附件 URL + */ + private String fileUrl; + +} \ No newline at end of file diff --git a/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/dal/dataobject/stock/ErpStockMoveItemDO.java b/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/dal/dataobject/stock/ErpStockMoveItemDO.java new file mode 100644 index 000000000..2e34df0dc --- /dev/null +++ b/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/dal/dataobject/stock/ErpStockMoveItemDO.java @@ -0,0 +1,79 @@ +package cn.iocoder.yudao.module.erp.dal.dataobject.stock; + +import cn.iocoder.yudao.framework.mybatis.core.dataobject.BaseDO; +import cn.iocoder.yudao.module.erp.dal.dataobject.product.ErpProductDO; +import com.baomidou.mybatisplus.annotation.KeySequence; +import com.baomidou.mybatisplus.annotation.TableId; +import com.baomidou.mybatisplus.annotation.TableName; +import lombok.*; + +import java.math.BigDecimal; + +/** + * ERP 库存调拨单项 DO + * + * @author 芋道源码 + */ +@TableName("erp_stock_in_item") +@KeySequence("erp_stock_in_item_seq") // 用于 Oracle、PostgreSQL、Kingbase、DB2、H2 数据库的主键自增。如果是 MySQL 等数据库,可不写。 +@Data +@EqualsAndHashCode(callSuper = true) +@ToString(callSuper = true) +@Builder +@NoArgsConstructor +@AllArgsConstructor +public class ErpStockMoveItemDO extends BaseDO { + + /** + * 调拨项编号 + */ + @TableId + private Long id; + /** + * 调拨编号 + * + * 关联 {@link ErpStockMoveDO#getId()} + */ + private Long moveId; + /** + * 调出仓库编号 + * + * 关联 {@link ErpWarehouseDO#getId()} + */ + private Long fromWarehouseId; + /** + * 调入仓库编号 + * + * 关联 {@link ErpWarehouseDO#getId()} + */ + private Long toWarehouseId; + /** + * 产品编号 + * + * 关联 {@link ErpProductDO#getId()} + */ + private Long productId; + /** + * 产品单位编号 + * + * 冗余 {@link ErpProductDO#getUnitId()} + */ + private Long productUnitId; + /** + * 产品单价 + */ + private BigDecimal productPrice; + /** + * 产品数量 + */ + private BigDecimal count; + /** + * 合计金额,单位:元 + */ + private BigDecimal totalPrice; + /** + * 备注 + */ + private String remark; + +} \ No newline at end of file diff --git a/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/dal/mysql/stock/ErpStockMoveItemMapper.java b/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/dal/mysql/stock/ErpStockMoveItemMapper.java new file mode 100644 index 000000000..21a267029 --- /dev/null +++ b/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/dal/mysql/stock/ErpStockMoveItemMapper.java @@ -0,0 +1,30 @@ +package cn.iocoder.yudao.module.erp.dal.mysql.stock; + +import cn.iocoder.yudao.framework.mybatis.core.mapper.BaseMapperX; +import cn.iocoder.yudao.module.erp.dal.dataobject.stock.ErpStockMoveItemDO; +import org.apache.ibatis.annotations.Mapper; + +import java.util.Collection; +import java.util.List; + +/** + * ERP 库存调拨单项 Mapper + * + * @author 芋道源码 + */ +@Mapper +public interface ErpStockMoveItemMapper extends BaseMapperX { + + default List selectListByMoveId(Long moveId) { + return selectList(ErpStockMoveItemDO::getMoveId, moveId); + } + + default List selectListByMoveIds(Collection moveIds) { + return selectList(ErpStockMoveItemDO::getMoveId, moveIds); + } + + default int deleteByMoveId(Long moveId) { + return delete(ErpStockMoveItemDO::getMoveId, moveId); + } + +} \ No newline at end of file diff --git a/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/dal/mysql/stock/ErpStockMoveMapper.java b/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/dal/mysql/stock/ErpStockMoveMapper.java new file mode 100644 index 000000000..2b45f6c7e --- /dev/null +++ b/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/dal/mysql/stock/ErpStockMoveMapper.java @@ -0,0 +1,46 @@ +package cn.iocoder.yudao.module.erp.dal.mysql.stock; + +import cn.iocoder.yudao.framework.common.pojo.PageResult; +import cn.iocoder.yudao.framework.mybatis.core.mapper.BaseMapperX; +import cn.iocoder.yudao.framework.mybatis.core.query.MPJLambdaWrapperX; +import cn.iocoder.yudao.module.erp.controller.admin.stock.vo.move.ErpStockMovePageReqVO; +import cn.iocoder.yudao.module.erp.dal.dataobject.stock.ErpStockMoveDO; +import cn.iocoder.yudao.module.erp.dal.dataobject.stock.ErpStockMoveItemDO; +import com.baomidou.mybatisplus.core.conditions.update.LambdaUpdateWrapper; +import org.apache.ibatis.annotations.Mapper; + +/** + * ERP 库存调拨单 Mapper + * + * @author 芋道源码 + */ +@Mapper +public interface ErpStockMoveMapper extends BaseMapperX { + + default PageResult selectPage(ErpStockMovePageReqVO reqVO) { + MPJLambdaWrapperX query = new MPJLambdaWrapperX() + .eqIfPresent(ErpStockMoveDO::getNo, reqVO.getNo()) + .betweenIfPresent(ErpStockMoveDO::getMoveTime, reqVO.getMoveTime()) + .eqIfPresent(ErpStockMoveDO::getStatus, reqVO.getStatus()) + .likeIfPresent(ErpStockMoveDO::getRemark, reqVO.getRemark()) + .eqIfPresent(ErpStockMoveDO::getCreator, reqVO.getCreator()) + .orderByDesc(ErpStockMoveDO::getId); + if (reqVO.getFromWarehouseId() != null || reqVO.getProductId() != null) { + query.leftJoin(ErpStockMoveItemDO.class, ErpStockMoveItemDO::getMoveId, ErpStockMoveDO::getId) + .eq(reqVO.getFromWarehouseId() != null, ErpStockMoveItemDO::getFromWarehouseId, reqVO.getFromWarehouseId()) + .eq(reqVO.getProductId() != null, ErpStockMoveItemDO::getProductId, reqVO.getProductId()) + .groupBy(ErpStockMoveDO::getId); // 避免 1 对多查询,产生相同的 1 + } + return selectJoinPage(reqVO, ErpStockMoveDO.class, query); + } + + default int updateByIdAndStatus(Long id, Integer status, ErpStockMoveDO updateObj) { + return update(updateObj, new LambdaUpdateWrapper() + .eq(ErpStockMoveDO::getId, id).eq(ErpStockMoveDO::getStatus, status)); + } + + default ErpStockMoveDO selectByNo(String no) { + return selectOne(ErpStockMoveDO::getNo, no); + } + +} \ No newline at end of file diff --git a/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/service/stock/ErpStockMoveService.java b/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/service/stock/ErpStockMoveService.java new file mode 100644 index 000000000..8af13a639 --- /dev/null +++ b/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/service/stock/ErpStockMoveService.java @@ -0,0 +1,84 @@ +package cn.iocoder.yudao.module.erp.service.stock; + +import cn.iocoder.yudao.framework.common.pojo.PageResult; +import cn.iocoder.yudao.module.erp.controller.admin.stock.vo.move.ErpStockMovePageReqVO; +import cn.iocoder.yudao.module.erp.controller.admin.stock.vo.move.ErpStockMoveSaveReqVO; +import cn.iocoder.yudao.module.erp.dal.dataobject.stock.ErpStockMoveDO; +import cn.iocoder.yudao.module.erp.dal.dataobject.stock.ErpStockMoveItemDO; +import jakarta.validation.Valid; + +import java.util.Collection; +import java.util.List; + +/** + * ERP 库存调拨单 Service 接口 + * + * @author 芋道源码 + */ +public interface ErpStockMoveService { + + /** + * 创建库存调拨单 + * + * @param createReqVO 创建信息 + * @return 编号 + */ + Long createStockMove(@Valid ErpStockMoveSaveReqVO createReqVO); + + /** + * 更新库存调拨单 + * + * @param updateReqVO 更新信息 + */ + void updateStockMove(@Valid ErpStockMoveSaveReqVO updateReqVO); + + /** + * 更新库存调拨单的状态 + * + * @param id 编号 + * @param status 状态 + */ + void updateStockMoveStatus(Long id, Integer status); + + /** + * 删除库存调拨单 + * + * @param ids 编号数组 + */ + void deleteStockMove(List ids); + + /** + * 获得库存调拨单 + * + * @param id 编号 + * @return 库存调拨单 + */ + ErpStockMoveDO getStockMove(Long id); + + /** + * 获得库存调拨单分页 + * + * @param pageReqVO 分页查询 + * @return 库存调拨单分页 + */ + PageResult getStockMovePage(ErpStockMovePageReqVO pageReqVO); + + // ==================== 调拨项 ==================== + + /** + * 获得库存调拨单项列表 + * + * @param moveId 调拨编号 + * @return 库存调拨单项列表 + */ + List getStockMoveItemListByMoveId(Long moveId); + + /** + * 获得库存调拨单项 List + * + * @param moveIds 调拨编号数组 + * @return 库存调拨单项 List + */ + List getStockMoveItemListByMoveIds(Collection moveIds); + +} \ No newline at end of file diff --git a/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/service/stock/ErpStockMoveServiceImpl.java b/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/service/stock/ErpStockMoveServiceImpl.java new file mode 100644 index 000000000..603ddfcaa --- /dev/null +++ b/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/service/stock/ErpStockMoveServiceImpl.java @@ -0,0 +1,229 @@ +package cn.iocoder.yudao.module.erp.service.stock; + +import cn.hutool.core.collection.CollUtil; +import cn.iocoder.yudao.framework.common.pojo.PageResult; +import cn.iocoder.yudao.framework.common.util.number.MoneyUtils; +import cn.iocoder.yudao.framework.common.util.object.BeanUtils; +import cn.iocoder.yudao.module.erp.controller.admin.stock.vo.move.ErpStockMovePageReqVO; +import cn.iocoder.yudao.module.erp.controller.admin.stock.vo.move.ErpStockMoveSaveReqVO; +import cn.iocoder.yudao.module.erp.dal.dataobject.product.ErpProductDO; +import cn.iocoder.yudao.module.erp.dal.dataobject.stock.ErpStockMoveDO; +import cn.iocoder.yudao.module.erp.dal.dataobject.stock.ErpStockMoveItemDO; +import cn.iocoder.yudao.module.erp.dal.mysql.stock.ErpStockMoveItemMapper; +import cn.iocoder.yudao.module.erp.dal.mysql.stock.ErpStockMoveMapper; +import cn.iocoder.yudao.module.erp.dal.redis.no.ErpNoRedisDAO; +import cn.iocoder.yudao.module.erp.enums.ErpAuditStatus; +import cn.iocoder.yudao.module.erp.enums.stock.ErpStockRecordBizTypeEnum; +import cn.iocoder.yudao.module.erp.service.product.ErpProductService; +import cn.iocoder.yudao.module.erp.service.sale.ErpCustomerService; +import jakarta.annotation.Resource; +import org.springframework.stereotype.Service; +import org.springframework.transaction.annotation.Transactional; +import org.springframework.validation.annotation.Validated; + +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.exception.util.ServiceExceptionUtil.exception; +import static cn.iocoder.yudao.framework.common.util.collection.CollectionUtils.*; +import static cn.iocoder.yudao.module.erp.enums.ErrorCodeConstants.*; + +// TODO 芋艿:记录操作日志 + +/** + * ERP 库存调拨单 Service 实现类 + * + * @author 芋道源码 + */ +@Service +@Validated +public class ErpStockMoveServiceImpl implements ErpStockMoveService { + + @Resource + private ErpStockMoveMapper stockMoveMapper; + @Resource + private ErpStockMoveItemMapper stockMoveItemMapper; + + @Resource + private ErpNoRedisDAO noRedisDAO; + + @Resource + private ErpProductService productService; + @Resource + private ErpWarehouseService warehouseService; + @Resource + private ErpCustomerService customerService; + @Resource + private ErpStockRecordService stockRecordService; + + @Override + @Transactional(rollbackFor = Exception.class) + public Long createStockMove(ErpStockMoveSaveReqVO createReqVO) { + // 1.1 校验出库项的有效性 + List stockMoveItems = validateStockMoveItems(createReqVO.getItems()); + // 1.2 校验客户 + customerService.validateCustomer(createReqVO.getCustomerId()); + // 1.3 + String no = noRedisDAO.generate(ErpNoRedisDAO.STOCK_OUT_NO_PREFIX); + if (stockMoveMapper.selectByNo(no) != null) { + throw exception(STOCK_OUT_NO_EXISTS); + } + + // 2.1 插入出库单 + ErpStockMoveDO stockMove = BeanUtils.toBean(createReqVO, ErpStockMoveDO.class, in -> in + .setNo(no).setStatus(ErpAuditStatus.PROCESS.getStatus()) + .setTotalCount(getSumValue(stockMoveItems, ErpStockMoveItemDO::getCount, BigDecimal::add)) + .setTotalPrice(getSumValue(stockMoveItems, ErpStockMoveItemDO::getTotalPrice, BigDecimal::add, BigDecimal.ZERO))); + stockMoveMapper.insert(stockMove); + // 2.2 插入出库单项 + stockMoveItems.forEach(o -> o.setMoveId(stockMove.getId())); + stockMoveItemMapper.insertBatch(stockMoveItems); + return stockMove.getId(); + } + + @Override + @Transactional(rollbackFor = Exception.class) + public void updateStockMove(ErpStockMoveSaveReqVO updateReqVO) { + // 1.1 校验存在 + ErpStockMoveDO stockMove = validateStockMoveExists(updateReqVO.getId()); + if (ErpAuditStatus.APPROVE.getStatus().equals(stockMove.getStatus())) { + throw exception(STOCK_OUT_UPDATE_FAIL_APPROVE, stockMove.getNo()); + } + // 1.2 校验客户 + customerService.validateCustomer(updateReqVO.getCustomerId()); + // 1.3 校验出库项的有效性 + List stockMoveItems = validateStockMoveItems(updateReqVO.getItems()); + + // 2.1 更新出库单 + ErpStockMoveDO updateObj = BeanUtils.toBean(updateReqVO, ErpStockMoveDO.class, in -> in + .setTotalCount(getSumValue(stockMoveItems, ErpStockMoveItemDO::getCount, BigDecimal::add)) + .setTotalPrice(getSumValue(stockMoveItems, ErpStockMoveItemDO::getTotalPrice, BigDecimal::add))); + stockMoveMapper.updateById(updateObj); + // 2.2 更新出库单项 + updateStockMoveItemList(updateReqVO.getId(), stockMoveItems); + } + + @Override + @Transactional(rollbackFor = Exception.class) + public void updateStockMoveStatus(Long id, Integer status) { + boolean approve = ErpAuditStatus.APPROVE.getStatus().equals(status); + // 1.1 校验存在 + ErpStockMoveDO stockMove = validateStockMoveExists(id); + // 1.2 校验状态 + if (stockMove.getStatus().equals(status)) { + throw exception(approve ? STOCK_OUT_APPROVE_FAIL : STOCK_OUT_PROCESS_FAIL); + } + + // 2. 更新状态 + int updateCount = stockMoveMapper.updateByIdAndStatus(id, stockMove.getStatus(), + new ErpStockMoveDO().setStatus(status)); + if (updateCount == 0) { + throw exception(approve ? STOCK_OUT_APPROVE_FAIL : STOCK_OUT_PROCESS_FAIL); + } + + // 3. 变更库存 + List stockMoveItems = stockMoveItemMapper.selectListByMoveId(id); + Integer bizType = approve ? ErpStockRecordBizTypeEnum.OTHER_OUT.getType() + : ErpStockRecordBizTypeEnum.OTHER_OUT_CANCEL.getType(); + stockMoveItems.forEach(stockMoveItem -> { + BigDecimal count = approve ? stockMoveItem.getCount() : stockMoveItem.getCount().negate(); + // TODO 芋艿:稍后搞 +// stockRecordService.createStockRecord(new ErpStockRecordCreateReqBO( +// stockMoveItem.getProductId(), stockMoveItem.getWarehouseId(), count, +// bizType, stockMoveItem.getMoveId(), stockMoveItem.getId(), stockMove.getNo())); + }); + } + + private List validateStockMoveItems(List list) { + // 1.1 校验产品存在 + List productList = productService.validProductList( + convertSet(list, ErpStockMoveSaveReqVO.Item::getProductId)); + Map productMap = convertMap(productList, ErpProductDO::getId); + // 1.2 校验仓库存在 + // TODO 芋艿:稍后搞 +// warehouseService.validWarehouseList(convertSet(list, ErpStockMoveSaveReqVO.Item::getWarehouseId)); + // 2. 转化为 ErpStockMoveItemDO 列表 + return convertList(list, o -> BeanUtils.toBean(o, ErpStockMoveItemDO.class, item -> item + .setProductUnitId(productMap.get(item.getProductId()).getUnitId()) + .setTotalPrice(MoneyUtils.priceMultiply(item.getProductPrice(), item.getCount())))); + } + + private void updateStockMoveItemList(Long id, List newList) { + // 第一步,对比新老数据,获得添加、修改、删除的列表 + List oldList = stockMoveItemMapper.selectListByMoveId(id); + List> diffList = diffList(oldList, newList, // id 不同,就认为是不同的记录 + (oldVal, newVal) -> oldVal.getId().equals(newVal.getId())); + + // 第二步,批量添加、修改、删除 + if (CollUtil.isNotEmpty(diffList.get(0))) { + diffList.get(0).forEach(o -> o.setMoveId(id)); + stockMoveItemMapper.insertBatch(diffList.get(0)); + } + if (CollUtil.isNotEmpty(diffList.get(1))) { + stockMoveItemMapper.updateBatch(diffList.get(1)); + } + if (CollUtil.isNotEmpty(diffList.get(2))) { + stockMoveItemMapper.deleteBatchIds(convertList(diffList.get(2), ErpStockMoveItemDO::getId)); + } + } + + @Override + @Transactional(rollbackFor = Exception.class) + public void deleteStockMove(List ids) { + // 1. 校验不处于已审批 + List stockMoves = stockMoveMapper.selectBatchIds(ids); + if (CollUtil.isEmpty(stockMoves)) { + return; + } + stockMoves.forEach(stockMove -> { + if (ErpAuditStatus.APPROVE.getStatus().equals(stockMove.getStatus())) { + throw exception(STOCK_OUT_DELETE_FAIL_APPROVE, stockMove.getNo()); + } + }); + + // 2. 遍历删除,并记录操作日志 + stockMoves.forEach(stockMove -> { + // 2.1 删除出库单 + stockMoveMapper.deleteById(stockMove.getId()); + // 2.2 删除出库单项 + stockMoveItemMapper.deleteByMoveId(stockMove.getId()); + }); + } + + private ErpStockMoveDO validateStockMoveExists(Long id) { + ErpStockMoveDO stockMove = stockMoveMapper.selectById(id); + if (stockMove == null) { + throw exception(STOCK_OUT_NOT_EXISTS); + } + return stockMove; + } + + @Override + public ErpStockMoveDO getStockMove(Long id) { + return stockMoveMapper.selectById(id); + } + + @Override + public PageResult getStockMovePage(ErpStockMovePageReqVO pageReqVO) { + return stockMoveMapper.selectPage(pageReqVO); + } + + // ==================== 出库项 ==================== + + @Override + public List getStockMoveItemListByMoveId(Long inId) { + return stockMoveItemMapper.selectListByMoveId(inId); + } + + @Override + public List getStockMoveItemListByMoveIds(Collection inIds) { + if (CollUtil.isEmpty(inIds)) { + return Collections.emptyList(); + } + return stockMoveItemMapper.selectListByMoveIds(inIds); + } + +} \ No newline at end of file From 573a79cad6851cc7b8a36bad99824d3242339238 Mon Sep 17 00:00:00 2001 From: YunaiV Date: Wed, 7 Feb 2024 20:47:26 +0800 Subject: [PATCH 087/119] =?UTF-8?q?=E2=9C=A8=20ERP=EF=BC=9A=E5=A2=9E?= =?UTF-8?q?=E5=8A=A0=20ERP=20=E8=B0=83=E6=8B=A8=E5=8D=95=E7=9A=84=E5=AE=9E?= =?UTF-8?q?=E7=8E=B0=20100%?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../module/erp/enums/ErrorCodeConstants.java | 12 ++++- .../stock/ErpStockRecordBizTypeEnum.java | 5 ++ .../stock/vo/move/ErpStockMoveSaveReqVO.java | 9 ++++ .../dal/dataobject/stock/ErpStockMoveDO.java | 4 +- .../dataobject/stock/ErpStockMoveItemDO.java | 4 +- .../erp/dal/redis/no/ErpNoRedisDAO.java | 5 ++ .../service/stock/ErpStockInServiceImpl.java | 2 +- .../stock/ErpStockMoveServiceImpl.java | 50 +++++++++---------- .../service/stock/ErpStockOutServiceImpl.java | 4 +- .../service/stock/ErpStockServiceImpl.java | 13 ++++- 10 files changed, 72 insertions(+), 36 deletions(-) diff --git a/yudao-module-erp/yudao-module-erp-api/src/main/java/cn/iocoder/yudao/module/erp/enums/ErrorCodeConstants.java b/yudao-module-erp/yudao-module-erp-api/src/main/java/cn/iocoder/yudao/module/erp/enums/ErrorCodeConstants.java index 1926b34ac..ace58df2a 100644 --- a/yudao-module-erp/yudao-module-erp-api/src/main/java/cn/iocoder/yudao/module/erp/enums/ErrorCodeConstants.java +++ b/yudao-module-erp/yudao-module-erp-api/src/main/java/cn/iocoder/yudao/module/erp/enums/ErrorCodeConstants.java @@ -40,9 +40,17 @@ public interface ErrorCodeConstants { ErrorCode STOCK_OUT_NO_EXISTS = new ErrorCode(1_030_402_004, "生成出库单失败,请重新提交"); ErrorCode STOCK_OUT_UPDATE_FAIL_APPROVE = new ErrorCode(1_030_402_005, "其它出库单({})已审核,无法修改"); + // ========== ERP 其它出库单 1-030-403-000 ========== + ErrorCode STOCK_MOVE_NOT_EXISTS = new ErrorCode(1_030_402_000, "库存调拨单不存在"); + ErrorCode STOCK_MOVE_DELETE_FAIL_APPROVE = new ErrorCode(1_030_402_001, "库存调拨单({})已审核,无法删除"); + ErrorCode STOCK_MOVE_PROCESS_FAIL = new ErrorCode(1_030_402_002, "反审核失败,只有已审核的出库单才能反审核"); + ErrorCode STOCK_MOVE_APPROVE_FAIL = new ErrorCode(1_030_402_003, "审核失败,只有未审核的出库单才能审核"); + ErrorCode STOCK_MOVE_NO_EXISTS = new ErrorCode(1_030_402_004, "生成调拨号失败,请重新提交"); + ErrorCode STOCK_MOVE_UPDATE_FAIL_APPROVE = new ErrorCode(1_030_402_005, "库存调拨单({})已审核,无法修改"); + // ========== ERP 产品库存 1-030-403-000 ========== - ErrorCode STOCK_COUNT_NEGATIVE = new ErrorCode(1_030_403_000, "操作失败,产品当前库存:{},小于变更数量:{}"); - ErrorCode STOCK_COUNT_NEGATIVE2 = new ErrorCode(1_030_403_000, "操作失败,库存不足"); + ErrorCode STOCK_COUNT_NEGATIVE = new ErrorCode(1_030_403_000, "操作失败,产品({})所在仓库({})的库存:{},小于变更数量:{}"); + ErrorCode STOCK_COUNT_NEGATIVE2 = new ErrorCode(1_030_403_000, "操作失败,产品({})所在仓库({})的库存不足"); // ========== ERP 产品 1-030-500-000 ========== ErrorCode PRODUCT_NOT_EXISTS = new ErrorCode(1_030_500_000, "产品不存在"); diff --git a/yudao-module-erp/yudao-module-erp-api/src/main/java/cn/iocoder/yudao/module/erp/enums/stock/ErpStockRecordBizTypeEnum.java b/yudao-module-erp/yudao-module-erp-api/src/main/java/cn/iocoder/yudao/module/erp/enums/stock/ErpStockRecordBizTypeEnum.java index fb16934d9..d56bfa928 100644 --- a/yudao-module-erp/yudao-module-erp-api/src/main/java/cn/iocoder/yudao/module/erp/enums/stock/ErpStockRecordBizTypeEnum.java +++ b/yudao-module-erp/yudao-module-erp-api/src/main/java/cn/iocoder/yudao/module/erp/enums/stock/ErpStockRecordBizTypeEnum.java @@ -20,6 +20,11 @@ public enum ErpStockRecordBizTypeEnum implements IntArrayValuable { OTHER_OUT(20, "其它出库"), OTHER_OUT_CANCEL(21, "其它出库(作废)"), + + MOVE_IN(30, "调拨入库"), + MOVE_IN_CANCEL(31, "调拨入库(作废)"), + MOVE_OUT(32, "调拨出库"), + MOVE_OUT_CANCEL(33, "调拨出库(作废)"), ; public static final int[] ARRAYS = Arrays.stream(values()).mapToInt(ErpStockRecordBizTypeEnum::getType).toArray(); diff --git a/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/controller/admin/stock/vo/move/ErpStockMoveSaveReqVO.java b/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/controller/admin/stock/vo/move/ErpStockMoveSaveReqVO.java index 699d0d2a5..17a431561 100644 --- a/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/controller/admin/stock/vo/move/ErpStockMoveSaveReqVO.java +++ b/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/controller/admin/stock/vo/move/ErpStockMoveSaveReqVO.java @@ -1,7 +1,10 @@ package cn.iocoder.yudao.module.erp.controller.admin.stock.vo.move; +import cn.hutool.core.util.ObjectUtil; +import com.fasterxml.jackson.annotation.JsonIgnore; import io.swagger.v3.oas.annotations.media.Schema; import jakarta.validation.Valid; +import jakarta.validation.constraints.AssertTrue; import jakarta.validation.constraints.NotEmpty; import jakarta.validation.constraints.NotNull; import lombok.Data; @@ -63,6 +66,12 @@ public class ErpStockMoveSaveReqVO { @Schema(description = "备注", example = "随便") private String remark; + @AssertTrue(message = "调出、调仓仓库不能相同") + @JsonIgnore + public boolean isWarehouseValid() { + return ObjectUtil.notEqual(fromWarehouseId, toWarehouseId); + } + } } \ No newline at end of file diff --git a/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/dal/dataobject/stock/ErpStockMoveDO.java b/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/dal/dataobject/stock/ErpStockMoveDO.java index a07c9549d..682b33104 100644 --- a/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/dal/dataobject/stock/ErpStockMoveDO.java +++ b/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/dal/dataobject/stock/ErpStockMoveDO.java @@ -14,8 +14,8 @@ import java.time.LocalDateTime; * * @author 芋道源码 */ -@TableName("erp_stock_in") -@KeySequence("erp_stock_in_seq") // 用于 Oracle、PostgreSQL、Kingbase、DB2、H2 数据库的主键自增。如果是 MySQL 等数据库,可不写。 +@TableName("erp_stock_move") +@KeySequence("erp_stock_move_seq") // 用于 Oracle、PostgreSQL、Kingbase、DB2、H2 数据库的主键自增。如果是 MySQL 等数据库,可不写。 @Data @EqualsAndHashCode(callSuper = true) @ToString(callSuper = true) diff --git a/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/dal/dataobject/stock/ErpStockMoveItemDO.java b/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/dal/dataobject/stock/ErpStockMoveItemDO.java index 2e34df0dc..aee203670 100644 --- a/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/dal/dataobject/stock/ErpStockMoveItemDO.java +++ b/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/dal/dataobject/stock/ErpStockMoveItemDO.java @@ -14,8 +14,8 @@ import java.math.BigDecimal; * * @author 芋道源码 */ -@TableName("erp_stock_in_item") -@KeySequence("erp_stock_in_item_seq") // 用于 Oracle、PostgreSQL、Kingbase、DB2、H2 数据库的主键自增。如果是 MySQL 等数据库,可不写。 +@TableName("erp_stock_move_item") +@KeySequence("erp_stock_move_item_seq") // 用于 Oracle、PostgreSQL、Kingbase、DB2、H2 数据库的主键自增。如果是 MySQL 等数据库,可不写。 @Data @EqualsAndHashCode(callSuper = true) @ToString(callSuper = true) diff --git a/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/dal/redis/no/ErpNoRedisDAO.java b/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/dal/redis/no/ErpNoRedisDAO.java index 04d2c25ca..4be18012b 100644 --- a/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/dal/redis/no/ErpNoRedisDAO.java +++ b/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/dal/redis/no/ErpNoRedisDAO.java @@ -28,6 +28,11 @@ public class ErpNoRedisDAO { */ public static final String STOCK_OUT_NO_PREFIX = "QCKD"; + /** + * 库存调拨 {@link cn.iocoder.yudao.module.erp.dal.dataobject.stock.ErpStockMoveDO} + */ + public static final String STOCK_MOVE_NO_PREFIX = "QCDB"; + @Resource private StringRedisTemplate stringRedisTemplate; diff --git a/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/service/stock/ErpStockInServiceImpl.java b/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/service/stock/ErpStockInServiceImpl.java index 9e9280fcd..22b08b266 100644 --- a/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/service/stock/ErpStockInServiceImpl.java +++ b/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/service/stock/ErpStockInServiceImpl.java @@ -66,7 +66,7 @@ public class ErpStockInServiceImpl implements ErpStockInService { List stockInItems = validateStockInItems(createReqVO.getItems()); // 1.2 校验供应商 supplierService.validateSupplier(createReqVO.getSupplierId()); - // 1.3 + // 1.3 生成入库单号,并校验唯一性 String no = noRedisDAO.generate(ErpNoRedisDAO.STOCK_IN_NO_PREFIX); if (stockInMapper.selectByNo(no) != null) { throw exception(STOCK_IN_NO_EXISTS); diff --git a/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/service/stock/ErpStockMoveServiceImpl.java b/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/service/stock/ErpStockMoveServiceImpl.java index 603ddfcaa..089c98e72 100644 --- a/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/service/stock/ErpStockMoveServiceImpl.java +++ b/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/service/stock/ErpStockMoveServiceImpl.java @@ -15,7 +15,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.enums.stock.ErpStockRecordBizTypeEnum; import cn.iocoder.yudao.module.erp.service.product.ErpProductService; -import cn.iocoder.yudao.module.erp.service.sale.ErpCustomerService; +import cn.iocoder.yudao.module.erp.service.stock.bo.ErpStockRecordCreateReqBO; import jakarta.annotation.Resource; import org.springframework.stereotype.Service; import org.springframework.transaction.annotation.Transactional; @@ -26,6 +26,7 @@ import java.util.Collection; import java.util.Collections; import java.util.List; import java.util.Map; +import java.util.stream.Stream; import static cn.iocoder.yudao.framework.common.exception.util.ServiceExceptionUtil.exception; import static cn.iocoder.yudao.framework.common.util.collection.CollectionUtils.*; @@ -55,8 +56,6 @@ public class ErpStockMoveServiceImpl implements ErpStockMoveService { @Resource private ErpWarehouseService warehouseService; @Resource - private ErpCustomerService customerService; - @Resource private ErpStockRecordService stockRecordService; @Override @@ -64,12 +63,10 @@ public class ErpStockMoveServiceImpl implements ErpStockMoveService { public Long createStockMove(ErpStockMoveSaveReqVO createReqVO) { // 1.1 校验出库项的有效性 List stockMoveItems = validateStockMoveItems(createReqVO.getItems()); - // 1.2 校验客户 - customerService.validateCustomer(createReqVO.getCustomerId()); - // 1.3 - String no = noRedisDAO.generate(ErpNoRedisDAO.STOCK_OUT_NO_PREFIX); + // 1.2 生成调拨单号,并校验唯一性 + String no = noRedisDAO.generate(ErpNoRedisDAO.STOCK_MOVE_NO_PREFIX); if (stockMoveMapper.selectByNo(no) != null) { - throw exception(STOCK_OUT_NO_EXISTS); + throw exception(STOCK_MOVE_NO_EXISTS); } // 2.1 插入出库单 @@ -90,11 +87,9 @@ public class ErpStockMoveServiceImpl implements ErpStockMoveService { // 1.1 校验存在 ErpStockMoveDO stockMove = validateStockMoveExists(updateReqVO.getId()); if (ErpAuditStatus.APPROVE.getStatus().equals(stockMove.getStatus())) { - throw exception(STOCK_OUT_UPDATE_FAIL_APPROVE, stockMove.getNo()); + throw exception(STOCK_MOVE_UPDATE_FAIL_APPROVE, stockMove.getNo()); } - // 1.2 校验客户 - customerService.validateCustomer(updateReqVO.getCustomerId()); - // 1.3 校验出库项的有效性 + // 1.2 校验出库项的有效性 List stockMoveItems = validateStockMoveItems(updateReqVO.getItems()); // 2.1 更新出库单 @@ -114,26 +109,31 @@ public class ErpStockMoveServiceImpl implements ErpStockMoveService { ErpStockMoveDO stockMove = validateStockMoveExists(id); // 1.2 校验状态 if (stockMove.getStatus().equals(status)) { - throw exception(approve ? STOCK_OUT_APPROVE_FAIL : STOCK_OUT_PROCESS_FAIL); + throw exception(approve ? STOCK_MOVE_APPROVE_FAIL : STOCK_MOVE_PROCESS_FAIL); } // 2. 更新状态 int updateCount = stockMoveMapper.updateByIdAndStatus(id, stockMove.getStatus(), new ErpStockMoveDO().setStatus(status)); if (updateCount == 0) { - throw exception(approve ? STOCK_OUT_APPROVE_FAIL : STOCK_OUT_PROCESS_FAIL); + throw exception(approve ? STOCK_MOVE_APPROVE_FAIL : STOCK_MOVE_PROCESS_FAIL); } // 3. 变更库存 List stockMoveItems = stockMoveItemMapper.selectListByMoveId(id); - Integer bizType = approve ? ErpStockRecordBizTypeEnum.OTHER_OUT.getType() - : ErpStockRecordBizTypeEnum.OTHER_OUT_CANCEL.getType(); + Integer fromBizType = approve ? ErpStockRecordBizTypeEnum.MOVE_OUT.getType() + : ErpStockRecordBizTypeEnum.MOVE_OUT_CANCEL.getType(); + Integer toBizType = approve ? ErpStockRecordBizTypeEnum.MOVE_IN.getType() + : ErpStockRecordBizTypeEnum.MOVE_IN_CANCEL.getType(); stockMoveItems.forEach(stockMoveItem -> { - BigDecimal count = approve ? stockMoveItem.getCount() : stockMoveItem.getCount().negate(); - // TODO 芋艿:稍后搞 -// stockRecordService.createStockRecord(new ErpStockRecordCreateReqBO( -// stockMoveItem.getProductId(), stockMoveItem.getWarehouseId(), count, -// bizType, stockMoveItem.getMoveId(), stockMoveItem.getId(), stockMove.getNo())); + BigDecimal fromCount = approve ? stockMoveItem.getCount().negate() : stockMoveItem.getCount(); + BigDecimal toCount = approve ? stockMoveItem.getCount() : stockMoveItem.getCount().negate(); + stockRecordService.createStockRecord(new ErpStockRecordCreateReqBO( + stockMoveItem.getProductId(), stockMoveItem.getFromWarehouseId(), fromCount, + fromBizType, stockMoveItem.getMoveId(), stockMoveItem.getId(), stockMove.getNo())); + stockRecordService.createStockRecord(new ErpStockRecordCreateReqBO( + stockMoveItem.getProductId(), stockMoveItem.getToWarehouseId(), toCount, + toBizType, stockMoveItem.getMoveId(), stockMoveItem.getId(), stockMove.getNo())); }); } @@ -143,8 +143,8 @@ public class ErpStockMoveServiceImpl implements ErpStockMoveService { convertSet(list, ErpStockMoveSaveReqVO.Item::getProductId)); Map productMap = convertMap(productList, ErpProductDO::getId); // 1.2 校验仓库存在 - // TODO 芋艿:稍后搞 -// warehouseService.validWarehouseList(convertSet(list, ErpStockMoveSaveReqVO.Item::getWarehouseId)); + warehouseService.validWarehouseList(convertSetByFlatMap(list, + item -> Stream.of(item.getFromWarehouseId(), item.getToWarehouseId()))); // 2. 转化为 ErpStockMoveItemDO 列表 return convertList(list, o -> BeanUtils.toBean(o, ErpStockMoveItemDO.class, item -> item .setProductUnitId(productMap.get(item.getProductId()).getUnitId()) @@ -180,7 +180,7 @@ public class ErpStockMoveServiceImpl implements ErpStockMoveService { } stockMoves.forEach(stockMove -> { if (ErpAuditStatus.APPROVE.getStatus().equals(stockMove.getStatus())) { - throw exception(STOCK_OUT_DELETE_FAIL_APPROVE, stockMove.getNo()); + throw exception(STOCK_MOVE_DELETE_FAIL_APPROVE, stockMove.getNo()); } }); @@ -196,7 +196,7 @@ public class ErpStockMoveServiceImpl implements ErpStockMoveService { private ErpStockMoveDO validateStockMoveExists(Long id) { ErpStockMoveDO stockMove = stockMoveMapper.selectById(id); if (stockMove == null) { - throw exception(STOCK_OUT_NOT_EXISTS); + throw exception(STOCK_MOVE_NOT_EXISTS); } return stockMove; } diff --git a/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/service/stock/ErpStockOutServiceImpl.java b/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/service/stock/ErpStockOutServiceImpl.java index 36b5a30d8..8117ef36a 100644 --- a/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/service/stock/ErpStockOutServiceImpl.java +++ b/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/service/stock/ErpStockOutServiceImpl.java @@ -67,7 +67,7 @@ public class ErpStockOutServiceImpl implements ErpStockOutService { List stockOutItems = validateStockOutItems(createReqVO.getItems()); // 1.2 校验客户 customerService.validateCustomer(createReqVO.getCustomerId()); - // 1.3 + // 1.3 生成出库单号,并校验唯一性 String no = noRedisDAO.generate(ErpNoRedisDAO.STOCK_OUT_NO_PREFIX); if (stockOutMapper.selectByNo(no) != null) { throw exception(STOCK_OUT_NO_EXISTS); @@ -130,7 +130,7 @@ public class ErpStockOutServiceImpl implements ErpStockOutService { Integer bizType = approve ? ErpStockRecordBizTypeEnum.OTHER_OUT.getType() : ErpStockRecordBizTypeEnum.OTHER_OUT_CANCEL.getType(); stockOutItems.forEach(stockOutItem -> { - BigDecimal count = approve ? stockOutItem.getCount() : stockOutItem.getCount().negate(); + BigDecimal count = approve ? stockOutItem.getCount().negate() : stockOutItem.getCount(); stockRecordService.createStockRecord(new ErpStockRecordCreateReqBO( stockOutItem.getProductId(), stockOutItem.getWarehouseId(), count, bizType, stockOutItem.getOutId(), stockOutItem.getId(), stockOut.getNo())); diff --git a/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/service/stock/ErpStockServiceImpl.java b/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/service/stock/ErpStockServiceImpl.java index c930cff36..91495acda 100644 --- a/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/service/stock/ErpStockServiceImpl.java +++ b/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/service/stock/ErpStockServiceImpl.java @@ -4,6 +4,7 @@ import cn.iocoder.yudao.framework.common.pojo.PageResult; import cn.iocoder.yudao.module.erp.controller.admin.stock.vo.stock.ErpStockPageReqVO; import cn.iocoder.yudao.module.erp.dal.dataobject.stock.ErpStockDO; import cn.iocoder.yudao.module.erp.dal.mysql.stock.ErpStockMapper; +import cn.iocoder.yudao.module.erp.service.product.ErpProductService; import jakarta.annotation.Resource; import org.springframework.stereotype.Service; import org.springframework.validation.annotation.Validated; @@ -30,6 +31,11 @@ public class ErpStockServiceImpl implements ErpStockService { */ private static final Boolean NEGATIVE_STOCK_COUNT_ENABLE = false; + @Resource + private ErpProductService productService; + @Resource + private ErpWarehouseService warehouseService; + @Resource private ErpStockMapper stockMapper; @@ -58,13 +64,16 @@ public class ErpStockServiceImpl implements ErpStockService { } // 1.2 校验库存是否充足 if (!NEGATIVE_STOCK_COUNT_ENABLE && stock.getCount().add(count).compareTo(BigDecimal.ZERO) < 0) { - throw exception(STOCK_COUNT_NEGATIVE, stock.getCount(), count); + throw exception(STOCK_COUNT_NEGATIVE, productService.getProduct(productId).getName(), + warehouseService.getWarehouse(warehouseId).getName(), stock.getCount(), count); } // 2. 库存变更 int updateCount = stockMapper.updateCountIncrement(stock.getId(), count, NEGATIVE_STOCK_COUNT_ENABLE); if (updateCount == 0) { - throw exception(STOCK_COUNT_NEGATIVE2); // 此时不好去查询最新库存,所以直接抛出该提示,不提供具体库存数字 + // 此时不好去查询最新库存,所以直接抛出该提示,不提供具体库存数字 + throw exception(STOCK_COUNT_NEGATIVE2, productService.getProduct(productId).getName(), + warehouseService.getWarehouse(warehouseId).getName()); } // 3. 返回最新库存 From 3b612b2e6d7f775bceaf5e72e68fca54220bed2f Mon Sep 17 00:00:00 2001 From: dhb52 Date: Wed, 7 Feb 2024 23:53:48 +0800 Subject: [PATCH 088/119] =?UTF-8?q?feat:=20=E5=BE=85=E5=9B=9E=E6=AC=BE?= =?UTF-8?q?=E6=8F=90=E9=86=92,=E5=8D=B3=E5=B0=86=E5=88=B0=E6=9C=9F?= =?UTF-8?q?=E7=9A=84=E5=90=88=E5=90=8C,=E5=BE=85=E5=AE=A1=E6=A0=B8?= =?UTF-8?q?=E5=9B=9E=E6=AC=BE?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../contract/vo/CrmContractPageReqVO.java | 6 +++++ .../vo/plan/CrmReceivablePlanPageReqVO.java | 10 +++++++ .../vo/receivable/CrmReceivablePageReqVO.java | 3 +++ .../dal/mysql/contract/CrmContractMapper.java | 27 ++++++++++++++++--- .../mysql/receivable/CrmReceivableMapper.java | 1 + .../receivable/CrmReceivablePlanMapper.java | 23 ++++++++++++++++ 6 files changed, 66 insertions(+), 4 deletions(-) diff --git a/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/controller/admin/contract/vo/CrmContractPageReqVO.java b/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/controller/admin/contract/vo/CrmContractPageReqVO.java index 2e14f1566..70529198a 100644 --- a/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/controller/admin/contract/vo/CrmContractPageReqVO.java +++ b/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/controller/admin/contract/vo/CrmContractPageReqVO.java @@ -14,6 +14,9 @@ import lombok.ToString; @ToString(callSuper = true) public class CrmContractPageReqVO extends PageParam { + public static final Integer EXPIRY_TYPE_ABOUT_TO_EXPIRE = 1; + public static final Integer EXPIRY_TYPE_EXPIRED = 2; + @Schema(description = "合同编号", example = "XYZ008") private String no; @@ -33,4 +36,7 @@ public class CrmContractPageReqVO extends PageParam { @Schema(description = "审批状态", example = "20") private Integer auditStatus; + @Schema(description = "过期类型", example = "1") + private Integer expiryType; // 过期类型,为 null 时则表示全部 + } diff --git a/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/controller/admin/receivable/vo/plan/CrmReceivablePlanPageReqVO.java b/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/controller/admin/receivable/vo/plan/CrmReceivablePlanPageReqVO.java index f86aa346d..a041fa030 100644 --- a/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/controller/admin/receivable/vo/plan/CrmReceivablePlanPageReqVO.java +++ b/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/controller/admin/receivable/vo/plan/CrmReceivablePlanPageReqVO.java @@ -14,6 +14,13 @@ import lombok.ToString; @ToString(callSuper = true) public class CrmReceivablePlanPageReqVO extends PageParam { + // 待回款 + public final static Integer REMIND_NEEDED = 1; + // 已逾期 + public final static Integer REMIND_EXPIRED = 2; + // 已回款 + public final static Integer REMIND_RECEIVED = 3; + @Schema(description = "客户编号", example = "18026") private Long customerId; @@ -25,4 +32,7 @@ public class CrmReceivablePlanPageReqVO extends PageParam { @InEnum(CrmSceneTypeEnum.class) private Integer sceneType; // 场景类型,为 null 时则表示全部 + @Schema(description = "提醒类型", example = "1") + private Integer remindType; // 提醒类型,为 null 时则表示全部 + } diff --git a/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/controller/admin/receivable/vo/receivable/CrmReceivablePageReqVO.java b/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/controller/admin/receivable/vo/receivable/CrmReceivablePageReqVO.java index 1bca32fa3..d47ca83f0 100644 --- a/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/controller/admin/receivable/vo/receivable/CrmReceivablePageReqVO.java +++ b/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/controller/admin/receivable/vo/receivable/CrmReceivablePageReqVO.java @@ -27,4 +27,7 @@ public class CrmReceivablePageReqVO extends PageParam { @InEnum(CrmSceneTypeEnum.class) private Integer sceneType; // 场景类型,为 null 时则表示全部 + @Schema(description = "审批状态", example = "20") + private Integer auditStatus; + } diff --git a/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/dal/mysql/contract/CrmContractMapper.java b/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/dal/mysql/contract/CrmContractMapper.java index e7c56a622..d553962ee 100644 --- a/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/dal/mysql/contract/CrmContractMapper.java +++ b/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/dal/mysql/contract/CrmContractMapper.java @@ -1,16 +1,19 @@ package cn.iocoder.yudao.module.crm.dal.mysql.contract; +import cn.hutool.core.date.LocalDateTimeUtil; import cn.iocoder.yudao.framework.common.pojo.PageResult; import cn.iocoder.yudao.framework.mybatis.core.mapper.BaseMapperX; import cn.iocoder.yudao.framework.mybatis.core.query.LambdaQueryWrapperX; import cn.iocoder.yudao.framework.mybatis.core.query.MPJLambdaWrapperX; import cn.iocoder.yudao.module.crm.controller.admin.contract.vo.CrmContractPageReqVO; import cn.iocoder.yudao.module.crm.dal.dataobject.contract.CrmContractDO; +import cn.iocoder.yudao.module.crm.enums.common.CrmAuditStatusEnum; import cn.iocoder.yudao.module.crm.enums.common.CrmBizTypeEnum; import cn.iocoder.yudao.module.crm.util.CrmQueryWrapperUtils; import com.baomidou.mybatisplus.core.conditions.update.LambdaUpdateWrapper; import org.apache.ibatis.annotations.Mapper; +import java.time.LocalDateTime; import java.util.Collection; import java.util.List; @@ -39,19 +42,35 @@ public interface CrmContractMapper extends BaseMapperX { } default PageResult selectPage(CrmContractPageReqVO pageReqVO, Long userId) { - MPJLambdaWrapperX mpjLambdaWrapperX = new MPJLambdaWrapperX<>(); + MPJLambdaWrapperX query = new MPJLambdaWrapperX<>(); // 拼接数据权限的查询条件 - CrmQueryWrapperUtils.appendPermissionCondition(mpjLambdaWrapperX, CrmBizTypeEnum.CRM_CONTRACT.getType(), + CrmQueryWrapperUtils.appendPermissionCondition(query, CrmBizTypeEnum.CRM_CONTRACT.getType(), CrmContractDO::getId, userId, pageReqVO.getSceneType(), Boolean.FALSE); // 拼接自身的查询条件 - mpjLambdaWrapperX.selectAll(CrmContractDO.class) + query.selectAll(CrmContractDO.class) .likeIfPresent(CrmContractDO::getNo, pageReqVO.getNo()) .likeIfPresent(CrmContractDO::getName, pageReqVO.getName()) .eqIfPresent(CrmContractDO::getCustomerId, pageReqVO.getCustomerId()) .eqIfPresent(CrmContractDO::getBusinessId, pageReqVO.getBusinessId()) .eqIfPresent(CrmContractDO::getAuditStatus, pageReqVO.getAuditStatus()) .orderByDesc(CrmContractDO::getId); - return selectJoinPage(pageReqVO, CrmContractDO.class, mpjLambdaWrapperX); + + // Backlog: 即将到期的合同 + LocalDateTime beginOfToday = LocalDateTimeUtil.beginOfDay(LocalDateTime.now()); + LocalDateTime endOfToday = LocalDateTimeUtil.endOfDay(LocalDateTime.now()); + if (CrmContractPageReqVO.EXPIRY_TYPE_ABOUT_TO_EXPIRE.equals(pageReqVO.getExpiryType())) { + // 即将到期 + // TODO: @芋艿 需要配置 提前提醒天数 + int REMIND_DAYS = 20; + query.eq(CrmContractDO::getAuditStatus, CrmAuditStatusEnum.APPROVE.getStatus()) + .between(CrmContractDO::getEndTime, beginOfToday, endOfToday.plusDays(REMIND_DAYS)); + } else if (CrmContractPageReqVO.EXPIRY_TYPE_EXPIRED.equals(pageReqVO.getExpiryType())) { + // 已到期 + query.eq(CrmContractDO::getAuditStatus, CrmAuditStatusEnum.APPROVE.getStatus()) + .lt(CrmContractDO::getEndTime, endOfToday); + } + + return selectJoinPage(pageReqVO, CrmContractDO.class, query); } default List selectBatchIds(Collection ids, Long userId) { diff --git a/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/dal/mysql/receivable/CrmReceivableMapper.java b/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/dal/mysql/receivable/CrmReceivableMapper.java index 3ad8009f0..28b2298ec 100644 --- a/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/dal/mysql/receivable/CrmReceivableMapper.java +++ b/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/dal/mysql/receivable/CrmReceivableMapper.java @@ -45,6 +45,7 @@ public interface CrmReceivableMapper extends BaseMapperX { query.selectAll(CrmReceivableDO.class) .eqIfPresent(CrmReceivableDO::getNo, pageReqVO.getNo()) .eqIfPresent(CrmReceivableDO::getPlanId, pageReqVO.getPlanId()) + .eqIfPresent(CrmReceivableDO::getAuditStatus, pageReqVO.getAuditStatus()) .orderByDesc(CrmReceivableDO::getId); return selectJoinPage(pageReqVO, CrmReceivableDO.class, query); } diff --git a/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/dal/mysql/receivable/CrmReceivablePlanMapper.java b/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/dal/mysql/receivable/CrmReceivablePlanMapper.java index eb6587174..618a95750 100644 --- a/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/dal/mysql/receivable/CrmReceivablePlanMapper.java +++ b/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/dal/mysql/receivable/CrmReceivablePlanMapper.java @@ -1,5 +1,6 @@ package cn.iocoder.yudao.module.crm.dal.mysql.receivable; +import cn.hutool.core.date.LocalDateTimeUtil; import cn.iocoder.yudao.framework.common.pojo.PageResult; import cn.iocoder.yudao.framework.mybatis.core.mapper.BaseMapperX; import cn.iocoder.yudao.framework.mybatis.core.query.LambdaQueryWrapperX; @@ -11,6 +12,7 @@ import cn.iocoder.yudao.module.crm.util.CrmQueryWrapperUtils; import com.baomidou.mybatisplus.core.conditions.update.LambdaUpdateWrapper; import org.apache.ibatis.annotations.Mapper; +import java.time.LocalDateTime; import java.util.Collection; import java.util.List; @@ -45,6 +47,27 @@ public interface CrmReceivablePlanMapper extends BaseMapperX Date: Thu, 8 Feb 2024 06:59:19 +0800 Subject: [PATCH 089/119] =?UTF-8?q?=E2=9C=A8=20ERP=EF=BC=9A=E5=A2=9E?= =?UTF-8?q?=E5=8A=A0=20ERP=20=E7=9B=98=E7=82=B9=E5=8D=95=E7=9A=84=E5=AE=9E?= =?UTF-8?q?=E7=8E=B0=20100%?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../module/erp/enums/ErrorCodeConstants.java | 20 +- .../stock/ErpStockRecordBizTypeEnum.java | 5 + .../admin/stock/ErpStockCheckController.java | 149 +++++++++++ .../admin/stock/ErpStockMoveController.java | 3 - .../vo/check/ErpStockCheckPageReqVO.java | 45 ++++ .../stock/vo/check/ErpStockCheckRespVO.java | 111 +++++++++ .../vo/check/ErpStockCheckSaveReqVO.java | 69 ++++++ .../dal/dataobject/stock/ErpStockCheckDO.java | 63 +++++ .../dataobject/stock/ErpStockCheckItemDO.java | 83 +++++++ .../mysql/stock/ErpStockCheckItemMapper.java | 30 +++ .../dal/mysql/stock/ErpStockCheckMapper.java | 46 ++++ .../erp/dal/redis/no/ErpNoRedisDAO.java | 5 + .../service/stock/ErpStockCheckService.java | 84 +++++++ .../stock/ErpStockCheckServiceImpl.java | 232 ++++++++++++++++++ .../service/stock/ErpStockInServiceImpl.java | 6 +- .../stock/ErpStockMoveServiceImpl.java | 10 +- .../service/stock/ErpStockOutServiceImpl.java | 13 +- 17 files changed, 952 insertions(+), 22 deletions(-) create mode 100644 yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/controller/admin/stock/ErpStockCheckController.java create mode 100644 yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/controller/admin/stock/vo/check/ErpStockCheckPageReqVO.java create mode 100644 yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/controller/admin/stock/vo/check/ErpStockCheckRespVO.java create mode 100644 yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/controller/admin/stock/vo/check/ErpStockCheckSaveReqVO.java create mode 100644 yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/dal/dataobject/stock/ErpStockCheckDO.java create mode 100644 yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/dal/dataobject/stock/ErpStockCheckItemDO.java create mode 100644 yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/dal/mysql/stock/ErpStockCheckItemMapper.java create mode 100644 yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/dal/mysql/stock/ErpStockCheckMapper.java create mode 100644 yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/service/stock/ErpStockCheckService.java create mode 100644 yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/service/stock/ErpStockCheckServiceImpl.java diff --git a/yudao-module-erp/yudao-module-erp-api/src/main/java/cn/iocoder/yudao/module/erp/enums/ErrorCodeConstants.java b/yudao-module-erp/yudao-module-erp-api/src/main/java/cn/iocoder/yudao/module/erp/enums/ErrorCodeConstants.java index ace58df2a..7c04c19f1 100644 --- a/yudao-module-erp/yudao-module-erp-api/src/main/java/cn/iocoder/yudao/module/erp/enums/ErrorCodeConstants.java +++ b/yudao-module-erp/yudao-module-erp-api/src/main/java/cn/iocoder/yudao/module/erp/enums/ErrorCodeConstants.java @@ -40,17 +40,25 @@ public interface ErrorCodeConstants { ErrorCode STOCK_OUT_NO_EXISTS = new ErrorCode(1_030_402_004, "生成出库单失败,请重新提交"); ErrorCode STOCK_OUT_UPDATE_FAIL_APPROVE = new ErrorCode(1_030_402_005, "其它出库单({})已审核,无法修改"); - // ========== ERP 其它出库单 1-030-403-000 ========== + // ========== ERP 库存调拨单 1-030-403-000 ========== ErrorCode STOCK_MOVE_NOT_EXISTS = new ErrorCode(1_030_402_000, "库存调拨单不存在"); ErrorCode STOCK_MOVE_DELETE_FAIL_APPROVE = new ErrorCode(1_030_402_001, "库存调拨单({})已审核,无法删除"); - ErrorCode STOCK_MOVE_PROCESS_FAIL = new ErrorCode(1_030_402_002, "反审核失败,只有已审核的出库单才能反审核"); - ErrorCode STOCK_MOVE_APPROVE_FAIL = new ErrorCode(1_030_402_003, "审核失败,只有未审核的出库单才能审核"); + ErrorCode STOCK_MOVE_PROCESS_FAIL = new ErrorCode(1_030_402_002, "反审核失败,只有已审核的调拨单才能反审核"); + ErrorCode STOCK_MOVE_APPROVE_FAIL = new ErrorCode(1_030_402_003, "审核失败,只有未审核的调拨单才能审核"); ErrorCode STOCK_MOVE_NO_EXISTS = new ErrorCode(1_030_402_004, "生成调拨号失败,请重新提交"); ErrorCode STOCK_MOVE_UPDATE_FAIL_APPROVE = new ErrorCode(1_030_402_005, "库存调拨单({})已审核,无法修改"); - // ========== ERP 产品库存 1-030-403-000 ========== - ErrorCode STOCK_COUNT_NEGATIVE = new ErrorCode(1_030_403_000, "操作失败,产品({})所在仓库({})的库存:{},小于变更数量:{}"); - ErrorCode STOCK_COUNT_NEGATIVE2 = new ErrorCode(1_030_403_000, "操作失败,产品({})所在仓库({})的库存不足"); + // ========== ERP 库存盘点单 1-030-403-000 ========== + ErrorCode STOCK_CHECK_NOT_EXISTS = new ErrorCode(1_030_403_000, "库存盘点单不存在"); + ErrorCode STOCK_CHECK_DELETE_FAIL_APPROVE = new ErrorCode(1_030_403_001, "库存盘点单({})已审核,无法删除"); + ErrorCode STOCK_CHECK_PROCESS_FAIL = new ErrorCode(1_030_403_002, "反审核失败,只有已审核的盘点单才能反审核"); + ErrorCode STOCK_CHECK_APPROVE_FAIL = new ErrorCode(1_030_403_003, "审核失败,只有未审核的盘点单才能审核"); + ErrorCode STOCK_CHECK_NO_EXISTS = new ErrorCode(1_030_403_004, "生成盘点号失败,请重新提交"); + ErrorCode STOCK_CHECK_UPDATE_FAIL_APPROVE = new ErrorCode(1_030_403_005, "库存盘点单({})已审核,无法修改"); + + // ========== ERP 产品库存 1-030-404-000 ========== + ErrorCode STOCK_COUNT_NEGATIVE = new ErrorCode(1_030_404_000, "操作失败,产品({})所在仓库({})的库存:{},小于变更数量:{}"); + ErrorCode STOCK_COUNT_NEGATIVE2 = new ErrorCode(1_030_404_001, "操作失败,产品({})所在仓库({})的库存不足"); // ========== ERP 产品 1-030-500-000 ========== ErrorCode PRODUCT_NOT_EXISTS = new ErrorCode(1_030_500_000, "产品不存在"); diff --git a/yudao-module-erp/yudao-module-erp-api/src/main/java/cn/iocoder/yudao/module/erp/enums/stock/ErpStockRecordBizTypeEnum.java b/yudao-module-erp/yudao-module-erp-api/src/main/java/cn/iocoder/yudao/module/erp/enums/stock/ErpStockRecordBizTypeEnum.java index d56bfa928..31129a2e4 100644 --- a/yudao-module-erp/yudao-module-erp-api/src/main/java/cn/iocoder/yudao/module/erp/enums/stock/ErpStockRecordBizTypeEnum.java +++ b/yudao-module-erp/yudao-module-erp-api/src/main/java/cn/iocoder/yudao/module/erp/enums/stock/ErpStockRecordBizTypeEnum.java @@ -25,6 +25,11 @@ public enum ErpStockRecordBizTypeEnum implements IntArrayValuable { MOVE_IN_CANCEL(31, "调拨入库(作废)"), MOVE_OUT(32, "调拨出库"), MOVE_OUT_CANCEL(33, "调拨出库(作废)"), + + CHECK_MORE_IN(40, "盘盈入库"), + CHECK_MORE_IN_CANCEL(41, "盘盈入库(作废)"), + CHECK_LESS_OUT(42, "盘亏出库"), + CHECK_LESS_OUT_CANCEL(43, "盘亏出库(作废)"), ; public static final int[] ARRAYS = Arrays.stream(values()).mapToInt(ErpStockRecordBizTypeEnum::getType).toArray(); diff --git a/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/controller/admin/stock/ErpStockCheckController.java b/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/controller/admin/stock/ErpStockCheckController.java new file mode 100644 index 000000000..c2abc6ec9 --- /dev/null +++ b/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/controller/admin/stock/ErpStockCheckController.java @@ -0,0 +1,149 @@ +package cn.iocoder.yudao.module.erp.controller.admin.stock; + +import cn.hutool.core.collection.CollUtil; +import cn.iocoder.yudao.framework.common.pojo.CommonResult; +import cn.iocoder.yudao.framework.common.pojo.PageParam; +import cn.iocoder.yudao.framework.common.pojo.PageResult; +import cn.iocoder.yudao.framework.common.util.collection.MapUtils; +import cn.iocoder.yudao.framework.common.util.object.BeanUtils; +import cn.iocoder.yudao.framework.excel.core.util.ExcelUtils; +import cn.iocoder.yudao.framework.operatelog.core.annotations.OperateLog; +import cn.iocoder.yudao.module.erp.controller.admin.product.vo.product.ErpProductRespVO; +import cn.iocoder.yudao.module.erp.controller.admin.stock.vo.check.ErpStockCheckPageReqVO; +import cn.iocoder.yudao.module.erp.controller.admin.stock.vo.check.ErpStockCheckRespVO; +import cn.iocoder.yudao.module.erp.controller.admin.stock.vo.check.ErpStockCheckSaveReqVO; +import cn.iocoder.yudao.module.erp.dal.dataobject.stock.ErpStockCheckDO; +import cn.iocoder.yudao.module.erp.dal.dataobject.stock.ErpStockCheckItemDO; +import cn.iocoder.yudao.module.erp.service.product.ErpProductService; +import cn.iocoder.yudao.module.erp.service.stock.ErpStockCheckService; +import cn.iocoder.yudao.module.system.api.user.AdminUserApi; +import cn.iocoder.yudao.module.system.api.user.dto.AdminUserRespDTO; +import io.swagger.v3.oas.annotations.Operation; +import io.swagger.v3.oas.annotations.Parameter; +import io.swagger.v3.oas.annotations.tags.Tag; +import jakarta.annotation.Resource; +import jakarta.servlet.http.HttpServletResponse; +import jakarta.validation.Valid; +import org.springframework.security.access.prepost.PreAuthorize; +import org.springframework.validation.annotation.Validated; +import org.springframework.web.bind.annotation.*; + +import java.io.IOException; +import java.util.List; +import java.util.Map; + +import static cn.iocoder.yudao.framework.common.pojo.CommonResult.success; +import static cn.iocoder.yudao.framework.common.util.collection.CollectionUtils.convertMultiMap; +import static cn.iocoder.yudao.framework.common.util.collection.CollectionUtils.convertSet; +import static cn.iocoder.yudao.framework.operatelog.core.enums.OperateTypeEnum.EXPORT; + +@Tag(name = "管理后台 - ERP 库存调拨单") +@RestController +@RequestMapping("/erp/stock-check") +@Validated +public class ErpStockCheckController { + + @Resource + private ErpStockCheckService stockCheckService; + @Resource + private ErpProductService productService; + + @Resource + private AdminUserApi adminUserApi; + + @PostMapping("/create") + @Operation(summary = "创建库存调拨单") + @PreAuthorize("@ss.hasPermission('erp:stock-check:create')") + public CommonResult createStockCheck(@Valid @RequestBody ErpStockCheckSaveReqVO createReqVO) { + return success(stockCheckService.createStockCheck(createReqVO)); + } + + @PutMapping("/update") + @Operation(summary = "更新库存调拨单") + @PreAuthorize("@ss.hasPermission('erp:stock-check:update')") + public CommonResult updateStockCheck(@Valid @RequestBody ErpStockCheckSaveReqVO updateReqVO) { + stockCheckService.updateStockCheck(updateReqVO); + return success(true); + } + + @PutMapping("/update-status") + @Operation(summary = "更新库存调拨单的状态") + @PreAuthorize("@ss.hasPermission('erp:stock-check:update-status')") + public CommonResult updateStockCheckStatus(@RequestParam("id") Long id, + @RequestParam("status") Integer status) { + stockCheckService.updateStockCheckStatus(id, status); + return success(true); + } + + @DeleteMapping("/delete") + @Operation(summary = "删除库存调拨单") + @Parameter(name = "ids", description = "编号数组", required = true) + @PreAuthorize("@ss.hasPermission('erp:stock-check:delete')") + public CommonResult deleteStockCheck(@RequestParam("ids") List ids) { + stockCheckService.deleteStockCheck(ids); + return success(true); + } + + @GetMapping("/get") + @Operation(summary = "获得库存调拨单") + @Parameter(name = "id", description = "编号", required = true, example = "1024") + @PreAuthorize("@ss.hasPermission('erp:stock-check:query')") + public CommonResult getStockCheck(@RequestParam("id") Long id) { + ErpStockCheckDO stockCheck = stockCheckService.getStockCheck(id); + if (stockCheck == null) { + return success(null); + } + List stockCheckItemList = stockCheckService.getStockCheckItemListByCheckId(id); + Map productMap = productService.getProductVOMap( + convertSet(stockCheckItemList, ErpStockCheckItemDO::getProductId)); + return success(BeanUtils.toBean(stockCheck, ErpStockCheckRespVO.class, stockCheckVO -> + stockCheckVO.setItems(BeanUtils.toBean(stockCheckItemList, ErpStockCheckRespVO.Item.class, item -> + MapUtils.findAndThen(productMap, item.getProductId(), product -> item.setProductName(product.getName()) + .setProductBarCode(product.getBarCode()).setProductUnitName(product.getUnitName())))))); + } + + @GetMapping("/page") + @Operation(summary = "获得库存调拨单分页") + @PreAuthorize("@ss.hasPermission('erp:stock-check:query')") + public CommonResult> getStockCheckPage(@Valid ErpStockCheckPageReqVO pageReqVO) { + PageResult pageResult = stockCheckService.getStockCheckPage(pageReqVO); + return success(buildStockCheckVOPageResult(pageResult)); + } + + @GetMapping("/export-excel") + @Operation(summary = "导出库存调拨单 Excel") + @PreAuthorize("@ss.hasPermission('erp:stock-check:export')") + @OperateLog(type = EXPORT) + public void exportStockCheckExcel(@Valid ErpStockCheckPageReqVO pageReqVO, + HttpServletResponse response) throws IOException { + pageReqVO.setPageSize(PageParam.PAGE_SIZE_NONE); + List list = buildStockCheckVOPageResult(stockCheckService.getStockCheckPage(pageReqVO)).getList(); + // 导出 Excel + ExcelUtils.write(response, "库存调拨单.xls", "数据", ErpStockCheckRespVO.class, list); + } + + private PageResult buildStockCheckVOPageResult(PageResult pageResult) { + if (CollUtil.isEmpty(pageResult.getList())) { + return PageResult.empty(pageResult.getTotal()); + } + // 1.1 出库项 + List stockCheckItemList = stockCheckService.getStockCheckItemListByCheckIds( + convertSet(pageResult.getList(), ErpStockCheckDO::getId)); + Map> stockCheckItemMap = convertMultiMap(stockCheckItemList, ErpStockCheckItemDO::getCheckId); + // 1.2 商品信息 + Map productMap = productService.getProductVOMap( + convertSet(stockCheckItemList, ErpStockCheckItemDO::getProductId)); + // 1.3 管理员信息 + Map userMap = adminUserApi.getUserMap( + convertSet(pageResult.getList(), erpStockRecordDO -> Long.parseLong(erpStockRecordDO.getCreator()))); + // 2. 开始拼接 + return BeanUtils.toBean(pageResult, ErpStockCheckRespVO.class, stockCheck -> { + stockCheck.setItems(BeanUtils.toBean(stockCheckItemMap.get(stockCheck.getId()), ErpStockCheckRespVO.Item.class, + item -> MapUtils.findAndThen(productMap, item.getProductId(), product -> item.setProductName(product.getName()) + .setProductBarCode(product.getBarCode()).setProductUnitName(product.getUnitName())))); + stockCheck.setProductNames(CollUtil.join(stockCheck.getItems(), ",", ErpStockCheckRespVO.Item::getProductName)); + MapUtils.findAndThen(userMap, Long.parseLong(stockCheck.getCreator()), user -> stockCheck.setCreatorName(user.getNickname())); + }); + } + +} \ No newline at end of file diff --git a/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/controller/admin/stock/ErpStockMoveController.java b/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/controller/admin/stock/ErpStockMoveController.java index e39b7bba7..d8c838b61 100644 --- a/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/controller/admin/stock/ErpStockMoveController.java +++ b/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/controller/admin/stock/ErpStockMoveController.java @@ -16,7 +16,6 @@ import cn.iocoder.yudao.module.erp.dal.dataobject.stock.ErpStockDO; import cn.iocoder.yudao.module.erp.dal.dataobject.stock.ErpStockMoveDO; import cn.iocoder.yudao.module.erp.dal.dataobject.stock.ErpStockMoveItemDO; import cn.iocoder.yudao.module.erp.service.product.ErpProductService; -import cn.iocoder.yudao.module.erp.service.sale.ErpCustomerService; import cn.iocoder.yudao.module.erp.service.stock.ErpStockMoveService; import cn.iocoder.yudao.module.erp.service.stock.ErpStockService; import cn.iocoder.yudao.module.system.api.user.AdminUserApi; @@ -53,8 +52,6 @@ public class ErpStockMoveController { private ErpStockService stockService; @Resource private ErpProductService productService; - @Resource - private ErpCustomerService customerService; @Resource private AdminUserApi adminUserApi; diff --git a/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/controller/admin/stock/vo/check/ErpStockCheckPageReqVO.java b/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/controller/admin/stock/vo/check/ErpStockCheckPageReqVO.java new file mode 100644 index 000000000..2bae14c1e --- /dev/null +++ b/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/controller/admin/stock/vo/check/ErpStockCheckPageReqVO.java @@ -0,0 +1,45 @@ +package cn.iocoder.yudao.module.erp.controller.admin.stock.vo.check; + +import cn.iocoder.yudao.framework.common.pojo.PageParam; +import cn.iocoder.yudao.framework.common.validation.InEnum; +import cn.iocoder.yudao.module.erp.enums.ErpAuditStatus; +import io.swagger.v3.oas.annotations.media.Schema; +import lombok.Data; +import lombok.EqualsAndHashCode; +import lombok.ToString; +import org.springframework.format.annotation.DateTimeFormat; + +import java.time.LocalDateTime; + +import static cn.iocoder.yudao.framework.common.util.date.DateUtils.FORMAT_YEAR_MONTH_DAY_HOUR_MINUTE_SECOND; + +@Schema(description = "管理后台 - ERP 库存盘点单分页 Request VO") +@Data +@EqualsAndHashCode(callSuper = true) +@ToString(callSuper = true) +public class ErpStockCheckPageReqVO extends PageParam { + + @Schema(description = "盘点单号", example = "S123") + private String no; + + @Schema(description = "仓库编号", example = "3113") + private Long warehouseId; + + @Schema(description = "盘点时间") + @DateTimeFormat(pattern = FORMAT_YEAR_MONTH_DAY_HOUR_MINUTE_SECOND) + private LocalDateTime[] checkTime; + + @Schema(description = "状态", example = "10") + @InEnum(ErpAuditStatus.class) + private Integer status; + + @Schema(description = "备注", example = "随便") + private String remark; + + @Schema(description = "创建者") + private String creator; + + @Schema(description = "产品编号", example = "1") + private Long productId; + +} \ No newline at end of file diff --git a/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/controller/admin/stock/vo/check/ErpStockCheckRespVO.java b/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/controller/admin/stock/vo/check/ErpStockCheckRespVO.java new file mode 100644 index 000000000..d761516d9 --- /dev/null +++ b/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/controller/admin/stock/vo/check/ErpStockCheckRespVO.java @@ -0,0 +1,111 @@ +package cn.iocoder.yudao.module.erp.controller.admin.stock.vo.check; + +import cn.iocoder.yudao.framework.excel.core.annotations.DictFormat; +import cn.iocoder.yudao.framework.excel.core.convert.DictConvert; +import com.alibaba.excel.annotation.ExcelIgnoreUnannotated; +import com.alibaba.excel.annotation.ExcelProperty; +import io.swagger.v3.oas.annotations.media.Schema; +import jakarta.validation.constraints.NotNull; +import lombok.Data; + +import java.math.BigDecimal; +import java.time.LocalDateTime; +import java.util.List; + +import static cn.iocoder.yudao.module.erp.enums.DictTypeConstants.AUDIT_STATUS; + +@Schema(description = "管理后台 - ERP 库存盘点单 Response VO") +@Data +@ExcelIgnoreUnannotated +public class ErpStockCheckRespVO { + + @Schema(description = "盘点编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "11756") + @ExcelProperty("盘点编号") + private Long id; + + @Schema(description = "盘点单号", requiredMode = Schema.RequiredMode.REQUIRED, example = "S123") + @ExcelProperty("盘点单号") + private String no; + + @Schema(description = "盘点时间", requiredMode = Schema.RequiredMode.REQUIRED) + @ExcelProperty("盘点时间") + private LocalDateTime checkTime; + + @Schema(description = "合计数量", requiredMode = Schema.RequiredMode.REQUIRED, example = "15663") + @ExcelProperty("合计数量") + private BigDecimal totalCount; + + @Schema(description = "合计金额,单位:元", requiredMode = Schema.RequiredMode.REQUIRED, example = "24906") + @ExcelProperty("合计金额") + private BigDecimal totalPrice; + + @Schema(description = "状态", requiredMode = Schema.RequiredMode.REQUIRED, example = "10") + @ExcelProperty(value = "状态", converter = DictConvert.class) + @DictFormat(AUDIT_STATUS) + private Integer status; + + @Schema(description = "备注", example = "随便") + @ExcelProperty("备注") + private String remark; + + @Schema(description = "附件 URL", example = "https://www.iocoder.cn/1.doc") + private String fileUrl; + + @Schema(description = "审核人", example = "芋道") + private String creator; + @Schema(description = "审核人名称", example = "芋道") + private String creatorName; + + @Schema(description = "创建时间", requiredMode = Schema.RequiredMode.REQUIRED) + @ExcelProperty("创建时间") + private LocalDateTime createTime; + + @Schema(description = "盘点项列表", requiredMode = Schema.RequiredMode.REQUIRED) + private List items; + + @Schema(description = "产品信息", requiredMode = Schema.RequiredMode.REQUIRED) + @ExcelProperty("产品信息") + private String productNames; + + @Data + public static class Item { + + @Schema(description = "盘点项编号", example = "11756") + private Long id; + + @Schema(description = "仓库编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "3113") + private Long warehouseId; + + @Schema(description = "产品编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "3113") + private Long productId; + + @Schema(description = "产品单价", requiredMode = Schema.RequiredMode.REQUIRED, example = "100.00") + private BigDecimal productPrice; + + @Schema(description = "账面数量(当前库存)", requiredMode = Schema.RequiredMode.REQUIRED, example = "100.00") + @NotNull(message = "账面数量不能为空") + private BigDecimal stockCount; + + @Schema(description = "实际数量(实际库存)", requiredMode = Schema.RequiredMode.REQUIRED, example = "100.00") + @NotNull(message = "实际数量不能为空") + private BigDecimal actualCount; + + @Schema(description = "盈亏数量", requiredMode = Schema.RequiredMode.REQUIRED, example = "100.00") + @NotNull(message = "盈亏数量不能为空") + private BigDecimal count; + + @Schema(description = "备注", example = "随便") + private String remark; + + // ========== 关联字段 ========== + + @Schema(description = "产品名称", requiredMode = Schema.RequiredMode.REQUIRED, example = "巧克力") + private String productName; + @Schema(description = "产品条码", requiredMode = Schema.RequiredMode.REQUIRED, example = "A9985") + private String productBarCode; + @Schema(description = "产品单位名称", requiredMode = Schema.RequiredMode.REQUIRED, example = "盒") + private String productUnitName; + + } + +} \ No newline at end of file diff --git a/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/controller/admin/stock/vo/check/ErpStockCheckSaveReqVO.java b/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/controller/admin/stock/vo/check/ErpStockCheckSaveReqVO.java new file mode 100644 index 000000000..0af223fb5 --- /dev/null +++ b/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/controller/admin/stock/vo/check/ErpStockCheckSaveReqVO.java @@ -0,0 +1,69 @@ +package cn.iocoder.yudao.module.erp.controller.admin.stock.vo.check; + +import io.swagger.v3.oas.annotations.media.Schema; +import jakarta.validation.Valid; +import jakarta.validation.constraints.NotEmpty; +import jakarta.validation.constraints.NotNull; +import lombok.Data; + +import java.math.BigDecimal; +import java.time.LocalDateTime; +import java.util.List; + +@Schema(description = "管理后台 - ERP 其它出库单新增/修改 Request VO") +@Data +public class ErpStockCheckSaveReqVO { + + @Schema(description = "出库编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "11756") + private Long id; + + @Schema(description = "出库时间", requiredMode = Schema.RequiredMode.REQUIRED) + @NotNull(message = "出库时间不能为空") + private LocalDateTime checkTime; + + @Schema(description = "备注", example = "随便") + private String remark; + + @Schema(description = "附件 URL", example = "https://www.iocoder.cn/1.doc") + private String fileUrl; + + @Schema(description = "出库项列表", requiredMode = Schema.RequiredMode.REQUIRED) + @NotEmpty(message = "出库项列表不能为空") + @Valid + private List items; + + @Data + public static class Item { + + @Schema(description = "出库项编号", example = "11756") + private Long id; + + @Schema(description = "仓库编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "3113") + @NotNull(message = "仓库编号不能为空") + private Long warehouseId; + + @Schema(description = "产品编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "3113") + @NotNull(message = "产品编号不能为空") + private Long productId; + + @Schema(description = "产品单价", example = "100.00") + private BigDecimal productPrice; + + @Schema(description = "账面数量(当前库存)", requiredMode = Schema.RequiredMode.REQUIRED, example = "100.00") + @NotNull(message = "账面数量不能为空") + private BigDecimal stockCount; + + @Schema(description = "实际数量(实际库存)", requiredMode = Schema.RequiredMode.REQUIRED, example = "100.00") + @NotNull(message = "实际数量不能为空") + private BigDecimal actualCount; + + @Schema(description = "盈亏数量", requiredMode = Schema.RequiredMode.REQUIRED, example = "100.00") + @NotNull(message = "盈亏数量不能为空") + private BigDecimal count; + + @Schema(description = "备注", example = "随便") + private String remark; + + } + +} \ No newline at end of file diff --git a/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/dal/dataobject/stock/ErpStockCheckDO.java b/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/dal/dataobject/stock/ErpStockCheckDO.java new file mode 100644 index 000000000..e9168275f --- /dev/null +++ b/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/dal/dataobject/stock/ErpStockCheckDO.java @@ -0,0 +1,63 @@ +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.*; + +import java.math.BigDecimal; +import java.time.LocalDateTime; + +/** + * ERP 库存盘点单 DO + * + * @author 芋道源码 + */ +@TableName("erp_stock_check") +@KeySequence("erp_stock_check_seq") // 用于 Oracle、PostgreSQL、Kingbase、DB2、H2 数据库的主键自增。如果是 MySQL 等数据库,可不写。 +@Data +@EqualsAndHashCode(callSuper = true) +@ToString(callSuper = true) +@Builder +@NoArgsConstructor +@AllArgsConstructor +public class ErpStockCheckDO extends BaseDO { + + /** + * 盘点编号 + */ + @TableId + private Long id; + /** + * 盘点单号 + */ + private String no; + /** + * 盘点时间 + */ + private LocalDateTime checkTime; + /** + * 合计数量 + */ + private BigDecimal totalCount; + /** + * 合计金额,单位:元 + */ + private BigDecimal totalPrice; + /** + * 状态 + * + * 枚举 {@link cn.iocoder.yudao.module.erp.enums.ErpAuditStatus} + */ + private Integer status; + /** + * 备注 + */ + private String remark; + /** + * 附件 URL + */ + private String fileUrl; + +} \ No newline at end of file diff --git a/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/dal/dataobject/stock/ErpStockCheckItemDO.java b/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/dal/dataobject/stock/ErpStockCheckItemDO.java new file mode 100644 index 000000000..c3c4dbf99 --- /dev/null +++ b/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/dal/dataobject/stock/ErpStockCheckItemDO.java @@ -0,0 +1,83 @@ +package cn.iocoder.yudao.module.erp.dal.dataobject.stock; + +import cn.iocoder.yudao.framework.mybatis.core.dataobject.BaseDO; +import cn.iocoder.yudao.module.erp.dal.dataobject.product.ErpProductDO; +import com.baomidou.mybatisplus.annotation.KeySequence; +import com.baomidou.mybatisplus.annotation.TableId; +import com.baomidou.mybatisplus.annotation.TableName; +import lombok.*; + +import java.math.BigDecimal; + +/** + * ERP 库存盘点单项 DO + * + * @author 芋道源码 + */ +@TableName("erp_stock_check_item") +@KeySequence("erp_stock_check_item_seq") // 用于 Oracle、PostgreSQL、Kingbase、DB2、H2 数据库的主键自增。如果是 MySQL 等数据库,可不写。 +@Data +@EqualsAndHashCode(callSuper = true) +@ToString(callSuper = true) +@Builder +@NoArgsConstructor +@AllArgsConstructor +public class ErpStockCheckItemDO extends BaseDO { + + /** + * 盘点项编号 + */ + @TableId + private Long id; + /** + * 盘点编号 + * + * 关联 {@link ErpStockCheckDO#getId()} + */ + private Long checkId; + /** + * 仓库编号 + * + * 关联 {@link ErpWarehouseDO#getId()} + */ + private Long warehouseId; + /** + * 产品编号 + * + * 关联 {@link ErpProductDO#getId()} + */ + private Long productId; + /** + * 产品单位编号 + * + * 冗余 {@link ErpProductDO#getUnitId()} + */ + private Long productUnitId; + /** + * 产品单价 + */ + private BigDecimal productPrice; + /** + * 账面数量(当前库存) + */ + private BigDecimal stockCount; + /** + * 实际数量(实际库存) + */ + private BigDecimal actualCount; + /** + * 盈亏数量 + * + * count = stockCount - actualCount + */ + private BigDecimal count; + /** + * 合计金额,单位:元 + */ + private BigDecimal totalPrice; + /** + * 备注 + */ + private String remark; + +} \ No newline at end of file diff --git a/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/dal/mysql/stock/ErpStockCheckItemMapper.java b/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/dal/mysql/stock/ErpStockCheckItemMapper.java new file mode 100644 index 000000000..ae13f9f96 --- /dev/null +++ b/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/dal/mysql/stock/ErpStockCheckItemMapper.java @@ -0,0 +1,30 @@ +package cn.iocoder.yudao.module.erp.dal.mysql.stock; + +import cn.iocoder.yudao.framework.mybatis.core.mapper.BaseMapperX; +import cn.iocoder.yudao.module.erp.dal.dataobject.stock.ErpStockCheckItemDO; +import org.apache.ibatis.annotations.Mapper; + +import java.util.Collection; +import java.util.List; + +/** + * ERP 库存盘点单项 Mapper + * + * @author 芋道源码 + */ +@Mapper +public interface ErpStockCheckItemMapper extends BaseMapperX { + + default List selectListByCheckId(Long checkId) { + return selectList(ErpStockCheckItemDO::getCheckId, checkId); + } + + default List selectListByCheckIds(Collection checkIds) { + return selectList(ErpStockCheckItemDO::getCheckId, checkIds); + } + + default int deleteByCheckId(Long checkId) { + return delete(ErpStockCheckItemDO::getCheckId, checkId); + } + +} \ No newline at end of file diff --git a/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/dal/mysql/stock/ErpStockCheckMapper.java b/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/dal/mysql/stock/ErpStockCheckMapper.java new file mode 100644 index 000000000..3328f39b2 --- /dev/null +++ b/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/dal/mysql/stock/ErpStockCheckMapper.java @@ -0,0 +1,46 @@ +package cn.iocoder.yudao.module.erp.dal.mysql.stock; + +import cn.iocoder.yudao.framework.common.pojo.PageResult; +import cn.iocoder.yudao.framework.mybatis.core.mapper.BaseMapperX; +import cn.iocoder.yudao.framework.mybatis.core.query.MPJLambdaWrapperX; +import cn.iocoder.yudao.module.erp.controller.admin.stock.vo.check.ErpStockCheckPageReqVO; +import cn.iocoder.yudao.module.erp.dal.dataobject.stock.ErpStockCheckDO; +import cn.iocoder.yudao.module.erp.dal.dataobject.stock.ErpStockCheckItemDO; +import com.baomidou.mybatisplus.core.conditions.update.LambdaUpdateWrapper; +import org.apache.ibatis.annotations.Mapper; + +/** + * ERP 库存调拨单 Mapper + * + * @author 芋道源码 + */ +@Mapper +public interface ErpStockCheckMapper extends BaseMapperX { + + default PageResult selectPage(ErpStockCheckPageReqVO reqVO) { + MPJLambdaWrapperX query = new MPJLambdaWrapperX() + .eqIfPresent(ErpStockCheckDO::getNo, reqVO.getNo()) + .betweenIfPresent(ErpStockCheckDO::getCheckTime, reqVO.getCheckTime()) + .eqIfPresent(ErpStockCheckDO::getStatus, reqVO.getStatus()) + .likeIfPresent(ErpStockCheckDO::getRemark, reqVO.getRemark()) + .eqIfPresent(ErpStockCheckDO::getCreator, reqVO.getCreator()) + .orderByDesc(ErpStockCheckDO::getId); + if (reqVO.getWarehouseId() != null || reqVO.getProductId() != null) { + query.leftJoin(ErpStockCheckItemDO.class, ErpStockCheckItemDO::getCheckId, ErpStockCheckDO::getId) + .eq(reqVO.getWarehouseId() != null, ErpStockCheckItemDO::getWarehouseId, reqVO.getWarehouseId()) + .eq(reqVO.getProductId() != null, ErpStockCheckItemDO::getProductId, reqVO.getProductId()) + .groupBy(ErpStockCheckDO::getId); // 避免 1 对多查询,产生相同的 1 + } + return selectJoinPage(reqVO, ErpStockCheckDO.class, query); + } + + default int updateByIdAndStatus(Long id, Integer status, ErpStockCheckDO updateObj) { + return update(updateObj, new LambdaUpdateWrapper() + .eq(ErpStockCheckDO::getId, id).eq(ErpStockCheckDO::getStatus, status)); + } + + default ErpStockCheckDO selectByNo(String no) { + return selectOne(ErpStockCheckDO::getNo, no); + } + +} \ No newline at end of file diff --git a/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/dal/redis/no/ErpNoRedisDAO.java b/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/dal/redis/no/ErpNoRedisDAO.java index 4be18012b..bd2612db1 100644 --- a/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/dal/redis/no/ErpNoRedisDAO.java +++ b/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/dal/redis/no/ErpNoRedisDAO.java @@ -33,6 +33,11 @@ public class ErpNoRedisDAO { */ public static final String STOCK_MOVE_NO_PREFIX = "QCDB"; + /** + * 库存盘点 {@link cn.iocoder.yudao.module.erp.dal.dataobject.stock.ErpStockCheckDO} + */ + public static final String STOCK_CHECK_NO_PREFIX = "QCPD"; + @Resource private StringRedisTemplate stringRedisTemplate; diff --git a/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/service/stock/ErpStockCheckService.java b/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/service/stock/ErpStockCheckService.java new file mode 100644 index 000000000..2f8a0f9ee --- /dev/null +++ b/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/service/stock/ErpStockCheckService.java @@ -0,0 +1,84 @@ +package cn.iocoder.yudao.module.erp.service.stock; + +import cn.iocoder.yudao.framework.common.pojo.PageResult; +import cn.iocoder.yudao.module.erp.controller.admin.stock.vo.check.ErpStockCheckPageReqVO; +import cn.iocoder.yudao.module.erp.controller.admin.stock.vo.check.ErpStockCheckSaveReqVO; +import cn.iocoder.yudao.module.erp.dal.dataobject.stock.ErpStockCheckDO; +import cn.iocoder.yudao.module.erp.dal.dataobject.stock.ErpStockCheckItemDO; +import jakarta.validation.Valid; + +import java.util.Collection; +import java.util.List; + +/** + * ERP 库存盘点单 Service 接口 + * + * @author 芋道源码 + */ +public interface ErpStockCheckService { + + /** + * 创建库存盘点单 + * + * @param createReqVO 创建信息 + * @return 编号 + */ + Long createStockCheck(@Valid ErpStockCheckSaveReqVO createReqVO); + + /** + * 更新库存盘点单 + * + * @param updateReqVO 更新信息 + */ + void updateStockCheck(@Valid ErpStockCheckSaveReqVO updateReqVO); + + /** + * 更新库存盘点单的状态 + * + * @param id 编号 + * @param status 状态 + */ + void updateStockCheckStatus(Long id, Integer status); + + /** + * 删除库存盘点单 + * + * @param ids 编号数组 + */ + void deleteStockCheck(List ids); + + /** + * 获得库存盘点单 + * + * @param id 编号 + * @return 库存盘点单 + */ + ErpStockCheckDO getStockCheck(Long id); + + /** + * 获得库存盘点单分页 + * + * @param pageReqVO 分页查询 + * @return 库存盘点单分页 + */ + PageResult getStockCheckPage(ErpStockCheckPageReqVO pageReqVO); + + // ==================== 盘点项 ==================== + + /** + * 获得库存盘点单项列表 + * + * @param checkId 盘点编号 + * @return 库存盘点单项列表 + */ + List getStockCheckItemListByCheckId(Long checkId); + + /** + * 获得库存盘点单项 List + * + * @param checkIds 盘点编号数组 + * @return 库存盘点单项 List + */ + List getStockCheckItemListByCheckIds(Collection checkIds); + +} \ No newline at end of file diff --git a/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/service/stock/ErpStockCheckServiceImpl.java b/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/service/stock/ErpStockCheckServiceImpl.java new file mode 100644 index 000000000..49aca94d3 --- /dev/null +++ b/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/service/stock/ErpStockCheckServiceImpl.java @@ -0,0 +1,232 @@ +package cn.iocoder.yudao.module.erp.service.stock; + +import cn.hutool.core.collection.CollUtil; +import cn.iocoder.yudao.framework.common.pojo.PageResult; +import cn.iocoder.yudao.framework.common.util.number.MoneyUtils; +import cn.iocoder.yudao.framework.common.util.object.BeanUtils; +import cn.iocoder.yudao.module.erp.controller.admin.stock.vo.check.ErpStockCheckPageReqVO; +import cn.iocoder.yudao.module.erp.controller.admin.stock.vo.check.ErpStockCheckSaveReqVO; +import cn.iocoder.yudao.module.erp.dal.dataobject.product.ErpProductDO; +import cn.iocoder.yudao.module.erp.dal.dataobject.stock.ErpStockCheckDO; +import cn.iocoder.yudao.module.erp.dal.dataobject.stock.ErpStockCheckItemDO; +import cn.iocoder.yudao.module.erp.dal.mysql.stock.ErpStockCheckItemMapper; +import cn.iocoder.yudao.module.erp.dal.mysql.stock.ErpStockCheckMapper; +import cn.iocoder.yudao.module.erp.dal.redis.no.ErpNoRedisDAO; +import cn.iocoder.yudao.module.erp.enums.ErpAuditStatus; +import cn.iocoder.yudao.module.erp.enums.stock.ErpStockRecordBizTypeEnum; +import cn.iocoder.yudao.module.erp.service.product.ErpProductService; +import cn.iocoder.yudao.module.erp.service.stock.bo.ErpStockRecordCreateReqBO; +import jakarta.annotation.Resource; +import org.springframework.stereotype.Service; +import org.springframework.transaction.annotation.Transactional; +import org.springframework.validation.annotation.Validated; + +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.exception.util.ServiceExceptionUtil.exception; +import static cn.iocoder.yudao.framework.common.util.collection.CollectionUtils.*; +import static cn.iocoder.yudao.module.erp.enums.ErrorCodeConstants.*; + +// TODO 芋艿:记录操作日志 + +/** + * ERP 库存盘点单 Service 实现类 + * + * @author 芋道源码 + */ +@Service +@Validated +public class ErpStockCheckServiceImpl implements ErpStockCheckService { + + @Resource + private ErpStockCheckMapper stockCheckMapper; + @Resource + private ErpStockCheckItemMapper stockCheckItemMapper; + + @Resource + private ErpNoRedisDAO noRedisDAO; + + @Resource + private ErpProductService productService; + @Resource + private ErpWarehouseService warehouseService; + @Resource + private ErpStockRecordService stockRecordService; + + @Override + @Transactional(rollbackFor = Exception.class) + public Long createStockCheck(ErpStockCheckSaveReqVO createReqVO) { + // 1.1 校验盘点项的有效性 + List stockCheckItems = validateStockCheckItems(createReqVO.getItems()); + // 1.2 生成盘点单号,并校验唯一性 + String no = noRedisDAO.generate(ErpNoRedisDAO.STOCK_CHECK_NO_PREFIX); + if (stockCheckMapper.selectByNo(no) != null) { + throw exception(STOCK_CHECK_NO_EXISTS); + } + + // 2.1 插入盘点单 + ErpStockCheckDO stockCheck = BeanUtils.toBean(createReqVO, ErpStockCheckDO.class, in -> in + .setNo(no).setStatus(ErpAuditStatus.PROCESS.getStatus()) + .setTotalCount(getSumValue(stockCheckItems, ErpStockCheckItemDO::getCount, BigDecimal::add)) + .setTotalPrice(getSumValue(stockCheckItems, ErpStockCheckItemDO::getTotalPrice, BigDecimal::add, BigDecimal.ZERO))); + stockCheckMapper.insert(stockCheck); + // 2.2 插入盘点单项 + stockCheckItems.forEach(o -> o.setCheckId(stockCheck.getId())); + stockCheckItemMapper.insertBatch(stockCheckItems); + return stockCheck.getId(); + } + + @Override + @Transactional(rollbackFor = Exception.class) + public void updateStockCheck(ErpStockCheckSaveReqVO updateReqVO) { + // 1.1 校验存在 + ErpStockCheckDO stockCheck = validateStockCheckExists(updateReqVO.getId()); + if (ErpAuditStatus.APPROVE.getStatus().equals(stockCheck.getStatus())) { + throw exception(STOCK_CHECK_UPDATE_FAIL_APPROVE, stockCheck.getNo()); + } + // 1.2 校验盘点项的有效性 + List stockCheckItems = validateStockCheckItems(updateReqVO.getItems()); + + // 2.1 更新盘点单 + ErpStockCheckDO updateObj = BeanUtils.toBean(updateReqVO, ErpStockCheckDO.class, in -> in + .setTotalCount(getSumValue(stockCheckItems, ErpStockCheckItemDO::getCount, BigDecimal::add)) + .setTotalPrice(getSumValue(stockCheckItems, ErpStockCheckItemDO::getTotalPrice, BigDecimal::add))); + stockCheckMapper.updateById(updateObj); + // 2.2 更新盘点单项 + updateStockCheckItemList(updateReqVO.getId(), stockCheckItems); + } + + @Override + @Transactional(rollbackFor = Exception.class) + public void updateStockCheckStatus(Long id, Integer status) { + boolean approve = ErpAuditStatus.APPROVE.getStatus().equals(status); + // 1.1 校验存在 + ErpStockCheckDO stockCheck = validateStockCheckExists(id); + // 1.2 校验状态 + if (stockCheck.getStatus().equals(status)) { + throw exception(approve ? STOCK_CHECK_APPROVE_FAIL : STOCK_CHECK_PROCESS_FAIL); + } + + // 2. 更新状态 + int updateCount = stockCheckMapper.updateByIdAndStatus(id, stockCheck.getStatus(), + new ErpStockCheckDO().setStatus(status)); + if (updateCount == 0) { + throw exception(approve ? STOCK_CHECK_APPROVE_FAIL : STOCK_CHECK_PROCESS_FAIL); + } + + // 3. 变更库存 + List stockCheckItems = stockCheckItemMapper.selectListByCheckId(id); + stockCheckItems.forEach(stockCheckItem -> { + // 没有盈亏,不用出入库 + if (stockCheckItem.getCount().compareTo(BigDecimal.ZERO) == 0) { + return; + } + // 10;12;-2() + BigDecimal count = approve ? stockCheckItem.getCount(): stockCheckItem.getCount().negate(); + Integer bizType; + if (approve) { + bizType = count.compareTo(BigDecimal.ZERO) > 0 ? ErpStockRecordBizTypeEnum.CHECK_MORE_IN.getType() + : ErpStockRecordBizTypeEnum.CHECK_LESS_OUT.getType(); + } else { + bizType = count.compareTo(BigDecimal.ZERO) > 0 ? ErpStockRecordBizTypeEnum.CHECK_MORE_IN_CANCEL.getType() + : ErpStockRecordBizTypeEnum.CHECK_LESS_OUT_CANCEL.getType(); + } + stockRecordService.createStockRecord(new ErpStockRecordCreateReqBO( + stockCheckItem.getProductId(), stockCheckItem.getWarehouseId(), count, + bizType, stockCheckItem.getCheckId(), stockCheckItem.getId(), stockCheck.getNo())); + }); + } + + private List validateStockCheckItems(List list) { + // 1.1 校验产品存在 + List productList = productService.validProductList( + convertSet(list, ErpStockCheckSaveReqVO.Item::getProductId)); + Map productMap = convertMap(productList, ErpProductDO::getId); + // 1.2 校验仓库存在 + warehouseService.validWarehouseList(convertSet(list, ErpStockCheckSaveReqVO.Item::getWarehouseId)); + // 2. 转化为 ErpStockCheckItemDO 列表 + return convertList(list, o -> BeanUtils.toBean(o, ErpStockCheckItemDO.class, item -> item + .setProductUnitId(productMap.get(item.getProductId()).getUnitId()) + .setTotalPrice(MoneyUtils.priceMultiply(item.getProductPrice(), item.getCount())))); + } + + private void updateStockCheckItemList(Long id, List newList) { + // 第一步,对比新老数据,获得添加、修改、删除的列表 + List oldList = stockCheckItemMapper.selectListByCheckId(id); + List> diffList = diffList(oldList, newList, // id 不同,就认为是不同的记录 + (oldVal, newVal) -> oldVal.getId().equals(newVal.getId())); + + // 第二步,批量添加、修改、删除 + if (CollUtil.isNotEmpty(diffList.get(0))) { + diffList.get(0).forEach(o -> o.setCheckId(id)); + stockCheckItemMapper.insertBatch(diffList.get(0)); + } + if (CollUtil.isNotEmpty(diffList.get(1))) { + stockCheckItemMapper.updateBatch(diffList.get(1)); + } + if (CollUtil.isNotEmpty(diffList.get(2))) { + stockCheckItemMapper.deleteBatchIds(convertList(diffList.get(2), ErpStockCheckItemDO::getId)); + } + } + + @Override + @Transactional(rollbackFor = Exception.class) + public void deleteStockCheck(List ids) { + // 1. 校验不处于已审批 + List stockChecks = stockCheckMapper.selectBatchIds(ids); + if (CollUtil.isEmpty(stockChecks)) { + return; + } + stockChecks.forEach(stockCheck -> { + if (ErpAuditStatus.APPROVE.getStatus().equals(stockCheck.getStatus())) { + throw exception(STOCK_CHECK_DELETE_FAIL_APPROVE, stockCheck.getNo()); + } + }); + + // 2. 遍历删除,并记录操作日志 + stockChecks.forEach(stockCheck -> { + // 2.1 删除盘点单 + stockCheckMapper.deleteById(stockCheck.getId()); + // 2.2 删除盘点单项 + stockCheckItemMapper.deleteByCheckId(stockCheck.getId()); + }); + } + + private ErpStockCheckDO validateStockCheckExists(Long id) { + ErpStockCheckDO stockCheck = stockCheckMapper.selectById(id); + if (stockCheck == null) { + throw exception(STOCK_CHECK_NOT_EXISTS); + } + return stockCheck; + } + + @Override + public ErpStockCheckDO getStockCheck(Long id) { + return stockCheckMapper.selectById(id); + } + + @Override + public PageResult getStockCheckPage(ErpStockCheckPageReqVO pageReqVO) { + return stockCheckMapper.selectPage(pageReqVO); + } + + // ==================== 盘点项 ==================== + + @Override + public List getStockCheckItemListByCheckId(Long checkId) { + return stockCheckItemMapper.selectListByCheckId(checkId); + } + + @Override + public List getStockCheckItemListByCheckIds(Collection checkIds) { + if (CollUtil.isEmpty(checkIds)) { + return Collections.emptyList(); + } + return stockCheckItemMapper.selectListByCheckIds(checkIds); + } + +} \ No newline at end of file diff --git a/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/service/stock/ErpStockInServiceImpl.java b/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/service/stock/ErpStockInServiceImpl.java index 22b08b266..213fca8b8 100644 --- a/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/service/stock/ErpStockInServiceImpl.java +++ b/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/service/stock/ErpStockInServiceImpl.java @@ -138,10 +138,12 @@ public class ErpStockInServiceImpl implements ErpStockInService { private List validateStockInItems(List list) { // 1.1 校验产品存在 - List productList = productService.validProductList(convertSet(list, ErpStockInSaveReqVO.Item::getProductId)); + List productList = productService.validProductList( + convertSet(list, ErpStockInSaveReqVO.Item::getProductId)); Map productMap = convertMap(productList, ErpProductDO::getId); // 1.2 校验仓库存在 - warehouseService.validWarehouseList(convertSet(list, ErpStockInSaveReqVO.Item::getWarehouseId)); + warehouseService.validWarehouseList(convertSet( + list, ErpStockInSaveReqVO.Item::getWarehouseId)); // 2. 转化为 ErpStockInItemDO 列表 return convertList(list, o -> BeanUtils.toBean(o, ErpStockInItemDO.class, item -> item .setProductUnitId(productMap.get(item.getProductId()).getUnitId()) diff --git a/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/service/stock/ErpStockMoveServiceImpl.java b/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/service/stock/ErpStockMoveServiceImpl.java index 089c98e72..a0d8f79d4 100644 --- a/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/service/stock/ErpStockMoveServiceImpl.java +++ b/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/service/stock/ErpStockMoveServiceImpl.java @@ -214,16 +214,16 @@ public class ErpStockMoveServiceImpl implements ErpStockMoveService { // ==================== 出库项 ==================== @Override - public List getStockMoveItemListByMoveId(Long inId) { - return stockMoveItemMapper.selectListByMoveId(inId); + public List getStockMoveItemListByMoveId(Long moveId) { + return stockMoveItemMapper.selectListByMoveId(moveId); } @Override - public List getStockMoveItemListByMoveIds(Collection inIds) { - if (CollUtil.isEmpty(inIds)) { + public List getStockMoveItemListByMoveIds(Collection moveIds) { + if (CollUtil.isEmpty(moveIds)) { return Collections.emptyList(); } - return stockMoveItemMapper.selectListByMoveIds(inIds); + return stockMoveItemMapper.selectListByMoveIds(moveIds); } } \ No newline at end of file diff --git a/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/service/stock/ErpStockOutServiceImpl.java b/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/service/stock/ErpStockOutServiceImpl.java index 8117ef36a..9fa192465 100644 --- a/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/service/stock/ErpStockOutServiceImpl.java +++ b/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/service/stock/ErpStockOutServiceImpl.java @@ -139,7 +139,8 @@ public class ErpStockOutServiceImpl implements ErpStockOutService { private List validateStockOutItems(List list) { // 1.1 校验产品存在 - List productList = productService.validProductList(convertSet(list, ErpStockOutSaveReqVO.Item::getProductId)); + List productList = productService.validProductList( + convertSet(list, ErpStockOutSaveReqVO.Item::getProductId)); Map productMap = convertMap(productList, ErpProductDO::getId); // 1.2 校验仓库存在 warehouseService.validWarehouseList(convertSet(list, ErpStockOutSaveReqVO.Item::getWarehouseId)); @@ -212,16 +213,16 @@ public class ErpStockOutServiceImpl implements ErpStockOutService { // ==================== 出库项 ==================== @Override - public List getStockOutItemListByOutId(Long inId) { - return stockOutItemMapper.selectListByOutId(inId); + public List getStockOutItemListByOutId(Long outId) { + return stockOutItemMapper.selectListByOutId(outId); } @Override - public List getStockOutItemListByOutIds(Collection inIds) { - if (CollUtil.isEmpty(inIds)) { + public List getStockOutItemListByOutIds(Collection outIds) { + if (CollUtil.isEmpty(outIds)) { return Collections.emptyList(); } - return stockOutItemMapper.selectListByOutIds(inIds); + return stockOutItemMapper.selectListByOutIds(outIds); } } \ No newline at end of file From 9caaa96e5b3678365d11f23b15861070f1d8f259 Mon Sep 17 00:00:00 2001 From: puhui999 Date: Thu, 8 Feb 2024 11:53:23 +0800 Subject: [PATCH 090/119] =?UTF-8?q?CRM-=E5=90=88=E5=90=8C:=20=E6=96=B0?= =?UTF-8?q?=E5=A2=9E=E6=9B=B4=E6=96=B0=E5=90=88=E5=90=8C=E5=95=86=E5=93=81?= =?UTF-8?q?=E5=A6=82=E6=9E=9C=E6=9C=89=E5=85=B3=E8=81=94=E5=95=86=E6=9C=BA?= =?UTF-8?q?=E7=9A=84=E8=AF=9D=E5=88=99=E6=9B=B4=E6=96=B0=E5=95=86=E6=9C=BA?= =?UTF-8?q?=E5=95=86=E5=93=81?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../module/crm/enums/LogRecordConstants.java | 2 + .../admin/contract/CrmContractController.java | 9 ++- .../admin/contract/vo/CrmContractExcelVO.java | 71 ------------------- .../admin/customer/CrmCustomerController.java | 14 +--- .../customer/vo/CrmCustomerImportReqVO.java | 25 +++++++ .../service/business/CrmBusinessService.java | 24 ++++--- .../business/CrmBusinessServiceImpl.java | 19 +++-- .../bo/CrmBusinessUpdateProductReqBO.java | 48 +++++++++++++ .../contract/CrmContractServiceImpl.java | 41 ++++++++++- .../listener/CrmContractResultListener.java | 28 -------- .../service/customer/CrmCustomerService.java | 5 +- .../customer/CrmCustomerServiceImpl.java | 17 ++--- 12 files changed, 163 insertions(+), 140 deletions(-) delete mode 100644 yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/controller/admin/contract/vo/CrmContractExcelVO.java create mode 100644 yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/controller/admin/customer/vo/CrmCustomerImportReqVO.java create mode 100644 yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/service/business/bo/CrmBusinessUpdateProductReqBO.java diff --git a/yudao-module-crm/yudao-module-crm-api/src/main/java/cn/iocoder/yudao/module/crm/enums/LogRecordConstants.java b/yudao-module-crm/yudao-module-crm-api/src/main/java/cn/iocoder/yudao/module/crm/enums/LogRecordConstants.java index d22e87bed..98a66d2c9 100644 --- a/yudao-module-crm/yudao-module-crm-api/src/main/java/cn/iocoder/yudao/module/crm/enums/LogRecordConstants.java +++ b/yudao-module-crm/yudao-module-crm-api/src/main/java/cn/iocoder/yudao/module/crm/enums/LogRecordConstants.java @@ -93,6 +93,8 @@ public interface LogRecordConstants { String CRM_CONTRACT_DELETE_SUCCESS = "删除了合同【{{#contractName}}】"; String CRM_CONTRACT_TRANSFER_SUB_TYPE = "转移合同"; String CRM_CONTRACT_TRANSFER_SUCCESS = "将合同【{{#contract.name}}】的负责人从【{getAdminUserById{#contract.ownerUserId}}】变更为了【{getAdminUserById{#reqVO.newOwnerUserId}}】"; + String CRM_CONTRACT_SUBMIT_SUB_TYPE = "提交合同审批"; + String CRM_CONTRACT_SUBMIT_SUCCESS = "提交合同【{{#contractName}}】审批成功"; // ======================= CRM_PRODUCT 产品 ======================= diff --git a/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/controller/admin/contract/CrmContractController.java b/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/controller/admin/contract/CrmContractController.java index 982ec274c..7574e534a 100644 --- a/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/controller/admin/contract/CrmContractController.java +++ b/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/controller/admin/contract/CrmContractController.java @@ -8,7 +8,10 @@ import cn.iocoder.yudao.framework.common.util.number.NumberUtils; import cn.iocoder.yudao.framework.common.util.object.BeanUtils; import cn.iocoder.yudao.framework.excel.core.util.ExcelUtils; import cn.iocoder.yudao.framework.operatelog.core.annotations.OperateLog; -import cn.iocoder.yudao.module.crm.controller.admin.contract.vo.*; +import cn.iocoder.yudao.module.crm.controller.admin.contract.vo.CrmContractPageReqVO; +import cn.iocoder.yudao.module.crm.controller.admin.contract.vo.CrmContractRespVO; +import cn.iocoder.yudao.module.crm.controller.admin.contract.vo.CrmContractSaveReqVO; +import cn.iocoder.yudao.module.crm.controller.admin.contract.vo.CrmContractTransferReqVO; import cn.iocoder.yudao.module.crm.convert.contract.CrmContractConvert; import cn.iocoder.yudao.module.crm.dal.dataobject.business.CrmBusinessDO; import cn.iocoder.yudao.module.crm.dal.dataobject.contact.CrmContactDO; @@ -127,8 +130,8 @@ public class CrmContractController { HttpServletResponse response) throws IOException { PageResult pageResult = contractService.getContractPage(exportReqVO, getLoginUserId()); // 导出 Excel - ExcelUtils.write(response, "合同.xls", "数据", CrmContractExcelVO.class, - BeanUtils.toBean(pageResult.getList(), CrmContractExcelVO.class)); + ExcelUtils.write(response, "合同.xls", "数据", CrmContractRespVO.class, + BeanUtils.toBean(pageResult.getList(), CrmContractRespVO.class)); } @PutMapping("/transfer") diff --git a/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/controller/admin/contract/vo/CrmContractExcelVO.java b/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/controller/admin/contract/vo/CrmContractExcelVO.java deleted file mode 100644 index 841e56426..000000000 --- a/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/controller/admin/contract/vo/CrmContractExcelVO.java +++ /dev/null @@ -1,71 +0,0 @@ -package cn.iocoder.yudao.module.crm.controller.admin.contract.vo; - -import com.alibaba.excel.annotation.ExcelProperty; -import lombok.Data; - -import java.time.LocalDateTime; - -// TODO @puhui999:合并到 RespVO 里哈; -/** - * CRM 合同 Excel VO - * - * @author dhb52 - */ -@Data -public class CrmContractExcelVO { - - @ExcelProperty("合同编号") - private Long id; - - @ExcelProperty("合同名称") - private String name; - - @ExcelProperty("客户编号") - private Long customerId; - - @ExcelProperty("商机编号") - private Long businessId; - - @ExcelProperty("工作流编号") - private Long processInstanceId; - - @ExcelProperty("下单日期") - private LocalDateTime orderDate; - - @ExcelProperty("负责人的用户编号") - private Long ownerUserId; - - @ExcelProperty("合同编号") - private String no; - - @ExcelProperty("开始时间") - private LocalDateTime startTime; - - @ExcelProperty("结束时间") - private LocalDateTime endTime; - - @ExcelProperty("合同金额") - private Integer price; - - @ExcelProperty("整单折扣") - private Integer discountPercent; - - @ExcelProperty("产品总金额") - private Integer productPrice; - - @ExcelProperty("联系人编号") - private Long contactId; - - @ExcelProperty("公司签约人") - private Long signUserId; - - @ExcelProperty("最后跟进时间") - private LocalDateTime contactLastTime; - - @ExcelProperty("备注") - private String remark; - - @ExcelProperty("创建时间") - private LocalDateTime createTime; - -} diff --git a/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/controller/admin/customer/CrmCustomerController.java b/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/controller/admin/customer/CrmCustomerController.java index ddd2a7f70..da23f2b47 100644 --- a/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/controller/admin/customer/CrmCustomerController.java +++ b/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/controller/admin/customer/CrmCustomerController.java @@ -21,7 +21,6 @@ import cn.iocoder.yudao.module.system.api.user.AdminUserApi; import cn.iocoder.yudao.module.system.api.user.dto.AdminUserRespDTO; import io.swagger.v3.oas.annotations.Operation; import io.swagger.v3.oas.annotations.Parameter; -import io.swagger.v3.oas.annotations.Parameters; import io.swagger.v3.oas.annotations.tags.Tag; import jakarta.annotation.Resource; import jakarta.servlet.http.HttpServletResponse; @@ -30,7 +29,6 @@ import org.mapstruct.ap.internal.util.Collections; import org.springframework.security.access.prepost.PreAuthorize; import org.springframework.validation.annotation.Validated; import org.springframework.web.bind.annotation.*; -import org.springframework.web.multipart.MultipartFile; import java.io.IOException; import java.time.LocalDateTime; @@ -218,19 +216,13 @@ public class CrmCustomerController { ExcelUtils.write(response, "客户导入模板.xls", "客户列表", CrmCustomerImportExcelVO.class, list); } - // TODO @puhui999:updateSupport 要不改成前端必须传递;哈哈哈,代码排版看着有点乱; - // TODO @puhui999:加一个选择负责人;允许空,空就进入公海; @PostMapping("/import") @Operation(summary = "导入客户") - @Parameters({ - @Parameter(name = "file", description = "Excel 文件", required = true), - @Parameter(name = "updateSupport", description = "是否支持更新,默认为 false", example = "true") - }) @PreAuthorize("@ss.hasPermission('system:customer:import')") - public CommonResult importExcel(@RequestParam("file") MultipartFile file, @RequestParam(value = "updateSupport", required = false, defaultValue = "false") Boolean updateSupport) + public CommonResult importExcel(@Valid @RequestBody CrmCustomerImportReqVO importReqVO) throws Exception { - List list = ExcelUtils.read(file, CrmCustomerImportExcelVO.class); - return success(customerService.importCustomerList(list, updateSupport, getLoginUserId())); + List list = ExcelUtils.read(importReqVO.getFile(), CrmCustomerImportExcelVO.class); + return success(customerService.importCustomerList(list, importReqVO)); } @PutMapping("/transfer") diff --git a/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/controller/admin/customer/vo/CrmCustomerImportReqVO.java b/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/controller/admin/customer/vo/CrmCustomerImportReqVO.java new file mode 100644 index 000000000..a396dc50b --- /dev/null +++ b/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/controller/admin/customer/vo/CrmCustomerImportReqVO.java @@ -0,0 +1,25 @@ +package cn.iocoder.yudao.module.crm.controller.admin.customer.vo; + +import io.swagger.v3.oas.annotations.media.Schema; +import jakarta.validation.constraints.NotNull; +import lombok.Builder; +import lombok.Data; +import org.springframework.web.multipart.MultipartFile; + +@Schema(description = "管理后台 - 客户导入 Request VO") +@Data +@Builder +public class CrmCustomerImportReqVO { + + @Schema(description = "Excel 文件", requiredMode = Schema.RequiredMode.REQUIRED) + @NotNull(message = "Excel 文件不能为空") + private MultipartFile file; + + @Schema(description = "是否支持更新", requiredMode = Schema.RequiredMode.REQUIRED, example = "true") + @NotNull(message = "是否支持更新不能为空") + private Boolean updateSupport; + + @Schema(description = "负责人", example = "1") + private Long ownerUserId; // 为 null 则客户进入公海 + +} diff --git a/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/service/business/CrmBusinessService.java b/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/service/business/CrmBusinessService.java index fde5551c1..683070d02 100644 --- a/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/service/business/CrmBusinessService.java +++ b/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/service/business/CrmBusinessService.java @@ -7,6 +7,7 @@ import cn.iocoder.yudao.module.crm.controller.admin.business.vo.business.CrmBusi import cn.iocoder.yudao.module.crm.dal.dataobject.business.CrmBusinessDO; import cn.iocoder.yudao.module.crm.dal.dataobject.contact.CrmContactDO; import cn.iocoder.yudao.module.crm.dal.dataobject.customer.CrmCustomerDO; +import cn.iocoder.yudao.module.crm.service.business.bo.CrmBusinessUpdateProductReqBO; import cn.iocoder.yudao.module.crm.service.followup.bo.CrmUpdateFollowUpReqBO; import jakarta.validation.Valid; @@ -50,6 +51,21 @@ public interface CrmBusinessService { */ void deleteBusiness(Long id); + /** + * 商机转移 + * + * @param reqVO 请求 + * @param userId 用户编号 + */ + void transferBusiness(CrmBusinessTransferReqVO reqVO, Long userId); + + /** + * 更新商机关联商品 + * + * @param updateProductReqBO 请求 + */ + void updateBusinessProduct(CrmBusinessUpdateProductReqBO updateProductReqBO); + /** * 获得商机 * @@ -105,14 +121,6 @@ public interface CrmBusinessService { */ PageResult getBusinessPageByContact(CrmBusinessPageReqVO pageReqVO); - /** - * 商机转移 - * - * @param reqVO 请求 - * @param userId 用户编号 - */ - void transferBusiness(CrmBusinessTransferReqVO reqVO, Long userId); - /** * 获取关联客户的商机数量 * diff --git a/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/service/business/CrmBusinessServiceImpl.java b/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/service/business/CrmBusinessServiceImpl.java index 7de0ca424..5f80e5337 100644 --- a/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/service/business/CrmBusinessServiceImpl.java +++ b/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/service/business/CrmBusinessServiceImpl.java @@ -20,6 +20,7 @@ import cn.iocoder.yudao.module.crm.dal.mysql.business.CrmBusinessProductMapper; import cn.iocoder.yudao.module.crm.enums.common.CrmBizTypeEnum; import cn.iocoder.yudao.module.crm.enums.permission.CrmPermissionLevelEnum; import cn.iocoder.yudao.module.crm.framework.permission.core.annotations.CrmPermission; +import cn.iocoder.yudao.module.crm.service.business.bo.CrmBusinessUpdateProductReqBO; import cn.iocoder.yudao.module.crm.service.contact.CrmContactBusinessService; import cn.iocoder.yudao.module.crm.service.contract.CrmContractService; import cn.iocoder.yudao.module.crm.service.followup.bo.CrmUpdateFollowUpReqBO; @@ -80,7 +81,7 @@ public class CrmBusinessServiceImpl implements CrmBusinessService { businessMapper.insert(business); // 1.2 插入商机关联商品 if (CollUtil.isNotEmpty(createReqVO.getProductItems())) { // 如果有的话 - List productList = convertBusinessProductList(createReqVO, business.getId()); + List productList = convertBusinessProductList(createReqVO.getProductItems(), business.getId()); businessProductMapper.insertBatch(productList); // 更新合同商品总金额 businessMapper.updateById(new CrmBusinessDO().setId(business.getId()).setProductPrice( @@ -120,7 +121,7 @@ public class CrmBusinessServiceImpl implements CrmBusinessService { CrmBusinessDO updateObj = BeanUtils.toBean(updateReqVO, CrmBusinessDO.class); businessMapper.updateById(updateObj); // 2.2 更新商机关联商品 - List productList = convertBusinessProductList(updateReqVO, updateObj.getId()); + List productList = convertBusinessProductList(updateReqVO.getProductItems(), updateObj.getId()); updateBusinessProduct(productList, updateObj.getId()); // TODO @商机待定:如果状态发生变化,插入商机状态变更记录表 @@ -174,15 +175,15 @@ public class CrmBusinessServiceImpl implements CrmBusinessService { } } - private List convertBusinessProductList(CrmBusinessSaveReqVO reqVO, Long businessId) { + private List convertBusinessProductList(List productItems, Long businessId) { // 校验商品存在 - Set productIds = convertSet(reqVO.getProductItems(), CrmBusinessSaveReqVO.CrmBusinessProductItem::getId); + Set productIds = convertSet(productItems, CrmBusinessSaveReqVO.CrmBusinessProductItem::getId); List productList = productService.getProductList(productIds); if (CollUtil.isEmpty(productIds) || productList.size() != productIds.size()) { throw exception(PRODUCT_NOT_EXISTS); } Map productMap = convertMap(productList, CrmProductDO::getId); - return convertList(reqVO.getProductItems(), productItem -> { + return convertList(productItems, productItem -> { CrmProductDO product = productMap.get(productItem.getId()); return BeanUtils.toBean(product, CrmBusinessProductDO.class) .setId(null).setProductId(productItem.getId()).setBusinessId(businessId) @@ -231,6 +232,14 @@ public class CrmBusinessServiceImpl implements CrmBusinessService { LogRecordContext.putVariable("business", business); } + @Override + public void updateBusinessProduct(CrmBusinessUpdateProductReqBO updateProductReqBO) { + // 更新商机关联商品 + List productList = convertBusinessProductList( + BeanUtils.toBean(updateProductReqBO.getProductItems(), CrmBusinessSaveReqVO.CrmBusinessProductItem.class), updateProductReqBO.getId()); + updateBusinessProduct(productList, updateProductReqBO.getId()); + } + //======================= 查询相关 ======================= @Override diff --git a/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/service/business/bo/CrmBusinessUpdateProductReqBO.java b/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/service/business/bo/CrmBusinessUpdateProductReqBO.java new file mode 100644 index 000000000..4291df262 --- /dev/null +++ b/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/service/business/bo/CrmBusinessUpdateProductReqBO.java @@ -0,0 +1,48 @@ +package cn.iocoder.yudao.module.crm.service.business.bo; + +import io.swagger.v3.oas.annotations.media.Schema; +import jakarta.validation.constraints.NotEmpty; +import jakarta.validation.constraints.NotNull; +import lombok.AllArgsConstructor; +import lombok.Data; +import lombok.NoArgsConstructor; + +import java.util.List; + +/** + * 更新商机商品 Update Req BO + * + * @author HUIHUI + */ +@Data +public class CrmBusinessUpdateProductReqBO { + + /** + * 商机编号 + */ + @NotNull(message = "商机编号不能为空") + private Long id; + + @NotEmpty(message = "产品列表不能为空") + private List productItems; + + @Schema(description = "产品列表") + @Data + @NoArgsConstructor + @AllArgsConstructor + public static class CrmBusinessProductItem { + + @Schema(description = "产品编号", example = "20529") + @NotNull(message = "产品编号不能为空") + private Long id; + + @Schema(description = "产品数量", requiredMode = Schema.RequiredMode.REQUIRED, example = "8911") + @NotNull(message = "产品数量不能为空") + private Integer count; + + @Schema(description = "产品折扣") + private Integer discountPercent; + + } + +} diff --git a/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/service/contract/CrmContractServiceImpl.java b/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/service/contract/CrmContractServiceImpl.java index 0cf9065e4..fbf736699 100644 --- a/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/service/contract/CrmContractServiceImpl.java +++ b/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/service/contract/CrmContractServiceImpl.java @@ -11,6 +11,7 @@ import cn.iocoder.yudao.framework.common.util.object.ObjectUtils; import cn.iocoder.yudao.module.bpm.api.listener.dto.BpmResultListenerRespDTO; import cn.iocoder.yudao.module.bpm.api.task.BpmProcessInstanceApi; import cn.iocoder.yudao.module.bpm.api.task.dto.BpmProcessInstanceCreateReqDTO; +import cn.iocoder.yudao.module.bpm.enums.task.BpmProcessInstanceResultEnum; import cn.iocoder.yudao.module.crm.controller.admin.contract.vo.CrmContractPageReqVO; import cn.iocoder.yudao.module.crm.controller.admin.contract.vo.CrmContractSaveReqVO; import cn.iocoder.yudao.module.crm.controller.admin.contract.vo.CrmContractTransferReqVO; @@ -25,6 +26,7 @@ import cn.iocoder.yudao.module.crm.enums.common.CrmBizTypeEnum; import cn.iocoder.yudao.module.crm.enums.permission.CrmPermissionLevelEnum; import cn.iocoder.yudao.module.crm.framework.permission.core.annotations.CrmPermission; import cn.iocoder.yudao.module.crm.service.business.CrmBusinessService; +import cn.iocoder.yudao.module.crm.service.business.bo.CrmBusinessUpdateProductReqBO; import cn.iocoder.yudao.module.crm.service.customer.CrmCustomerService; import cn.iocoder.yudao.module.crm.service.followup.bo.CrmUpdateFollowUpReqBO; import cn.iocoder.yudao.module.crm.service.permission.CrmPermissionService; @@ -96,7 +98,11 @@ public class CrmContractServiceImpl implements CrmContractService { // 更新合同商品总金额 contractMapper.updateById(new CrmContractDO().setId(contract.getId()).setProductPrice( getSumValue(productList, CrmContractProductDO::getTotalPrice, Integer::sum))); - // TODO @puhui999: 如果存在合同关联了商机则更新商机商品关联 + // 如果存在合同关联了商机则更新商机商品关联 + if (contract.getBusinessId() != null) { + businessService.updateBusinessProduct(new CrmBusinessUpdateProductReqBO().setId(contract.getBusinessId()) + .setProductItems(BeanUtils.toBean(createReqVO.getProductItems(), CrmBusinessUpdateProductReqBO.CrmBusinessProductItem.class))); + } } // 2. 创建数据权限 @@ -251,7 +257,8 @@ public class CrmContractServiceImpl implements CrmContractService { @Override @Transactional(rollbackFor = Exception.class) - // TODO @puhui999:操作日志; + @LogRecord(type = CRM_CONTRACT_TYPE, subType = CRM_CONTRACT_SUBMIT_SUB_TYPE, bizNo = "{{#id}}", + success = CRM_CONTRACT_SUBMIT_SUCCESS) public void submitContract(Long id, Long userId) { // 1. 校验合同是否在审批 CrmContractDO contract = validateContractExists(id); @@ -266,15 +273,43 @@ public class CrmContractServiceImpl implements CrmContractService { // 3. 更新合同工作流编号 contractMapper.updateById(new CrmContractDO().setId(id).setProcessInstanceId(processInstanceId) .setAuditStatus(CrmAuditStatusEnum.PROCESS.getStatus())); + + // 3. 记录日志 + LogRecordContext.putVariable("contractName", contract.getName()); } @Override public void updateContractAuditStatus(BpmResultListenerRespDTO event) { - // TODO @puhui999:可能要判断下状态是否符合预期 + // 判断下状态是否符合预期 + if (!isEndResult(event.getResult())) { + return; + } + // 状态转换 + if (ObjUtil.equal(event.getResult(), BpmProcessInstanceResultEnum.APPROVE.getResult())) { + event.setResult(CrmAuditStatusEnum.APPROVE.getStatus()); + } + if (ObjUtil.equal(event.getResult(), BpmProcessInstanceResultEnum.REJECT.getResult())) { + event.setResult(CrmAuditStatusEnum.REJECT.getStatus()); + } + if (ObjUtil.equal(event.getResult(), BpmProcessInstanceResultEnum.CANCEL.getResult())) { + event.setResult(CrmAuditStatusEnum.CANCEL.getStatus()); + } + // 更新合同状态 contractMapper.updateById(new CrmContractDO().setId(Long.parseLong(event.getBusinessKey())) .setAuditStatus(event.getResult())); } + /** + * 判断该结果是否处于 End 最终结果 + * + * @param result 结果 + * @return 是否 + */ + public static boolean isEndResult(Integer result) { + return ObjectUtils.equalsAny(result, BpmProcessInstanceResultEnum.APPROVE.getResult(), + BpmProcessInstanceResultEnum.REJECT.getResult(), BpmProcessInstanceResultEnum.CANCEL.getResult()); + } + //======================= 查询相关 ======================= @Override diff --git a/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/service/contract/listener/CrmContractResultListener.java b/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/service/contract/listener/CrmContractResultListener.java index dc278f337..c5ee407bd 100644 --- a/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/service/contract/listener/CrmContractResultListener.java +++ b/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/service/contract/listener/CrmContractResultListener.java @@ -1,11 +1,7 @@ package cn.iocoder.yudao.module.crm.service.contract.listener; -import cn.hutool.core.util.ObjUtil; -import cn.iocoder.yudao.framework.common.util.object.ObjectUtils; import cn.iocoder.yudao.module.bpm.api.listener.BpmResultListenerApi; import cn.iocoder.yudao.module.bpm.api.listener.dto.BpmResultListenerRespDTO; -import cn.iocoder.yudao.module.bpm.enums.task.BpmProcessInstanceResultEnum; -import cn.iocoder.yudao.module.crm.enums.common.CrmAuditStatusEnum; import cn.iocoder.yudao.module.crm.service.contract.CrmContractService; import cn.iocoder.yudao.module.crm.service.contract.CrmContractServiceImpl; import jakarta.annotation.Resource; @@ -30,31 +26,7 @@ public class CrmContractResultListener implements BpmResultListenerApi { @Override public void onEvent(BpmResultListenerRespDTO event) { - boolean currentTaskFinish = isEndResult(event.getResult()); - if (!currentTaskFinish) { - return; - } - if (ObjUtil.equal(event.getResult(), BpmProcessInstanceResultEnum.APPROVE.getResult())) { - event.setResult(CrmAuditStatusEnum.APPROVE.getStatus()); - } - if (ObjUtil.equal(event.getResult(), BpmProcessInstanceResultEnum.REJECT.getResult())) { - event.setResult(CrmAuditStatusEnum.REJECT.getStatus()); - } - if (ObjUtil.equal(event.getResult(), BpmProcessInstanceResultEnum.CANCEL.getResult())) { - event.setResult(CrmAuditStatusEnum.CANCEL.getStatus()); - } contractService.updateContractAuditStatus(event); } - /** - * 判断该结果是否处于 End 最终结果 - * - * @param result 结果 - * @return 是否 - */ - public static boolean isEndResult(Integer result) { - return ObjectUtils.equalsAny(result, BpmProcessInstanceResultEnum.APPROVE.getResult(), - BpmProcessInstanceResultEnum.REJECT.getResult(), BpmProcessInstanceResultEnum.CANCEL.getResult()); - } - } diff --git a/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/service/customer/CrmCustomerService.java b/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/service/customer/CrmCustomerService.java index 259812e4b..911260f76 100644 --- a/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/service/customer/CrmCustomerService.java +++ b/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/service/customer/CrmCustomerService.java @@ -110,11 +110,10 @@ public interface CrmCustomerService { * 批量导入客户 * * @param importCustomers 导入客户列表 - * @param isUpdateSupport 是否支持更新 - * @param userId 用户编号 + * @param importReqVO 请求 * @return 导入结果 */ - CrmCustomerImportRespVO importCustomerList(List importCustomers, Boolean isUpdateSupport, Long userId); + CrmCustomerImportRespVO importCustomerList(List importCustomers, CrmCustomerImportReqVO importReqVO); // ==================== 公海相关操作 ==================== diff --git a/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/service/customer/CrmCustomerServiceImpl.java b/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/service/customer/CrmCustomerServiceImpl.java index eeea1efdf..8230ba4e2 100644 --- a/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/service/customer/CrmCustomerServiceImpl.java +++ b/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/service/customer/CrmCustomerServiceImpl.java @@ -108,7 +108,7 @@ public class CrmCustomerServiceImpl implements CrmCustomerService { /** * 初始化客户的通用字段 * - * @param customer 客户信息 + * @param customer 客户信息 * @param ownerUserId 负责人编号 * @return 客户信息 DO */ @@ -244,8 +244,7 @@ public class CrmCustomerServiceImpl implements CrmCustomerService { } @Override - public CrmCustomerImportRespVO importCustomerList(List importCustomers, - Boolean isUpdateSupport, Long userId) { + public CrmCustomerImportRespVO importCustomerList(List importCustomers, CrmCustomerImportReqVO importReqVO) { if (CollUtil.isEmpty(importCustomers)) { throw exception(CUSTOMER_IMPORT_LIST_IS_EMPTY); } @@ -264,19 +263,21 @@ public class CrmCustomerServiceImpl implements CrmCustomerService { CrmCustomerDO existCustomer = customerMapper.selectByCustomerName(importCustomer.getName()); if (existCustomer == null) { // 1.1 插入客户信息 - CrmCustomerDO customer = initCustomer(importCustomer, userId); + CrmCustomerDO customer = initCustomer(importCustomer, importReqVO.getOwnerUserId()); customerMapper.insert(customer); respVO.getCreateCustomerNames().add(importCustomer.getName()); - // 1.2 创建数据权限 - permissionService.createPermission(new CrmPermissionCreateReqBO().setBizType(CrmBizTypeEnum.CRM_CUSTOMER.getType()) - .setBizId(customer.getId()).setUserId(userId).setLevel(CrmPermissionLevelEnum.OWNER.getLevel())); // 设置当前操作的人为负责人 + if (importReqVO.getOwnerUserId() != null) { + // 1.2 创建数据权限 + permissionService.createPermission(new CrmPermissionCreateReqBO().setBizType(CrmBizTypeEnum.CRM_CUSTOMER.getType()) + .setBizId(customer.getId()).setUserId(importReqVO.getOwnerUserId()).setLevel(CrmPermissionLevelEnum.OWNER.getLevel())); // 设置当前操作的人为负责人 + } // 1.3 记录操作日志 getSelf().importCustomerLog(customer, false); return; } // 情况二:如果存在,判断是否允许更新 - if (!isUpdateSupport) { + if (!importReqVO.getUpdateSupport()) { respVO.getFailureCustomerNames().put(importCustomer.getName(), StrUtil.format(CUSTOMER_NAME_EXISTS.getMsg(), importCustomer.getName())); return; From 30de2176a4d547bc754943e40efaa27609146188 Mon Sep 17 00:00:00 2001 From: YunaiV Date: Fri, 9 Feb 2024 20:03:02 +0800 Subject: [PATCH 091/119] =?UTF-8?q?=E2=9C=A8=20ERP=EF=BC=9A=E5=A2=9E?= =?UTF-8?q?=E5=8A=A0=20ERP=20=E9=94=80=E5=94=AE=E8=AE=A2=E5=8D=95=E7=9A=84?= =?UTF-8?q?=E5=AE=9E=E7=8E=B0=2050%?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../enums/sale/ErpSaleOrderStatusEnum.java | 40 ---- .../admin/sale/ErpSaleOrderController.java | 121 +++++++++--- .../sale/vo/order/ErpSaleOrderPageReqVO.java | 21 +- .../sale/vo/order/ErpSaleOrderRespVO.java | 114 +++++++---- .../sale/vo/order/ErpSaleOrderSaveReqVO.java | 91 +++------ .../dal/dataobject/sale/ErpSaleOrderDO.java | 54 ++++-- ...derItemDO.java => ErpSaleOrderItemDO.java} | 60 +++--- .../mysql/sale/ErpSaleOrderItemMapper.java | 30 +++ .../dal/mysql/sale/ErpSaleOrderMapper.java | 27 ++- .../mysql/sale/ErpSalesOrderItemMapper.java | 25 --- .../erp/dal/mysql/stock/ErpStockMapper.java | 19 +- .../erp/service/sale/ErpSaleOrderService.java | 46 ++++- .../service/sale/ErpSaleOrderServiceImpl.java | 183 ++++++++++++++---- .../erp/service/stock/ErpStockService.java | 8 + .../service/stock/ErpStockServiceImpl.java | 5 + 15 files changed, 551 insertions(+), 293 deletions(-) delete mode 100644 yudao-module-erp/yudao-module-erp-api/src/main/java/cn/iocoder/yudao/module/erp/enums/sale/ErpSaleOrderStatusEnum.java rename yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/dal/dataobject/sale/{ErpSalesOrderItemDO.java => ErpSaleOrderItemDO.java} (54%) create mode 100644 yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/dal/mysql/sale/ErpSaleOrderItemMapper.java delete mode 100644 yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/dal/mysql/sale/ErpSalesOrderItemMapper.java diff --git a/yudao-module-erp/yudao-module-erp-api/src/main/java/cn/iocoder/yudao/module/erp/enums/sale/ErpSaleOrderStatusEnum.java b/yudao-module-erp/yudao-module-erp-api/src/main/java/cn/iocoder/yudao/module/erp/enums/sale/ErpSaleOrderStatusEnum.java deleted file mode 100644 index 4caa7f515..000000000 --- a/yudao-module-erp/yudao-module-erp-api/src/main/java/cn/iocoder/yudao/module/erp/enums/sale/ErpSaleOrderStatusEnum.java +++ /dev/null @@ -1,40 +0,0 @@ -package cn.iocoder.yudao.module.erp.enums.sale; - -import cn.iocoder.yudao.framework.common.core.IntArrayValuable; -import lombok.AllArgsConstructor; -import lombok.Getter; - -import java.util.Arrays; - -/** - * ERP 销售订单的状态枚举 - * - * @author 芋道源码 - */ -@AllArgsConstructor -@Getter -public enum ErpSaleOrderStatusEnum implements IntArrayValuable { - - AUDIT_NONE(0, "未审核"), - AUDIT_PASS(10, "已审核"), - SALE_PART(20, "部分销售"), - SALE_ALL(21, "完成销售"), - ; - - public static final int[] ARRAYS = Arrays.stream(values()).mapToInt(ErpSaleOrderStatusEnum::getStatus).toArray(); - - /** - * 状态 - */ - private final Integer status; - /** - * 状态名 - */ - private final String name; - - @Override - public int[] array() { - return ARRAYS; - } - -} diff --git a/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/controller/admin/sale/ErpSaleOrderController.java b/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/controller/admin/sale/ErpSaleOrderController.java index ba1345166..2971ff5fc 100644 --- a/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/controller/admin/sale/ErpSaleOrderController.java +++ b/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/controller/admin/sale/ErpSaleOrderController.java @@ -1,16 +1,26 @@ package cn.iocoder.yudao.module.erp.controller.admin.sale; +import cn.hutool.core.collection.CollUtil; import cn.iocoder.yudao.framework.common.pojo.CommonResult; import cn.iocoder.yudao.framework.common.pojo.PageParam; import cn.iocoder.yudao.framework.common.pojo.PageResult; +import cn.iocoder.yudao.framework.common.util.collection.MapUtils; import cn.iocoder.yudao.framework.common.util.object.BeanUtils; import cn.iocoder.yudao.framework.excel.core.util.ExcelUtils; import cn.iocoder.yudao.framework.operatelog.core.annotations.OperateLog; +import cn.iocoder.yudao.module.erp.controller.admin.product.vo.product.ErpProductRespVO; import cn.iocoder.yudao.module.erp.controller.admin.sale.vo.order.ErpSaleOrderPageReqVO; import cn.iocoder.yudao.module.erp.controller.admin.sale.vo.order.ErpSaleOrderRespVO; import cn.iocoder.yudao.module.erp.controller.admin.sale.vo.order.ErpSaleOrderSaveReqVO; +import cn.iocoder.yudao.module.erp.dal.dataobject.sale.ErpCustomerDO; import cn.iocoder.yudao.module.erp.dal.dataobject.sale.ErpSaleOrderDO; +import cn.iocoder.yudao.module.erp.dal.dataobject.sale.ErpSaleOrderItemDO; +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.ErpSaleOrderService; +import cn.iocoder.yudao.module.erp.service.stock.ErpStockService; +import cn.iocoder.yudao.module.system.api.user.AdminUserApi; +import cn.iocoder.yudao.module.system.api.user.dto.AdminUserRespDTO; import io.swagger.v3.oas.annotations.Operation; import io.swagger.v3.oas.annotations.Parameter; import io.swagger.v3.oas.annotations.tags.Tag; @@ -22,9 +32,13 @@ import org.springframework.validation.annotation.Validated; import org.springframework.web.bind.annotation.*; import java.io.IOException; +import java.math.BigDecimal; import java.util.List; +import java.util.Map; import static cn.iocoder.yudao.framework.common.pojo.CommonResult.success; +import static cn.iocoder.yudao.framework.common.util.collection.CollectionUtils.convertMultiMap; +import static cn.iocoder.yudao.framework.common.util.collection.CollectionUtils.convertSet; import static cn.iocoder.yudao.framework.operatelog.core.enums.OperateTypeEnum.EXPORT; @@ -36,65 +50,116 @@ public class ErpSaleOrderController { @Resource private ErpSaleOrderService saleOrderService; + @Resource + private ErpStockService stockService; + @Resource + private ErpProductService productService; + @Resource + private ErpCustomerService customerService; + + @Resource + private AdminUserApi adminUserApi; - // TODO 芋艿:待 review @PostMapping("/create") - @Operation(summary = "创建ERP 销售订单") - @PreAuthorize("@ss.hasPermission('erp:sale-order:create')") + @Operation(summary = "创建销售订单") + @PreAuthorize("@ss.hasPermission('erp:stock-out:create')") public CommonResult createSaleOrder(@Valid @RequestBody ErpSaleOrderSaveReqVO createReqVO) { return success(saleOrderService.createSaleOrder(createReqVO)); } - // TODO 芋艿:待 review @PutMapping("/update") - @Operation(summary = "更新ERP 销售订单") - @PreAuthorize("@ss.hasPermission('erp:sale-order:update')") + @Operation(summary = "更新销售订单") + @PreAuthorize("@ss.hasPermission('erp:stock-out:update')") public CommonResult updateSaleOrder(@Valid @RequestBody ErpSaleOrderSaveReqVO updateReqVO) { saleOrderService.updateSaleOrder(updateReqVO); return success(true); } - // TODO 芋艿:待 review - @DeleteMapping("/delete") - @Operation(summary = "删除ERP 销售订单") - @Parameter(name = "id", description = "编号", required = true) - @PreAuthorize("@ss.hasPermission('erp:sale-order:delete')") - public CommonResult deleteSaleOrder(@RequestParam("id") Long id) { - saleOrderService.deleteSaleOrder(id); + @PutMapping("/update-status") + @Operation(summary = "更新销售订单的状态") + @PreAuthorize("@ss.hasPermission('erp:stock-out:update-status')") + public CommonResult updateSaleOrderStatus(@RequestParam("id") Long id, + @RequestParam("status") Integer status) { + saleOrderService.updateSaleOrderStatus(id, status); + return success(true); + } + + @DeleteMapping("/delete") + @Operation(summary = "删除销售订单") + @Parameter(name = "ids", description = "编号数组", required = true) + @PreAuthorize("@ss.hasPermission('erp:stock-out:delete')") + public CommonResult deleteSaleOrder(@RequestParam("ids") List ids) { + saleOrderService.deleteSaleOrder(ids); return success(true); } - // TODO 芋艿:待 review @GetMapping("/get") - @Operation(summary = "获得ERP 销售订单") + @Operation(summary = "获得销售订单") @Parameter(name = "id", description = "编号", required = true, example = "1024") - @PreAuthorize("@ss.hasPermission('erp:sale-order:query')") + @PreAuthorize("@ss.hasPermission('erp:stock-out:query')") public CommonResult getSaleOrder(@RequestParam("id") Long id) { ErpSaleOrderDO saleOrder = saleOrderService.getSaleOrder(id); - return success(BeanUtils.toBean(saleOrder, ErpSaleOrderRespVO.class)); + if (saleOrder == null) { + return success(null); + } + List saleOrderItemList = saleOrderService.getSaleOrderItemListByOrderId(id); + Map productMap = productService.getProductVOMap( + convertSet(saleOrderItemList, ErpSaleOrderItemDO::getProductId)); + return success(BeanUtils.toBean(saleOrder, ErpSaleOrderRespVO.class, saleOrderVO -> + saleOrderVO.setItems(BeanUtils.toBean(saleOrderItemList, ErpSaleOrderRespVO.Item.class, item -> { + BigDecimal stockCount = stockService.getStockCount(item.getProductId()); + item.setStockCount(stockCount != null ? stockCount : BigDecimal.ZERO); + MapUtils.findAndThen(productMap, item.getProductId(), product -> item.setProductName(product.getName()) + .setProductBarCode(product.getBarCode()).setProductUnitName(product.getUnitName())); + })))); } - // TODO 芋艿:待 review @GetMapping("/page") - @Operation(summary = "获得ERP 销售订单分页") - @PreAuthorize("@ss.hasPermission('erp:sale-order:query')") + @Operation(summary = "获得销售订单分页") + @PreAuthorize("@ss.hasPermission('erp:stock-out:query')") public CommonResult> getSaleOrderPage(@Valid ErpSaleOrderPageReqVO pageReqVO) { PageResult pageResult = saleOrderService.getSaleOrderPage(pageReqVO); - return success(BeanUtils.toBean(pageResult, ErpSaleOrderRespVO.class)); + return success(buildSaleOrderVOPageResult(pageResult)); } - // TODO 芋艿:待 review @GetMapping("/export-excel") - @Operation(summary = "导出ERP 销售订单 Excel") - @PreAuthorize("@ss.hasPermission('erp:sale-order:export')") + @Operation(summary = "导出销售订单 Excel") + @PreAuthorize("@ss.hasPermission('erp:stock-out:export')") @OperateLog(type = EXPORT) public void exportSaleOrderExcel(@Valid ErpSaleOrderPageReqVO pageReqVO, - HttpServletResponse response) throws IOException { + HttpServletResponse response) throws IOException { pageReqVO.setPageSize(PageParam.PAGE_SIZE_NONE); - List list = saleOrderService.getSaleOrderPage(pageReqVO).getList(); + List list = buildSaleOrderVOPageResult(saleOrderService.getSaleOrderPage(pageReqVO)).getList(); // 导出 Excel - ExcelUtils.write(response, "ERP 销售订单.xls", "数据", ErpSaleOrderRespVO.class, - BeanUtils.toBean(list, ErpSaleOrderRespVO.class)); + ExcelUtils.write(response, "销售订单.xls", "数据", ErpSaleOrderRespVO.class, list); + } + + private PageResult buildSaleOrderVOPageResult(PageResult pageResult) { + if (CollUtil.isEmpty(pageResult.getList())) { + return PageResult.empty(pageResult.getTotal()); + } + // 1.1 出库项 + List saleOrderItemList = saleOrderService.getSaleOrderItemListByOrderIds( + convertSet(pageResult.getList(), ErpSaleOrderDO::getId)); + Map> saleOrderItemMap = convertMultiMap(saleOrderItemList, ErpSaleOrderItemDO::getOrderId); + // 1.2 商品信息 + Map productMap = productService.getProductVOMap( + convertSet(saleOrderItemList, ErpSaleOrderItemDO::getProductId)); + // 1.3 客户信息 + Map customerMap = customerService.getCustomerMap( + convertSet(pageResult.getList(), ErpSaleOrderDO::getCustomerId)); + // 1.4 管理员信息 + Map userMap = adminUserApi.getUserMap( + convertSet(pageResult.getList(), erpStockRecordDO -> Long.parseLong(erpStockRecordDO.getCreator()))); + // 2. 开始拼接 + return BeanUtils.toBean(pageResult, ErpSaleOrderRespVO.class, saleOrder -> { + saleOrder.setItems(BeanUtils.toBean(saleOrderItemMap.get(saleOrder.getId()), ErpSaleOrderRespVO.Item.class, + item -> MapUtils.findAndThen(productMap, item.getProductId(), product -> item.setProductName(product.getName()) + .setProductBarCode(product.getBarCode()).setProductUnitName(product.getUnitName())))); + saleOrder.setProductNames(CollUtil.join(saleOrder.getItems(), ",", ErpSaleOrderRespVO.Item::getProductName)); + MapUtils.findAndThen(customerMap, saleOrder.getCustomerId(), supplier -> saleOrder.setCustomerName(supplier.getName())); + MapUtils.findAndThen(userMap, Long.parseLong(saleOrder.getCreator()), user -> saleOrder.setCreatorName(user.getNickname())); + }); } } \ No newline at end of file diff --git a/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/controller/admin/sale/vo/order/ErpSaleOrderPageReqVO.java b/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/controller/admin/sale/vo/order/ErpSaleOrderPageReqVO.java index 8e46a64b0..c5d748f22 100644 --- a/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/controller/admin/sale/vo/order/ErpSaleOrderPageReqVO.java +++ b/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/controller/admin/sale/vo/order/ErpSaleOrderPageReqVO.java @@ -17,6 +17,19 @@ import static cn.iocoder.yudao.framework.common.util.date.DateUtils.FORMAT_YEAR_ @ToString(callSuper = true) public class ErpSaleOrderPageReqVO extends PageParam { + /** + * 入库状态 - 无 + */ + public static final Integer IN_STATUS_NONE = 0; + /** + * 入库状态 - 部分 + */ + public static final Integer IN_STATUS_PART = 1; + /** + * 入库状态 - 全部 + */ + public static final Integer IN_STATUS_ALL = 2; + @Schema(description = "销售单编号", example = "XS001") private String no; @@ -28,7 +41,7 @@ public class ErpSaleOrderPageReqVO extends PageParam { private LocalDateTime[] orderTime; @Schema(description = "备注", example = "你猜") - private String description; + private String remark; @Schema(description = "销售状态", example = "2") private Integer status; @@ -36,4 +49,10 @@ public class ErpSaleOrderPageReqVO extends PageParam { @Schema(description = "创建者") private String creator; + @Schema(description = "产品编号", example = "1") + private Long productId; + + @Schema(description = "入库状态", example = "2") + private Integer inStatus; + } \ No newline at end of file diff --git a/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/controller/admin/sale/vo/order/ErpSaleOrderRespVO.java b/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/controller/admin/sale/vo/order/ErpSaleOrderRespVO.java index ea24e08ca..8fd879621 100644 --- a/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/controller/admin/sale/vo/order/ErpSaleOrderRespVO.java +++ b/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/controller/admin/sale/vo/order/ErpSaleOrderRespVO.java @@ -3,12 +3,13 @@ package cn.iocoder.yudao.module.erp.controller.admin.sale.vo.order; import com.alibaba.excel.annotation.ExcelIgnoreUnannotated; import com.alibaba.excel.annotation.ExcelProperty; import io.swagger.v3.oas.annotations.media.Schema; +import jakarta.validation.constraints.NotNull; import lombok.Data; import java.math.BigDecimal; import java.time.LocalDateTime; +import java.util.List; -// TODO 芋艿:导出最后搞 @Schema(description = "管理后台 - ERP 销售订单 Response VO") @Data @ExcelIgnoreUnannotated @@ -23,56 +24,103 @@ public class ErpSaleOrderRespVO { private String no; @Schema(description = "客户编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "1724") - @ExcelProperty("客户编号") private Long customerId; + @Schema(description = "客户名称", example = "芋道") + @ExcelProperty("客户名称") + private String customerName; @Schema(description = "下单时间", requiredMode = Schema.RequiredMode.REQUIRED) @ExcelProperty("下单时间") private LocalDateTime orderTime; - // TODO 芋艿:example 后面 - @Schema(description = "销售员编号数组") - @ExcelProperty("销售员编号数组") - private String salePersonIds; - - @Schema(description = "合计价格,单位:元", requiredMode = Schema.RequiredMode.REQUIRED, example = "26094") - @ExcelProperty("合计价格,单位:元") - private BigDecimal totalPrice; - - @Schema(description = "优惠率,百分比", requiredMode = Schema.RequiredMode.REQUIRED, example = "99.88") - @ExcelProperty("优惠率,百分比") - private BigDecimal discountPercent; - - @Schema(description = "优惠金额,单位:元", requiredMode = Schema.RequiredMode.REQUIRED, example = "44.52") - @ExcelProperty("优惠金额,单位:元") - private BigDecimal discountPrice; - - @Schema(description = "支付金额,单位:元", requiredMode = Schema.RequiredMode.REQUIRED, example = "322.40") - @ExcelProperty("支付金额,单位:元") - private BigDecimal payPrice; - - @Schema(description = "定金金额,单位:元", requiredMode = Schema.RequiredMode.REQUIRED, example = "71.27") - @ExcelProperty("定金金额,单位:元") - private BigDecimal depositPrice; - - @Schema(description = "附件地址", example = "https://www.iocoder.cn") - @ExcelProperty("附件地址") - private String fileUrl; + @Schema(description = "销售员编号", example = "1888") + private Long saleUserId; @Schema(description = "结算账户编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "311.89") @ExcelProperty("结算账户编号") private Long accountId; - @Schema(description = "备注", example = "你猜") - @ExcelProperty("备注") - private String description; + @Schema(description = "合计产品价格,单位:元", requiredMode = Schema.RequiredMode.REQUIRED, example = "7127") + private BigDecimal totalProductPrice; + + @Schema(description = "合计税额,单位:元", requiredMode = Schema.RequiredMode.REQUIRED, example = "7127") + private BigDecimal totalTaxPrice; + + @Schema(description = "优惠率,百分比", requiredMode = Schema.RequiredMode.REQUIRED, example = "99.88") + private BigDecimal discountPercent; + + @Schema(description = "优惠金额,单位:元", requiredMode = Schema.RequiredMode.REQUIRED, example = "7127") + private BigDecimal discountPrice; + + @Schema(description = "定金金额,单位:元", requiredMode = Schema.RequiredMode.REQUIRED, example = "7127") + @NotNull(message = "定金金额,单位:元不能为空") + private BigDecimal depositPrice; @Schema(description = "销售状态", requiredMode = Schema.RequiredMode.REQUIRED, example = "2") @ExcelProperty("销售状态") private Integer status; + @Schema(description = "附件地址", example = "https://www.iocoder.cn") + @ExcelProperty("附件地址") + private String fileUrl; + + @Schema(description = "备注", example = "你猜") + @ExcelProperty("备注") + private String remark; + + @Schema(description = "审核人", example = "芋道") + private String creator; + @Schema(description = "审核人名称", example = "芋道") + private String creatorName; + @Schema(description = "创建时间", requiredMode = Schema.RequiredMode.REQUIRED) @ExcelProperty("创建时间") private LocalDateTime createTime; + @Schema(description = "订单项列表", requiredMode = Schema.RequiredMode.REQUIRED) + private List items; + + @Schema(description = "产品信息", requiredMode = Schema.RequiredMode.REQUIRED) + @ExcelProperty("产品信息") + private String productNames; + + @Data + public static class Item { + + @Schema(description = "订单项编号", example = "11756") + private Long id; + + @Schema(description = "产品编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "3113") + private Long productId; + + @Schema(description = "产品单位单位", requiredMode = Schema.RequiredMode.REQUIRED, example = "3113") + private Long productUnitId; + + @Schema(description = "产品单价", example = "100.00") + private BigDecimal productPrice; + + @Schema(description = "产品数量", requiredMode = Schema.RequiredMode.REQUIRED, example = "100.00") + @NotNull(message = "产品数量不能为空") + private BigDecimal count; + + @Schema(description = "税率,百分比", example = "99.88") + private BigDecimal taxPercent; + + @Schema(description = "备注", example = "随便") + private String remark; + + // ========== 关联字段 ========== + + @Schema(description = "产品名称", requiredMode = Schema.RequiredMode.REQUIRED, example = "巧克力") + private String productName; + @Schema(description = "产品条码", requiredMode = Schema.RequiredMode.REQUIRED, example = "A9985") + private String productBarCode; + @Schema(description = "产品单位名称", requiredMode = Schema.RequiredMode.REQUIRED, example = "盒") + private String productUnitName; + + @Schema(description = "库存数量", requiredMode = Schema.RequiredMode.REQUIRED, example = "100.00") + private BigDecimal stockCount; // 该字段仅仅在“详情”和“编辑”时使用 + + } + } \ No newline at end of file diff --git a/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/controller/admin/sale/vo/order/ErpSaleOrderSaveReqVO.java b/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/controller/admin/sale/vo/order/ErpSaleOrderSaveReqVO.java index e40b38902..1706915aa 100644 --- a/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/controller/admin/sale/vo/order/ErpSaleOrderSaveReqVO.java +++ b/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/controller/admin/sale/vo/order/ErpSaleOrderSaveReqVO.java @@ -28,26 +28,16 @@ public class ErpSaleOrderSaveReqVO { @NotNull(message = "下单时间不能为空") private LocalDateTime orderTime; - @Schema(description = "销售员编号数组") - private List salePersonIds; + @Schema(description = "销售员编号", example = "1888") + private Long saleUserId; - @Schema(description = "合计价格,单位:元", requiredMode = Schema.RequiredMode.REQUIRED, example = "26094") - @NotNull(message = "合计价格,单位:元不能为空") - private BigDecimal totalPrice; + @Schema(description = "结算账户编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "31189") + @NotNull(message = "结算账户编号不能为空") + private Long accountId; @Schema(description = "优惠率,百分比", requiredMode = Schema.RequiredMode.REQUIRED, example = "99.88") - @NotNull(message = "优惠率,百分比不能为空") private BigDecimal discountPercent; - @Schema(description = "优惠金额,单位:元", requiredMode = Schema.RequiredMode.REQUIRED, example = "4452") - @NotNull(message = "优惠金额,单位:元不能为空") - private BigDecimal discountPrice; - - // TODO 芋艿:后面删除 -// @Schema(description = "支付金额,单位:元", requiredMode = Schema.RequiredMode.REQUIRED, example = "32240") -// @NotNull(message = "支付金额,单位:元不能为空") -// private BigDecimal payPrice; - @Schema(description = "定金金额,单位:元", requiredMode = Schema.RequiredMode.REQUIRED, example = "7127") @NotNull(message = "定金金额,单位:元不能为空") private BigDecimal depositPrice; @@ -55,73 +45,38 @@ public class ErpSaleOrderSaveReqVO { @Schema(description = "附件地址", example = "https://www.iocoder.cn") private String fileUrl; - @Schema(description = "结算账户编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "31189") - @NotNull(message = "结算账户编号不能为空") - private Long accountId; - @Schema(description = "备注", example = "你猜") - private String description; + private String remark; - // TODO 芋艿:后面删除 -// @Schema(description = "销售状态", requiredMode = Schema.RequiredMode.REQUIRED, example = "2") -// @NotNull(message = "销售状态不能为空") -// private Integer status; + @Schema(description = "订单清单列表") + private List items; - @Schema(description = "ERP 销售订单明细列表") - private List salesOrderItems; - - @Schema(description = "管理后台 - ERP 销售订单明细新增/修改 Request VO") @Data - public class Item { + public static class Item { - @Schema(description = "编号", example = "20704") + @Schema(description = "订单项编号", example = "11756") private Long id; - // TODO 芋艿:后面删除 -// @Schema(description = "销售订单编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "30765") -// @NotNull(message = "销售订单编号不能为空") -// private Long orderId; + @Schema(description = "产品编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "3113") + @NotNull(message = "产品编号不能为空") + private Long productId; -// @Schema(description = "商品 SPU 编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "5574") -// @NotNull(message = "商品 SPU 编号不能为空") -// private Long productSpuId; + @Schema(description = "产品单位单位", requiredMode = Schema.RequiredMode.REQUIRED, example = "3113") + @NotNull(message = "产品单位单位不能为空") + private Long productUnitId; - @Schema(description = "商品 SKU 编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "21273") - @NotNull(message = "商品 SKU 编号不能为空") - private Long productSkuId; - - @Schema(description = "商品单位", requiredMode = Schema.RequiredMode.REQUIRED) - @NotEmpty(message = "商品单位不能为空") - private String productUnit; - - @Schema(description = "商品单价", requiredMode = Schema.RequiredMode.REQUIRED, example = "6897") - @NotNull(message = "商品单价不能为空") + @Schema(description = "产品单价", example = "100.00") private BigDecimal productPrice; - @Schema(description = "数量", requiredMode = Schema.RequiredMode.REQUIRED, example = "22100") - @NotNull(message = "数量不能为空") - private Integer count; + @Schema(description = "产品数量", requiredMode = Schema.RequiredMode.REQUIRED, example = "100.00") + @NotNull(message = "产品数量不能为空") + private BigDecimal count; - // TODO 芋艿:后面删除 -// @Schema(description = "总价", requiredMode = Schema.RequiredMode.REQUIRED, example = "26868") -// @NotNull(message = "总价不能为空") -// private BigDecimal totalPrice; - - @Schema(description = "备注", example = "你说的对") - private String description; - - @Schema(description = "税率,百分比", requiredMode = Schema.RequiredMode.REQUIRED) - @NotNull(message = "税率,百分比不能为空") + @Schema(description = "税率,百分比", example = "99.88") private BigDecimal taxPercent; - @Schema(description = "税额,单位:元", requiredMode = Schema.RequiredMode.REQUIRED, example = "15791") - @NotNull(message = "税额,单位:元不能为空") - private BigDecimal taxPrice; - - // TODO 芋艿:后面删除 -// @Schema(description = "支付金额,单位:元", requiredMode = Schema.RequiredMode.REQUIRED, example = "21930") -// @NotNull(message = "支付金额,单位:元不能为空") -// private BigDecimal payPrice; + @Schema(description = "备注", example = "随便") + private String remark; } diff --git a/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/dal/dataobject/sale/ErpSaleOrderDO.java b/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/dal/dataobject/sale/ErpSaleOrderDO.java index 749eabd49..8bbbcdefb 100644 --- a/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/dal/dataobject/sale/ErpSaleOrderDO.java +++ b/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/dal/dataobject/sale/ErpSaleOrderDO.java @@ -1,24 +1,20 @@ package cn.iocoder.yudao.module.erp.dal.dataobject.sale; import cn.iocoder.yudao.framework.mybatis.core.dataobject.BaseDO; -import cn.iocoder.yudao.framework.mybatis.core.type.LongListTypeHandler; -import cn.iocoder.yudao.module.erp.enums.sale.ErpSaleOrderStatusEnum; import com.baomidou.mybatisplus.annotation.KeySequence; -import com.baomidou.mybatisplus.annotation.TableField; import com.baomidou.mybatisplus.annotation.TableId; import com.baomidou.mybatisplus.annotation.TableName; import lombok.*; import java.math.BigDecimal; import java.time.LocalDateTime; -import java.util.List; /** * ERP 销售订单 DO * * @author 芋道源码 */ -@TableName(value = "erp_sale_order", autoResultMap = true) +@TableName(value = "erp_sale_order") @KeySequence("erp_sale_order_seq") // 用于 Oracle、PostgreSQL、Kingbase、DB2、H2 数据库的主键自增。如果是 MySQL 等数据库,可不写。 @Data @EqualsAndHashCode(callSuper = true) @@ -40,13 +36,13 @@ public class ErpSaleOrderDO extends BaseDO { /** * 销售状态 * - * 枚举 {@link ErpSaleOrderStatusEnum} + * 枚举 {@link cn.iocoder.yudao.module.erp.enums.ErpAuditStatus} */ private Integer status; /** * 客户编号 * - * TODO 芋艿:关联 + * 关联 {@link ErpCustomerDO#getId()} */ private Long customerId; /** @@ -56,33 +52,45 @@ public class ErpSaleOrderDO extends BaseDO { */ private Long accountId; /** - * 销售员编号数组 + * 销售员编号 * - * TODO 芋艿:关联 + * 关联 AdminUserDO 的 id 字段 */ - @TableField(typeHandler = LongListTypeHandler.class) - private List salePersonIds; + private Long saleUserId; /** * 下单时间 */ private LocalDateTime orderTime; /** - * 合计价格,单位:元 + * 合计数量 + */ + private BigDecimal totalCount; + /** + * 最终合计价格,单位:元 + * + * totalPrice = totalProductPrice + totalTaxPrice - discountPrice */ private BigDecimal totalPrice; + + /** + * 合计产品价格,单位:元 + */ + private BigDecimal totalProductPrice; + /** + * 合计税额,单位:元 + */ + private BigDecimal totalTaxPrice; /** * 优惠率,百分比 */ private BigDecimal discountPercent; /** * 优惠金额,单位:元 + * + * discountPrice = (totalProductPrice + totalTaxPrice) * discountPercent */ private BigDecimal discountPrice; - /** - * 支付金额,单位:元 - */ - private BigDecimal payPrice; /** * 定金金额,单位:元 */ @@ -95,6 +103,18 @@ public class ErpSaleOrderDO extends BaseDO { /** * 备注 */ - private String description; + private String remark; + + // ========== 销售入库 ========== + /** + * 销售入库数量 + */ + private BigDecimal inCount; + + // ========== 销售退货(出库)) ========== + /** + * 销售退货数量 + */ + private BigDecimal returnCount; } \ No newline at end of file diff --git a/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/dal/dataobject/sale/ErpSalesOrderItemDO.java b/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/dal/dataobject/sale/ErpSaleOrderItemDO.java similarity index 54% rename from yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/dal/dataobject/sale/ErpSalesOrderItemDO.java rename to yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/dal/dataobject/sale/ErpSaleOrderItemDO.java index 7e1b25f8d..d25a5471c 100644 --- a/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/dal/dataobject/sale/ErpSalesOrderItemDO.java +++ b/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/dal/dataobject/sale/ErpSaleOrderItemDO.java @@ -1,6 +1,7 @@ package cn.iocoder.yudao.module.erp.dal.dataobject.sale; import cn.iocoder.yudao.framework.mybatis.core.dataobject.BaseDO; +import cn.iocoder.yudao.module.erp.dal.dataobject.product.ErpProductDO; import com.baomidou.mybatisplus.annotation.KeySequence; import com.baomidou.mybatisplus.annotation.TableId; import com.baomidou.mybatisplus.annotation.TableName; @@ -13,15 +14,15 @@ import java.math.BigDecimal; * * @author 芋道源码 */ -@TableName("erp_sales_order_items") -@KeySequence("erp_sales_order_items_seq") // 用于 Oracle、PostgreSQL、Kingbase、DB2、H2 数据库的主键自增。如果是 MySQL 等数据库,可不写。 +@TableName("erp_sale_order_items") +@KeySequence("erp_sale_order_items_seq") // 用于 Oracle、PostgreSQL、Kingbase、DB2、H2 数据库的主键自增。如果是 MySQL 等数据库,可不写。 @Data @EqualsAndHashCode(callSuper = true) @ToString(callSuper = true) @Builder @NoArgsConstructor @AllArgsConstructor -public class ErpSalesOrderItemDO extends BaseDO { +public class ErpSaleOrderItemDO extends BaseDO { /** * 编号 @@ -36,53 +37,58 @@ public class ErpSalesOrderItemDO extends BaseDO { private Long orderId; /** - * 商品 SPU 编号 + * 产品编号 * - * TODO 芋艿 关联 + * 关联 {@link ErpProductDO#getId()} */ - private Long productSpuId; + private Long productId; /** - * 商品 SKU 编号 + * 产品单位单位 * - * TODO 芋艿 关联 + * 冗余 {@link ErpProductDO#getUnitId()} */ - private Long productSkuId; + private Long productUnitId; + /** - * 商品单位 - * - * TODO 芋艿 冗余 - */ - private String productUnit; - /** - * 商品单价 - * - * TODO 芋艿 冗余 + * 产品单位单价,单位:元 */ private BigDecimal productPrice; - /** * 数量 */ - private Integer count; + private BigDecimal count; /** - * 总价 + * 总价,单位:元 + * + * totalPrice = productPrice * count */ private BigDecimal totalPrice; - /** - * 备注 - */ - private String description; /** * 税率,百分比 */ private BigDecimal taxPercent; /** * 税额,单位:元 + * + * taxPrice = totalPrice * taxPercent */ private BigDecimal taxPrice; + /** - * 支付金额,单位:元 + * 备注 */ - private BigDecimal payPrice; + private String remark; + + // ========== 销售入库 ========== + /** + * 销售入库数量 + */ + private BigDecimal inCount; + + // ========== 销售退货(出库)) ========== + /** + * 销售退货数量 + */ + private BigDecimal returnCount; } \ No newline at end of file diff --git a/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/dal/mysql/sale/ErpSaleOrderItemMapper.java b/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/dal/mysql/sale/ErpSaleOrderItemMapper.java new file mode 100644 index 000000000..fd3f82f0b --- /dev/null +++ b/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/dal/mysql/sale/ErpSaleOrderItemMapper.java @@ -0,0 +1,30 @@ +package cn.iocoder.yudao.module.erp.dal.mysql.sale; + +import cn.iocoder.yudao.framework.mybatis.core.mapper.BaseMapperX; +import cn.iocoder.yudao.module.erp.dal.dataobject.sale.ErpSaleOrderItemDO; +import org.apache.ibatis.annotations.Mapper; + +import java.util.Collection; +import java.util.List; + +/** + * ERP 销售订单明细 Mapper + * + * @author 芋道源码 + */ +@Mapper +public interface ErpSaleOrderItemMapper extends BaseMapperX { + + default List selectListByOrderId(Long orderId) { + return selectList(ErpSaleOrderItemDO::getOrderId, orderId); + } + + default List selectListByOrderIds(Collection orderIds) { + return selectList(ErpSaleOrderItemDO::getOrderId, orderIds); + } + + default int deleteByOrderId(Long orderId) { + return delete(ErpSaleOrderItemDO::getOrderId, orderId); + } + +} \ No newline at end of file diff --git a/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/dal/mysql/sale/ErpSaleOrderMapper.java b/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/dal/mysql/sale/ErpSaleOrderMapper.java index 07c80c480..d39c1ee4d 100644 --- a/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/dal/mysql/sale/ErpSaleOrderMapper.java +++ b/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/dal/mysql/sale/ErpSaleOrderMapper.java @@ -3,9 +3,11 @@ package cn.iocoder.yudao.module.erp.dal.mysql.sale; import cn.iocoder.yudao.framework.common.pojo.PageResult; import cn.iocoder.yudao.framework.mybatis.core.mapper.BaseMapperX; -import cn.iocoder.yudao.framework.mybatis.core.query.LambdaQueryWrapperX; +import cn.iocoder.yudao.framework.mybatis.core.query.MPJLambdaWrapperX; import cn.iocoder.yudao.module.erp.controller.admin.sale.vo.order.ErpSaleOrderPageReqVO; import cn.iocoder.yudao.module.erp.dal.dataobject.sale.ErpSaleOrderDO; +import cn.iocoder.yudao.module.erp.dal.dataobject.stock.ErpStockOutItemDO; +import com.baomidou.mybatisplus.core.conditions.update.LambdaUpdateWrapper; import org.apache.ibatis.annotations.Mapper; /** @@ -17,14 +19,29 @@ import org.apache.ibatis.annotations.Mapper; public interface ErpSaleOrderMapper extends BaseMapperX { default PageResult selectPage(ErpSaleOrderPageReqVO reqVO) { - return selectPage(reqVO, new LambdaQueryWrapperX() - .likeIfPresent(ErpSaleOrderDO::getNo, reqVO.getNo()) + MPJLambdaWrapperX query = new MPJLambdaWrapperX() + .eqIfPresent(ErpSaleOrderDO::getNo, reqVO.getNo()) .eqIfPresent(ErpSaleOrderDO::getCustomerId, reqVO.getCustomerId()) .betweenIfPresent(ErpSaleOrderDO::getOrderTime, reqVO.getOrderTime()) - .eqIfPresent(ErpSaleOrderDO::getDescription, reqVO.getDescription()) .eqIfPresent(ErpSaleOrderDO::getStatus, reqVO.getStatus()) + .likeIfPresent(ErpSaleOrderDO::getRemark, reqVO.getRemark()) .eqIfPresent(ErpSaleOrderDO::getCreator, reqVO.getCreator()) - .orderByDesc(ErpSaleOrderDO::getId)); + .orderByDesc(ErpSaleOrderDO::getId); + if (reqVO.getProductId() != null) { + query.leftJoin(ErpStockOutItemDO.class, ErpStockOutItemDO::getOutId, ErpSaleOrderDO::getId) + .eq(reqVO.getProductId() != null, ErpStockOutItemDO::getProductId, reqVO.getProductId()) + .groupBy(ErpSaleOrderDO::getId); // 避免 1 对多查询,产生相同的 1 + } + return selectJoinPage(reqVO, ErpSaleOrderDO.class, query); + } + + default int updateByIdAndStatus(Long id, Integer status, ErpSaleOrderDO updateObj) { + return update(updateObj, new LambdaUpdateWrapper() + .eq(ErpSaleOrderDO::getId, id).eq(ErpSaleOrderDO::getStatus, status)); + } + + default ErpSaleOrderDO selectByNo(String no) { + return selectOne(ErpSaleOrderDO::getNo, no); } } \ No newline at end of file diff --git a/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/dal/mysql/sale/ErpSalesOrderItemMapper.java b/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/dal/mysql/sale/ErpSalesOrderItemMapper.java deleted file mode 100644 index eb8628291..000000000 --- a/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/dal/mysql/sale/ErpSalesOrderItemMapper.java +++ /dev/null @@ -1,25 +0,0 @@ -package cn.iocoder.yudao.module.erp.dal.mysql.sale; - -import cn.iocoder.yudao.framework.mybatis.core.mapper.BaseMapperX; -import cn.iocoder.yudao.module.erp.dal.dataobject.sale.ErpSalesOrderItemDO; -import org.apache.ibatis.annotations.Mapper; - -import java.util.List; - -/** - * ERP 销售订单明细 Mapper - * - * @author 芋道源码 - */ -@Mapper -public interface ErpSalesOrderItemMapper extends BaseMapperX { - - default List selectListById(Long id) { - return selectList(ErpSalesOrderItemDO::getId, id); - } - - default int deleteById(Long id) { - return delete(ErpSalesOrderItemDO::getId, id); - } - -} \ No newline at end of file diff --git a/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/dal/mysql/stock/ErpStockMapper.java b/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/dal/mysql/stock/ErpStockMapper.java index 35fd85248..0ebc98597 100644 --- a/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/dal/mysql/stock/ErpStockMapper.java +++ b/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/dal/mysql/stock/ErpStockMapper.java @@ -1,14 +1,19 @@ package cn.iocoder.yudao.module.erp.dal.mysql.stock; +import cn.hutool.core.collection.CollUtil; +import cn.hutool.core.map.MapUtil; import cn.iocoder.yudao.framework.common.pojo.PageResult; import cn.iocoder.yudao.framework.mybatis.core.mapper.BaseMapperX; import cn.iocoder.yudao.framework.mybatis.core.query.LambdaQueryWrapperX; import cn.iocoder.yudao.module.erp.controller.admin.stock.vo.stock.ErpStockPageReqVO; import cn.iocoder.yudao.module.erp.dal.dataobject.stock.ErpStockDO; +import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper; import com.baomidou.mybatisplus.core.conditions.update.LambdaUpdateWrapper; import org.apache.ibatis.annotations.Mapper; import java.math.BigDecimal; +import java.util.List; +import java.util.Map; /** * ERP 产品库存 Mapper @@ -37,11 +42,23 @@ public interface ErpStockMapper extends BaseMapperX { updateWrapper.setSql("count = count + " + count); } else if (count.compareTo(BigDecimal.ZERO) < 0) { if (!negativeEnable) { - updateWrapper.gt(ErpStockDO::getCount, count.abs()); + updateWrapper.ge(ErpStockDO::getCount, count.abs()); } updateWrapper.setSql("count = count - " + count.abs()); } return update(null, updateWrapper); } + default BigDecimal selectSumByProductId(Long productId) { + // SQL sum 查询 + List> result = selectMaps(new QueryWrapper() + .select("SUM(count) AS sumCount") + .eq("product_id", productId)); + // 获得数量 + if (CollUtil.isEmpty(result)) { + return BigDecimal.ZERO; + } + return BigDecimal.valueOf(MapUtil.getDouble(result.get(0), "sumCount", 0D)); + } + } \ No newline at end of file diff --git a/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/service/sale/ErpSaleOrderService.java b/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/service/sale/ErpSaleOrderService.java index 6554f2c18..cd32f62c4 100644 --- a/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/service/sale/ErpSaleOrderService.java +++ b/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/service/sale/ErpSaleOrderService.java @@ -4,8 +4,12 @@ import cn.iocoder.yudao.framework.common.pojo.PageResult; import cn.iocoder.yudao.module.erp.controller.admin.sale.vo.order.ErpSaleOrderPageReqVO; import cn.iocoder.yudao.module.erp.controller.admin.sale.vo.order.ErpSaleOrderSaveReqVO; 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.util.Collection; +import java.util.List; + /** * ERP 销售订单 Service 接口 * @@ -14,7 +18,7 @@ import jakarta.validation.Valid; public interface ErpSaleOrderService { /** - * 创建ERP 销售订单 + * 创建销售订单 * * @param createReqVO 创建信息 * @return 编号 @@ -22,33 +26,59 @@ public interface ErpSaleOrderService { Long createSaleOrder(@Valid ErpSaleOrderSaveReqVO createReqVO); /** - * 更新ERP 销售订单 + * 更新销售订单 * * @param updateReqVO 更新信息 */ void updateSaleOrder(@Valid ErpSaleOrderSaveReqVO updateReqVO); /** - * 删除ERP 销售订单 + * 更新销售订单的状态 * * @param id 编号 + * @param status 状态 */ - void deleteSaleOrder(Long id); + void updateSaleOrderStatus(Long id, Integer status); /** - * 获得ERP 销售订单 + * 删除销售订单 + * + * @param ids 编号数组 + */ + void deleteSaleOrder(List ids); + + /** + * 获得销售订单 * * @param id 编号 - * @return ERP 销售订单 + * @return 销售订单 */ ErpSaleOrderDO getSaleOrder(Long id); /** - * 获得ERP 销售订单分页 + * 获得销售订单分页 * * @param pageReqVO 分页查询 - * @return ERP 销售订单分页 + * @return 销售订单分页 */ PageResult getSaleOrderPage(ErpSaleOrderPageReqVO pageReqVO); + // ==================== 销售订单项 ==================== + + /** + * 获得销售订单项列表 + * + * @param orderId 销售订单编号 + * @return 销售订单项列表 + */ + List getSaleOrderItemListByOrderId(Long orderId); + + /** + * 获得销售订单项 List + * + * @param orderIds 销售订单编号数组 + * @return 销售订单项 List + */ + List getSaleOrderItemListByOrderIds(Collection orderIds); + } \ No newline at end of file diff --git a/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/service/sale/ErpSaleOrderServiceImpl.java b/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/service/sale/ErpSaleOrderServiceImpl.java index 429633f23..3e5d7d11b 100644 --- a/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/service/sale/ErpSaleOrderServiceImpl.java +++ b/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/service/sale/ErpSaleOrderServiceImpl.java @@ -1,23 +1,36 @@ package cn.iocoder.yudao.module.erp.service.sale; +import cn.hutool.core.collection.CollUtil; import cn.iocoder.yudao.framework.common.pojo.PageResult; +import cn.iocoder.yudao.framework.common.util.number.MoneyUtils; import cn.iocoder.yudao.framework.common.util.object.BeanUtils; import cn.iocoder.yudao.module.erp.controller.admin.sale.vo.order.ErpSaleOrderPageReqVO; import cn.iocoder.yudao.module.erp.controller.admin.sale.vo.order.ErpSaleOrderSaveReqVO; +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.ErpSalesOrderItemDO; +import cn.iocoder.yudao.module.erp.dal.dataobject.sale.ErpSaleOrderItemDO; +import cn.iocoder.yudao.module.erp.dal.mysql.sale.ErpSaleOrderItemMapper; import cn.iocoder.yudao.module.erp.dal.mysql.sale.ErpSaleOrderMapper; -import cn.iocoder.yudao.module.erp.dal.mysql.sale.ErpSalesOrderItemMapper; +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.product.ErpProductService; import jakarta.annotation.Resource; import org.springframework.stereotype.Service; import org.springframework.transaction.annotation.Transactional; import org.springframework.validation.annotation.Validated; +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.exception.util.ServiceExceptionUtil.exception; +import static cn.iocoder.yudao.framework.common.util.collection.CollectionUtils.*; import static cn.iocoder.yudao.module.erp.enums.ErrorCodeConstants.*; +// TODO 芋艿:记录操作日志 + /** * ERP 销售订单 Service 实现类 * @@ -30,61 +43,142 @@ public class ErpSaleOrderServiceImpl implements ErpSaleOrderService { @Resource private ErpSaleOrderMapper saleOrderMapper; @Resource - private ErpSalesOrderItemMapper salesOrderItemMapper; + private ErpSaleOrderItemMapper saleOrderItemMapper; + + @Resource + private ErpNoRedisDAO noRedisDAO; + + @Resource + private ErpProductService productService; + @Resource + private ErpCustomerService customerService; @Override @Transactional(rollbackFor = Exception.class) public Long createSaleOrder(ErpSaleOrderSaveReqVO createReqVO) { - // 插入 - ErpSaleOrderDO saleOrder = BeanUtils.toBean(createReqVO, ErpSaleOrderDO.class); + // 1.1 校验订单项的有效性 + List saleOrderItems = validateSaleOrderItems(createReqVO.getItems()); + // 1.2 校验客户 + customerService.validateCustomer(createReqVO.getCustomerId()); + // 1.3 生成调拨单号,并校验唯一性 + String no = noRedisDAO.generate(ErpNoRedisDAO.STOCK_MOVE_NO_PREFIX); + if (saleOrderMapper.selectByNo(no) != null) { + throw exception(STOCK_MOVE_NO_EXISTS); + } + + // 2.1 插入订单 + ErpSaleOrderDO saleOrder = BeanUtils.toBean(createReqVO, ErpSaleOrderDO.class, in -> in + .setNo(no).setStatus(ErpAuditStatus.PROCESS.getStatus()) + .setTotalCount(getSumValue(saleOrderItems, ErpSaleOrderItemDO::getCount, BigDecimal::add)) + .setTotalPrice(getSumValue(saleOrderItems, ErpSaleOrderItemDO::getTotalPrice, BigDecimal::add, BigDecimal.ZERO))); saleOrderMapper.insert(saleOrder); - - // 插入子表 -// createSalesOrderItemsList(saleOrder.getId(), createReqVO.getSalesOrderItems()); - // 返回 + // 2.2 插入订单项 + saleOrderItems.forEach(o -> o.setOrderId(saleOrder.getId())); + saleOrderItemMapper.insertBatch(saleOrderItems); return saleOrder.getId(); } - private void createSalesOrderItemsList(Long id, List list) { - list.forEach(o -> o.setId(id)); - salesOrderItemMapper.insertBatch(list); - } - @Override @Transactional(rollbackFor = Exception.class) public void updateSaleOrder(ErpSaleOrderSaveReqVO updateReqVO) { - // 校验存在 - validateSaleOrderExists(updateReqVO.getId()); - // 更新 - ErpSaleOrderDO updateObj = BeanUtils.toBean(updateReqVO, ErpSaleOrderDO.class); + // 1.1 校验存在 + ErpSaleOrderDO saleOrder = validateSaleOrderExists(updateReqVO.getId()); + if (ErpAuditStatus.APPROVE.getStatus().equals(saleOrder.getStatus())) { + throw exception(STOCK_MOVE_UPDATE_FAIL_APPROVE, saleOrder.getNo()); + } + // 1.2 校验客户 + customerService.validateCustomer(updateReqVO.getCustomerId()); + // 1.3 校验订单项的有效性 + List saleOrderItems = validateSaleOrderItems(updateReqVO.getItems()); + + // 2.1 更新订单 + ErpSaleOrderDO updateObj = BeanUtils.toBean(updateReqVO, ErpSaleOrderDO.class, in -> in + .setTotalCount(getSumValue(saleOrderItems, ErpSaleOrderItemDO::getCount, BigDecimal::add)) + .setTotalPrice(getSumValue(saleOrderItems, ErpSaleOrderItemDO::getTotalPrice, BigDecimal::add))); saleOrderMapper.updateById(updateObj); - - // 更新子表 -// updateSalesOrderItemsList(updateReqVO.getId(), updateReqVO.getSalesOrderItems()); - } - - private void updateSalesOrderItemsList(Long id, List list) { - deleteSalesOrderItemsById(id); - list.forEach(o -> o.setId(null).setUpdater(null).setUpdateTime(null)); // 解决更新情况下:1)id 冲突;2)updateTime 不更新 - createSalesOrderItemsList(id, list); + // 2.2 更新订单项 + updateSaleOrderItemList(updateReqVO.getId(), saleOrderItems); } @Override @Transactional(rollbackFor = Exception.class) - public void deleteSaleOrder(Long id) { - // 校验存在 - validateSaleOrderExists(id); - // 删除 - saleOrderMapper.deleteById(id); + public void updateSaleOrderStatus(Long id, Integer status) { + boolean approve = ErpAuditStatus.APPROVE.getStatus().equals(status); + // 1.1 校验存在 + ErpSaleOrderDO saleOrder = validateSaleOrderExists(id); + // 1.2 校验状态 + if (saleOrder.getStatus().equals(status)) { + throw exception(approve ? STOCK_MOVE_APPROVE_FAIL : STOCK_MOVE_PROCESS_FAIL); + } + // TODO @芋艿:需要校验是不是有入库、有退货 - // 删除子表 - deleteSalesOrderItemsById(id); + // 2. 更新状态 + int updateCount = saleOrderMapper.updateByIdAndStatus(id, saleOrder.getStatus(), + new ErpSaleOrderDO().setStatus(status)); + if (updateCount == 0) { + throw exception(approve ? STOCK_MOVE_APPROVE_FAIL : STOCK_MOVE_PROCESS_FAIL); + } } - private void validateSaleOrderExists(Long id) { - if (saleOrderMapper.selectById(id) == null) { - throw exception(SALE_ORDER_NOT_EXISTS); + private List validateSaleOrderItems(List list) { + // 1. 校验产品存在 + List productList = productService.validProductList( + convertSet(list, ErpSaleOrderSaveReqVO.Item::getProductId)); + Map productMap = convertMap(productList, ErpProductDO::getId); + // 2. 转化为 ErpSaleOrderItemDO 列表 + return convertList(list, o -> BeanUtils.toBean(o, ErpSaleOrderItemDO.class, item -> item + .setProductUnitId(productMap.get(item.getProductId()).getUnitId()) + .setTotalPrice(MoneyUtils.priceMultiply(item.getProductPrice(), item.getCount())))); + } + + private void updateSaleOrderItemList(Long id, List newList) { + // 第一步,对比新老数据,获得添加、修改、删除的列表 + List oldList = saleOrderItemMapper.selectListByOrderId(id); + List> diffList = diffList(oldList, newList, // id 不同,就认为是不同的记录 + (oldVal, newVal) -> oldVal.getId().equals(newVal.getId())); + + // 第二步,批量添加、修改、删除 + if (CollUtil.isNotEmpty(diffList.get(0))) { + diffList.get(0).forEach(o -> o.setOrderId(id)); + saleOrderItemMapper.insertBatch(diffList.get(0)); } + if (CollUtil.isNotEmpty(diffList.get(1))) { + saleOrderItemMapper.updateBatch(diffList.get(1)); + } + if (CollUtil.isNotEmpty(diffList.get(2))) { + saleOrderItemMapper.deleteBatchIds(convertList(diffList.get(2), ErpSaleOrderItemDO::getId)); + } + } + + @Override + @Transactional(rollbackFor = Exception.class) + public void deleteSaleOrder(List ids) { + // 1. 校验不处于已审批 + List saleOrders = saleOrderMapper.selectBatchIds(ids); + if (CollUtil.isEmpty(saleOrders)) { + return; + } + saleOrders.forEach(saleOrder -> { + if (ErpAuditStatus.APPROVE.getStatus().equals(saleOrder.getStatus())) { + throw exception(STOCK_MOVE_DELETE_FAIL_APPROVE, saleOrder.getNo()); + } + }); + + // 2. 遍历删除,并记录操作日志 + saleOrders.forEach(saleOrder -> { + // 2.1 删除订单 + saleOrderMapper.deleteById(saleOrder.getId()); + // 2.2 删除订单项 + saleOrderItemMapper.deleteByOrderId(saleOrder.getId()); + }); + } + + private ErpSaleOrderDO validateSaleOrderExists(Long id) { + ErpSaleOrderDO saleOrder = saleOrderMapper.selectById(id); + if (saleOrder == null) { + throw exception(STOCK_MOVE_NOT_EXISTS); + } + return saleOrder; } @Override @@ -97,10 +191,19 @@ public class ErpSaleOrderServiceImpl implements ErpSaleOrderService { return saleOrderMapper.selectPage(pageReqVO); } - // ==================== 子表(ERP 销售订单明细) ==================== + // ==================== 订单项 ==================== - private void deleteSalesOrderItemsById(Long id) { - salesOrderItemMapper.deleteById(id); + @Override + public List getSaleOrderItemListByOrderId(Long moveId) { + return saleOrderItemMapper.selectListByOrderId(moveId); + } + + @Override + public List getSaleOrderItemListByOrderIds(Collection moveIds) { + if (CollUtil.isEmpty(moveIds)) { + return Collections.emptyList(); + } + return saleOrderItemMapper.selectListByOrderIds(moveIds); } } \ No newline at end of file diff --git a/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/service/stock/ErpStockService.java b/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/service/stock/ErpStockService.java index 91224c7fa..7ca13548e 100644 --- a/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/service/stock/ErpStockService.java +++ b/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/service/stock/ErpStockService.java @@ -30,6 +30,14 @@ public interface ErpStockService { */ ErpStockDO getStock(Long productId, Long warehouseId); + /** + * 获得产品库存数量 + * + * @param productId 产品编号 + * @return 产品库存数量 + */ + BigDecimal getStockCount(Long productId); + /** * 获得产品库存分页 * diff --git a/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/service/stock/ErpStockServiceImpl.java b/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/service/stock/ErpStockServiceImpl.java index 91495acda..432153759 100644 --- a/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/service/stock/ErpStockServiceImpl.java +++ b/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/service/stock/ErpStockServiceImpl.java @@ -49,6 +49,11 @@ public class ErpStockServiceImpl implements ErpStockService { return stockMapper.selectByProductIdAndWarehouseId(productId, warehouseId); } + @Override + public BigDecimal getStockCount(Long productId) { + return stockMapper.selectSumByProductId(productId); + } + @Override public PageResult getStockPage(ErpStockPageReqVO pageReqVO) { return stockMapper.selectPage(pageReqVO); From 5fd23cacc7da16488aebd091d34967b8597e2fe4 Mon Sep 17 00:00:00 2001 From: YunaiV Date: Sat, 10 Feb 2024 00:07:08 +0800 Subject: [PATCH 092/119] =?UTF-8?q?=E2=9C=A8=20ERP=EF=BC=9A=E5=A2=9E?= =?UTF-8?q?=E5=8A=A0=20ERP=20=E9=94=80=E5=94=AE=E8=AE=A2=E5=8D=95=E7=9A=84?= =?UTF-8?q?=E5=AE=9E=E7=8E=B0=2050%=EF=BC=88=E8=AF=A6=E6=83=85=EF=BC=89?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit 新年快乐~ --- .../sale/vo/order/ErpSaleOrderPageReqVO.java | 16 ++++++++ .../sale/vo/order/ErpSaleOrderRespVO.java | 40 ++++++++++++++----- .../admin/stock/ErpStockController.java | 8 ++++ .../dal/mysql/sale/ErpSaleOrderMapper.java | 24 +++++++++-- .../product/ErpProductServiceImpl.java | 3 ++ .../erp/service/stock/ErpStockService.java | 2 + .../service/stock/ErpStockServiceImpl.java | 3 +- 7 files changed, 82 insertions(+), 14 deletions(-) diff --git a/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/controller/admin/sale/vo/order/ErpSaleOrderPageReqVO.java b/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/controller/admin/sale/vo/order/ErpSaleOrderPageReqVO.java index c5d748f22..ae430d78f 100644 --- a/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/controller/admin/sale/vo/order/ErpSaleOrderPageReqVO.java +++ b/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/controller/admin/sale/vo/order/ErpSaleOrderPageReqVO.java @@ -30,6 +30,19 @@ public class ErpSaleOrderPageReqVO extends PageParam { */ public static final Integer IN_STATUS_ALL = 2; + /** + * 退货状态 - 无 + */ + public static final Integer RETURN_STATUS_NONE = 0; + /** + * 退货状态 - 部分 + */ + public static final Integer RETURN_STATUS_PART = 1; + /** + * 退货状态 - 全部 + */ + public static final Integer RETURN_STATUS_ALL = 2; + @Schema(description = "销售单编号", example = "XS001") private String no; @@ -55,4 +68,7 @@ public class ErpSaleOrderPageReqVO extends PageParam { @Schema(description = "入库状态", example = "2") private Integer inStatus; + @Schema(description = "退货状态", example = "2") + private Integer returnStatus; + } \ No newline at end of file diff --git a/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/controller/admin/sale/vo/order/ErpSaleOrderRespVO.java b/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/controller/admin/sale/vo/order/ErpSaleOrderRespVO.java index 8fd879621..c90d4b63b 100644 --- a/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/controller/admin/sale/vo/order/ErpSaleOrderRespVO.java +++ b/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/controller/admin/sale/vo/order/ErpSaleOrderRespVO.java @@ -23,22 +23,33 @@ public class ErpSaleOrderRespVO { @ExcelProperty("销售单编号") private String no; + @Schema(description = "销售状态", requiredMode = Schema.RequiredMode.REQUIRED, example = "2") + @ExcelProperty("销售状态") + private Integer status; + @Schema(description = "客户编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "1724") private Long customerId; @Schema(description = "客户名称", example = "芋道") @ExcelProperty("客户名称") private String customerName; - @Schema(description = "下单时间", requiredMode = Schema.RequiredMode.REQUIRED) - @ExcelProperty("下单时间") - private LocalDateTime orderTime; + @Schema(description = "结算账户编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "311.89") + @ExcelProperty("结算账户编号") + private Long accountId; @Schema(description = "销售员编号", example = "1888") private Long saleUserId; - @Schema(description = "结算账户编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "311.89") - @ExcelProperty("结算账户编号") - private Long accountId; + @Schema(description = "下单时间", requiredMode = Schema.RequiredMode.REQUIRED) + @ExcelProperty("下单时间") + private LocalDateTime orderTime; + + @Schema(description = "合计数量", requiredMode = Schema.RequiredMode.REQUIRED, example = "15663") + @ExcelProperty("合计数量") + private BigDecimal totalCount; + @Schema(description = "最终合计价格", requiredMode = Schema.RequiredMode.REQUIRED, example = "24906") + @ExcelProperty("最终合计价格") + private BigDecimal totalPrice; @Schema(description = "合计产品价格,单位:元", requiredMode = Schema.RequiredMode.REQUIRED, example = "7127") private BigDecimal totalProductPrice; @@ -56,10 +67,6 @@ public class ErpSaleOrderRespVO { @NotNull(message = "定金金额,单位:元不能为空") private BigDecimal depositPrice; - @Schema(description = "销售状态", requiredMode = Schema.RequiredMode.REQUIRED, example = "2") - @ExcelProperty("销售状态") - private Integer status; - @Schema(description = "附件地址", example = "https://www.iocoder.cn") @ExcelProperty("附件地址") private String fileUrl; @@ -84,6 +91,16 @@ 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 returnCount; + @Data public static class Item { @@ -106,6 +123,9 @@ public class ErpSaleOrderRespVO { @Schema(description = "税率,百分比", example = "99.88") private BigDecimal taxPercent; + @Schema(description = "税额,单位:元", example = "100.00") + private BigDecimal taxPrice; + @Schema(description = "备注", example = "随便") private String remark; diff --git a/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/controller/admin/stock/ErpStockController.java b/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/controller/admin/stock/ErpStockController.java index 224468657..912f59731 100644 --- a/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/controller/admin/stock/ErpStockController.java +++ b/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/controller/admin/stock/ErpStockController.java @@ -31,6 +31,7 @@ import org.springframework.web.bind.annotation.RequestParam; import org.springframework.web.bind.annotation.RestController; import java.io.IOException; +import java.math.BigDecimal; import java.util.List; import java.util.Map; @@ -66,6 +67,13 @@ public class ErpStockController { return success(BeanUtils.toBean(stock, ErpStockRespVO.class)); } + @GetMapping("/get-count") + @Operation(summary = "获得产品库存数量") + @Parameter(name = "productId", description = "产品编号", example = "10") + public CommonResult getStockCount(@RequestParam("productId") Long productId) { + return success(stockService.getStockCount(productId)); + } + @GetMapping("/page") @Operation(summary = "获得产品库存分页") @PreAuthorize("@ss.hasPermission('erp:stock:query')") diff --git a/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/dal/mysql/sale/ErpSaleOrderMapper.java b/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/dal/mysql/sale/ErpSaleOrderMapper.java index d39c1ee4d..70ff75285 100644 --- a/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/dal/mysql/sale/ErpSaleOrderMapper.java +++ b/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/dal/mysql/sale/ErpSaleOrderMapper.java @@ -6,10 +6,12 @@ import cn.iocoder.yudao.framework.mybatis.core.mapper.BaseMapperX; import cn.iocoder.yudao.framework.mybatis.core.query.MPJLambdaWrapperX; import cn.iocoder.yudao.module.erp.controller.admin.sale.vo.order.ErpSaleOrderPageReqVO; import cn.iocoder.yudao.module.erp.dal.dataobject.sale.ErpSaleOrderDO; -import cn.iocoder.yudao.module.erp.dal.dataobject.stock.ErpStockOutItemDO; +import cn.iocoder.yudao.module.erp.dal.dataobject.sale.ErpSaleOrderItemDO; import com.baomidou.mybatisplus.core.conditions.update.LambdaUpdateWrapper; import org.apache.ibatis.annotations.Mapper; +import java.util.Objects; + /** * ERP 销售订单 Mapper * @@ -27,9 +29,25 @@ public interface ErpSaleOrderMapper extends BaseMapperX { .likeIfPresent(ErpSaleOrderDO::getRemark, reqVO.getRemark()) .eqIfPresent(ErpSaleOrderDO::getCreator, reqVO.getCreator()) .orderByDesc(ErpSaleOrderDO::getId); + // 入库状态。为什么需要 t. 的原因,是因为联表查询时,需要指定表名,不然会报 in_count 错误 + if (Objects.equals(reqVO.getInStatus(), ErpSaleOrderPageReqVO.IN_STATUS_NONE)) { + query.eq(ErpSaleOrderDO::getInCount, 0); + } else if (Objects.equals(reqVO.getInStatus(), ErpSaleOrderPageReqVO.IN_STATUS_PART)) { + query.gt(ErpSaleOrderDO::getInCount, 0).apply("t.in_count < t.total_count"); + } else if (Objects.equals(reqVO.getInStatus(), ErpSaleOrderPageReqVO.IN_STATUS_ALL)) { + query.apply("t.in_count = t.total_count"); + } + // 退货状态 + if (Objects.equals(reqVO.getReturnStatus(), ErpSaleOrderPageReqVO.RETURN_STATUS_NONE)) { + query.eq(ErpSaleOrderDO::getReturnCount, 0); + } else if (Objects.equals(reqVO.getReturnStatus(), ErpSaleOrderPageReqVO.RETURN_STATUS_PART)) { + query.gt(ErpSaleOrderDO::getReturnCount, 0).apply("t.return_count < t.total_count"); + } else if (Objects.equals(reqVO.getReturnStatus(), ErpSaleOrderPageReqVO.RETURN_STATUS_ALL)) { + query.apply("t.return_count = t.total_count"); + } if (reqVO.getProductId() != null) { - query.leftJoin(ErpStockOutItemDO.class, ErpStockOutItemDO::getOutId, ErpSaleOrderDO::getId) - .eq(reqVO.getProductId() != null, ErpStockOutItemDO::getProductId, reqVO.getProductId()) + query.leftJoin(ErpSaleOrderItemDO.class, ErpSaleOrderItemDO::getOrderId, ErpSaleOrderDO::getId) + .eq(reqVO.getProductId() != null, ErpSaleOrderItemDO::getProductId, reqVO.getProductId()) .groupBy(ErpSaleOrderDO::getId); // 避免 1 对多查询,产生相同的 1 } return selectJoinPage(reqVO, ErpSaleOrderDO.class, query); diff --git a/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/service/product/ErpProductServiceImpl.java b/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/service/product/ErpProductServiceImpl.java index 53794043f..cbe689c6a 100644 --- a/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/service/product/ErpProductServiceImpl.java +++ b/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/service/product/ErpProductServiceImpl.java @@ -105,6 +105,9 @@ public class ErpProductServiceImpl implements ErpProductService { @Override public List getProductVOList(Collection ids) { + if (CollUtil.isEmpty(ids)) { + return Collections.emptyList(); + } List list = productMapper.selectBatchIds(ids); return buildProductVOList(list); } diff --git a/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/service/stock/ErpStockService.java b/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/service/stock/ErpStockService.java index 7ca13548e..63ad5fefa 100644 --- a/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/service/stock/ErpStockService.java +++ b/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/service/stock/ErpStockService.java @@ -33,6 +33,8 @@ public interface ErpStockService { /** * 获得产品库存数量 * + * 如果不存在库存记录,则返回 0 + * * @param productId 产品编号 * @return 产品库存数量 */ diff --git a/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/service/stock/ErpStockServiceImpl.java b/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/service/stock/ErpStockServiceImpl.java index 432153759..654117047 100644 --- a/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/service/stock/ErpStockServiceImpl.java +++ b/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/service/stock/ErpStockServiceImpl.java @@ -51,7 +51,8 @@ public class ErpStockServiceImpl implements ErpStockService { @Override public BigDecimal getStockCount(Long productId) { - return stockMapper.selectSumByProductId(productId); + BigDecimal count = stockMapper.selectSumByProductId(productId); + return count != null ? count : BigDecimal.ZERO; } @Override From d06a22dab34315f774aa68da9e3f8f6c2ba4c768 Mon Sep 17 00:00:00 2001 From: YunaiV Date: Sat, 10 Feb 2024 08:32:27 +0800 Subject: [PATCH 093/119] =?UTF-8?q?=E2=9C=A8=20ERP=EF=BC=9A=E5=A2=9E?= =?UTF-8?q?=E5=8A=A0=E7=BB=93=E7=AE=97=E8=B4=A6=E6=88=B7=20100%?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../module/erp/enums/ErrorCodeConstants.java | 9 ++ .../admin/finance/ErpAccountController.java | 106 +++++++++++++ .../admin/finance/vo/ErpAccountPageReqVO.java | 24 +++ .../admin/finance/vo/ErpAccountRespVO.java | 50 ++++++ .../admin/finance/vo/ErpAccountSaveReqVO.java | 36 +++++ .../sale/vo/order/ErpSaleOrderSaveReqVO.java | 11 +- .../dal/dataobject/finance/ErpAccountDO.java | 56 +++++++ .../dal/mysql/finance/ErpAccountMapper.java | 36 +++++ .../erp/dal/redis/no/ErpNoRedisDAO.java | 5 + .../service/finance/ErpAccountService.java | 70 +++++++++ .../finance/ErpAccountServiceImpl.java | 99 ++++++++++++ .../service/sale/ErpSaleOrderServiceImpl.java | 64 +++++--- .../mapper/finance/ErpAccountMapper.xml | 12 ++ .../finance/ErpAccountServiceImplTest.java | 142 ++++++++++++++++++ 14 files changed, 693 insertions(+), 27 deletions(-) create mode 100644 yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/controller/admin/finance/ErpAccountController.java create mode 100644 yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/controller/admin/finance/vo/ErpAccountPageReqVO.java create mode 100644 yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/controller/admin/finance/vo/ErpAccountRespVO.java create mode 100644 yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/controller/admin/finance/vo/ErpAccountSaveReqVO.java create mode 100644 yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/dal/dataobject/finance/ErpAccountDO.java create mode 100644 yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/dal/mysql/finance/ErpAccountMapper.java create mode 100644 yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/service/finance/ErpAccountService.java create mode 100644 yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/service/finance/ErpAccountServiceImpl.java create mode 100644 yudao-module-erp/yudao-module-erp-biz/src/main/resources/mapper/finance/ErpAccountMapper.xml create mode 100644 yudao-module-erp/yudao-module-erp-biz/src/test/java/cn/iocoder/yudao/module/erp/service/finance/ErpAccountServiceImplTest.java diff --git a/yudao-module-erp/yudao-module-erp-api/src/main/java/cn/iocoder/yudao/module/erp/enums/ErrorCodeConstants.java b/yudao-module-erp/yudao-module-erp-api/src/main/java/cn/iocoder/yudao/module/erp/enums/ErrorCodeConstants.java index 7c04c19f1..958e25898 100644 --- a/yudao-module-erp/yudao-module-erp-api/src/main/java/cn/iocoder/yudao/module/erp/enums/ErrorCodeConstants.java +++ b/yudao-module-erp/yudao-module-erp-api/src/main/java/cn/iocoder/yudao/module/erp/enums/ErrorCodeConstants.java @@ -19,6 +19,11 @@ public interface ErrorCodeConstants { // ========== ERP 销售订单(1-030-201-000) ========== ErrorCode SALE_ORDER_NOT_EXISTS = new ErrorCode(1_020_201_000, "销售订单不存在"); + ErrorCode SALE_ORDER_DELETE_FAIL_APPROVE = new ErrorCode(1_020_201_001, "销售订单({})已审核,无法删除"); + ErrorCode SALE_ORDER_PROCESS_FAIL = new ErrorCode(1_020_201_002, "反审核失败,只有已审核的销售订单才能反审核"); + 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, "销售订单({})已审核,无法修改"); // ========== ERP 仓库 1-030-400-000 ========== ErrorCode WAREHOUSE_NOT_EXISTS = new ErrorCode(1_030_400_000, "仓库不存在"); @@ -78,4 +83,8 @@ public interface ErrorCodeConstants { ErrorCode PRODUCT_UNIT_NAME_DUPLICATE = new ErrorCode(1_030_502_001, "已存在该名字的产品单位"); ErrorCode PRODUCT_UNIT_EXITS_PRODUCT = new ErrorCode(1_030_502_002, "存在产品使用该单位,无法删除"); + // ========== ERP 结算账户 1-030-600-000 ========== + ErrorCode ACCOUNT_NOT_EXISTS = new ErrorCode(1_030_600_000, "结算账户不存在"); + ErrorCode ACCOUNT_NOT_ENABLE = new ErrorCode(1_030_600_001, "结算账户({})未启用"); + } diff --git a/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/controller/admin/finance/ErpAccountController.java b/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/controller/admin/finance/ErpAccountController.java new file mode 100644 index 000000000..a66d28bdf --- /dev/null +++ b/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/controller/admin/finance/ErpAccountController.java @@ -0,0 +1,106 @@ +package cn.iocoder.yudao.module.erp.controller.admin.finance; + +import cn.iocoder.yudao.framework.common.pojo.CommonResult; +import cn.iocoder.yudao.framework.common.pojo.PageParam; +import cn.iocoder.yudao.framework.common.pojo.PageResult; +import cn.iocoder.yudao.framework.common.util.object.BeanUtils; +import cn.iocoder.yudao.framework.excel.core.util.ExcelUtils; +import cn.iocoder.yudao.framework.operatelog.core.annotations.OperateLog; +import cn.iocoder.yudao.module.erp.controller.admin.finance.vo.ErpAccountPageReqVO; +import cn.iocoder.yudao.module.erp.controller.admin.finance.vo.ErpAccountRespVO; +import cn.iocoder.yudao.module.erp.controller.admin.finance.vo.ErpAccountSaveReqVO; +import cn.iocoder.yudao.module.erp.dal.dataobject.finance.ErpAccountDO; +import cn.iocoder.yudao.module.erp.service.finance.ErpAccountService; +import io.swagger.v3.oas.annotations.Operation; +import io.swagger.v3.oas.annotations.Parameter; +import io.swagger.v3.oas.annotations.Parameters; +import io.swagger.v3.oas.annotations.tags.Tag; +import jakarta.annotation.Resource; +import jakarta.servlet.http.HttpServletResponse; +import jakarta.validation.Valid; +import org.springframework.security.access.prepost.PreAuthorize; +import org.springframework.validation.annotation.Validated; +import org.springframework.web.bind.annotation.*; + +import java.io.IOException; +import java.util.List; + +import static cn.iocoder.yudao.framework.common.pojo.CommonResult.success; +import static cn.iocoder.yudao.framework.operatelog.core.enums.OperateTypeEnum.EXPORT; + +@Tag(name = "管理后台 - ERP 结算账户") +@RestController +@RequestMapping("/erp/account") +@Validated +public class ErpAccountController { + + @Resource + private ErpAccountService accountService; + + @PostMapping("/create") + @Operation(summary = "创建结算账户") + @PreAuthorize("@ss.hasPermission('erp:account:create')") + public CommonResult createAccount(@Valid @RequestBody ErpAccountSaveReqVO createReqVO) { + return success(accountService.createAccount(createReqVO)); + } + + @PutMapping("/update") + @Operation(summary = "更新结算账户") + @PreAuthorize("@ss.hasPermission('erp:account:update')") + public CommonResult updateAccount(@Valid @RequestBody ErpAccountSaveReqVO updateReqVO) { + accountService.updateAccount(updateReqVO); + return success(true); + } + + @PutMapping("/update-default-status") + @Operation(summary = "更新结算账户默认状态") + @Parameters({ + @Parameter(name = "id", description = "编号", required = true), + @Parameter(name = "status", description = "状态", required = true) + }) + public CommonResult updateAccountDefaultStatus(@RequestParam("id") Long id, + @RequestParam("defaultStatus") Boolean defaultStatus) { + accountService.updateAccountDefaultStatus(id, defaultStatus); + return success(true); + } + + @DeleteMapping("/delete") + @Operation(summary = "删除结算账户") + @Parameter(name = "id", description = "编号", required = true) + @PreAuthorize("@ss.hasPermission('erp:account:delete')") + public CommonResult deleteAccount(@RequestParam("id") Long id) { + accountService.deleteAccount(id); + return success(true); + } + + @GetMapping("/get") + @Operation(summary = "获得结算账户") + @Parameter(name = "id", description = "编号", required = true, example = "1024") + @PreAuthorize("@ss.hasPermission('erp:account:query')") + public CommonResult getAccount(@RequestParam("id") Long id) { + ErpAccountDO account = accountService.getAccount(id); + return success(BeanUtils.toBean(account, ErpAccountRespVO.class)); + } + + @GetMapping("/page") + @Operation(summary = "获得结算账户分页") + @PreAuthorize("@ss.hasPermission('erp:account:query')") + public CommonResult> getAccountPage(@Valid ErpAccountPageReqVO pageReqVO) { + PageResult pageResult = accountService.getAccountPage(pageReqVO); + return success(BeanUtils.toBean(pageResult, ErpAccountRespVO.class)); + } + + @GetMapping("/export-excel") + @Operation(summary = "导出结算账户 Excel") + @PreAuthorize("@ss.hasPermission('erp:account:export')") + @OperateLog(type = EXPORT) + public void exportAccountExcel(@Valid ErpAccountPageReqVO pageReqVO, + HttpServletResponse response) throws IOException { + pageReqVO.setPageSize(PageParam.PAGE_SIZE_NONE); + List list = accountService.getAccountPage(pageReqVO).getList(); + // 导出 Excel + ExcelUtils.write(response, "结算账户.xls", "数据", ErpAccountRespVO.class, + BeanUtils.toBean(list, ErpAccountRespVO.class)); + } + +} \ No newline at end of file diff --git a/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/controller/admin/finance/vo/ErpAccountPageReqVO.java b/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/controller/admin/finance/vo/ErpAccountPageReqVO.java new file mode 100644 index 000000000..682689e5e --- /dev/null +++ b/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/controller/admin/finance/vo/ErpAccountPageReqVO.java @@ -0,0 +1,24 @@ +package cn.iocoder.yudao.module.erp.controller.admin.finance.vo; + +import cn.iocoder.yudao.framework.common.pojo.PageParam; +import io.swagger.v3.oas.annotations.media.Schema; +import lombok.Data; +import lombok.EqualsAndHashCode; +import lombok.ToString; + +@Schema(description = "管理后台 - ERP 结算账户分页 Request VO") +@Data +@EqualsAndHashCode(callSuper = true) +@ToString(callSuper = true) +public class ErpAccountPageReqVO extends PageParam { + + @Schema(description = "账户编码", example = "A88") + private String no; + + @Schema(description = "账户名称", example = "张三") + private String name; + + @Schema(description = "备注", example = "随便") + private String remark; + +} \ No newline at end of file diff --git a/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/controller/admin/finance/vo/ErpAccountRespVO.java b/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/controller/admin/finance/vo/ErpAccountRespVO.java new file mode 100644 index 000000000..57e6c10b5 --- /dev/null +++ b/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/controller/admin/finance/vo/ErpAccountRespVO.java @@ -0,0 +1,50 @@ +package cn.iocoder.yudao.module.erp.controller.admin.finance.vo; + +import cn.iocoder.yudao.framework.excel.core.annotations.DictFormat; +import cn.iocoder.yudao.module.system.enums.DictTypeConstants; +import com.alibaba.excel.annotation.ExcelIgnoreUnannotated; +import com.alibaba.excel.annotation.ExcelProperty; +import io.swagger.v3.oas.annotations.media.Schema; +import lombok.Data; + +import java.time.LocalDateTime; + +@Schema(description = "管理后台 - ERP 结算账户 Response VO") +@Data +@ExcelIgnoreUnannotated +public class ErpAccountRespVO { + + @Schema(description = "结算账户编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "28684") + @ExcelProperty("结算账户编号") + private Long id; + + @Schema(description = "账户名称", requiredMode = Schema.RequiredMode.REQUIRED, example = "张三") + @ExcelProperty("账户名称") + private String name; + + @Schema(description = "账户编码", example = "A88") + @ExcelProperty("账户编码") + private String no; + + @Schema(description = "备注", example = "随便") + @ExcelProperty("备注") + private String remark; + + @Schema(description = "开启状态", requiredMode = Schema.RequiredMode.REQUIRED, example = "1") + @ExcelProperty("开启状态") + @DictFormat(DictTypeConstants.COMMON_STATUS) + private Integer status; + + @Schema(description = "排序", requiredMode = Schema.RequiredMode.REQUIRED, example = "1") + @ExcelProperty("排序") + private Integer sort; + + @Schema(description = "是否默认", example = "1") + @ExcelProperty("是否默认") + private Boolean defaultStatus; + + @Schema(description = "创建时间", requiredMode = Schema.RequiredMode.REQUIRED) + @ExcelProperty("创建时间") + private LocalDateTime createTime; + +} \ No newline at end of file diff --git a/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/controller/admin/finance/vo/ErpAccountSaveReqVO.java b/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/controller/admin/finance/vo/ErpAccountSaveReqVO.java new file mode 100644 index 000000000..1f96946a7 --- /dev/null +++ b/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/controller/admin/finance/vo/ErpAccountSaveReqVO.java @@ -0,0 +1,36 @@ +package cn.iocoder.yudao.module.erp.controller.admin.finance.vo; + +import cn.iocoder.yudao.framework.common.enums.CommonStatusEnum; +import cn.iocoder.yudao.framework.common.validation.InEnum; +import io.swagger.v3.oas.annotations.media.Schema; +import jakarta.validation.constraints.NotEmpty; +import jakarta.validation.constraints.NotNull; +import lombok.Data; + +@Schema(description = "管理后台 - ERP 结算账户新增/修改 Request VO") +@Data +public class ErpAccountSaveReqVO { + + @Schema(description = "结算账户编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "28684") + private Long id; + + @Schema(description = "账户名称", requiredMode = Schema.RequiredMode.REQUIRED, example = "张三") + @NotEmpty(message = "账户名称不能为空") + private String name; + + @Schema(description = "账户编码", example = "A88") + private String no; + + @Schema(description = "备注", example = "随便") + private String remark; + + @Schema(description = "开启状态", requiredMode = Schema.RequiredMode.REQUIRED, example = "1") + @NotNull(message = "开启状态不能为空") + @InEnum(value = CommonStatusEnum.class) + private Integer status; + + @Schema(description = "排序", requiredMode = Schema.RequiredMode.REQUIRED, example = "1") + @NotNull(message = "排序不能为空") + private Integer sort; + +} \ No newline at end of file diff --git a/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/controller/admin/sale/vo/order/ErpSaleOrderSaveReqVO.java b/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/controller/admin/sale/vo/order/ErpSaleOrderSaveReqVO.java index 1706915aa..e23a1fab3 100644 --- a/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/controller/admin/sale/vo/order/ErpSaleOrderSaveReqVO.java +++ b/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/controller/admin/sale/vo/order/ErpSaleOrderSaveReqVO.java @@ -1,7 +1,6 @@ package cn.iocoder.yudao.module.erp.controller.admin.sale.vo.order; import io.swagger.v3.oas.annotations.media.Schema; -import jakarta.validation.constraints.NotEmpty; import jakarta.validation.constraints.NotNull; import lombok.Data; @@ -16,10 +15,6 @@ public class ErpSaleOrderSaveReqVO { @Schema(description = "编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "17386") private Long id; - @Schema(description = "销售单编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "XS001") - @NotEmpty(message = "销售单编号不能为空") - private String no; - @Schema(description = "客户编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "1724") @NotNull(message = "客户编号不能为空") private Long customerId; @@ -31,15 +26,13 @@ public class ErpSaleOrderSaveReqVO { @Schema(description = "销售员编号", example = "1888") private Long saleUserId; - @Schema(description = "结算账户编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "31189") - @NotNull(message = "结算账户编号不能为空") + @Schema(description = "结算账户编号", example = "31189") private Long accountId; @Schema(description = "优惠率,百分比", requiredMode = Schema.RequiredMode.REQUIRED, example = "99.88") private BigDecimal discountPercent; - @Schema(description = "定金金额,单位:元", requiredMode = Schema.RequiredMode.REQUIRED, example = "7127") - @NotNull(message = "定金金额,单位:元不能为空") + @Schema(description = "定金金额,单位:元", example = "7127") private BigDecimal depositPrice; @Schema(description = "附件地址", example = "https://www.iocoder.cn") diff --git a/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/dal/dataobject/finance/ErpAccountDO.java b/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/dal/dataobject/finance/ErpAccountDO.java new file mode 100644 index 000000000..fe01cc228 --- /dev/null +++ b/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/dal/dataobject/finance/ErpAccountDO.java @@ -0,0 +1,56 @@ +package cn.iocoder.yudao.module.erp.dal.dataobject.finance; + +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.*; + +/** + * ERP 结算账户 DO + * + * @author 芋道源码 + */ +@TableName("erp_account") +@KeySequence("erp_account_seq") // 用于 Oracle、PostgreSQL、Kingbase、DB2、H2 数据库的主键自增。如果是 MySQL 等数据库,可不写。 +@Data +@EqualsAndHashCode(callSuper = true) +@ToString(callSuper = true) +@Builder +@NoArgsConstructor +@AllArgsConstructor +public class ErpAccountDO extends BaseDO { + + /** + * 结算账户编号 + */ + @TableId + private Long id; + /** + * 账户名称 + */ + private String name; + /** + * 账户编码 + */ + private String no; + /** + * 备注 + */ + private String remark; + /** + * 开启状态 + * + * 枚举 {@link cn.iocoder.yudao.framework.common.enums.CommonStatusEnum} + */ + private Integer status; + /** + * 排序 + */ + private Integer sort; + /** + * 是否默认 + */ + private Boolean defaultStatus; + +} \ No newline at end of file diff --git a/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/dal/mysql/finance/ErpAccountMapper.java b/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/dal/mysql/finance/ErpAccountMapper.java new file mode 100644 index 000000000..d879a933e --- /dev/null +++ b/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/dal/mysql/finance/ErpAccountMapper.java @@ -0,0 +1,36 @@ +package cn.iocoder.yudao.module.erp.dal.mysql.finance; + +import cn.iocoder.yudao.framework.common.pojo.PageResult; +import cn.iocoder.yudao.framework.mybatis.core.mapper.BaseMapperX; +import cn.iocoder.yudao.framework.mybatis.core.query.LambdaQueryWrapperX; +import cn.iocoder.yudao.module.erp.controller.admin.finance.vo.ErpAccountPageReqVO; +import cn.iocoder.yudao.module.erp.dal.dataobject.finance.ErpAccountDO; +import org.apache.ibatis.annotations.Mapper; + +import java.util.List; + +/** + * ERP 结算账户 Mapper + * + * @author 芋道源码 + */ +@Mapper +public interface ErpAccountMapper extends BaseMapperX { + + default PageResult selectPage(ErpAccountPageReqVO reqVO) { + return selectPage(reqVO, new LambdaQueryWrapperX() + .likeIfPresent(ErpAccountDO::getName, reqVO.getName()) + .eqIfPresent(ErpAccountDO::getNo, reqVO.getNo()) + .eqIfPresent(ErpAccountDO::getRemark, reqVO.getRemark()) + .orderByDesc(ErpAccountDO::getId)); + } + + default ErpAccountDO selectByDefaultStatus() { + return selectOne(ErpAccountDO::getDefaultStatus, true); + } + + default List selectListByStatus(Integer status) { + return selectList(ErpAccountDO::getStatus, status); + } + +} \ No newline at end of file diff --git a/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/dal/redis/no/ErpNoRedisDAO.java b/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/dal/redis/no/ErpNoRedisDAO.java index bd2612db1..0e48e97e1 100644 --- a/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/dal/redis/no/ErpNoRedisDAO.java +++ b/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/dal/redis/no/ErpNoRedisDAO.java @@ -38,6 +38,11 @@ public class ErpNoRedisDAO { */ public static final String STOCK_CHECK_NO_PREFIX = "QCPD"; + /** + * 销售订单 {@link cn.iocoder.yudao.module.erp.dal.dataobject.sale.ErpSaleOrderDO} + */ + public static final String SALE_ORDER_NO_PREFIX = "XSDD"; + @Resource private StringRedisTemplate stringRedisTemplate; diff --git a/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/service/finance/ErpAccountService.java b/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/service/finance/ErpAccountService.java new file mode 100644 index 000000000..8e23f0dca --- /dev/null +++ b/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/service/finance/ErpAccountService.java @@ -0,0 +1,70 @@ +package cn.iocoder.yudao.module.erp.service.finance; + +import cn.iocoder.yudao.framework.common.pojo.PageResult; +import cn.iocoder.yudao.module.erp.controller.admin.finance.vo.ErpAccountPageReqVO; +import cn.iocoder.yudao.module.erp.controller.admin.finance.vo.ErpAccountSaveReqVO; +import cn.iocoder.yudao.module.erp.dal.dataobject.finance.ErpAccountDO; +import jakarta.validation.Valid; + +/** + * ERP 结算账户 Service 接口 + * + * @author 芋道源码 + */ +public interface ErpAccountService { + + /** + * 创建结算账户 + * + * @param createReqVO 创建信息 + * @return 编号 + */ + Long createAccount(@Valid ErpAccountSaveReqVO createReqVO); + + /** + * 更新ERP 结算账户 + * + * @param updateReqVO 更新信息 + */ + void updateAccount(@Valid ErpAccountSaveReqVO updateReqVO); + + /** + * 更新结算账户默认状态 + * + * @param id 编号 + * @param defaultStatus 默认状态 + */ + void updateAccountDefaultStatus(Long id, Boolean defaultStatus); + + /** + * 删除结算账户 + * + * @param id 编号 + */ + void deleteAccount(Long id); + + /** + * 获得结算账户 + * + * @param id 编号 + * @return 结算账户 + */ + ErpAccountDO getAccount(Long id); + + /** + * 校验结算账户 + * + * @param id 编号 + * @return 结算账户 + */ + ErpAccountDO validateAccount(Long id); + + /** + * 获得结算账户分页 + * + * @param pageReqVO 分页查询 + * @return 结算账户分页 + */ + PageResult getAccountPage(ErpAccountPageReqVO pageReqVO); + +} \ No newline at end of file diff --git a/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/service/finance/ErpAccountServiceImpl.java b/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/service/finance/ErpAccountServiceImpl.java new file mode 100644 index 000000000..2ff33de1a --- /dev/null +++ b/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/service/finance/ErpAccountServiceImpl.java @@ -0,0 +1,99 @@ +package cn.iocoder.yudao.module.erp.service.finance; + +import cn.iocoder.yudao.framework.common.enums.CommonStatusEnum; +import cn.iocoder.yudao.framework.common.pojo.PageResult; +import cn.iocoder.yudao.framework.common.util.object.BeanUtils; +import cn.iocoder.yudao.module.erp.controller.admin.finance.vo.ErpAccountPageReqVO; +import cn.iocoder.yudao.module.erp.controller.admin.finance.vo.ErpAccountSaveReqVO; +import cn.iocoder.yudao.module.erp.dal.dataobject.finance.ErpAccountDO; +import cn.iocoder.yudao.module.erp.dal.mysql.finance.ErpAccountMapper; +import jakarta.annotation.Resource; +import org.springframework.stereotype.Service; +import org.springframework.validation.annotation.Validated; + +import static cn.iocoder.yudao.framework.common.exception.util.ServiceExceptionUtil.exception; +import static cn.iocoder.yudao.module.erp.enums.ErrorCodeConstants.*; + +/** + * ERP 结算账户 Service 实现类 + * + * @author 芋道源码 + */ +@Service +@Validated +public class ErpAccountServiceImpl implements ErpAccountService { + + @Resource + private ErpAccountMapper accountMapper; + + @Override + public Long createAccount(ErpAccountSaveReqVO createReqVO) { + // 插入 + ErpAccountDO account = BeanUtils.toBean(createReqVO, ErpAccountDO.class); + accountMapper.insert(account); + // 返回 + return account.getId(); + } + + @Override + public void updateAccount(ErpAccountSaveReqVO updateReqVO) { + // 校验存在 + validateAccountExists(updateReqVO.getId()); + // 更新 + ErpAccountDO updateObj = BeanUtils.toBean(updateReqVO, ErpAccountDO.class); + accountMapper.updateById(updateObj); + } + + @Override + public void updateAccountDefaultStatus(Long id, Boolean defaultStatus) { + // 1. 校验存在 + validateAccountExists(id); + + // 2.1 如果开启,则需要关闭所有其它的默认 + if (defaultStatus) { + ErpAccountDO account = accountMapper.selectByDefaultStatus(); + if (account != null) { + accountMapper.updateById(new ErpAccountDO().setId(account.getId()).setDefaultStatus(false)); + } + } + // 2.2 更新对应的默认状态 + accountMapper.updateById(new ErpAccountDO().setId(id).setDefaultStatus(defaultStatus)); + } + + @Override + public void deleteAccount(Long id) { + // 校验存在 + validateAccountExists(id); + // 删除 + accountMapper.deleteById(id); + } + + private void validateAccountExists(Long id) { + if (accountMapper.selectById(id) == null) { + throw exception(ACCOUNT_NOT_EXISTS); + } + } + + @Override + public ErpAccountDO getAccount(Long id) { + return accountMapper.selectById(id); + } + + @Override + public ErpAccountDO validateAccount(Long id) { + ErpAccountDO account = accountMapper.selectById(id); + if (account == null) { + throw exception(ACCOUNT_NOT_EXISTS); + } + if (CommonStatusEnum.isDisable(account.getStatus())) { + throw exception(ACCOUNT_NOT_ENABLE, account.getName()); + } + return account; + } + + @Override + public PageResult getAccountPage(ErpAccountPageReqVO pageReqVO) { + return accountMapper.selectPage(pageReqVO); + } + +} \ No newline at end of file diff --git a/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/service/sale/ErpSaleOrderServiceImpl.java b/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/service/sale/ErpSaleOrderServiceImpl.java index 3e5d7d11b..662eb1189 100644 --- a/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/service/sale/ErpSaleOrderServiceImpl.java +++ b/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/service/sale/ErpSaleOrderServiceImpl.java @@ -13,6 +13,7 @@ import cn.iocoder.yudao.module.erp.dal.mysql.sale.ErpSaleOrderItemMapper; import cn.iocoder.yudao.module.erp.dal.mysql.sale.ErpSaleOrderMapper; 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 jakarta.annotation.Resource; import org.springframework.stereotype.Service; @@ -52,6 +53,8 @@ public class ErpSaleOrderServiceImpl implements ErpSaleOrderService { private ErpProductService productService; @Resource private ErpCustomerService customerService; + @Resource + private ErpAccountService accountService; @Override @Transactional(rollbackFor = Exception.class) @@ -60,17 +63,20 @@ public class ErpSaleOrderServiceImpl implements ErpSaleOrderService { List saleOrderItems = validateSaleOrderItems(createReqVO.getItems()); // 1.2 校验客户 customerService.validateCustomer(createReqVO.getCustomerId()); - // 1.3 生成调拨单号,并校验唯一性 - String no = noRedisDAO.generate(ErpNoRedisDAO.STOCK_MOVE_NO_PREFIX); + // 1.3 校验结算账户 + if (createReqVO.getAccountId() != null) { + accountService.validateAccount(createReqVO.getAccountId()); + } + // 1.4 生成调拨单号,并校验唯一性 + String no = noRedisDAO.generate(ErpNoRedisDAO.SALE_ORDER_NO_PREFIX); if (saleOrderMapper.selectByNo(no) != null) { - throw exception(STOCK_MOVE_NO_EXISTS); + throw exception(SALE_ORDER_NO_EXISTS); } // 2.1 插入订单 ErpSaleOrderDO saleOrder = BeanUtils.toBean(createReqVO, ErpSaleOrderDO.class, in -> in - .setNo(no).setStatus(ErpAuditStatus.PROCESS.getStatus()) - .setTotalCount(getSumValue(saleOrderItems, ErpSaleOrderItemDO::getCount, BigDecimal::add)) - .setTotalPrice(getSumValue(saleOrderItems, ErpSaleOrderItemDO::getTotalPrice, BigDecimal::add, BigDecimal.ZERO))); + .setNo(no).setStatus(ErpAuditStatus.PROCESS.getStatus())); + calculateTotalPrice(saleOrder, saleOrderItems); saleOrderMapper.insert(saleOrder); // 2.2 插入订单项 saleOrderItems.forEach(o -> o.setOrderId(saleOrder.getId())); @@ -84,22 +90,38 @@ public class ErpSaleOrderServiceImpl implements ErpSaleOrderService { // 1.1 校验存在 ErpSaleOrderDO saleOrder = validateSaleOrderExists(updateReqVO.getId()); if (ErpAuditStatus.APPROVE.getStatus().equals(saleOrder.getStatus())) { - throw exception(STOCK_MOVE_UPDATE_FAIL_APPROVE, saleOrder.getNo()); + throw exception(SALE_ORDER_UPDATE_FAIL_APPROVE, saleOrder.getNo()); } // 1.2 校验客户 customerService.validateCustomer(updateReqVO.getCustomerId()); - // 1.3 校验订单项的有效性 + // 1.3 校验结算账户 + if (updateReqVO.getAccountId() != null) { + accountService.validateAccount(updateReqVO.getAccountId()); + } + // 1.4 校验订单项的有效性 List saleOrderItems = validateSaleOrderItems(updateReqVO.getItems()); // 2.1 更新订单 - ErpSaleOrderDO updateObj = BeanUtils.toBean(updateReqVO, ErpSaleOrderDO.class, in -> in - .setTotalCount(getSumValue(saleOrderItems, ErpSaleOrderItemDO::getCount, BigDecimal::add)) - .setTotalPrice(getSumValue(saleOrderItems, ErpSaleOrderItemDO::getTotalPrice, BigDecimal::add))); + ErpSaleOrderDO updateObj = BeanUtils.toBean(updateReqVO, ErpSaleOrderDO.class); + calculateTotalPrice(updateObj, saleOrderItems); saleOrderMapper.updateById(updateObj); // 2.2 更新订单项 updateSaleOrderItemList(updateReqVO.getId(), saleOrderItems); } + private void calculateTotalPrice(ErpSaleOrderDO saleOrder, List saleOrderItems) { + saleOrder.setTotalCount(getSumValue(saleOrderItems, ErpSaleOrderItemDO::getCount, BigDecimal::add)); + saleOrder.setTotalProductPrice(getSumValue(saleOrderItems, ErpSaleOrderItemDO::getTotalPrice, BigDecimal::add, BigDecimal.ZERO)); + saleOrder.setTotalTaxPrice(getSumValue(saleOrderItems, ErpSaleOrderItemDO::getTaxPrice, BigDecimal::add, BigDecimal.ZERO)); + saleOrder.setTotalPrice(saleOrder.getTotalProductPrice().add(saleOrder.getTotalTaxPrice())); + // 计算优惠价格 + if (saleOrder.getDiscountPercent() == null) { + saleOrder.setDiscountPercent(BigDecimal.ZERO); + } + saleOrder.setDiscountPrice(MoneyUtils.priceMultiply(saleOrder.getTotalPrice(), saleOrder.getDiscountPercent())); + saleOrder.setTotalPrice(saleOrder.getTotalPrice().subtract(saleOrder.getDiscountPrice())); + } + @Override @Transactional(rollbackFor = Exception.class) public void updateSaleOrderStatus(Long id, Integer status) { @@ -108,7 +130,7 @@ public class ErpSaleOrderServiceImpl implements ErpSaleOrderService { ErpSaleOrderDO saleOrder = validateSaleOrderExists(id); // 1.2 校验状态 if (saleOrder.getStatus().equals(status)) { - throw exception(approve ? STOCK_MOVE_APPROVE_FAIL : STOCK_MOVE_PROCESS_FAIL); + throw exception(approve ? SALE_ORDER_APPROVE_FAIL : SALE_ORDER_PROCESS_FAIL); } // TODO @芋艿:需要校验是不是有入库、有退货 @@ -116,7 +138,7 @@ public class ErpSaleOrderServiceImpl implements ErpSaleOrderService { int updateCount = saleOrderMapper.updateByIdAndStatus(id, saleOrder.getStatus(), new ErpSaleOrderDO().setStatus(status)); if (updateCount == 0) { - throw exception(approve ? STOCK_MOVE_APPROVE_FAIL : STOCK_MOVE_PROCESS_FAIL); + throw exception(approve ? SALE_ORDER_APPROVE_FAIL : SALE_ORDER_PROCESS_FAIL); } } @@ -126,9 +148,15 @@ public class ErpSaleOrderServiceImpl implements ErpSaleOrderService { convertSet(list, ErpSaleOrderSaveReqVO.Item::getProductId)); Map productMap = convertMap(productList, ErpProductDO::getId); // 2. 转化为 ErpSaleOrderItemDO 列表 - return convertList(list, o -> BeanUtils.toBean(o, ErpSaleOrderItemDO.class, item -> item - .setProductUnitId(productMap.get(item.getProductId()).getUnitId()) - .setTotalPrice(MoneyUtils.priceMultiply(item.getProductPrice(), item.getCount())))); + return convertList(list, o -> BeanUtils.toBean(o, ErpSaleOrderItemDO.class, item -> { + item.setProductUnitId(productMap.get(item.getProductId()).getUnitId()); + item.setTotalPrice(MoneyUtils.priceMultiply(item.getProductPrice(), item.getCount())); + if (item.getTotalPrice() == null) { + return; + } + item.setTaxPrice(MoneyUtils.priceMultiply(item.getTotalPrice(), item.getTaxPercent())); + item.setTotalPrice(item.getTotalPrice().add(item.getTaxPrice())); + })); } private void updateSaleOrderItemList(Long id, List newList) { @@ -160,7 +188,7 @@ public class ErpSaleOrderServiceImpl implements ErpSaleOrderService { } saleOrders.forEach(saleOrder -> { if (ErpAuditStatus.APPROVE.getStatus().equals(saleOrder.getStatus())) { - throw exception(STOCK_MOVE_DELETE_FAIL_APPROVE, saleOrder.getNo()); + throw exception(SALE_ORDER_DELETE_FAIL_APPROVE, saleOrder.getNo()); } }); @@ -176,7 +204,7 @@ public class ErpSaleOrderServiceImpl implements ErpSaleOrderService { private ErpSaleOrderDO validateSaleOrderExists(Long id) { ErpSaleOrderDO saleOrder = saleOrderMapper.selectById(id); if (saleOrder == null) { - throw exception(STOCK_MOVE_NOT_EXISTS); + throw exception(SALE_ORDER_NOT_EXISTS); } return saleOrder; } diff --git a/yudao-module-erp/yudao-module-erp-biz/src/main/resources/mapper/finance/ErpAccountMapper.xml b/yudao-module-erp/yudao-module-erp-biz/src/main/resources/mapper/finance/ErpAccountMapper.xml new file mode 100644 index 000000000..a3cf6877b --- /dev/null +++ b/yudao-module-erp/yudao-module-erp-biz/src/main/resources/mapper/finance/ErpAccountMapper.xml @@ -0,0 +1,12 @@ + + + + + + + \ No newline at end of file diff --git a/yudao-module-erp/yudao-module-erp-biz/src/test/java/cn/iocoder/yudao/module/erp/service/finance/ErpAccountServiceImplTest.java b/yudao-module-erp/yudao-module-erp-biz/src/test/java/cn/iocoder/yudao/module/erp/service/finance/ErpAccountServiceImplTest.java new file mode 100644 index 000000000..19fc9f313 --- /dev/null +++ b/yudao-module-erp/yudao-module-erp-biz/src/test/java/cn/iocoder/yudao/module/erp/service/finance/ErpAccountServiceImplTest.java @@ -0,0 +1,142 @@ +package cn.iocoder.yudao.module.erp.service.finance; + +import org.junit.jupiter.api.Disabled; +import org.junit.jupiter.api.Test; +import org.springframework.boot.test.mock.mockito.MockBean; + +import jakarta.annotation.Resource; + +import cn.iocoder.yudao.framework.test.core.ut.BaseDbUnitTest; + +import cn.iocoder.yudao.module.erp.controller.admin.finance.vo.*; +import cn.iocoder.yudao.module.erp.dal.dataobject.finance.ErpAccountDO; +import cn.iocoder.yudao.module.erp.dal.mysql.finance.ErpAccountMapper; +import cn.iocoder.yudao.framework.common.pojo.PageResult; + +import jakarta.annotation.Resource; +import org.springframework.context.annotation.Import; +import java.util.*; +import java.time.LocalDateTime; + +import static cn.hutool.core.util.RandomUtil.*; +import static cn.iocoder.yudao.module.erp.enums.ErrorCodeConstants.*; +import static cn.iocoder.yudao.framework.test.core.util.AssertUtils.*; +import static cn.iocoder.yudao.framework.test.core.util.RandomUtils.*; +import static cn.iocoder.yudao.framework.common.util.date.LocalDateTimeUtils.*; +import static cn.iocoder.yudao.framework.common.util.object.ObjectUtils.*; +import static cn.iocoder.yudao.framework.common.util.date.DateUtils.*; +import static org.junit.jupiter.api.Assertions.*; +import static org.mockito.Mockito.*; + +/** + * {@link ErpAccountServiceImpl} 的单元测试类 + * + * @author 芋道源码 + */ +@Import(ErpAccountServiceImpl.class) +public class ErpAccountServiceImplTest extends BaseDbUnitTest { + + @Resource + private ErpAccountServiceImpl accountService; + + @Resource + private ErpAccountMapper accountMapper; + + @Test + public void testCreateAccount_success() { + // 准备参数 + ErpAccountSaveReqVO createReqVO = randomPojo(ErpAccountSaveReqVO.class).setId(null); + + // 调用 + Long accountId = accountService.createAccount(createReqVO); + // 断言 + assertNotNull(accountId); + // 校验记录的属性是否正确 + ErpAccountDO account = accountMapper.selectById(accountId); + assertPojoEquals(createReqVO, account, "id"); + } + + @Test + public void testUpdateAccount_success() { + // mock 数据 + ErpAccountDO dbAccount = randomPojo(ErpAccountDO.class); + accountMapper.insert(dbAccount);// @Sql: 先插入出一条存在的数据 + // 准备参数 + ErpAccountSaveReqVO updateReqVO = randomPojo(ErpAccountSaveReqVO.class, o -> { + o.setId(dbAccount.getId()); // 设置更新的 ID + }); + + // 调用 + accountService.updateAccount(updateReqVO); + // 校验是否更新正确 + ErpAccountDO account = accountMapper.selectById(updateReqVO.getId()); // 获取最新的 + assertPojoEquals(updateReqVO, account); + } + + @Test + public void testUpdateAccount_notExists() { + // 准备参数 + ErpAccountSaveReqVO updateReqVO = randomPojo(ErpAccountSaveReqVO.class); + + // 调用, 并断言异常 + assertServiceException(() -> accountService.updateAccount(updateReqVO), ACCOUNT_NOT_EXISTS); + } + + @Test + public void testDeleteAccount_success() { + // mock 数据 + ErpAccountDO dbAccount = randomPojo(ErpAccountDO.class); + accountMapper.insert(dbAccount);// @Sql: 先插入出一条存在的数据 + // 准备参数 + Long id = dbAccount.getId(); + + // 调用 + accountService.deleteAccount(id); + // 校验数据不存在了 + assertNull(accountMapper.selectById(id)); + } + + @Test + public void testDeleteAccount_notExists() { + // 准备参数 + Long id = randomLongId(); + + // 调用, 并断言异常 + assertServiceException(() -> accountService.deleteAccount(id), ACCOUNT_NOT_EXISTS); + } + + @Test + @Disabled // TODO 请修改 null 为需要的值,然后删除 @Disabled 注解 + public void testGetAccountPage() { + // mock 数据 + ErpAccountDO dbAccount = randomPojo(ErpAccountDO.class, o -> { // 等会查询到 + o.setNo(null); + o.setRemark(null); + o.setStatus(null); + o.setName(null); + }); + accountMapper.insert(dbAccount); + // 测试 no 不匹配 + accountMapper.insert(cloneIgnoreId(dbAccount, o -> o.setNo(null))); + // 测试 remark 不匹配 + accountMapper.insert(cloneIgnoreId(dbAccount, o -> o.setRemark(null))); + // 测试 status 不匹配 + accountMapper.insert(cloneIgnoreId(dbAccount, o -> o.setStatus(null))); + // 测试 name 不匹配 + accountMapper.insert(cloneIgnoreId(dbAccount, o -> o.setName(null))); + // 准备参数 + ErpAccountPageReqVO reqVO = new ErpAccountPageReqVO(); + reqVO.setNo(null); + reqVO.setRemark(null); + reqVO.setStatus(null); + reqVO.setName(null); + + // 调用 + PageResult pageResult = accountService.getAccountPage(reqVO); + // 断言 + assertEquals(1, pageResult.getTotal()); + assertEquals(1, pageResult.getList().size()); + assertPojoEquals(dbAccount, pageResult.getList().get(0)); + } + +} \ No newline at end of file From 3c6ab397f9290372697b8cb40cc9fd19f1147d10 Mon Sep 17 00:00:00 2001 From: YunaiV Date: Sat, 10 Feb 2024 18:20:59 +0800 Subject: [PATCH 094/119] =?UTF-8?q?=E2=9C=A8=20ERP=EF=BC=9A=E5=88=9D?= =?UTF-8?q?=E5=A7=8B=E5=8C=96=E9=94=80=E5=94=AE=E5=87=BA=E5=BA=93=2030%?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../admin/finance/ErpAccountController.java | 10 + .../admin/sale/ErpSaleOrderController.http | 4 - .../admin/sale/ErpSaleOutController.java | 165 +++++++++++++ .../sale/vo/order/ErpSaleOrderRespVO.java | 1 - .../sale/vo/out/ErpSaleOutPageReqVO.java | 54 ++++ .../admin/sale/vo/out/ErpSaleOutRespVO.java | 152 ++++++++++++ .../sale/vo/out/ErpSaleOutSaveReqVO.java | 88 +++++++ .../admin/stock/ErpWarehouseController.java | 4 +- .../dal/dataobject/sale/ErpSaleOrderDO.java | 5 +- .../dataobject/sale/ErpSaleOrderItemDO.java | 3 +- .../erp/dal/dataobject/sale/ErpSaleOutDO.java | 135 ++++++++++ .../dal/dataobject/sale/ErpSaleOutItemDO.java | 96 ++++++++ .../mysql/sale/ErpSaleOrderItemMapper.java | 2 +- .../dal/mysql/sale/ErpSaleOutItemMapper.java | 30 +++ .../erp/dal/mysql/sale/ErpSaleOutMapper.java | 53 ++++ .../service/finance/ErpAccountService.java | 10 + .../finance/ErpAccountServiceImpl.java | 7 + .../service/sale/ErpSaleOrderServiceImpl.java | 10 +- .../erp/service/sale/ErpSaleOutService.java | 84 +++++++ .../service/sale/ErpSaleOutServiceImpl.java | 233 ++++++++++++++++++ 20 files changed, 1130 insertions(+), 16 deletions(-) delete mode 100644 yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/controller/admin/sale/ErpSaleOrderController.http create mode 100644 yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/controller/admin/sale/ErpSaleOutController.java create mode 100644 yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/controller/admin/sale/vo/out/ErpSaleOutPageReqVO.java create mode 100644 yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/controller/admin/sale/vo/out/ErpSaleOutRespVO.java create mode 100644 yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/controller/admin/sale/vo/out/ErpSaleOutSaveReqVO.java create mode 100644 yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/dal/dataobject/sale/ErpSaleOutDO.java create mode 100644 yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/dal/dataobject/sale/ErpSaleOutItemDO.java create mode 100644 yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/dal/mysql/sale/ErpSaleOutItemMapper.java create mode 100644 yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/dal/mysql/sale/ErpSaleOutMapper.java create mode 100644 yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/service/sale/ErpSaleOutService.java create mode 100644 yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/service/sale/ErpSaleOutServiceImpl.java diff --git a/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/controller/admin/finance/ErpAccountController.java b/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/controller/admin/finance/ErpAccountController.java index a66d28bdf..52d62ac4a 100644 --- a/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/controller/admin/finance/ErpAccountController.java +++ b/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/controller/admin/finance/ErpAccountController.java @@ -1,5 +1,6 @@ package cn.iocoder.yudao.module.erp.controller.admin.finance; +import cn.iocoder.yudao.framework.common.enums.CommonStatusEnum; import cn.iocoder.yudao.framework.common.pojo.CommonResult; import cn.iocoder.yudao.framework.common.pojo.PageParam; import cn.iocoder.yudao.framework.common.pojo.PageResult; @@ -26,6 +27,7 @@ import java.io.IOException; import java.util.List; 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.operatelog.core.enums.OperateTypeEnum.EXPORT; @Tag(name = "管理后台 - ERP 结算账户") @@ -82,6 +84,14 @@ public class ErpAccountController { return success(BeanUtils.toBean(account, ErpAccountRespVO.class)); } + @GetMapping("/simple-list") + @Operation(summary = "获得结算账户精简列表", description = "只包含被开启的结算账户,主要用于前端的下拉选项") + public CommonResult> getWarehouseSimpleList() { + List list = accountService.getAccountListByStatus(CommonStatusEnum.ENABLE.getStatus()); + return success(convertList(list, account -> new ErpAccountRespVO().setId(account.getId()) + .setName(account.getName()).setDefaultStatus(account.getDefaultStatus()))); + } + @GetMapping("/page") @Operation(summary = "获得结算账户分页") @PreAuthorize("@ss.hasPermission('erp:account:query')") diff --git a/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/controller/admin/sale/ErpSaleOrderController.http b/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/controller/admin/sale/ErpSaleOrderController.http deleted file mode 100644 index f8a5c970e..000000000 --- a/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/controller/admin/sale/ErpSaleOrderController.http +++ /dev/null @@ -1,4 +0,0 @@ -### 请求 /transfer -GET {{baseUrl}}/erp/sale-order/demo -Authorization: Bearer {{token}} -tenant-id: {{adminTenentId}} \ No newline at end of file diff --git a/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/controller/admin/sale/ErpSaleOutController.java b/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/controller/admin/sale/ErpSaleOutController.java new file mode 100644 index 000000000..b390038f2 --- /dev/null +++ b/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/controller/admin/sale/ErpSaleOutController.java @@ -0,0 +1,165 @@ +package cn.iocoder.yudao.module.erp.controller.admin.sale; + +import cn.hutool.core.collection.CollUtil; +import cn.iocoder.yudao.framework.common.pojo.CommonResult; +import cn.iocoder.yudao.framework.common.pojo.PageParam; +import cn.iocoder.yudao.framework.common.pojo.PageResult; +import cn.iocoder.yudao.framework.common.util.collection.MapUtils; +import cn.iocoder.yudao.framework.common.util.object.BeanUtils; +import cn.iocoder.yudao.framework.excel.core.util.ExcelUtils; +import cn.iocoder.yudao.framework.operatelog.core.annotations.OperateLog; +import cn.iocoder.yudao.module.erp.controller.admin.product.vo.product.ErpProductRespVO; +import cn.iocoder.yudao.module.erp.controller.admin.sale.vo.out.ErpSaleOutPageReqVO; +import cn.iocoder.yudao.module.erp.controller.admin.sale.vo.out.ErpSaleOutRespVO; +import cn.iocoder.yudao.module.erp.controller.admin.sale.vo.out.ErpSaleOutSaveReqVO; +import cn.iocoder.yudao.module.erp.dal.dataobject.sale.ErpCustomerDO; +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.dataobject.stock.ErpStockDO; +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.ErpSaleOutService; +import cn.iocoder.yudao.module.erp.service.stock.ErpStockService; +import cn.iocoder.yudao.module.system.api.user.AdminUserApi; +import cn.iocoder.yudao.module.system.api.user.dto.AdminUserRespDTO; +import io.swagger.v3.oas.annotations.Operation; +import io.swagger.v3.oas.annotations.Parameter; +import io.swagger.v3.oas.annotations.tags.Tag; +import jakarta.annotation.Resource; +import jakarta.servlet.http.HttpServletResponse; +import jakarta.validation.Valid; +import org.springframework.security.access.prepost.PreAuthorize; +import org.springframework.validation.annotation.Validated; +import org.springframework.web.bind.annotation.*; + +import java.io.IOException; +import java.math.BigDecimal; +import java.util.List; +import java.util.Map; + +import static cn.iocoder.yudao.framework.common.pojo.CommonResult.success; +import static cn.iocoder.yudao.framework.common.util.collection.CollectionUtils.convertMultiMap; +import static cn.iocoder.yudao.framework.common.util.collection.CollectionUtils.convertSet; +import static cn.iocoder.yudao.framework.operatelog.core.enums.OperateTypeEnum.EXPORT; + +@Tag(name = "管理后台 - ERP 销售出库") +@RestController +@RequestMapping("/erp/sale-out") +@Validated +public class ErpSaleOutController { + + @Resource + private ErpSaleOutService saleOutService; + @Resource + private ErpStockService stockService; + @Resource + private ErpProductService productService; + @Resource + private ErpCustomerService customerService; + + @Resource + private AdminUserApi adminUserApi; + + @PostMapping("/create") + @Operation(summary = "创建销售出库") + @PreAuthorize("@ss.hasPermission('erp:stock-out:create')") + public CommonResult createSaleOut(@Valid @RequestBody ErpSaleOutSaveReqVO createReqVO) { + return success(saleOutService.createSaleOut(createReqVO)); + } + + @PutMapping("/update") + @Operation(summary = "更新销售出库") + @PreAuthorize("@ss.hasPermission('erp:stock-out:update')") + public CommonResult updateSaleOut(@Valid @RequestBody ErpSaleOutSaveReqVO updateReqVO) { + saleOutService.updateSaleOut(updateReqVO); + return success(true); + } + + @PutMapping("/update-status") + @Operation(summary = "更新销售出库的状态") + @PreAuthorize("@ss.hasPermission('erp:stock-out:update-status')") + public CommonResult updateSaleOutStatus(@RequestParam("id") Long id, + @RequestParam("status") Integer status) { + saleOutService.updateSaleOutStatus(id, status); + return success(true); + } + + @DeleteMapping("/delete") + @Operation(summary = "删除销售出库") + @Parameter(name = "ids", description = "编号数组", required = true) + @PreAuthorize("@ss.hasPermission('erp:stock-out:delete')") + public CommonResult deleteSaleOut(@RequestParam("ids") List ids) { + saleOutService.deleteSaleOut(ids); + return success(true); + } + + @GetMapping("/get") + @Operation(summary = "获得销售出库") + @Parameter(name = "id", description = "编号", required = true, example = "1024") + @PreAuthorize("@ss.hasPermission('erp:stock-out:query')") + public CommonResult getSaleOut(@RequestParam("id") Long id) { + ErpSaleOutDO saleOut = saleOutService.getSaleOut(id); + if (saleOut == null) { + return success(null); + } + List saleOutItemList = saleOutService.getSaleOutItemListByOutId(id); + Map productMap = productService.getProductVOMap( + convertSet(saleOutItemList, ErpSaleOutItemDO::getProductId)); + return success(BeanUtils.toBean(saleOut, ErpSaleOutRespVO.class, saleOutVO -> + saleOutVO.setItems(BeanUtils.toBean(saleOutItemList, ErpSaleOutRespVO.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") + @Operation(summary = "获得销售出库分页") + @PreAuthorize("@ss.hasPermission('erp:stock-out:query')") + public CommonResult> getSaleOutPage(@Valid ErpSaleOutPageReqVO pageReqVO) { + PageResult pageResult = saleOutService.getSaleOutPage(pageReqVO); + return success(buildSaleOutVOPageResult(pageResult)); + } + + @GetMapping("/export-excel") + @Operation(summary = "导出销售出库 Excel") + @PreAuthorize("@ss.hasPermission('erp:stock-out:export')") + @OperateLog(type = EXPORT) + public void exportSaleOutExcel(@Valid ErpSaleOutPageReqVO pageReqVO, + HttpServletResponse response) throws IOException { + pageReqVO.setPageSize(PageParam.PAGE_SIZE_NONE); + List list = buildSaleOutVOPageResult(saleOutService.getSaleOutPage(pageReqVO)).getList(); + // 导出 Excel + ExcelUtils.write(response, "销售出库.xls", "数据", ErpSaleOutRespVO.class, list); + } + + private PageResult buildSaleOutVOPageResult(PageResult pageResult) { + if (CollUtil.isEmpty(pageResult.getList())) { + return PageResult.empty(pageResult.getTotal()); + } + // 1.1 出库项 + List saleOutItemList = saleOutService.getSaleOutItemListByOutIds( + convertSet(pageResult.getList(), ErpSaleOutDO::getId)); + Map> saleOutItemMap = convertMultiMap(saleOutItemList, ErpSaleOutItemDO::getOutId); + // 1.2 商品信息 + Map productMap = productService.getProductVOMap( + convertSet(saleOutItemList, ErpSaleOutItemDO::getProductId)); + // 1.3 客户信息 + Map customerMap = customerService.getCustomerMap( + convertSet(pageResult.getList(), ErpSaleOutDO::getCustomerId)); + // 1.4 管理员信息 + Map userMap = adminUserApi.getUserMap( + convertSet(pageResult.getList(), erpStockRecordDO -> Long.parseLong(erpStockRecordDO.getCreator()))); + // 2. 开始拼接 + return BeanUtils.toBean(pageResult, ErpSaleOutRespVO.class, saleOut -> { + saleOut.setItems(BeanUtils.toBean(saleOutItemMap.get(saleOut.getId()), ErpSaleOutRespVO.Item.class, + item -> MapUtils.findAndThen(productMap, item.getProductId(), product -> item.setProductName(product.getName()) + .setProductBarCode(product.getBarCode()).setProductUnitName(product.getUnitName())))); + saleOut.setProductNames(CollUtil.join(saleOut.getItems(), ",", ErpSaleOutRespVO.Item::getProductName)); + MapUtils.findAndThen(customerMap, saleOut.getCustomerId(), supplier -> saleOut.setCustomerName(supplier.getName())); + MapUtils.findAndThen(userMap, Long.parseLong(saleOut.getCreator()), user -> saleOut.setCreatorName(user.getNickname())); + }); + } + +} \ No newline at end of file diff --git a/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/controller/admin/sale/vo/order/ErpSaleOrderRespVO.java b/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/controller/admin/sale/vo/order/ErpSaleOrderRespVO.java index c90d4b63b..0beb312ee 100644 --- a/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/controller/admin/sale/vo/order/ErpSaleOrderRespVO.java +++ b/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/controller/admin/sale/vo/order/ErpSaleOrderRespVO.java @@ -64,7 +64,6 @@ public class ErpSaleOrderRespVO { private BigDecimal discountPrice; @Schema(description = "定金金额,单位:元", requiredMode = Schema.RequiredMode.REQUIRED, example = "7127") - @NotNull(message = "定金金额,单位:元不能为空") private BigDecimal depositPrice; @Schema(description = "附件地址", example = "https://www.iocoder.cn") diff --git a/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/controller/admin/sale/vo/out/ErpSaleOutPageReqVO.java b/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/controller/admin/sale/vo/out/ErpSaleOutPageReqVO.java new file mode 100644 index 000000000..708b9cf1f --- /dev/null +++ b/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/controller/admin/sale/vo/out/ErpSaleOutPageReqVO.java @@ -0,0 +1,54 @@ +package cn.iocoder.yudao.module.erp.controller.admin.sale.vo.out; + +import cn.iocoder.yudao.framework.common.pojo.PageParam; +import io.swagger.v3.oas.annotations.media.Schema; +import lombok.Data; +import lombok.EqualsAndHashCode; +import lombok.ToString; +import org.springframework.format.annotation.DateTimeFormat; + +import java.time.LocalDateTime; + +import static cn.iocoder.yudao.framework.common.util.date.DateUtils.FORMAT_YEAR_MONTH_DAY_HOUR_MINUTE_SECOND; + +@Schema(description = "管理后台 - ERP 销售出库分页 Request VO") +@Data +@EqualsAndHashCode(callSuper = true) +@ToString(callSuper = true) +public class ErpSaleOutPageReqVO extends PageParam { + + @Schema(description = "销售单编号", example = "XS001") + private String no; + + @Schema(description = "客户编号", example = "1724") + private Long customerId; + + @Schema(description = "出库时间") + @DateTimeFormat(pattern = FORMAT_YEAR_MONTH_DAY_HOUR_MINUTE_SECOND) + private LocalDateTime[] outTime; + + @Schema(description = "备注", example = "你猜") + private String remark; + + @Schema(description = "销售状态", example = "2") + private Integer status; + + @Schema(description = "创建者") + private String creator; + + @Schema(description = "产品编号", example = "1") + private Long productId; + + @Schema(description = "仓库编号", example = "1") + private Long warehouseId; + + @Schema(description = "结算账号编号", example = "1") + private Long accountId; + + @Schema(description = "是否欠款", example = "true") + private Boolean debtStatus; + + @Schema(description = "销售单号", example = "1") + private String orderNo; + +} \ No newline at end of file diff --git a/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/controller/admin/sale/vo/out/ErpSaleOutRespVO.java b/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/controller/admin/sale/vo/out/ErpSaleOutRespVO.java new file mode 100644 index 000000000..3901d9e05 --- /dev/null +++ b/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/controller/admin/sale/vo/out/ErpSaleOutRespVO.java @@ -0,0 +1,152 @@ +package cn.iocoder.yudao.module.erp.controller.admin.sale.vo.out; + +import com.alibaba.excel.annotation.ExcelIgnoreUnannotated; +import com.alibaba.excel.annotation.ExcelProperty; +import io.swagger.v3.oas.annotations.media.Schema; +import jakarta.validation.constraints.NotNull; +import lombok.Data; + +import java.math.BigDecimal; +import java.time.LocalDateTime; +import java.util.List; + +@Schema(description = "管理后台 - ERP 出库出库 Response VO") +@Data +@ExcelIgnoreUnannotated +public class ErpSaleOutRespVO { + + @Schema(description = "编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "17386") + @ExcelProperty("编号") + private Long id; + + @Schema(description = "出库单编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "XS001") + @ExcelProperty("出库单编号") + private String no; + + @Schema(description = "出库状态", requiredMode = Schema.RequiredMode.REQUIRED, example = "2") + @ExcelProperty("出库状态") + private Integer status; + + @Schema(description = "客户编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "1724") + private Long customerId; + @Schema(description = "客户名称", example = "芋道") + @ExcelProperty("客户名称") + private String customerName; + + @Schema(description = "结算账户编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "311.89") + @ExcelProperty("结算账户编号") + private Long accountId; + + @Schema(description = "出库员编号", example = "1888") + private Long saleUserId; + + @Schema(description = "出库时间", requiredMode = Schema.RequiredMode.REQUIRED) + @ExcelProperty("出库时间") + private LocalDateTime outTime; + + @Schema(description = "销售订单编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "17386") + private Long orderId; + @Schema(description = "销售订单号", requiredMode = Schema.RequiredMode.REQUIRED, example = "XS001") + private Long orderNo; + + @Schema(description = "合计数量", requiredMode = Schema.RequiredMode.REQUIRED, example = "15663") + @ExcelProperty("合计数量") + private BigDecimal totalCount; + @Schema(description = "最终合计价格", requiredMode = Schema.RequiredMode.REQUIRED, example = "24906") + @ExcelProperty("最终合计价格") + private BigDecimal totalPrice; + + @Schema(description = "合计产品价格,单位:元", requiredMode = Schema.RequiredMode.REQUIRED, example = "7127") + private BigDecimal totalProductPrice; + + @Schema(description = "合计税额,单位:元", requiredMode = Schema.RequiredMode.REQUIRED, example = "7127") + private BigDecimal totalTaxPrice; + + @Schema(description = "优惠率,百分比", requiredMode = Schema.RequiredMode.REQUIRED, example = "99.88") + private BigDecimal discountPercent; + + @Schema(description = "优惠金额,单位:元", requiredMode = Schema.RequiredMode.REQUIRED, example = "7127") + private BigDecimal discountPrice; + + @Schema(description = "定金金额,单位:元", requiredMode = Schema.RequiredMode.REQUIRED, example = "7127") + private BigDecimal otherPrice; + + @Schema(description = "本次收款,单位:元", requiredMode = Schema.RequiredMode.REQUIRED, example = "7127") + private BigDecimal payPrice; + @Schema(description = "本次欠款,单位:元", requiredMode = Schema.RequiredMode.REQUIRED, example = "666") + private BigDecimal debtPrice; + + + @Schema(description = "附件地址", example = "https://www.iocoder.cn") + @ExcelProperty("附件地址") + private String fileUrl; + + @Schema(description = "备注", example = "你猜") + @ExcelProperty("备注") + private String remark; + + @Schema(description = "审核人", example = "芋道") + private String creator; + @Schema(description = "审核人名称", example = "芋道") + private String creatorName; + + @Schema(description = "创建时间", requiredMode = Schema.RequiredMode.REQUIRED) + @ExcelProperty("创建时间") + private LocalDateTime createTime; + + @Schema(description = "出库项列表", requiredMode = Schema.RequiredMode.REQUIRED) + private List items; + + @Schema(description = "产品信息", requiredMode = Schema.RequiredMode.REQUIRED) + @ExcelProperty("产品信息") + private String productNames; + + @Data + public static class Item { + + @Schema(description = "出库项编号", example = "11756") + private Long id; + + @Schema(description = "销售订单项编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "11756") + private Long orderItemId; + + @Schema(description = "仓库编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "3113") + private Long warehouseId; + + @Schema(description = "产品编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "3113") + private Long productId; + + @Schema(description = "产品单位单位", requiredMode = Schema.RequiredMode.REQUIRED, example = "3113") + private Long productUnitId; + + @Schema(description = "产品单价", example = "100.00") + private BigDecimal productPrice; + + @Schema(description = "产品数量", requiredMode = Schema.RequiredMode.REQUIRED, example = "100.00") + @NotNull(message = "产品数量不能为空") + private BigDecimal count; + + @Schema(description = "税率,百分比", example = "99.88") + private BigDecimal taxPercent; + + @Schema(description = "税额,单位:元", example = "100.00") + private BigDecimal taxPrice; + + @Schema(description = "备注", example = "随便") + private String remark; + + // ========== 关联字段 ========== + + @Schema(description = "产品名称", requiredMode = Schema.RequiredMode.REQUIRED, example = "巧克力") + private String productName; + @Schema(description = "产品条码", requiredMode = Schema.RequiredMode.REQUIRED, example = "A9985") + private String productBarCode; + @Schema(description = "产品单位名称", requiredMode = Schema.RequiredMode.REQUIRED, example = "盒") + private String productUnitName; + + @Schema(description = "库存数量", requiredMode = Schema.RequiredMode.REQUIRED, example = "100.00") + private BigDecimal stockCount; // 该字段仅仅在“详情”和“编辑”时使用 + + } + +} \ No newline at end of file diff --git a/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/controller/admin/sale/vo/out/ErpSaleOutSaveReqVO.java b/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/controller/admin/sale/vo/out/ErpSaleOutSaveReqVO.java new file mode 100644 index 000000000..ac09f6bf1 --- /dev/null +++ b/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/controller/admin/sale/vo/out/ErpSaleOutSaveReqVO.java @@ -0,0 +1,88 @@ +package cn.iocoder.yudao.module.erp.controller.admin.sale.vo.out; + +import io.swagger.v3.oas.annotations.media.Schema; +import jakarta.validation.constraints.NotNull; +import lombok.Data; + +import java.math.BigDecimal; +import java.time.LocalDateTime; +import java.util.List; + +@Schema(description = "管理后台 - ERP 销售出库新增/修改 Request VO") +@Data +public class ErpSaleOutSaveReqVO { + + @Schema(description = "编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "17386") + private Long id; + + @Schema(description = "结算账户编号", example = "31189") + private Long accountId; + + @Schema(description = "销售员编号", example = "1888") + private Long saleUserId; + + @Schema(description = "出库时间", requiredMode = Schema.RequiredMode.REQUIRED) + @NotNull(message = "出库时间不能为空") + private LocalDateTime outTime; + + @Schema(description = "销售订单编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "17386") + @NotNull(message = "销售订单编号不能为空") + private Long orderId; + + @Schema(description = "优惠率,百分比", requiredMode = Schema.RequiredMode.REQUIRED, example = "99.88") + private BigDecimal discountPercent; + + @Schema(description = "其它金额,单位:元", example = "7127") + private BigDecimal otherPrice; + + @Schema(description = "本次收款,单位:元", requiredMode = Schema.RequiredMode.REQUIRED, example = "7127") + @NotNull(message = "本次收款不能为空") + private BigDecimal payPrice; + + @Schema(description = "附件地址", example = "https://www.iocoder.cn") + private String fileUrl; + + @Schema(description = "备注", example = "你猜") + private String remark; + + @Schema(description = "出库清单列表") + private List items; + + @Data + public static class Item { + + @Schema(description = "出库项编号", example = "11756") + private Long id; + + @Schema(description = "销售订单项编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "11756") + @NotNull(message = "销售订单项编号不能为空") + private Long orderItemId; + + @Schema(description = "仓库编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "3113") + @NotNull(message = "仓库编号不能为空") + private Long warehouseId; + + @Schema(description = "产品编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "3113") + @NotNull(message = "产品编号不能为空") + private Long productId; + + @Schema(description = "产品单位单位", requiredMode = Schema.RequiredMode.REQUIRED, example = "3113") + @NotNull(message = "产品单位单位不能为空") + private Long productUnitId; + + @Schema(description = "产品单价", example = "100.00") + private BigDecimal productPrice; + + @Schema(description = "产品数量", requiredMode = Schema.RequiredMode.REQUIRED, example = "100.00") + @NotNull(message = "产品数量不能为空") + private BigDecimal count; + + @Schema(description = "税率,百分比", example = "99.88") + private BigDecimal taxPercent; + + @Schema(description = "备注", example = "随便") + private String remark; + + } + +} \ No newline at end of file diff --git a/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/controller/admin/stock/ErpWarehouseController.java b/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/controller/admin/stock/ErpWarehouseController.java index 32c33075d..744f439f5 100644 --- a/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/controller/admin/stock/ErpWarehouseController.java +++ b/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/controller/admin/stock/ErpWarehouseController.java @@ -27,6 +27,7 @@ import java.io.IOException; import java.util.List; 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.operatelog.core.enums.OperateTypeEnum.EXPORT; @Tag(name = "管理后台 - ERP 仓库") @@ -95,7 +96,8 @@ public class ErpWarehouseController { @Operation(summary = "获得仓库精简列表", description = "只包含被开启的仓库,主要用于前端的下拉选项") public CommonResult> getWarehouseSimpleList() { List list = warehouseService.getWarehouseListByStatus(CommonStatusEnum.ENABLE.getStatus()); - return success(BeanUtils.toBean(list, ErpWarehouseRespVO.class)); + return success(convertList(list, warehouse -> new ErpWarehouseRespVO().setId(warehouse.getId()) + .setName(warehouse.getName()).setDefaultStatus(warehouse.getDefaultStatus()))); } @GetMapping("/export-excel") diff --git a/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/dal/dataobject/sale/ErpSaleOrderDO.java b/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/dal/dataobject/sale/ErpSaleOrderDO.java index 8bbbcdefb..5f34e2aa4 100644 --- a/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/dal/dataobject/sale/ErpSaleOrderDO.java +++ b/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/dal/dataobject/sale/ErpSaleOrderDO.java @@ -1,6 +1,7 @@ package cn.iocoder.yudao.module.erp.dal.dataobject.sale; import cn.iocoder.yudao.framework.mybatis.core.dataobject.BaseDO; +import cn.iocoder.yudao.module.erp.dal.dataobject.finance.ErpAccountDO; import com.baomidou.mybatisplus.annotation.KeySequence; import com.baomidou.mybatisplus.annotation.TableId; import com.baomidou.mybatisplus.annotation.TableName; @@ -30,7 +31,7 @@ public class ErpSaleOrderDO extends BaseDO { @TableId private Long id; /** - * 销售单编号 + * 销售订单号 */ private String no; /** @@ -48,7 +49,7 @@ public class ErpSaleOrderDO extends BaseDO { /** * 结算账户编号 * - * TODO 芋艿:关联 + * 关联 {@link ErpAccountDO#getId()} */ private Long accountId; /** diff --git a/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/dal/dataobject/sale/ErpSaleOrderItemDO.java b/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/dal/dataobject/sale/ErpSaleOrderItemDO.java index d25a5471c..5cdf3a14c 100644 --- a/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/dal/dataobject/sale/ErpSaleOrderItemDO.java +++ b/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/dal/dataobject/sale/ErpSaleOrderItemDO.java @@ -10,7 +10,7 @@ import lombok.*; import java.math.BigDecimal; /** - * ERP 销售订单明细 DO + * ERP 销售订单项 DO * * @author 芋道源码 */ @@ -35,7 +35,6 @@ public class ErpSaleOrderItemDO extends BaseDO { * 关联 {@link ErpSaleOrderDO#getId()} */ private Long orderId; - /** * 产品编号 * diff --git a/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/dal/dataobject/sale/ErpSaleOutDO.java b/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/dal/dataobject/sale/ErpSaleOutDO.java new file mode 100644 index 000000000..1a0e6f1d3 --- /dev/null +++ b/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/dal/dataobject/sale/ErpSaleOutDO.java @@ -0,0 +1,135 @@ +package cn.iocoder.yudao.module.erp.dal.dataobject.sale; + +import cn.iocoder.yudao.framework.mybatis.core.dataobject.BaseDO; +import cn.iocoder.yudao.module.erp.dal.dataobject.finance.ErpAccountDO; +import com.baomidou.mybatisplus.annotation.KeySequence; +import com.baomidou.mybatisplus.annotation.TableId; +import com.baomidou.mybatisplus.annotation.TableName; +import lombok.*; + +import java.math.BigDecimal; +import java.time.LocalDateTime; + +/** + * ERP 销售出库 DO + * + * @author 芋道源码 + */ +@TableName(value = "erp_sale_out") +@KeySequence("erp_sale_out_seq") // 用于 Oracle、PostgreSQL、Kingbase、DB2、H2 数据库的主键自增。如果是 MySQL 等数据库,可不写。 +@Data +@EqualsAndHashCode(callSuper = true) +@ToString(callSuper = true) +@Builder +@NoArgsConstructor +@AllArgsConstructor +public class ErpSaleOutDO extends BaseDO { + + /** + * 编号 + */ + @TableId + private Long id; + /** + * 销售出库单号 + */ + private String no; + /** + * 出库状态 + * + * 枚举 {@link cn.iocoder.yudao.module.erp.enums.ErpAuditStatus} + */ + private Integer status; + /** + * 客户编号 + * + * 关联 {@link ErpCustomerDO#getId()} + */ + private Long customerId; + /** + * 结算账户编号 + * + * 关联 {@link ErpAccountDO#getId()} + */ + private Long accountId; + /** + * 销售员编号 + * + * 关联 AdminUserDO 的 id 字段 + */ + private Long saleUserId; + /** + * 出库时间 + */ + private LocalDateTime outTime; + + /** + * 销售订单编号 + * + * 关联 {@link ErpSaleOrderDO#getId()} + */ + private Long orderId; + /** + * 销售订单号 + * + * 冗余 {@link ErpSaleOrderDO#getNo()} + */ + private Long orderNo; + + /** + * 合计数量 + */ + private BigDecimal totalCount; + /** + * 最终合计价格,单位:元 + * + * totalPrice = totalProductPrice + totalTaxPrice - discountPrice + */ + private BigDecimal totalPrice; + + /** + * 合计产品价格,单位:元 + */ + private BigDecimal totalProductPrice; + /** + * 合计税额,单位:元 + */ + private BigDecimal totalTaxPrice; + /** + * 优惠率,百分比 + */ + private BigDecimal discountPercent; + /** + * 优惠金额,单位:元 + * + * discountPrice = (totalProductPrice + totalTaxPrice) * discountPercent + */ + private BigDecimal discountPrice; + /** + * 其它金额,单位:元 + * + * 注意:它不算在 {@link #totalPrice} 中 + */ + private BigDecimal otherPrice; + + /** + * 本次收款,单位:元 + * + * payPrice = totalPrice + otherPrice - debtPrice + */ + private BigDecimal payPrice; + /** + * 本次欠款,单位:元 + */ + private BigDecimal debtPrice; + + /** + * 附件地址 + */ + private String fileUrl; + /** + * 备注 + */ + private String remark; + +} \ No newline at end of file diff --git a/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/dal/dataobject/sale/ErpSaleOutItemDO.java b/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/dal/dataobject/sale/ErpSaleOutItemDO.java new file mode 100644 index 000000000..d13915dae --- /dev/null +++ b/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/dal/dataobject/sale/ErpSaleOutItemDO.java @@ -0,0 +1,96 @@ +package cn.iocoder.yudao.module.erp.dal.dataobject.sale; + +import cn.iocoder.yudao.framework.mybatis.core.dataobject.BaseDO; +import cn.iocoder.yudao.module.erp.dal.dataobject.product.ErpProductDO; +import cn.iocoder.yudao.module.erp.dal.dataobject.stock.ErpStockOutDO; +import cn.iocoder.yudao.module.erp.dal.dataobject.stock.ErpWarehouseDO; +import com.baomidou.mybatisplus.annotation.KeySequence; +import com.baomidou.mybatisplus.annotation.TableId; +import com.baomidou.mybatisplus.annotation.TableName; +import lombok.*; + +import java.math.BigDecimal; + +/** + * ERP 销售出库项 DO + * + * @author 芋道源码 + */ +@TableName("erp_sale_order_items") +@KeySequence("erp_sale_order_items_seq") // 用于 Oracle、PostgreSQL、Kingbase、DB2、H2 数据库的主键自增。如果是 MySQL 等数据库,可不写。 +@Data +@EqualsAndHashCode(callSuper = true) +@ToString(callSuper = true) +@Builder +@NoArgsConstructor +@AllArgsConstructor +public class ErpSaleOutItemDO extends BaseDO { + + /** + * 编号 + */ + @TableId + private Long id; + /** + * 销售出库编号 + * + * 关联 {@link ErpStockOutDO##getId()} + */ + private Long outId; + /** + * 销售订单项编号 + * + * 关联 {@link ErpSaleOrderItemDO#getId()} + * 目的:方便更新关联的销售订单项的出库数量 + */ + private Long orderItemId; + /** + * 仓库编号 + * + * 关联 {@link ErpWarehouseDO#getId()} + */ + private Long warehouseId; + /** + * 产品编号 + * + * 关联 {@link ErpProductDO#getId()} + */ + private Long productId; + /** + * 产品单位单位 + * + * 冗余 {@link ErpProductDO#getUnitId()} + */ + private Long productUnitId; + + /** + * 产品单位单价,单位:元 + */ + private BigDecimal productPrice; + /** + * 数量 + */ + private BigDecimal count; + /** + * 总价,单位:元 + * + * totalPrice = productPrice * count + */ + private BigDecimal totalPrice; + /** + * 税率,百分比 + */ + private BigDecimal taxPercent; + /** + * 税额,单位:元 + * + * taxPrice = totalPrice * taxPercent + */ + private BigDecimal taxPrice; + + /** + * 备注 + */ + private String remark; + +} \ No newline at end of file diff --git a/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/dal/mysql/sale/ErpSaleOrderItemMapper.java b/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/dal/mysql/sale/ErpSaleOrderItemMapper.java index fd3f82f0b..d2825e563 100644 --- a/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/dal/mysql/sale/ErpSaleOrderItemMapper.java +++ b/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/dal/mysql/sale/ErpSaleOrderItemMapper.java @@ -8,7 +8,7 @@ import java.util.Collection; import java.util.List; /** - * ERP 销售订单明细 Mapper + * ERP 销售订单明项目 Mapper * * @author 芋道源码 */ diff --git a/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/dal/mysql/sale/ErpSaleOutItemMapper.java b/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/dal/mysql/sale/ErpSaleOutItemMapper.java new file mode 100644 index 000000000..957667c73 --- /dev/null +++ b/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/dal/mysql/sale/ErpSaleOutItemMapper.java @@ -0,0 +1,30 @@ +package cn.iocoder.yudao.module.erp.dal.mysql.sale; + +import cn.iocoder.yudao.framework.mybatis.core.mapper.BaseMapperX; +import cn.iocoder.yudao.module.erp.dal.dataobject.sale.ErpSaleOutItemDO; +import org.apache.ibatis.annotations.Mapper; + +import java.util.Collection; +import java.util.List; + +/** + * ERP 销售出库项 Mapper + * + * @author 芋道源码 + */ +@Mapper +public interface ErpSaleOutItemMapper extends BaseMapperX { + + default List selectListByOutId(Long orderId) { + return selectList(ErpSaleOutItemDO::getOutId, orderId); + } + + default List selectListByOutIds(Collection orderIds) { + return selectList(ErpSaleOutItemDO::getOutId, orderIds); + } + + default int deleteByOutId(Long orderId) { + return delete(ErpSaleOutItemDO::getOutId, orderId); + } + +} \ No newline at end of file diff --git a/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/dal/mysql/sale/ErpSaleOutMapper.java b/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/dal/mysql/sale/ErpSaleOutMapper.java new file mode 100644 index 000000000..809954df9 --- /dev/null +++ b/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/dal/mysql/sale/ErpSaleOutMapper.java @@ -0,0 +1,53 @@ +package cn.iocoder.yudao.module.erp.dal.mysql.sale; + + +import cn.iocoder.yudao.framework.common.pojo.PageResult; +import cn.iocoder.yudao.framework.mybatis.core.mapper.BaseMapperX; +import cn.iocoder.yudao.framework.mybatis.core.query.MPJLambdaWrapperX; +import cn.iocoder.yudao.module.erp.controller.admin.sale.vo.out.ErpSaleOutPageReqVO; +import cn.iocoder.yudao.module.erp.dal.dataobject.sale.ErpSaleOutDO; +import cn.iocoder.yudao.module.erp.dal.dataobject.sale.ErpSaleOutItemDO; +import com.baomidou.mybatisplus.core.conditions.update.LambdaUpdateWrapper; +import org.apache.ibatis.annotations.Mapper; + +import java.math.BigDecimal; + +/** + * ERP 销售出库 Mapper + * + * @author 芋道源码 + */ +@Mapper +public interface ErpSaleOutMapper extends BaseMapperX { + + default PageResult selectPage(ErpSaleOutPageReqVO reqVO) { + MPJLambdaWrapperX query = new MPJLambdaWrapperX() + .eqIfPresent(ErpSaleOutDO::getNo, reqVO.getNo()) + .eqIfPresent(ErpSaleOutDO::getCustomerId, reqVO.getCustomerId()) + .betweenIfPresent(ErpSaleOutDO::getOutTime, reqVO.getOutTime()) + .eqIfPresent(ErpSaleOutDO::getStatus, reqVO.getStatus()) + .likeIfPresent(ErpSaleOutDO::getRemark, reqVO.getRemark()) + .eqIfPresent(ErpSaleOutDO::getCreator, reqVO.getCreator()) + .eqIfPresent(ErpSaleOutDO::getAccountId, reqVO.getAccountId()) + .likeIfPresent(ErpSaleOutDO::getOrderNo, reqVO.getOrderNo()) + .orderByDesc(ErpSaleOutDO::getId); + query.gt(Boolean.TRUE.equals(reqVO.getDebtStatus()), ErpSaleOutDO::getDebtPrice, BigDecimal.ZERO); + if (reqVO.getWarehouseId() != null && reqVO.getProductId() != null) { + query.leftJoin(ErpSaleOutItemDO.class, ErpSaleOutItemDO::getOutId, ErpSaleOutDO::getId) + .eq(reqVO.getWarehouseId() != null, ErpSaleOutItemDO::getWarehouseId, reqVO.getWarehouseId()) + .eq(reqVO.getProductId() != null, ErpSaleOutItemDO::getProductId, reqVO.getProductId()) + .groupBy(ErpSaleOutDO::getId); // 避免 1 对多查询,产生相同的 1 + } + return selectJoinPage(reqVO, ErpSaleOutDO.class, query); + } + + default int updateByIdAndStatus(Long id, Integer status, ErpSaleOutDO updateObj) { + return update(updateObj, new LambdaUpdateWrapper() + .eq(ErpSaleOutDO::getId, id).eq(ErpSaleOutDO::getStatus, status)); + } + + default ErpSaleOutDO selectByNo(String no) { + return selectOne(ErpSaleOutDO::getNo, no); + } + +} \ No newline at end of file diff --git a/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/service/finance/ErpAccountService.java b/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/service/finance/ErpAccountService.java index 8e23f0dca..e1d321ec0 100644 --- a/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/service/finance/ErpAccountService.java +++ b/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/service/finance/ErpAccountService.java @@ -6,6 +6,8 @@ import cn.iocoder.yudao.module.erp.controller.admin.finance.vo.ErpAccountSaveReq import cn.iocoder.yudao.module.erp.dal.dataobject.finance.ErpAccountDO; import jakarta.validation.Valid; +import java.util.List; + /** * ERP 结算账户 Service 接口 * @@ -59,6 +61,14 @@ public interface ErpAccountService { */ ErpAccountDO validateAccount(Long id); + /** + * 获得指定状态的结算账户列表 + * + * @param status 状态 + * @return 结算账户 + */ + List getAccountListByStatus(Integer status); + /** * 获得结算账户分页 * diff --git a/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/service/finance/ErpAccountServiceImpl.java b/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/service/finance/ErpAccountServiceImpl.java index 2ff33de1a..375a4ca48 100644 --- a/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/service/finance/ErpAccountServiceImpl.java +++ b/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/service/finance/ErpAccountServiceImpl.java @@ -11,6 +11,8 @@ import jakarta.annotation.Resource; import org.springframework.stereotype.Service; import org.springframework.validation.annotation.Validated; +import java.util.List; + import static cn.iocoder.yudao.framework.common.exception.util.ServiceExceptionUtil.exception; import static cn.iocoder.yudao.module.erp.enums.ErrorCodeConstants.*; @@ -91,6 +93,11 @@ public class ErpAccountServiceImpl implements ErpAccountService { return account; } + @Override + public List getAccountListByStatus(Integer status) { + return accountMapper.selectListByStatus(status); + } + @Override public PageResult getAccountPage(ErpAccountPageReqVO pageReqVO) { return accountMapper.selectPage(pageReqVO); diff --git a/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/service/sale/ErpSaleOrderServiceImpl.java b/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/service/sale/ErpSaleOrderServiceImpl.java index 662eb1189..fae8fe114 100644 --- a/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/service/sale/ErpSaleOrderServiceImpl.java +++ b/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/service/sale/ErpSaleOrderServiceImpl.java @@ -222,16 +222,16 @@ public class ErpSaleOrderServiceImpl implements ErpSaleOrderService { // ==================== 订单项 ==================== @Override - public List getSaleOrderItemListByOrderId(Long moveId) { - return saleOrderItemMapper.selectListByOrderId(moveId); + public List getSaleOrderItemListByOrderId(Long orderId) { + return saleOrderItemMapper.selectListByOrderId(orderId); } @Override - public List getSaleOrderItemListByOrderIds(Collection moveIds) { - if (CollUtil.isEmpty(moveIds)) { + public List getSaleOrderItemListByOrderIds(Collection orderIds) { + if (CollUtil.isEmpty(orderIds)) { return Collections.emptyList(); } - return saleOrderItemMapper.selectListByOrderIds(moveIds); + return saleOrderItemMapper.selectListByOrderIds(orderIds); } } \ No newline at end of file diff --git a/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/service/sale/ErpSaleOutService.java b/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/service/sale/ErpSaleOutService.java new file mode 100644 index 000000000..60ea7912f --- /dev/null +++ b/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/service/sale/ErpSaleOutService.java @@ -0,0 +1,84 @@ +package cn.iocoder.yudao.module.erp.service.sale; + +import cn.iocoder.yudao.framework.common.pojo.PageResult; +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.sale.ErpSaleOutDO; +import cn.iocoder.yudao.module.erp.dal.dataobject.sale.ErpSaleOutItemDO; +import jakarta.validation.Valid; + +import java.util.Collection; +import java.util.List; + +/** + * ERP 销售出库 Service 接口 + * + * @author 芋道源码 + */ +public interface ErpSaleOutService { + + /** + * 创建销售出库 + * + * @param createReqVO 创建信息 + * @return 编号 + */ + Long createSaleOut(@Valid ErpSaleOutSaveReqVO createReqVO); + + /** + * 更新销售出库 + * + * @param updateReqVO 更新信息 + */ + void updateSaleOut(@Valid ErpSaleOutSaveReqVO updateReqVO); + + /** + * 更新销售出库的状态 + * + * @param id 编号 + * @param status 状态 + */ + void updateSaleOutStatus(Long id, Integer status); + + /** + * 删除销售出库 + * + * @param ids 编号数组 + */ + void deleteSaleOut(List ids); + + /** + * 获得销售出库 + * + * @param id 编号 + * @return 销售出库 + */ + ErpSaleOutDO getSaleOut(Long id); + + /** + * 获得销售出库分页 + * + * @param pageReqVO 分页查询 + * @return 销售出库分页 + */ + PageResult getSaleOutPage(ErpSaleOutPageReqVO pageReqVO); + + // ==================== 销售出库项 ==================== + + /** + * 获得销售出库项列表 + * + * @param outId 销售出库编号 + * @return 销售出库项列表 + */ + List getSaleOutItemListByOutId(Long outId); + + /** + * 获得销售出库项 List + * + * @param outIds 销售出库编号数组 + * @return 销售出库项 List + */ + List getSaleOutItemListByOutIds(Collection outIds); + +} \ No newline at end of file diff --git a/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/service/sale/ErpSaleOutServiceImpl.java b/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/service/sale/ErpSaleOutServiceImpl.java new file mode 100644 index 000000000..aae5a60de --- /dev/null +++ b/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/service/sale/ErpSaleOutServiceImpl.java @@ -0,0 +1,233 @@ +package cn.iocoder.yudao.module.erp.service.sale; + +import cn.hutool.core.collection.CollUtil; +import cn.iocoder.yudao.framework.common.pojo.PageResult; +import cn.iocoder.yudao.framework.common.util.number.MoneyUtils; +import cn.iocoder.yudao.framework.common.util.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.ErpSaleOutDO; +import cn.iocoder.yudao.module.erp.dal.dataobject.sale.ErpSaleOutItemDO; +import cn.iocoder.yudao.module.erp.dal.mysql.sale.ErpSaleOutItemMapper; +import cn.iocoder.yudao.module.erp.dal.mysql.sale.ErpSaleOutMapper; +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 jakarta.annotation.Resource; +import org.springframework.stereotype.Service; +import org.springframework.transaction.annotation.Transactional; +import org.springframework.validation.annotation.Validated; + +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.exception.util.ServiceExceptionUtil.exception; +import static cn.iocoder.yudao.framework.common.util.collection.CollectionUtils.*; +import static cn.iocoder.yudao.module.erp.enums.ErrorCodeConstants.*; + +// TODO 芋艿:记录操作日志 + +/** + * ERP 销售订单 Service 实现类 + * + * @author 芋道源码 + */ +@Service +@Validated +public class ErpSaleOutServiceImpl implements ErpSaleOutService { + + @Resource + private ErpSaleOutMapper saleOutMapper; + @Resource + private ErpSaleOutItemMapper saleOutItemMapper; + + @Resource + private ErpNoRedisDAO noRedisDAO; + + @Resource + private ErpProductService productService; + @Resource + private ErpCustomerService customerService; + @Resource + private ErpAccountService accountService; + + @Override + @Transactional(rollbackFor = Exception.class) + public Long createSaleOut(ErpSaleOutSaveReqVO createReqVO) { + // 1.1 校验订单项的有效性 + List 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); + if (saleOutMapper.selectByNo(no) != null) { + throw exception(SALE_ORDER_NO_EXISTS); + } + + // 2.1 插入订单 + ErpSaleOutDO saleOut = BeanUtils.toBean(createReqVO, ErpSaleOutDO.class, in -> in + .setNo(no).setStatus(ErpAuditStatus.PROCESS.getStatus())); + calculateTotalPrice(saleOut, saleOutItems); + saleOutMapper.insert(saleOut); + // 2.2 插入订单项 + saleOutItems.forEach(o -> o.setOutId(saleOut.getId())); + saleOutItemMapper.insertBatch(saleOutItems); + return saleOut.getId(); + } + + @Override + @Transactional(rollbackFor = Exception.class) + public void updateSaleOut(ErpSaleOutSaveReqVO updateReqVO) { + // 1.1 校验存在 + ErpSaleOutDO saleOut = validateSaleOutExists(updateReqVO.getId()); + if (ErpAuditStatus.APPROVE.getStatus().equals(saleOut.getStatus())) { + throw exception(SALE_ORDER_UPDATE_FAIL_APPROVE, saleOut.getNo()); + } + // 1.2 校验客户 TODO 芋艿:需要在瞅瞅 +// customerService.validateCustomer(updateReqVO.getCustomerId()); + // 1.3 校验结算账户 + accountService.validateAccount(updateReqVO.getAccountId()); + // 1.4 校验订单项的有效性 + List saleOutItems = validateSaleOutItems(updateReqVO.getItems()); + + // 2.1 更新订单 + ErpSaleOutDO updateObj = BeanUtils.toBean(updateReqVO, ErpSaleOutDO.class); + calculateTotalPrice(updateObj, saleOutItems); + saleOutMapper.updateById(updateObj); + // 2.2 更新订单项 + updateSaleOutItemList(updateReqVO.getId(), saleOutItems); + } + + private void calculateTotalPrice(ErpSaleOutDO saleOut, List saleOutItems) { + saleOut.setTotalCount(getSumValue(saleOutItems, ErpSaleOutItemDO::getCount, BigDecimal::add)); + saleOut.setTotalProductPrice(getSumValue(saleOutItems, ErpSaleOutItemDO::getTotalPrice, BigDecimal::add, BigDecimal.ZERO)); + saleOut.setTotalTaxPrice(getSumValue(saleOutItems, ErpSaleOutItemDO::getTaxPrice, BigDecimal::add, BigDecimal.ZERO)); + saleOut.setTotalPrice(saleOut.getTotalProductPrice().add(saleOut.getTotalTaxPrice())); + // 计算优惠价格 + if (saleOut.getDiscountPercent() == null) { + saleOut.setDiscountPercent(BigDecimal.ZERO); + } + saleOut.setDiscountPrice(MoneyUtils.priceMultiply(saleOut.getTotalPrice(), saleOut.getDiscountPercent())); + saleOut.setTotalPrice(saleOut.getTotalPrice().subtract(saleOut.getDiscountPrice())); + } + + @Override + @Transactional(rollbackFor = Exception.class) + public void updateSaleOutStatus(Long id, Integer status) { + boolean approve = ErpAuditStatus.APPROVE.getStatus().equals(status); + // 1.1 校验存在 + ErpSaleOutDO saleOut = validateSaleOutExists(id); + // 1.2 校验状态 + if (saleOut.getStatus().equals(status)) { + throw exception(approve ? SALE_ORDER_APPROVE_FAIL : SALE_ORDER_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); + } + } + + private List validateSaleOutItems(List list) { + // 1. 校验产品存在 + List productList = productService.validProductList( + convertSet(list, ErpSaleOutSaveReqVO.Item::getProductId)); + Map productMap = convertMap(productList, ErpProductDO::getId); + // 2. 转化为 ErpSaleOutItemDO 列表 + return convertList(list, o -> BeanUtils.toBean(o, ErpSaleOutItemDO.class, item -> { + item.setProductUnitId(productMap.get(item.getProductId()).getUnitId()); + item.setTotalPrice(MoneyUtils.priceMultiply(item.getProductPrice(), item.getCount())); + if (item.getTotalPrice() == null) { + return; + } + item.setTaxPrice(MoneyUtils.priceMultiply(item.getTotalPrice(), item.getTaxPercent())); + item.setTotalPrice(item.getTotalPrice().add(item.getTaxPrice())); + })); + } + + private void updateSaleOutItemList(Long id, List newList) { + // 第一步,对比新老数据,获得添加、修改、删除的列表 + List oldList = saleOutItemMapper.selectListByOutId(id); + List> diffList = diffList(oldList, newList, // id 不同,就认为是不同的记录 + (oldVal, newVal) -> oldVal.getId().equals(newVal.getId())); + + // 第二步,批量添加、修改、删除 + if (CollUtil.isNotEmpty(diffList.get(0))) { + diffList.get(0).forEach(o -> o.setOutId(id)); + saleOutItemMapper.insertBatch(diffList.get(0)); + } + if (CollUtil.isNotEmpty(diffList.get(1))) { + saleOutItemMapper.updateBatch(diffList.get(1)); + } + if (CollUtil.isNotEmpty(diffList.get(2))) { + saleOutItemMapper.deleteBatchIds(convertList(diffList.get(2), ErpSaleOutItemDO::getId)); + } + } + + @Override + @Transactional(rollbackFor = Exception.class) + public void deleteSaleOut(List ids) { + // 1. 校验不处于已审批 + List saleOuts = saleOutMapper.selectBatchIds(ids); + if (CollUtil.isEmpty(saleOuts)) { + return; + } + saleOuts.forEach(saleOut -> { + if (ErpAuditStatus.APPROVE.getStatus().equals(saleOut.getStatus())) { + throw exception(SALE_ORDER_DELETE_FAIL_APPROVE, saleOut.getNo()); + } + }); + + // 2. 遍历删除,并记录操作日志 + saleOuts.forEach(saleOut -> { + // 2.1 删除订单 + saleOutMapper.deleteById(saleOut.getId()); + // 2.2 删除订单项 + saleOutItemMapper.deleteByOutId(saleOut.getId()); + }); + } + + private ErpSaleOutDO validateSaleOutExists(Long id) { + ErpSaleOutDO saleOut = saleOutMapper.selectById(id); + if (saleOut == null) { + throw exception(SALE_ORDER_NOT_EXISTS); + } + return saleOut; + } + + @Override + public ErpSaleOutDO getSaleOut(Long id) { + return saleOutMapper.selectById(id); + } + + @Override + public PageResult getSaleOutPage(ErpSaleOutPageReqVO pageReqVO) { + return saleOutMapper.selectPage(pageReqVO); + } + + // ==================== 订单项 ==================== + + @Override + public List getSaleOutItemListByOutId(Long outId) { + return saleOutItemMapper.selectListByOutId(outId); + } + + @Override + public List getSaleOutItemListByOutIds(Collection outIds) { + if (CollUtil.isEmpty(outIds)) { + return Collections.emptyList(); + } + return saleOutItemMapper.selectListByOutIds(outIds); + } + +} \ No newline at end of file From 6f5798720817883b600728a4f711c967a9b1dbe0 Mon Sep 17 00:00:00 2001 From: YunaiV Date: Sat, 10 Feb 2024 22:47:30 +0800 Subject: [PATCH 095/119] =?UTF-8?q?=E2=9C=A8=20ERP=EF=BC=9A=E5=A2=9E?= =?UTF-8?q?=E5=8A=A0=20ERP=20=E9=94=80=E5=94=AE=E5=87=BA=E5=BA=93=E7=9A=84?= =?UTF-8?q?=E5=AE=9E=E7=8E=B0=2030%=EF=BC=88=E5=88=97=E8=A1=A8=EF=BC=89?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../module/erp/dal/dataobject/sale/ErpSaleOutDO.java | 2 -- .../erp/dal/dataobject/sale/ErpSaleOutItemDO.java | 4 ++-- .../module/erp/dal/mysql/finance/ErpAccountMapper.java | 2 +- .../module/erp/dal/mysql/sale/ErpSaleOrderMapper.java | 2 +- .../module/erp/dal/mysql/sale/ErpSaleOutMapper.java | 10 +++++++--- .../erp/dal/mysql/stock/ErpStockCheckMapper.java | 2 +- .../module/erp/dal/mysql/stock/ErpStockInMapper.java | 2 +- .../module/erp/dal/mysql/stock/ErpStockMoveMapper.java | 2 +- .../module/erp/dal/mysql/stock/ErpStockOutMapper.java | 2 +- 9 files changed, 15 insertions(+), 13 deletions(-) diff --git a/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/dal/dataobject/sale/ErpSaleOutDO.java b/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/dal/dataobject/sale/ErpSaleOutDO.java index 1a0e6f1d3..3ce6efcbd 100644 --- a/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/dal/dataobject/sale/ErpSaleOutDO.java +++ b/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/dal/dataobject/sale/ErpSaleOutDO.java @@ -107,8 +107,6 @@ public class ErpSaleOutDO extends BaseDO { private BigDecimal discountPrice; /** * 其它金额,单位:元 - * - * 注意:它不算在 {@link #totalPrice} 中 */ private BigDecimal otherPrice; diff --git a/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/dal/dataobject/sale/ErpSaleOutItemDO.java b/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/dal/dataobject/sale/ErpSaleOutItemDO.java index d13915dae..b9b406413 100644 --- a/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/dal/dataobject/sale/ErpSaleOutItemDO.java +++ b/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/dal/dataobject/sale/ErpSaleOutItemDO.java @@ -16,8 +16,8 @@ import java.math.BigDecimal; * * @author 芋道源码 */ -@TableName("erp_sale_order_items") -@KeySequence("erp_sale_order_items_seq") // 用于 Oracle、PostgreSQL、Kingbase、DB2、H2 数据库的主键自增。如果是 MySQL 等数据库,可不写。 +@TableName("erp_sale_out_items") +@KeySequence("erp_sale_out_items_seq") // 用于 Oracle、PostgreSQL、Kingbase、DB2、H2 数据库的主键自增。如果是 MySQL 等数据库,可不写。 @Data @EqualsAndHashCode(callSuper = true) @ToString(callSuper = true) diff --git a/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/dal/mysql/finance/ErpAccountMapper.java b/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/dal/mysql/finance/ErpAccountMapper.java index d879a933e..693a2804b 100644 --- a/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/dal/mysql/finance/ErpAccountMapper.java +++ b/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/dal/mysql/finance/ErpAccountMapper.java @@ -20,7 +20,7 @@ public interface ErpAccountMapper extends BaseMapperX { default PageResult selectPage(ErpAccountPageReqVO reqVO) { return selectPage(reqVO, new LambdaQueryWrapperX() .likeIfPresent(ErpAccountDO::getName, reqVO.getName()) - .eqIfPresent(ErpAccountDO::getNo, reqVO.getNo()) + .likeIfPresent(ErpAccountDO::getNo, reqVO.getNo()) .eqIfPresent(ErpAccountDO::getRemark, reqVO.getRemark()) .orderByDesc(ErpAccountDO::getId)); } diff --git a/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/dal/mysql/sale/ErpSaleOrderMapper.java b/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/dal/mysql/sale/ErpSaleOrderMapper.java index 70ff75285..d586c32fc 100644 --- a/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/dal/mysql/sale/ErpSaleOrderMapper.java +++ b/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/dal/mysql/sale/ErpSaleOrderMapper.java @@ -22,7 +22,7 @@ public interface ErpSaleOrderMapper extends BaseMapperX { default PageResult selectPage(ErpSaleOrderPageReqVO reqVO) { MPJLambdaWrapperX query = new MPJLambdaWrapperX() - .eqIfPresent(ErpSaleOrderDO::getNo, reqVO.getNo()) + .likeIfPresent(ErpSaleOrderDO::getNo, reqVO.getNo()) .eqIfPresent(ErpSaleOrderDO::getCustomerId, reqVO.getCustomerId()) .betweenIfPresent(ErpSaleOrderDO::getOrderTime, reqVO.getOrderTime()) .eqIfPresent(ErpSaleOrderDO::getStatus, reqVO.getStatus()) diff --git a/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/dal/mysql/sale/ErpSaleOutMapper.java b/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/dal/mysql/sale/ErpSaleOutMapper.java index 809954df9..e146994bf 100644 --- a/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/dal/mysql/sale/ErpSaleOutMapper.java +++ b/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/dal/mysql/sale/ErpSaleOutMapper.java @@ -22,7 +22,7 @@ public interface ErpSaleOutMapper extends BaseMapperX { default PageResult selectPage(ErpSaleOutPageReqVO reqVO) { MPJLambdaWrapperX query = new MPJLambdaWrapperX() - .eqIfPresent(ErpSaleOutDO::getNo, reqVO.getNo()) + .likeIfPresent(ErpSaleOutDO::getNo, reqVO.getNo()) .eqIfPresent(ErpSaleOutDO::getCustomerId, reqVO.getCustomerId()) .betweenIfPresent(ErpSaleOutDO::getOutTime, reqVO.getOutTime()) .eqIfPresent(ErpSaleOutDO::getStatus, reqVO.getStatus()) @@ -31,8 +31,12 @@ public interface ErpSaleOutMapper extends BaseMapperX { .eqIfPresent(ErpSaleOutDO::getAccountId, reqVO.getAccountId()) .likeIfPresent(ErpSaleOutDO::getOrderNo, reqVO.getOrderNo()) .orderByDesc(ErpSaleOutDO::getId); - query.gt(Boolean.TRUE.equals(reqVO.getDebtStatus()), ErpSaleOutDO::getDebtPrice, BigDecimal.ZERO); - if (reqVO.getWarehouseId() != null && reqVO.getProductId() != null) { + if (Boolean.TRUE.equals(reqVO.getDebtStatus())) { + query.gt(ErpSaleOutDO::getDebtPrice, BigDecimal.ZERO); + } else if (Boolean.FALSE.equals(reqVO.getDebtStatus())) { + query.eq(ErpSaleOutDO::getDebtPrice, BigDecimal.ZERO); + } + if (reqVO.getWarehouseId() != null || reqVO.getProductId() != null) { query.leftJoin(ErpSaleOutItemDO.class, ErpSaleOutItemDO::getOutId, ErpSaleOutDO::getId) .eq(reqVO.getWarehouseId() != null, ErpSaleOutItemDO::getWarehouseId, reqVO.getWarehouseId()) .eq(reqVO.getProductId() != null, ErpSaleOutItemDO::getProductId, reqVO.getProductId()) diff --git a/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/dal/mysql/stock/ErpStockCheckMapper.java b/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/dal/mysql/stock/ErpStockCheckMapper.java index 3328f39b2..dd976df3d 100644 --- a/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/dal/mysql/stock/ErpStockCheckMapper.java +++ b/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/dal/mysql/stock/ErpStockCheckMapper.java @@ -19,7 +19,7 @@ public interface ErpStockCheckMapper extends BaseMapperX { default PageResult selectPage(ErpStockCheckPageReqVO reqVO) { MPJLambdaWrapperX query = new MPJLambdaWrapperX() - .eqIfPresent(ErpStockCheckDO::getNo, reqVO.getNo()) + .likeIfPresent(ErpStockCheckDO::getNo, reqVO.getNo()) .betweenIfPresent(ErpStockCheckDO::getCheckTime, reqVO.getCheckTime()) .eqIfPresent(ErpStockCheckDO::getStatus, reqVO.getStatus()) .likeIfPresent(ErpStockCheckDO::getRemark, reqVO.getRemark()) diff --git a/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/dal/mysql/stock/ErpStockInMapper.java b/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/dal/mysql/stock/ErpStockInMapper.java index 9e7ea9bca..e815583ac 100644 --- a/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/dal/mysql/stock/ErpStockInMapper.java +++ b/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/dal/mysql/stock/ErpStockInMapper.java @@ -19,7 +19,7 @@ public interface ErpStockInMapper extends BaseMapperX { default PageResult selectPage(ErpStockInPageReqVO reqVO) { MPJLambdaWrapperX query = new MPJLambdaWrapperX() - .eqIfPresent(ErpStockInDO::getNo, reqVO.getNo()) + .likeIfPresent(ErpStockInDO::getNo, reqVO.getNo()) .eqIfPresent(ErpStockInDO::getSupplierId, reqVO.getSupplierId()) .betweenIfPresent(ErpStockInDO::getInTime, reqVO.getInTime()) .eqIfPresent(ErpStockInDO::getStatus, reqVO.getStatus()) diff --git a/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/dal/mysql/stock/ErpStockMoveMapper.java b/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/dal/mysql/stock/ErpStockMoveMapper.java index 2b45f6c7e..9a8ce0b64 100644 --- a/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/dal/mysql/stock/ErpStockMoveMapper.java +++ b/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/dal/mysql/stock/ErpStockMoveMapper.java @@ -19,7 +19,7 @@ public interface ErpStockMoveMapper extends BaseMapperX { default PageResult selectPage(ErpStockMovePageReqVO reqVO) { MPJLambdaWrapperX query = new MPJLambdaWrapperX() - .eqIfPresent(ErpStockMoveDO::getNo, reqVO.getNo()) + .likeIfPresent(ErpStockMoveDO::getNo, reqVO.getNo()) .betweenIfPresent(ErpStockMoveDO::getMoveTime, reqVO.getMoveTime()) .eqIfPresent(ErpStockMoveDO::getStatus, reqVO.getStatus()) .likeIfPresent(ErpStockMoveDO::getRemark, reqVO.getRemark()) diff --git a/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/dal/mysql/stock/ErpStockOutMapper.java b/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/dal/mysql/stock/ErpStockOutMapper.java index f27e01310..a73dd3ccf 100644 --- a/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/dal/mysql/stock/ErpStockOutMapper.java +++ b/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/dal/mysql/stock/ErpStockOutMapper.java @@ -19,7 +19,7 @@ public interface ErpStockOutMapper extends BaseMapperX { default PageResult selectPage(ErpStockOutPageReqVO reqVO) { MPJLambdaWrapperX query = new MPJLambdaWrapperX() - .eqIfPresent(ErpStockOutDO::getNo, reqVO.getNo()) + .likeIfPresent(ErpStockOutDO::getNo, reqVO.getNo()) .eqIfPresent(ErpStockOutDO::getCustomerId, reqVO.getCustomerId()) .betweenIfPresent(ErpStockOutDO::getOutTime, reqVO.getOutTime()) .eqIfPresent(ErpStockOutDO::getStatus, reqVO.getStatus()) From 09e4763c7997f34b06da4ec2e60d7ad197ee87aa Mon Sep 17 00:00:00 2001 From: YunaiV Date: Sun, 11 Feb 2024 10:33:37 +0800 Subject: [PATCH 096/119] =?UTF-8?q?=E2=9C=A8=20ERP=EF=BC=9A=E5=A2=9E?= =?UTF-8?q?=E5=8A=A0=20ERP=20=E5=8F=AF=E5=87=BA=E5=BA=93=E8=AE=A2=E5=8D=95?= =?UTF-8?q?=E5=88=97=E8=A1=A8?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../admin/sale/vo/order/ErpSaleOrderPageReqVO.java | 3 +++ .../yudao/module/erp/dal/mysql/sale/ErpSaleOrderMapper.java | 6 ++++++ 2 files changed, 9 insertions(+) diff --git a/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/controller/admin/sale/vo/order/ErpSaleOrderPageReqVO.java b/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/controller/admin/sale/vo/order/ErpSaleOrderPageReqVO.java index ae430d78f..13b1abd76 100644 --- a/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/controller/admin/sale/vo/order/ErpSaleOrderPageReqVO.java +++ b/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/controller/admin/sale/vo/order/ErpSaleOrderPageReqVO.java @@ -71,4 +71,7 @@ public class ErpSaleOrderPageReqVO extends PageParam { @Schema(description = "退货状态", example = "2") private Integer returnStatus; + @Schema(description = "是否可出库", example = "true") + private Boolean outEnable; + } \ No newline at end of file diff --git a/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/dal/mysql/sale/ErpSaleOrderMapper.java b/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/dal/mysql/sale/ErpSaleOrderMapper.java index d586c32fc..ca0066f4f 100644 --- a/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/dal/mysql/sale/ErpSaleOrderMapper.java +++ b/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/dal/mysql/sale/ErpSaleOrderMapper.java @@ -7,6 +7,7 @@ import cn.iocoder.yudao.framework.mybatis.core.query.MPJLambdaWrapperX; import cn.iocoder.yudao.module.erp.controller.admin.sale.vo.order.ErpSaleOrderPageReqVO; import cn.iocoder.yudao.module.erp.dal.dataobject.sale.ErpSaleOrderDO; import cn.iocoder.yudao.module.erp.dal.dataobject.sale.ErpSaleOrderItemDO; +import cn.iocoder.yudao.module.erp.enums.ErpAuditStatus; import com.baomidou.mybatisplus.core.conditions.update.LambdaUpdateWrapper; import org.apache.ibatis.annotations.Mapper; @@ -45,6 +46,11 @@ public interface ErpSaleOrderMapper extends BaseMapperX { } else if (Objects.equals(reqVO.getReturnStatus(), ErpSaleOrderPageReqVO.RETURN_STATUS_ALL)) { query.apply("t.return_count = t.total_count"); } + // 可出库 + if (Boolean.TRUE.equals(reqVO.getOutEnable())) { + query.eq(ErpSaleOrderDO::getStatus, ErpAuditStatus.APPROVE.getStatus()) + .apply("t.in_count < t.total_count"); + } if (reqVO.getProductId() != null) { query.leftJoin(ErpSaleOrderItemDO.class, ErpSaleOrderItemDO::getOrderId, ErpSaleOrderDO::getId) .eq(reqVO.getProductId() != null, ErpSaleOrderItemDO::getProductId, reqVO.getProductId()) From 0694bc868447ddb5210ceb359720fd2d31e72682 Mon Sep 17 00:00:00 2001 From: YunaiV Date: Sun, 11 Feb 2024 21:19:16 +0800 Subject: [PATCH 097/119] =?UTF-8?q?=E2=9C=A8=20ERP=EF=BC=9A=E5=AE=8C?= =?UTF-8?q?=E5=96=84=20ERP=20=E9=94=80=E5=94=AE=E5=87=BA=E5=BA=93=E5=8D=95?= =?UTF-8?q?=E7=9A=84=E4=BF=9D=E5=AD=98?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../util/collection/CollectionUtils.java | 2 +- .../module/erp/enums/ErrorCodeConstants.java | 11 +++ .../sale/vo/order/ErpSaleOrderRespVO.java | 16 +++- .../admin/sale/vo/out/ErpSaleOutRespVO.java | 2 +- .../dal/dataobject/sale/ErpSaleOrderDO.java | 6 +- .../dataobject/sale/ErpSaleOrderItemDO.java | 6 +- .../erp/dal/dataobject/sale/ErpSaleOutDO.java | 2 +- .../dal/mysql/sale/ErpSaleOrderMapper.java | 10 +-- .../dal/mysql/sale/ErpSaleOutItemMapper.java | 26 +++++++ .../erp/dal/mysql/sale/ErpSaleOutMapper.java | 5 ++ .../erp/dal/redis/no/ErpNoRedisDAO.java | 4 + .../erp/service/sale/ErpSaleOrderService.java | 18 +++++ .../service/sale/ErpSaleOrderServiceImpl.java | 52 ++++++++++++- .../service/sale/ErpSaleOutServiceImpl.java | 77 ++++++++++++++----- .../module/system/api/user/AdminUserApi.java | 12 +++ 15 files changed, 211 insertions(+), 38 deletions(-) diff --git a/yudao-framework/yudao-common/src/main/java/cn/iocoder/yudao/framework/common/util/collection/CollectionUtils.java b/yudao-framework/yudao-common/src/main/java/cn/iocoder/yudao/framework/common/util/collection/CollectionUtils.java index 2d9e4dd63..4fd6203f8 100644 --- a/yudao-framework/yudao-common/src/main/java/cn/iocoder/yudao/framework/common/util/collection/CollectionUtils.java +++ b/yudao-framework/yudao-common/src/main/java/cn/iocoder/yudao/framework/common/util/collection/CollectionUtils.java @@ -291,7 +291,7 @@ public class CollectionUtils { return getSumValue(from, valueFunc, accumulator, null); } - public static > V getSumValue(List from, Function valueFunc, + public static > V getSumValue(Collection from, Function valueFunc, BinaryOperator accumulator, V defaultValue) { if (CollUtil.isEmpty(from)) { return defaultValue; diff --git a/yudao-module-erp/yudao-module-erp-api/src/main/java/cn/iocoder/yudao/module/erp/enums/ErrorCodeConstants.java b/yudao-module-erp/yudao-module-erp-api/src/main/java/cn/iocoder/yudao/module/erp/enums/ErrorCodeConstants.java index 958e25898..c25a544ec 100644 --- a/yudao-module-erp/yudao-module-erp-api/src/main/java/cn/iocoder/yudao/module/erp/enums/ErrorCodeConstants.java +++ b/yudao-module-erp/yudao-module-erp-api/src/main/java/cn/iocoder/yudao/module/erp/enums/ErrorCodeConstants.java @@ -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, "仓库不存在"); diff --git a/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/controller/admin/sale/vo/order/ErpSaleOrderRespVO.java b/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/controller/admin/sale/vo/order/ErpSaleOrderRespVO.java index 0beb312ee..8b0aa83ea 100644 --- a/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/controller/admin/sale/vo/order/ErpSaleOrderRespVO.java +++ b/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/controller/admin/sale/vo/order/ErpSaleOrderRespVO.java @@ -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 = "巧克力") diff --git a/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/controller/admin/sale/vo/out/ErpSaleOutRespVO.java b/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/controller/admin/sale/vo/out/ErpSaleOutRespVO.java index 3901d9e05..3f85a902a 100644 --- a/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/controller/admin/sale/vo/out/ErpSaleOutRespVO.java +++ b/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/controller/admin/sale/vo/out/ErpSaleOutRespVO.java @@ -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("合计数量") diff --git a/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/dal/dataobject/sale/ErpSaleOrderDO.java b/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/dal/dataobject/sale/ErpSaleOrderDO.java index 5f34e2aa4..81f02ccc3 100644 --- a/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/dal/dataobject/sale/ErpSaleOrderDO.java +++ b/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/dal/dataobject/sale/ErpSaleOrderDO.java @@ -106,11 +106,11 @@ public class ErpSaleOrderDO extends BaseDO { */ private String remark; - // ========== 销售入库 ========== + // ========== 销售出库 ========== /** - * 销售入库数量 + * 销售出库数量 */ - private BigDecimal inCount; + private BigDecimal outCount; // ========== 销售退货(出库)) ========== /** diff --git a/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/dal/dataobject/sale/ErpSaleOrderItemDO.java b/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/dal/dataobject/sale/ErpSaleOrderItemDO.java index 5cdf3a14c..3a9778aec 100644 --- a/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/dal/dataobject/sale/ErpSaleOrderItemDO.java +++ b/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/dal/dataobject/sale/ErpSaleOrderItemDO.java @@ -78,11 +78,11 @@ public class ErpSaleOrderItemDO extends BaseDO { */ private String remark; - // ========== 销售入库 ========== + // ========== 销售出库 ========== /** - * 销售入库数量 + * 销售出库数量 */ - private BigDecimal inCount; + private BigDecimal outCount; // ========== 销售退货(出库)) ========== /** diff --git a/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/dal/dataobject/sale/ErpSaleOutDO.java b/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/dal/dataobject/sale/ErpSaleOutDO.java index 3ce6efcbd..57ab55650 100644 --- a/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/dal/dataobject/sale/ErpSaleOutDO.java +++ b/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/dal/dataobject/sale/ErpSaleOutDO.java @@ -74,7 +74,7 @@ public class ErpSaleOutDO extends BaseDO { * * 冗余 {@link ErpSaleOrderDO#getNo()} */ - private Long orderNo; + private String orderNo; /** * 合计数量 diff --git a/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/dal/mysql/sale/ErpSaleOrderMapper.java b/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/dal/mysql/sale/ErpSaleOrderMapper.java index ca0066f4f..f290fb6fd 100644 --- a/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/dal/mysql/sale/ErpSaleOrderMapper.java +++ b/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/dal/mysql/sale/ErpSaleOrderMapper.java @@ -30,13 +30,13 @@ public interface ErpSaleOrderMapper extends BaseMapperX { .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 { // 可出库 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) diff --git a/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/dal/mysql/sale/ErpSaleOutItemMapper.java b/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/dal/mysql/sale/ErpSaleOutItemMapper.java index 957667c73..b5fab517c 100644 --- a/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/dal/mysql/sale/ErpSaleOutItemMapper.java +++ b/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/dal/mysql/sale/ErpSaleOutItemMapper.java @@ -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 { return delete(ErpSaleOutItemDO::getOutId, orderId); } + /** + * 基于销售订单编号,查询每个销售订单项的出库数量之和 + * + * @param outIds 出库订单项编号数组 + * @return key:销售订单项编号;value:出库数量之和 + */ + default Map selectOrderItemCountSumMapByOutIds(Collection outIds) { + if (CollUtil.isEmpty(outIds)) { + return Collections.emptyMap(); + } + // SQL sum 查询 + List> result = selectMaps(new QueryWrapper() + .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")); + } + } \ No newline at end of file diff --git a/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/dal/mysql/sale/ErpSaleOutMapper.java b/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/dal/mysql/sale/ErpSaleOutMapper.java index e146994bf..e530557fb 100644 --- a/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/dal/mysql/sale/ErpSaleOutMapper.java +++ b/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/dal/mysql/sale/ErpSaleOutMapper.java @@ -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 { return selectOne(ErpSaleOutDO::getNo, no); } + default List selectListByOrderId(Long orderId) { + return selectList(ErpSaleOutDO::getOrderId, orderId); + } + } \ No newline at end of file diff --git a/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/dal/redis/no/ErpNoRedisDAO.java b/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/dal/redis/no/ErpNoRedisDAO.java index 0e48e97e1..7e88beb6d 100644 --- a/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/dal/redis/no/ErpNoRedisDAO.java +++ b/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/dal/redis/no/ErpNoRedisDAO.java @@ -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; diff --git a/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/service/sale/ErpSaleOrderService.java b/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/service/sale/ErpSaleOrderService.java index cd32f62c4..0a204b315 100644 --- a/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/service/sale/ErpSaleOrderService.java +++ b/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/service/sale/ErpSaleOrderService.java @@ -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 returnCountMap); + /** * 删除销售订单 * @@ -55,6 +65,14 @@ public interface ErpSaleOrderService { */ ErpSaleOrderDO getSaleOrder(Long id); + /** + * 校验销售订单,已经审核通过 + * + * @param id 编号 + * @return 销售订单 + */ + ErpSaleOrderDO validateSaleOrder(Long id); + /** * 获得销售订单分页 * diff --git a/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/service/sale/ErpSaleOrderServiceImpl.java b/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/service/sale/ErpSaleOrderServiceImpl.java index fae8fe114..c9945b5e4 100644 --- a/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/service/sale/ErpSaleOrderServiceImpl.java +++ b/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/service/sale/ErpSaleOrderServiceImpl.java @@ -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 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 returnCountMap) { + List 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 validateSaleOrderItems(List list) { // 1. 校验产品存在 List 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 getSaleOrderPage(ErpSaleOrderPageReqVO pageReqVO) { return saleOrderMapper.selectPage(pageReqVO); diff --git a/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/service/sale/ErpSaleOutServiceImpl.java b/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/service/sale/ErpSaleOutServiceImpl.java index aae5a60de..7f6ebc777 100644 --- a/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/service/sale/ErpSaleOutServiceImpl.java +++ b/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/service/sale/ErpSaleOutServiceImpl.java @@ -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 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 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 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 saleOuts = saleOutMapper.selectListByOrderId(orderId); + // 1.2 查询对应的销售订单项的出库数量 + Map 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; } diff --git a/yudao-module-system/yudao-module-system-api/src/main/java/cn/iocoder/yudao/module/system/api/user/AdminUserApi.java b/yudao-module-system/yudao-module-system-api/src/main/java/cn/iocoder/yudao/module/system/api/user/AdminUserApi.java index b6cab3030..cea3c3663 100644 --- a/yudao-module-system/yudao-module-system-api/src/main/java/cn/iocoder/yudao/module/system/api/user/AdminUserApi.java +++ b/yudao-module-system/yudao-module-system-api/src/main/java/cn/iocoder/yudao/module/system/api/user/AdminUserApi.java @@ -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. 用户编号不存在 From dbc367ad9511445c437b3b17aa5a92df4b13bab8 Mon Sep 17 00:00:00 2001 From: YunaiV Date: Sun, 11 Feb 2024 22:12:56 +0800 Subject: [PATCH 098/119] =?UTF-8?q?=E2=9C=A8=20ERP=EF=BC=9A=E5=9F=BA?= =?UTF-8?q?=E6=9C=AC=E5=AE=8C=E6=88=90=E9=94=80=E5=94=AE=E5=85=A5=E5=BA=93?= =?UTF-8?q?=E6=A8=A1=E5=9D=97?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../common/util/number/MoneyUtils.java | 21 ++++++++++++++ .../stock/ErpStockRecordBizTypeEnum.java | 3 ++ .../service/sale/ErpSaleOrderServiceImpl.java | 9 ++++-- .../service/sale/ErpSaleOutServiceImpl.java | 28 +++++++++++++++++-- 4 files changed, 55 insertions(+), 6 deletions(-) diff --git a/yudao-framework/yudao-common/src/main/java/cn/iocoder/yudao/framework/common/util/number/MoneyUtils.java b/yudao-framework/yudao-common/src/main/java/cn/iocoder/yudao/framework/common/util/number/MoneyUtils.java index dbc16dc86..90888d7d3 100644 --- a/yudao-framework/yudao-common/src/main/java/cn/iocoder/yudao/framework/common/util/number/MoneyUtils.java +++ b/yudao-framework/yudao-common/src/main/java/cn/iocoder/yudao/framework/common/util/number/MoneyUtils.java @@ -18,6 +18,11 @@ public class MoneyUtils { */ private static final int PRICE_SCALE = 2; + /** + * 百分比对应的 BigDecimal 对象 + */ + public static final BigDecimal PERCENT_100 = BigDecimal.valueOf(100); + /** * 计算百分比金额,四舍五入 * @@ -107,4 +112,20 @@ public class MoneyUtils { return price.multiply(count).setScale(PRICE_SCALE, RoundingMode.HALF_UP); } + /** + * 金额相乘(百分比),默认进行四舍五入 + * + * 位数:{@link #PRICE_SCALE} + * + * @param price 金额 + * @param percent 百分比 + * @return 金额相乘结果 + */ + public static BigDecimal priceMultiplyPercent(BigDecimal price, BigDecimal percent) { + if (price == null || percent == null) { + return null; + } + return price.multiply(percent).divide(PERCENT_100, PRICE_SCALE, RoundingMode.HALF_UP); + } + } diff --git a/yudao-module-erp/yudao-module-erp-api/src/main/java/cn/iocoder/yudao/module/erp/enums/stock/ErpStockRecordBizTypeEnum.java b/yudao-module-erp/yudao-module-erp-api/src/main/java/cn/iocoder/yudao/module/erp/enums/stock/ErpStockRecordBizTypeEnum.java index 31129a2e4..01da541b9 100644 --- a/yudao-module-erp/yudao-module-erp-api/src/main/java/cn/iocoder/yudao/module/erp/enums/stock/ErpStockRecordBizTypeEnum.java +++ b/yudao-module-erp/yudao-module-erp-api/src/main/java/cn/iocoder/yudao/module/erp/enums/stock/ErpStockRecordBizTypeEnum.java @@ -30,6 +30,9 @@ public enum ErpStockRecordBizTypeEnum implements IntArrayValuable { CHECK_MORE_IN_CANCEL(41, "盘盈入库(作废)"), CHECK_LESS_OUT(42, "盘亏出库"), CHECK_LESS_OUT_CANCEL(43, "盘亏出库(作废)"), + + SALE_OUT(50, "销售出库"), + SALE_OUT_CANCEL(51, "销售出库(作废)"), ; public static final int[] ARRAYS = Arrays.stream(values()).mapToInt(ErpStockRecordBizTypeEnum::getType).toArray(); diff --git a/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/service/sale/ErpSaleOrderServiceImpl.java b/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/service/sale/ErpSaleOrderServiceImpl.java index c9945b5e4..fff5add14 100644 --- a/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/service/sale/ErpSaleOrderServiceImpl.java +++ b/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/service/sale/ErpSaleOrderServiceImpl.java @@ -131,7 +131,7 @@ public class ErpSaleOrderServiceImpl implements ErpSaleOrderService { if (saleOrder.getDiscountPercent() == null) { saleOrder.setDiscountPercent(BigDecimal.ZERO); } - saleOrder.setDiscountPrice(MoneyUtils.priceMultiply(saleOrder.getTotalPrice(), saleOrder.getDiscountPercent())); + saleOrder.setDiscountPrice(MoneyUtils.priceMultiplyPercent(saleOrder.getTotalPrice(), saleOrder.getDiscountPercent())); saleOrder.setTotalPrice(saleOrder.getTotalPrice().subtract(saleOrder.getDiscountPrice())); } @@ -191,8 +191,11 @@ public class ErpSaleOrderServiceImpl implements ErpSaleOrderService { if (item.getTotalPrice() == null) { return; } - item.setTaxPrice(MoneyUtils.priceMultiply(item.getTotalPrice(), item.getTaxPercent())); - item.setTotalPrice(item.getTotalPrice().add(item.getTaxPrice())); + if (item.getTaxPercent() == null) { + item.setTaxPercent(BigDecimal.ZERO); + } else { + item.setTaxPrice(MoneyUtils.priceMultiplyPercent(item.getTotalPrice(), item.getTaxPercent())); + } })); } diff --git a/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/service/sale/ErpSaleOutServiceImpl.java b/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/service/sale/ErpSaleOutServiceImpl.java index 7f6ebc777..f0943d407 100644 --- a/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/service/sale/ErpSaleOutServiceImpl.java +++ b/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/service/sale/ErpSaleOutServiceImpl.java @@ -15,8 +15,11 @@ import cn.iocoder.yudao.module.erp.dal.mysql.sale.ErpSaleOutItemMapper; import cn.iocoder.yudao.module.erp.dal.mysql.sale.ErpSaleOutMapper; import cn.iocoder.yudao.module.erp.dal.redis.no.ErpNoRedisDAO; import cn.iocoder.yudao.module.erp.enums.ErpAuditStatus; +import cn.iocoder.yudao.module.erp.enums.stock.ErpStockRecordBizTypeEnum; import cn.iocoder.yudao.module.erp.service.finance.ErpAccountService; import cn.iocoder.yudao.module.erp.service.product.ErpProductService; +import cn.iocoder.yudao.module.erp.service.stock.ErpStockRecordService; +import cn.iocoder.yudao.module.erp.service.stock.bo.ErpStockRecordCreateReqBO; import cn.iocoder.yudao.module.system.api.user.AdminUserApi; import jakarta.annotation.Resource; import org.springframework.context.annotation.Lazy; @@ -60,6 +63,8 @@ public class ErpSaleOutServiceImpl implements ErpSaleOutService { private ErpSaleOrderService saleOrderService; @Resource private ErpAccountService accountService; + @Resource + private ErpStockRecordService stockRecordService; @Resource private AdminUserApi adminUserApi; @@ -142,8 +147,11 @@ public class ErpSaleOutServiceImpl implements ErpSaleOutService { if (saleOut.getDiscountPercent() == null) { saleOut.setDiscountPercent(BigDecimal.ZERO); } - saleOut.setDiscountPrice(MoneyUtils.priceMultiply(saleOut.getTotalPrice(), saleOut.getDiscountPercent())); + saleOut.setDiscountPrice(MoneyUtils.priceMultiplyPercent(saleOut.getTotalPrice(), saleOut.getDiscountPercent())); saleOut.setTotalPrice(saleOut.getTotalPrice().subtract(saleOut.getDiscountPrice())); + // 计算应收金额 + BigDecimal allPrice = saleOut.getTotalPrice().add(saleOut.getOtherPrice()); + saleOut.setDebtPrice(allPrice.subtract(saleOut.getPayPrice())); } private void updateSaleOrderOutCount(Long orderId) { @@ -173,6 +181,17 @@ public class ErpSaleOutServiceImpl implements ErpSaleOutService { if (updateCount == 0) { throw exception(approve ? SALE_OUT_APPROVE_FAIL : SALE_OUT_PROCESS_FAIL); } + + // 3. 变更库存 + List saleOutItems = saleOutItemMapper.selectListByOutId(id); + Integer bizType = approve ? ErpStockRecordBizTypeEnum.SALE_OUT.getType() + : ErpStockRecordBizTypeEnum.SALE_OUT_CANCEL.getType(); + saleOutItems.forEach(saleOutItem -> { + BigDecimal count = approve ? saleOutItem.getCount().negate() : saleOutItem.getCount(); + stockRecordService.createStockRecord(new ErpStockRecordCreateReqBO( + saleOutItem.getProductId(), saleOutItem.getWarehouseId(), count, + bizType, saleOutItem.getOutId(), saleOutItem.getId(), saleOut.getNo())); + }); } private List validateSaleOutItems(List list) { @@ -187,8 +206,11 @@ public class ErpSaleOutServiceImpl implements ErpSaleOutService { if (item.getTotalPrice() == null) { return; } - item.setTaxPrice(MoneyUtils.priceMultiply(item.getTotalPrice(), item.getTaxPercent())); - item.setTotalPrice(item.getTotalPrice().add(item.getTaxPrice())); + if (item.getTaxPercent() == null) { + item.setTaxPercent(BigDecimal.ZERO); + } else { + item.setTaxPrice(MoneyUtils.priceMultiplyPercent(item.getTotalPrice(), item.getTaxPercent())); + } })); } From 926286fe08799aea7a78c08c0fbb6220897404df Mon Sep 17 00:00:00 2001 From: YunaiV Date: Mon, 12 Feb 2024 06:08:09 +0800 Subject: [PATCH 099/119] =?UTF-8?q?=E2=9C=A8=20ERP=EF=BC=9A=E5=88=9D?= =?UTF-8?q?=E5=A7=8B=E5=8C=96=E9=94=80=E5=94=AE=E9=80=80=E8=B4=A7=E9=80=BB?= =?UTF-8?q?=E8=BE=91=2050%?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../module/erp/enums/ErrorCodeConstants.java | 12 +- .../stock/ErpStockRecordBizTypeEnum.java | 3 + .../admin/sale/ErpSaleReturnController.java | 165 ++++++++++ .../sale/vo/out/ErpSaleOutPageReqVO.java | 2 +- .../admin/sale/vo/out/ErpSaleOutRespVO.java | 2 +- .../vo/returns/ErpSaleReturnPageReqVO.java | 51 +++ .../sale/vo/returns/ErpSaleReturnRespVO.java | 152 +++++++++ .../vo/returns/ErpSaleReturnSaveReqVO.java | 88 ++++++ .../dal/dataobject/sale/ErpSaleReturnDO.java | 133 ++++++++ .../dataobject/sale/ErpSaleReturnItemDO.java | 95 ++++++ .../dal/mysql/sale/ErpSaleOutItemMapper.java | 12 +- .../mysql/sale/ErpSaleReturnItemMapper.java | 56 ++++ .../dal/mysql/sale/ErpSaleReturnMapper.java | 56 ++++ .../erp/dal/redis/no/ErpNoRedisDAO.java | 4 + .../erp/service/sale/ErpSaleOrderService.java | 12 +- .../service/sale/ErpSaleOrderServiceImpl.java | 65 ++-- .../service/sale/ErpSaleOutServiceImpl.java | 14 +- .../service/sale/ErpSaleReturnService.java | 84 +++++ .../sale/ErpSaleReturnServiceImpl.java | 296 ++++++++++++++++++ 19 files changed, 1263 insertions(+), 39 deletions(-) create mode 100644 yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/controller/admin/sale/ErpSaleReturnController.java create mode 100644 yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/controller/admin/sale/vo/returns/ErpSaleReturnPageReqVO.java create mode 100644 yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/controller/admin/sale/vo/returns/ErpSaleReturnRespVO.java create mode 100644 yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/controller/admin/sale/vo/returns/ErpSaleReturnSaveReqVO.java create mode 100644 yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/dal/dataobject/sale/ErpSaleReturnDO.java create mode 100644 yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/dal/dataobject/sale/ErpSaleReturnItemDO.java create mode 100644 yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/dal/mysql/sale/ErpSaleReturnItemMapper.java create mode 100644 yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/dal/mysql/sale/ErpSaleReturnMapper.java create mode 100644 yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/service/sale/ErpSaleReturnService.java create mode 100644 yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/service/sale/ErpSaleReturnServiceImpl.java diff --git a/yudao-module-erp/yudao-module-erp-api/src/main/java/cn/iocoder/yudao/module/erp/enums/ErrorCodeConstants.java b/yudao-module-erp/yudao-module-erp-api/src/main/java/cn/iocoder/yudao/module/erp/enums/ErrorCodeConstants.java index c25a544ec..7fc4007d8 100644 --- a/yudao-module-erp/yudao-module-erp-api/src/main/java/cn/iocoder/yudao/module/erp/enums/ErrorCodeConstants.java +++ b/yudao-module-erp/yudao-module-erp-api/src/main/java/cn/iocoder/yudao/module/erp/enums/ErrorCodeConstants.java @@ -26,7 +26,9 @@ public interface ErrorCodeConstants { 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, "反审核失败,已存在对应的销售出库单"); + ErrorCode SALE_ORDER_PROCESS_FAIL_EXISTS_OUT = new ErrorCode(1_020_201_008, "反审核失败,已存在对应的销售出库单"); + ErrorCode SALE_ORDER_ITEM_RETURN_FAIL_OUT_EXCEED = new ErrorCode(1_020_201_009, "销售订单项({})超过最大允许退货数量({})"); + ErrorCode SALE_ORDER_PROCESS_FAIL_EXISTS_RETURN = new ErrorCode(1_020_201_010, "反审核失败,已存在对应的销售退货单"); // ========== ERP 销售出库(1-030-202-000) ========== ErrorCode SALE_OUT_NOT_EXISTS = new ErrorCode(1_020_202_000, "销售出库单不存在"); @@ -36,6 +38,14 @@ public interface ErrorCodeConstants { 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-203-000) ========== + ErrorCode SALE_RETURN_NOT_EXISTS = new ErrorCode(1_020_203_000, "销售退货单不存在"); + ErrorCode SALE_RETURN_DELETE_FAIL_APPROVE = new ErrorCode(1_020_203_001, "销售退货单({})已审核,无法删除"); + ErrorCode SALE_RETURN_PROCESS_FAIL = new ErrorCode(1_020_203_002, "反审核失败,只有已审核的退货单才能反审核"); + ErrorCode SALE_RETURN_APPROVE_FAIL = new ErrorCode(1_020_203_003, "审核失败,只有未审核的退货单才能审核"); + ErrorCode SALE_RETURN_NO_EXISTS = new ErrorCode(1_020_203_004, "生成退货单失败,请重新提交"); + ErrorCode SALE_RETURN_UPDATE_FAIL_APPROVE = new ErrorCode(1_020_203_005, "销售退货单({})已审核,无法修改"); + // ========== ERP 仓库 1-030-400-000 ========== ErrorCode WAREHOUSE_NOT_EXISTS = new ErrorCode(1_030_400_000, "仓库不存在"); ErrorCode WAREHOUSE_NOT_ENABLE = new ErrorCode(1_030_400_001, "仓库({})未启用"); diff --git a/yudao-module-erp/yudao-module-erp-api/src/main/java/cn/iocoder/yudao/module/erp/enums/stock/ErpStockRecordBizTypeEnum.java b/yudao-module-erp/yudao-module-erp-api/src/main/java/cn/iocoder/yudao/module/erp/enums/stock/ErpStockRecordBizTypeEnum.java index 01da541b9..05379ba9f 100644 --- a/yudao-module-erp/yudao-module-erp-api/src/main/java/cn/iocoder/yudao/module/erp/enums/stock/ErpStockRecordBizTypeEnum.java +++ b/yudao-module-erp/yudao-module-erp-api/src/main/java/cn/iocoder/yudao/module/erp/enums/stock/ErpStockRecordBizTypeEnum.java @@ -33,6 +33,9 @@ public enum ErpStockRecordBizTypeEnum implements IntArrayValuable { SALE_OUT(50, "销售出库"), SALE_OUT_CANCEL(51, "销售出库(作废)"), + + SALE_RETURN(60, "销售退货入库"), + SALE_RETURN_CANCEL(61, "销售退货入库(作废)"), ; public static final int[] ARRAYS = Arrays.stream(values()).mapToInt(ErpStockRecordBizTypeEnum::getType).toArray(); diff --git a/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/controller/admin/sale/ErpSaleReturnController.java b/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/controller/admin/sale/ErpSaleReturnController.java new file mode 100644 index 000000000..3c95fa640 --- /dev/null +++ b/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/controller/admin/sale/ErpSaleReturnController.java @@ -0,0 +1,165 @@ +package cn.iocoder.yudao.module.erp.controller.admin.sale; + +import cn.hutool.core.collection.CollUtil; +import cn.iocoder.yudao.framework.common.pojo.CommonResult; +import cn.iocoder.yudao.framework.common.pojo.PageParam; +import cn.iocoder.yudao.framework.common.pojo.PageResult; +import cn.iocoder.yudao.framework.common.util.collection.MapUtils; +import cn.iocoder.yudao.framework.common.util.object.BeanUtils; +import cn.iocoder.yudao.framework.excel.core.util.ExcelUtils; +import cn.iocoder.yudao.framework.operatelog.core.annotations.OperateLog; +import cn.iocoder.yudao.module.erp.controller.admin.product.vo.product.ErpProductRespVO; +import cn.iocoder.yudao.module.erp.controller.admin.sale.vo.returns.ErpSaleReturnPageReqVO; +import cn.iocoder.yudao.module.erp.controller.admin.sale.vo.returns.ErpSaleReturnRespVO; +import cn.iocoder.yudao.module.erp.controller.admin.sale.vo.returns.ErpSaleReturnSaveReqVO; +import cn.iocoder.yudao.module.erp.dal.dataobject.sale.ErpCustomerDO; +import cn.iocoder.yudao.module.erp.dal.dataobject.sale.ErpSaleReturnDO; +import cn.iocoder.yudao.module.erp.dal.dataobject.sale.ErpSaleReturnItemDO; +import cn.iocoder.yudao.module.erp.dal.dataobject.stock.ErpStockDO; +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.ErpSaleReturnService; +import cn.iocoder.yudao.module.erp.service.stock.ErpStockService; +import cn.iocoder.yudao.module.system.api.user.AdminUserApi; +import cn.iocoder.yudao.module.system.api.user.dto.AdminUserRespDTO; +import io.swagger.v3.oas.annotations.Operation; +import io.swagger.v3.oas.annotations.Parameter; +import io.swagger.v3.oas.annotations.tags.Tag; +import jakarta.annotation.Resource; +import jakarta.servlet.http.HttpServletResponse; +import jakarta.validation.Valid; +import org.springframework.security.access.prepost.PreAuthorize; +import org.springframework.validation.annotation.Validated; +import org.springframework.web.bind.annotation.*; + +import java.io.IOException; +import java.math.BigDecimal; +import java.util.List; +import java.util.Map; + +import static cn.iocoder.yudao.framework.common.pojo.CommonResult.success; +import static cn.iocoder.yudao.framework.common.util.collection.CollectionUtils.convertMultiMap; +import static cn.iocoder.yudao.framework.common.util.collection.CollectionUtils.convertSet; +import static cn.iocoder.yudao.framework.operatelog.core.enums.OperateTypeEnum.EXPORT; + +@Tag(name = "管理后台 - ERP 销售退货") +@RestController +@RequestMapping("/erp/sale-return") +@Validated +public class ErpSaleReturnController { + + @Resource + private ErpSaleReturnService saleReturnService; + @Resource + private ErpStockService stockService; + @Resource + private ErpProductService productService; + @Resource + private ErpCustomerService customerService; + + @Resource + private AdminUserApi adminUserApi; + + @PostMapping("/create") + @Operation(summary = "创建销售退货") + @PreAuthorize("@ss.hasPermission('erp:stock-return:create')") + public CommonResult createSaleReturn(@Valid @RequestBody ErpSaleReturnSaveReqVO createReqVO) { + return success(saleReturnService.createSaleReturn(createReqVO)); + } + + @PutMapping("/update") + @Operation(summary = "更新销售退货") + @PreAuthorize("@ss.hasPermission('erp:stock-return:update')") + public CommonResult updateSaleReturn(@Valid @RequestBody ErpSaleReturnSaveReqVO updateReqVO) { + saleReturnService.updateSaleReturn(updateReqVO); + return success(true); + } + + @PutMapping("/update-status") + @Operation(summary = "更新销售退货的状态") + @PreAuthorize("@ss.hasPermission('erp:stock-return:update-status')") + public CommonResult updateSaleReturnStatus(@RequestParam("id") Long id, + @RequestParam("status") Integer status) { + saleReturnService.updateSaleReturnStatus(id, status); + return success(true); + } + + @DeleteMapping("/delete") + @Operation(summary = "删除销售退货") + @Parameter(name = "ids", description = "编号数组", required = true) + @PreAuthorize("@ss.hasPermission('erp:stock-return:delete')") + public CommonResult deleteSaleReturn(@RequestParam("ids") List ids) { + saleReturnService.deleteSaleReturn(ids); + return success(true); + } + + @GetMapping("/get") + @Operation(summary = "获得销售退货") + @Parameter(name = "id", description = "编号", required = true, example = "1024") + @PreAuthorize("@ss.hasPermission('erp:stock-return:query')") + public CommonResult getSaleReturn(@RequestParam("id") Long id) { + ErpSaleReturnDO saleReturn = saleReturnService.getSaleReturn(id); + if (saleReturn == null) { + return success(null); + } + List saleReturnItemList = saleReturnService.getSaleReturnItemListByReturnId(id); + Map productMap = productService.getProductVOMap( + convertSet(saleReturnItemList, ErpSaleReturnItemDO::getProductId)); + return success(BeanUtils.toBean(saleReturn, ErpSaleReturnRespVO.class, saleReturnVO -> + saleReturnVO.setItems(BeanUtils.toBean(saleReturnItemList, ErpSaleReturnRespVO.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") + @Operation(summary = "获得销售退货分页") + @PreAuthorize("@ss.hasPermission('erp:stock-return:query')") + public CommonResult> getSaleReturnPage(@Valid ErpSaleReturnPageReqVO pageReqVO) { + PageResult pageResult = saleReturnService.getSaleReturnPage(pageReqVO); + return success(buildSaleReturnVOPageResult(pageResult)); + } + + @GetMapping("/export-excel") + @Operation(summary = "导出销售退货 Excel") + @PreAuthorize("@ss.hasPermission('erp:stock-return:export')") + @OperateLog(type = EXPORT) + public void exportSaleReturnExcel(@Valid ErpSaleReturnPageReqVO pageReqVO, + HttpServletResponse response) throws IOException { + pageReqVO.setPageSize(PageParam.PAGE_SIZE_NONE); + List list = buildSaleReturnVOPageResult(saleReturnService.getSaleReturnPage(pageReqVO)).getList(); + // 导出 Excel + ExcelUtils.write(response, "销售退货.xls", "数据", ErpSaleReturnRespVO.class, list); + } + + private PageResult buildSaleReturnVOPageResult(PageResult pageResult) { + if (CollUtil.isEmpty(pageResult.getList())) { + return PageResult.empty(pageResult.getTotal()); + } + // 1.1 退货项 + List saleReturnItemList = saleReturnService.getSaleReturnItemListByReturnIds( + convertSet(pageResult.getList(), ErpSaleReturnDO::getId)); + Map> saleReturnItemMap = convertMultiMap(saleReturnItemList, ErpSaleReturnItemDO::getReturnId); + // 1.2 商品信息 + Map productMap = productService.getProductVOMap( + convertSet(saleReturnItemList, ErpSaleReturnItemDO::getProductId)); + // 1.3 客户信息 + Map customerMap = customerService.getCustomerMap( + convertSet(pageResult.getList(), ErpSaleReturnDO::getCustomerId)); + // 1.4 管理员信息 + Map userMap = adminUserApi.getUserMap( + convertSet(pageResult.getList(), erpStockRecordDO -> Long.parseLong(erpStockRecordDO.getCreator()))); + // 2. 开始拼接 + return BeanUtils.toBean(pageResult, ErpSaleReturnRespVO.class, saleReturn -> { + saleReturn.setItems(BeanUtils.toBean(saleReturnItemMap.get(saleReturn.getId()), ErpSaleReturnRespVO.Item.class, + item -> MapUtils.findAndThen(productMap, item.getProductId(), product -> item.setProductName(product.getName()) + .setProductBarCode(product.getBarCode()).setProductUnitName(product.getUnitName())))); + saleReturn.setProductNames(CollUtil.join(saleReturn.getItems(), ",", ErpSaleReturnRespVO.Item::getProductName)); + MapUtils.findAndThen(customerMap, saleReturn.getCustomerId(), supplier -> saleReturn.setCustomerName(supplier.getName())); + MapUtils.findAndThen(userMap, Long.parseLong(saleReturn.getCreator()), user -> saleReturn.setCreatorName(user.getNickname())); + }); + } + +} \ No newline at end of file diff --git a/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/controller/admin/sale/vo/out/ErpSaleOutPageReqVO.java b/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/controller/admin/sale/vo/out/ErpSaleOutPageReqVO.java index 708b9cf1f..c422a6088 100644 --- a/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/controller/admin/sale/vo/out/ErpSaleOutPageReqVO.java +++ b/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/controller/admin/sale/vo/out/ErpSaleOutPageReqVO.java @@ -30,7 +30,7 @@ public class ErpSaleOutPageReqVO extends PageParam { @Schema(description = "备注", example = "你猜") private String remark; - @Schema(description = "销售状态", example = "2") + @Schema(description = "出库状态", example = "2") private Integer status; @Schema(description = "创建者") diff --git a/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/controller/admin/sale/vo/out/ErpSaleOutRespVO.java b/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/controller/admin/sale/vo/out/ErpSaleOutRespVO.java index 3f85a902a..832d34974 100644 --- a/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/controller/admin/sale/vo/out/ErpSaleOutRespVO.java +++ b/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/controller/admin/sale/vo/out/ErpSaleOutRespVO.java @@ -10,7 +10,7 @@ import java.math.BigDecimal; import java.time.LocalDateTime; import java.util.List; -@Schema(description = "管理后台 - ERP 出库出库 Response VO") +@Schema(description = "管理后台 - ERP 销售出库 Response VO") @Data @ExcelIgnoreUnannotated public class ErpSaleOutRespVO { diff --git a/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/controller/admin/sale/vo/returns/ErpSaleReturnPageReqVO.java b/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/controller/admin/sale/vo/returns/ErpSaleReturnPageReqVO.java new file mode 100644 index 000000000..db4f73f5b --- /dev/null +++ b/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/controller/admin/sale/vo/returns/ErpSaleReturnPageReqVO.java @@ -0,0 +1,51 @@ +package cn.iocoder.yudao.module.erp.controller.admin.sale.vo.returns; + +import cn.iocoder.yudao.framework.common.pojo.PageParam; +import io.swagger.v3.oas.annotations.media.Schema; +import lombok.Data; +import lombok.EqualsAndHashCode; +import lombok.ToString; +import org.springframework.format.annotation.DateTimeFormat; + +import java.time.LocalDateTime; + +import static cn.iocoder.yudao.framework.common.util.date.DateUtils.FORMAT_YEAR_MONTH_DAY_HOUR_MINUTE_SECOND; + +@Schema(description = "管理后台 - ERP 销售退货分页 Request VO") +@Data +@EqualsAndHashCode(callSuper = true) +@ToString(callSuper = true) +public class ErpSaleReturnPageReqVO extends PageParam { + + @Schema(description = "销售单编号", example = "XS001") + private String no; + + @Schema(description = "客户编号", example = "1724") + private Long customerId; + + @Schema(description = "退货时间") + @DateTimeFormat(pattern = FORMAT_YEAR_MONTH_DAY_HOUR_MINUTE_SECOND) + private LocalDateTime[] returnTime; + + @Schema(description = "备注", example = "你猜") + private String remark; + + @Schema(description = "退货状态", example = "2") + private Integer status; + + @Schema(description = "创建者") + private String creator; + + @Schema(description = "产品编号", example = "1") + private Long productId; + + @Schema(description = "仓库编号", example = "1") + private Long warehouseId; + + @Schema(description = "结算账号编号", example = "1") + private Long accountId; + + @Schema(description = "销售单号", example = "1") + private String orderNo; + +} \ No newline at end of file diff --git a/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/controller/admin/sale/vo/returns/ErpSaleReturnRespVO.java b/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/controller/admin/sale/vo/returns/ErpSaleReturnRespVO.java new file mode 100644 index 000000000..1284909fe --- /dev/null +++ b/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/controller/admin/sale/vo/returns/ErpSaleReturnRespVO.java @@ -0,0 +1,152 @@ +package cn.iocoder.yudao.module.erp.controller.admin.sale.vo.returns; + +import com.alibaba.excel.annotation.ExcelIgnoreUnannotated; +import com.alibaba.excel.annotation.ExcelProperty; +import io.swagger.v3.oas.annotations.media.Schema; +import jakarta.validation.constraints.NotNull; +import lombok.Data; + +import java.math.BigDecimal; +import java.time.LocalDateTime; +import java.util.List; + +@Schema(description = "管理后台 - ERP 销售退货 Response VO") +@Data +@ExcelIgnoreUnannotated +public class ErpSaleReturnRespVO { + + @Schema(description = "编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "17386") + @ExcelProperty("编号") + private Long id; + + @Schema(description = "退货单编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "XS001") + @ExcelProperty("退货单编号") + private String no; + + @Schema(description = "退货状态", requiredMode = Schema.RequiredMode.REQUIRED, example = "2") + @ExcelProperty("退货状态") + private Integer status; + + @Schema(description = "客户编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "1724") + private Long customerId; + @Schema(description = "客户名称", example = "芋道") + @ExcelProperty("客户名称") + private String customerName; + + @Schema(description = "结算账户编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "311.89") + @ExcelProperty("结算账户编号") + private Long accountId; + + @Schema(description = "退货员编号", example = "1888") + private Long saleUserId; + + @Schema(description = "退货时间", requiredMode = Schema.RequiredMode.REQUIRED) + @ExcelProperty("退货时间") + private LocalDateTime outTime; + + @Schema(description = "销售订单编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "17386") + private Long orderId; + @Schema(description = "销售订单号", requiredMode = Schema.RequiredMode.REQUIRED, example = "XS001") + private String orderNo; + + @Schema(description = "合计数量", requiredMode = Schema.RequiredMode.REQUIRED, example = "15663") + @ExcelProperty("合计数量") + private BigDecimal totalCount; + @Schema(description = "最终合计价格", requiredMode = Schema.RequiredMode.REQUIRED, example = "24906") + @ExcelProperty("最终合计价格") + private BigDecimal totalPrice; + + @Schema(description = "合计产品价格,单位:元", requiredMode = Schema.RequiredMode.REQUIRED, example = "7127") + private BigDecimal totalProductPrice; + + @Schema(description = "合计税额,单位:元", requiredMode = Schema.RequiredMode.REQUIRED, example = "7127") + private BigDecimal totalTaxPrice; + + @Schema(description = "优惠率,百分比", requiredMode = Schema.RequiredMode.REQUIRED, example = "99.88") + private BigDecimal discountPercent; + + @Schema(description = "优惠金额,单位:元", requiredMode = Schema.RequiredMode.REQUIRED, example = "7127") + private BigDecimal discountPrice; + + @Schema(description = "定金金额,单位:元", requiredMode = Schema.RequiredMode.REQUIRED, example = "7127") + private BigDecimal otherPrice; + + @Schema(description = "本次退款,单位:元", requiredMode = Schema.RequiredMode.REQUIRED, example = "7127") + private BigDecimal refundPrice; + @Schema(description = "本次欠款,单位:元", requiredMode = Schema.RequiredMode.REQUIRED, example = "666") + private BigDecimal debtPrice; + + + @Schema(description = "附件地址", example = "https://www.iocoder.cn") + @ExcelProperty("附件地址") + private String fileUrl; + + @Schema(description = "备注", example = "你猜") + @ExcelProperty("备注") + private String remark; + + @Schema(description = "审核人", example = "芋道") + private String creator; + @Schema(description = "审核人名称", example = "芋道") + private String creatorName; + + @Schema(description = "创建时间", requiredMode = Schema.RequiredMode.REQUIRED) + @ExcelProperty("创建时间") + private LocalDateTime createTime; + + @Schema(description = "退货项列表", requiredMode = Schema.RequiredMode.REQUIRED) + private List items; + + @Schema(description = "产品信息", requiredMode = Schema.RequiredMode.REQUIRED) + @ExcelProperty("产品信息") + private String productNames; + + @Data + public static class Item { + + @Schema(description = "退货项编号", example = "11756") + private Long id; + + @Schema(description = "销售订单项编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "11756") + private Long orderItemId; + + @Schema(description = "仓库编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "3113") + private Long warehouseId; + + @Schema(description = "产品编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "3113") + private Long productId; + + @Schema(description = "产品单位单位", requiredMode = Schema.RequiredMode.REQUIRED, example = "3113") + private Long productUnitId; + + @Schema(description = "产品单价", example = "100.00") + private BigDecimal productPrice; + + @Schema(description = "产品数量", requiredMode = Schema.RequiredMode.REQUIRED, example = "100.00") + @NotNull(message = "产品数量不能为空") + private BigDecimal count; + + @Schema(description = "税率,百分比", example = "99.88") + private BigDecimal taxPercent; + + @Schema(description = "税额,单位:元", example = "100.00") + private BigDecimal taxPrice; + + @Schema(description = "备注", example = "随便") + private String remark; + + // ========== 关联字段 ========== + + @Schema(description = "产品名称", requiredMode = Schema.RequiredMode.REQUIRED, example = "巧克力") + private String productName; + @Schema(description = "产品条码", requiredMode = Schema.RequiredMode.REQUIRED, example = "A9985") + private String productBarCode; + @Schema(description = "产品单位名称", requiredMode = Schema.RequiredMode.REQUIRED, example = "盒") + private String productUnitName; + + @Schema(description = "库存数量", requiredMode = Schema.RequiredMode.REQUIRED, example = "100.00") + private BigDecimal stockCount; // 该字段仅仅在“详情”和“编辑”时使用 + + } + +} \ No newline at end of file diff --git a/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/controller/admin/sale/vo/returns/ErpSaleReturnSaveReqVO.java b/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/controller/admin/sale/vo/returns/ErpSaleReturnSaveReqVO.java new file mode 100644 index 000000000..837a4b509 --- /dev/null +++ b/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/controller/admin/sale/vo/returns/ErpSaleReturnSaveReqVO.java @@ -0,0 +1,88 @@ +package cn.iocoder.yudao.module.erp.controller.admin.sale.vo.returns; + +import io.swagger.v3.oas.annotations.media.Schema; +import jakarta.validation.constraints.NotNull; +import lombok.Data; + +import java.math.BigDecimal; +import java.time.LocalDateTime; +import java.util.List; + +@Schema(description = "管理后台 - ERP 销售退货新增/修改 Request VO") +@Data +public class ErpSaleReturnSaveReqVO { + + @Schema(description = "编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "17386") + private Long id; + + @Schema(description = "结算账户编号", example = "31189") + private Long accountId; + + @Schema(description = "销售员编号", example = "1888") + private Long saleUserId; + + @Schema(description = "退货时间", requiredMode = Schema.RequiredMode.REQUIRED) + @NotNull(message = "退货时间不能为空") + private LocalDateTime returnTime; + + @Schema(description = "销售订单编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "17386") + @NotNull(message = "销售订单编号不能为空") + private Long orderId; + + @Schema(description = "优惠率,百分比", requiredMode = Schema.RequiredMode.REQUIRED, example = "99.88") + private BigDecimal discountPercent; + + @Schema(description = "其它金额,单位:元", example = "7127") + private BigDecimal otherPrice; + + @Schema(description = "本次退款,单位:元", requiredMode = Schema.RequiredMode.REQUIRED, example = "7127") + @NotNull(message = "本次退款不能为空") + private BigDecimal refundPrice; + + @Schema(description = "附件地址", example = "https://www.iocoder.cn") + private String fileUrl; + + @Schema(description = "备注", example = "你猜") + private String remark; + + @Schema(description = "退货清单列表") + private List items; + + @Data + public static class Item { + + @Schema(description = "退货项编号", example = "11756") + private Long id; + + @Schema(description = "销售订单项编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "11756") + @NotNull(message = "销售订单项编号不能为空") + private Long orderItemId; + + @Schema(description = "仓库编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "3113") + @NotNull(message = "仓库编号不能为空") + private Long warehouseId; + + @Schema(description = "产品编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "3113") + @NotNull(message = "产品编号不能为空") + private Long productId; + + @Schema(description = "产品单位单位", requiredMode = Schema.RequiredMode.REQUIRED, example = "3113") + @NotNull(message = "产品单位单位不能为空") + private Long productUnitId; + + @Schema(description = "产品单价", example = "100.00") + private BigDecimal productPrice; + + @Schema(description = "产品数量", requiredMode = Schema.RequiredMode.REQUIRED, example = "100.00") + @NotNull(message = "产品数量不能为空") + private BigDecimal count; + + @Schema(description = "税率,百分比", example = "99.88") + private BigDecimal taxPercent; + + @Schema(description = "备注", example = "随便") + private String remark; + + } + +} \ No newline at end of file diff --git a/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/dal/dataobject/sale/ErpSaleReturnDO.java b/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/dal/dataobject/sale/ErpSaleReturnDO.java new file mode 100644 index 000000000..2ee54363c --- /dev/null +++ b/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/dal/dataobject/sale/ErpSaleReturnDO.java @@ -0,0 +1,133 @@ +package cn.iocoder.yudao.module.erp.dal.dataobject.sale; + +import cn.iocoder.yudao.framework.mybatis.core.dataobject.BaseDO; +import cn.iocoder.yudao.module.erp.dal.dataobject.finance.ErpAccountDO; +import com.baomidou.mybatisplus.annotation.KeySequence; +import com.baomidou.mybatisplus.annotation.TableId; +import com.baomidou.mybatisplus.annotation.TableName; +import lombok.*; + +import java.math.BigDecimal; +import java.time.LocalDateTime; + +/** + * ERP 销售退货 DO + * + * @author 芋道源码 + */ +@TableName(value = "erp_sale_return") +@KeySequence("erp_sale_return_seq") // 用于 Oracle、PostgreSQL、Kingbase、DB2、H2 数据库的主键自增。如果是 MySQL 等数据库,可不写。 +@Data +@EqualsAndHashCode(callSuper = true) +@ToString(callSuper = true) +@Builder +@NoArgsConstructor +@AllArgsConstructor +public class ErpSaleReturnDO extends BaseDO { + + /** + * 编号 + */ + @TableId + private Long id; + /** + * 销售退货单号 + */ + private String no; + /** + * 退货状态 + * + * 枚举 {@link cn.iocoder.yudao.module.erp.enums.ErpAuditStatus} + */ + private Integer status; + /** + * 客户编号 + * + * 关联 {@link ErpCustomerDO#getId()} + */ + private Long customerId; + /** + * 结算账户编号 + * + * 关联 {@link ErpAccountDO#getId()} + */ + private Long accountId; + /** + * 销售员编号 + * + * 关联 AdminUserDO 的 id 字段 + */ + private Long saleUserId; + /** + * 退货时间 + */ + private LocalDateTime returnTime; + + /** + * 销售订单编号 + * + * 关联 {@link ErpSaleOrderDO#getId()} + */ + private Long orderId; + /** + * 销售订单号 + * + * 冗余 {@link ErpSaleOrderDO#getNo()} + */ + private String orderNo; + + /** + * 合计数量 + */ + private BigDecimal totalCount; + /** + * 最终合计价格,单位:元 + * + * totalPrice = totalProductPrice + totalTaxPrice - discountPrice + */ + private BigDecimal totalPrice; + + /** + * 合计产品价格,单位:元 + */ + private BigDecimal totalProductPrice; + /** + * 合计税额,单位:元 + */ + private BigDecimal totalTaxPrice; + /** + * 优惠率,百分比 + */ + private BigDecimal discountPercent; + /** + * 优惠金额,单位:元 + * + * discountPrice = (totalProductPrice + totalTaxPrice) * discountPercent + */ + private BigDecimal discountPrice; + /** + * 其它金额,单位:元 + */ + private BigDecimal otherPrice; + + /** + * 本次收款,单位:元 + * + * refundPrice = totalPrice + otherPrice - debtPrice + */ + private BigDecimal refundPrice; + /** + * 本次欠款,单位:元 + */ + private BigDecimal debtPrice; + + /** + * 附件地址 + */ + private String fileUrl; + /** + * 备注 + */ + private String remark; + +} \ No newline at end of file diff --git a/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/dal/dataobject/sale/ErpSaleReturnItemDO.java b/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/dal/dataobject/sale/ErpSaleReturnItemDO.java new file mode 100644 index 000000000..8851d157c --- /dev/null +++ b/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/dal/dataobject/sale/ErpSaleReturnItemDO.java @@ -0,0 +1,95 @@ +package cn.iocoder.yudao.module.erp.dal.dataobject.sale; + +import cn.iocoder.yudao.framework.mybatis.core.dataobject.BaseDO; +import cn.iocoder.yudao.module.erp.dal.dataobject.product.ErpProductDO; +import cn.iocoder.yudao.module.erp.dal.dataobject.stock.ErpWarehouseDO; +import com.baomidou.mybatisplus.annotation.KeySequence; +import com.baomidou.mybatisplus.annotation.TableId; +import com.baomidou.mybatisplus.annotation.TableName; +import lombok.*; + +import java.math.BigDecimal; + +/** + * ERP 销售退货项 DO + * + * @author 芋道源码 + */ +@TableName("erp_sale_return_items") +@KeySequence("erp_sale_return_items_seq") // 用于 Oracle、PostgreSQL、Kingbase、DB2、H2 数据库的主键自增。如果是 MySQL 等数据库,可不写。 +@Data +@EqualsAndHashCode(callSuper = true) +@ToString(callSuper = true) +@Builder +@NoArgsConstructor +@AllArgsConstructor +public class ErpSaleReturnItemDO extends BaseDO { + + /** + * 编号 + */ + @TableId + private Long id; + /** + * 销售退货编号 + * + * 关联 {@link ErpSaleReturnDO##getId()} + */ + private Long returnId; + /** + * 销售订单项编号 + * + * 关联 {@link ErpSaleOrderItemDO#getId()} + * 目的:方便更新关联的销售订单项的退货数量 + */ + private Long orderItemId; + /** + * 仓库编号 + * + * 关联 {@link ErpWarehouseDO#getId()} + */ + private Long warehouseId; + /** + * 产品编号 + * + * 关联 {@link ErpProductDO#getId()} + */ + private Long productId; + /** + * 产品单位单位 + * + * 冗余 {@link ErpProductDO#getUnitId()} + */ + private Long productUnitId; + + /** + * 产品单位单价,单位:元 + */ + private BigDecimal productPrice; + /** + * 数量 + */ + private BigDecimal count; + /** + * 总价,单位:元 + * + * totalPrice = productPrice * count + */ + private BigDecimal totalPrice; + /** + * 税率,百分比 + */ + private BigDecimal taxPercent; + /** + * 税额,单位:元 + * + * taxPrice = totalPrice * taxPercent + */ + private BigDecimal taxPrice; + + /** + * 备注 + */ + private String remark; + +} \ No newline at end of file diff --git a/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/dal/mysql/sale/ErpSaleOutItemMapper.java b/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/dal/mysql/sale/ErpSaleOutItemMapper.java index b5fab517c..9cd5dede0 100644 --- a/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/dal/mysql/sale/ErpSaleOutItemMapper.java +++ b/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/dal/mysql/sale/ErpSaleOutItemMapper.java @@ -22,16 +22,16 @@ import static cn.iocoder.yudao.framework.common.util.collection.CollectionUtils. @Mapper public interface ErpSaleOutItemMapper extends BaseMapperX { - default List selectListByOutId(Long orderId) { - return selectList(ErpSaleOutItemDO::getOutId, orderId); + default List selectListByOutId(Long outId) { + return selectList(ErpSaleOutItemDO::getOutId, outId); } - default List selectListByOutIds(Collection orderIds) { - return selectList(ErpSaleOutItemDO::getOutId, orderIds); + default List selectListByOutIds(Collection outIds) { + return selectList(ErpSaleOutItemDO::getOutId, outIds); } - default int deleteByOutId(Long orderId) { - return delete(ErpSaleOutItemDO::getOutId, orderId); + default int deleteByOutId(Long outId) { + return delete(ErpSaleOutItemDO::getOutId, outId); } /** diff --git a/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/dal/mysql/sale/ErpSaleReturnItemMapper.java b/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/dal/mysql/sale/ErpSaleReturnItemMapper.java new file mode 100644 index 000000000..771a0e904 --- /dev/null +++ b/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/dal/mysql/sale/ErpSaleReturnItemMapper.java @@ -0,0 +1,56 @@ +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.ErpSaleReturnItemDO; +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 + * + * @author 芋道源码 + */ +@Mapper +public interface ErpSaleReturnItemMapper extends BaseMapperX { + + default List selectListByReturnId(Long returnId) { + return selectList(ErpSaleReturnItemDO::getReturnId, returnId); + } + + default List selectListByReturnIds(Collection returnIds) { + return selectList(ErpSaleReturnItemDO::getReturnId, returnIds); + } + + default int deleteByReturnId(Long returnId) { + return delete(ErpSaleReturnItemDO::getReturnId, returnId); + } + + /** + * 基于销售订单编号,查询每个销售订单项的出库数量之和 + * + * @param returnIds 出库订单项编号数组 + * @return key:销售订单项编号;value:出库数量之和 + */ + default Map selectOrderItemCountSumMapByReturnIds(Collection returnIds) { + if (CollUtil.isEmpty(returnIds)) { + return Collections.emptyMap(); + } + // SQL sum 查询 + List> result = selectMaps(new QueryWrapper() + .select("order_item_id, SUM(count) AS sumCount") + .groupBy("order_item_id") + .in("return_id", returnIds)); + // 获得数量 + return convertMap(result, obj -> (Long) obj.get("order_item_id"), obj -> (BigDecimal) obj.get("sumCount")); + } + +} \ No newline at end of file diff --git a/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/dal/mysql/sale/ErpSaleReturnMapper.java b/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/dal/mysql/sale/ErpSaleReturnMapper.java new file mode 100644 index 000000000..2ca45900c --- /dev/null +++ b/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/dal/mysql/sale/ErpSaleReturnMapper.java @@ -0,0 +1,56 @@ +package cn.iocoder.yudao.module.erp.dal.mysql.sale; + + +import cn.iocoder.yudao.framework.common.pojo.PageResult; +import cn.iocoder.yudao.framework.mybatis.core.mapper.BaseMapperX; +import cn.iocoder.yudao.framework.mybatis.core.query.MPJLambdaWrapperX; +import cn.iocoder.yudao.module.erp.controller.admin.sale.vo.returns.ErpSaleReturnPageReqVO; +import cn.iocoder.yudao.module.erp.dal.dataobject.sale.ErpSaleReturnDO; +import cn.iocoder.yudao.module.erp.dal.dataobject.sale.ErpSaleReturnItemDO; +import com.baomidou.mybatisplus.core.conditions.update.LambdaUpdateWrapper; +import org.apache.ibatis.annotations.Mapper; + +import java.util.List; + +/** + * ERP 销售退货 Mapper + * + * @author 芋道源码 + */ +@Mapper +public interface ErpSaleReturnMapper extends BaseMapperX { + + default PageResult selectPage(ErpSaleReturnPageReqVO reqVO) { + MPJLambdaWrapperX query = new MPJLambdaWrapperX() + .likeIfPresent(ErpSaleReturnDO::getNo, reqVO.getNo()) + .eqIfPresent(ErpSaleReturnDO::getCustomerId, reqVO.getCustomerId()) + .betweenIfPresent(ErpSaleReturnDO::getReturnTime, reqVO.getReturnTime()) + .eqIfPresent(ErpSaleReturnDO::getStatus, reqVO.getStatus()) + .likeIfPresent(ErpSaleReturnDO::getRemark, reqVO.getRemark()) + .eqIfPresent(ErpSaleReturnDO::getCreator, reqVO.getCreator()) + .eqIfPresent(ErpSaleReturnDO::getAccountId, reqVO.getAccountId()) + .likeIfPresent(ErpSaleReturnDO::getOrderNo, reqVO.getOrderNo()) + .orderByDesc(ErpSaleReturnDO::getId); + if (reqVO.getWarehouseId() != null || reqVO.getProductId() != null) { + query.leftJoin(ErpSaleReturnItemDO.class, ErpSaleReturnItemDO::getReturnId, ErpSaleReturnDO::getId) + .eq(reqVO.getWarehouseId() != null, ErpSaleReturnItemDO::getWarehouseId, reqVO.getWarehouseId()) + .eq(reqVO.getProductId() != null, ErpSaleReturnItemDO::getProductId, reqVO.getProductId()) + .groupBy(ErpSaleReturnDO::getId); // 避免 1 对多查询,产生相同的 1 + } + return selectJoinPage(reqVO, ErpSaleReturnDO.class, query); + } + + default int updateByIdAndStatus(Long id, Integer status, ErpSaleReturnDO updateObj) { + return update(updateObj, new LambdaUpdateWrapper() + .eq(ErpSaleReturnDO::getId, id).eq(ErpSaleReturnDO::getStatus, status)); + } + + default ErpSaleReturnDO selectByNo(String no) { + return selectOne(ErpSaleReturnDO::getNo, no); + } + + default List selectListByOrderId(Long orderId) { + return selectList(ErpSaleReturnDO::getOrderId, orderId); + } + +} \ No newline at end of file diff --git a/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/dal/redis/no/ErpNoRedisDAO.java b/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/dal/redis/no/ErpNoRedisDAO.java index 7e88beb6d..192d99bcf 100644 --- a/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/dal/redis/no/ErpNoRedisDAO.java +++ b/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/dal/redis/no/ErpNoRedisDAO.java @@ -46,6 +46,10 @@ public class ErpNoRedisDAO { * 销售出库 {@link cn.iocoder.yudao.module.erp.dal.dataobject.sale.ErpSaleOutDO} */ public static final String SALE_OUT_NO_PREFIX = "XSCK"; + /** + * 销售退货 {@link cn.iocoder.yudao.module.erp.dal.dataobject.sale.ErpSaleReturnDO} + */ + public static final String SALE_RETURN_NO_PREFIX = "XSTH"; @Resource private StringRedisTemplate stringRedisTemplate; diff --git a/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/service/sale/ErpSaleOrderService.java b/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/service/sale/ErpSaleOrderService.java index 0a204b315..c75f201f3 100644 --- a/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/service/sale/ErpSaleOrderService.java +++ b/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/service/sale/ErpSaleOrderService.java @@ -46,9 +46,17 @@ public interface ErpSaleOrderService { * 更新销售订单的出库数量 * * @param id 编号 - * @param returnCountMap 出库数量 Map:key 销售订单项编号;value 出库数量 + * @param outCountMap 出库数量 Map:key 销售订单项编号;value 出库数量 */ - void updateSaleOrderOutCount(Long id, Map returnCountMap); + void updateSaleOrderOutCount(Long id, Map outCountMap); + + /** + * 更新销售订单的退货数量 + * + * @param orderId 编号 + * @param returnCountMap 退货数量 Map:key 销售订单项编号;value 退货数量 + */ + void updateSaleOrderReturnCount(Long orderId, Map returnCountMap); /** * 删除销售订单 diff --git a/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/service/sale/ErpSaleOrderServiceImpl.java b/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/service/sale/ErpSaleOrderServiceImpl.java index fff5add14..c19d8be57 100644 --- a/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/service/sale/ErpSaleOrderServiceImpl.java +++ b/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/service/sale/ErpSaleOrderServiceImpl.java @@ -149,7 +149,10 @@ public class ErpSaleOrderServiceImpl implements ErpSaleOrderService { if (!approve && saleOrder.getOutCount().compareTo(BigDecimal.ZERO) > 0) { throw exception(SALE_ORDER_PROCESS_FAIL_EXISTS_OUT); } - // TODO @芋艿:需要校验是不是有有退货 + // 1.4 存在销售退货单,无法反审核 + if (!approve && saleOrder.getReturnCount().compareTo(BigDecimal.ZERO) > 0) { + throw exception(SALE_ORDER_PROCESS_FAIL_EXISTS_RETURN); + } // 2. 更新状态 int updateCount = saleOrderMapper.updateByIdAndStatus(id, saleOrder.getStatus(), @@ -159,26 +162,6 @@ public class ErpSaleOrderServiceImpl implements ErpSaleOrderService { } } - @Override - public void updateSaleOrderOutCount(Long id, Map returnCountMap) { - List 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 validateSaleOrderItems(List list) { // 1. 校验产品存在 List productList = productService.validProductList( @@ -218,6 +201,46 @@ public class ErpSaleOrderServiceImpl implements ErpSaleOrderService { } } + @Override + public void updateSaleOrderOutCount(Long id, Map outCountMap) { + List orderItems = saleOrderItemMapper.selectListByOrderId(id); + // 1. 更新每个销售订单项 + orderItems.forEach(item -> { + BigDecimal outCount = outCountMap.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(outCountMap.values(), value -> value, BigDecimal::add, BigDecimal.ZERO); + saleOrderMapper.updateById(new ErpSaleOrderDO().setId(id).setOutCount(totalOutCount)); + } + + @Override + public void updateSaleOrderReturnCount(Long orderId, Map returnCountMap) { + List orderItems = saleOrderItemMapper.selectListByOrderId(orderId); + // 1. 更新每个销售订单项 + orderItems.forEach(item -> { + BigDecimal returnCount = returnCountMap.getOrDefault(item.getId(), BigDecimal.ZERO); + if (item.getReturnCount().equals(returnCount)) { + return; + } + if (returnCount.compareTo(item.getOutCount()) > 0) { + throw exception(SALE_ORDER_ITEM_RETURN_FAIL_OUT_EXCEED, + productService.getProduct(item.getProductId()).getName(), item.getOutCount()); + } + saleOrderItemMapper.updateById(new ErpSaleOrderItemDO().setId(item.getId()).setReturnCount(returnCount)); + }); + // 2. 更新销售订单 + BigDecimal totalReturnCount = getSumValue(returnCountMap.values(), value -> value, BigDecimal::add, BigDecimal.ZERO); + saleOrderMapper.updateById(new ErpSaleOrderDO().setId(orderId).setReturnCount(totalReturnCount)); + } + @Override @Transactional(rollbackFor = Exception.class) public void deleteSaleOrder(List ids) { diff --git a/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/service/sale/ErpSaleOutServiceImpl.java b/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/service/sale/ErpSaleOutServiceImpl.java index f0943d407..db5dcca71 100644 --- a/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/service/sale/ErpSaleOutServiceImpl.java +++ b/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/service/sale/ErpSaleOutServiceImpl.java @@ -40,7 +40,7 @@ import static cn.iocoder.yudao.module.erp.enums.ErrorCodeConstants.*; // TODO 芋艿:记录操作日志 /** - * ERP 销售订单 Service 实现类 + * ERP 销售出库 Service 实现类 * * @author 芋道源码 */ @@ -74,7 +74,7 @@ public class ErpSaleOutServiceImpl implements ErpSaleOutService { public Long createSaleOut(ErpSaleOutSaveReqVO createReqVO) { // 1.1 校验销售订单已审核 ErpSaleOrderDO saleOrder = saleOrderService.validateSaleOrder(createReqVO.getOrderId()); - // 1.2 校验订单项的有效性 + // 1.2 校验出库项的有效性 List saleOutItems = validateSaleOutItems(createReqVO.getItems()); // 1.3 校验结算账户 accountService.validateAccount(createReqVO.getAccountId()); @@ -88,13 +88,13 @@ public class ErpSaleOutServiceImpl implements ErpSaleOutService { throw exception(SALE_OUT_NO_EXISTS); } - // 2.1 插入订单 + // 2.1 插入出库 ErpSaleOutDO saleOut = BeanUtils.toBean(createReqVO, ErpSaleOutDO.class, in -> in .setNo(no).setStatus(ErpAuditStatus.PROCESS.getStatus())) .setOrderNo(saleOrder.getNo()).setCustomerId(saleOrder.getCustomerId()); calculateTotalPrice(saleOut, saleOutItems); saleOutMapper.insert(saleOut); - // 2.2 插入订单项 + // 2.2 插入出库项 saleOutItems.forEach(o -> o.setOutId(saleOut.getId())); saleOutItemMapper.insertBatch(saleOutItems); @@ -122,12 +122,12 @@ public class ErpSaleOutServiceImpl implements ErpSaleOutService { // 1.5 校验订单项的有效性 List saleOutItems = validateSaleOutItems(updateReqVO.getItems()); - // 2.1 更新订单 + // 2.1 更新出库 ErpSaleOutDO updateObj = BeanUtils.toBean(updateReqVO, ErpSaleOutDO.class) .setOrderNo(saleOrder.getNo()).setCustomerId(saleOrder.getCustomerId()); calculateTotalPrice(updateObj, saleOutItems); saleOutMapper.updateById(updateObj); - // 2.2 更新订单项 + // 2.2 更新出库项 updateSaleOutItemList(updateReqVO.getId(), saleOutItems); // 3.1 更新销售订单的出库数量 @@ -278,7 +278,7 @@ public class ErpSaleOutServiceImpl implements ErpSaleOutService { return saleOutMapper.selectPage(pageReqVO); } - // ==================== 订单项 ==================== + // ==================== 销售出库项 ==================== @Override public List getSaleOutItemListByOutId(Long outId) { diff --git a/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/service/sale/ErpSaleReturnService.java b/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/service/sale/ErpSaleReturnService.java new file mode 100644 index 000000000..2186bba54 --- /dev/null +++ b/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/service/sale/ErpSaleReturnService.java @@ -0,0 +1,84 @@ +package cn.iocoder.yudao.module.erp.service.sale; + +import cn.iocoder.yudao.framework.common.pojo.PageResult; +import cn.iocoder.yudao.module.erp.controller.admin.sale.vo.returns.ErpSaleReturnPageReqVO; +import cn.iocoder.yudao.module.erp.controller.admin.sale.vo.returns.ErpSaleReturnSaveReqVO; +import cn.iocoder.yudao.module.erp.dal.dataobject.sale.ErpSaleReturnDO; +import cn.iocoder.yudao.module.erp.dal.dataobject.sale.ErpSaleReturnItemDO; +import jakarta.validation.Valid; + +import java.util.Collection; +import java.util.List; + +/** + * ERP 销售退货 Service 接口 + * + * @author 芋道源码 + */ +public interface ErpSaleReturnService { + + /** + * 创建销售退货 + * + * @param createReqVO 创建信息 + * @return 编号 + */ + Long createSaleReturn(@Valid ErpSaleReturnSaveReqVO createReqVO); + + /** + * 更新销售退货 + * + * @param updateReqVO 更新信息 + */ + void updateSaleReturn(@Valid ErpSaleReturnSaveReqVO updateReqVO); + + /** + * 更新销售退货的状态 + * + * @param id 编号 + * @param status 状态 + */ + void updateSaleReturnStatus(Long id, Integer status); + + /** + * 删除销售退货 + * + * @param ids 编号数组 + */ + void deleteSaleReturn(List ids); + + /** + * 获得销售退货 + * + * @param id 编号 + * @return 销售退货 + */ + ErpSaleReturnDO getSaleReturn(Long id); + + /** + * 获得销售退货分页 + * + * @param pageReqVO 分页查询 + * @return 销售退货分页 + */ + PageResult getSaleReturnPage(ErpSaleReturnPageReqVO pageReqVO); + + // ==================== 销售退货项 ==================== + + /** + * 获得销售退货项列表 + * + * @param returnId 销售退货编号 + * @return 销售退货项列表 + */ + List getSaleReturnItemListByReturnId(Long returnId); + + /** + * 获得销售退货项 List + * + * @param returnIds 销售退货编号数组 + * @return 销售退货项 List + */ + List getSaleReturnItemListByReturnIds(Collection returnIds); + +} \ No newline at end of file diff --git a/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/service/sale/ErpSaleReturnServiceImpl.java b/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/service/sale/ErpSaleReturnServiceImpl.java new file mode 100644 index 000000000..e144e30bc --- /dev/null +++ b/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/service/sale/ErpSaleReturnServiceImpl.java @@ -0,0 +1,296 @@ +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.returns.ErpSaleReturnPageReqVO; +import cn.iocoder.yudao.module.erp.controller.admin.sale.vo.returns.ErpSaleReturnSaveReqVO; +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.ErpSaleReturnDO; +import cn.iocoder.yudao.module.erp.dal.dataobject.sale.ErpSaleReturnItemDO; +import cn.iocoder.yudao.module.erp.dal.mysql.sale.ErpSaleReturnItemMapper; +import cn.iocoder.yudao.module.erp.dal.mysql.sale.ErpSaleReturnMapper; +import cn.iocoder.yudao.module.erp.dal.redis.no.ErpNoRedisDAO; +import cn.iocoder.yudao.module.erp.enums.ErpAuditStatus; +import cn.iocoder.yudao.module.erp.enums.stock.ErpStockRecordBizTypeEnum; +import cn.iocoder.yudao.module.erp.service.finance.ErpAccountService; +import cn.iocoder.yudao.module.erp.service.product.ErpProductService; +import cn.iocoder.yudao.module.erp.service.stock.ErpStockRecordService; +import cn.iocoder.yudao.module.erp.service.stock.bo.ErpStockRecordCreateReqBO; +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; + +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.exception.util.ServiceExceptionUtil.exception; +import static cn.iocoder.yudao.framework.common.util.collection.CollectionUtils.*; +import static cn.iocoder.yudao.module.erp.enums.ErrorCodeConstants.*; + +// TODO 芋艿:记录操作日志 + +/** + * ERP 销售退货 Service 实现类 + * + * @author 芋道源码 + */ +@Service +@Validated +public class ErpSaleReturnServiceImpl implements ErpSaleReturnService { + + @Resource + private ErpSaleReturnMapper saleReturnMapper; + @Resource + private ErpSaleReturnItemMapper saleReturnItemMapper; + + @Resource + private ErpNoRedisDAO noRedisDAO; + + @Resource + private ErpProductService productService; + @Resource + @Lazy // 延迟加载,避免循环依赖 + private ErpSaleOrderService saleOrderService; + @Resource + private ErpAccountService accountService; + @Resource + private ErpStockRecordService stockRecordService; + + @Resource + private AdminUserApi adminUserApi; + + @Override + @Transactional(rollbackFor = Exception.class) + public Long createSaleReturn(ErpSaleReturnSaveReqVO createReqVO) { + // 1.1 校验销售订单已审核 + ErpSaleOrderDO saleOrder = saleOrderService.validateSaleOrder(createReqVO.getOrderId()); + // 1.2 校验退货项的有效性 + List saleReturnItems = validateSaleReturnItems(createReqVO.getItems()); + // 1.3 校验结算账户 + accountService.validateAccount(createReqVO.getAccountId()); + // 1.4 校验销售人员 + if (createReqVO.getSaleUserId() != null) { + adminUserApi.validateUser(createReqVO.getSaleUserId()); + } + // 1.5 生成调拨单号,并校验唯一性 + String no = noRedisDAO.generate(ErpNoRedisDAO.SALE_RETURN_NO_PREFIX); + if (saleReturnMapper.selectByNo(no) != null) { + throw exception(SALE_RETURN_NO_EXISTS); + } + + // 2.1 插入退货 + ErpSaleReturnDO saleReturn = BeanUtils.toBean(createReqVO, ErpSaleReturnDO.class, in -> in + .setNo(no).setStatus(ErpAuditStatus.PROCESS.getStatus())) + .setOrderNo(saleOrder.getNo()).setCustomerId(saleOrder.getCustomerId()); + calculateTotalPrice(saleReturn, saleReturnItems); + saleReturnMapper.insert(saleReturn); + // 2.2 插入退货项 + saleReturnItems.forEach(o -> o.setReturnId(saleReturn.getId())); + saleReturnItemMapper.insertBatch(saleReturnItems); + + // 3. 更新销售订单的退货数量 + updateSaleOrderReturnCount(createReqVO.getOrderId()); + return saleReturn.getId(); + } + + @Override + @Transactional(rollbackFor = Exception.class) + public void updateSaleReturn(ErpSaleReturnSaveReqVO updateReqVO) { + // 1.1 校验存在 + ErpSaleReturnDO saleReturn = validateSaleReturnExists(updateReqVO.getId()); + if (ErpAuditStatus.APPROVE.getStatus().equals(saleReturn.getStatus())) { + throw exception(SALE_RETURN_UPDATE_FAIL_APPROVE, saleReturn.getNo()); + } + // 1.2 校验销售订单已审核 + ErpSaleOrderDO saleOrder = saleOrderService.validateSaleOrder(updateReqVO.getOrderId()); + // 1.3 校验结算账户 + accountService.validateAccount(updateReqVO.getAccountId()); + // 1.4 校验销售人员 + if (updateReqVO.getSaleUserId() != null) { + adminUserApi.validateUser(updateReqVO.getSaleUserId()); + } + // 1.5 校验订单项的有效性 + List saleReturnItems = validateSaleReturnItems(updateReqVO.getItems()); + + // 2.1 更新退货 + ErpSaleReturnDO updateObj = BeanUtils.toBean(updateReqVO, ErpSaleReturnDO.class) + .setOrderNo(saleOrder.getNo()).setCustomerId(saleOrder.getCustomerId()); + calculateTotalPrice(updateObj, saleReturnItems); + saleReturnMapper.updateById(updateObj); + // 2.2 更新退货项 + updateSaleReturnItemList(updateReqVO.getId(), saleReturnItems); + + // 3.1 更新销售订单的出库数量 + updateSaleOrderReturnCount(updateObj.getOrderId()); + // 3.2 注意:如果销售订单编号变更了,需要更新“老”销售订单的出库数量 + if (ObjectUtil.notEqual(saleReturn.getOrderId(), updateObj.getOrderId())) { + updateSaleOrderReturnCount(saleReturn.getOrderId()); + } + } + + private void calculateTotalPrice(ErpSaleReturnDO saleReturn, List saleReturnItems) { + saleReturn.setTotalCount(getSumValue(saleReturnItems, ErpSaleReturnItemDO::getCount, BigDecimal::add)); + saleReturn.setTotalProductPrice(getSumValue(saleReturnItems, ErpSaleReturnItemDO::getTotalPrice, BigDecimal::add, BigDecimal.ZERO)); + saleReturn.setTotalTaxPrice(getSumValue(saleReturnItems, ErpSaleReturnItemDO::getTaxPrice, BigDecimal::add, BigDecimal.ZERO)); + saleReturn.setTotalPrice(saleReturn.getTotalProductPrice().add(saleReturn.getTotalTaxPrice())); + // 计算优惠价格 + if (saleReturn.getDiscountPercent() == null) { + saleReturn.setDiscountPercent(BigDecimal.ZERO); + } + saleReturn.setDiscountPrice(MoneyUtils.priceMultiplyPercent(saleReturn.getTotalPrice(), saleReturn.getDiscountPercent())); + saleReturn.setTotalPrice(saleReturn.getTotalPrice().subtract(saleReturn.getDiscountPrice())); + // 计算应退金额 + BigDecimal allPrice = saleReturn.getTotalPrice().add(saleReturn.getOtherPrice()); + saleReturn.setDebtPrice(allPrice.subtract(saleReturn.getRefundPrice())); + } + + private void updateSaleOrderReturnCount(Long orderId) { + // 1.1 查询销售订单对应的销售出库单列表 + List saleReturns = saleReturnMapper.selectListByOrderId(orderId); + // 1.2 查询对应的销售订单项的出库数量 + Map returnCountMap = saleReturnItemMapper.selectOrderItemCountSumMapByReturnIds( + convertList(saleReturns, ErpSaleReturnDO::getId)); + // 2. 更新销售订单的出库数量 + saleOrderService.updateSaleOrderReturnCount(orderId, returnCountMap); + } + + @Override + @Transactional(rollbackFor = Exception.class) + public void updateSaleReturnStatus(Long id, Integer status) { + boolean approve = ErpAuditStatus.APPROVE.getStatus().equals(status); + // 1.1 校验存在 + ErpSaleReturnDO saleReturn = validateSaleReturnExists(id); + // 1.2 校验状态 + if (saleReturn.getStatus().equals(status)) { + throw exception(approve ? SALE_RETURN_APPROVE_FAIL : SALE_RETURN_PROCESS_FAIL); + } + + // 2. 更新状态 + int updateCount = saleReturnMapper.updateByIdAndStatus(id, saleReturn.getStatus(), + new ErpSaleReturnDO().setStatus(status)); + if (updateCount == 0) { + throw exception(approve ? SALE_RETURN_APPROVE_FAIL : SALE_RETURN_PROCESS_FAIL); + } + + // 3. 变更库存 + List saleReturnItems = saleReturnItemMapper.selectListByReturnId(id); + Integer bizType = approve ? ErpStockRecordBizTypeEnum.SALE_RETURN.getType() + : ErpStockRecordBizTypeEnum.SALE_RETURN_CANCEL.getType(); + saleReturnItems.forEach(saleReturnItem -> { + BigDecimal count = approve ? saleReturnItem.getCount().negate() : saleReturnItem.getCount(); + stockRecordService.createStockRecord(new ErpStockRecordCreateReqBO( + saleReturnItem.getProductId(), saleReturnItem.getWarehouseId(), count, + bizType, saleReturnItem.getReturnId(), saleReturnItem.getId(), saleReturn.getNo())); + }); + } + + private List validateSaleReturnItems(List list) { + // 1. 校验产品存在 + List productList = productService.validProductList( + convertSet(list, ErpSaleReturnSaveReqVO.Item::getProductId)); + Map productMap = convertMap(productList, ErpProductDO::getId); + // 2. 转化为 ErpSaleReturnItemDO 列表 + return convertList(list, o -> BeanUtils.toBean(o, ErpSaleReturnItemDO.class, item -> { + item.setProductUnitId(productMap.get(item.getProductId()).getUnitId()); + item.setTotalPrice(MoneyUtils.priceMultiply(item.getProductPrice(), item.getCount())); + if (item.getTotalPrice() == null) { + return; + } + if (item.getTaxPercent() == null) { + item.setTaxPercent(BigDecimal.ZERO); + } else { + item.setTaxPrice(MoneyUtils.priceMultiplyPercent(item.getTotalPrice(), item.getTaxPercent())); + } + })); + } + + private void updateSaleReturnItemList(Long id, List newList) { + // 第一步,对比新老数据,获得添加、修改、删除的列表 + List oldList = saleReturnItemMapper.selectListByReturnId(id); + List> diffList = diffList(oldList, newList, // id 不同,就认为是不同的记录 + (oldVal, newVal) -> oldVal.getId().equals(newVal.getId())); + + // 第二步,批量添加、修改、删除 + if (CollUtil.isNotEmpty(diffList.get(0))) { + diffList.get(0).forEach(o -> o.setReturnId(id)); + saleReturnItemMapper.insertBatch(diffList.get(0)); + } + if (CollUtil.isNotEmpty(diffList.get(1))) { + saleReturnItemMapper.updateBatch(diffList.get(1)); + } + if (CollUtil.isNotEmpty(diffList.get(2))) { + saleReturnItemMapper.deleteBatchIds(convertList(diffList.get(2), ErpSaleReturnItemDO::getId)); + } + } + + @Override + @Transactional(rollbackFor = Exception.class) + public void deleteSaleReturn(List ids) { + // 1. 校验不处于已审批 + List saleReturns = saleReturnMapper.selectBatchIds(ids); + if (CollUtil.isEmpty(saleReturns)) { + return; + } + saleReturns.forEach(saleReturn -> { + if (ErpAuditStatus.APPROVE.getStatus().equals(saleReturn.getStatus())) { + throw exception(SALE_RETURN_DELETE_FAIL_APPROVE, saleReturn.getNo()); + } + }); + + // 2. 遍历删除,并记录操作日志 + saleReturns.forEach(saleReturn -> { + // 2.1 删除订单 + saleReturnMapper.deleteById(saleReturn.getId()); + // 2.2 删除订单项 + saleReturnItemMapper.deleteByReturnId(saleReturn.getId()); + + // 2.3 更新销售订单的出库数量 + updateSaleOrderReturnCount(saleReturn.getOrderId()); + }); + + } + + private ErpSaleReturnDO validateSaleReturnExists(Long id) { + ErpSaleReturnDO saleReturn = saleReturnMapper.selectById(id); + if (saleReturn == null) { + throw exception(SALE_RETURN_NOT_EXISTS); + } + return saleReturn; + } + + @Override + public ErpSaleReturnDO getSaleReturn(Long id) { + return saleReturnMapper.selectById(id); + } + + @Override + public PageResult getSaleReturnPage(ErpSaleReturnPageReqVO pageReqVO) { + return saleReturnMapper.selectPage(pageReqVO); + } + + // ==================== 销售退货项 ==================== + + @Override + public List getSaleReturnItemListByReturnId(Long returnId) { + return saleReturnItemMapper.selectListByReturnId(returnId); + } + + @Override + public List getSaleReturnItemListByReturnIds(Collection returnIds) { + if (CollUtil.isEmpty(returnIds)) { + return Collections.emptyList(); + } + return saleReturnItemMapper.selectListByReturnIds(returnIds); + } + +} \ No newline at end of file From 798b72778ef1af60745fc8f1416f38d30934f694 Mon Sep 17 00:00:00 2001 From: YunaiV Date: Mon, 12 Feb 2024 06:52:20 +0800 Subject: [PATCH 100/119] =?UTF-8?q?=E2=9C=A8=20ERP=EF=BC=9A=E5=88=9D?= =?UTF-8?q?=E5=A7=8B=E5=8C=96=E9=94=80=E5=94=AE=E9=80=80=E8=B4=A7=E9=80=BB?= =?UTF-8?q?=E8=BE=91=20100%?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../admin/sale/vo/order/ErpSaleOrderPageReqVO.java | 3 +++ .../admin/sale/vo/returns/ErpSaleReturnRespVO.java | 2 +- .../module/erp/dal/mysql/sale/ErpSaleOrderMapper.java | 7 ++++++- 3 files changed, 10 insertions(+), 2 deletions(-) diff --git a/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/controller/admin/sale/vo/order/ErpSaleOrderPageReqVO.java b/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/controller/admin/sale/vo/order/ErpSaleOrderPageReqVO.java index 13b1abd76..5d4f22f1b 100644 --- a/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/controller/admin/sale/vo/order/ErpSaleOrderPageReqVO.java +++ b/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/controller/admin/sale/vo/order/ErpSaleOrderPageReqVO.java @@ -74,4 +74,7 @@ public class ErpSaleOrderPageReqVO extends PageParam { @Schema(description = "是否可出库", example = "true") private Boolean outEnable; + @Schema(description = "是否可退货", example = "true") + private Boolean returnEnable; + } \ No newline at end of file diff --git a/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/controller/admin/sale/vo/returns/ErpSaleReturnRespVO.java b/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/controller/admin/sale/vo/returns/ErpSaleReturnRespVO.java index 1284909fe..78b94a35e 100644 --- a/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/controller/admin/sale/vo/returns/ErpSaleReturnRespVO.java +++ b/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/controller/admin/sale/vo/returns/ErpSaleReturnRespVO.java @@ -42,7 +42,7 @@ public class ErpSaleReturnRespVO { @Schema(description = "退货时间", requiredMode = Schema.RequiredMode.REQUIRED) @ExcelProperty("退货时间") - private LocalDateTime outTime; + private LocalDateTime returnTime; @Schema(description = "销售订单编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "17386") private Long orderId; diff --git a/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/dal/mysql/sale/ErpSaleOrderMapper.java b/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/dal/mysql/sale/ErpSaleOrderMapper.java index f290fb6fd..a8a31bd2a 100644 --- a/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/dal/mysql/sale/ErpSaleOrderMapper.java +++ b/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/dal/mysql/sale/ErpSaleOrderMapper.java @@ -46,11 +46,16 @@ public interface ErpSaleOrderMapper extends BaseMapperX { } else if (Objects.equals(reqVO.getReturnStatus(), ErpSaleOrderPageReqVO.RETURN_STATUS_ALL)) { query.apply("t.return_count = t.total_count"); } - // 可出库 + // 可销售出库 if (Boolean.TRUE.equals(reqVO.getOutEnable())) { query.eq(ErpSaleOrderDO::getStatus, ErpAuditStatus.APPROVE.getStatus()) .apply("t.out_count < t.total_count"); } + // 可销售退货 + if (Boolean.TRUE.equals(reqVO.getReturnEnable())) { + query.eq(ErpSaleOrderDO::getStatus, ErpAuditStatus.APPROVE.getStatus()) + .apply("t.return_count < t.out_count"); + } if (reqVO.getProductId() != null) { query.leftJoin(ErpSaleOrderItemDO.class, ErpSaleOrderItemDO::getOrderId, ErpSaleOrderDO::getId) .eq(reqVO.getProductId() != null, ErpSaleOrderItemDO::getProductId, reqVO.getProductId()) From c5d9ad59e0075d2e8397beed117c1179668b6aa6 Mon Sep 17 00:00:00 2001 From: YunaiV Date: Mon, 12 Feb 2024 08:39:43 +0800 Subject: [PATCH 101/119] =?UTF-8?q?=E2=9C=A8=20ERP=EF=BC=9A=E5=88=9D?= =?UTF-8?q?=E5=A7=8B=E5=8C=96=E9=87=87=E8=B4=AD=E8=AE=A2=E5=8D=95=2050%?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../module/erp/enums/ErrorCodeConstants.java | 13 + .../purchase/ErpPurchaseOrderController.java | 165 ++++++++++ .../vo/order/ErpPurchaseOrderPageReqVO.java | 80 +++++ .../vo/order/ErpPurchaseOrderRespVO.java | 152 +++++++++ .../vo/order/ErpPurchaseOrderSaveReqVO.java | 73 +++++ .../admin/sale/ErpSaleOrderController.java | 16 +- .../admin/sale/ErpSaleOutController.java | 16 +- .../admin/sale/ErpSaleReturnController.java | 16 +- .../sale/vo/order/ErpSaleOrderPageReqVO.java | 16 +- .../sale/vo/order/ErpSaleOrderRespVO.java | 6 +- .../admin/sale/vo/out/ErpSaleOutRespVO.java | 4 +- .../sale/vo/returns/ErpSaleReturnRespVO.java | 4 +- .../admin/stock/ErpStockCheckController.java | 2 +- .../admin/stock/ErpStockInController.java | 2 +- .../admin/stock/ErpStockMoveController.java | 2 +- .../admin/stock/ErpStockOutController.java | 2 +- .../stock/vo/check/ErpStockCheckRespVO.java | 4 +- .../admin/stock/vo/in/ErpStockInRespVO.java | 4 +- .../stock/vo/move/ErpStockMoveRespVO.java | 4 +- .../admin/stock/vo/out/ErpStockOutRespVO.java | 4 +- .../purchase/ErpPurchaseOrderDO.java | 115 +++++++ .../purchase/ErpPurchaseOrderItemDO.java | 93 ++++++ .../dal/dataobject/sale/ErpSaleOrderDO.java | 2 +- .../dataobject/sale/ErpSaleOrderItemDO.java | 2 +- .../purchase/ErpPurchaseOrderItemMapper.java | 30 ++ .../purchase/ErpPurchaseOrderMapper.java | 75 +++++ .../dal/mysql/sale/ErpSaleOrderMapper.java | 6 +- .../erp/dal/redis/no/ErpNoRedisDAO.java | 5 + .../product/ErpProductUnitServiceImpl.java | 2 +- .../purchase/ErpPurchaseOrderService.java | 110 +++++++ .../purchase/ErpPurchaseOrderServiceImpl.java | 297 ++++++++++++++++++ .../sale/ErpSaleReturnServiceImpl.java | 2 +- 32 files changed, 1266 insertions(+), 58 deletions(-) create mode 100644 yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/controller/admin/purchase/ErpPurchaseOrderController.java create mode 100644 yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/controller/admin/purchase/vo/order/ErpPurchaseOrderPageReqVO.java create mode 100644 yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/controller/admin/purchase/vo/order/ErpPurchaseOrderRespVO.java create mode 100644 yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/controller/admin/purchase/vo/order/ErpPurchaseOrderSaveReqVO.java create mode 100644 yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/dal/dataobject/purchase/ErpPurchaseOrderDO.java create mode 100644 yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/dal/dataobject/purchase/ErpPurchaseOrderItemDO.java create mode 100644 yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/dal/mysql/purchase/ErpPurchaseOrderItemMapper.java create mode 100644 yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/dal/mysql/purchase/ErpPurchaseOrderMapper.java create mode 100644 yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/service/purchase/ErpPurchaseOrderService.java create mode 100644 yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/service/purchase/ErpPurchaseOrderServiceImpl.java diff --git a/yudao-module-erp/yudao-module-erp-api/src/main/java/cn/iocoder/yudao/module/erp/enums/ErrorCodeConstants.java b/yudao-module-erp/yudao-module-erp-api/src/main/java/cn/iocoder/yudao/module/erp/enums/ErrorCodeConstants.java index 7fc4007d8..5ad887abd 100644 --- a/yudao-module-erp/yudao-module-erp-api/src/main/java/cn/iocoder/yudao/module/erp/enums/ErrorCodeConstants.java +++ b/yudao-module-erp/yudao-module-erp-api/src/main/java/cn/iocoder/yudao/module/erp/enums/ErrorCodeConstants.java @@ -13,6 +13,19 @@ public interface ErrorCodeConstants { ErrorCode SUPPLIER_NOT_EXISTS = new ErrorCode(1_030_100_000, "供应商不存在"); ErrorCode SUPPLIER_NOT_ENABLE = new ErrorCode(1_030_100_000, "供应商({})未启用"); + // ========== ERP 采购订单(1-030-101-000) ========== + ErrorCode PURCHASE_ORDER_NOT_EXISTS = new ErrorCode(1_030_101_000, "采购订单不存在"); + ErrorCode PURCHASE_ORDER_DELETE_FAIL_APPROVE = new ErrorCode(1_030_101_001, "采购订单({})已审核,无法删除"); + ErrorCode PURCHASE_ORDER_PROCESS_FAIL = new ErrorCode(1_030_101_002, "反审核失败,只有已审核的采购订单才能反审核"); + ErrorCode PURCHASE_ORDER_APPROVE_FAIL = new ErrorCode(1_030_101_003, "审核失败,只有未审核的采购订单才能审核"); + ErrorCode PURCHASE_ORDER_NO_EXISTS = new ErrorCode(1_030_101_004, "生成采购单号失败,请重新提交"); + ErrorCode PURCHASE_ORDER_UPDATE_FAIL_APPROVE = new ErrorCode(1_030_101_005, "采购订单({})已审核,无法修改"); + ErrorCode PURCHASE_ORDER_NOT_APPROVE = new ErrorCode(1_030_101_006, "采购订单未审核,无法操作"); + ErrorCode PURCHASE_ORDER_ITEM_IN_FAIL_PRODUCT_EXCEED = new ErrorCode(1_030_101_007, "采购订单项({})超过最大允许入库数量({})"); + ErrorCode PURCHASE_ORDER_PROCESS_FAIL_EXISTS_IN = new ErrorCode(1_030_101_008, "反审核失败,已存在对应的采购入库单"); +ErrorCode PURCHASE_ORDER_ITEM_RETURN_FAIL_IN_EXCEED = new ErrorCode(1_030_101_009, "采购订单项({})超过最大允许退货数量({})"); + ErrorCode PURCHASE_ORDER_PROCESS_FAIL_EXISTS_RETURN = new ErrorCode(1_030_101_010, "反审核失败,已存在对应的采购退货单"); + // ========== ERP 客户(1-030-200-000)========== ErrorCode CUSTOMER_NOT_EXISTS = new ErrorCode(1_020_200_000, "客户不存在"); ErrorCode CUSTOMER_NOT_ENABLE = new ErrorCode(1_020_200_001, "客户({})未启用"); diff --git a/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/controller/admin/purchase/ErpPurchaseOrderController.java b/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/controller/admin/purchase/ErpPurchaseOrderController.java new file mode 100644 index 000000000..f7579e903 --- /dev/null +++ b/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/controller/admin/purchase/ErpPurchaseOrderController.java @@ -0,0 +1,165 @@ +package cn.iocoder.yudao.module.erp.controller.admin.purchase; + +import cn.hutool.core.collection.CollUtil; +import cn.iocoder.yudao.framework.common.pojo.CommonResult; +import cn.iocoder.yudao.framework.common.pojo.PageParam; +import cn.iocoder.yudao.framework.common.pojo.PageResult; +import cn.iocoder.yudao.framework.common.util.collection.MapUtils; +import cn.iocoder.yudao.framework.common.util.object.BeanUtils; +import cn.iocoder.yudao.framework.excel.core.util.ExcelUtils; +import cn.iocoder.yudao.framework.operatelog.core.annotations.OperateLog; +import cn.iocoder.yudao.module.erp.controller.admin.product.vo.product.ErpProductRespVO; +import cn.iocoder.yudao.module.erp.controller.admin.purchase.vo.order.ErpPurchaseOrderPageReqVO; +import cn.iocoder.yudao.module.erp.controller.admin.purchase.vo.order.ErpPurchaseOrderRespVO; +import cn.iocoder.yudao.module.erp.controller.admin.purchase.vo.order.ErpPurchaseOrderSaveReqVO; +import cn.iocoder.yudao.module.erp.dal.dataobject.purchase.ErpPurchaseOrderDO; +import cn.iocoder.yudao.module.erp.dal.dataobject.purchase.ErpPurchaseOrderItemDO; +import cn.iocoder.yudao.module.erp.dal.dataobject.purchase.ErpSupplierDO; +import cn.iocoder.yudao.module.erp.service.product.ErpProductService; +import cn.iocoder.yudao.module.erp.service.purchase.ErpPurchaseOrderService; +import cn.iocoder.yudao.module.erp.service.purchase.ErpSupplierService; +import cn.iocoder.yudao.module.erp.service.stock.ErpStockService; +import cn.iocoder.yudao.module.system.api.user.AdminUserApi; +import cn.iocoder.yudao.module.system.api.user.dto.AdminUserRespDTO; +import io.swagger.v3.oas.annotations.Operation; +import io.swagger.v3.oas.annotations.Parameter; +import io.swagger.v3.oas.annotations.tags.Tag; +import jakarta.annotation.Resource; +import jakarta.servlet.http.HttpServletResponse; +import jakarta.validation.Valid; +import org.springframework.security.access.prepost.PreAuthorize; +import org.springframework.validation.annotation.Validated; +import org.springframework.web.bind.annotation.*; + +import java.io.IOException; +import java.math.BigDecimal; +import java.util.List; +import java.util.Map; + +import static cn.iocoder.yudao.framework.common.pojo.CommonResult.success; +import static cn.iocoder.yudao.framework.common.util.collection.CollectionUtils.convertMultiMap; +import static cn.iocoder.yudao.framework.common.util.collection.CollectionUtils.convertSet; +import static cn.iocoder.yudao.framework.operatelog.core.enums.OperateTypeEnum.EXPORT; + + +@Tag(name = "管理后台 - ERP 采购订单") +@RestController +@RequestMapping("/erp/purchase-order") +@Validated +public class ErpPurchaseOrderController { + + @Resource + private ErpPurchaseOrderService purchaseOrderService; + @Resource + private ErpStockService stockService; + @Resource + private ErpProductService productService; + @Resource + private ErpSupplierService supplierService; + + @Resource + private AdminUserApi adminUserApi; + + @PostMapping("/create") + @Operation(summary = "创建采购订单") + @PreAuthorize("@ss.hasPermission('erp:purchase-out:create')") + public CommonResult createPurchaseOrder(@Valid @RequestBody ErpPurchaseOrderSaveReqVO createReqVO) { + return success(purchaseOrderService.createPurchaseOrder(createReqVO)); + } + + @PutMapping("/update") + @Operation(summary = "更新采购订单") + @PreAuthorize("@ss.hasPermission('erp:purchase-out:update')") + public CommonResult updatePurchaseOrder(@Valid @RequestBody ErpPurchaseOrderSaveReqVO updateReqVO) { + purchaseOrderService.updatePurchaseOrder(updateReqVO); + return success(true); + } + + @PutMapping("/update-status") + @Operation(summary = "更新采购订单的状态") + @PreAuthorize("@ss.hasPermission('erp:purchase-out:update-status')") + public CommonResult updatePurchaseOrderStatus(@RequestParam("id") Long id, + @RequestParam("status") Integer status) { + purchaseOrderService.updatePurchaseOrderStatus(id, status); + return success(true); + } + + @DeleteMapping("/delete") + @Operation(summary = "删除采购订单") + @Parameter(name = "ids", description = "编号数组", required = true) + @PreAuthorize("@ss.hasPermission('erp:purchase-out:delete')") + public CommonResult deletePurchaseOrder(@RequestParam("ids") List ids) { + purchaseOrderService.deletePurchaseOrder(ids); + return success(true); + } + + @GetMapping("/get") + @Operation(summary = "获得采购订单") + @Parameter(name = "id", description = "编号", required = true, example = "1024") + @PreAuthorize("@ss.hasPermission('erp:purchase-out:query')") + public CommonResult getPurchaseOrder(@RequestParam("id") Long id) { + ErpPurchaseOrderDO purchaseOrder = purchaseOrderService.getPurchaseOrder(id); + if (purchaseOrder == null) { + return success(null); + } + List purchaseOrderItemList = purchaseOrderService.getPurchaseOrderItemListByOrderId(id); + Map productMap = productService.getProductVOMap( + convertSet(purchaseOrderItemList, ErpPurchaseOrderItemDO::getProductId)); + return success(BeanUtils.toBean(purchaseOrder, ErpPurchaseOrderRespVO.class, purchaseOrderVO -> + purchaseOrderVO.setItems(BeanUtils.toBean(purchaseOrderItemList, ErpPurchaseOrderRespVO.Item.class, item -> { + BigDecimal purchaseCount = stockService.getStockCount(item.getProductId()); + item.setStockCount(purchaseCount != null ? purchaseCount : BigDecimal.ZERO); + MapUtils.findAndThen(productMap, item.getProductId(), product -> item.setProductName(product.getName()) + .setProductBarCode(product.getBarCode()).setProductUnitName(product.getUnitName())); + })))); + } + + @GetMapping("/page") + @Operation(summary = "获得采购订单分页") + @PreAuthorize("@ss.hasPermission('erp:purchase-out:query')") + public CommonResult> getPurchaseOrderPage(@Valid ErpPurchaseOrderPageReqVO pageReqVO) { + PageResult pageResult = purchaseOrderService.getPurchaseOrderPage(pageReqVO); + return success(buildPurchaseOrderVOPageResult(pageResult)); + } + + @GetMapping("/export-excel") + @Operation(summary = "导出采购订单 Excel") + @PreAuthorize("@ss.hasPermission('erp:purchase-out:export')") + @OperateLog(type = EXPORT) + public void exportPurchaseOrderExcel(@Valid ErpPurchaseOrderPageReqVO pageReqVO, + HttpServletResponse response) throws IOException { + pageReqVO.setPageSize(PageParam.PAGE_SIZE_NONE); + List list = buildPurchaseOrderVOPageResult(purchaseOrderService.getPurchaseOrderPage(pageReqVO)).getList(); + // 导出 Excel + ExcelUtils.write(response, "采购订单.xls", "数据", ErpPurchaseOrderRespVO.class, list); + } + + private PageResult buildPurchaseOrderVOPageResult(PageResult pageResult) { + if (CollUtil.isEmpty(pageResult.getList())) { + return PageResult.empty(pageResult.getTotal()); + } + // 1.1 出库项 + List purchaseOrderItemList = purchaseOrderService.getPurchaseOrderItemListByOrderIds( + convertSet(pageResult.getList(), ErpPurchaseOrderDO::getId)); + Map> purchaseOrderItemMap = convertMultiMap(purchaseOrderItemList, ErpPurchaseOrderItemDO::getOrderId); + // 1.2 产品信息 + Map productMap = productService.getProductVOMap( + convertSet(purchaseOrderItemList, ErpPurchaseOrderItemDO::getProductId)); + // 1.3 供应商信息 + Map supplierMap = supplierService.getSupplierMap( + convertSet(pageResult.getList(), ErpPurchaseOrderDO::getSupplierId)); + // 1.4 管理员信息 + Map userMap = adminUserApi.getUserMap( + convertSet(pageResult.getList(), erpStockRecordDO -> Long.parseLong(erpStockRecordDO.getCreator()))); + // 2. 开始拼接 + return BeanUtils.toBean(pageResult, ErpPurchaseOrderRespVO.class, purchaseOrder -> { + purchaseOrder.setItems(BeanUtils.toBean(purchaseOrderItemMap.get(purchaseOrder.getId()), ErpPurchaseOrderRespVO.Item.class, + item -> MapUtils.findAndThen(productMap, item.getProductId(), product -> item.setProductName(product.getName()) + .setProductBarCode(product.getBarCode()).setProductUnitName(product.getUnitName())))); + purchaseOrder.setProductNames(CollUtil.join(purchaseOrder.getItems(), ",", ErpPurchaseOrderRespVO.Item::getProductName)); + MapUtils.findAndThen(supplierMap, purchaseOrder.getSupplierId(), supplier -> purchaseOrder.setSupplierName(supplier.getName())); + MapUtils.findAndThen(userMap, Long.parseLong(purchaseOrder.getCreator()), user -> purchaseOrder.setCreatorName(user.getNickname())); + }); + } + +} \ No newline at end of file diff --git a/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/controller/admin/purchase/vo/order/ErpPurchaseOrderPageReqVO.java b/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/controller/admin/purchase/vo/order/ErpPurchaseOrderPageReqVO.java new file mode 100644 index 000000000..8bf70d427 --- /dev/null +++ b/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/controller/admin/purchase/vo/order/ErpPurchaseOrderPageReqVO.java @@ -0,0 +1,80 @@ +package cn.iocoder.yudao.module.erp.controller.admin.purchase.vo.order; + +import cn.iocoder.yudao.framework.common.pojo.PageParam; +import io.swagger.v3.oas.annotations.media.Schema; +import lombok.Data; +import lombok.EqualsAndHashCode; +import lombok.ToString; +import org.springframework.format.annotation.DateTimeFormat; + +import java.time.LocalDateTime; + +import static cn.iocoder.yudao.framework.common.util.date.DateUtils.FORMAT_YEAR_MONTH_DAY_HOUR_MINUTE_SECOND; + +@Schema(description = "管理后台 - ERP 采购订单分页 Request VO") +@Data +@EqualsAndHashCode(callSuper = true) +@ToString(callSuper = true) +public class ErpPurchaseOrderPageReqVO extends PageParam { + + /** + * 入库状态 - 无 + */ + public static final Integer IN_STATUS_NONE = 0; + /** + * 入库状态 - 部分 + */ + public static final Integer IN_STATUS_PART = 1; + /** + * 入库状态 - 全部 + */ + public static final Integer IN_STATUS_ALL = 2; + + /** + * 退货状态 - 无 + */ + public static final Integer RETURN_STATUS_NONE = 0; + /** + * 退货状态 - 部分 + */ + public static final Integer RETURN_STATUS_PART = 1; + /** + * 退货状态 - 全部 + */ + public static final Integer RETURN_STATUS_ALL = 2; + + @Schema(description = "采购单编号", example = "XS001") + private String no; + + @Schema(description = "供应商编号", example = "1724") + private Long supplierId; + + @Schema(description = "采购时间") + @DateTimeFormat(pattern = FORMAT_YEAR_MONTH_DAY_HOUR_MINUTE_SECOND) + private LocalDateTime[] orderTime; + + @Schema(description = "备注", example = "你猜") + private String remark; + + @Schema(description = "采购状态", example = "2") + private Integer status; + + @Schema(description = "创建者") + private String creator; + + @Schema(description = "产品编号", example = "1") + private Long productId; + + @Schema(description = "入库状态", example = "2") + private Integer inStatus; + + @Schema(description = "退货状态", example = "2") + private Integer returnStatus; + + @Schema(description = "是否可入库", example = "true") + private Boolean inEnable; + + @Schema(description = "是否可退货", example = "true") + private Boolean returnEnable; + +} \ No newline at end of file diff --git a/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/controller/admin/purchase/vo/order/ErpPurchaseOrderRespVO.java b/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/controller/admin/purchase/vo/order/ErpPurchaseOrderRespVO.java new file mode 100644 index 000000000..fb3ac63df --- /dev/null +++ b/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/controller/admin/purchase/vo/order/ErpPurchaseOrderRespVO.java @@ -0,0 +1,152 @@ +package cn.iocoder.yudao.module.erp.controller.admin.purchase.vo.order; + +import com.alibaba.excel.annotation.ExcelIgnoreUnannotated; +import com.alibaba.excel.annotation.ExcelProperty; +import io.swagger.v3.oas.annotations.media.Schema; +import jakarta.validation.constraints.NotNull; +import lombok.Data; + +import java.math.BigDecimal; +import java.time.LocalDateTime; +import java.util.List; + +@Schema(description = "管理后台 - ERP 采购订单 Response VO") +@Data +@ExcelIgnoreUnannotated +public class ErpPurchaseOrderRespVO { + + @Schema(description = "编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "17386") + @ExcelProperty("编号") + private Long id; + + @Schema(description = "采购单编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "XS001") + @ExcelProperty("采购单编号") + private String no; + + @Schema(description = "采购状态", requiredMode = Schema.RequiredMode.REQUIRED, example = "2") + @ExcelProperty("采购状态") + private Integer status; + + @Schema(description = "供应商编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "1724") + private Long supplierId; + @Schema(description = "供应商名称", example = "芋道") + @ExcelProperty("供应商名称") + private String supplierName; + + @Schema(description = "结算账户编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "311.89") + @ExcelProperty("结算账户编号") + private Long accountId; + + @Schema(description = "采购时间", requiredMode = Schema.RequiredMode.REQUIRED) + @ExcelProperty("采购时间") + private LocalDateTime orderTime; + + @Schema(description = "合计数量", requiredMode = Schema.RequiredMode.REQUIRED, example = "15663") + @ExcelProperty("合计数量") + private BigDecimal totalCount; + @Schema(description = "最终合计价格", requiredMode = Schema.RequiredMode.REQUIRED, example = "24906") + @ExcelProperty("最终合计价格") + private BigDecimal totalPrice; + + @Schema(description = "合计产品价格,单位:元", requiredMode = Schema.RequiredMode.REQUIRED, example = "7127") + private BigDecimal totalProductPrice; + + @Schema(description = "合计税额,单位:元", requiredMode = Schema.RequiredMode.REQUIRED, example = "7127") + private BigDecimal totalTaxPrice; + + @Schema(description = "优惠率,百分比", requiredMode = Schema.RequiredMode.REQUIRED, example = "99.88") + private BigDecimal discountPercent; + + @Schema(description = "优惠金额,单位:元", requiredMode = Schema.RequiredMode.REQUIRED, example = "7127") + private BigDecimal discountPrice; + + @Schema(description = "定金金额,单位:元", requiredMode = Schema.RequiredMode.REQUIRED, example = "7127") + private BigDecimal depositPrice; + + @Schema(description = "附件地址", example = "https://www.iocoder.cn") + @ExcelProperty("附件地址") + private String fileUrl; + + @Schema(description = "备注", example = "你猜") + @ExcelProperty("备注") + private String remark; + + @Schema(description = "创建人", example = "芋道") + private String creator; + @Schema(description = "创建人名称", example = "芋道") + private String creatorName; + + @Schema(description = "创建时间", requiredMode = Schema.RequiredMode.REQUIRED) + @ExcelProperty("创建时间") + private LocalDateTime createTime; + + @Schema(description = "订单项列表", requiredMode = Schema.RequiredMode.REQUIRED) + private List items; + + @Schema(description = "产品信息", requiredMode = Schema.RequiredMode.REQUIRED) + @ExcelProperty("产品信息") + private String productNames; + + // ========== 采购出库 ========== + + @Schema(description = "采购出库数量", requiredMode = Schema.RequiredMode.REQUIRED, example = "100.00") + private BigDecimal outCount; + + // ========== 采购退货(出库)) ========== + + @Schema(description = "采购退货数量", requiredMode = Schema.RequiredMode.REQUIRED, example = "100.00") + private BigDecimal returnCount; + + @Data + public static class Item { + + @Schema(description = "订单项编号", example = "11756") + private Long id; + + @Schema(description = "产品编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "3113") + private Long productId; + + @Schema(description = "产品单位单位", requiredMode = Schema.RequiredMode.REQUIRED, example = "3113") + private Long productUnitId; + + @Schema(description = "产品单价", example = "100.00") + private BigDecimal productPrice; + + @Schema(description = "产品数量", requiredMode = Schema.RequiredMode.REQUIRED, example = "100.00") + @NotNull(message = "产品数量不能为空") + private BigDecimal count; + + @Schema(description = "税率,百分比", example = "99.88") + private BigDecimal taxPercent; + + @Schema(description = "税额,单位:元", example = "100.00") + private BigDecimal taxPrice; + + @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 = "巧克力") + private String productName; + @Schema(description = "产品条码", requiredMode = Schema.RequiredMode.REQUIRED, example = "A9985") + private String productBarCode; + @Schema(description = "产品单位名称", requiredMode = Schema.RequiredMode.REQUIRED, example = "盒") + private String productUnitName; + + @Schema(description = "库存数量", requiredMode = Schema.RequiredMode.REQUIRED, example = "100.00") + private BigDecimal stockCount; // 该字段仅仅在“详情”和“编辑”时使用 + + } + +} \ No newline at end of file diff --git a/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/controller/admin/purchase/vo/order/ErpPurchaseOrderSaveReqVO.java b/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/controller/admin/purchase/vo/order/ErpPurchaseOrderSaveReqVO.java new file mode 100644 index 000000000..061ed9dcc --- /dev/null +++ b/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/controller/admin/purchase/vo/order/ErpPurchaseOrderSaveReqVO.java @@ -0,0 +1,73 @@ +package cn.iocoder.yudao.module.erp.controller.admin.purchase.vo.order; + +import io.swagger.v3.oas.annotations.media.Schema; +import jakarta.validation.constraints.NotNull; +import lombok.Data; + +import java.math.BigDecimal; +import java.time.LocalDateTime; +import java.util.List; + +@Schema(description = "管理后台 - ERP 采购订单新增/修改 Request VO") +@Data +public class ErpPurchaseOrderSaveReqVO { + + @Schema(description = "编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "17386") + private Long id; + + @Schema(description = "供应商编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "1724") + @NotNull(message = "供应商编号不能为空") + private Long supplierId; + + @Schema(description = "结算账户编号", example = "31189") + private Long accountId; + + @Schema(description = "采购时间", requiredMode = Schema.RequiredMode.REQUIRED) + @NotNull(message = "采购时间不能为空") + private LocalDateTime orderTime; + + @Schema(description = "优惠率,百分比", requiredMode = Schema.RequiredMode.REQUIRED, example = "99.88") + private BigDecimal discountPercent; + + @Schema(description = "定金金额,单位:元", example = "7127") + private BigDecimal depositPrice; + + @Schema(description = "附件地址", example = "https://www.iocoder.cn") + private String fileUrl; + + @Schema(description = "备注", example = "你猜") + private String remark; + + @Schema(description = "订单清单列表") + private List items; + + @Data + public static class Item { + + @Schema(description = "订单项编号", example = "11756") + private Long id; + + @Schema(description = "产品编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "3113") + @NotNull(message = "产品编号不能为空") + private Long productId; + + @Schema(description = "产品单位单位", requiredMode = Schema.RequiredMode.REQUIRED, example = "3113") + @NotNull(message = "产品单位单位不能为空") + private Long productUnitId; + + @Schema(description = "产品单价", example = "100.00") + private BigDecimal productPrice; + + @Schema(description = "产品数量", requiredMode = Schema.RequiredMode.REQUIRED, example = "100.00") + @NotNull(message = "产品数量不能为空") + private BigDecimal count; + + @Schema(description = "税率,百分比", example = "99.88") + private BigDecimal taxPercent; + + @Schema(description = "备注", example = "随便") + private String remark; + + } + +} \ No newline at end of file diff --git a/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/controller/admin/sale/ErpSaleOrderController.java b/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/controller/admin/sale/ErpSaleOrderController.java index 2971ff5fc..348690fb3 100644 --- a/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/controller/admin/sale/ErpSaleOrderController.java +++ b/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/controller/admin/sale/ErpSaleOrderController.java @@ -62,14 +62,14 @@ public class ErpSaleOrderController { @PostMapping("/create") @Operation(summary = "创建销售订单") - @PreAuthorize("@ss.hasPermission('erp:stock-out:create')") + @PreAuthorize("@ss.hasPermission('erp:sale-out:create')") public CommonResult createSaleOrder(@Valid @RequestBody ErpSaleOrderSaveReqVO createReqVO) { return success(saleOrderService.createSaleOrder(createReqVO)); } @PutMapping("/update") @Operation(summary = "更新销售订单") - @PreAuthorize("@ss.hasPermission('erp:stock-out:update')") + @PreAuthorize("@ss.hasPermission('erp:sale-out:update')") public CommonResult updateSaleOrder(@Valid @RequestBody ErpSaleOrderSaveReqVO updateReqVO) { saleOrderService.updateSaleOrder(updateReqVO); return success(true); @@ -77,7 +77,7 @@ public class ErpSaleOrderController { @PutMapping("/update-status") @Operation(summary = "更新销售订单的状态") - @PreAuthorize("@ss.hasPermission('erp:stock-out:update-status')") + @PreAuthorize("@ss.hasPermission('erp:sale-out:update-status')") public CommonResult updateSaleOrderStatus(@RequestParam("id") Long id, @RequestParam("status") Integer status) { saleOrderService.updateSaleOrderStatus(id, status); @@ -87,7 +87,7 @@ public class ErpSaleOrderController { @DeleteMapping("/delete") @Operation(summary = "删除销售订单") @Parameter(name = "ids", description = "编号数组", required = true) - @PreAuthorize("@ss.hasPermission('erp:stock-out:delete')") + @PreAuthorize("@ss.hasPermission('erp:sale-out:delete')") public CommonResult deleteSaleOrder(@RequestParam("ids") List ids) { saleOrderService.deleteSaleOrder(ids); return success(true); @@ -96,7 +96,7 @@ public class ErpSaleOrderController { @GetMapping("/get") @Operation(summary = "获得销售订单") @Parameter(name = "id", description = "编号", required = true, example = "1024") - @PreAuthorize("@ss.hasPermission('erp:stock-out:query')") + @PreAuthorize("@ss.hasPermission('erp:sale-out:query')") public CommonResult getSaleOrder(@RequestParam("id") Long id) { ErpSaleOrderDO saleOrder = saleOrderService.getSaleOrder(id); if (saleOrder == null) { @@ -116,7 +116,7 @@ public class ErpSaleOrderController { @GetMapping("/page") @Operation(summary = "获得销售订单分页") - @PreAuthorize("@ss.hasPermission('erp:stock-out:query')") + @PreAuthorize("@ss.hasPermission('erp:sale-out:query')") public CommonResult> getSaleOrderPage(@Valid ErpSaleOrderPageReqVO pageReqVO) { PageResult pageResult = saleOrderService.getSaleOrderPage(pageReqVO); return success(buildSaleOrderVOPageResult(pageResult)); @@ -124,7 +124,7 @@ public class ErpSaleOrderController { @GetMapping("/export-excel") @Operation(summary = "导出销售订单 Excel") - @PreAuthorize("@ss.hasPermission('erp:stock-out:export')") + @PreAuthorize("@ss.hasPermission('erp:sale-out:export')") @OperateLog(type = EXPORT) public void exportSaleOrderExcel(@Valid ErpSaleOrderPageReqVO pageReqVO, HttpServletResponse response) throws IOException { @@ -142,7 +142,7 @@ public class ErpSaleOrderController { List saleOrderItemList = saleOrderService.getSaleOrderItemListByOrderIds( convertSet(pageResult.getList(), ErpSaleOrderDO::getId)); Map> saleOrderItemMap = convertMultiMap(saleOrderItemList, ErpSaleOrderItemDO::getOrderId); - // 1.2 商品信息 + // 1.2 产品信息 Map productMap = productService.getProductVOMap( convertSet(saleOrderItemList, ErpSaleOrderItemDO::getProductId)); // 1.3 客户信息 diff --git a/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/controller/admin/sale/ErpSaleOutController.java b/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/controller/admin/sale/ErpSaleOutController.java index b390038f2..e640a358c 100644 --- a/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/controller/admin/sale/ErpSaleOutController.java +++ b/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/controller/admin/sale/ErpSaleOutController.java @@ -62,14 +62,14 @@ public class ErpSaleOutController { @PostMapping("/create") @Operation(summary = "创建销售出库") - @PreAuthorize("@ss.hasPermission('erp:stock-out:create')") + @PreAuthorize("@ss.hasPermission('erp:sale-out:create')") public CommonResult createSaleOut(@Valid @RequestBody ErpSaleOutSaveReqVO createReqVO) { return success(saleOutService.createSaleOut(createReqVO)); } @PutMapping("/update") @Operation(summary = "更新销售出库") - @PreAuthorize("@ss.hasPermission('erp:stock-out:update')") + @PreAuthorize("@ss.hasPermission('erp:sale-out:update')") public CommonResult updateSaleOut(@Valid @RequestBody ErpSaleOutSaveReqVO updateReqVO) { saleOutService.updateSaleOut(updateReqVO); return success(true); @@ -77,7 +77,7 @@ public class ErpSaleOutController { @PutMapping("/update-status") @Operation(summary = "更新销售出库的状态") - @PreAuthorize("@ss.hasPermission('erp:stock-out:update-status')") + @PreAuthorize("@ss.hasPermission('erp:sale-out:update-status')") public CommonResult updateSaleOutStatus(@RequestParam("id") Long id, @RequestParam("status") Integer status) { saleOutService.updateSaleOutStatus(id, status); @@ -87,7 +87,7 @@ public class ErpSaleOutController { @DeleteMapping("/delete") @Operation(summary = "删除销售出库") @Parameter(name = "ids", description = "编号数组", required = true) - @PreAuthorize("@ss.hasPermission('erp:stock-out:delete')") + @PreAuthorize("@ss.hasPermission('erp:sale-out:delete')") public CommonResult deleteSaleOut(@RequestParam("ids") List ids) { saleOutService.deleteSaleOut(ids); return success(true); @@ -96,7 +96,7 @@ public class ErpSaleOutController { @GetMapping("/get") @Operation(summary = "获得销售出库") @Parameter(name = "id", description = "编号", required = true, example = "1024") - @PreAuthorize("@ss.hasPermission('erp:stock-out:query')") + @PreAuthorize("@ss.hasPermission('erp:sale-out:query')") public CommonResult getSaleOut(@RequestParam("id") Long id) { ErpSaleOutDO saleOut = saleOutService.getSaleOut(id); if (saleOut == null) { @@ -116,7 +116,7 @@ public class ErpSaleOutController { @GetMapping("/page") @Operation(summary = "获得销售出库分页") - @PreAuthorize("@ss.hasPermission('erp:stock-out:query')") + @PreAuthorize("@ss.hasPermission('erp:sale-out:query')") public CommonResult> getSaleOutPage(@Valid ErpSaleOutPageReqVO pageReqVO) { PageResult pageResult = saleOutService.getSaleOutPage(pageReqVO); return success(buildSaleOutVOPageResult(pageResult)); @@ -124,7 +124,7 @@ public class ErpSaleOutController { @GetMapping("/export-excel") @Operation(summary = "导出销售出库 Excel") - @PreAuthorize("@ss.hasPermission('erp:stock-out:export')") + @PreAuthorize("@ss.hasPermission('erp:sale-out:export')") @OperateLog(type = EXPORT) public void exportSaleOutExcel(@Valid ErpSaleOutPageReqVO pageReqVO, HttpServletResponse response) throws IOException { @@ -142,7 +142,7 @@ public class ErpSaleOutController { List saleOutItemList = saleOutService.getSaleOutItemListByOutIds( convertSet(pageResult.getList(), ErpSaleOutDO::getId)); Map> saleOutItemMap = convertMultiMap(saleOutItemList, ErpSaleOutItemDO::getOutId); - // 1.2 商品信息 + // 1.2 产品信息 Map productMap = productService.getProductVOMap( convertSet(saleOutItemList, ErpSaleOutItemDO::getProductId)); // 1.3 客户信息 diff --git a/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/controller/admin/sale/ErpSaleReturnController.java b/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/controller/admin/sale/ErpSaleReturnController.java index 3c95fa640..09ba77291 100644 --- a/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/controller/admin/sale/ErpSaleReturnController.java +++ b/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/controller/admin/sale/ErpSaleReturnController.java @@ -62,14 +62,14 @@ public class ErpSaleReturnController { @PostMapping("/create") @Operation(summary = "创建销售退货") - @PreAuthorize("@ss.hasPermission('erp:stock-return:create')") + @PreAuthorize("@ss.hasPermission('erp:sale-return:create')") public CommonResult createSaleReturn(@Valid @RequestBody ErpSaleReturnSaveReqVO createReqVO) { return success(saleReturnService.createSaleReturn(createReqVO)); } @PutMapping("/update") @Operation(summary = "更新销售退货") - @PreAuthorize("@ss.hasPermission('erp:stock-return:update')") + @PreAuthorize("@ss.hasPermission('erp:sale-return:update')") public CommonResult updateSaleReturn(@Valid @RequestBody ErpSaleReturnSaveReqVO updateReqVO) { saleReturnService.updateSaleReturn(updateReqVO); return success(true); @@ -77,7 +77,7 @@ public class ErpSaleReturnController { @PutMapping("/update-status") @Operation(summary = "更新销售退货的状态") - @PreAuthorize("@ss.hasPermission('erp:stock-return:update-status')") + @PreAuthorize("@ss.hasPermission('erp:sale-return:update-status')") public CommonResult updateSaleReturnStatus(@RequestParam("id") Long id, @RequestParam("status") Integer status) { saleReturnService.updateSaleReturnStatus(id, status); @@ -87,7 +87,7 @@ public class ErpSaleReturnController { @DeleteMapping("/delete") @Operation(summary = "删除销售退货") @Parameter(name = "ids", description = "编号数组", required = true) - @PreAuthorize("@ss.hasPermission('erp:stock-return:delete')") + @PreAuthorize("@ss.hasPermission('erp:sale-return:delete')") public CommonResult deleteSaleReturn(@RequestParam("ids") List ids) { saleReturnService.deleteSaleReturn(ids); return success(true); @@ -96,7 +96,7 @@ public class ErpSaleReturnController { @GetMapping("/get") @Operation(summary = "获得销售退货") @Parameter(name = "id", description = "编号", required = true, example = "1024") - @PreAuthorize("@ss.hasPermission('erp:stock-return:query')") + @PreAuthorize("@ss.hasPermission('erp:sale-return:query')") public CommonResult getSaleReturn(@RequestParam("id") Long id) { ErpSaleReturnDO saleReturn = saleReturnService.getSaleReturn(id); if (saleReturn == null) { @@ -116,7 +116,7 @@ public class ErpSaleReturnController { @GetMapping("/page") @Operation(summary = "获得销售退货分页") - @PreAuthorize("@ss.hasPermission('erp:stock-return:query')") + @PreAuthorize("@ss.hasPermission('erp:sale-return:query')") public CommonResult> getSaleReturnPage(@Valid ErpSaleReturnPageReqVO pageReqVO) { PageResult pageResult = saleReturnService.getSaleReturnPage(pageReqVO); return success(buildSaleReturnVOPageResult(pageResult)); @@ -124,7 +124,7 @@ public class ErpSaleReturnController { @GetMapping("/export-excel") @Operation(summary = "导出销售退货 Excel") - @PreAuthorize("@ss.hasPermission('erp:stock-return:export')") + @PreAuthorize("@ss.hasPermission('erp:sale-return:export')") @OperateLog(type = EXPORT) public void exportSaleReturnExcel(@Valid ErpSaleReturnPageReqVO pageReqVO, HttpServletResponse response) throws IOException { @@ -142,7 +142,7 @@ public class ErpSaleReturnController { List saleReturnItemList = saleReturnService.getSaleReturnItemListByReturnIds( convertSet(pageResult.getList(), ErpSaleReturnDO::getId)); Map> saleReturnItemMap = convertMultiMap(saleReturnItemList, ErpSaleReturnItemDO::getReturnId); - // 1.2 商品信息 + // 1.2 产品信息 Map productMap = productService.getProductVOMap( convertSet(saleReturnItemList, ErpSaleReturnItemDO::getProductId)); // 1.3 客户信息 diff --git a/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/controller/admin/sale/vo/order/ErpSaleOrderPageReqVO.java b/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/controller/admin/sale/vo/order/ErpSaleOrderPageReqVO.java index 5d4f22f1b..84d92fb67 100644 --- a/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/controller/admin/sale/vo/order/ErpSaleOrderPageReqVO.java +++ b/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/controller/admin/sale/vo/order/ErpSaleOrderPageReqVO.java @@ -18,17 +18,17 @@ import static cn.iocoder.yudao.framework.common.util.date.DateUtils.FORMAT_YEAR_ public class ErpSaleOrderPageReqVO extends PageParam { /** - * 入库状态 - 无 + * 出库状态 - 无 */ - public static final Integer IN_STATUS_NONE = 0; + public static final Integer OUT_STATUS_NONE = 0; /** - * 入库状态 - 部分 + * 出库状态 - 部分 */ - public static final Integer IN_STATUS_PART = 1; + public static final Integer OUT_STATUS_PART = 1; /** - * 入库状态 - 全部 + * 出库状态 - 全部 */ - public static final Integer IN_STATUS_ALL = 2; + public static final Integer OUT_STATUS_ALL = 2; /** * 退货状态 - 无 @@ -65,8 +65,8 @@ public class ErpSaleOrderPageReqVO extends PageParam { @Schema(description = "产品编号", example = "1") private Long productId; - @Schema(description = "入库状态", example = "2") - private Integer inStatus; + @Schema(description = "出库状态", example = "2") + private Integer outStatus; @Schema(description = "退货状态", example = "2") private Integer returnStatus; diff --git a/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/controller/admin/sale/vo/order/ErpSaleOrderRespVO.java b/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/controller/admin/sale/vo/order/ErpSaleOrderRespVO.java index 8b0aa83ea..e5958a841 100644 --- a/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/controller/admin/sale/vo/order/ErpSaleOrderRespVO.java +++ b/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/controller/admin/sale/vo/order/ErpSaleOrderRespVO.java @@ -74,9 +74,9 @@ public class ErpSaleOrderRespVO { @ExcelProperty("备注") private String remark; - @Schema(description = "审核人", example = "芋道") + @Schema(description = "创建人", example = "芋道") private String creator; - @Schema(description = "审核人名称", example = "芋道") + @Schema(description = "创建人名称", example = "芋道") private String creatorName; @Schema(description = "创建时间", requiredMode = Schema.RequiredMode.REQUIRED) @@ -133,7 +133,7 @@ public class ErpSaleOrderRespVO { @Schema(description = "销售出库数量", requiredMode = Schema.RequiredMode.REQUIRED, example = "100.00") private BigDecimal outCount; - // ========== 销售退货(出库)) ========== + // ========== 销售退货(入库)) ========== @Schema(description = "销售退货数量", requiredMode = Schema.RequiredMode.REQUIRED, example = "100.00") private BigDecimal returnCount; diff --git a/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/controller/admin/sale/vo/out/ErpSaleOutRespVO.java b/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/controller/admin/sale/vo/out/ErpSaleOutRespVO.java index 832d34974..4f6cc49ab 100644 --- a/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/controller/admin/sale/vo/out/ErpSaleOutRespVO.java +++ b/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/controller/admin/sale/vo/out/ErpSaleOutRespVO.java @@ -85,9 +85,9 @@ public class ErpSaleOutRespVO { @ExcelProperty("备注") private String remark; - @Schema(description = "审核人", example = "芋道") + @Schema(description = "创建人", example = "芋道") private String creator; - @Schema(description = "审核人名称", example = "芋道") + @Schema(description = "创建人名称", example = "芋道") private String creatorName; @Schema(description = "创建时间", requiredMode = Schema.RequiredMode.REQUIRED) diff --git a/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/controller/admin/sale/vo/returns/ErpSaleReturnRespVO.java b/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/controller/admin/sale/vo/returns/ErpSaleReturnRespVO.java index 78b94a35e..0a7801de1 100644 --- a/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/controller/admin/sale/vo/returns/ErpSaleReturnRespVO.java +++ b/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/controller/admin/sale/vo/returns/ErpSaleReturnRespVO.java @@ -85,9 +85,9 @@ public class ErpSaleReturnRespVO { @ExcelProperty("备注") private String remark; - @Schema(description = "审核人", example = "芋道") + @Schema(description = "创建人", example = "芋道") private String creator; - @Schema(description = "审核人名称", example = "芋道") + @Schema(description = "创建人名称", example = "芋道") private String creatorName; @Schema(description = "创建时间", requiredMode = Schema.RequiredMode.REQUIRED) diff --git a/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/controller/admin/stock/ErpStockCheckController.java b/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/controller/admin/stock/ErpStockCheckController.java index c2abc6ec9..8e30232f6 100644 --- a/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/controller/admin/stock/ErpStockCheckController.java +++ b/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/controller/admin/stock/ErpStockCheckController.java @@ -130,7 +130,7 @@ public class ErpStockCheckController { List stockCheckItemList = stockCheckService.getStockCheckItemListByCheckIds( convertSet(pageResult.getList(), ErpStockCheckDO::getId)); Map> stockCheckItemMap = convertMultiMap(stockCheckItemList, ErpStockCheckItemDO::getCheckId); - // 1.2 商品信息 + // 1.2 产品信息 Map productMap = productService.getProductVOMap( convertSet(stockCheckItemList, ErpStockCheckItemDO::getProductId)); // 1.3 管理员信息 diff --git a/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/controller/admin/stock/ErpStockInController.java b/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/controller/admin/stock/ErpStockInController.java index 75120fce5..8cdd84c58 100644 --- a/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/controller/admin/stock/ErpStockInController.java +++ b/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/controller/admin/stock/ErpStockInController.java @@ -142,7 +142,7 @@ public class ErpStockInController { List stockInItemList = stockInService.getStockInItemListByInIds( convertSet(pageResult.getList(), ErpStockInDO::getId)); Map> stockInItemMap = convertMultiMap(stockInItemList, ErpStockInItemDO::getInId); - // 1.2 商品信息 + // 1.2 产品信息 Map productMap = productService.getProductVOMap( convertSet(stockInItemList, ErpStockInItemDO::getProductId)); // 1.3 供应商信息 diff --git a/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/controller/admin/stock/ErpStockMoveController.java b/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/controller/admin/stock/ErpStockMoveController.java index d8c838b61..e3805c994 100644 --- a/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/controller/admin/stock/ErpStockMoveController.java +++ b/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/controller/admin/stock/ErpStockMoveController.java @@ -138,7 +138,7 @@ public class ErpStockMoveController { List stockMoveItemList = stockMoveService.getStockMoveItemListByMoveIds( convertSet(pageResult.getList(), ErpStockMoveDO::getId)); Map> stockMoveItemMap = convertMultiMap(stockMoveItemList, ErpStockMoveItemDO::getMoveId); - // 1.2 商品信息 + // 1.2 产品信息 Map productMap = productService.getProductVOMap( convertSet(stockMoveItemList, ErpStockMoveItemDO::getProductId)); // 1.3 TODO 芋艿:搞仓库信息 diff --git a/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/controller/admin/stock/ErpStockOutController.java b/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/controller/admin/stock/ErpStockOutController.java index 504a06e98..55b7fa988 100644 --- a/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/controller/admin/stock/ErpStockOutController.java +++ b/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/controller/admin/stock/ErpStockOutController.java @@ -142,7 +142,7 @@ public class ErpStockOutController { List stockOutItemList = stockOutService.getStockOutItemListByOutIds( convertSet(pageResult.getList(), ErpStockOutDO::getId)); Map> stockOutItemMap = convertMultiMap(stockOutItemList, ErpStockOutItemDO::getOutId); - // 1.2 商品信息 + // 1.2 产品信息 Map productMap = productService.getProductVOMap( convertSet(stockOutItemList, ErpStockOutItemDO::getProductId)); // 1.3 客户信息 diff --git a/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/controller/admin/stock/vo/check/ErpStockCheckRespVO.java b/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/controller/admin/stock/vo/check/ErpStockCheckRespVO.java index d761516d9..af53e3c72 100644 --- a/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/controller/admin/stock/vo/check/ErpStockCheckRespVO.java +++ b/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/controller/admin/stock/vo/check/ErpStockCheckRespVO.java @@ -51,9 +51,9 @@ public class ErpStockCheckRespVO { @Schema(description = "附件 URL", example = "https://www.iocoder.cn/1.doc") private String fileUrl; - @Schema(description = "审核人", example = "芋道") + @Schema(description = "创建人", example = "芋道") private String creator; - @Schema(description = "审核人名称", example = "芋道") + @Schema(description = "创建人名称", example = "芋道") private String creatorName; @Schema(description = "创建时间", requiredMode = Schema.RequiredMode.REQUIRED) diff --git a/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/controller/admin/stock/vo/in/ErpStockInRespVO.java b/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/controller/admin/stock/vo/in/ErpStockInRespVO.java index e6263db61..077b9dd1b 100644 --- a/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/controller/admin/stock/vo/in/ErpStockInRespVO.java +++ b/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/controller/admin/stock/vo/in/ErpStockInRespVO.java @@ -56,9 +56,9 @@ public class ErpStockInRespVO { @Schema(description = "附件 URL", example = "https://www.iocoder.cn/1.doc") private String fileUrl; - @Schema(description = "审核人", example = "芋道") + @Schema(description = "创建人", example = "芋道") private String creator; - @Schema(description = "审核人名称", example = "芋道") + @Schema(description = "创建人名称", example = "芋道") private String creatorName; @Schema(description = "创建时间", requiredMode = Schema.RequiredMode.REQUIRED) diff --git a/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/controller/admin/stock/vo/move/ErpStockMoveRespVO.java b/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/controller/admin/stock/vo/move/ErpStockMoveRespVO.java index b09fb15a1..799ddc3f1 100644 --- a/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/controller/admin/stock/vo/move/ErpStockMoveRespVO.java +++ b/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/controller/admin/stock/vo/move/ErpStockMoveRespVO.java @@ -50,9 +50,9 @@ public class ErpStockMoveRespVO { @Schema(description = "附件 URL", example = "https://www.iocoder.cn/1.doc") private String fileUrl; - @Schema(description = "审核人", example = "芋道") + @Schema(description = "创建人", example = "芋道") private String creator; - @Schema(description = "审核人名称", example = "芋道") + @Schema(description = "创建人名称", example = "芋道") private String creatorName; @Schema(description = "创建时间", requiredMode = Schema.RequiredMode.REQUIRED) diff --git a/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/controller/admin/stock/vo/out/ErpStockOutRespVO.java b/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/controller/admin/stock/vo/out/ErpStockOutRespVO.java index e0128730e..22a88e7c9 100644 --- a/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/controller/admin/stock/vo/out/ErpStockOutRespVO.java +++ b/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/controller/admin/stock/vo/out/ErpStockOutRespVO.java @@ -56,9 +56,9 @@ public class ErpStockOutRespVO { @Schema(description = "附件 URL", example = "https://www.iocoder.cn/1.doc") private String fileUrl; - @Schema(description = "审核人", example = "芋道") + @Schema(description = "创建人", example = "芋道") private String creator; - @Schema(description = "审核人名称", example = "芋道") + @Schema(description = "创建人名称", example = "芋道") private String creatorName; @Schema(description = "创建时间", requiredMode = Schema.RequiredMode.REQUIRED) diff --git a/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/dal/dataobject/purchase/ErpPurchaseOrderDO.java b/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/dal/dataobject/purchase/ErpPurchaseOrderDO.java new file mode 100644 index 000000000..bba1542e3 --- /dev/null +++ b/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/dal/dataobject/purchase/ErpPurchaseOrderDO.java @@ -0,0 +1,115 @@ +package cn.iocoder.yudao.module.erp.dal.dataobject.purchase; + +import cn.iocoder.yudao.framework.mybatis.core.dataobject.BaseDO; +import cn.iocoder.yudao.module.erp.dal.dataobject.finance.ErpAccountDO; +import com.baomidou.mybatisplus.annotation.KeySequence; +import com.baomidou.mybatisplus.annotation.TableId; +import com.baomidou.mybatisplus.annotation.TableName; +import lombok.*; + +import java.math.BigDecimal; +import java.time.LocalDateTime; + +/** + * ERP 采购订单 DO + * + * @author 芋道源码 + */ +@TableName(value = "erp_purchase_order") +@KeySequence("erp_purchase_order_seq") // 用于 Oracle、PostgreSQL、Kingbase、DB2、H2 数据库的主键自增。如果是 MySQL 等数据库,可不写。 +@Data +@EqualsAndHashCode(callSuper = true) +@ToString(callSuper = true) +@Builder +@NoArgsConstructor +@AllArgsConstructor +public class ErpPurchaseOrderDO extends BaseDO { + + /** + * 编号 + */ + @TableId + private Long id; + /** + * 采购订单号 + */ + private String no; + /** + * 采购状态 + * + * 枚举 {@link cn.iocoder.yudao.module.erp.enums.ErpAuditStatus} + */ + private Integer status; + /** + * 供应商编号 + * + * 关联 {@link ErpSupplierDO#getId()} + */ + private Long supplierId; + /** + * 结算账户编号 + * + * 关联 {@link ErpAccountDO#getId()} + */ + private Long accountId; + /** + * 下单时间 + */ + private LocalDateTime orderTime; + + /** + * 合计数量 + */ + private BigDecimal totalCount; + /** + * 最终合计价格,单位:元 + * + * totalPrice = totalProductPrice + totalTaxPrice - discountPrice + */ + private BigDecimal totalPrice; + + /** + * 合计产品价格,单位:元 + */ + private BigDecimal totalProductPrice; + /** + * 合计税额,单位:元 + */ + private BigDecimal totalTaxPrice; + /** + * 优惠率,百分比 + */ + private BigDecimal discountPercent; + /** + * 优惠金额,单位:元 + * + * discountPrice = (totalProductPrice + totalTaxPrice) * discountPercent + */ + private BigDecimal discountPrice; + /** + * 定金金额,单位:元 + */ + private BigDecimal depositPrice; + + /** + * 附件地址 + */ + private String fileUrl; + /** + * 备注 + */ + private String remark; + + // ========== 采购入库 ========== + /** + * 采购入库数量 + */ + private BigDecimal inCount; + + // ========== 采购退货(出库)) ========== + /** + * 采购退货数量 + */ + private BigDecimal returnCount; + +} \ No newline at end of file diff --git a/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/dal/dataobject/purchase/ErpPurchaseOrderItemDO.java b/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/dal/dataobject/purchase/ErpPurchaseOrderItemDO.java new file mode 100644 index 000000000..52930b58f --- /dev/null +++ b/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/dal/dataobject/purchase/ErpPurchaseOrderItemDO.java @@ -0,0 +1,93 @@ +package cn.iocoder.yudao.module.erp.dal.dataobject.purchase; + +import cn.iocoder.yudao.framework.mybatis.core.dataobject.BaseDO; +import cn.iocoder.yudao.module.erp.dal.dataobject.product.ErpProductDO; +import com.baomidou.mybatisplus.annotation.KeySequence; +import com.baomidou.mybatisplus.annotation.TableId; +import com.baomidou.mybatisplus.annotation.TableName; +import lombok.*; + +import java.math.BigDecimal; + +/** + * ERP 采购订单项 DO + * + * @author 芋道源码 + */ +@TableName("erp_sale_order_items") +@KeySequence("erp_sale_order_items_seq") // 用于 Oracle、PostgreSQL、Kingbase、DB2、H2 数据库的主键自增。如果是 MySQL 等数据库,可不写。 +@Data +@EqualsAndHashCode(callSuper = true) +@ToString(callSuper = true) +@Builder +@NoArgsConstructor +@AllArgsConstructor +public class ErpPurchaseOrderItemDO extends BaseDO { + + /** + * 编号 + */ + @TableId + private Long id; + /** + * 采购订单编号 + * + * 关联 {@link ErpPurchaseOrderDO#getId()} + */ + private Long orderId; + /** + * 产品编号 + * + * 关联 {@link ErpProductDO#getId()} + */ + private Long productId; + /** + * 产品单位单位 + * + * 冗余 {@link ErpProductDO#getUnitId()} + */ + private Long productUnitId; + + /** + * 产品单位单价,单位:元 + */ + private BigDecimal productPrice; + /** + * 数量 + */ + private BigDecimal count; + /** + * 总价,单位:元 + * + * totalPrice = productPrice * count + */ + private BigDecimal totalPrice; + /** + * 税率,百分比 + */ + private BigDecimal taxPercent; + /** + * 税额,单位:元 + * + * taxPrice = totalPrice * taxPercent + */ + private BigDecimal taxPrice; + + /** + * 备注 + */ + private String remark; + + // ========== 采购入库 ========== + /** + * 采购入库数量 + */ + private BigDecimal inCount; + + // ========== 采购退货(出库)) ========== + /** + * 采购退货数量 + */ + private BigDecimal returnCount; + +} \ No newline at end of file diff --git a/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/dal/dataobject/sale/ErpSaleOrderDO.java b/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/dal/dataobject/sale/ErpSaleOrderDO.java index 81f02ccc3..5cdd4344e 100644 --- a/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/dal/dataobject/sale/ErpSaleOrderDO.java +++ b/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/dal/dataobject/sale/ErpSaleOrderDO.java @@ -112,7 +112,7 @@ public class ErpSaleOrderDO extends BaseDO { */ private BigDecimal outCount; - // ========== 销售退货(出库)) ========== + // ========== 销售退货(入库)) ========== /** * 销售退货数量 */ diff --git a/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/dal/dataobject/sale/ErpSaleOrderItemDO.java b/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/dal/dataobject/sale/ErpSaleOrderItemDO.java index 3a9778aec..4c829765b 100644 --- a/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/dal/dataobject/sale/ErpSaleOrderItemDO.java +++ b/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/dal/dataobject/sale/ErpSaleOrderItemDO.java @@ -84,7 +84,7 @@ public class ErpSaleOrderItemDO extends BaseDO { */ private BigDecimal outCount; - // ========== 销售退货(出库)) ========== + // ========== 销售退货(入库)) ========== /** * 销售退货数量 */ diff --git a/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/dal/mysql/purchase/ErpPurchaseOrderItemMapper.java b/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/dal/mysql/purchase/ErpPurchaseOrderItemMapper.java new file mode 100644 index 000000000..17f1fe290 --- /dev/null +++ b/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/dal/mysql/purchase/ErpPurchaseOrderItemMapper.java @@ -0,0 +1,30 @@ +package cn.iocoder.yudao.module.erp.dal.mysql.purchase; + +import cn.iocoder.yudao.framework.mybatis.core.mapper.BaseMapperX; +import cn.iocoder.yudao.module.erp.dal.dataobject.purchase.ErpPurchaseOrderItemDO; +import org.apache.ibatis.annotations.Mapper; + +import java.util.Collection; +import java.util.List; + +/** + * ERP 采购订单明项目 Mapper + * + * @author 芋道源码 + */ +@Mapper +public interface ErpPurchaseOrderItemMapper extends BaseMapperX { + + default List selectListByOrderId(Long orderId) { + return selectList(ErpPurchaseOrderItemDO::getOrderId, orderId); + } + + default List selectListByOrderIds(Collection orderIds) { + return selectList(ErpPurchaseOrderItemDO::getOrderId, orderIds); + } + + default int deleteByOrderId(Long orderId) { + return delete(ErpPurchaseOrderItemDO::getOrderId, orderId); + } + +} \ No newline at end of file diff --git a/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/dal/mysql/purchase/ErpPurchaseOrderMapper.java b/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/dal/mysql/purchase/ErpPurchaseOrderMapper.java new file mode 100644 index 000000000..8061c6f0d --- /dev/null +++ b/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/dal/mysql/purchase/ErpPurchaseOrderMapper.java @@ -0,0 +1,75 @@ +package cn.iocoder.yudao.module.erp.dal.mysql.purchase; + +import cn.iocoder.yudao.framework.common.pojo.PageResult; +import cn.iocoder.yudao.framework.mybatis.core.mapper.BaseMapperX; +import cn.iocoder.yudao.framework.mybatis.core.query.MPJLambdaWrapperX; +import cn.iocoder.yudao.module.erp.controller.admin.purchase.vo.order.ErpPurchaseOrderPageReqVO; +import cn.iocoder.yudao.module.erp.dal.dataobject.purchase.ErpPurchaseOrderDO; +import cn.iocoder.yudao.module.erp.dal.dataobject.purchase.ErpPurchaseOrderItemDO; +import cn.iocoder.yudao.module.erp.enums.ErpAuditStatus; +import com.baomidou.mybatisplus.core.conditions.update.LambdaUpdateWrapper; +import org.apache.ibatis.annotations.Mapper; + +import java.util.Objects; + +/** + * ERP 采购订单 Mapper + * + * @author 芋道源码 + */ +@Mapper +public interface ErpPurchaseOrderMapper extends BaseMapperX { + + default PageResult selectPage(ErpPurchaseOrderPageReqVO reqVO) { + MPJLambdaWrapperX query = new MPJLambdaWrapperX() + .likeIfPresent(ErpPurchaseOrderDO::getNo, reqVO.getNo()) + .eqIfPresent(ErpPurchaseOrderDO::getSupplierId, reqVO.getSupplierId()) + .betweenIfPresent(ErpPurchaseOrderDO::getOrderTime, reqVO.getOrderTime()) + .eqIfPresent(ErpPurchaseOrderDO::getStatus, reqVO.getStatus()) + .likeIfPresent(ErpPurchaseOrderDO::getRemark, reqVO.getRemark()) + .eqIfPresent(ErpPurchaseOrderDO::getCreator, reqVO.getCreator()) + .orderByDesc(ErpPurchaseOrderDO::getId); + // 入库状态。为什么需要 t. 的原因,是因为联表查询时,需要指定表名,不然会报 in_count 错误 + if (Objects.equals(reqVO.getInStatus(), ErpPurchaseOrderPageReqVO.IN_STATUS_NONE)) { + query.eq(ErpPurchaseOrderDO::getInCount, 0); + } else if (Objects.equals(reqVO.getInStatus(), ErpPurchaseOrderPageReqVO.IN_STATUS_PART)) { + query.gt(ErpPurchaseOrderDO::getInCount, 0).apply("t.in_count < t.total_count"); + } else if (Objects.equals(reqVO.getInStatus(), ErpPurchaseOrderPageReqVO.IN_STATUS_ALL)) { + query.apply("t.in_count = t.total_count"); + } + // 退货状态 + if (Objects.equals(reqVO.getReturnStatus(), ErpPurchaseOrderPageReqVO.RETURN_STATUS_NONE)) { + query.eq(ErpPurchaseOrderDO::getReturnCount, 0); + } else if (Objects.equals(reqVO.getReturnStatus(), ErpPurchaseOrderPageReqVO.RETURN_STATUS_PART)) { + query.gt(ErpPurchaseOrderDO::getReturnCount, 0).apply("t.return_count < t.total_count"); + } else if (Objects.equals(reqVO.getReturnStatus(), ErpPurchaseOrderPageReqVO.RETURN_STATUS_ALL)) { + query.apply("t.return_count = t.total_count"); + } + // 可采购出库 + if (Boolean.TRUE.equals(reqVO.getInEnable())) { + query.eq(ErpPurchaseOrderDO::getStatus, ErpAuditStatus.APPROVE.getStatus()) + .apply("t.in_count < t.total_count"); + } + // 可采购退货 + if (Boolean.TRUE.equals(reqVO.getReturnEnable())) { + query.eq(ErpPurchaseOrderDO::getStatus, ErpAuditStatus.APPROVE.getStatus()) + .apply("t.return_count < t.in_count"); + } + if (reqVO.getProductId() != null) { + query.leftJoin(ErpPurchaseOrderItemDO.class, ErpPurchaseOrderItemDO::getOrderId, ErpPurchaseOrderDO::getId) + .eq(reqVO.getProductId() != null, ErpPurchaseOrderItemDO::getProductId, reqVO.getProductId()) + .groupBy(ErpPurchaseOrderDO::getId); // 避免 1 对多查询,产生相同的 1 + } + return selectJoinPage(reqVO, ErpPurchaseOrderDO.class, query); + } + + default int updateByIdAndStatus(Long id, Integer status, ErpPurchaseOrderDO updateObj) { + return update(updateObj, new LambdaUpdateWrapper() + .eq(ErpPurchaseOrderDO::getId, id).eq(ErpPurchaseOrderDO::getStatus, status)); + } + + default ErpPurchaseOrderDO selectByNo(String no) { + return selectOne(ErpPurchaseOrderDO::getNo, no); + } + +} \ No newline at end of file diff --git a/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/dal/mysql/sale/ErpSaleOrderMapper.java b/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/dal/mysql/sale/ErpSaleOrderMapper.java index a8a31bd2a..8ed3b6fcd 100644 --- a/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/dal/mysql/sale/ErpSaleOrderMapper.java +++ b/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/dal/mysql/sale/ErpSaleOrderMapper.java @@ -31,11 +31,11 @@ public interface ErpSaleOrderMapper extends BaseMapperX { .eqIfPresent(ErpSaleOrderDO::getCreator, reqVO.getCreator()) .orderByDesc(ErpSaleOrderDO::getId); // 入库状态。为什么需要 t. 的原因,是因为联表查询时,需要指定表名,不然会报 out_count 错误 - if (Objects.equals(reqVO.getInStatus(), ErpSaleOrderPageReqVO.IN_STATUS_NONE)) { + if (Objects.equals(reqVO.getOutStatus(), ErpSaleOrderPageReqVO.OUT_STATUS_NONE)) { query.eq(ErpSaleOrderDO::getOutCount, 0); - } else if (Objects.equals(reqVO.getInStatus(), ErpSaleOrderPageReqVO.IN_STATUS_PART)) { + } else if (Objects.equals(reqVO.getOutStatus(), ErpSaleOrderPageReqVO.OUT_STATUS_PART)) { query.gt(ErpSaleOrderDO::getOutCount, 0).apply("t.out_count < t.total_count"); - } else if (Objects.equals(reqVO.getInStatus(), ErpSaleOrderPageReqVO.IN_STATUS_ALL)) { + } else if (Objects.equals(reqVO.getOutStatus(), ErpSaleOrderPageReqVO.OUT_STATUS_ALL)) { query.apply("t.out_count = t.total_count"); } // 退货状态 diff --git a/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/dal/redis/no/ErpNoRedisDAO.java b/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/dal/redis/no/ErpNoRedisDAO.java index 192d99bcf..b8d51b5d9 100644 --- a/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/dal/redis/no/ErpNoRedisDAO.java +++ b/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/dal/redis/no/ErpNoRedisDAO.java @@ -51,6 +51,11 @@ public class ErpNoRedisDAO { */ public static final String SALE_RETURN_NO_PREFIX = "XSTH"; + /** + * 采购订单 {@link cn.iocoder.yudao.module.erp.dal.dataobject.purchase.ErpPurchaseOrderDO} + */ + public static final String PURCHASE_ORDER_NO_PREFIX = "CGDD"; + @Resource private StringRedisTemplate stringRedisTemplate; diff --git a/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/service/product/ErpProductUnitServiceImpl.java b/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/service/product/ErpProductUnitServiceImpl.java index 87d78a54f..89ba6b08e 100644 --- a/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/service/product/ErpProductUnitServiceImpl.java +++ b/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/service/product/ErpProductUnitServiceImpl.java @@ -74,7 +74,7 @@ public class ErpProductUnitServiceImpl implements ErpProductUnitService { public void deleteProductUnit(Long id) { // 1.1 校验存在 validateProductUnitExists(id); - // 1.2 校验商品是否使用 + // 1.2 校验产品是否使用 if (productService.getProductCountByUnitId(id) > 0) { throw exception(PRODUCT_UNIT_EXITS_PRODUCT); } diff --git a/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/service/purchase/ErpPurchaseOrderService.java b/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/service/purchase/ErpPurchaseOrderService.java new file mode 100644 index 000000000..bfea076bb --- /dev/null +++ b/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/service/purchase/ErpPurchaseOrderService.java @@ -0,0 +1,110 @@ +package cn.iocoder.yudao.module.erp.service.purchase; + +import cn.iocoder.yudao.framework.common.pojo.PageResult; +import cn.iocoder.yudao.module.erp.controller.admin.purchase.vo.order.ErpPurchaseOrderPageReqVO; +import cn.iocoder.yudao.module.erp.controller.admin.purchase.vo.order.ErpPurchaseOrderSaveReqVO; +import cn.iocoder.yudao.module.erp.dal.dataobject.purchase.ErpPurchaseOrderDO; +import cn.iocoder.yudao.module.erp.dal.dataobject.purchase.ErpPurchaseOrderItemDO; +import jakarta.validation.Valid; + +import java.math.BigDecimal; +import java.util.Collection; +import java.util.List; +import java.util.Map; + +/** + * ERP 采购订单 Service 接口 + * + * @author 芋道源码 + */ +public interface ErpPurchaseOrderService { + + /** + * 创建采购订单 + * + * @param createReqVO 创建信息 + * @return 编号 + */ + Long createPurchaseOrder(@Valid ErpPurchaseOrderSaveReqVO createReqVO); + + /** + * 更新采购订单 + * + * @param updateReqVO 更新信息 + */ + void updatePurchaseOrder(@Valid ErpPurchaseOrderSaveReqVO updateReqVO); + + /** + * 更新采购订单的状态 + * + * @param id 编号 + * @param status 状态 + */ + void updatePurchaseOrderStatus(Long id, Integer status); + + /** + * 更新采购订单的入库数量 + * + * @param id 编号 + * @param inCountMap 入库数量 Map:key 采购订单项编号;value 入库数量 + */ + void updatePurchaseOrderInCount(Long id, Map inCountMap); + + /** + * 更新采购订单的退货数量 + * + * @param orderId 编号 + * @param returnCountMap 退货数量 Map:key 采购订单项编号;value 退货数量 + */ + void updatePurchaseOrderReturnCount(Long orderId, Map returnCountMap); + + /** + * 删除采购订单 + * + * @param ids 编号数组 + */ + void deletePurchaseOrder(List ids); + + /** + * 获得采购订单 + * + * @param id 编号 + * @return 采购订单 + */ + ErpPurchaseOrderDO getPurchaseOrder(Long id); + + /** + * 校验采购订单,已经审核通过 + * + * @param id 编号 + * @return 采购订单 + */ + ErpPurchaseOrderDO validatePurchaseOrder(Long id); + + /** + * 获得采购订单分页 + * + * @param pageReqVO 分页查询 + * @return 采购订单分页 + */ + PageResult getPurchaseOrderPage(ErpPurchaseOrderPageReqVO pageReqVO); + + // ==================== 采购订单项 ==================== + + /** + * 获得采购订单项列表 + * + * @param orderId 采购订单编号 + * @return 采购订单项列表 + */ + List getPurchaseOrderItemListByOrderId(Long orderId); + + /** + * 获得采购订单项 List + * + * @param orderIds 采购订单编号数组 + * @return 采购订单项 List + */ + List getPurchaseOrderItemListByOrderIds(Collection orderIds); + +} \ No newline at end of file diff --git a/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/service/purchase/ErpPurchaseOrderServiceImpl.java b/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/service/purchase/ErpPurchaseOrderServiceImpl.java new file mode 100644 index 000000000..f21d163c5 --- /dev/null +++ b/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/service/purchase/ErpPurchaseOrderServiceImpl.java @@ -0,0 +1,297 @@ +package cn.iocoder.yudao.module.erp.service.purchase; + +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.purchase.vo.order.ErpPurchaseOrderPageReqVO; +import cn.iocoder.yudao.module.erp.controller.admin.purchase.vo.order.ErpPurchaseOrderSaveReqVO; +import cn.iocoder.yudao.module.erp.dal.dataobject.product.ErpProductDO; +import cn.iocoder.yudao.module.erp.dal.dataobject.purchase.ErpPurchaseOrderDO; +import cn.iocoder.yudao.module.erp.dal.dataobject.purchase.ErpPurchaseOrderItemDO; +import cn.iocoder.yudao.module.erp.dal.mysql.purchase.ErpPurchaseOrderItemMapper; +import cn.iocoder.yudao.module.erp.dal.mysql.purchase.ErpPurchaseOrderMapper; +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 jakarta.annotation.Resource; +import org.springframework.stereotype.Service; +import org.springframework.transaction.annotation.Transactional; +import org.springframework.validation.annotation.Validated; + +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.exception.util.ServiceExceptionUtil.exception; +import static cn.iocoder.yudao.framework.common.util.collection.CollectionUtils.*; +import static cn.iocoder.yudao.module.erp.enums.ErrorCodeConstants.*; + +// TODO 芋艿:记录操作日志 + +/** + * ERP 采购订单 Service 实现类 + * + * @author 芋道源码 + */ +@Service +@Validated +public class ErpPurchaseOrderServiceImpl implements ErpPurchaseOrderService { + + @Resource + private ErpPurchaseOrderMapper purchaseOrderMapper; + @Resource + private ErpPurchaseOrderItemMapper purchaseOrderItemMapper; + + @Resource + private ErpNoRedisDAO noRedisDAO; + + @Resource + private ErpProductService productService; + @Resource + private ErpSupplierService supplierService; + @Resource + private ErpAccountService accountService; + + @Override + @Transactional(rollbackFor = Exception.class) + public Long createPurchaseOrder(ErpPurchaseOrderSaveReqVO createReqVO) { + // 1.1 校验订单项的有效性 + List purchaseOrderItems = validatePurchaseOrderItems(createReqVO.getItems()); + // 1.2 校验供应商 + supplierService.validateSupplier(createReqVO.getSupplierId()); + // 1.3 校验结算账户 + if (createReqVO.getAccountId() != null) { + accountService.validateAccount(createReqVO.getAccountId()); + } + // 1.4 生成调拨单号,并校验唯一性 + String no = noRedisDAO.generate(ErpNoRedisDAO.PURCHASE_ORDER_NO_PREFIX); + if (purchaseOrderMapper.selectByNo(no) != null) { + throw exception(PURCHASE_ORDER_NO_EXISTS); + } + + // 2.1 插入订单 + ErpPurchaseOrderDO purchaseOrder = BeanUtils.toBean(createReqVO, ErpPurchaseOrderDO.class, in -> in + .setNo(no).setStatus(ErpAuditStatus.PROCESS.getStatus())); + calculateTotalPrice(purchaseOrder, purchaseOrderItems); + purchaseOrderMapper.insert(purchaseOrder); + // 2.2 插入订单项 + purchaseOrderItems.forEach(o -> o.setOrderId(purchaseOrder.getId())); + purchaseOrderItemMapper.insertBatch(purchaseOrderItems); + return purchaseOrder.getId(); + } + + @Override + @Transactional(rollbackFor = Exception.class) + public void updatePurchaseOrder(ErpPurchaseOrderSaveReqVO updateReqVO) { + // 1.1 校验存在 + ErpPurchaseOrderDO purchaseOrder = validatePurchaseOrderExists(updateReqVO.getId()); + if (ErpAuditStatus.APPROVE.getStatus().equals(purchaseOrder.getStatus())) { + throw exception(PURCHASE_ORDER_UPDATE_FAIL_APPROVE, purchaseOrder.getNo()); + } + // 1.2 校验供应商 + supplierService.validateSupplier(updateReqVO.getSupplierId()); + // 1.3 校验结算账户 + if (updateReqVO.getAccountId() != null) { + accountService.validateAccount(updateReqVO.getAccountId()); + } + // 1.4 校验订单项的有效性 + List purchaseOrderItems = validatePurchaseOrderItems(updateReqVO.getItems()); + + // 2.1 更新订单 + ErpPurchaseOrderDO updateObj = BeanUtils.toBean(updateReqVO, ErpPurchaseOrderDO.class); + calculateTotalPrice(updateObj, purchaseOrderItems); + purchaseOrderMapper.updateById(updateObj); + // 2.2 更新订单项 + updatePurchaseOrderItemList(updateReqVO.getId(), purchaseOrderItems); + } + + private void calculateTotalPrice(ErpPurchaseOrderDO purchaseOrder, List purchaseOrderItems) { + purchaseOrder.setTotalCount(getSumValue(purchaseOrderItems, ErpPurchaseOrderItemDO::getCount, BigDecimal::add)); + purchaseOrder.setTotalProductPrice(getSumValue(purchaseOrderItems, ErpPurchaseOrderItemDO::getTotalPrice, BigDecimal::add, BigDecimal.ZERO)); + purchaseOrder.setTotalTaxPrice(getSumValue(purchaseOrderItems, ErpPurchaseOrderItemDO::getTaxPrice, BigDecimal::add, BigDecimal.ZERO)); + purchaseOrder.setTotalPrice(purchaseOrder.getTotalProductPrice().add(purchaseOrder.getTotalTaxPrice())); + // 计算优惠价格 + if (purchaseOrder.getDiscountPercent() == null) { + purchaseOrder.setDiscountPercent(BigDecimal.ZERO); + } + purchaseOrder.setDiscountPrice(MoneyUtils.priceMultiplyPercent(purchaseOrder.getTotalPrice(), purchaseOrder.getDiscountPercent())); + purchaseOrder.setTotalPrice(purchaseOrder.getTotalPrice().subtract(purchaseOrder.getDiscountPrice())); + } + + @Override + @Transactional(rollbackFor = Exception.class) + public void updatePurchaseOrderStatus(Long id, Integer status) { + boolean approve = ErpAuditStatus.APPROVE.getStatus().equals(status); + // 1.1 校验存在 + ErpPurchaseOrderDO purchaseOrder = validatePurchaseOrderExists(id); + // 1.2 校验状态 + if (purchaseOrder.getStatus().equals(status)) { + throw exception(approve ? PURCHASE_ORDER_APPROVE_FAIL : PURCHASE_ORDER_PROCESS_FAIL); + } + // 1.3 存在采购入单,无法反审核 + if (!approve && purchaseOrder.getInCount().compareTo(BigDecimal.ZERO) > 0) { + throw exception(PURCHASE_ORDER_PROCESS_FAIL_EXISTS_IN); + } + // 1.4 存在采购退货单,无法反审核 + if (!approve && purchaseOrder.getReturnCount().compareTo(BigDecimal.ZERO) > 0) { + throw exception(PURCHASE_ORDER_PROCESS_FAIL_EXISTS_RETURN); + } + + // 2. 更新状态 + int updateCount = purchaseOrderMapper.updateByIdAndStatus(id, purchaseOrder.getStatus(), + new ErpPurchaseOrderDO().setStatus(status)); + if (updateCount == 0) { + throw exception(approve ? PURCHASE_ORDER_APPROVE_FAIL : PURCHASE_ORDER_PROCESS_FAIL); + } + } + + private List validatePurchaseOrderItems(List list) { + // 1. 校验产品存在 + List productList = productService.validProductList( + convertSet(list, ErpPurchaseOrderSaveReqVO.Item::getProductId)); + Map productMap = convertMap(productList, ErpProductDO::getId); + // 2. 转化为 ErpPurchaseOrderItemDO 列表 + return convertList(list, o -> BeanUtils.toBean(o, ErpPurchaseOrderItemDO.class, item -> { + item.setProductUnitId(productMap.get(item.getProductId()).getUnitId()); + item.setTotalPrice(MoneyUtils.priceMultiply(item.getProductPrice(), item.getCount())); + if (item.getTotalPrice() == null) { + return; + } + if (item.getTaxPercent() == null) { + item.setTaxPercent(BigDecimal.ZERO); + } else { + item.setTaxPrice(MoneyUtils.priceMultiplyPercent(item.getTotalPrice(), item.getTaxPercent())); + } + })); + } + + private void updatePurchaseOrderItemList(Long id, List newList) { + // 第一步,对比新老数据,获得添加、修改、删除的列表 + List oldList = purchaseOrderItemMapper.selectListByOrderId(id); + List> diffList = diffList(oldList, newList, // id 不同,就认为是不同的记录 + (oldVal, newVal) -> oldVal.getId().equals(newVal.getId())); + + // 第二步,批量添加、修改、删除 + if (CollUtil.isNotEmpty(diffList.get(0))) { + diffList.get(0).forEach(o -> o.setOrderId(id)); + purchaseOrderItemMapper.insertBatch(diffList.get(0)); + } + if (CollUtil.isNotEmpty(diffList.get(1))) { + purchaseOrderItemMapper.updateBatch(diffList.get(1)); + } + if (CollUtil.isNotEmpty(diffList.get(2))) { + purchaseOrderItemMapper.deleteBatchIds(convertList(diffList.get(2), ErpPurchaseOrderItemDO::getId)); + } + } + + @Override + public void updatePurchaseOrderInCount(Long id, Map inCountMap) { + List orderItems = purchaseOrderItemMapper.selectListByOrderId(id); + // 1. 更新每个采购订单项 + orderItems.forEach(item -> { + BigDecimal inCount = inCountMap.getOrDefault(item.getId(), BigDecimal.ZERO); + if (item.getInCount().equals(inCount)) { + return; + } + if (inCount.compareTo(item.getCount()) > 0) { + throw exception(PURCHASE_ORDER_ITEM_IN_FAIL_PRODUCT_EXCEED, + productService.getProduct(item.getProductId()).getName(), item.getCount()); + } + purchaseOrderItemMapper.updateById(new ErpPurchaseOrderItemDO().setId(item.getId()).setInCount(inCount)); + }); + // 2. 更新采购订单 + BigDecimal totalInCount = getSumValue(inCountMap.values(), value -> value, BigDecimal::add, BigDecimal.ZERO); + purchaseOrderMapper.updateById(new ErpPurchaseOrderDO().setId(id).setInCount(totalInCount)); + } + + @Override + public void updatePurchaseOrderReturnCount(Long orderId, Map returnCountMap) { + List orderItems = purchaseOrderItemMapper.selectListByOrderId(orderId); + // 1. 更新每个采购订单项 + orderItems.forEach(item -> { + BigDecimal returnCount = returnCountMap.getOrDefault(item.getId(), BigDecimal.ZERO); + if (item.getReturnCount().equals(returnCount)) { + return; + } + if (returnCount.compareTo(item.getInCount()) > 0) { + throw exception(PURCHASE_ORDER_ITEM_RETURN_FAIL_IN_EXCEED, + productService.getProduct(item.getProductId()).getName(), item.getInCount()); + } + purchaseOrderItemMapper.updateById(new ErpPurchaseOrderItemDO().setId(item.getId()).setReturnCount(returnCount)); + }); + // 2. 更新采购订单 + BigDecimal totalReturnCount = getSumValue(returnCountMap.values(), value -> value, BigDecimal::add, BigDecimal.ZERO); + purchaseOrderMapper.updateById(new ErpPurchaseOrderDO().setId(orderId).setReturnCount(totalReturnCount)); + } + + @Override + @Transactional(rollbackFor = Exception.class) + public void deletePurchaseOrder(List ids) { + // 1. 校验不处于已审批 + List purchaseOrders = purchaseOrderMapper.selectBatchIds(ids); + if (CollUtil.isEmpty(purchaseOrders)) { + return; + } + purchaseOrders.forEach(purchaseOrder -> { + if (ErpAuditStatus.APPROVE.getStatus().equals(purchaseOrder.getStatus())) { + throw exception(PURCHASE_ORDER_DELETE_FAIL_APPROVE, purchaseOrder.getNo()); + } + }); + + // 2. 遍历删除,并记录操作日志 + purchaseOrders.forEach(purchaseOrder -> { + // 2.1 删除订单 + purchaseOrderMapper.deleteById(purchaseOrder.getId()); + // 2.2 删除订单项 + purchaseOrderItemMapper.deleteByOrderId(purchaseOrder.getId()); + }); + } + + private ErpPurchaseOrderDO validatePurchaseOrderExists(Long id) { + ErpPurchaseOrderDO purchaseOrder = purchaseOrderMapper.selectById(id); + if (purchaseOrder == null) { + throw exception(PURCHASE_ORDER_NOT_EXISTS); + } + return purchaseOrder; + } + + @Override + public ErpPurchaseOrderDO getPurchaseOrder(Long id) { + return purchaseOrderMapper.selectById(id); + } + + @Override + public ErpPurchaseOrderDO validatePurchaseOrder(Long id) { + ErpPurchaseOrderDO purchaseOrder = validatePurchaseOrderExists(id); + if (ObjectUtil.notEqual(purchaseOrder.getStatus(), ErpAuditStatus.APPROVE.getStatus())) { + throw exception(PURCHASE_ORDER_NOT_APPROVE); + } + return purchaseOrder; + } + + @Override + public PageResult getPurchaseOrderPage(ErpPurchaseOrderPageReqVO pageReqVO) { + return purchaseOrderMapper.selectPage(pageReqVO); + } + + // ==================== 订单项 ==================== + + @Override + public List getPurchaseOrderItemListByOrderId(Long orderId) { + return purchaseOrderItemMapper.selectListByOrderId(orderId); + } + + @Override + public List getPurchaseOrderItemListByOrderIds(Collection orderIds) { + if (CollUtil.isEmpty(orderIds)) { + return Collections.emptyList(); + } + return purchaseOrderItemMapper.selectListByOrderIds(orderIds); + } + +} \ No newline at end of file diff --git a/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/service/sale/ErpSaleReturnServiceImpl.java b/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/service/sale/ErpSaleReturnServiceImpl.java index e144e30bc..68f903a36 100644 --- a/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/service/sale/ErpSaleReturnServiceImpl.java +++ b/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/service/sale/ErpSaleReturnServiceImpl.java @@ -187,7 +187,7 @@ public class ErpSaleReturnServiceImpl implements ErpSaleReturnService { Integer bizType = approve ? ErpStockRecordBizTypeEnum.SALE_RETURN.getType() : ErpStockRecordBizTypeEnum.SALE_RETURN_CANCEL.getType(); saleReturnItems.forEach(saleReturnItem -> { - BigDecimal count = approve ? saleReturnItem.getCount().negate() : saleReturnItem.getCount(); + BigDecimal count = approve ? saleReturnItem.getCount() : saleReturnItem.getCount().negate(); stockRecordService.createStockRecord(new ErpStockRecordCreateReqBO( saleReturnItem.getProductId(), saleReturnItem.getWarehouseId(), count, bizType, saleReturnItem.getReturnId(), saleReturnItem.getId(), saleReturn.getNo())); From 5d092361edcbcb0bf3284bf72f77c25f8ab1f4d7 Mon Sep 17 00:00:00 2001 From: YunaiV Date: Mon, 12 Feb 2024 10:00:02 +0800 Subject: [PATCH 102/119] =?UTF-8?q?=E2=9C=A8=20ERP=EF=BC=9A=E5=9F=BA?= =?UTF-8?q?=E6=9C=AC=E5=AE=8C=E6=88=90=E9=87=87=E8=B4=AD=E8=AE=A2=E5=8D=95?= =?UTF-8?q?=20100%?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../purchase/vo/order/ErpPurchaseOrderRespVO.java | 12 ++++++------ .../dataobject/purchase/ErpPurchaseOrderItemDO.java | 4 ++-- .../purchase/ErpPurchaseOrderServiceImpl.java | 4 +--- .../erp/service/purchase/ErpSupplierServiceImpl.java | 4 ++-- .../erp/service/sale/ErpSaleOrderServiceImpl.java | 4 +--- .../erp/service/sale/ErpSaleOutServiceImpl.java | 4 +--- .../erp/service/sale/ErpSaleReturnServiceImpl.java | 4 +--- 7 files changed, 14 insertions(+), 22 deletions(-) diff --git a/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/controller/admin/purchase/vo/order/ErpPurchaseOrderRespVO.java b/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/controller/admin/purchase/vo/order/ErpPurchaseOrderRespVO.java index fb3ac63df..bc76720ee 100644 --- a/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/controller/admin/purchase/vo/order/ErpPurchaseOrderRespVO.java +++ b/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/controller/admin/purchase/vo/order/ErpPurchaseOrderRespVO.java @@ -87,10 +87,10 @@ public class ErpPurchaseOrderRespVO { @ExcelProperty("产品信息") private String productNames; - // ========== 采购出库 ========== + // ========== 采购入库 ========== - @Schema(description = "采购出库数量", requiredMode = Schema.RequiredMode.REQUIRED, example = "100.00") - private BigDecimal outCount; + @Schema(description = "采购入库数量", requiredMode = Schema.RequiredMode.REQUIRED, example = "100.00") + private BigDecimal inCount; // ========== 采购退货(出库)) ========== @@ -125,10 +125,10 @@ public class ErpPurchaseOrderRespVO { @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 inCount; // ========== 采购退货(入库)) ========== diff --git a/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/dal/dataobject/purchase/ErpPurchaseOrderItemDO.java b/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/dal/dataobject/purchase/ErpPurchaseOrderItemDO.java index 52930b58f..aa54d336b 100644 --- a/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/dal/dataobject/purchase/ErpPurchaseOrderItemDO.java +++ b/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/dal/dataobject/purchase/ErpPurchaseOrderItemDO.java @@ -14,8 +14,8 @@ import java.math.BigDecimal; * * @author 芋道源码 */ -@TableName("erp_sale_order_items") -@KeySequence("erp_sale_order_items_seq") // 用于 Oracle、PostgreSQL、Kingbase、DB2、H2 数据库的主键自增。如果是 MySQL 等数据库,可不写。 +@TableName("erp_purchase_order_items") +@KeySequence("erp_purchase_order_items_seq") // 用于 Oracle、PostgreSQL、Kingbase、DB2、H2 数据库的主键自增。如果是 MySQL 等数据库,可不写。 @Data @EqualsAndHashCode(callSuper = true) @ToString(callSuper = true) diff --git a/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/service/purchase/ErpPurchaseOrderServiceImpl.java b/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/service/purchase/ErpPurchaseOrderServiceImpl.java index f21d163c5..0c0790734 100644 --- a/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/service/purchase/ErpPurchaseOrderServiceImpl.java +++ b/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/service/purchase/ErpPurchaseOrderServiceImpl.java @@ -162,9 +162,7 @@ public class ErpPurchaseOrderServiceImpl implements ErpPurchaseOrderService { if (item.getTotalPrice() == null) { return; } - if (item.getTaxPercent() == null) { - item.setTaxPercent(BigDecimal.ZERO); - } else { + if (item.getTaxPercent() != null) { item.setTaxPrice(MoneyUtils.priceMultiplyPercent(item.getTotalPrice(), item.getTaxPercent())); } })); diff --git a/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/service/purchase/ErpSupplierServiceImpl.java b/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/service/purchase/ErpSupplierServiceImpl.java index c862a84da..1c90ff3f6 100644 --- a/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/service/purchase/ErpSupplierServiceImpl.java +++ b/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/service/purchase/ErpSupplierServiceImpl.java @@ -68,10 +68,10 @@ public class ErpSupplierServiceImpl implements ErpSupplierService { public ErpSupplierDO validateSupplier(Long id) { ErpSupplierDO supplier = supplierMapper.selectById(id); if (supplier == null) { - throw exception(WAREHOUSE_NOT_EXISTS); + throw exception(SUPPLIER_NOT_EXISTS); } if (CommonStatusEnum.isDisable(supplier.getStatus())) { - throw exception(WAREHOUSE_NOT_ENABLE, supplier.getName()); + throw exception(SUPPLIER_NOT_ENABLE, supplier.getName()); } return supplier; } diff --git a/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/service/sale/ErpSaleOrderServiceImpl.java b/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/service/sale/ErpSaleOrderServiceImpl.java index c19d8be57..03b51125c 100644 --- a/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/service/sale/ErpSaleOrderServiceImpl.java +++ b/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/service/sale/ErpSaleOrderServiceImpl.java @@ -174,9 +174,7 @@ public class ErpSaleOrderServiceImpl implements ErpSaleOrderService { if (item.getTotalPrice() == null) { return; } - if (item.getTaxPercent() == null) { - item.setTaxPercent(BigDecimal.ZERO); - } else { + if (item.getTaxPercent() != null) { item.setTaxPrice(MoneyUtils.priceMultiplyPercent(item.getTotalPrice(), item.getTaxPercent())); } })); diff --git a/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/service/sale/ErpSaleOutServiceImpl.java b/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/service/sale/ErpSaleOutServiceImpl.java index db5dcca71..03743f0bd 100644 --- a/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/service/sale/ErpSaleOutServiceImpl.java +++ b/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/service/sale/ErpSaleOutServiceImpl.java @@ -206,9 +206,7 @@ public class ErpSaleOutServiceImpl implements ErpSaleOutService { if (item.getTotalPrice() == null) { return; } - if (item.getTaxPercent() == null) { - item.setTaxPercent(BigDecimal.ZERO); - } else { + if (item.getTaxPercent() != null) { item.setTaxPrice(MoneyUtils.priceMultiplyPercent(item.getTotalPrice(), item.getTaxPercent())); } })); diff --git a/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/service/sale/ErpSaleReturnServiceImpl.java b/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/service/sale/ErpSaleReturnServiceImpl.java index 68f903a36..eaea5c00e 100644 --- a/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/service/sale/ErpSaleReturnServiceImpl.java +++ b/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/service/sale/ErpSaleReturnServiceImpl.java @@ -206,9 +206,7 @@ public class ErpSaleReturnServiceImpl implements ErpSaleReturnService { if (item.getTotalPrice() == null) { return; } - if (item.getTaxPercent() == null) { - item.setTaxPercent(BigDecimal.ZERO); - } else { + if (item.getTaxPercent() != null) { item.setTaxPrice(MoneyUtils.priceMultiplyPercent(item.getTotalPrice(), item.getTaxPercent())); } })); From 0599f5392c6f9552b81cbc7929d87c5a0ebe36d2 Mon Sep 17 00:00:00 2001 From: YunaiV Date: Mon, 12 Feb 2024 10:42:23 +0800 Subject: [PATCH 103/119] =?UTF-8?q?=E2=9C=A8=20ERP=EF=BC=9A=E9=87=87?= =?UTF-8?q?=E8=B4=AD=E5=85=A5=E5=BA=93=2050%?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../module/erp/enums/ErrorCodeConstants.java | 8 + .../stock/ErpStockRecordBizTypeEnum.java | 3 + .../purchase/ErpPurchaseInController.java | 165 ++++++++++ .../vo/in/ErpPurchaseInPageReqVO.java | 54 ++++ .../purchase/vo/in/ErpPurchaseInRespVO.java | 148 +++++++++ .../vo/in/ErpPurchaseInSaveReqVO.java | 85 ++++++ .../dataobject/purchase/ErpPurchaseInDO.java | 127 ++++++++ .../purchase/ErpPurchaseInItemDO.java | 95 ++++++ .../purchase/ErpPurchaseInItemMapper.java | 56 ++++ .../mysql/purchase/ErpPurchaseInMapper.java | 62 ++++ .../erp/dal/redis/no/ErpNoRedisDAO.java | 4 + .../purchase/ErpPurchaseInService.java | 84 +++++ .../purchase/ErpPurchaseInServiceImpl.java | 286 ++++++++++++++++++ 13 files changed, 1177 insertions(+) create mode 100644 yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/controller/admin/purchase/ErpPurchaseInController.java create mode 100644 yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/controller/admin/purchase/vo/in/ErpPurchaseInPageReqVO.java create mode 100644 yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/controller/admin/purchase/vo/in/ErpPurchaseInRespVO.java create mode 100644 yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/controller/admin/purchase/vo/in/ErpPurchaseInSaveReqVO.java create mode 100644 yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/dal/dataobject/purchase/ErpPurchaseInDO.java create mode 100644 yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/dal/dataobject/purchase/ErpPurchaseInItemDO.java create mode 100644 yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/dal/mysql/purchase/ErpPurchaseInItemMapper.java create mode 100644 yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/dal/mysql/purchase/ErpPurchaseInMapper.java create mode 100644 yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/service/purchase/ErpPurchaseInService.java create mode 100644 yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/service/purchase/ErpPurchaseInServiceImpl.java diff --git a/yudao-module-erp/yudao-module-erp-api/src/main/java/cn/iocoder/yudao/module/erp/enums/ErrorCodeConstants.java b/yudao-module-erp/yudao-module-erp-api/src/main/java/cn/iocoder/yudao/module/erp/enums/ErrorCodeConstants.java index 5ad887abd..b3133d63d 100644 --- a/yudao-module-erp/yudao-module-erp-api/src/main/java/cn/iocoder/yudao/module/erp/enums/ErrorCodeConstants.java +++ b/yudao-module-erp/yudao-module-erp-api/src/main/java/cn/iocoder/yudao/module/erp/enums/ErrorCodeConstants.java @@ -26,6 +26,14 @@ public interface ErrorCodeConstants { ErrorCode PURCHASE_ORDER_ITEM_RETURN_FAIL_IN_EXCEED = new ErrorCode(1_030_101_009, "采购订单项({})超过最大允许退货数量({})"); ErrorCode PURCHASE_ORDER_PROCESS_FAIL_EXISTS_RETURN = new ErrorCode(1_030_101_010, "反审核失败,已存在对应的采购退货单"); + // ========== ERP 采购入库(1-030-102-000) ========== + ErrorCode PURCHASE_IN_NOT_EXISTS = new ErrorCode(1_030_102_000, "采购入库单不存在"); + ErrorCode PURCHASE_IN_DELETE_FAIL_APPROVE = new ErrorCode(1_030_102_001, "采购入库单({})已审核,无法删除"); + ErrorCode PURCHASE_IN_PROCESS_FAIL = new ErrorCode(1_030_102_002, "反审核失败,只有已审核的入库单才能反审核"); + ErrorCode PURCHASE_IN_APPROVE_FAIL = new ErrorCode(1_030_102_003, "审核失败,只有未审核的入库单才能审核"); + ErrorCode PURCHASE_IN_NO_EXISTS = new ErrorCode(1_030_102_004, "生成入库单失败,请重新提交"); + ErrorCode PURCHASE_IN_UPDATE_FAIL_APPROVE = new ErrorCode(1_030_102_005, "采购入库单({})已审核,无法修改"); + // ========== ERP 客户(1-030-200-000)========== ErrorCode CUSTOMER_NOT_EXISTS = new ErrorCode(1_020_200_000, "客户不存在"); ErrorCode CUSTOMER_NOT_ENABLE = new ErrorCode(1_020_200_001, "客户({})未启用"); diff --git a/yudao-module-erp/yudao-module-erp-api/src/main/java/cn/iocoder/yudao/module/erp/enums/stock/ErpStockRecordBizTypeEnum.java b/yudao-module-erp/yudao-module-erp-api/src/main/java/cn/iocoder/yudao/module/erp/enums/stock/ErpStockRecordBizTypeEnum.java index 05379ba9f..af8c4ded9 100644 --- a/yudao-module-erp/yudao-module-erp-api/src/main/java/cn/iocoder/yudao/module/erp/enums/stock/ErpStockRecordBizTypeEnum.java +++ b/yudao-module-erp/yudao-module-erp-api/src/main/java/cn/iocoder/yudao/module/erp/enums/stock/ErpStockRecordBizTypeEnum.java @@ -36,6 +36,9 @@ public enum ErpStockRecordBizTypeEnum implements IntArrayValuable { SALE_RETURN(60, "销售退货入库"), SALE_RETURN_CANCEL(61, "销售退货入库(作废)"), + + PURCHASE_IN(70, "采购入库"), + PURCHASE_IN_CANCEL(71, "采购入库(作废)"), ; public static final int[] ARRAYS = Arrays.stream(values()).mapToInt(ErpStockRecordBizTypeEnum::getType).toArray(); diff --git a/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/controller/admin/purchase/ErpPurchaseInController.java b/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/controller/admin/purchase/ErpPurchaseInController.java new file mode 100644 index 000000000..91f321a1e --- /dev/null +++ b/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/controller/admin/purchase/ErpPurchaseInController.java @@ -0,0 +1,165 @@ +package cn.iocoder.yudao.module.erp.controller.admin.purchase; + +import cn.hutool.core.collection.CollUtil; +import cn.iocoder.yudao.framework.common.pojo.CommonResult; +import cn.iocoder.yudao.framework.common.pojo.PageParam; +import cn.iocoder.yudao.framework.common.pojo.PageResult; +import cn.iocoder.yudao.framework.common.util.collection.MapUtils; +import cn.iocoder.yudao.framework.common.util.object.BeanUtils; +import cn.iocoder.yudao.framework.excel.core.util.ExcelUtils; +import cn.iocoder.yudao.framework.operatelog.core.annotations.OperateLog; +import cn.iocoder.yudao.module.erp.controller.admin.product.vo.product.ErpProductRespVO; +import cn.iocoder.yudao.module.erp.controller.admin.purchase.vo.in.ErpPurchaseInPageReqVO; +import cn.iocoder.yudao.module.erp.controller.admin.purchase.vo.in.ErpPurchaseInRespVO; +import cn.iocoder.yudao.module.erp.controller.admin.purchase.vo.in.ErpPurchaseInSaveReqVO; +import cn.iocoder.yudao.module.erp.dal.dataobject.purchase.ErpPurchaseInDO; +import cn.iocoder.yudao.module.erp.dal.dataobject.purchase.ErpPurchaseInItemDO; +import cn.iocoder.yudao.module.erp.dal.dataobject.purchase.ErpSupplierDO; +import cn.iocoder.yudao.module.erp.dal.dataobject.stock.ErpStockDO; +import cn.iocoder.yudao.module.erp.service.product.ErpProductService; +import cn.iocoder.yudao.module.erp.service.purchase.ErpPurchaseInService; +import cn.iocoder.yudao.module.erp.service.purchase.ErpSupplierService; +import cn.iocoder.yudao.module.erp.service.stock.ErpStockService; +import cn.iocoder.yudao.module.system.api.user.AdminUserApi; +import cn.iocoder.yudao.module.system.api.user.dto.AdminUserRespDTO; +import io.swagger.v3.oas.annotations.Operation; +import io.swagger.v3.oas.annotations.Parameter; +import io.swagger.v3.oas.annotations.tags.Tag; +import jakarta.annotation.Resource; +import jakarta.servlet.http.HttpServletResponse; +import jakarta.validation.Valid; +import org.springframework.security.access.prepost.PreAuthorize; +import org.springframework.validation.annotation.Validated; +import org.springframework.web.bind.annotation.*; + +import java.io.IOException; +import java.math.BigDecimal; +import java.util.List; +import java.util.Map; + +import static cn.iocoder.yudao.framework.common.pojo.CommonResult.success; +import static cn.iocoder.yudao.framework.common.util.collection.CollectionUtils.convertMultiMap; +import static cn.iocoder.yudao.framework.common.util.collection.CollectionUtils.convertSet; +import static cn.iocoder.yudao.framework.operatelog.core.enums.OperateTypeEnum.EXPORT; + +@Tag(name = "管理后台 - ERP 采购入库") +@RestController +@RequestMapping("/erp/purchase-in") +@Validated +public class ErpPurchaseInController { + + @Resource + private ErpPurchaseInService purchaseInService; + @Resource + private ErpStockService stockService; + @Resource + private ErpProductService productService; + @Resource + private ErpSupplierService supplierService; + + @Resource + private AdminUserApi adminUserApi; + + @PostMapping("/create") + @Operation(summary = "创建采购入库") + @PreAuthorize("@ss.hasPermission('erp:purchase-in:create')") + public CommonResult createPurchaseIn(@Valid @RequestBody ErpPurchaseInSaveReqVO createReqVO) { + return success(purchaseInService.createPurchaseIn(createReqVO)); + } + + @PutMapping("/update") + @Operation(summary = "更新采购入库") + @PreAuthorize("@ss.hasPermission('erp:purchase-in:update')") + public CommonResult updatePurchaseIn(@Valid @RequestBody ErpPurchaseInSaveReqVO updateReqVO) { + purchaseInService.updatePurchaseIn(updateReqVO); + return success(true); + } + + @PutMapping("/update-status") + @Operation(summary = "更新采购入库的状态") + @PreAuthorize("@ss.hasPermission('erp:purchase-in:update-status')") + public CommonResult updatePurchaseInStatus(@RequestParam("id") Long id, + @RequestParam("status") Integer status) { + purchaseInService.updatePurchaseInStatus(id, status); + return success(true); + } + + @DeleteMapping("/delete") + @Operation(summary = "删除采购入库") + @Parameter(name = "ids", description = "编号数组", required = true) + @PreAuthorize("@ss.hasPermission('erp:purchase-in:delete')") + public CommonResult deletePurchaseIn(@RequestParam("ids") List ids) { + purchaseInService.deletePurchaseIn(ids); + return success(true); + } + + @GetMapping("/get") + @Operation(summary = "获得采购入库") + @Parameter(name = "id", description = "编号", required = true, example = "1024") + @PreAuthorize("@ss.hasPermission('erp:purchase-in:query')") + public CommonResult getPurchaseIn(@RequestParam("id") Long id) { + ErpPurchaseInDO purchaseIn = purchaseInService.getPurchaseIn(id); + if (purchaseIn == null) { + return success(null); + } + List purchaseInItemList = purchaseInService.getPurchaseInItemListByInId(id); + Map productMap = productService.getProductVOMap( + convertSet(purchaseInItemList, ErpPurchaseInItemDO::getProductId)); + return success(BeanUtils.toBean(purchaseIn, ErpPurchaseInRespVO.class, purchaseInVO -> + purchaseInVO.setItems(BeanUtils.toBean(purchaseInItemList, ErpPurchaseInRespVO.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") + @Operation(summary = "获得采购入库分页") + @PreAuthorize("@ss.hasPermission('erp:purchase-in:query')") + public CommonResult> getPurchaseInPage(@Valid ErpPurchaseInPageReqVO pageReqVO) { + PageResult pageResult = purchaseInService.getPurchaseInPage(pageReqVO); + return success(buildPurchaseInVOPageResult(pageResult)); + } + + @GetMapping("/export-excel") + @Operation(summary = "导出采购入库 Excel") + @PreAuthorize("@ss.hasPermission('erp:purchase-in:export')") + @OperateLog(type = EXPORT) + public void exportPurchaseInExcel(@Valid ErpPurchaseInPageReqVO pageReqVO, + HttpServletResponse response) throws IOException { + pageReqVO.setPageSize(PageParam.PAGE_SIZE_NONE); + List list = buildPurchaseInVOPageResult(purchaseInService.getPurchaseInPage(pageReqVO)).getList(); + // 导出 Excel + ExcelUtils.write(response, "采购入库.xls", "数据", ErpPurchaseInRespVO.class, list); + } + + private PageResult buildPurchaseInVOPageResult(PageResult pageResult) { + if (CollUtil.isEmpty(pageResult.getList())) { + return PageResult.empty(pageResult.getTotal()); + } + // 1.1 出库项 + List purchaseInItemList = purchaseInService.getPurchaseInItemListByInIds( + convertSet(pageResult.getList(), ErpPurchaseInDO::getId)); + Map> purchaseInItemMap = convertMultiMap(purchaseInItemList, ErpPurchaseInItemDO::getInId); + // 1.2 产品信息 + Map productMap = productService.getProductVOMap( + convertSet(purchaseInItemList, ErpPurchaseInItemDO::getProductId)); + // 1.3 供应商信息 + Map supplierMap = supplierService.getSupplierMap( + convertSet(pageResult.getList(), ErpPurchaseInDO::getSupplierId)); + // 1.4 管理员信息 + Map userMap = adminUserApi.getUserMap( + convertSet(pageResult.getList(), erpStockRecordDO -> Long.parseLong(erpStockRecordDO.getCreator()))); + // 2. 开始拼接 + return BeanUtils.toBean(pageResult, ErpPurchaseInRespVO.class, purchaseIn -> { + purchaseIn.setItems(BeanUtils.toBean(purchaseInItemMap.get(purchaseIn.getId()), ErpPurchaseInRespVO.Item.class, + item -> MapUtils.findAndThen(productMap, item.getProductId(), product -> item.setProductName(product.getName()) + .setProductBarCode(product.getBarCode()).setProductUnitName(product.getUnitName())))); + purchaseIn.setProductNames(CollUtil.join(purchaseIn.getItems(), ",", ErpPurchaseInRespVO.Item::getProductName)); + MapUtils.findAndThen(supplierMap, purchaseIn.getSupplierId(), supplier -> purchaseIn.setSupplierName(supplier.getName())); + MapUtils.findAndThen(userMap, Long.parseLong(purchaseIn.getCreator()), user -> purchaseIn.setCreatorName(user.getNickname())); + }); + } + +} \ No newline at end of file diff --git a/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/controller/admin/purchase/vo/in/ErpPurchaseInPageReqVO.java b/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/controller/admin/purchase/vo/in/ErpPurchaseInPageReqVO.java new file mode 100644 index 000000000..2be52e5ff --- /dev/null +++ b/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/controller/admin/purchase/vo/in/ErpPurchaseInPageReqVO.java @@ -0,0 +1,54 @@ +package cn.iocoder.yudao.module.erp.controller.admin.purchase.vo.in; + +import cn.iocoder.yudao.framework.common.pojo.PageParam; +import io.swagger.v3.oas.annotations.media.Schema; +import lombok.Data; +import lombok.EqualsAndHashCode; +import lombok.ToString; +import org.springframework.format.annotation.DateTimeFormat; + +import java.time.LocalDateTime; + +import static cn.iocoder.yudao.framework.common.util.date.DateUtils.FORMAT_YEAR_MONTH_DAY_HOUR_MINUTE_SECOND; + +@Schema(description = "管理后台 - ERP 采购入库分页 Request VO") +@Data +@EqualsAndHashCode(callSuper = true) +@ToString(callSuper = true) +public class ErpPurchaseInPageReqVO extends PageParam { + + @Schema(description = "采购单编号", example = "XS001") + private String no; + + @Schema(description = "供应商编号", example = "1724") + private Long supplierId; + + @Schema(description = "入库时间") + @DateTimeFormat(pattern = FORMAT_YEAR_MONTH_DAY_HOUR_MINUTE_SECOND) + private LocalDateTime[] inTime; + + @Schema(description = "备注", example = "你猜") + private String remark; + + @Schema(description = "入库状态", example = "2") + private Integer status; + + @Schema(description = "创建者") + private String creator; + + @Schema(description = "产品编号", example = "1") + private Long productId; + + @Schema(description = "仓库编号", example = "1") + private Long warehouseId; + + @Schema(description = "结算账号编号", example = "1") + private Long accountId; + + @Schema(description = "是否欠款", example = "true") + private Boolean debtStatus; + + @Schema(description = "采购单号", example = "1") + private String orderNo; + +} \ No newline at end of file diff --git a/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/controller/admin/purchase/vo/in/ErpPurchaseInRespVO.java b/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/controller/admin/purchase/vo/in/ErpPurchaseInRespVO.java new file mode 100644 index 000000000..ce16cf57a --- /dev/null +++ b/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/controller/admin/purchase/vo/in/ErpPurchaseInRespVO.java @@ -0,0 +1,148 @@ +package cn.iocoder.yudao.module.erp.controller.admin.purchase.vo.in; + +import com.alibaba.excel.annotation.ExcelIgnoreUnannotated; +import com.alibaba.excel.annotation.ExcelProperty; +import io.swagger.v3.oas.annotations.media.Schema; +import jakarta.validation.constraints.NotNull; +import lombok.Data; + +import java.math.BigDecimal; +import java.time.LocalDateTime; +import java.util.List; + +@Schema(description = "管理后台 - ERP 采购入库 Response VO") +@Data +@ExcelIgnoreUnannotated +public class ErpPurchaseInRespVO { + + @Schema(description = "编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "17386") + @ExcelProperty("编号") + private Long id; + + @Schema(description = "入库单编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "XS001") + @ExcelProperty("入库单编号") + private String no; + + @Schema(description = "入库状态", requiredMode = Schema.RequiredMode.REQUIRED, example = "2") + @ExcelProperty("入库状态") + private Integer status; + + @Schema(description = "供应商编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "1724") + private Long supplierId; + @Schema(description = "供应商名称", example = "芋道") + @ExcelProperty("供应商名称") + private String supplierName; + + @Schema(description = "结算账户编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "311.89") + @ExcelProperty("结算账户编号") + private Long accountId; + + @Schema(description = "入库时间", requiredMode = Schema.RequiredMode.REQUIRED) + @ExcelProperty("入库时间") + private LocalDateTime inTime; + + @Schema(description = "采购订单编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "17386") + private Long orderId; + @Schema(description = "采购订单号", requiredMode = Schema.RequiredMode.REQUIRED, example = "XS001") + private String orderNo; + + @Schema(description = "合计数量", requiredMode = Schema.RequiredMode.REQUIRED, example = "15663") + @ExcelProperty("合计数量") + private BigDecimal totalCount; + @Schema(description = "最终合计价格", requiredMode = Schema.RequiredMode.REQUIRED, example = "24906") + @ExcelProperty("最终合计价格") + private BigDecimal totalPrice; + + @Schema(description = "合计产品价格,单位:元", requiredMode = Schema.RequiredMode.REQUIRED, example = "7127") + private BigDecimal totalProductPrice; + + @Schema(description = "合计税额,单位:元", requiredMode = Schema.RequiredMode.REQUIRED, example = "7127") + private BigDecimal totalTaxPrice; + + @Schema(description = "优惠率,百分比", requiredMode = Schema.RequiredMode.REQUIRED, example = "99.88") + private BigDecimal discountPercent; + + @Schema(description = "优惠金额,单位:元", requiredMode = Schema.RequiredMode.REQUIRED, example = "7127") + private BigDecimal discountPrice; + + @Schema(description = "定金金额,单位:元", requiredMode = Schema.RequiredMode.REQUIRED, example = "7127") + private BigDecimal otherPrice; + + @Schema(description = "本次收款,单位:元", requiredMode = Schema.RequiredMode.REQUIRED, example = "7127") + private BigDecimal payPrice; + @Schema(description = "本次欠款,单位:元", requiredMode = Schema.RequiredMode.REQUIRED, example = "666") + private BigDecimal debtPrice; + + @Schema(description = "附件地址", example = "https://www.iocoder.cn") + @ExcelProperty("附件地址") + private String fileUrl; + + @Schema(description = "备注", example = "你猜") + @ExcelProperty("备注") + private String remark; + + @Schema(description = "创建人", example = "芋道") + private String creator; + @Schema(description = "创建人名称", example = "芋道") + private String creatorName; + + @Schema(description = "创建时间", requiredMode = Schema.RequiredMode.REQUIRED) + @ExcelProperty("创建时间") + private LocalDateTime createTime; + + @Schema(description = "入库项列表", requiredMode = Schema.RequiredMode.REQUIRED) + private List items; + + @Schema(description = "产品信息", requiredMode = Schema.RequiredMode.REQUIRED) + @ExcelProperty("产品信息") + private String productNames; + + @Data + public static class Item { + + @Schema(description = "入库项编号", example = "11756") + private Long id; + + @Schema(description = "采购订单项编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "11756") + private Long orderItemId; + + @Schema(description = "仓库编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "3113") + private Long warehouseId; + + @Schema(description = "产品编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "3113") + private Long productId; + + @Schema(description = "产品单位单位", requiredMode = Schema.RequiredMode.REQUIRED, example = "3113") + private Long productUnitId; + + @Schema(description = "产品单价", example = "100.00") + private BigDecimal productPrice; + + @Schema(description = "产品数量", requiredMode = Schema.RequiredMode.REQUIRED, example = "100.00") + @NotNull(message = "产品数量不能为空") + private BigDecimal count; + + @Schema(description = "税率,百分比", example = "99.88") + private BigDecimal taxPercent; + + @Schema(description = "税额,单位:元", example = "100.00") + private BigDecimal taxPrice; + + @Schema(description = "备注", example = "随便") + private String remark; + + // ========== 关联字段 ========== + + @Schema(description = "产品名称", requiredMode = Schema.RequiredMode.REQUIRED, example = "巧克力") + private String productName; + @Schema(description = "产品条码", requiredMode = Schema.RequiredMode.REQUIRED, example = "A9985") + private String productBarCode; + @Schema(description = "产品单位名称", requiredMode = Schema.RequiredMode.REQUIRED, example = "盒") + private String productUnitName; + + @Schema(description = "库存数量", requiredMode = Schema.RequiredMode.REQUIRED, example = "100.00") + private BigDecimal stockCount; // 该字段仅仅在“详情”和“编辑”时使用 + + } + +} \ No newline at end of file diff --git a/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/controller/admin/purchase/vo/in/ErpPurchaseInSaveReqVO.java b/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/controller/admin/purchase/vo/in/ErpPurchaseInSaveReqVO.java new file mode 100644 index 000000000..dd1543d5b --- /dev/null +++ b/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/controller/admin/purchase/vo/in/ErpPurchaseInSaveReqVO.java @@ -0,0 +1,85 @@ +package cn.iocoder.yudao.module.erp.controller.admin.purchase.vo.in; + +import io.swagger.v3.oas.annotations.media.Schema; +import jakarta.validation.constraints.NotNull; +import lombok.Data; + +import java.math.BigDecimal; +import java.time.LocalDateTime; +import java.util.List; + +@Schema(description = "管理后台 - ERP 采购入库新增/修改 Request VO") +@Data +public class ErpPurchaseInSaveReqVO { + + @Schema(description = "编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "17386") + private Long id; + + @Schema(description = "结算账户编号", example = "31189") + private Long accountId; + + @Schema(description = "入库时间", requiredMode = Schema.RequiredMode.REQUIRED) + @NotNull(message = "入库时间不能为空") + private LocalDateTime inTime; + + @Schema(description = "采购订单编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "17386") + @NotNull(message = "采购订单编号不能为空") + private Long orderId; + + @Schema(description = "优惠率,百分比", requiredMode = Schema.RequiredMode.REQUIRED, example = "99.88") + private BigDecimal discountPercent; + + @Schema(description = "其它金额,单位:元", example = "7127") + private BigDecimal otherPrice; + + @Schema(description = "本次收款,单位:元", requiredMode = Schema.RequiredMode.REQUIRED, example = "7127") + @NotNull(message = "本次收款不能为空") + private BigDecimal payPrice; + + @Schema(description = "附件地址", example = "https://www.iocoder.cn") + private String fileUrl; + + @Schema(description = "备注", example = "你猜") + private String remark; + + @Schema(description = "入库清单列表") + private List items; + + @Data + public static class Item { + + @Schema(description = "入库项编号", example = "11756") + private Long id; + + @Schema(description = "采购订单项编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "11756") + @NotNull(message = "采购订单项编号不能为空") + private Long orderItemId; + + @Schema(description = "仓库编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "3113") + @NotNull(message = "仓库编号不能为空") + private Long warehouseId; + + @Schema(description = "产品编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "3113") + @NotNull(message = "产品编号不能为空") + private Long productId; + + @Schema(description = "产品单位单位", requiredMode = Schema.RequiredMode.REQUIRED, example = "3113") + @NotNull(message = "产品单位单位不能为空") + private Long productUnitId; + + @Schema(description = "产品单价", example = "100.00") + private BigDecimal productPrice; + + @Schema(description = "产品数量", requiredMode = Schema.RequiredMode.REQUIRED, example = "100.00") + @NotNull(message = "产品数量不能为空") + private BigDecimal count; + + @Schema(description = "税率,百分比", example = "99.88") + private BigDecimal taxPercent; + + @Schema(description = "备注", example = "随便") + private String remark; + + } + +} \ No newline at end of file diff --git a/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/dal/dataobject/purchase/ErpPurchaseInDO.java b/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/dal/dataobject/purchase/ErpPurchaseInDO.java new file mode 100644 index 000000000..7fd4c1c4e --- /dev/null +++ b/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/dal/dataobject/purchase/ErpPurchaseInDO.java @@ -0,0 +1,127 @@ +package cn.iocoder.yudao.module.erp.dal.dataobject.purchase; + +import cn.iocoder.yudao.framework.mybatis.core.dataobject.BaseDO; +import cn.iocoder.yudao.module.erp.dal.dataobject.finance.ErpAccountDO; +import com.baomidou.mybatisplus.annotation.KeySequence; +import com.baomidou.mybatisplus.annotation.TableId; +import com.baomidou.mybatisplus.annotation.TableName; +import lombok.*; + +import java.math.BigDecimal; +import java.time.LocalDateTime; + +/** + * ERP 采购入库 DO + * + * @author 芋道源码 + */ +@TableName(value = "erp_purchase_in") +@KeySequence("erp_purchase_in_seq") // 用于 Oracle、PostgreSQL、Kingbase、DB2、H2 数据库的主键自增。如果是 MySQL 等数据库,可不写。 +@Data +@EqualsAndHashCode(callSuper = true) +@ToString(callSuper = true) +@Builder +@NoArgsConstructor +@AllArgsConstructor +public class ErpPurchaseInDO extends BaseDO { + + /** + * 编号 + */ + @TableId + private Long id; + /** + * 销售入库单号 + */ + private String no; + /** + * 入库状态 + * + * 枚举 {@link cn.iocoder.yudao.module.erp.enums.ErpAuditStatus} + */ + private Integer status; + /** + * 供应商编号 + * + * 关联 {@link ErpSupplierDO#getId()} + */ + private Long supplierId; + /** + * 结算账户编号 + * + * 关联 {@link ErpAccountDO#getId()} + */ + private Long accountId; + /** + * 入库时间 + */ + private LocalDateTime inTime; + + /** + * 采购订单编号 + * + * 关联 {@link ErpPurchaseOrderDO#getId()} + */ + private Long orderId; + /** + * 采购订单号 + * + * 冗余 {@link ErpPurchaseOrderDO#getNo()} + */ + private String orderNo; + + /** + * 合计数量 + */ + private BigDecimal totalCount; + /** + * 最终合计价格,单位:元 + * + * totalPrice = totalProductPrice + totalTaxPrice - discountPrice + */ + private BigDecimal totalPrice; + + /** + * 合计产品价格,单位:元 + */ + private BigDecimal totalProductPrice; + /** + * 合计税额,单位:元 + */ + private BigDecimal totalTaxPrice; + /** + * 优惠率,百分比 + */ + private BigDecimal discountPercent; + /** + * 优惠金额,单位:元 + * + * discountPrice = (totalProductPrice + totalTaxPrice) * discountPercent + */ + private BigDecimal discountPrice; + /** + * 其它金额,单位:元 + */ + private BigDecimal otherPrice; + + /** + * 本次收款,单位:元 + * + * payPrice = totalPrice + otherPrice - debtPrice + */ + private BigDecimal payPrice; + /** + * 本次欠款,单位:元 + */ + private BigDecimal debtPrice; + + /** + * 附件地址 + */ + private String fileUrl; + /** + * 备注 + */ + private String remark; + +} \ No newline at end of file diff --git a/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/dal/dataobject/purchase/ErpPurchaseInItemDO.java b/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/dal/dataobject/purchase/ErpPurchaseInItemDO.java new file mode 100644 index 000000000..1597bc10b --- /dev/null +++ b/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/dal/dataobject/purchase/ErpPurchaseInItemDO.java @@ -0,0 +1,95 @@ +package cn.iocoder.yudao.module.erp.dal.dataobject.purchase; + +import cn.iocoder.yudao.framework.mybatis.core.dataobject.BaseDO; +import cn.iocoder.yudao.module.erp.dal.dataobject.product.ErpProductDO; +import cn.iocoder.yudao.module.erp.dal.dataobject.stock.ErpWarehouseDO; +import com.baomidou.mybatisplus.annotation.KeySequence; +import com.baomidou.mybatisplus.annotation.TableId; +import com.baomidou.mybatisplus.annotation.TableName; +import lombok.*; + +import java.math.BigDecimal; + +/** + * ERP 采购入库项 DO + * + * @author 芋道源码 + */ +@TableName("erp_purchase_in_items") +@KeySequence("erp_purchase_in_items_seq") // 用于 Oracle、PostgreSQL、Kingbase、DB2、H2 数据库的主键自增。如果是 MySQL 等数据库,可不写。 +@Data +@EqualsAndHashCode(callSuper = true) +@ToString(callSuper = true) +@Builder +@NoArgsConstructor +@AllArgsConstructor +public class ErpPurchaseInItemDO extends BaseDO { + + /** + * 编号 + */ + @TableId + private Long id; + /** + * 采购入库编号 + * + * 关联 {@link ErpPurchaseInDO##getId()} + */ + private Long inId; + /** + * 采购订单项编号 + * + * 关联 {@link ErpPurchaseOrderItemDO#getId()} + * 目的:方便更新关联的采购订单项的入库数量 + */ + private Long orderItemId; + /** + * 仓库编号 + * + * 关联 {@link ErpWarehouseDO#getId()} + */ + private Long warehouseId; + /** + * 产品编号 + * + * 关联 {@link ErpProductDO#getId()} + */ + private Long productId; + /** + * 产品单位单位 + * + * 冗余 {@link ErpProductDO#getUnitId()} + */ + private Long productUnitId; + + /** + * 产品单位单价,单位:元 + */ + private BigDecimal productPrice; + /** + * 数量 + */ + private BigDecimal count; + /** + * 总价,单位:元 + * + * totalPrice = productPrice * count + */ + private BigDecimal totalPrice; + /** + * 税率,百分比 + */ + private BigDecimal taxPercent; + /** + * 税额,单位:元 + * + * taxPrice = totalPrice * taxPercent + */ + private BigDecimal taxPrice; + + /** + * 备注 + */ + private String remark; + +} \ No newline at end of file diff --git a/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/dal/mysql/purchase/ErpPurchaseInItemMapper.java b/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/dal/mysql/purchase/ErpPurchaseInItemMapper.java new file mode 100644 index 000000000..b3a6987e2 --- /dev/null +++ b/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/dal/mysql/purchase/ErpPurchaseInItemMapper.java @@ -0,0 +1,56 @@ +package cn.iocoder.yudao.module.erp.dal.mysql.purchase; + +import cn.hutool.core.collection.CollUtil; +import cn.iocoder.yudao.framework.mybatis.core.mapper.BaseMapperX; +import cn.iocoder.yudao.module.erp.dal.dataobject.purchase.ErpPurchaseInItemDO; +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 + * + * @author 芋道源码 + */ +@Mapper +public interface ErpPurchaseInItemMapper extends BaseMapperX { + + default List selectListByInId(Long inId) { + return selectList(ErpPurchaseInItemDO::getInId, inId); + } + + default List selectListByInIds(Collection inIds) { + return selectList(ErpPurchaseInItemDO::getInId, inIds); + } + + default int deleteByInId(Long inId) { + return delete(ErpPurchaseInItemDO::getInId, inId); + } + + /** + * 基于销售订单编号,查询每个销售订单项的入库数量之和 + * + * @param inIds 入库订单项编号数组 + * @return key:销售订单项编号;value:入库数量之和 + */ + default Map selectOrderItemCountSumMapByInIds(Collection inIds) { + if (CollUtil.isEmpty(inIds)) { + return Collections.emptyMap(); + } + // SQL sum 查询 + List> result = selectMaps(new QueryWrapper() + .select("order_item_id, SUM(count) AS sumCount") + .groupBy("order_item_id") + .in("in_id", inIds)); + // 获得数量 + return convertMap(result, obj -> (Long) obj.get("order_item_id"), obj -> (BigDecimal) obj.get("sumCount")); + } + +} \ No newline at end of file diff --git a/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/dal/mysql/purchase/ErpPurchaseInMapper.java b/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/dal/mysql/purchase/ErpPurchaseInMapper.java new file mode 100644 index 000000000..ff43be137 --- /dev/null +++ b/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/dal/mysql/purchase/ErpPurchaseInMapper.java @@ -0,0 +1,62 @@ +package cn.iocoder.yudao.module.erp.dal.mysql.purchase; + + +import cn.iocoder.yudao.framework.common.pojo.PageResult; +import cn.iocoder.yudao.framework.mybatis.core.mapper.BaseMapperX; +import cn.iocoder.yudao.framework.mybatis.core.query.MPJLambdaWrapperX; +import cn.iocoder.yudao.module.erp.controller.admin.purchase.vo.in.ErpPurchaseInPageReqVO; +import cn.iocoder.yudao.module.erp.dal.dataobject.purchase.ErpPurchaseInDO; +import cn.iocoder.yudao.module.erp.dal.dataobject.purchase.ErpPurchaseInItemDO; +import com.baomidou.mybatisplus.core.conditions.update.LambdaUpdateWrapper; +import org.apache.ibatis.annotations.Mapper; + +import java.math.BigDecimal; +import java.util.List; + +/** + * ERP 采购入库 Mapper + * + * @author 芋道源码 + */ +@Mapper +public interface ErpPurchaseInMapper extends BaseMapperX { + + default PageResult selectPage(ErpPurchaseInPageReqVO reqVO) { + MPJLambdaWrapperX query = new MPJLambdaWrapperX() + .likeIfPresent(ErpPurchaseInDO::getNo, reqVO.getNo()) + .eqIfPresent(ErpPurchaseInDO::getSupplierId, reqVO.getSupplierId()) + .betweenIfPresent(ErpPurchaseInDO::getInTime, reqVO.getInTime()) + .eqIfPresent(ErpPurchaseInDO::getStatus, reqVO.getStatus()) + .likeIfPresent(ErpPurchaseInDO::getRemark, reqVO.getRemark()) + .eqIfPresent(ErpPurchaseInDO::getCreator, reqVO.getCreator()) + .eqIfPresent(ErpPurchaseInDO::getAccountId, reqVO.getAccountId()) + .likeIfPresent(ErpPurchaseInDO::getOrderNo, reqVO.getOrderNo()) + .orderByDesc(ErpPurchaseInDO::getId); + if (Boolean.TRUE.equals(reqVO.getDebtStatus())) { + query.gt(ErpPurchaseInDO::getDebtPrice, BigDecimal.ZERO); + } else if (Boolean.FALSE.equals(reqVO.getDebtStatus())) { + query.eq(ErpPurchaseInDO::getDebtPrice, BigDecimal.ZERO); + } + if (reqVO.getWarehouseId() != null || reqVO.getProductId() != null) { + query.leftJoin(ErpPurchaseInItemDO.class, ErpPurchaseInItemDO::getInId, ErpPurchaseInDO::getId) + .eq(reqVO.getWarehouseId() != null, ErpPurchaseInItemDO::getWarehouseId, reqVO.getWarehouseId()) + .eq(reqVO.getProductId() != null, ErpPurchaseInItemDO::getProductId, reqVO.getProductId()) + .groupBy(ErpPurchaseInDO::getId); // 避免 1 对多查询,产生相同的 1 + } + return selectJoinPage(reqVO, ErpPurchaseInDO.class, query); + } + + default int updateByIdAndStatus(Long id, Integer status, ErpPurchaseInDO updateObj) { + return update(updateObj, new LambdaUpdateWrapper() + .eq(ErpPurchaseInDO::getId, id).eq(ErpPurchaseInDO::getStatus, status)); + } + + default ErpPurchaseInDO selectByNo(String no) { + return selectOne(ErpPurchaseInDO::getNo, no); + } + + default List selectListByOrderId(Long orderId) { + return selectList(ErpPurchaseInDO::getOrderId, orderId); + } + +} \ No newline at end of file diff --git a/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/dal/redis/no/ErpNoRedisDAO.java b/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/dal/redis/no/ErpNoRedisDAO.java index b8d51b5d9..f7a258634 100644 --- a/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/dal/redis/no/ErpNoRedisDAO.java +++ b/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/dal/redis/no/ErpNoRedisDAO.java @@ -55,6 +55,10 @@ public class ErpNoRedisDAO { * 采购订单 {@link cn.iocoder.yudao.module.erp.dal.dataobject.purchase.ErpPurchaseOrderDO} */ public static final String PURCHASE_ORDER_NO_PREFIX = "CGDD"; + /** + * 采购入库 {@link cn.iocoder.yudao.module.erp.dal.dataobject.purchase.ErpPurchaseInDO} + */ + public static final String PURCHASE_IN_NO_PREFIX = "CGRK"; @Resource private StringRedisTemplate stringRedisTemplate; diff --git a/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/service/purchase/ErpPurchaseInService.java b/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/service/purchase/ErpPurchaseInService.java new file mode 100644 index 000000000..12ad08a3c --- /dev/null +++ b/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/service/purchase/ErpPurchaseInService.java @@ -0,0 +1,84 @@ +package cn.iocoder.yudao.module.erp.service.purchase; + +import cn.iocoder.yudao.framework.common.pojo.PageResult; +import cn.iocoder.yudao.module.erp.controller.admin.purchase.vo.in.ErpPurchaseInPageReqVO; +import cn.iocoder.yudao.module.erp.controller.admin.purchase.vo.in.ErpPurchaseInSaveReqVO; +import cn.iocoder.yudao.module.erp.dal.dataobject.purchase.ErpPurchaseInDO; +import cn.iocoder.yudao.module.erp.dal.dataobject.purchase.ErpPurchaseInItemDO; +import jakarta.validation.Valid; + +import java.util.Collection; +import java.util.List; + +/** + * ERP 采购入库 Service 接口 + * + * @author 芋道源码 + */ +public interface ErpPurchaseInService { + + /** + * 创建采购入库 + * + * @param createReqVO 创建信息 + * @return 编号 + */ + Long createPurchaseIn(@Valid ErpPurchaseInSaveReqVO createReqVO); + + /** + * 更新采购入库 + * + * @param updateReqVO 更新信息 + */ + void updatePurchaseIn(@Valid ErpPurchaseInSaveReqVO updateReqVO); + + /** + * 更新采购入库的状态 + * + * @param id 编号 + * @param status 状态 + */ + void updatePurchaseInStatus(Long id, Integer status); + + /** + * 删除采购入库 + * + * @param ids 编号数组 + */ + void deletePurchaseIn(List ids); + + /** + * 获得采购入库 + * + * @param id 编号 + * @return 采购入库 + */ + ErpPurchaseInDO getPurchaseIn(Long id); + + /** + * 获得采购入库分页 + * + * @param pageReqVO 分页查询 + * @return 采购入库分页 + */ + PageResult getPurchaseInPage(ErpPurchaseInPageReqVO pageReqVO); + + // ==================== 采购入库项 ==================== + + /** + * 获得采购入库项列表 + * + * @param inId 采购入库编号 + * @return 采购入库项列表 + */ + List getPurchaseInItemListByInId(Long inId); + + /** + * 获得采购入库项 List + * + * @param inIds 采购入库编号数组 + * @return 采购入库项 List + */ + List getPurchaseInItemListByInIds(Collection inIds); + +} \ No newline at end of file diff --git a/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/service/purchase/ErpPurchaseInServiceImpl.java b/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/service/purchase/ErpPurchaseInServiceImpl.java new file mode 100644 index 000000000..58a3e2bb0 --- /dev/null +++ b/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/service/purchase/ErpPurchaseInServiceImpl.java @@ -0,0 +1,286 @@ +package cn.iocoder.yudao.module.erp.service.purchase; + +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.purchase.vo.in.ErpPurchaseInPageReqVO; +import cn.iocoder.yudao.module.erp.controller.admin.purchase.vo.in.ErpPurchaseInSaveReqVO; +import cn.iocoder.yudao.module.erp.dal.dataobject.product.ErpProductDO; +import cn.iocoder.yudao.module.erp.dal.dataobject.purchase.ErpPurchaseInDO; +import cn.iocoder.yudao.module.erp.dal.dataobject.purchase.ErpPurchaseInItemDO; +import cn.iocoder.yudao.module.erp.dal.dataobject.purchase.ErpPurchaseOrderDO; +import cn.iocoder.yudao.module.erp.dal.mysql.purchase.ErpPurchaseInItemMapper; +import cn.iocoder.yudao.module.erp.dal.mysql.purchase.ErpPurchaseInMapper; +import cn.iocoder.yudao.module.erp.dal.redis.no.ErpNoRedisDAO; +import cn.iocoder.yudao.module.erp.enums.ErpAuditStatus; +import cn.iocoder.yudao.module.erp.enums.stock.ErpStockRecordBizTypeEnum; +import cn.iocoder.yudao.module.erp.service.finance.ErpAccountService; +import cn.iocoder.yudao.module.erp.service.product.ErpProductService; +import cn.iocoder.yudao.module.erp.service.stock.ErpStockRecordService; +import cn.iocoder.yudao.module.erp.service.stock.bo.ErpStockRecordCreateReqBO; +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; + +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.exception.util.ServiceExceptionUtil.exception; +import static cn.iocoder.yudao.framework.common.util.collection.CollectionUtils.*; +import static cn.iocoder.yudao.module.erp.enums.ErrorCodeConstants.*; + +// TODO 芋艿:记录操作日志 + +/** + * ERP 采购入库 Service 实现类 + * + * @author 芋道源码 + */ +@Service +@Validated +public class ErpPurchaseInServiceImpl implements ErpPurchaseInService { + + @Resource + private ErpPurchaseInMapper purchaseInMapper; + @Resource + private ErpPurchaseInItemMapper purchaseInItemMapper; + + @Resource + private ErpNoRedisDAO noRedisDAO; + + @Resource + private ErpProductService productService; + @Resource + @Lazy // 延迟加载,避免循环依赖 + private ErpPurchaseOrderService purchaseOrderService; + @Resource + private ErpAccountService accountService; + @Resource + private ErpStockRecordService stockRecordService; + + @Resource + private AdminUserApi adminUserApi; + + @Override + @Transactional(rollbackFor = Exception.class) + public Long createPurchaseIn(ErpPurchaseInSaveReqVO createReqVO) { + // 1.1 校验采购订单已审核 + ErpPurchaseOrderDO purchaseOrder = purchaseOrderService.validatePurchaseOrder(createReqVO.getOrderId()); + // 1.2 校验入库项的有效性 + List purchaseInItems = validatePurchaseInItems(createReqVO.getItems()); + // 1.3 校验结算账户 + accountService.validateAccount(createReqVO.getAccountId()); + // 1.4 生成调拨单号,并校验唯一性 + String no = noRedisDAO.generate(ErpNoRedisDAO.PURCHASE_IN_NO_PREFIX); + if (purchaseInMapper.selectByNo(no) != null) { + throw exception(PURCHASE_IN_NO_EXISTS); + } + + // 2.1 插入入库 + ErpPurchaseInDO purchaseIn = BeanUtils.toBean(createReqVO, ErpPurchaseInDO.class, in -> in + .setNo(no).setStatus(ErpAuditStatus.PROCESS.getStatus())) + .setOrderNo(purchaseOrder.getNo()).setSupplierId(purchaseOrder.getSupplierId()); + calculateTotalPrice(purchaseIn, purchaseInItems); + purchaseInMapper.insert(purchaseIn); + // 2.2 插入入库项 + purchaseInItems.forEach(o -> o.setInId(purchaseIn.getId())); + purchaseInItemMapper.insertBatch(purchaseInItems); + + // 3. 更新采购订单的入库数量 + updatePurchaseOrderInCount(createReqVO.getOrderId()); + return purchaseIn.getId(); + } + + @Override + @Transactional(rollbackFor = Exception.class) + public void updatePurchaseIn(ErpPurchaseInSaveReqVO updateReqVO) { + // 1.1 校验存在 + ErpPurchaseInDO purchaseIn = validatePurchaseInExists(updateReqVO.getId()); + if (ErpAuditStatus.APPROVE.getStatus().equals(purchaseIn.getStatus())) { + throw exception(PURCHASE_IN_UPDATE_FAIL_APPROVE, purchaseIn.getNo()); + } + // 1.2 校验采购订单已审核 + ErpPurchaseOrderDO purchaseOrder = purchaseOrderService.validatePurchaseOrder(updateReqVO.getOrderId()); + // 1.3 校验结算账户 + accountService.validateAccount(updateReqVO.getAccountId()); + // 1.4 校验订单项的有效性 + List purchaseInItems = validatePurchaseInItems(updateReqVO.getItems()); + + // 2.1 更新入库 + ErpPurchaseInDO updateObj = BeanUtils.toBean(updateReqVO, ErpPurchaseInDO.class) + .setOrderNo(purchaseOrder.getNo()).setSupplierId(purchaseOrder.getSupplierId()); + calculateTotalPrice(updateObj, purchaseInItems); + purchaseInMapper.updateById(updateObj); + // 2.2 更新入库项 + updatePurchaseInItemList(updateReqVO.getId(), purchaseInItems); + + // 3.1 更新采购订单的入库数量 + updatePurchaseOrderInCount(updateObj.getOrderId()); + // 3.2 注意:如果采购订单编号变更了,需要更新“老”采购订单的入库数量 + if (ObjectUtil.notEqual(purchaseIn.getOrderId(), updateObj.getOrderId())) { + updatePurchaseOrderInCount(purchaseIn.getOrderId()); + } + } + + private void calculateTotalPrice(ErpPurchaseInDO purchaseIn, List purchaseInItems) { + purchaseIn.setTotalCount(getSumValue(purchaseInItems, ErpPurchaseInItemDO::getCount, BigDecimal::add)); + purchaseIn.setTotalProductPrice(getSumValue(purchaseInItems, ErpPurchaseInItemDO::getTotalPrice, BigDecimal::add, BigDecimal.ZERO)); + purchaseIn.setTotalTaxPrice(getSumValue(purchaseInItems, ErpPurchaseInItemDO::getTaxPrice, BigDecimal::add, BigDecimal.ZERO)); + purchaseIn.setTotalPrice(purchaseIn.getTotalProductPrice().add(purchaseIn.getTotalTaxPrice())); + // 计算优惠价格 + if (purchaseIn.getDiscountPercent() == null) { + purchaseIn.setDiscountPercent(BigDecimal.ZERO); + } + purchaseIn.setDiscountPrice(MoneyUtils.priceMultiplyPercent(purchaseIn.getTotalPrice(), purchaseIn.getDiscountPercent())); + purchaseIn.setTotalPrice(purchaseIn.getTotalPrice().subtract(purchaseIn.getDiscountPrice())); + // 计算应收金额 + BigDecimal allPrice = purchaseIn.getTotalPrice().add(purchaseIn.getOtherPrice()); + purchaseIn.setDebtPrice(allPrice.subtract(purchaseIn.getPayPrice())); + } + + private void updatePurchaseOrderInCount(Long orderId) { + // 1.1 查询采购订单对应的采购入库单列表 + List purchaseIns = purchaseInMapper.selectListByOrderId(orderId); + // 1.2 查询对应的采购订单项的入库数量 + Map returnCountMap = purchaseInItemMapper.selectOrderItemCountSumMapByInIds( + convertList(purchaseIns, ErpPurchaseInDO::getId)); + // 2. 更新采购订单的入库数量 + purchaseOrderService.updatePurchaseOrderInCount(orderId, returnCountMap); + } + + @Override + @Transactional(rollbackFor = Exception.class) + public void updatePurchaseInStatus(Long id, Integer status) { + boolean approve = ErpAuditStatus.APPROVE.getStatus().equals(status); + // 1.1 校验存在 + ErpPurchaseInDO purchaseIn = validatePurchaseInExists(id); + // 1.2 校验状态 + if (purchaseIn.getStatus().equals(status)) { + throw exception(approve ? PURCHASE_IN_APPROVE_FAIL : PURCHASE_IN_PROCESS_FAIL); + } + + // 2. 更新状态 + int updateCount = purchaseInMapper.updateByIdAndStatus(id, purchaseIn.getStatus(), + new ErpPurchaseInDO().setStatus(status)); + if (updateCount == 0) { + throw exception(approve ? PURCHASE_IN_APPROVE_FAIL : PURCHASE_IN_PROCESS_FAIL); + } + + // 3. 变更库存 + List purchaseInItems = purchaseInItemMapper.selectListByInId(id); + Integer bizType = approve ? ErpStockRecordBizTypeEnum.PURCHASE_IN.getType() + : ErpStockRecordBizTypeEnum.PURCHASE_IN_CANCEL.getType(); + purchaseInItems.forEach(purchaseInItem -> { + BigDecimal count = approve ? purchaseInItem.getCount() : purchaseInItem.getCount().negate(); + stockRecordService.createStockRecord(new ErpStockRecordCreateReqBO( + purchaseInItem.getProductId(), purchaseInItem.getWarehouseId(), count, + bizType, purchaseInItem.getInId(), purchaseInItem.getId(), purchaseIn.getNo())); + }); + } + + private List validatePurchaseInItems(List list) { + // 1. 校验产品存在 + List productList = productService.validProductList( + convertSet(list, ErpPurchaseInSaveReqVO.Item::getProductId)); + Map productMap = convertMap(productList, ErpProductDO::getId); + // 2. 转化为 ErpPurchaseInItemDO 列表 + return convertList(list, o -> BeanUtils.toBean(o, ErpPurchaseInItemDO.class, item -> { + item.setProductUnitId(productMap.get(item.getProductId()).getUnitId()); + item.setTotalPrice(MoneyUtils.priceMultiply(item.getProductPrice(), item.getCount())); + if (item.getTotalPrice() == null) { + return; + } + if (item.getTaxPercent() != null) { + item.setTaxPrice(MoneyUtils.priceMultiplyPercent(item.getTotalPrice(), item.getTaxPercent())); + } + })); + } + + private void updatePurchaseInItemList(Long id, List newList) { + // 第一步,对比新老数据,获得添加、修改、删除的列表 + List oldList = purchaseInItemMapper.selectListByInId(id); + List> diffList = diffList(oldList, newList, // id 不同,就认为是不同的记录 + (oldVal, newVal) -> oldVal.getId().equals(newVal.getId())); + + // 第二步,批量添加、修改、删除 + if (CollUtil.isNotEmpty(diffList.get(0))) { + diffList.get(0).forEach(o -> o.setInId(id)); + purchaseInItemMapper.insertBatch(diffList.get(0)); + } + if (CollUtil.isNotEmpty(diffList.get(1))) { + purchaseInItemMapper.updateBatch(diffList.get(1)); + } + if (CollUtil.isNotEmpty(diffList.get(2))) { + purchaseInItemMapper.deleteBatchIds(convertList(diffList.get(2), ErpPurchaseInItemDO::getId)); + } + } + + @Override + @Transactional(rollbackFor = Exception.class) + public void deletePurchaseIn(List ids) { + // 1. 校验不处于已审批 + List purchaseIns = purchaseInMapper.selectBatchIds(ids); + if (CollUtil.isEmpty(purchaseIns)) { + return; + } + purchaseIns.forEach(purchaseIn -> { + if (ErpAuditStatus.APPROVE.getStatus().equals(purchaseIn.getStatus())) { + throw exception(PURCHASE_IN_DELETE_FAIL_APPROVE, purchaseIn.getNo()); + } + }); + + // 2. 遍历删除,并记录操作日志 + purchaseIns.forEach(purchaseIn -> { + // 2.1 删除订单 + purchaseInMapper.deleteById(purchaseIn.getId()); + // 2.2 删除订单项 + purchaseInItemMapper.deleteByInId(purchaseIn.getId()); + + // 2.3 更新采购订单的入库数量 + updatePurchaseOrderInCount(purchaseIn.getOrderId()); + }); + + } + + private ErpPurchaseInDO validatePurchaseInExists(Long id) { + ErpPurchaseInDO purchaseIn = purchaseInMapper.selectById(id); + if (purchaseIn == null) { + throw exception(PURCHASE_IN_NOT_EXISTS); + } + return purchaseIn; + } + + @Override + public ErpPurchaseInDO getPurchaseIn(Long id) { + return purchaseInMapper.selectById(id); + } + + @Override + public PageResult getPurchaseInPage(ErpPurchaseInPageReqVO pageReqVO) { + return purchaseInMapper.selectPage(pageReqVO); + } + + // ==================== 采购入库项 ==================== + + @Override + public List getPurchaseInItemListByInId(Long inId) { + return purchaseInItemMapper.selectListByInId(inId); + } + + @Override + public List getPurchaseInItemListByInIds(Collection inIds) { + if (CollUtil.isEmpty(inIds)) { + return Collections.emptyList(); + } + return purchaseInItemMapper.selectListByInIds(inIds); + } + +} \ No newline at end of file From 62ef4b16afb2680fa0688683ae40c0df9b2bb1c8 Mon Sep 17 00:00:00 2001 From: YunaiV Date: Mon, 12 Feb 2024 16:51:56 +0800 Subject: [PATCH 104/119] =?UTF-8?q?=E2=9C=A8=20ERP=EF=BC=9A=E9=87=87?= =?UTF-8?q?=E8=B4=AD=E5=85=A5=E5=BA=93=20100%?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../admin/purchase/vo/in/ErpPurchaseInRespVO.java | 4 ++-- .../admin/purchase/vo/in/ErpPurchaseInSaveReqVO.java | 6 +++--- .../module/erp/dal/dataobject/purchase/ErpPurchaseInDO.java | 4 ++-- .../erp/service/purchase/ErpPurchaseInServiceImpl.java | 2 +- 4 files changed, 8 insertions(+), 8 deletions(-) diff --git a/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/controller/admin/purchase/vo/in/ErpPurchaseInRespVO.java b/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/controller/admin/purchase/vo/in/ErpPurchaseInRespVO.java index ce16cf57a..fe6a31010 100644 --- a/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/controller/admin/purchase/vo/in/ErpPurchaseInRespVO.java +++ b/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/controller/admin/purchase/vo/in/ErpPurchaseInRespVO.java @@ -68,8 +68,8 @@ public class ErpPurchaseInRespVO { @Schema(description = "定金金额,单位:元", requiredMode = Schema.RequiredMode.REQUIRED, example = "7127") private BigDecimal otherPrice; - @Schema(description = "本次收款,单位:元", requiredMode = Schema.RequiredMode.REQUIRED, example = "7127") - private BigDecimal payPrice; + @Schema(description = "本次付款,单位:元", requiredMode = Schema.RequiredMode.REQUIRED, example = "7127") + private BigDecimal refundPrice; @Schema(description = "本次欠款,单位:元", requiredMode = Schema.RequiredMode.REQUIRED, example = "666") private BigDecimal debtPrice; diff --git a/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/controller/admin/purchase/vo/in/ErpPurchaseInSaveReqVO.java b/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/controller/admin/purchase/vo/in/ErpPurchaseInSaveReqVO.java index dd1543d5b..64dbac499 100644 --- a/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/controller/admin/purchase/vo/in/ErpPurchaseInSaveReqVO.java +++ b/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/controller/admin/purchase/vo/in/ErpPurchaseInSaveReqVO.java @@ -32,9 +32,9 @@ public class ErpPurchaseInSaveReqVO { @Schema(description = "其它金额,单位:元", example = "7127") private BigDecimal otherPrice; - @Schema(description = "本次收款,单位:元", requiredMode = Schema.RequiredMode.REQUIRED, example = "7127") - @NotNull(message = "本次收款不能为空") - private BigDecimal payPrice; + @Schema(description = "本次付款,单位:元", requiredMode = Schema.RequiredMode.REQUIRED, example = "7127") + @NotNull(message = "本次付款不能为空") + private BigDecimal refundPrice; @Schema(description = "附件地址", example = "https://www.iocoder.cn") private String fileUrl; diff --git a/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/dal/dataobject/purchase/ErpPurchaseInDO.java b/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/dal/dataobject/purchase/ErpPurchaseInDO.java index 7fd4c1c4e..51dc90f59 100644 --- a/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/dal/dataobject/purchase/ErpPurchaseInDO.java +++ b/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/dal/dataobject/purchase/ErpPurchaseInDO.java @@ -107,9 +107,9 @@ public class ErpPurchaseInDO extends BaseDO { /** * 本次收款,单位:元 * - * payPrice = totalPrice + otherPrice - debtPrice + * refundPrice = totalPrice + otherPrice - debtPrice */ - private BigDecimal payPrice; + private BigDecimal refundPrice; /** * 本次欠款,单位:元 */ diff --git a/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/service/purchase/ErpPurchaseInServiceImpl.java b/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/service/purchase/ErpPurchaseInServiceImpl.java index 58a3e2bb0..24209a55a 100644 --- a/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/service/purchase/ErpPurchaseInServiceImpl.java +++ b/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/service/purchase/ErpPurchaseInServiceImpl.java @@ -143,7 +143,7 @@ public class ErpPurchaseInServiceImpl implements ErpPurchaseInService { purchaseIn.setTotalPrice(purchaseIn.getTotalPrice().subtract(purchaseIn.getDiscountPrice())); // 计算应收金额 BigDecimal allPrice = purchaseIn.getTotalPrice().add(purchaseIn.getOtherPrice()); - purchaseIn.setDebtPrice(allPrice.subtract(purchaseIn.getPayPrice())); + purchaseIn.setDebtPrice(allPrice.subtract(purchaseIn.getRefundPrice())); } private void updatePurchaseOrderInCount(Long orderId) { From 2d02430768bcb5ad1bb8a7f251ccbeebc705768a Mon Sep 17 00:00:00 2001 From: YunaiV Date: Mon, 12 Feb 2024 20:42:37 +0800 Subject: [PATCH 105/119] =?UTF-8?q?=E2=9C=A8=20ERP=EF=BC=9A=E9=87=87?= =?UTF-8?q?=E8=B4=AD=E5=87=BA=E5=BA=93=2050%?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../module/erp/enums/ErrorCodeConstants.java | 8 + .../stock/ErpStockRecordBizTypeEnum.java | 3 + .../purchase/ErpPurchaseReturnController.java | 165 ++++++++++ .../returns/ErpPurchaseReturnPageReqVO.java | 51 ++++ .../vo/returns/ErpPurchaseReturnRespVO.java | 148 +++++++++ .../returns/ErpPurchaseReturnSaveReqVO.java | 85 ++++++ .../dataobject/purchase/ErpPurchaseInDO.java | 4 +- .../purchase/ErpPurchaseReturnDO.java | 127 ++++++++ .../purchase/ErpPurchaseReturnItemDO.java | 95 ++++++ .../purchase/ErpPurchaseInItemMapper.java | 4 +- .../purchase/ErpPurchaseOrderMapper.java | 2 +- .../purchase/ErpPurchaseReturnItemMapper.java | 56 ++++ .../purchase/ErpPurchaseReturnMapper.java | 55 ++++ .../mysql/sale/ErpSaleReturnItemMapper.java | 4 +- .../erp/dal/redis/no/ErpNoRedisDAO.java | 6 +- .../purchase/ErpPurchaseReturnService.java | 84 ++++++ .../ErpPurchaseReturnServiceImpl.java | 282 ++++++++++++++++++ .../sale/ErpSaleReturnServiceImpl.java | 2 +- 18 files changed, 1172 insertions(+), 9 deletions(-) create mode 100644 yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/controller/admin/purchase/ErpPurchaseReturnController.java create mode 100644 yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/controller/admin/purchase/vo/returns/ErpPurchaseReturnPageReqVO.java create mode 100644 yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/controller/admin/purchase/vo/returns/ErpPurchaseReturnRespVO.java create mode 100644 yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/controller/admin/purchase/vo/returns/ErpPurchaseReturnSaveReqVO.java create mode 100644 yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/dal/dataobject/purchase/ErpPurchaseReturnDO.java create mode 100644 yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/dal/dataobject/purchase/ErpPurchaseReturnItemDO.java create mode 100644 yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/dal/mysql/purchase/ErpPurchaseReturnItemMapper.java create mode 100644 yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/dal/mysql/purchase/ErpPurchaseReturnMapper.java create mode 100644 yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/service/purchase/ErpPurchaseReturnService.java create mode 100644 yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/service/purchase/ErpPurchaseReturnServiceImpl.java diff --git a/yudao-module-erp/yudao-module-erp-api/src/main/java/cn/iocoder/yudao/module/erp/enums/ErrorCodeConstants.java b/yudao-module-erp/yudao-module-erp-api/src/main/java/cn/iocoder/yudao/module/erp/enums/ErrorCodeConstants.java index b3133d63d..b368f5509 100644 --- a/yudao-module-erp/yudao-module-erp-api/src/main/java/cn/iocoder/yudao/module/erp/enums/ErrorCodeConstants.java +++ b/yudao-module-erp/yudao-module-erp-api/src/main/java/cn/iocoder/yudao/module/erp/enums/ErrorCodeConstants.java @@ -34,6 +34,14 @@ ErrorCode PURCHASE_ORDER_ITEM_RETURN_FAIL_IN_EXCEED = new ErrorCode(1_030_101_00 ErrorCode PURCHASE_IN_NO_EXISTS = new ErrorCode(1_030_102_004, "生成入库单失败,请重新提交"); ErrorCode PURCHASE_IN_UPDATE_FAIL_APPROVE = new ErrorCode(1_030_102_005, "采购入库单({})已审核,无法修改"); + // ========== ERP 采购退货(1-030-103-000) ========== + ErrorCode PURCHASE_RETURN_NOT_EXISTS = new ErrorCode(1_030_103_000, "采购退货单不存在"); + ErrorCode PURCHASE_RETURN_DELETE_FAIL_APPROVE = new ErrorCode(1_030_103_001, "采购退货单({})已审核,无法删除"); + ErrorCode PURCHASE_RETURN_PROCESS_FAIL = new ErrorCode(1_030_103_002, "反审核失败,只有已审核的退货单才能反审核"); + ErrorCode PURCHASE_RETURN_APPROVE_FAIL = new ErrorCode(1_030_103_003, "审核失败,只有未审核的退货单才能审核"); + ErrorCode PURCHASE_RETURN_NO_EXISTS = new ErrorCode(1_030_103_004, "生成退货单失败,请重新提交"); + ErrorCode PURCHASE_RETURN_UPDATE_FAIL_APPROVE = new ErrorCode(1_030_103_005, "采购退货单({})已审核,无法修改"); + // ========== ERP 客户(1-030-200-000)========== ErrorCode CUSTOMER_NOT_EXISTS = new ErrorCode(1_020_200_000, "客户不存在"); ErrorCode CUSTOMER_NOT_ENABLE = new ErrorCode(1_020_200_001, "客户({})未启用"); diff --git a/yudao-module-erp/yudao-module-erp-api/src/main/java/cn/iocoder/yudao/module/erp/enums/stock/ErpStockRecordBizTypeEnum.java b/yudao-module-erp/yudao-module-erp-api/src/main/java/cn/iocoder/yudao/module/erp/enums/stock/ErpStockRecordBizTypeEnum.java index af8c4ded9..559bf4ccf 100644 --- a/yudao-module-erp/yudao-module-erp-api/src/main/java/cn/iocoder/yudao/module/erp/enums/stock/ErpStockRecordBizTypeEnum.java +++ b/yudao-module-erp/yudao-module-erp-api/src/main/java/cn/iocoder/yudao/module/erp/enums/stock/ErpStockRecordBizTypeEnum.java @@ -39,6 +39,9 @@ public enum ErpStockRecordBizTypeEnum implements IntArrayValuable { PURCHASE_IN(70, "采购入库"), PURCHASE_IN_CANCEL(71, "采购入库(作废)"), + + PURCHASE_RETURN(80, "采购退货出库"), + PURCHASE_RETURN_CANCEL(81, "采购退货出库(作废)"), ; public static final int[] ARRAYS = Arrays.stream(values()).mapToInt(ErpStockRecordBizTypeEnum::getType).toArray(); diff --git a/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/controller/admin/purchase/ErpPurchaseReturnController.java b/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/controller/admin/purchase/ErpPurchaseReturnController.java new file mode 100644 index 000000000..4d420836b --- /dev/null +++ b/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/controller/admin/purchase/ErpPurchaseReturnController.java @@ -0,0 +1,165 @@ +package cn.iocoder.yudao.module.erp.controller.admin.purchase; + +import cn.hutool.core.collection.CollUtil; +import cn.iocoder.yudao.framework.common.pojo.CommonResult; +import cn.iocoder.yudao.framework.common.pojo.PageParam; +import cn.iocoder.yudao.framework.common.pojo.PageResult; +import cn.iocoder.yudao.framework.common.util.collection.MapUtils; +import cn.iocoder.yudao.framework.common.util.object.BeanUtils; +import cn.iocoder.yudao.framework.excel.core.util.ExcelUtils; +import cn.iocoder.yudao.framework.operatelog.core.annotations.OperateLog; +import cn.iocoder.yudao.module.erp.controller.admin.product.vo.product.ErpProductRespVO; +import cn.iocoder.yudao.module.erp.controller.admin.purchase.vo.returns.ErpPurchaseReturnPageReqVO; +import cn.iocoder.yudao.module.erp.controller.admin.purchase.vo.returns.ErpPurchaseReturnRespVO; +import cn.iocoder.yudao.module.erp.controller.admin.purchase.vo.returns.ErpPurchaseReturnSaveReqVO; +import cn.iocoder.yudao.module.erp.dal.dataobject.purchase.ErpPurchaseReturnDO; +import cn.iocoder.yudao.module.erp.dal.dataobject.purchase.ErpPurchaseReturnItemDO; +import cn.iocoder.yudao.module.erp.dal.dataobject.purchase.ErpSupplierDO; +import cn.iocoder.yudao.module.erp.dal.dataobject.stock.ErpStockDO; +import cn.iocoder.yudao.module.erp.service.product.ErpProductService; +import cn.iocoder.yudao.module.erp.service.purchase.ErpPurchaseReturnService; +import cn.iocoder.yudao.module.erp.service.purchase.ErpSupplierService; +import cn.iocoder.yudao.module.erp.service.stock.ErpStockService; +import cn.iocoder.yudao.module.system.api.user.AdminUserApi; +import cn.iocoder.yudao.module.system.api.user.dto.AdminUserRespDTO; +import io.swagger.v3.oas.annotations.Operation; +import io.swagger.v3.oas.annotations.Parameter; +import io.swagger.v3.oas.annotations.tags.Tag; +import jakarta.annotation.Resource; +import jakarta.servlet.http.HttpServletResponse; +import jakarta.validation.Valid; +import org.springframework.security.access.prepost.PreAuthorize; +import org.springframework.validation.annotation.Validated; +import org.springframework.web.bind.annotation.*; + +import java.io.IOException; +import java.math.BigDecimal; +import java.util.List; +import java.util.Map; + +import static cn.iocoder.yudao.framework.common.pojo.CommonResult.success; +import static cn.iocoder.yudao.framework.common.util.collection.CollectionUtils.convertMultiMap; +import static cn.iocoder.yudao.framework.common.util.collection.CollectionUtils.convertSet; +import static cn.iocoder.yudao.framework.operatelog.core.enums.OperateTypeEnum.EXPORT; + +@Tag(name = "管理后台 - ERP 采购退货") +@RestController +@RequestMapping("/erp/purchase-return") +@Validated +public class ErpPurchaseReturnController { + + @Resource + private ErpPurchaseReturnService purchaseReturnService; + @Resource + private ErpStockService stockService; + @Resource + private ErpProductService productService; + @Resource + private ErpSupplierService supplierService; + + @Resource + private AdminUserApi adminUserApi; + + @PostMapping("/create") + @Operation(summary = "创建采购退货") + @PreAuthorize("@ss.hasPermission('erp:purchase-return:create')") + public CommonResult createPurchaseReturn(@Valid @RequestBody ErpPurchaseReturnSaveReqVO createReqVO) { + return success(purchaseReturnService.createPurchaseReturn(createReqVO)); + } + + @PutMapping("/update") + @Operation(summary = "更新采购退货") + @PreAuthorize("@ss.hasPermission('erp:purchase-return:update')") + public CommonResult updatePurchaseReturn(@Valid @RequestBody ErpPurchaseReturnSaveReqVO updateReqVO) { + purchaseReturnService.updatePurchaseReturn(updateReqVO); + return success(true); + } + + @PutMapping("/update-status") + @Operation(summary = "更新采购退货的状态") + @PreAuthorize("@ss.hasPermission('erp:purchase-return:update-status')") + public CommonResult updatePurchaseReturnStatus(@RequestParam("id") Long id, + @RequestParam("status") Integer status) { + purchaseReturnService.updatePurchaseReturnStatus(id, status); + return success(true); + } + + @DeleteMapping("/delete") + @Operation(summary = "删除采购退货") + @Parameter(name = "ids", description = "编号数组", required = true) + @PreAuthorize("@ss.hasPermission('erp:purchase-return:delete')") + public CommonResult deletePurchaseReturn(@RequestParam("ids") List ids) { + purchaseReturnService.deletePurchaseReturn(ids); + return success(true); + } + + @GetMapping("/get") + @Operation(summary = "获得采购退货") + @Parameter(name = "id", description = "编号", required = true, example = "1024") + @PreAuthorize("@ss.hasPermission('erp:purchase-return:query')") + public CommonResult getPurchaseReturn(@RequestParam("id") Long id) { + ErpPurchaseReturnDO purchaseReturn = purchaseReturnService.getPurchaseReturn(id); + if (purchaseReturn == null) { + return success(null); + } + List purchaseReturnItemList = purchaseReturnService.getPurchaseReturnItemListByReturnId(id); + Map productMap = productService.getProductVOMap( + convertSet(purchaseReturnItemList, ErpPurchaseReturnItemDO::getProductId)); + return success(BeanUtils.toBean(purchaseReturn, ErpPurchaseReturnRespVO.class, purchaseReturnVO -> + purchaseReturnVO.setItems(BeanUtils.toBean(purchaseReturnItemList, ErpPurchaseReturnRespVO.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") + @Operation(summary = "获得采购退货分页") + @PreAuthorize("@ss.hasPermission('erp:purchase-return:query')") + public CommonResult> getPurchaseReturnPage(@Valid ErpPurchaseReturnPageReqVO pageReqVO) { + PageResult pageResult = purchaseReturnService.getPurchaseReturnPage(pageReqVO); + return success(buildPurchaseReturnVOPageResult(pageResult)); + } + + @GetMapping("/export-excel") + @Operation(summary = "导出采购退货 Excel") + @PreAuthorize("@ss.hasPermission('erp:purchase-return:export')") + @OperateLog(type = EXPORT) + public void exportPurchaseReturnExcel(@Valid ErpPurchaseReturnPageReqVO pageReqVO, + HttpServletResponse response) throws IOException { + pageReqVO.setPageSize(PageParam.PAGE_SIZE_NONE); + List list = buildPurchaseReturnVOPageResult(purchaseReturnService.getPurchaseReturnPage(pageReqVO)).getList(); + // 导出 Excel + ExcelUtils.write(response, "采购退货.xls", "数据", ErpPurchaseReturnRespVO.class, list); + } + + private PageResult buildPurchaseReturnVOPageResult(PageResult pageResult) { + if (CollUtil.isEmpty(pageResult.getList())) { + return PageResult.empty(pageResult.getTotal()); + } + // 1.1 退货项 + List purchaseReturnItemList = purchaseReturnService.getPurchaseReturnItemListByReturnIds( + convertSet(pageResult.getList(), ErpPurchaseReturnDO::getId)); + Map> purchaseReturnItemMap = convertMultiMap(purchaseReturnItemList, ErpPurchaseReturnItemDO::getReturnId); + // 1.2 产品信息 + Map productMap = productService.getProductVOMap( + convertSet(purchaseReturnItemList, ErpPurchaseReturnItemDO::getProductId)); + // 1.3 供应商信息 + Map supplierMap = supplierService.getSupplierMap( + convertSet(pageResult.getList(), ErpPurchaseReturnDO::getSupplierId)); + // 1.4 管理员信息 + Map userMap = adminUserApi.getUserMap( + convertSet(pageResult.getList(), erpStockRecordDO -> Long.parseLong(erpStockRecordDO.getCreator()))); + // 2. 开始拼接 + return BeanUtils.toBean(pageResult, ErpPurchaseReturnRespVO.class, purchaseReturn -> { + purchaseReturn.setItems(BeanUtils.toBean(purchaseReturnItemMap.get(purchaseReturn.getId()), ErpPurchaseReturnRespVO.Item.class, + item -> MapUtils.findAndThen(productMap, item.getProductId(), product -> item.setProductName(product.getName()) + .setProductBarCode(product.getBarCode()).setProductUnitName(product.getUnitName())))); + purchaseReturn.setProductNames(CollUtil.join(purchaseReturn.getItems(), ",", ErpPurchaseReturnRespVO.Item::getProductName)); + MapUtils.findAndThen(supplierMap, purchaseReturn.getSupplierId(), supplier -> purchaseReturn.setSupplierName(supplier.getName())); + MapUtils.findAndThen(userMap, Long.parseLong(purchaseReturn.getCreator()), user -> purchaseReturn.setCreatorName(user.getNickname())); + }); + } + +} \ No newline at end of file diff --git a/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/controller/admin/purchase/vo/returns/ErpPurchaseReturnPageReqVO.java b/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/controller/admin/purchase/vo/returns/ErpPurchaseReturnPageReqVO.java new file mode 100644 index 000000000..b9d9d4b0b --- /dev/null +++ b/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/controller/admin/purchase/vo/returns/ErpPurchaseReturnPageReqVO.java @@ -0,0 +1,51 @@ +package cn.iocoder.yudao.module.erp.controller.admin.purchase.vo.returns; + +import cn.iocoder.yudao.framework.common.pojo.PageParam; +import io.swagger.v3.oas.annotations.media.Schema; +import lombok.Data; +import lombok.EqualsAndHashCode; +import lombok.ToString; +import org.springframework.format.annotation.DateTimeFormat; + +import java.time.LocalDateTime; + +import static cn.iocoder.yudao.framework.common.util.date.DateUtils.FORMAT_YEAR_MONTH_DAY_HOUR_MINUTE_SECOND; + +@Schema(description = "管理后台 - ERP 采购退货分页 Request VO") +@Data +@EqualsAndHashCode(callSuper = true) +@ToString(callSuper = true) +public class ErpPurchaseReturnPageReqVO extends PageParam { + + @Schema(description = "采购单编号", example = "XS001") + private String no; + + @Schema(description = "供应商编号", example = "1724") + private Long supplierId; + + @Schema(description = "退货时间") + @DateTimeFormat(pattern = FORMAT_YEAR_MONTH_DAY_HOUR_MINUTE_SECOND) + private LocalDateTime[] returnTime; + + @Schema(description = "备注", example = "你猜") + private String remark; + + @Schema(description = "退货状态", example = "2") + private Integer status; + + @Schema(description = "创建者") + private String creator; + + @Schema(description = "产品编号", example = "1") + private Long productId; + + @Schema(description = "仓库编号", example = "1") + private Long warehouseId; + + @Schema(description = "结算账号编号", example = "1") + private Long accountId; + + @Schema(description = "采购单号", example = "1") + private String orderNo; + +} \ No newline at end of file diff --git a/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/controller/admin/purchase/vo/returns/ErpPurchaseReturnRespVO.java b/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/controller/admin/purchase/vo/returns/ErpPurchaseReturnRespVO.java new file mode 100644 index 000000000..887b5f040 --- /dev/null +++ b/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/controller/admin/purchase/vo/returns/ErpPurchaseReturnRespVO.java @@ -0,0 +1,148 @@ +package cn.iocoder.yudao.module.erp.controller.admin.purchase.vo.returns; + +import com.alibaba.excel.annotation.ExcelIgnoreUnannotated; +import com.alibaba.excel.annotation.ExcelProperty; +import io.swagger.v3.oas.annotations.media.Schema; +import jakarta.validation.constraints.NotNull; +import lombok.Data; + +import java.math.BigDecimal; +import java.time.LocalDateTime; +import java.util.List; + +@Schema(description = "管理后台 - ERP 采购退货 Response VO") +@Data +@ExcelIgnoreUnannotated +public class ErpPurchaseReturnRespVO { + + @Schema(description = "编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "17386") + @ExcelProperty("编号") + private Long id; + + @Schema(description = "退货单编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "XS001") + @ExcelProperty("退货单编号") + private String no; + + @Schema(description = "退货状态", requiredMode = Schema.RequiredMode.REQUIRED, example = "2") + @ExcelProperty("退货状态") + private Integer status; + + @Schema(description = "供应商编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "1724") + private Long supplierId; + @Schema(description = "供应商名称", example = "芋道") + @ExcelProperty("供应商名称") + private String supplierName; + + @Schema(description = "结算账户编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "311.89") + @ExcelProperty("结算账户编号") + private Long accountId; + + @Schema(description = "退货时间", requiredMode = Schema.RequiredMode.REQUIRED) + @ExcelProperty("退货时间") + private LocalDateTime returnTime; + + @Schema(description = "采购订单编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "17386") + private Long orderId; + @Schema(description = "采购订单号", requiredMode = Schema.RequiredMode.REQUIRED, example = "XS001") + private String orderNo; + + @Schema(description = "合计数量", requiredMode = Schema.RequiredMode.REQUIRED, example = "15663") + @ExcelProperty("合计数量") + private BigDecimal totalCount; + @Schema(description = "最终合计价格", requiredMode = Schema.RequiredMode.REQUIRED, example = "24906") + @ExcelProperty("最终合计价格") + private BigDecimal totalPrice; + + @Schema(description = "合计产品价格,单位:元", requiredMode = Schema.RequiredMode.REQUIRED, example = "7127") + private BigDecimal totalProductPrice; + + @Schema(description = "合计税额,单位:元", requiredMode = Schema.RequiredMode.REQUIRED, example = "7127") + private BigDecimal totalTaxPrice; + + @Schema(description = "优惠率,百分比", requiredMode = Schema.RequiredMode.REQUIRED, example = "99.88") + private BigDecimal discountPercent; + + @Schema(description = "优惠金额,单位:元", requiredMode = Schema.RequiredMode.REQUIRED, example = "7127") + private BigDecimal discountPrice; + + @Schema(description = "定金金额,单位:元", requiredMode = Schema.RequiredMode.REQUIRED, example = "7127") + private BigDecimal otherPrice; + + @Schema(description = "本次退款,单位:元", requiredMode = Schema.RequiredMode.REQUIRED, example = "7127") + private BigDecimal refundPrice; + @Schema(description = "本次欠款,单位:元", requiredMode = Schema.RequiredMode.REQUIRED, example = "666") + private BigDecimal debtPrice; + + @Schema(description = "附件地址", example = "https://www.iocoder.cn") + @ExcelProperty("附件地址") + private String fileUrl; + + @Schema(description = "备注", example = "你猜") + @ExcelProperty("备注") + private String remark; + + @Schema(description = "创建人", example = "芋道") + private String creator; + @Schema(description = "创建人名称", example = "芋道") + private String creatorName; + + @Schema(description = "创建时间", requiredMode = Schema.RequiredMode.REQUIRED) + @ExcelProperty("创建时间") + private LocalDateTime createTime; + + @Schema(description = "退货项列表", requiredMode = Schema.RequiredMode.REQUIRED) + private List items; + + @Schema(description = "产品信息", requiredMode = Schema.RequiredMode.REQUIRED) + @ExcelProperty("产品信息") + private String productNames; + + @Data + public static class Item { + + @Schema(description = "退货项编号", example = "11756") + private Long id; + + @Schema(description = "采购订单项编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "11756") + private Long orderItemId; + + @Schema(description = "仓库编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "3113") + private Long warehouseId; + + @Schema(description = "产品编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "3113") + private Long productId; + + @Schema(description = "产品单位单位", requiredMode = Schema.RequiredMode.REQUIRED, example = "3113") + private Long productUnitId; + + @Schema(description = "产品单价", example = "100.00") + private BigDecimal productPrice; + + @Schema(description = "产品数量", requiredMode = Schema.RequiredMode.REQUIRED, example = "100.00") + @NotNull(message = "产品数量不能为空") + private BigDecimal count; + + @Schema(description = "税率,百分比", example = "99.88") + private BigDecimal taxPercent; + + @Schema(description = "税额,单位:元", example = "100.00") + private BigDecimal taxPrice; + + @Schema(description = "备注", example = "随便") + private String remark; + + // ========== 关联字段 ========== + + @Schema(description = "产品名称", requiredMode = Schema.RequiredMode.REQUIRED, example = "巧克力") + private String productName; + @Schema(description = "产品条码", requiredMode = Schema.RequiredMode.REQUIRED, example = "A9985") + private String productBarCode; + @Schema(description = "产品单位名称", requiredMode = Schema.RequiredMode.REQUIRED, example = "盒") + private String productUnitName; + + @Schema(description = "库存数量", requiredMode = Schema.RequiredMode.REQUIRED, example = "100.00") + private BigDecimal stockCount; // 该字段仅仅在“详情”和“编辑”时使用 + + } + +} \ No newline at end of file diff --git a/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/controller/admin/purchase/vo/returns/ErpPurchaseReturnSaveReqVO.java b/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/controller/admin/purchase/vo/returns/ErpPurchaseReturnSaveReqVO.java new file mode 100644 index 000000000..ae258c06a --- /dev/null +++ b/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/controller/admin/purchase/vo/returns/ErpPurchaseReturnSaveReqVO.java @@ -0,0 +1,85 @@ +package cn.iocoder.yudao.module.erp.controller.admin.purchase.vo.returns; + +import io.swagger.v3.oas.annotations.media.Schema; +import jakarta.validation.constraints.NotNull; +import lombok.Data; + +import java.math.BigDecimal; +import java.time.LocalDateTime; +import java.util.List; + +@Schema(description = "管理后台 - ERP 采购退货新增/修改 Request VO") +@Data +public class ErpPurchaseReturnSaveReqVO { + + @Schema(description = "编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "17386") + private Long id; + + @Schema(description = "结算账户编号", example = "31189") + private Long accountId; + + @Schema(description = "退货时间", requiredMode = Schema.RequiredMode.REQUIRED) + @NotNull(message = "退货时间不能为空") + private LocalDateTime returnTime; + + @Schema(description = "采购订单编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "17386") + @NotNull(message = "采购订单编号不能为空") + private Long orderId; + + @Schema(description = "优惠率,百分比", requiredMode = Schema.RequiredMode.REQUIRED, example = "99.88") + private BigDecimal discountPercent; + + @Schema(description = "其它金额,单位:元", example = "7127") + private BigDecimal otherPrice; + + @Schema(description = "本次退款,单位:元", requiredMode = Schema.RequiredMode.REQUIRED, example = "7127") + @NotNull(message = "本次退款不能为空") + private BigDecimal refundPrice; + + @Schema(description = "附件地址", example = "https://www.iocoder.cn") + private String fileUrl; + + @Schema(description = "备注", example = "你猜") + private String remark; + + @Schema(description = "退货清单列表") + private List items; + + @Data + public static class Item { + + @Schema(description = "退货项编号", example = "11756") + private Long id; + + @Schema(description = "采购订单项编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "11756") + @NotNull(message = "采购订单项编号不能为空") + private Long orderItemId; + + @Schema(description = "仓库编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "3113") + @NotNull(message = "仓库编号不能为空") + private Long warehouseId; + + @Schema(description = "产品编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "3113") + @NotNull(message = "产品编号不能为空") + private Long productId; + + @Schema(description = "产品单位单位", requiredMode = Schema.RequiredMode.REQUIRED, example = "3113") + @NotNull(message = "产品单位单位不能为空") + private Long productUnitId; + + @Schema(description = "产品单价", example = "100.00") + private BigDecimal productPrice; + + @Schema(description = "产品数量", requiredMode = Schema.RequiredMode.REQUIRED, example = "100.00") + @NotNull(message = "产品数量不能为空") + private BigDecimal count; + + @Schema(description = "税率,百分比", example = "99.88") + private BigDecimal taxPercent; + + @Schema(description = "备注", example = "随便") + private String remark; + + } + +} \ No newline at end of file diff --git a/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/dal/dataobject/purchase/ErpPurchaseInDO.java b/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/dal/dataobject/purchase/ErpPurchaseInDO.java index 51dc90f59..5e7ff5947 100644 --- a/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/dal/dataobject/purchase/ErpPurchaseInDO.java +++ b/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/dal/dataobject/purchase/ErpPurchaseInDO.java @@ -31,7 +31,7 @@ public class ErpPurchaseInDO extends BaseDO { @TableId private Long id; /** - * 销售入库单号 + * 采购入库单号 */ private String no; /** @@ -105,7 +105,7 @@ public class ErpPurchaseInDO extends BaseDO { private BigDecimal otherPrice; /** - * 本次收款,单位:元 + * 本次退款,单位:元 * * refundPrice = totalPrice + otherPrice - debtPrice */ diff --git a/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/dal/dataobject/purchase/ErpPurchaseReturnDO.java b/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/dal/dataobject/purchase/ErpPurchaseReturnDO.java new file mode 100644 index 000000000..0ec4ac6fd --- /dev/null +++ b/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/dal/dataobject/purchase/ErpPurchaseReturnDO.java @@ -0,0 +1,127 @@ +package cn.iocoder.yudao.module.erp.dal.dataobject.purchase; + +import cn.iocoder.yudao.framework.mybatis.core.dataobject.BaseDO; +import cn.iocoder.yudao.module.erp.dal.dataobject.finance.ErpAccountDO; +import com.baomidou.mybatisplus.annotation.KeySequence; +import com.baomidou.mybatisplus.annotation.TableId; +import com.baomidou.mybatisplus.annotation.TableName; +import lombok.*; + +import java.math.BigDecimal; +import java.time.LocalDateTime; + +/** + * ERP 采购退货 DO + * + * @author 芋道源码 + */ +@TableName(value = "erp_purchase_return") +@KeySequence("erp_purchase_return_seq") // 用于 Oracle、PostgreSQL、Kingbase、DB2、H2 数据库的主键自增。如果是 MySQL 等数据库,可不写。 +@Data +@EqualsAndHashCode(callSuper = true) +@ToString(callSuper = true) +@Builder +@NoArgsConstructor +@AllArgsConstructor +public class ErpPurchaseReturnDO extends BaseDO { + + /** + * 编号 + */ + @TableId + private Long id; + /** + * 采购退货单号 + */ + private String no; + /** + * 退货状态 + * + * 枚举 {@link cn.iocoder.yudao.module.erp.enums.ErpAuditStatus} + */ + private Integer status; + /** + * 供应商编号 + * + * 关联 {@link ErpSupplierDO#getId()} + */ + private Long supplierId; + /** + * 结算账户编号 + * + * 关联 {@link ErpAccountDO#getId()} + */ + private Long accountId; + /** + * 退货时间 + */ + private LocalDateTime returnTime; + + /** + * 采购订单编号 + * + * 关联 {@link ErpPurchaseOrderDO#getId()} + */ + private Long orderId; + /** + * 采购订单号 + * + * 冗余 {@link ErpPurchaseOrderDO#getNo()} + */ + private String orderNo; + + /** + * 合计数量 + */ + private BigDecimal totalCount; + /** + * 最终合计价格,单位:元 + * + * totalPrice = totalProductPrice + totalTaxPrice - discountPrice + */ + private BigDecimal totalPrice; + + /** + * 合计产品价格,单位:元 + */ + private BigDecimal totalProductPrice; + /** + * 合计税额,单位:元 + */ + private BigDecimal totalTaxPrice; + /** + * 优惠率,百分比 + */ + private BigDecimal discountPercent; + /** + * 优惠金额,单位:元 + * + * discountPrice = (totalProductPrice + totalTaxPrice) * discountPercent + */ + private BigDecimal discountPrice; + /** + * 其它金额,单位:元 + */ + private BigDecimal otherPrice; + + /** + * 本次退款,单位:元 + * + * refundPrice = totalPrice + otherPrice - debtPrice + */ + private BigDecimal refundPrice; + /** + * 本次欠款,单位:元 + */ + private BigDecimal debtPrice; + + /** + * 附件地址 + */ + private String fileUrl; + /** + * 备注 + */ + private String remark; + +} \ No newline at end of file diff --git a/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/dal/dataobject/purchase/ErpPurchaseReturnItemDO.java b/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/dal/dataobject/purchase/ErpPurchaseReturnItemDO.java new file mode 100644 index 000000000..1e1713277 --- /dev/null +++ b/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/dal/dataobject/purchase/ErpPurchaseReturnItemDO.java @@ -0,0 +1,95 @@ +package cn.iocoder.yudao.module.erp.dal.dataobject.purchase; + +import cn.iocoder.yudao.framework.mybatis.core.dataobject.BaseDO; +import cn.iocoder.yudao.module.erp.dal.dataobject.product.ErpProductDO; +import cn.iocoder.yudao.module.erp.dal.dataobject.stock.ErpWarehouseDO; +import com.baomidou.mybatisplus.annotation.KeySequence; +import com.baomidou.mybatisplus.annotation.TableId; +import com.baomidou.mybatisplus.annotation.TableName; +import lombok.*; + +import java.math.BigDecimal; + +/** + * ERP 采购退货项 DO + * + * @author 芋道源码 + */ +@TableName("erp_purchase_return_items") +@KeySequence("erp_purchase_return_items_seq") // 用于 Oracle、PostgreSQL、Kingbase、DB2、H2 数据库的主键自增。如果是 MySQL 等数据库,可不写。 +@Data +@EqualsAndHashCode(callSuper = true) +@ToString(callSuper = true) +@Builder +@NoArgsConstructor +@AllArgsConstructor +public class ErpPurchaseReturnItemDO extends BaseDO { + + /** + * 编号 + */ + @TableId + private Long id; + /** + * 采购退货编号 + * + * 关联 {@link ErpPurchaseReturnDO##getId()} + */ + private Long returnId; + /** + * 采购订单项编号 + * + * 关联 {@link ErpPurchaseOrderItemDO#getId()} + * 目的:方便更新关联的采购订单项的退货数量 + */ + private Long orderItemId; + /** + * 仓库编号 + * + * 关联 {@link ErpWarehouseDO#getId()} + */ + private Long warehouseId; + /** + * 产品编号 + * + * 关联 {@link ErpProductDO#getId()} + */ + private Long productId; + /** + * 产品单位单位 + * + * 冗余 {@link ErpProductDO#getUnitId()} + */ + private Long productUnitId; + + /** + * 产品单位单价,单位:元 + */ + private BigDecimal productPrice; + /** + * 数量 + */ + private BigDecimal count; + /** + * 总价,单位:元 + * + * totalPrice = productPrice * count + */ + private BigDecimal totalPrice; + /** + * 税率,百分比 + */ + private BigDecimal taxPercent; + /** + * 税额,单位:元 + * + * taxPrice = totalPrice * taxPercent + */ + private BigDecimal taxPrice; + + /** + * 备注 + */ + private String remark; + +} \ No newline at end of file diff --git a/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/dal/mysql/purchase/ErpPurchaseInItemMapper.java b/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/dal/mysql/purchase/ErpPurchaseInItemMapper.java index b3a6987e2..9140f9548 100644 --- a/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/dal/mysql/purchase/ErpPurchaseInItemMapper.java +++ b/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/dal/mysql/purchase/ErpPurchaseInItemMapper.java @@ -35,10 +35,10 @@ public interface ErpPurchaseInItemMapper extends BaseMapperX selectOrderItemCountSumMapByInIds(Collection inIds) { if (CollUtil.isEmpty(inIds)) { diff --git a/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/dal/mysql/purchase/ErpPurchaseOrderMapper.java b/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/dal/mysql/purchase/ErpPurchaseOrderMapper.java index 8061c6f0d..01f0303f9 100644 --- a/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/dal/mysql/purchase/ErpPurchaseOrderMapper.java +++ b/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/dal/mysql/purchase/ErpPurchaseOrderMapper.java @@ -45,7 +45,7 @@ public interface ErpPurchaseOrderMapper extends BaseMapperX } else if (Objects.equals(reqVO.getReturnStatus(), ErpPurchaseOrderPageReqVO.RETURN_STATUS_ALL)) { query.apply("t.return_count = t.total_count"); } - // 可采购出库 + // 可采购入库 if (Boolean.TRUE.equals(reqVO.getInEnable())) { query.eq(ErpPurchaseOrderDO::getStatus, ErpAuditStatus.APPROVE.getStatus()) .apply("t.in_count < t.total_count"); diff --git a/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/dal/mysql/purchase/ErpPurchaseReturnItemMapper.java b/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/dal/mysql/purchase/ErpPurchaseReturnItemMapper.java new file mode 100644 index 000000000..2a8011900 --- /dev/null +++ b/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/dal/mysql/purchase/ErpPurchaseReturnItemMapper.java @@ -0,0 +1,56 @@ +package cn.iocoder.yudao.module.erp.dal.mysql.purchase; + +import cn.hutool.core.collection.CollUtil; +import cn.iocoder.yudao.framework.mybatis.core.mapper.BaseMapperX; +import cn.iocoder.yudao.module.erp.dal.dataobject.purchase.ErpPurchaseReturnItemDO; +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 + * + * @author 芋道源码 + */ +@Mapper +public interface ErpPurchaseReturnItemMapper extends BaseMapperX { + + default List selectListByReturnId(Long returnId) { + return selectList(ErpPurchaseReturnItemDO::getReturnId, returnId); + } + + default List selectListByReturnIds(Collection returnIds) { + return selectList(ErpPurchaseReturnItemDO::getReturnId, returnIds); + } + + default int deleteByReturnId(Long returnId) { + return delete(ErpPurchaseReturnItemDO::getReturnId, returnId); + } + + /** + * 基于采购订单编号,查询每个采购订单项的退货数量之和 + * + * @param returnIds 入库订单项编号数组 + * @return key:采购订单项编号;value:退货数量之和 + */ + default Map selectOrderItemCountSumMapByReturnIds(Collection returnIds) { + if (CollUtil.isEmpty(returnIds)) { + return Collections.emptyMap(); + } + // SQL sum 查询 + List> result = selectMaps(new QueryWrapper() + .select("order_item_id, SUM(count) AS sumCount") + .groupBy("order_item_id") + .in("return_id", returnIds)); + // 获得数量 + return convertMap(result, obj -> (Long) obj.get("order_item_id"), obj -> (BigDecimal) obj.get("sumCount")); + } + +} \ No newline at end of file diff --git a/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/dal/mysql/purchase/ErpPurchaseReturnMapper.java b/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/dal/mysql/purchase/ErpPurchaseReturnMapper.java new file mode 100644 index 000000000..716b27574 --- /dev/null +++ b/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/dal/mysql/purchase/ErpPurchaseReturnMapper.java @@ -0,0 +1,55 @@ +package cn.iocoder.yudao.module.erp.dal.mysql.purchase; + +import cn.iocoder.yudao.framework.common.pojo.PageResult; +import cn.iocoder.yudao.framework.mybatis.core.mapper.BaseMapperX; +import cn.iocoder.yudao.framework.mybatis.core.query.MPJLambdaWrapperX; +import cn.iocoder.yudao.module.erp.controller.admin.purchase.vo.returns.ErpPurchaseReturnPageReqVO; +import cn.iocoder.yudao.module.erp.dal.dataobject.purchase.ErpPurchaseReturnDO; +import cn.iocoder.yudao.module.erp.dal.dataobject.purchase.ErpPurchaseReturnItemDO; +import com.baomidou.mybatisplus.core.conditions.update.LambdaUpdateWrapper; +import org.apache.ibatis.annotations.Mapper; + +import java.util.List; + +/** + * ERP 采购退货 Mapper + * + * @author 芋道源码 + */ +@Mapper +public interface ErpPurchaseReturnMapper extends BaseMapperX { + + default PageResult selectPage(ErpPurchaseReturnPageReqVO reqVO) { + MPJLambdaWrapperX query = new MPJLambdaWrapperX() + .likeIfPresent(ErpPurchaseReturnDO::getNo, reqVO.getNo()) + .eqIfPresent(ErpPurchaseReturnDO::getSupplierId, reqVO.getSupplierId()) + .betweenIfPresent(ErpPurchaseReturnDO::getReturnTime, reqVO.getReturnTime()) + .eqIfPresent(ErpPurchaseReturnDO::getStatus, reqVO.getStatus()) + .likeIfPresent(ErpPurchaseReturnDO::getRemark, reqVO.getRemark()) + .eqIfPresent(ErpPurchaseReturnDO::getCreator, reqVO.getCreator()) + .eqIfPresent(ErpPurchaseReturnDO::getAccountId, reqVO.getAccountId()) + .likeIfPresent(ErpPurchaseReturnDO::getOrderNo, reqVO.getOrderNo()) + .orderByDesc(ErpPurchaseReturnDO::getId); + if (reqVO.getWarehouseId() != null || reqVO.getProductId() != null) { + query.leftJoin(ErpPurchaseReturnItemDO.class, ErpPurchaseReturnItemDO::getReturnId, ErpPurchaseReturnDO::getId) + .eq(reqVO.getWarehouseId() != null, ErpPurchaseReturnItemDO::getWarehouseId, reqVO.getWarehouseId()) + .eq(reqVO.getProductId() != null, ErpPurchaseReturnItemDO::getProductId, reqVO.getProductId()) + .groupBy(ErpPurchaseReturnDO::getId); // 避免 1 对多查询,产生相同的 1 + } + return selectJoinPage(reqVO, ErpPurchaseReturnDO.class, query); + } + + default int updateByIdAndStatus(Long id, Integer status, ErpPurchaseReturnDO updateObj) { + return update(updateObj, new LambdaUpdateWrapper() + .eq(ErpPurchaseReturnDO::getId, id).eq(ErpPurchaseReturnDO::getStatus, status)); + } + + default ErpPurchaseReturnDO selectByNo(String no) { + return selectOne(ErpPurchaseReturnDO::getNo, no); + } + + default List selectListByOrderId(Long orderId) { + return selectList(ErpPurchaseReturnDO::getOrderId, orderId); + } + +} \ No newline at end of file diff --git a/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/dal/mysql/sale/ErpSaleReturnItemMapper.java b/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/dal/mysql/sale/ErpSaleReturnItemMapper.java index 771a0e904..fdc572964 100644 --- a/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/dal/mysql/sale/ErpSaleReturnItemMapper.java +++ b/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/dal/mysql/sale/ErpSaleReturnItemMapper.java @@ -35,10 +35,10 @@ public interface ErpSaleReturnItemMapper extends BaseMapperX selectOrderItemCountSumMapByReturnIds(Collection returnIds) { if (CollUtil.isEmpty(returnIds)) { diff --git a/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/dal/redis/no/ErpNoRedisDAO.java b/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/dal/redis/no/ErpNoRedisDAO.java index f7a258634..f2e72a4dd 100644 --- a/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/dal/redis/no/ErpNoRedisDAO.java +++ b/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/dal/redis/no/ErpNoRedisDAO.java @@ -59,6 +59,10 @@ public class ErpNoRedisDAO { * 采购入库 {@link cn.iocoder.yudao.module.erp.dal.dataobject.purchase.ErpPurchaseInDO} */ public static final String PURCHASE_IN_NO_PREFIX = "CGRK"; + /** + * 采购退货 {@link cn.iocoder.yudao.module.erp.dal.dataobject.purchase.ErpPurchaseReturnDO} + */ + public static final String PURCHASE_RETURN_NO_PREFIX = "CGTH"; @Resource private StringRedisTemplate stringRedisTemplate; @@ -76,7 +80,7 @@ public class ErpNoRedisDAO { String key = RedisKeyConstants.NO + noPrefix; Long no = stringRedisTemplate.opsForValue().increment(key); // 设置过期时间 - stringRedisTemplate.expire(key, Duration.ofMinutes(1L)); + stringRedisTemplate.expire(key, Duration.ofDays(1L)); return noPrefix + String.format("%06d", no); } diff --git a/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/service/purchase/ErpPurchaseReturnService.java b/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/service/purchase/ErpPurchaseReturnService.java new file mode 100644 index 000000000..b8e0ad665 --- /dev/null +++ b/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/service/purchase/ErpPurchaseReturnService.java @@ -0,0 +1,84 @@ +package cn.iocoder.yudao.module.erp.service.purchase; + +import cn.iocoder.yudao.framework.common.pojo.PageResult; +import cn.iocoder.yudao.module.erp.controller.admin.purchase.vo.returns.ErpPurchaseReturnPageReqVO; +import cn.iocoder.yudao.module.erp.controller.admin.purchase.vo.returns.ErpPurchaseReturnSaveReqVO; +import cn.iocoder.yudao.module.erp.dal.dataobject.purchase.ErpPurchaseReturnDO; +import cn.iocoder.yudao.module.erp.dal.dataobject.purchase.ErpPurchaseReturnItemDO; +import jakarta.validation.Valid; + +import java.util.Collection; +import java.util.List; + +/** + * ERP 采购退货 Service 接口 + * + * @author 芋道源码 + */ +public interface ErpPurchaseReturnService { + + /** + * 创建采购退货 + * + * @param createReqVO 创建信息 + * @return 编号 + */ + Long createPurchaseReturn(@Valid ErpPurchaseReturnSaveReqVO createReqVO); + + /** + * 更新采购退货 + * + * @param updateReqVO 更新信息 + */ + void updatePurchaseReturn(@Valid ErpPurchaseReturnSaveReqVO updateReqVO); + + /** + * 更新采购退货的状态 + * + * @param id 编号 + * @param status 状态 + */ + void updatePurchaseReturnStatus(Long id, Integer status); + + /** + * 删除采购退货 + * + * @param ids 编号数组 + */ + void deletePurchaseReturn(List ids); + + /** + * 获得采购退货 + * + * @param id 编号 + * @return 采购退货 + */ + ErpPurchaseReturnDO getPurchaseReturn(Long id); + + /** + * 获得采购退货分页 + * + * @param pageReqVO 分页查询 + * @return 采购退货分页 + */ + PageResult getPurchaseReturnPage(ErpPurchaseReturnPageReqVO pageReqVO); + + // ==================== 采购退货项 ==================== + + /** + * 获得采购退货项列表 + * + * @param returnId 采购退货编号 + * @return 采购退货项列表 + */ + List getPurchaseReturnItemListByReturnId(Long returnId); + + /** + * 获得采购退货项 List + * + * @param returnIds 采购退货编号数组 + * @return 采购退货项 List + */ + List getPurchaseReturnItemListByReturnIds(Collection returnIds); + +} \ No newline at end of file diff --git a/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/service/purchase/ErpPurchaseReturnServiceImpl.java b/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/service/purchase/ErpPurchaseReturnServiceImpl.java new file mode 100644 index 000000000..1d503178a --- /dev/null +++ b/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/service/purchase/ErpPurchaseReturnServiceImpl.java @@ -0,0 +1,282 @@ +package cn.iocoder.yudao.module.erp.service.purchase; + +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.purchase.vo.returns.ErpPurchaseReturnPageReqVO; +import cn.iocoder.yudao.module.erp.controller.admin.purchase.vo.returns.ErpPurchaseReturnSaveReqVO; +import cn.iocoder.yudao.module.erp.dal.dataobject.product.ErpProductDO; +import cn.iocoder.yudao.module.erp.dal.dataobject.purchase.ErpPurchaseOrderDO; +import cn.iocoder.yudao.module.erp.dal.dataobject.purchase.ErpPurchaseReturnDO; +import cn.iocoder.yudao.module.erp.dal.dataobject.purchase.ErpPurchaseReturnItemDO; +import cn.iocoder.yudao.module.erp.dal.mysql.purchase.ErpPurchaseReturnItemMapper; +import cn.iocoder.yudao.module.erp.dal.mysql.purchase.ErpPurchaseReturnMapper; +import cn.iocoder.yudao.module.erp.dal.redis.no.ErpNoRedisDAO; +import cn.iocoder.yudao.module.erp.enums.ErpAuditStatus; +import cn.iocoder.yudao.module.erp.enums.stock.ErpStockRecordBizTypeEnum; +import cn.iocoder.yudao.module.erp.service.finance.ErpAccountService; +import cn.iocoder.yudao.module.erp.service.product.ErpProductService; +import cn.iocoder.yudao.module.erp.service.stock.ErpStockRecordService; +import cn.iocoder.yudao.module.erp.service.stock.bo.ErpStockRecordCreateReqBO; +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; + +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.exception.util.ServiceExceptionUtil.exception; +import static cn.iocoder.yudao.framework.common.util.collection.CollectionUtils.*; +import static cn.iocoder.yudao.module.erp.enums.ErrorCodeConstants.*; + +// TODO 芋艿:记录操作日志 + +/** + * ERP 采购退货 Service 实现类 + * + * @author 芋道源码 + */ +@Service +@Validated +public class ErpPurchaseReturnServiceImpl implements ErpPurchaseReturnService { + + @Resource + private ErpPurchaseReturnMapper purchaseReturnMapper; + @Resource + private ErpPurchaseReturnItemMapper purchaseReturnItemMapper; + + @Resource + private ErpNoRedisDAO noRedisDAO; + + @Resource + private ErpProductService productService; + @Resource + @Lazy // 延迟加载,避免循环依赖 + private ErpPurchaseOrderService purchaseOrderService; + @Resource + private ErpAccountService accountService; + @Resource + private ErpStockRecordService stockRecordService; + + @Override + @Transactional(rollbackFor = Exception.class) + public Long createPurchaseReturn(ErpPurchaseReturnSaveReqVO createReqVO) { + // 1.1 校验采购订单已审核 + ErpPurchaseOrderDO purchaseOrder = purchaseOrderService.validatePurchaseOrder(createReqVO.getOrderId()); + // 1.2 校验退货项的有效性 + List purchaseReturnItems = validatePurchaseReturnItems(createReqVO.getItems()); + // 1.3 校验结算账户 + accountService.validateAccount(createReqVO.getAccountId()); + // 1.4 生成调拨单号,并校验唯一性 + String no = noRedisDAO.generate(ErpNoRedisDAO.PURCHASE_RETURN_NO_PREFIX); + if (purchaseReturnMapper.selectByNo(no) != null) { + throw exception(PURCHASE_RETURN_NO_EXISTS); + } + + // 2.1 插入退货 + ErpPurchaseReturnDO purchaseReturn = BeanUtils.toBean(createReqVO, ErpPurchaseReturnDO.class, in -> in + .setNo(no).setStatus(ErpAuditStatus.PROCESS.getStatus())) + .setOrderNo(purchaseOrder.getNo()).setSupplierId(purchaseOrder.getSupplierId()); + calculateTotalPrice(purchaseReturn, purchaseReturnItems); + purchaseReturnMapper.insert(purchaseReturn); + // 2.2 插入退货项 + purchaseReturnItems.forEach(o -> o.setReturnId(purchaseReturn.getId())); + purchaseReturnItemMapper.insertBatch(purchaseReturnItems); + + // 3. 更新采购订单的退货数量 + updatePurchaseOrderReturnCount(createReqVO.getOrderId()); + return purchaseReturn.getId(); + } + + @Override + @Transactional(rollbackFor = Exception.class) + public void updatePurchaseReturn(ErpPurchaseReturnSaveReqVO updateReqVO) { + // 1.1 校验存在 + ErpPurchaseReturnDO purchaseReturn = validatePurchaseReturnExists(updateReqVO.getId()); + if (ErpAuditStatus.APPROVE.getStatus().equals(purchaseReturn.getStatus())) { + throw exception(PURCHASE_RETURN_UPDATE_FAIL_APPROVE, purchaseReturn.getNo()); + } + // 1.2 校验采购订单已审核 + ErpPurchaseOrderDO purchaseOrder = purchaseOrderService.validatePurchaseOrder(updateReqVO.getOrderId()); + // 1.3 校验结算账户 + accountService.validateAccount(updateReqVO.getAccountId()); + // 1.4 校验订单项的有效性 + List purchaseReturnItems = validatePurchaseReturnItems(updateReqVO.getItems()); + + // 2.1 更新退货 + ErpPurchaseReturnDO updateObj = BeanUtils.toBean(updateReqVO, ErpPurchaseReturnDO.class) + .setOrderNo(purchaseOrder.getNo()).setSupplierId(purchaseOrder.getSupplierId()); + calculateTotalPrice(updateObj, purchaseReturnItems); + purchaseReturnMapper.updateById(updateObj); + // 2.2 更新退货项 + updatePurchaseReturnItemList(updateReqVO.getId(), purchaseReturnItems); + + // 3.1 更新采购订单的出库数量 + updatePurchaseOrderReturnCount(updateObj.getOrderId()); + // 3.2 注意:如果采购订单编号变更了,需要更新“老”采购订单的出库数量 + if (ObjectUtil.notEqual(purchaseReturn.getOrderId(), updateObj.getOrderId())) { + updatePurchaseOrderReturnCount(purchaseReturn.getOrderId()); + } + } + + private void calculateTotalPrice(ErpPurchaseReturnDO purchaseReturn, List purchaseReturnItems) { + purchaseReturn.setTotalCount(getSumValue(purchaseReturnItems, ErpPurchaseReturnItemDO::getCount, BigDecimal::add)); + purchaseReturn.setTotalProductPrice(getSumValue(purchaseReturnItems, ErpPurchaseReturnItemDO::getTotalPrice, BigDecimal::add, BigDecimal.ZERO)); + purchaseReturn.setTotalTaxPrice(getSumValue(purchaseReturnItems, ErpPurchaseReturnItemDO::getTaxPrice, BigDecimal::add, BigDecimal.ZERO)); + purchaseReturn.setTotalPrice(purchaseReturn.getTotalProductPrice().add(purchaseReturn.getTotalTaxPrice())); + // 计算优惠价格 + if (purchaseReturn.getDiscountPercent() == null) { + purchaseReturn.setDiscountPercent(BigDecimal.ZERO); + } + purchaseReturn.setDiscountPrice(MoneyUtils.priceMultiplyPercent(purchaseReturn.getTotalPrice(), purchaseReturn.getDiscountPercent())); + purchaseReturn.setTotalPrice(purchaseReturn.getTotalPrice().subtract(purchaseReturn.getDiscountPrice())); + // 计算应退金额 + BigDecimal allPrice = purchaseReturn.getTotalPrice().add(purchaseReturn.getOtherPrice()); + purchaseReturn.setDebtPrice(allPrice.subtract(purchaseReturn.getRefundPrice())); + } + + private void updatePurchaseOrderReturnCount(Long orderId) { + // 1.1 查询采购订单对应的采购出库单列表 + List purchaseReturns = purchaseReturnMapper.selectListByOrderId(orderId); + // 1.2 查询对应的采购订单项的退货数量 + Map returnCountMap = purchaseReturnItemMapper.selectOrderItemCountSumMapByReturnIds( + convertList(purchaseReturns, ErpPurchaseReturnDO::getId)); + // 2. 更新采购订单的出库数量 + purchaseOrderService.updatePurchaseOrderReturnCount(orderId, returnCountMap); + } + + @Override + @Transactional(rollbackFor = Exception.class) + public void updatePurchaseReturnStatus(Long id, Integer status) { + boolean approve = ErpAuditStatus.APPROVE.getStatus().equals(status); + // 1.1 校验存在 + ErpPurchaseReturnDO purchaseReturn = validatePurchaseReturnExists(id); + // 1.2 校验状态 + if (purchaseReturn.getStatus().equals(status)) { + throw exception(approve ? PURCHASE_RETURN_APPROVE_FAIL : PURCHASE_RETURN_PROCESS_FAIL); + } + + // 2. 更新状态 + int updateCount = purchaseReturnMapper.updateByIdAndStatus(id, purchaseReturn.getStatus(), + new ErpPurchaseReturnDO().setStatus(status)); + if (updateCount == 0) { + throw exception(approve ? PURCHASE_RETURN_APPROVE_FAIL : PURCHASE_RETURN_PROCESS_FAIL); + } + + // 3. 变更库存 + List purchaseReturnItems = purchaseReturnItemMapper.selectListByReturnId(id); + Integer bizType = approve ? ErpStockRecordBizTypeEnum.PURCHASE_RETURN.getType() + : ErpStockRecordBizTypeEnum.PURCHASE_RETURN_CANCEL.getType(); + purchaseReturnItems.forEach(purchaseReturnItem -> { + BigDecimal count = approve ? purchaseReturnItem.getCount().negate() : purchaseReturnItem.getCount(); + stockRecordService.createStockRecord(new ErpStockRecordCreateReqBO( + purchaseReturnItem.getProductId(), purchaseReturnItem.getWarehouseId(), count, + bizType, purchaseReturnItem.getReturnId(), purchaseReturnItem.getId(), purchaseReturn.getNo())); + }); + } + + private List validatePurchaseReturnItems(List list) { + // 1. 校验产品存在 + List productList = productService.validProductList( + convertSet(list, ErpPurchaseReturnSaveReqVO.Item::getProductId)); + Map productMap = convertMap(productList, ErpProductDO::getId); + // 2. 转化为 ErpPurchaseReturnItemDO 列表 + return convertList(list, o -> BeanUtils.toBean(o, ErpPurchaseReturnItemDO.class, item -> { + item.setProductUnitId(productMap.get(item.getProductId()).getUnitId()); + item.setTotalPrice(MoneyUtils.priceMultiply(item.getProductPrice(), item.getCount())); + if (item.getTotalPrice() == null) { + return; + } + if (item.getTaxPercent() != null) { + item.setTaxPrice(MoneyUtils.priceMultiplyPercent(item.getTotalPrice(), item.getTaxPercent())); + } + })); + } + + private void updatePurchaseReturnItemList(Long id, List newList) { + // 第一步,对比新老数据,获得添加、修改、删除的列表 + List oldList = purchaseReturnItemMapper.selectListByReturnId(id); + List> diffList = diffList(oldList, newList, // id 不同,就认为是不同的记录 + (oldVal, newVal) -> oldVal.getId().equals(newVal.getId())); + + // 第二步,批量添加、修改、删除 + if (CollUtil.isNotEmpty(diffList.get(0))) { + diffList.get(0).forEach(o -> o.setReturnId(id)); + purchaseReturnItemMapper.insertBatch(diffList.get(0)); + } + if (CollUtil.isNotEmpty(diffList.get(1))) { + purchaseReturnItemMapper.updateBatch(diffList.get(1)); + } + if (CollUtil.isNotEmpty(diffList.get(2))) { + purchaseReturnItemMapper.deleteBatchIds(convertList(diffList.get(2), ErpPurchaseReturnItemDO::getId)); + } + } + + @Override + @Transactional(rollbackFor = Exception.class) + public void deletePurchaseReturn(List ids) { + // 1. 校验不处于已审批 + List purchaseReturns = purchaseReturnMapper.selectBatchIds(ids); + if (CollUtil.isEmpty(purchaseReturns)) { + return; + } + purchaseReturns.forEach(purchaseReturn -> { + if (ErpAuditStatus.APPROVE.getStatus().equals(purchaseReturn.getStatus())) { + throw exception(PURCHASE_RETURN_DELETE_FAIL_APPROVE, purchaseReturn.getNo()); + } + }); + + // 2. 遍历删除,并记录操作日志 + purchaseReturns.forEach(purchaseReturn -> { + // 2.1 删除订单 + purchaseReturnMapper.deleteById(purchaseReturn.getId()); + // 2.2 删除订单项 + purchaseReturnItemMapper.deleteByReturnId(purchaseReturn.getId()); + + // 2.3 更新采购订单的出库数量 + updatePurchaseOrderReturnCount(purchaseReturn.getOrderId()); + }); + + } + + private ErpPurchaseReturnDO validatePurchaseReturnExists(Long id) { + ErpPurchaseReturnDO purchaseReturn = purchaseReturnMapper.selectById(id); + if (purchaseReturn == null) { + throw exception(PURCHASE_RETURN_NOT_EXISTS); + } + return purchaseReturn; + } + + @Override + public ErpPurchaseReturnDO getPurchaseReturn(Long id) { + return purchaseReturnMapper.selectById(id); + } + + @Override + public PageResult getPurchaseReturnPage(ErpPurchaseReturnPageReqVO pageReqVO) { + return purchaseReturnMapper.selectPage(pageReqVO); + } + + // ==================== 采购退货项 ==================== + + @Override + public List getPurchaseReturnItemListByReturnId(Long returnId) { + return purchaseReturnItemMapper.selectListByReturnId(returnId); + } + + @Override + public List getPurchaseReturnItemListByReturnIds(Collection returnIds) { + if (CollUtil.isEmpty(returnIds)) { + return Collections.emptyList(); + } + return purchaseReturnItemMapper.selectListByReturnIds(returnIds); + } + +} \ No newline at end of file diff --git a/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/service/sale/ErpSaleReturnServiceImpl.java b/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/service/sale/ErpSaleReturnServiceImpl.java index eaea5c00e..ae5775551 100644 --- a/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/service/sale/ErpSaleReturnServiceImpl.java +++ b/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/service/sale/ErpSaleReturnServiceImpl.java @@ -157,7 +157,7 @@ public class ErpSaleReturnServiceImpl implements ErpSaleReturnService { private void updateSaleOrderReturnCount(Long orderId) { // 1.1 查询销售订单对应的销售出库单列表 List saleReturns = saleReturnMapper.selectListByOrderId(orderId); - // 1.2 查询对应的销售订单项的出库数量 + // 1.2 查询对应的销售订单项的退货数量 Map returnCountMap = saleReturnItemMapper.selectOrderItemCountSumMapByReturnIds( convertList(saleReturns, ErpSaleReturnDO::getId)); // 2. 更新销售订单的出库数量 From 2d43c1f9beac3a67fc4f358e89759d4997caa6b1 Mon Sep 17 00:00:00 2001 From: YunaiV Date: Tue, 13 Feb 2024 14:33:02 +0800 Subject: [PATCH 106/119] =?UTF-8?q?=E2=9C=A8=20ERP=EF=BC=9A=E9=87=87?= =?UTF-8?q?=E8=B4=AD=E8=AE=A2=E5=8D=95=E7=9A=84=20paymentPrice=20=E8=B0=83?= =?UTF-8?q?=E6=95=B4=EF=BC=8C=E4=B8=BA=E6=8E=A5=E5=85=A5=E8=B4=A2=E5=8A=A1?= =?UTF-8?q?=E7=9A=84=E4=BB=98=E6=AC=BE=E5=8D=95=E5=81=9A=E5=87=86=E5=A4=87?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../vo/in/ErpPurchaseInPageReqVO.java | 11 +++++++++-- .../purchase/vo/in/ErpPurchaseInRespVO.java | 7 ++----- .../vo/in/ErpPurchaseInSaveReqVO.java | 4 ---- .../returns/ErpPurchaseReturnPageReqVO.java | 10 ++++++++++ .../vo/returns/ErpPurchaseReturnRespVO.java | 7 ++----- .../returns/ErpPurchaseReturnSaveReqVO.java | 4 ---- .../dataobject/purchase/ErpPurchaseInDO.java | 19 +++++++------------ .../purchase/ErpPurchaseReturnDO.java | 19 +++++++------------ .../erp/dal/dataobject/sale/ErpSaleOutDO.java | 1 + .../mysql/purchase/ErpPurchaseInMapper.java | 16 +++++++++++----- .../purchase/ErpPurchaseReturnMapper.java | 12 ++++++++++++ .../purchase/ErpPurchaseInServiceImpl.java | 5 +---- .../ErpPurchaseReturnServiceImpl.java | 5 +---- 13 files changed, 63 insertions(+), 57 deletions(-) diff --git a/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/controller/admin/purchase/vo/in/ErpPurchaseInPageReqVO.java b/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/controller/admin/purchase/vo/in/ErpPurchaseInPageReqVO.java index 2be52e5ff..e84607ce4 100644 --- a/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/controller/admin/purchase/vo/in/ErpPurchaseInPageReqVO.java +++ b/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/controller/admin/purchase/vo/in/ErpPurchaseInPageReqVO.java @@ -17,6 +17,10 @@ import static cn.iocoder.yudao.framework.common.util.date.DateUtils.FORMAT_YEAR_ @ToString(callSuper = true) public class ErpPurchaseInPageReqVO extends PageParam { + public static final Integer PAYMENT_STATUS_NONE = 0; + public static final Integer PAYMENT_STATUS_PART = 1; + public static final Integer PAYMENT_STATUS_ALL = 2; + @Schema(description = "采购单编号", example = "XS001") private String no; @@ -45,8 +49,11 @@ public class ErpPurchaseInPageReqVO extends PageParam { @Schema(description = "结算账号编号", example = "1") private Long accountId; - @Schema(description = "是否欠款", example = "true") - private Boolean debtStatus; + @Schema(description = "付款状态", example = "1") + private Integer paymentStatus; + + @Schema(description = "是否可付款", example = "true") + private Boolean paymentEnable; // 对应 paymentStatus = [0, 1] @Schema(description = "采购单号", example = "1") private String orderNo; diff --git a/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/controller/admin/purchase/vo/in/ErpPurchaseInRespVO.java b/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/controller/admin/purchase/vo/in/ErpPurchaseInRespVO.java index fe6a31010..beeeab869 100644 --- a/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/controller/admin/purchase/vo/in/ErpPurchaseInRespVO.java +++ b/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/controller/admin/purchase/vo/in/ErpPurchaseInRespVO.java @@ -52,6 +52,8 @@ public class ErpPurchaseInRespVO { @Schema(description = "最终合计价格", requiredMode = Schema.RequiredMode.REQUIRED, example = "24906") @ExcelProperty("最终合计价格") private BigDecimal totalPrice; + @Schema(description = "已付款金额,单位:元", requiredMode = Schema.RequiredMode.REQUIRED, example = "7127") + private BigDecimal paymentPrice; @Schema(description = "合计产品价格,单位:元", requiredMode = Schema.RequiredMode.REQUIRED, example = "7127") private BigDecimal totalProductPrice; @@ -68,11 +70,6 @@ public class ErpPurchaseInRespVO { @Schema(description = "定金金额,单位:元", requiredMode = Schema.RequiredMode.REQUIRED, example = "7127") private BigDecimal otherPrice; - @Schema(description = "本次付款,单位:元", requiredMode = Schema.RequiredMode.REQUIRED, example = "7127") - private BigDecimal refundPrice; - @Schema(description = "本次欠款,单位:元", requiredMode = Schema.RequiredMode.REQUIRED, example = "666") - private BigDecimal debtPrice; - @Schema(description = "附件地址", example = "https://www.iocoder.cn") @ExcelProperty("附件地址") private String fileUrl; diff --git a/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/controller/admin/purchase/vo/in/ErpPurchaseInSaveReqVO.java b/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/controller/admin/purchase/vo/in/ErpPurchaseInSaveReqVO.java index 64dbac499..80edeec6d 100644 --- a/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/controller/admin/purchase/vo/in/ErpPurchaseInSaveReqVO.java +++ b/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/controller/admin/purchase/vo/in/ErpPurchaseInSaveReqVO.java @@ -32,10 +32,6 @@ public class ErpPurchaseInSaveReqVO { @Schema(description = "其它金额,单位:元", example = "7127") private BigDecimal otherPrice; - @Schema(description = "本次付款,单位:元", requiredMode = Schema.RequiredMode.REQUIRED, example = "7127") - @NotNull(message = "本次付款不能为空") - private BigDecimal refundPrice; - @Schema(description = "附件地址", example = "https://www.iocoder.cn") private String fileUrl; diff --git a/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/controller/admin/purchase/vo/returns/ErpPurchaseReturnPageReqVO.java b/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/controller/admin/purchase/vo/returns/ErpPurchaseReturnPageReqVO.java index b9d9d4b0b..a534d2e3e 100644 --- a/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/controller/admin/purchase/vo/returns/ErpPurchaseReturnPageReqVO.java +++ b/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/controller/admin/purchase/vo/returns/ErpPurchaseReturnPageReqVO.java @@ -17,6 +17,10 @@ import static cn.iocoder.yudao.framework.common.util.date.DateUtils.FORMAT_YEAR_ @ToString(callSuper = true) public class ErpPurchaseReturnPageReqVO extends PageParam { + public static final Integer REFUND_STATUS_NONE = 0; + public static final Integer REFUND_STATUS_PART = 1; + public static final Integer REFUND_STATUS_ALL = 2; + @Schema(description = "采购单编号", example = "XS001") private String no; @@ -48,4 +52,10 @@ public class ErpPurchaseReturnPageReqVO extends PageParam { @Schema(description = "采购单号", example = "1") private String orderNo; + @Schema(description = "退款状态", example = "1") + private Integer refundStatus; + + @Schema(description = "是否可退款", example = "true") + private Boolean refundEnable; // 对应 refundStatus = [0, 1] + } \ No newline at end of file diff --git a/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/controller/admin/purchase/vo/returns/ErpPurchaseReturnRespVO.java b/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/controller/admin/purchase/vo/returns/ErpPurchaseReturnRespVO.java index 887b5f040..223b9327e 100644 --- a/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/controller/admin/purchase/vo/returns/ErpPurchaseReturnRespVO.java +++ b/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/controller/admin/purchase/vo/returns/ErpPurchaseReturnRespVO.java @@ -52,6 +52,8 @@ public class ErpPurchaseReturnRespVO { @Schema(description = "最终合计价格", requiredMode = Schema.RequiredMode.REQUIRED, example = "24906") @ExcelProperty("最终合计价格") private BigDecimal totalPrice; + @Schema(description = "已退款金额,单位:元", requiredMode = Schema.RequiredMode.REQUIRED, example = "7127") + private BigDecimal refundPrice; @Schema(description = "合计产品价格,单位:元", requiredMode = Schema.RequiredMode.REQUIRED, example = "7127") private BigDecimal totalProductPrice; @@ -68,11 +70,6 @@ public class ErpPurchaseReturnRespVO { @Schema(description = "定金金额,单位:元", requiredMode = Schema.RequiredMode.REQUIRED, example = "7127") private BigDecimal otherPrice; - @Schema(description = "本次退款,单位:元", requiredMode = Schema.RequiredMode.REQUIRED, example = "7127") - private BigDecimal refundPrice; - @Schema(description = "本次欠款,单位:元", requiredMode = Schema.RequiredMode.REQUIRED, example = "666") - private BigDecimal debtPrice; - @Schema(description = "附件地址", example = "https://www.iocoder.cn") @ExcelProperty("附件地址") private String fileUrl; diff --git a/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/controller/admin/purchase/vo/returns/ErpPurchaseReturnSaveReqVO.java b/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/controller/admin/purchase/vo/returns/ErpPurchaseReturnSaveReqVO.java index ae258c06a..9254bd583 100644 --- a/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/controller/admin/purchase/vo/returns/ErpPurchaseReturnSaveReqVO.java +++ b/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/controller/admin/purchase/vo/returns/ErpPurchaseReturnSaveReqVO.java @@ -32,10 +32,6 @@ public class ErpPurchaseReturnSaveReqVO { @Schema(description = "其它金额,单位:元", example = "7127") private BigDecimal otherPrice; - @Schema(description = "本次退款,单位:元", requiredMode = Schema.RequiredMode.REQUIRED, example = "7127") - @NotNull(message = "本次退款不能为空") - private BigDecimal refundPrice; - @Schema(description = "附件地址", example = "https://www.iocoder.cn") private String fileUrl; diff --git a/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/dal/dataobject/purchase/ErpPurchaseInDO.java b/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/dal/dataobject/purchase/ErpPurchaseInDO.java index 5e7ff5947..a16844d3e 100644 --- a/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/dal/dataobject/purchase/ErpPurchaseInDO.java +++ b/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/dal/dataobject/purchase/ErpPurchaseInDO.java @@ -77,9 +77,15 @@ public class ErpPurchaseInDO extends BaseDO { /** * 最终合计价格,单位:元 * - * totalPrice = totalProductPrice + totalTaxPrice - discountPrice + * totalPrice = totalProductPrice + totalTaxPrice - discountPrice + otherPrice */ private BigDecimal totalPrice; + /** + * 已支付金额,单位:元 + * + * 目的:和 TODO erp_finance_payment 结合,记录已支付金额 + */ + private BigDecimal paymentPrice; /** * 合计产品价格,单位:元 @@ -104,17 +110,6 @@ public class ErpPurchaseInDO extends BaseDO { */ private BigDecimal otherPrice; - /** - * 本次退款,单位:元 - * - * refundPrice = totalPrice + otherPrice - debtPrice - */ - private BigDecimal refundPrice; - /** - * 本次欠款,单位:元 - */ - private BigDecimal debtPrice; - /** * 附件地址 */ diff --git a/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/dal/dataobject/purchase/ErpPurchaseReturnDO.java b/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/dal/dataobject/purchase/ErpPurchaseReturnDO.java index 0ec4ac6fd..a1c8cc4d5 100644 --- a/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/dal/dataobject/purchase/ErpPurchaseReturnDO.java +++ b/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/dal/dataobject/purchase/ErpPurchaseReturnDO.java @@ -77,9 +77,15 @@ public class ErpPurchaseReturnDO extends BaseDO { /** * 最终合计价格,单位:元 * - * totalPrice = totalProductPrice + totalTaxPrice - discountPrice + * totalPrice = totalProductPrice + totalTaxPrice - discountPrice + otherPrice */ private BigDecimal totalPrice; + /** + * 已退款金额,单位:元 + * + * 目的:和 TODO erp_finance_payment 结合,记录已退款金额 + */ + private BigDecimal refundPrice; /** * 合计产品价格,单位:元 @@ -104,17 +110,6 @@ public class ErpPurchaseReturnDO extends BaseDO { */ private BigDecimal otherPrice; - /** - * 本次退款,单位:元 - * - * refundPrice = totalPrice + otherPrice - debtPrice - */ - private BigDecimal refundPrice; - /** - * 本次欠款,单位:元 - */ - private BigDecimal debtPrice; - /** * 附件地址 */ diff --git a/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/dal/dataobject/sale/ErpSaleOutDO.java b/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/dal/dataobject/sale/ErpSaleOutDO.java index 57ab55650..4bf567159 100644 --- a/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/dal/dataobject/sale/ErpSaleOutDO.java +++ b/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/dal/dataobject/sale/ErpSaleOutDO.java @@ -110,6 +110,7 @@ public class ErpSaleOutDO extends BaseDO { */ private BigDecimal otherPrice; + // TODO 芋艿:receiptPrice /** * 本次收款,单位:元 * diff --git a/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/dal/mysql/purchase/ErpPurchaseInMapper.java b/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/dal/mysql/purchase/ErpPurchaseInMapper.java index ff43be137..cd227c351 100644 --- a/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/dal/mysql/purchase/ErpPurchaseInMapper.java +++ b/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/dal/mysql/purchase/ErpPurchaseInMapper.java @@ -10,8 +10,8 @@ import cn.iocoder.yudao.module.erp.dal.dataobject.purchase.ErpPurchaseInItemDO; import com.baomidou.mybatisplus.core.conditions.update.LambdaUpdateWrapper; import org.apache.ibatis.annotations.Mapper; -import java.math.BigDecimal; import java.util.List; +import java.util.Objects; /** * ERP 采购入库 Mapper @@ -32,10 +32,16 @@ public interface ErpPurchaseInMapper extends BaseMapperX { .eqIfPresent(ErpPurchaseInDO::getAccountId, reqVO.getAccountId()) .likeIfPresent(ErpPurchaseInDO::getOrderNo, reqVO.getOrderNo()) .orderByDesc(ErpPurchaseInDO::getId); - if (Boolean.TRUE.equals(reqVO.getDebtStatus())) { - query.gt(ErpPurchaseInDO::getDebtPrice, BigDecimal.ZERO); - } else if (Boolean.FALSE.equals(reqVO.getDebtStatus())) { - query.eq(ErpPurchaseInDO::getDebtPrice, BigDecimal.ZERO); + // 付款状态。为什么需要 t. 的原因,是因为联表查询时,需要指定表名,不然会报字段不存在的错误 + if (Objects.equals(reqVO.getPaymentStatus(), ErpPurchaseInPageReqVO.PAYMENT_STATUS_NONE)) { + query.eq(ErpPurchaseInDO::getPaymentPrice, 0); + } else if (Objects.equals(reqVO.getPaymentStatus(), ErpPurchaseInPageReqVO.PAYMENT_STATUS_PART)) { + query.gt(ErpPurchaseInDO::getPaymentPrice, 0).apply("t.payment_price < t.total_price"); + } else if (Objects.equals(reqVO.getPaymentStatus(), ErpPurchaseInPageReqVO.PAYMENT_STATUS_ALL)) { + query.apply("t.payment_price = t.total_price"); + } + if (Boolean.TRUE.equals(reqVO.getPaymentEnable())) { + query.apply("t.payment_price < t.total_price"); } if (reqVO.getWarehouseId() != null || reqVO.getProductId() != null) { query.leftJoin(ErpPurchaseInItemDO.class, ErpPurchaseInItemDO::getInId, ErpPurchaseInDO::getId) diff --git a/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/dal/mysql/purchase/ErpPurchaseReturnMapper.java b/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/dal/mysql/purchase/ErpPurchaseReturnMapper.java index 716b27574..aa3c9ad5f 100644 --- a/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/dal/mysql/purchase/ErpPurchaseReturnMapper.java +++ b/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/dal/mysql/purchase/ErpPurchaseReturnMapper.java @@ -10,6 +10,7 @@ import com.baomidou.mybatisplus.core.conditions.update.LambdaUpdateWrapper; import org.apache.ibatis.annotations.Mapper; import java.util.List; +import java.util.Objects; /** * ERP 采购退货 Mapper @@ -30,6 +31,17 @@ public interface ErpPurchaseReturnMapper extends BaseMapperX Date: Wed, 14 Feb 2024 08:09:15 +0800 Subject: [PATCH 107/119] =?UTF-8?q?=E2=9C=A8=20ERP=EF=BC=9A=E5=88=9D?= =?UTF-8?q?=E5=A7=8B=E5=8C=96=20payment=20=E4=BB=98=E6=AC=BE=E5=8D=95?= =?UTF-8?q?=E7=9A=84=E9=80=BB=E8=BE=91=2030%?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../module/erp/enums/ErrorCodeConstants.java | 9 + .../erp/enums/common/ErpBizTypeEnum.java | 43 ++++ .../admin/finance/ErpAccountController.java | 6 +- .../finance/ErpFinancePaymentController.java | 145 +++++++++++ .../vo/{ => account}/ErpAccountPageReqVO.java | 2 +- .../vo/{ => account}/ErpAccountRespVO.java | 2 +- .../vo/{ => account}/ErpAccountSaveReqVO.java | 2 +- .../payment/ErpFinancePaymentPageReqVO.java | 48 ++++ .../vo/payment/ErpFinancePaymentRespVO.java | 95 +++++++ .../payment/ErpFinancePaymentSaveReqVO.java | 78 ++++++ .../purchase/ErpPurchaseInController.java | 4 +- .../purchase/ErpPurchaseOrderController.java | 19 +- .../purchase/ErpPurchaseReturnController.java | 2 +- .../admin/sale/ErpSaleOrderController.java | 4 +- .../admin/sale/ErpSaleOutController.java | 2 +- .../admin/sale/ErpSaleReturnController.java | 2 +- .../admin/stock/ErpStockCheckController.java | 4 +- .../admin/stock/ErpStockInController.java | 2 +- .../admin/stock/ErpStockMoveController.java | 4 +- .../admin/stock/ErpStockOutController.java | 2 +- .../admin/stock/ErpStockRecordController.java | 2 +- .../finance/ErpFinancePaymentDO.java | 86 +++++++ .../finance/ErpFinancePaymentItemDO.java | 75 ++++++ .../dal/mysql/finance/ErpAccountMapper.java | 2 +- .../finance/ErpFinancePaymentItemMapper.java | 30 +++ .../finance/ErpFinancePaymentMapper.java | 48 ++++ .../erp/dal/redis/no/ErpNoRedisDAO.java | 5 + .../service/finance/ErpAccountService.java | 4 +- .../finance/ErpAccountServiceImpl.java | 4 +- .../finance/ErpFinancePaymentService.java | 84 ++++++ .../finance/ErpFinancePaymentServiceImpl.java | 241 ++++++++++++++++++ .../purchase/ErpPurchaseInService.java | 8 + .../purchase/ErpPurchaseInServiceImpl.java | 12 +- .../purchase/ErpPurchaseOrderServiceImpl.java | 2 +- .../purchase/ErpPurchaseReturnService.java | 8 + .../ErpPurchaseReturnServiceImpl.java | 12 +- .../service/sale/ErpSaleOrderServiceImpl.java | 2 +- .../service/sale/ErpSaleOutServiceImpl.java | 2 +- .../sale/ErpSaleReturnServiceImpl.java | 2 +- .../finance/ErpAccountServiceImplTest.java | 142 ----------- .../ErpProductUnitServiceImplTest.java | 131 ---------- .../product/ProductServiceImplTest.java | 131 ---------- .../sale/ErpCustomerServiceImplTest.java | 131 ---------- .../stock/ErpWarehouseServiceImplTest.java | 126 --------- 44 files changed, 1063 insertions(+), 702 deletions(-) create mode 100644 yudao-module-erp/yudao-module-erp-api/src/main/java/cn/iocoder/yudao/module/erp/enums/common/ErpBizTypeEnum.java create mode 100644 yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/controller/admin/finance/ErpFinancePaymentController.java rename yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/controller/admin/finance/vo/{ => account}/ErpAccountPageReqVO.java (89%) rename yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/controller/admin/finance/vo/{ => account}/ErpAccountRespVO.java (95%) rename yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/controller/admin/finance/vo/{ => account}/ErpAccountSaveReqVO.java (94%) create mode 100644 yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/controller/admin/finance/vo/payment/ErpFinancePaymentPageReqVO.java create mode 100644 yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/controller/admin/finance/vo/payment/ErpFinancePaymentRespVO.java create mode 100644 yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/controller/admin/finance/vo/payment/ErpFinancePaymentSaveReqVO.java create mode 100644 yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/dal/dataobject/finance/ErpFinancePaymentDO.java create mode 100644 yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/dal/dataobject/finance/ErpFinancePaymentItemDO.java create mode 100644 yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/dal/mysql/finance/ErpFinancePaymentItemMapper.java create mode 100644 yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/dal/mysql/finance/ErpFinancePaymentMapper.java create mode 100644 yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/service/finance/ErpFinancePaymentService.java create mode 100644 yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/service/finance/ErpFinancePaymentServiceImpl.java delete mode 100644 yudao-module-erp/yudao-module-erp-biz/src/test/java/cn/iocoder/yudao/module/erp/service/finance/ErpAccountServiceImplTest.java delete mode 100644 yudao-module-erp/yudao-module-erp-biz/src/test/java/cn/iocoder/yudao/module/erp/service/product/ErpProductUnitServiceImplTest.java delete mode 100644 yudao-module-erp/yudao-module-erp-biz/src/test/java/cn/iocoder/yudao/module/erp/service/product/ProductServiceImplTest.java delete mode 100644 yudao-module-erp/yudao-module-erp-biz/src/test/java/cn/iocoder/yudao/module/erp/service/sale/ErpCustomerServiceImplTest.java delete mode 100644 yudao-module-erp/yudao-module-erp-biz/src/test/java/cn/iocoder/yudao/module/erp/service/stock/ErpWarehouseServiceImplTest.java diff --git a/yudao-module-erp/yudao-module-erp-api/src/main/java/cn/iocoder/yudao/module/erp/enums/ErrorCodeConstants.java b/yudao-module-erp/yudao-module-erp-api/src/main/java/cn/iocoder/yudao/module/erp/enums/ErrorCodeConstants.java index b368f5509..3fafa752b 100644 --- a/yudao-module-erp/yudao-module-erp-api/src/main/java/cn/iocoder/yudao/module/erp/enums/ErrorCodeConstants.java +++ b/yudao-module-erp/yudao-module-erp-api/src/main/java/cn/iocoder/yudao/module/erp/enums/ErrorCodeConstants.java @@ -33,6 +33,7 @@ ErrorCode PURCHASE_ORDER_ITEM_RETURN_FAIL_IN_EXCEED = new ErrorCode(1_030_101_00 ErrorCode PURCHASE_IN_APPROVE_FAIL = new ErrorCode(1_030_102_003, "审核失败,只有未审核的入库单才能审核"); ErrorCode PURCHASE_IN_NO_EXISTS = new ErrorCode(1_030_102_004, "生成入库单失败,请重新提交"); ErrorCode PURCHASE_IN_UPDATE_FAIL_APPROVE = new ErrorCode(1_030_102_005, "采购入库单({})已审核,无法修改"); + ErrorCode PURCHASE_IN_NOT_APPROVE = new ErrorCode(1_030_102_006, "采购入库单未审核,无法操作"); // ========== ERP 采购退货(1-030-103-000) ========== ErrorCode PURCHASE_RETURN_NOT_EXISTS = new ErrorCode(1_030_103_000, "采购退货单不存在"); @@ -41,6 +42,7 @@ ErrorCode PURCHASE_ORDER_ITEM_RETURN_FAIL_IN_EXCEED = new ErrorCode(1_030_101_00 ErrorCode PURCHASE_RETURN_APPROVE_FAIL = new ErrorCode(1_030_103_003, "审核失败,只有未审核的退货单才能审核"); ErrorCode PURCHASE_RETURN_NO_EXISTS = new ErrorCode(1_030_103_004, "生成退货单失败,请重新提交"); ErrorCode PURCHASE_RETURN_UPDATE_FAIL_APPROVE = new ErrorCode(1_030_103_005, "采购退货单({})已审核,无法修改"); + ErrorCode PURCHASE_RETURN_NOT_APPROVE = new ErrorCode(1_030_103_006, "采购退货单未审核,无法操作"); // ========== ERP 客户(1-030-200-000)========== ErrorCode CUSTOMER_NOT_EXISTS = new ErrorCode(1_020_200_000, "客户不存在"); @@ -137,4 +139,11 @@ ErrorCode PURCHASE_ORDER_ITEM_RETURN_FAIL_IN_EXCEED = new ErrorCode(1_030_101_00 ErrorCode ACCOUNT_NOT_EXISTS = new ErrorCode(1_030_600_000, "结算账户不存在"); ErrorCode ACCOUNT_NOT_ENABLE = new ErrorCode(1_030_600_001, "结算账户({})未启用"); + // ========== ERP 付款单 1-030-601-000 ========== + ErrorCode FINANCE_PAYMENT_NOT_EXISTS = new ErrorCode(1_030_601_000, "付款单不存在"); + ErrorCode FINANCE_PAYMENT_DELETE_FAIL_APPROVE = new ErrorCode(1_030_601_001, "付款单({})已审核,无法删除"); + ErrorCode FINANCE_PAYMENT_PROCESS_FAIL = new ErrorCode(1_030_601_002, "反审核失败,只有已审核的付款单才能反审核"); + ErrorCode FINANCE_PAYMENT_APPROVE_FAIL = new ErrorCode(1_030_601_003, "审核失败,只有未审核的付款单才能审核"); + ErrorCode FINANCE_PAYMENT_NO_EXISTS = new ErrorCode(1_030_601_004, "生成付款单号失败,请重新提交"); + } diff --git a/yudao-module-erp/yudao-module-erp-api/src/main/java/cn/iocoder/yudao/module/erp/enums/common/ErpBizTypeEnum.java b/yudao-module-erp/yudao-module-erp-api/src/main/java/cn/iocoder/yudao/module/erp/enums/common/ErpBizTypeEnum.java new file mode 100644 index 000000000..bba2b309b --- /dev/null +++ b/yudao-module-erp/yudao-module-erp-api/src/main/java/cn/iocoder/yudao/module/erp/enums/common/ErpBizTypeEnum.java @@ -0,0 +1,43 @@ +package cn.iocoder.yudao.module.erp.enums.common; + +import cn.iocoder.yudao.framework.common.core.IntArrayValuable; +import lombok.Getter; +import lombok.RequiredArgsConstructor; + +import java.util.Arrays; + +/** + * ERP 业务类型枚举 + * + * @author HUIHUI + */ +@RequiredArgsConstructor +@Getter +public enum ErpBizTypeEnum implements IntArrayValuable { + + PURCHASE_ORDER(10, "采购订单"), + PURCHASE_IN(11, "采购入库"), + PURCHASE_RETURN(12, "采购退货"), + + SALE_ORDER(20, "销售订单"), + SALE_OUT(21, "销售订单"), + SALE_RETURN(22, "销售退货"), + ; + + public static final int[] ARRAYS = Arrays.stream(values()).mapToInt(ErpBizTypeEnum::getType).toArray(); + + /** + * 类型 + */ + private final Integer type; + /** + * 名称 + */ + private final String name; + + @Override + public int[] array() { + return ARRAYS; + } + +} diff --git a/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/controller/admin/finance/ErpAccountController.java b/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/controller/admin/finance/ErpAccountController.java index 52d62ac4a..4c8c98058 100644 --- a/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/controller/admin/finance/ErpAccountController.java +++ b/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/controller/admin/finance/ErpAccountController.java @@ -7,9 +7,9 @@ import cn.iocoder.yudao.framework.common.pojo.PageResult; import cn.iocoder.yudao.framework.common.util.object.BeanUtils; import cn.iocoder.yudao.framework.excel.core.util.ExcelUtils; import cn.iocoder.yudao.framework.operatelog.core.annotations.OperateLog; -import cn.iocoder.yudao.module.erp.controller.admin.finance.vo.ErpAccountPageReqVO; -import cn.iocoder.yudao.module.erp.controller.admin.finance.vo.ErpAccountRespVO; -import cn.iocoder.yudao.module.erp.controller.admin.finance.vo.ErpAccountSaveReqVO; +import cn.iocoder.yudao.module.erp.controller.admin.finance.vo.account.ErpAccountPageReqVO; +import cn.iocoder.yudao.module.erp.controller.admin.finance.vo.account.ErpAccountRespVO; +import cn.iocoder.yudao.module.erp.controller.admin.finance.vo.account.ErpAccountSaveReqVO; import cn.iocoder.yudao.module.erp.dal.dataobject.finance.ErpAccountDO; import cn.iocoder.yudao.module.erp.service.finance.ErpAccountService; import io.swagger.v3.oas.annotations.Operation; diff --git a/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/controller/admin/finance/ErpFinancePaymentController.java b/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/controller/admin/finance/ErpFinancePaymentController.java new file mode 100644 index 000000000..a4d16898b --- /dev/null +++ b/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/controller/admin/finance/ErpFinancePaymentController.java @@ -0,0 +1,145 @@ +package cn.iocoder.yudao.module.erp.controller.admin.finance; + +import cn.hutool.core.collection.CollUtil; +import cn.iocoder.yudao.framework.common.pojo.CommonResult; +import cn.iocoder.yudao.framework.common.pojo.PageParam; +import cn.iocoder.yudao.framework.common.pojo.PageResult; +import cn.iocoder.yudao.framework.common.util.collection.MapUtils; +import cn.iocoder.yudao.framework.common.util.number.NumberUtils; +import cn.iocoder.yudao.framework.common.util.object.BeanUtils; +import cn.iocoder.yudao.framework.excel.core.util.ExcelUtils; +import cn.iocoder.yudao.framework.operatelog.core.annotations.OperateLog; +import cn.iocoder.yudao.module.erp.controller.admin.finance.vo.payment.ErpFinancePaymentPageReqVO; +import cn.iocoder.yudao.module.erp.controller.admin.finance.vo.payment.ErpFinancePaymentRespVO; +import cn.iocoder.yudao.module.erp.controller.admin.finance.vo.payment.ErpFinancePaymentSaveReqVO; +import cn.iocoder.yudao.module.erp.dal.dataobject.finance.ErpFinancePaymentDO; +import cn.iocoder.yudao.module.erp.dal.dataobject.finance.ErpFinancePaymentItemDO; +import cn.iocoder.yudao.module.erp.dal.dataobject.purchase.ErpSupplierDO; +import cn.iocoder.yudao.module.erp.service.finance.ErpFinancePaymentService; +import cn.iocoder.yudao.module.erp.service.purchase.ErpSupplierService; +import cn.iocoder.yudao.module.system.api.user.AdminUserApi; +import cn.iocoder.yudao.module.system.api.user.dto.AdminUserRespDTO; +import io.swagger.v3.oas.annotations.Operation; +import io.swagger.v3.oas.annotations.Parameter; +import io.swagger.v3.oas.annotations.tags.Tag; +import jakarta.annotation.Resource; +import jakarta.servlet.http.HttpServletResponse; +import jakarta.validation.Valid; +import org.springframework.security.access.prepost.PreAuthorize; +import org.springframework.validation.annotation.Validated; +import org.springframework.web.bind.annotation.*; + +import java.io.IOException; +import java.util.List; +import java.util.Map; +import java.util.stream.Stream; + +import static cn.iocoder.yudao.framework.common.pojo.CommonResult.success; +import static cn.iocoder.yudao.framework.common.util.collection.CollectionUtils.*; +import static cn.iocoder.yudao.framework.operatelog.core.enums.OperateTypeEnum.EXPORT; + +@Tag(name = "管理后台 - ERP 付款单") +@RestController +@RequestMapping("/erp/finance-payment") +@Validated +public class ErpFinancePaymentController { + + @Resource + private ErpFinancePaymentService financePaymentService; + @Resource + private ErpSupplierService supplierService; + + @Resource + private AdminUserApi adminUserApi; + + @PostMapping("/create") + @Operation(summary = "创建付款单") + @PreAuthorize("@ss.hasPermission('erp:finance-payment:create')") + public CommonResult createFinancePayment(@Valid @RequestBody ErpFinancePaymentSaveReqVO createReqVO) { + return success(financePaymentService.createFinancePayment(createReqVO)); + } + + @PutMapping("/update") + @Operation(summary = "更新付款单") + @PreAuthorize("@ss.hasPermission('erp:finance-payment:update')") + public CommonResult updateFinancePayment(@Valid @RequestBody ErpFinancePaymentSaveReqVO updateReqVO) { + financePaymentService.updateFinancePayment(updateReqVO); + return success(true); + } + + @PutMapping("/update-status") + @Operation(summary = "更新付款单的状态") + @PreAuthorize("@ss.hasPermission('erp:finance-payment:update-status')") + public CommonResult updateFinancePaymentStatus(@RequestParam("id") Long id, + @RequestParam("status") Integer status) { + financePaymentService.updateFinancePaymentStatus(id, status); + return success(true); + } + + @DeleteMapping("/delete") + @Operation(summary = "删除付款单") + @Parameter(name = "ids", description = "编号数组", required = true) + @PreAuthorize("@ss.hasPermission('erp:finance-payment:delete')") + public CommonResult deleteFinancePayment(@RequestParam("ids") List ids) { + financePaymentService.deleteFinancePayment(ids); + return success(true); + } + + @GetMapping("/get") + @Operation(summary = "获得付款单") + @Parameter(name = "id", description = "编号", required = true, example = "1024") + @PreAuthorize("@ss.hasPermission('erp:finance-payment:query')") + public CommonResult getFinancePayment(@RequestParam("id") Long id) { + ErpFinancePaymentDO payment = financePaymentService.getFinancePayment(id); + if (payment == null) { + return success(null); + } + List paymentItemList = financePaymentService.getFinancePaymentItemListByPaymentId(id); + return success(BeanUtils.toBean(payment, ErpFinancePaymentRespVO.class, financePaymentVO -> + financePaymentVO.setItems(BeanUtils.toBean(paymentItemList, ErpFinancePaymentRespVO.Item.class)))); + } + + @GetMapping("/page") + @Operation(summary = "获得付款单分页") + @PreAuthorize("@ss.hasPermission('erp:finance-payment:query')") + public CommonResult> getFinancePaymentPage(@Valid ErpFinancePaymentPageReqVO pageReqVO) { + PageResult pageResult = financePaymentService.getFinancePaymentPage(pageReqVO); + return success(buildFinancePaymentVOPageResult(pageResult)); + } + + @GetMapping("/export-excel") + @Operation(summary = "导出付款单 Excel") + @PreAuthorize("@ss.hasPermission('erp:finance-payment:export')") + @OperateLog(type = EXPORT) + public void exportFinancePaymentExcel(@Valid ErpFinancePaymentPageReqVO pageReqVO, + HttpServletResponse response) throws IOException { + pageReqVO.setPageSize(PageParam.PAGE_SIZE_NONE); + List list = buildFinancePaymentVOPageResult(financePaymentService.getFinancePaymentPage(pageReqVO)).getList(); + // 导出 Excel + ExcelUtils.write(response, "付款单.xls", "数据", ErpFinancePaymentRespVO.class, list); + } + + private PageResult buildFinancePaymentVOPageResult(PageResult pageResult) { + if (CollUtil.isEmpty(pageResult.getList())) { + return PageResult.empty(pageResult.getTotal()); + } + // 1.1 付款项 + List paymentItemList = financePaymentService.getFinancePaymentItemListByPaymentIds( + convertSet(pageResult.getList(), ErpFinancePaymentDO::getId)); + Map> financePaymentItemMap = convertMultiMap(paymentItemList, ErpFinancePaymentItemDO::getPaymentId); + // 1.2 供应商信息 + Map supplierMap = supplierService.getSupplierMap( + convertSet(pageResult.getList(), ErpFinancePaymentDO::getSupplierId)); + // 1.3 管理员信息 + Map userMap = adminUserApi.getUserMap(convertListByFlatMap(pageResult.getList(), + contact -> Stream.of(NumberUtils.parseLong(contact.getCreator()), contact.getFinanceUserId()))); + // 2. 开始拼接 + return BeanUtils.toBean(pageResult, ErpFinancePaymentRespVO.class, payment -> { + payment.setItems(BeanUtils.toBean(financePaymentItemMap.get(payment.getId()), ErpFinancePaymentRespVO.Item.class)); + MapUtils.findAndThen(supplierMap, payment.getSupplierId(), supplier -> payment.setSupplierName(supplier.getName())); + MapUtils.findAndThen(userMap, Long.parseLong(payment.getCreator()), user -> payment.setCreatorName(user.getNickname())); + MapUtils.findAndThen(userMap, payment.getFinanceUserId(), user -> payment.setFinanceUserName(user.getNickname())); + }); + } + +} diff --git a/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/controller/admin/finance/vo/ErpAccountPageReqVO.java b/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/controller/admin/finance/vo/account/ErpAccountPageReqVO.java similarity index 89% rename from yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/controller/admin/finance/vo/ErpAccountPageReqVO.java rename to yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/controller/admin/finance/vo/account/ErpAccountPageReqVO.java index 682689e5e..3e1fa72f4 100644 --- a/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/controller/admin/finance/vo/ErpAccountPageReqVO.java +++ b/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/controller/admin/finance/vo/account/ErpAccountPageReqVO.java @@ -1,4 +1,4 @@ -package cn.iocoder.yudao.module.erp.controller.admin.finance.vo; +package cn.iocoder.yudao.module.erp.controller.admin.finance.vo.account; import cn.iocoder.yudao.framework.common.pojo.PageParam; import io.swagger.v3.oas.annotations.media.Schema; diff --git a/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/controller/admin/finance/vo/ErpAccountRespVO.java b/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/controller/admin/finance/vo/account/ErpAccountRespVO.java similarity index 95% rename from yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/controller/admin/finance/vo/ErpAccountRespVO.java rename to yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/controller/admin/finance/vo/account/ErpAccountRespVO.java index 57e6c10b5..a1c2e954d 100644 --- a/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/controller/admin/finance/vo/ErpAccountRespVO.java +++ b/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/controller/admin/finance/vo/account/ErpAccountRespVO.java @@ -1,4 +1,4 @@ -package cn.iocoder.yudao.module.erp.controller.admin.finance.vo; +package cn.iocoder.yudao.module.erp.controller.admin.finance.vo.account; import cn.iocoder.yudao.framework.excel.core.annotations.DictFormat; import cn.iocoder.yudao.module.system.enums.DictTypeConstants; diff --git a/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/controller/admin/finance/vo/ErpAccountSaveReqVO.java b/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/controller/admin/finance/vo/account/ErpAccountSaveReqVO.java similarity index 94% rename from yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/controller/admin/finance/vo/ErpAccountSaveReqVO.java rename to yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/controller/admin/finance/vo/account/ErpAccountSaveReqVO.java index 1f96946a7..6f3556530 100644 --- a/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/controller/admin/finance/vo/ErpAccountSaveReqVO.java +++ b/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/controller/admin/finance/vo/account/ErpAccountSaveReqVO.java @@ -1,4 +1,4 @@ -package cn.iocoder.yudao.module.erp.controller.admin.finance.vo; +package cn.iocoder.yudao.module.erp.controller.admin.finance.vo.account; import cn.iocoder.yudao.framework.common.enums.CommonStatusEnum; import cn.iocoder.yudao.framework.common.validation.InEnum; diff --git a/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/controller/admin/finance/vo/payment/ErpFinancePaymentPageReqVO.java b/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/controller/admin/finance/vo/payment/ErpFinancePaymentPageReqVO.java new file mode 100644 index 000000000..39a0f9505 --- /dev/null +++ b/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/controller/admin/finance/vo/payment/ErpFinancePaymentPageReqVO.java @@ -0,0 +1,48 @@ +package cn.iocoder.yudao.module.erp.controller.admin.finance.vo.payment; + +import cn.iocoder.yudao.framework.common.pojo.PageParam; +import io.swagger.v3.oas.annotations.media.Schema; +import lombok.Data; +import lombok.EqualsAndHashCode; +import lombok.ToString; +import org.springframework.format.annotation.DateTimeFormat; + +import java.time.LocalDateTime; + +import static cn.iocoder.yudao.framework.common.util.date.DateUtils.FORMAT_YEAR_MONTH_DAY_HOUR_MINUTE_SECOND; + +@Schema(description = "管理后台 - ERP 付款单分页 Request VO") +@Data +@EqualsAndHashCode(callSuper = true) +@ToString(callSuper = true) +public class ErpFinancePaymentPageReqVO extends PageParam { + + @Schema(description = "采购单编号", example = "XS001") + private String no; + + @Schema(description = "付款时间") + @DateTimeFormat(pattern = FORMAT_YEAR_MONTH_DAY_HOUR_MINUTE_SECOND) + private LocalDateTime[] paymentTime; + + @Schema(description = "供应商编号", example = "1724") + private Long supplierId; + + @Schema(description = "创建者", example = "666") + private String creator; + + @Schema(description = "财务人员编号", example = "888") + private String financeUserId; + + @Schema(description = "结算账户编号", example = "31189") + private Long accountId; + + @Schema(description = "付款状态", example = "2") + private Integer status; + + @Schema(description = "备注", example = "你猜") + private String remark; + + @Schema(description = "业务编号", example = "123") + private String bizNo; + +} \ No newline at end of file diff --git a/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/controller/admin/finance/vo/payment/ErpFinancePaymentRespVO.java b/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/controller/admin/finance/vo/payment/ErpFinancePaymentRespVO.java new file mode 100644 index 000000000..323d86db5 --- /dev/null +++ b/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/controller/admin/finance/vo/payment/ErpFinancePaymentRespVO.java @@ -0,0 +1,95 @@ +package cn.iocoder.yudao.module.erp.controller.admin.finance.vo.payment; + +import com.alibaba.excel.annotation.ExcelProperty; +import io.swagger.v3.oas.annotations.media.Schema; +import jakarta.validation.constraints.NotNull; +import lombok.Data; + +import java.math.BigDecimal; +import java.time.LocalDateTime; +import java.util.List; + +@Schema(description = "管理后台 - ERP 付款单 Response VO") +@Data +public class ErpFinancePaymentRespVO { + + @Schema(description = "编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "23752") + private Long id; + + @Schema(description = "付款单号", requiredMode = Schema.RequiredMode.REQUIRED, example = "FKD888") + private String no; + + @Schema(description = "付款状态", requiredMode = Schema.RequiredMode.REQUIRED, example = "1") + private Integer status; + + @Schema(description = "付款时间", requiredMode = Schema.RequiredMode.REQUIRED) + private LocalDateTime paymentTime; + + @Schema(description = "财务人员编号", example = "19690") + private Long financeUserId; + @Schema(description = "财务人员名称", example = "张三") + private String financeUserName; + + @Schema(description = "供应商编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "29399") + private Long supplierId; + @Schema(description = "供应商名称", requiredMode = Schema.RequiredMode.REQUIRED, example = "小番茄公司") + private String supplierName; + + @Schema(description = "付款账户编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "28989") + private Long accountId; + + @Schema(description = "合计价格,单位:元", requiredMode = Schema.RequiredMode.REQUIRED, example = "13832") + private BigDecimal totalPrice; + + @Schema(description = "优惠金额,单位:元", requiredMode = Schema.RequiredMode.REQUIRED, example = "11600") + private BigDecimal discountPrice; + + @Schema(description = "实际价格,单位:元", requiredMode = Schema.RequiredMode.REQUIRED, example = "10000") + private BigDecimal paymentPrice; + + @Schema(description = "备注", example = "你猜") + private String remark; + + @Schema(description = "创建人", example = "芋道") + private String creator; + @Schema(description = "创建人名称", example = "芋道") + private String creatorName; + + @Schema(description = "创建时间", requiredMode = Schema.RequiredMode.REQUIRED) + @ExcelProperty("创建时间") + private LocalDateTime createTime; + + @Schema(description = "付款项列表", requiredMode = Schema.RequiredMode.REQUIRED) + private List items; + + @Data + public static class Item { + + @Schema(description = "付款项编号", example = "11756") + private Long id; + + @Schema(description = "业务类型", requiredMode = Schema.RequiredMode.REQUIRED, example = "1") + private Integer bizType; + + @Schema(description = "业务编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "11756") + private Long bizId; + + @Schema(description = "业务单号", requiredMode = Schema.RequiredMode.REQUIRED, example = "11756") + private String bizNo; + + @Schema(description = "应付欠款,单位:分", requiredMode = Schema.RequiredMode.REQUIRED, example = "10000") + private BigDecimal totalPrice; + + @Schema(description = "已付欠款,单位:分", requiredMode = Schema.RequiredMode.REQUIRED, example = "10000") + private BigDecimal paidPrice; + + @Schema(description = "本次付款,单位:分", requiredMode = Schema.RequiredMode.REQUIRED, example = "10000") + @NotNull(message = "本次付款不能为空") + private BigDecimal paymentPrice; + + @Schema(description = "备注", example = "随便") + private String remark; + + } + +} \ No newline at end of file diff --git a/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/controller/admin/finance/vo/payment/ErpFinancePaymentSaveReqVO.java b/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/controller/admin/finance/vo/payment/ErpFinancePaymentSaveReqVO.java new file mode 100644 index 000000000..ab74c83b1 --- /dev/null +++ b/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/controller/admin/finance/vo/payment/ErpFinancePaymentSaveReqVO.java @@ -0,0 +1,78 @@ +package cn.iocoder.yudao.module.erp.controller.admin.finance.vo.payment; + +import io.swagger.v3.oas.annotations.media.Schema; +import jakarta.validation.Valid; +import jakarta.validation.constraints.NotEmpty; +import jakarta.validation.constraints.NotNull; +import lombok.Data; + +import java.math.BigDecimal; +import java.time.LocalDateTime; +import java.util.List; + +@Schema(description = "管理后台 - ERP 付款单新增/修改 Request VO") +@Data +public class ErpFinancePaymentSaveReqVO { + + @Schema(description = "编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "23752") + private Long id; + + @Schema(description = "付款单号", requiredMode = Schema.RequiredMode.REQUIRED, example = "FKD888") + @NotEmpty(message = "付款单号不能为空") + private String no; + + @Schema(description = "付款时间", requiredMode = Schema.RequiredMode.REQUIRED) + @NotNull(message = "付款时间不能为空") + private LocalDateTime paymentTime; + + @Schema(description = "财务人员编号", example = "19690") + private Long financeUserId; + + @Schema(description = "供应商编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "29399") + @NotNull(message = "供应商编号不能为空") + private Long supplierId; + + @Schema(description = "付款账户编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "28989") + @NotNull(message = "付款账户编号不能为空") + private Long accountId; + + @Schema(description = "优惠金额,单位:元", requiredMode = Schema.RequiredMode.REQUIRED, example = "11600") + @NotNull(message = "优惠金额不能为空") + private BigDecimal discountPrice; + + @Schema(description = "备注", example = "你猜") + private String remark; + + @Schema(description = "付款项列表", requiredMode = Schema.RequiredMode.REQUIRED) + @NotEmpty(message = "付款项列表不能为空") + @Valid + private List items; + + @Data + public static class Item { + + @Schema(description = "付款项编号", example = "11756") + private Long id; + + @Schema(description = "业务类型", requiredMode = Schema.RequiredMode.REQUIRED, example = "1") + @NotNull(message = "业务类型不能为空") + private Integer bizType; + + @Schema(description = "业务编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "11756") + @NotNull(message = "业务编号不能为空") + private Long bizId; + + @Schema(description = "已付欠款,单位:分", requiredMode = Schema.RequiredMode.REQUIRED, example = "10000") + @NotNull(message = "已付欠款不能为空") + private BigDecimal paidPrice; + + @Schema(description = "本次付款,单位:分", requiredMode = Schema.RequiredMode.REQUIRED, example = "10000") + @NotNull(message = "本次付款不能为空") + private BigDecimal paymentPrice; + + @Schema(description = "备注", example = "随便") + private String remark; + + } + +} \ No newline at end of file diff --git a/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/controller/admin/purchase/ErpPurchaseInController.java b/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/controller/admin/purchase/ErpPurchaseInController.java index 91f321a1e..d33c7ae4d 100644 --- a/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/controller/admin/purchase/ErpPurchaseInController.java +++ b/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/controller/admin/purchase/ErpPurchaseInController.java @@ -138,7 +138,7 @@ public class ErpPurchaseInController { if (CollUtil.isEmpty(pageResult.getList())) { return PageResult.empty(pageResult.getTotal()); } - // 1.1 出库项 + // 1.1 入库项 List purchaseInItemList = purchaseInService.getPurchaseInItemListByInIds( convertSet(pageResult.getList(), ErpPurchaseInDO::getId)); Map> purchaseInItemMap = convertMultiMap(purchaseInItemList, ErpPurchaseInItemDO::getInId); @@ -150,7 +150,7 @@ public class ErpPurchaseInController { convertSet(pageResult.getList(), ErpPurchaseInDO::getSupplierId)); // 1.4 管理员信息 Map userMap = adminUserApi.getUserMap( - convertSet(pageResult.getList(), erpStockRecordDO -> Long.parseLong(erpStockRecordDO.getCreator()))); + convertSet(pageResult.getList(), purchaseIn -> Long.parseLong(purchaseIn.getCreator()))); // 2. 开始拼接 return BeanUtils.toBean(pageResult, ErpPurchaseInRespVO.class, purchaseIn -> { purchaseIn.setItems(BeanUtils.toBean(purchaseInItemMap.get(purchaseIn.getId()), ErpPurchaseInRespVO.Item.class, diff --git a/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/controller/admin/purchase/ErpPurchaseOrderController.java b/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/controller/admin/purchase/ErpPurchaseOrderController.java index f7579e903..203d2fec0 100644 --- a/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/controller/admin/purchase/ErpPurchaseOrderController.java +++ b/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/controller/admin/purchase/ErpPurchaseOrderController.java @@ -41,7 +41,6 @@ import static cn.iocoder.yudao.framework.common.util.collection.CollectionUtils. import static cn.iocoder.yudao.framework.common.util.collection.CollectionUtils.convertSet; import static cn.iocoder.yudao.framework.operatelog.core.enums.OperateTypeEnum.EXPORT; - @Tag(name = "管理后台 - ERP 采购订单") @RestController @RequestMapping("/erp/purchase-order") @@ -62,14 +61,14 @@ public class ErpPurchaseOrderController { @PostMapping("/create") @Operation(summary = "创建采购订单") - @PreAuthorize("@ss.hasPermission('erp:purchase-out:create')") + @PreAuthorize("@ss.hasPermission('erp:purchase-create:create')") public CommonResult createPurchaseOrder(@Valid @RequestBody ErpPurchaseOrderSaveReqVO createReqVO) { return success(purchaseOrderService.createPurchaseOrder(createReqVO)); } @PutMapping("/update") @Operation(summary = "更新采购订单") - @PreAuthorize("@ss.hasPermission('erp:purchase-out:update')") + @PreAuthorize("@ss.hasPermission('erp:purchase-create:update')") public CommonResult updatePurchaseOrder(@Valid @RequestBody ErpPurchaseOrderSaveReqVO updateReqVO) { purchaseOrderService.updatePurchaseOrder(updateReqVO); return success(true); @@ -77,7 +76,7 @@ public class ErpPurchaseOrderController { @PutMapping("/update-status") @Operation(summary = "更新采购订单的状态") - @PreAuthorize("@ss.hasPermission('erp:purchase-out:update-status')") + @PreAuthorize("@ss.hasPermission('erp:purchase-create:update-status')") public CommonResult updatePurchaseOrderStatus(@RequestParam("id") Long id, @RequestParam("status") Integer status) { purchaseOrderService.updatePurchaseOrderStatus(id, status); @@ -87,7 +86,7 @@ public class ErpPurchaseOrderController { @DeleteMapping("/delete") @Operation(summary = "删除采购订单") @Parameter(name = "ids", description = "编号数组", required = true) - @PreAuthorize("@ss.hasPermission('erp:purchase-out:delete')") + @PreAuthorize("@ss.hasPermission('erp:purchase-create:delete')") public CommonResult deletePurchaseOrder(@RequestParam("ids") List ids) { purchaseOrderService.deletePurchaseOrder(ids); return success(true); @@ -96,7 +95,7 @@ public class ErpPurchaseOrderController { @GetMapping("/get") @Operation(summary = "获得采购订单") @Parameter(name = "id", description = "编号", required = true, example = "1024") - @PreAuthorize("@ss.hasPermission('erp:purchase-out:query')") + @PreAuthorize("@ss.hasPermission('erp:purchase-create:query')") public CommonResult getPurchaseOrder(@RequestParam("id") Long id) { ErpPurchaseOrderDO purchaseOrder = purchaseOrderService.getPurchaseOrder(id); if (purchaseOrder == null) { @@ -116,7 +115,7 @@ public class ErpPurchaseOrderController { @GetMapping("/page") @Operation(summary = "获得采购订单分页") - @PreAuthorize("@ss.hasPermission('erp:purchase-out:query')") + @PreAuthorize("@ss.hasPermission('erp:purchase-create:query')") public CommonResult> getPurchaseOrderPage(@Valid ErpPurchaseOrderPageReqVO pageReqVO) { PageResult pageResult = purchaseOrderService.getPurchaseOrderPage(pageReqVO); return success(buildPurchaseOrderVOPageResult(pageResult)); @@ -124,7 +123,7 @@ public class ErpPurchaseOrderController { @GetMapping("/export-excel") @Operation(summary = "导出采购订单 Excel") - @PreAuthorize("@ss.hasPermission('erp:purchase-out:export')") + @PreAuthorize("@ss.hasPermission('erp:purchase-create:export')") @OperateLog(type = EXPORT) public void exportPurchaseOrderExcel(@Valid ErpPurchaseOrderPageReqVO pageReqVO, HttpServletResponse response) throws IOException { @@ -138,7 +137,7 @@ public class ErpPurchaseOrderController { if (CollUtil.isEmpty(pageResult.getList())) { return PageResult.empty(pageResult.getTotal()); } - // 1.1 出库项 + // 1.1 订单项 List purchaseOrderItemList = purchaseOrderService.getPurchaseOrderItemListByOrderIds( convertSet(pageResult.getList(), ErpPurchaseOrderDO::getId)); Map> purchaseOrderItemMap = convertMultiMap(purchaseOrderItemList, ErpPurchaseOrderItemDO::getOrderId); @@ -150,7 +149,7 @@ public class ErpPurchaseOrderController { convertSet(pageResult.getList(), ErpPurchaseOrderDO::getSupplierId)); // 1.4 管理员信息 Map userMap = adminUserApi.getUserMap( - convertSet(pageResult.getList(), erpStockRecordDO -> Long.parseLong(erpStockRecordDO.getCreator()))); + convertSet(pageResult.getList(), purchaseOrder -> Long.parseLong(purchaseOrder.getCreator()))); // 2. 开始拼接 return BeanUtils.toBean(pageResult, ErpPurchaseOrderRespVO.class, purchaseOrder -> { purchaseOrder.setItems(BeanUtils.toBean(purchaseOrderItemMap.get(purchaseOrder.getId()), ErpPurchaseOrderRespVO.Item.class, diff --git a/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/controller/admin/purchase/ErpPurchaseReturnController.java b/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/controller/admin/purchase/ErpPurchaseReturnController.java index 4d420836b..0df31bcf1 100644 --- a/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/controller/admin/purchase/ErpPurchaseReturnController.java +++ b/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/controller/admin/purchase/ErpPurchaseReturnController.java @@ -150,7 +150,7 @@ public class ErpPurchaseReturnController { convertSet(pageResult.getList(), ErpPurchaseReturnDO::getSupplierId)); // 1.4 管理员信息 Map userMap = adminUserApi.getUserMap( - convertSet(pageResult.getList(), erpStockRecordDO -> Long.parseLong(erpStockRecordDO.getCreator()))); + convertSet(pageResult.getList(), purchaseReturn -> Long.parseLong(purchaseReturn.getCreator()))); // 2. 开始拼接 return BeanUtils.toBean(pageResult, ErpPurchaseReturnRespVO.class, purchaseReturn -> { purchaseReturn.setItems(BeanUtils.toBean(purchaseReturnItemMap.get(purchaseReturn.getId()), ErpPurchaseReturnRespVO.Item.class, diff --git a/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/controller/admin/sale/ErpSaleOrderController.java b/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/controller/admin/sale/ErpSaleOrderController.java index 348690fb3..0ca56a45e 100644 --- a/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/controller/admin/sale/ErpSaleOrderController.java +++ b/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/controller/admin/sale/ErpSaleOrderController.java @@ -138,7 +138,7 @@ public class ErpSaleOrderController { if (CollUtil.isEmpty(pageResult.getList())) { return PageResult.empty(pageResult.getTotal()); } - // 1.1 出库项 + // 1.1 订单项 List saleOrderItemList = saleOrderService.getSaleOrderItemListByOrderIds( convertSet(pageResult.getList(), ErpSaleOrderDO::getId)); Map> saleOrderItemMap = convertMultiMap(saleOrderItemList, ErpSaleOrderItemDO::getOrderId); @@ -150,7 +150,7 @@ public class ErpSaleOrderController { convertSet(pageResult.getList(), ErpSaleOrderDO::getCustomerId)); // 1.4 管理员信息 Map userMap = adminUserApi.getUserMap( - convertSet(pageResult.getList(), erpStockRecordDO -> Long.parseLong(erpStockRecordDO.getCreator()))); + convertSet(pageResult.getList(), saleOrder -> Long.parseLong(saleOrder.getCreator()))); // 2. 开始拼接 return BeanUtils.toBean(pageResult, ErpSaleOrderRespVO.class, saleOrder -> { saleOrder.setItems(BeanUtils.toBean(saleOrderItemMap.get(saleOrder.getId()), ErpSaleOrderRespVO.Item.class, diff --git a/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/controller/admin/sale/ErpSaleOutController.java b/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/controller/admin/sale/ErpSaleOutController.java index e640a358c..5875ea39f 100644 --- a/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/controller/admin/sale/ErpSaleOutController.java +++ b/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/controller/admin/sale/ErpSaleOutController.java @@ -150,7 +150,7 @@ public class ErpSaleOutController { convertSet(pageResult.getList(), ErpSaleOutDO::getCustomerId)); // 1.4 管理员信息 Map userMap = adminUserApi.getUserMap( - convertSet(pageResult.getList(), erpStockRecordDO -> Long.parseLong(erpStockRecordDO.getCreator()))); + convertSet(pageResult.getList(), stockOut -> Long.parseLong(stockOut.getCreator()))); // 2. 开始拼接 return BeanUtils.toBean(pageResult, ErpSaleOutRespVO.class, saleOut -> { saleOut.setItems(BeanUtils.toBean(saleOutItemMap.get(saleOut.getId()), ErpSaleOutRespVO.Item.class, diff --git a/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/controller/admin/sale/ErpSaleReturnController.java b/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/controller/admin/sale/ErpSaleReturnController.java index 09ba77291..0dfba67e9 100644 --- a/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/controller/admin/sale/ErpSaleReturnController.java +++ b/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/controller/admin/sale/ErpSaleReturnController.java @@ -150,7 +150,7 @@ public class ErpSaleReturnController { convertSet(pageResult.getList(), ErpSaleReturnDO::getCustomerId)); // 1.4 管理员信息 Map userMap = adminUserApi.getUserMap( - convertSet(pageResult.getList(), erpStockRecordDO -> Long.parseLong(erpStockRecordDO.getCreator()))); + convertSet(pageResult.getList(), saleReturn -> Long.parseLong(saleReturn.getCreator()))); // 2. 开始拼接 return BeanUtils.toBean(pageResult, ErpSaleReturnRespVO.class, saleReturn -> { saleReturn.setItems(BeanUtils.toBean(saleReturnItemMap.get(saleReturn.getId()), ErpSaleReturnRespVO.Item.class, diff --git a/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/controller/admin/stock/ErpStockCheckController.java b/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/controller/admin/stock/ErpStockCheckController.java index 8e30232f6..298ed54fa 100644 --- a/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/controller/admin/stock/ErpStockCheckController.java +++ b/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/controller/admin/stock/ErpStockCheckController.java @@ -126,7 +126,7 @@ public class ErpStockCheckController { if (CollUtil.isEmpty(pageResult.getList())) { return PageResult.empty(pageResult.getTotal()); } - // 1.1 出库项 + // 1.1 盘点项 List stockCheckItemList = stockCheckService.getStockCheckItemListByCheckIds( convertSet(pageResult.getList(), ErpStockCheckDO::getId)); Map> stockCheckItemMap = convertMultiMap(stockCheckItemList, ErpStockCheckItemDO::getCheckId); @@ -135,7 +135,7 @@ public class ErpStockCheckController { convertSet(stockCheckItemList, ErpStockCheckItemDO::getProductId)); // 1.3 管理员信息 Map userMap = adminUserApi.getUserMap( - convertSet(pageResult.getList(), erpStockRecordDO -> Long.parseLong(erpStockRecordDO.getCreator()))); + convertSet(pageResult.getList(), stockCheck -> Long.parseLong(stockCheck.getCreator()))); // 2. 开始拼接 return BeanUtils.toBean(pageResult, ErpStockCheckRespVO.class, stockCheck -> { stockCheck.setItems(BeanUtils.toBean(stockCheckItemMap.get(stockCheck.getId()), ErpStockCheckRespVO.Item.class, diff --git a/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/controller/admin/stock/ErpStockInController.java b/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/controller/admin/stock/ErpStockInController.java index 8cdd84c58..8813da89a 100644 --- a/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/controller/admin/stock/ErpStockInController.java +++ b/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/controller/admin/stock/ErpStockInController.java @@ -150,7 +150,7 @@ public class ErpStockInController { convertSet(pageResult.getList(), ErpStockInDO::getSupplierId)); // 1.4 管理员信息 Map userMap = adminUserApi.getUserMap( - convertSet(pageResult.getList(), erpStockRecordDO -> Long.parseLong(erpStockRecordDO.getCreator()))); + convertSet(pageResult.getList(), stockIn -> Long.parseLong(stockIn.getCreator()))); // 2. 开始拼接 return BeanUtils.toBean(pageResult, ErpStockInRespVO.class, stockIn -> { stockIn.setItems(BeanUtils.toBean(stockInItemMap.get(stockIn.getId()), ErpStockInRespVO.Item.class, diff --git a/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/controller/admin/stock/ErpStockMoveController.java b/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/controller/admin/stock/ErpStockMoveController.java index e3805c994..1df3fd7fc 100644 --- a/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/controller/admin/stock/ErpStockMoveController.java +++ b/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/controller/admin/stock/ErpStockMoveController.java @@ -134,7 +134,7 @@ public class ErpStockMoveController { if (CollUtil.isEmpty(pageResult.getList())) { return PageResult.empty(pageResult.getTotal()); } - // 1.1 出库项 + // 1.1 调拨项 List stockMoveItemList = stockMoveService.getStockMoveItemListByMoveIds( convertSet(pageResult.getList(), ErpStockMoveDO::getId)); Map> stockMoveItemMap = convertMultiMap(stockMoveItemList, ErpStockMoveItemDO::getMoveId); @@ -144,7 +144,7 @@ public class ErpStockMoveController { // 1.3 TODO 芋艿:搞仓库信息 // 1.4 管理员信息 Map userMap = adminUserApi.getUserMap( - convertSet(pageResult.getList(), erpStockRecordDO -> Long.parseLong(erpStockRecordDO.getCreator()))); + convertSet(pageResult.getList(), stockMove -> Long.parseLong(stockMove.getCreator()))); // 2. 开始拼接 return BeanUtils.toBean(pageResult, ErpStockMoveRespVO.class, stockMove -> { stockMove.setItems(BeanUtils.toBean(stockMoveItemMap.get(stockMove.getId()), ErpStockMoveRespVO.Item.class, diff --git a/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/controller/admin/stock/ErpStockOutController.java b/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/controller/admin/stock/ErpStockOutController.java index 55b7fa988..9ad592f1a 100644 --- a/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/controller/admin/stock/ErpStockOutController.java +++ b/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/controller/admin/stock/ErpStockOutController.java @@ -150,7 +150,7 @@ public class ErpStockOutController { convertSet(pageResult.getList(), ErpStockOutDO::getCustomerId)); // 1.4 管理员信息 Map userMap = adminUserApi.getUserMap( - convertSet(pageResult.getList(), erpStockRecordDO -> Long.parseLong(erpStockRecordDO.getCreator()))); + convertSet(pageResult.getList(), stockOut -> Long.parseLong(stockOut.getCreator()))); // 2. 开始拼接 return BeanUtils.toBean(pageResult, ErpStockOutRespVO.class, stockOut -> { stockOut.setItems(BeanUtils.toBean(stockOutItemMap.get(stockOut.getId()), ErpStockOutRespVO.Item.class, diff --git a/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/controller/admin/stock/ErpStockRecordController.java b/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/controller/admin/stock/ErpStockRecordController.java index 09f9feaf9..6ed453894 100644 --- a/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/controller/admin/stock/ErpStockRecordController.java +++ b/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/controller/admin/stock/ErpStockRecordController.java @@ -93,7 +93,7 @@ public class ErpStockRecordController { Map warehouseMap = warehouseService.getWarehouseMap( convertSet(pageResult.getList(), ErpStockRecordDO::getWarehouseId)); Map userMap = adminUserApi.getUserMap( - convertSet(pageResult.getList(), erpStockRecordDO -> Long.parseLong(erpStockRecordDO.getCreator()))); + convertSet(pageResult.getList(), record -> Long.parseLong(record.getCreator()))); return BeanUtils.toBean(pageResult, ErpStockRecordRespVO.class, stock -> { MapUtils.findAndThen(productMap, stock.getProductId(), product -> stock.setProductName(product.getName()) .setCategoryName(product.getCategoryName()).setUnitName(product.getUnitName())); diff --git a/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/dal/dataobject/finance/ErpFinancePaymentDO.java b/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/dal/dataobject/finance/ErpFinancePaymentDO.java new file mode 100644 index 000000000..edb55edbf --- /dev/null +++ b/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/dal/dataobject/finance/ErpFinancePaymentDO.java @@ -0,0 +1,86 @@ +package cn.iocoder.yudao.module.erp.dal.dataobject.finance; + +import cn.iocoder.yudao.framework.mybatis.core.dataobject.BaseDO; +import cn.iocoder.yudao.module.erp.dal.dataobject.purchase.ErpSupplierDO; +import com.baomidou.mybatisplus.annotation.KeySequence; +import com.baomidou.mybatisplus.annotation.TableId; +import com.baomidou.mybatisplus.annotation.TableName; +import lombok.*; + +import java.math.BigDecimal; +import java.time.LocalDateTime; + +/** + * ERP 付款单 DO + * + * @author 芋道源码 + */ +@TableName("erp_finance_payment") +@KeySequence("erp_finance_payment_seq") // 用于 Oracle、PostgreSQL、Kingbase、DB2、H2 数据库的主键自增。如果是 MySQL 等数据库,可不写。 +@Data +@EqualsAndHashCode(callSuper = true) +@ToString(callSuper = true) +@Builder +@NoArgsConstructor +@AllArgsConstructor +public class ErpFinancePaymentDO extends BaseDO { + + /** + * 编号 + */ + @TableId + private Long id; + /** + * 付款单号 + */ + private String no; + /** + * 付款状态 + * + * 枚举 {@link cn.iocoder.yudao.module.erp.enums.ErpAuditStatus} + */ + private Integer status; + /** + * 付款时间 + */ + private LocalDateTime paymentTime; + /** + * 财务人员编号 + * + * 关联 AdminUserDO 的 id 字段 + */ + private Long financeUserId; + /** + * 供应商编号 + * + * 关联 {@link ErpSupplierDO#getId()} + */ + private Long supplierId; + /** + * 付款账户编号 + * + * 关联 {@link ErpAccountDO#getId()} + */ + private Long accountId; + + /** + * 合计价格,单位:元 + */ + private BigDecimal totalPrice; + /** + * 优惠金额,单位:元 + */ + private BigDecimal discountPrice; + /** + * 实付金额,单位:分 + * + * paymentPrice = totalPrice - discountPrice + */ + private BigDecimal paymentPrice; + + /** + * 备注 + */ + private String remark; + +} \ No newline at end of file diff --git a/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/dal/dataobject/finance/ErpFinancePaymentItemDO.java b/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/dal/dataobject/finance/ErpFinancePaymentItemDO.java new file mode 100644 index 000000000..fc3ed1ada --- /dev/null +++ b/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/dal/dataobject/finance/ErpFinancePaymentItemDO.java @@ -0,0 +1,75 @@ +package cn.iocoder.yudao.module.erp.dal.dataobject.finance; + +import cn.iocoder.yudao.framework.mybatis.core.dataobject.BaseDO; +import cn.iocoder.yudao.module.erp.dal.dataobject.purchase.ErpPurchaseInDO; +import com.baomidou.mybatisplus.annotation.KeySequence; +import com.baomidou.mybatisplus.annotation.TableId; +import com.baomidou.mybatisplus.annotation.TableName; +import lombok.*; + +import java.math.BigDecimal; + +/** + * ERP 付款项 DO + * + * @author 芋道源码 + */ +@TableName("erp_finance_payment_item") +@KeySequence("erp_finance_payment_item_seq") // 用于 Oracle、PostgreSQL、Kingbase、DB2、H2 数据库的主键自增。如果是 MySQL 等数据库,可不写。 +@Data +@EqualsAndHashCode(callSuper = true) +@ToString(callSuper = true) +@Builder +@NoArgsConstructor +@AllArgsConstructor +public class ErpFinancePaymentItemDO extends BaseDO { + + /** + * 入库项编号 + */ + @TableId + private Long id; + /** + * 付款单编号 + * + * 关联 {@link ErpFinancePaymentDO#getId()} + */ + private Long paymentId; + + /** + * 业务类型 + * + * 枚举 {@link cn.iocoder.yudao.module.erp.enums.common.ErpBizTypeEnum} 的采购入库、退货 + */ + private Integer bizType; + /** + * 业务编号 + * + * 例如说:{@link ErpPurchaseInDO#getId()} + */ + private Long bizId; + /** + * 业务单号 + * + * 例如说:{@link ErpPurchaseInDO#getNo()} + */ + private String bizNo; + + /** + * 应付欠款,单位:分 + */ + private BigDecimal totalPrice; + /** + * 已付欠款,单位:分 + */ + private BigDecimal paidPrice; + /** + * 本次付款,单位:分 + */ + private BigDecimal paymentPrice; + /** + * 备注 + */ + private String remark; + +} \ No newline at end of file diff --git a/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/dal/mysql/finance/ErpAccountMapper.java b/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/dal/mysql/finance/ErpAccountMapper.java index 693a2804b..2f98147e2 100644 --- a/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/dal/mysql/finance/ErpAccountMapper.java +++ b/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/dal/mysql/finance/ErpAccountMapper.java @@ -3,7 +3,7 @@ package cn.iocoder.yudao.module.erp.dal.mysql.finance; import cn.iocoder.yudao.framework.common.pojo.PageResult; import cn.iocoder.yudao.framework.mybatis.core.mapper.BaseMapperX; import cn.iocoder.yudao.framework.mybatis.core.query.LambdaQueryWrapperX; -import cn.iocoder.yudao.module.erp.controller.admin.finance.vo.ErpAccountPageReqVO; +import cn.iocoder.yudao.module.erp.controller.admin.finance.vo.account.ErpAccountPageReqVO; import cn.iocoder.yudao.module.erp.dal.dataobject.finance.ErpAccountDO; import org.apache.ibatis.annotations.Mapper; diff --git a/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/dal/mysql/finance/ErpFinancePaymentItemMapper.java b/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/dal/mysql/finance/ErpFinancePaymentItemMapper.java new file mode 100644 index 000000000..646d07976 --- /dev/null +++ b/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/dal/mysql/finance/ErpFinancePaymentItemMapper.java @@ -0,0 +1,30 @@ +package cn.iocoder.yudao.module.erp.dal.mysql.finance; + +import cn.iocoder.yudao.framework.mybatis.core.mapper.BaseMapperX; +import cn.iocoder.yudao.module.erp.dal.dataobject.finance.ErpFinancePaymentItemDO; +import org.apache.ibatis.annotations.Mapper; + +import java.util.Collection; +import java.util.List; + +/** + * ERP 付款单项 Mapper + * + * @author 芋道源码 + */ +@Mapper +public interface ErpFinancePaymentItemMapper extends BaseMapperX { + + default List selectListByPaymentId(Long paymentId) { + return selectList(ErpFinancePaymentItemDO::getPaymentId, paymentId); + } + + default List selectListByPaymentIds(Collection paymentIds) { + return selectList(ErpFinancePaymentItemDO::getPaymentId, paymentIds); + } + + default int deleteByPaymentId(Long paymentId) { + return delete(ErpFinancePaymentItemDO::getPaymentId, paymentId); + } + +} \ No newline at end of file diff --git a/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/dal/mysql/finance/ErpFinancePaymentMapper.java b/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/dal/mysql/finance/ErpFinancePaymentMapper.java new file mode 100644 index 000000000..5ad0cccfd --- /dev/null +++ b/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/dal/mysql/finance/ErpFinancePaymentMapper.java @@ -0,0 +1,48 @@ +package cn.iocoder.yudao.module.erp.dal.mysql.finance; + +import cn.iocoder.yudao.framework.common.pojo.PageResult; +import cn.iocoder.yudao.framework.mybatis.core.mapper.BaseMapperX; +import cn.iocoder.yudao.framework.mybatis.core.query.MPJLambdaWrapperX; +import cn.iocoder.yudao.module.erp.controller.admin.finance.vo.payment.ErpFinancePaymentPageReqVO; +import cn.iocoder.yudao.module.erp.dal.dataobject.finance.ErpFinancePaymentDO; +import cn.iocoder.yudao.module.erp.dal.dataobject.finance.ErpFinancePaymentItemDO; +import com.baomidou.mybatisplus.core.conditions.update.LambdaUpdateWrapper; +import org.apache.ibatis.annotations.Mapper; + +/** + * ERP 付款单 Mapper + * + * @author 芋道源码 + */ +@Mapper +public interface ErpFinancePaymentMapper extends BaseMapperX { + + default PageResult selectPage(ErpFinancePaymentPageReqVO reqVO) { + MPJLambdaWrapperX query = new MPJLambdaWrapperX() + .likeIfPresent(ErpFinancePaymentDO::getNo, reqVO.getNo()) + .betweenIfPresent(ErpFinancePaymentDO::getPaymentTime, reqVO.getPaymentTime()) + .eqIfPresent(ErpFinancePaymentDO::getSupplierId, reqVO.getSupplierId()) + .eqIfPresent(ErpFinancePaymentDO::getCreator, reqVO.getCreator()) + .eqIfPresent(ErpFinancePaymentDO::getFinanceUserId, reqVO.getFinanceUserId()) + .eqIfPresent(ErpFinancePaymentDO::getAccountId, reqVO.getAccountId()) + .eqIfPresent(ErpFinancePaymentDO::getStatus, reqVO.getStatus()) + .likeIfPresent(ErpFinancePaymentDO::getRemark, reqVO.getRemark()) + .orderByDesc(ErpFinancePaymentDO::getId); + if (reqVO.getBizNo() != null) { + query.leftJoin(ErpFinancePaymentItemDO.class, ErpFinancePaymentItemDO::getPaymentId, ErpFinancePaymentDO::getId) + .eq(reqVO.getBizNo() != null, ErpFinancePaymentItemDO::getBizNo, reqVO.getBizNo()) + .groupBy(ErpFinancePaymentDO::getId); // 避免 1 对多查询,产生相同的 1 + } + return selectJoinPage(reqVO, ErpFinancePaymentDO.class, query); + } + + default int updateByIdAndStatus(Long id, Integer status, ErpFinancePaymentDO updateObj) { + return update(updateObj, new LambdaUpdateWrapper() + .eq(ErpFinancePaymentDO::getId, id).eq(ErpFinancePaymentDO::getStatus, status)); + } + + default ErpFinancePaymentDO selectByNo(String no) { + return selectOne(ErpFinancePaymentDO::getNo, no); + } + +} \ No newline at end of file diff --git a/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/dal/redis/no/ErpNoRedisDAO.java b/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/dal/redis/no/ErpNoRedisDAO.java index f2e72a4dd..d99990133 100644 --- a/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/dal/redis/no/ErpNoRedisDAO.java +++ b/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/dal/redis/no/ErpNoRedisDAO.java @@ -64,6 +64,11 @@ public class ErpNoRedisDAO { */ public static final String PURCHASE_RETURN_NO_PREFIX = "CGTH"; + /** + * 付款单 {@link cn.iocoder.yudao.module.erp.dal.dataobject.finance.ErpFinancePaymentDO} + */ + public static final String FINANCE_PAYMENT_NO_PREFIX = "FKD"; + @Resource private StringRedisTemplate stringRedisTemplate; diff --git a/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/service/finance/ErpAccountService.java b/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/service/finance/ErpAccountService.java index e1d321ec0..b6bba2fd9 100644 --- a/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/service/finance/ErpAccountService.java +++ b/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/service/finance/ErpAccountService.java @@ -1,8 +1,8 @@ package cn.iocoder.yudao.module.erp.service.finance; import cn.iocoder.yudao.framework.common.pojo.PageResult; -import cn.iocoder.yudao.module.erp.controller.admin.finance.vo.ErpAccountPageReqVO; -import cn.iocoder.yudao.module.erp.controller.admin.finance.vo.ErpAccountSaveReqVO; +import cn.iocoder.yudao.module.erp.controller.admin.finance.vo.account.ErpAccountPageReqVO; +import cn.iocoder.yudao.module.erp.controller.admin.finance.vo.account.ErpAccountSaveReqVO; import cn.iocoder.yudao.module.erp.dal.dataobject.finance.ErpAccountDO; import jakarta.validation.Valid; diff --git a/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/service/finance/ErpAccountServiceImpl.java b/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/service/finance/ErpAccountServiceImpl.java index 375a4ca48..bc5dafa24 100644 --- a/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/service/finance/ErpAccountServiceImpl.java +++ b/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/service/finance/ErpAccountServiceImpl.java @@ -3,8 +3,8 @@ package cn.iocoder.yudao.module.erp.service.finance; import cn.iocoder.yudao.framework.common.enums.CommonStatusEnum; import cn.iocoder.yudao.framework.common.pojo.PageResult; import cn.iocoder.yudao.framework.common.util.object.BeanUtils; -import cn.iocoder.yudao.module.erp.controller.admin.finance.vo.ErpAccountPageReqVO; -import cn.iocoder.yudao.module.erp.controller.admin.finance.vo.ErpAccountSaveReqVO; +import cn.iocoder.yudao.module.erp.controller.admin.finance.vo.account.ErpAccountPageReqVO; +import cn.iocoder.yudao.module.erp.controller.admin.finance.vo.account.ErpAccountSaveReqVO; import cn.iocoder.yudao.module.erp.dal.dataobject.finance.ErpAccountDO; import cn.iocoder.yudao.module.erp.dal.mysql.finance.ErpAccountMapper; import jakarta.annotation.Resource; diff --git a/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/service/finance/ErpFinancePaymentService.java b/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/service/finance/ErpFinancePaymentService.java new file mode 100644 index 000000000..b2f27917d --- /dev/null +++ b/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/service/finance/ErpFinancePaymentService.java @@ -0,0 +1,84 @@ +package cn.iocoder.yudao.module.erp.service.finance; + +import cn.iocoder.yudao.framework.common.pojo.PageResult; +import cn.iocoder.yudao.module.erp.controller.admin.finance.vo.payment.ErpFinancePaymentPageReqVO; +import cn.iocoder.yudao.module.erp.controller.admin.finance.vo.payment.ErpFinancePaymentSaveReqVO; +import cn.iocoder.yudao.module.erp.dal.dataobject.finance.ErpFinancePaymentDO; +import cn.iocoder.yudao.module.erp.dal.dataobject.finance.ErpFinancePaymentItemDO; +import jakarta.validation.Valid; + +import java.util.Collection; +import java.util.List; + +/** + * ERP 付款单 Service 接口 + * + * @author 芋道源码 + */ +public interface ErpFinancePaymentService { + + /** + * 创建付款单 + * + * @param createReqVO 创建信息 + * @return 编号 + */ + Long createFinancePayment(@Valid ErpFinancePaymentSaveReqVO createReqVO); + + /** + * 更新付款单 + * + * @param updateReqVO 更新信息 + */ + void updateFinancePayment(@Valid ErpFinancePaymentSaveReqVO updateReqVO); + + /** + * 更新付款单的状态 + * + * @param id 编号 + * @param status 状态 + */ + void updateFinancePaymentStatus(Long id, Integer status); + + /** + * 删除付款单 + * + * @param ids 编号数组 + */ + void deleteFinancePayment(List ids); + + /** + * 获得付款单 + * + * @param id 编号 + * @return 付款单 + */ + ErpFinancePaymentDO getFinancePayment(Long id); + + /** + * 获得付款单分页 + * + * @param pageReqVO 分页查询 + * @return 付款单分页 + */ + PageResult getFinancePaymentPage(ErpFinancePaymentPageReqVO pageReqVO); + + // ==================== 付款单项 ==================== + + /** + * 获得付款单项列表 + * + * @param paymentId 付款单编号 + * @return 付款单项列表 + */ + List getFinancePaymentItemListByPaymentId(Long paymentId); + + /** + * 获得付款单项 List + * + * @param paymentIds 付款单编号数组 + * @return 付款单项 List + */ + List getFinancePaymentItemListByPaymentIds(Collection paymentIds); + +} \ No newline at end of file diff --git a/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/service/finance/ErpFinancePaymentServiceImpl.java b/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/service/finance/ErpFinancePaymentServiceImpl.java new file mode 100644 index 000000000..a20a35742 --- /dev/null +++ b/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/service/finance/ErpFinancePaymentServiceImpl.java @@ -0,0 +1,241 @@ +package cn.iocoder.yudao.module.erp.service.finance; + +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.object.BeanUtils; +import cn.iocoder.yudao.module.erp.controller.admin.finance.vo.payment.ErpFinancePaymentPageReqVO; +import cn.iocoder.yudao.module.erp.controller.admin.finance.vo.payment.ErpFinancePaymentSaveReqVO; +import cn.iocoder.yudao.module.erp.dal.dataobject.finance.ErpFinancePaymentDO; +import cn.iocoder.yudao.module.erp.dal.dataobject.finance.ErpFinancePaymentItemDO; +import cn.iocoder.yudao.module.erp.dal.dataobject.purchase.ErpPurchaseInDO; +import cn.iocoder.yudao.module.erp.dal.dataobject.purchase.ErpPurchaseReturnDO; +import cn.iocoder.yudao.module.erp.dal.mysql.finance.ErpFinancePaymentItemMapper; +import cn.iocoder.yudao.module.erp.dal.mysql.finance.ErpFinancePaymentMapper; +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.common.ErpBizTypeEnum; +import cn.iocoder.yudao.module.erp.service.purchase.ErpPurchaseInService; +import cn.iocoder.yudao.module.erp.service.purchase.ErpPurchaseReturnService; +import cn.iocoder.yudao.module.erp.service.purchase.ErpSupplierService; +import cn.iocoder.yudao.module.system.api.user.AdminUserApi; +import jakarta.annotation.Resource; +import org.springframework.stereotype.Service; +import org.springframework.transaction.annotation.Transactional; +import org.springframework.validation.annotation.Validated; + +import java.math.BigDecimal; +import java.util.Collection; +import java.util.Collections; +import java.util.List; + +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.module.erp.enums.ErrorCodeConstants.*; + +// TODO 芋艿:记录操作日志 + +/** + * ERP 付款单 Service 实现类 + * + * @author 芋道源码 + */ +@Service +@Validated +public class ErpFinancePaymentServiceImpl implements ErpFinancePaymentService { + + @Resource + private ErpFinancePaymentMapper financePaymentMapper; + @Resource + private ErpFinancePaymentItemMapper financePaymentItemMapper; + + @Resource + private ErpNoRedisDAO noRedisDAO; + + @Resource + private ErpSupplierService supplierService; + @Resource + private ErpAccountService accountService; + @Resource + private ErpPurchaseInService purchaseInService; + @Resource + private ErpPurchaseReturnService purchaseReturnService; + + @Resource + private AdminUserApi adminUserApi; + + @Override + @Transactional(rollbackFor = Exception.class) + public Long createFinancePayment(ErpFinancePaymentSaveReqVO createReqVO) { + // 1.1 校验订单项的有效性 + List paymentItems = validateFinancePaymentItems(createReqVO.getItems()); + // 1.2 校验供应商 + supplierService.validateSupplier(createReqVO.getSupplierId()); + // 1.3 校验结算账户 + if (createReqVO.getAccountId() != null) { + accountService.validateAccount(createReqVO.getAccountId()); + } + // 1.4 校验财务人员 + if (createReqVO.getFinanceUserId() != null) { + adminUserApi.validateUser(createReqVO.getFinanceUserId()); + } + // 1.5 生成付款单号,并校验唯一性 + String no = noRedisDAO.generate(ErpNoRedisDAO.FINANCE_PAYMENT_NO_PREFIX); + if (financePaymentMapper.selectByNo(no) != null) { + throw exception(FINANCE_PAYMENT_NO_EXISTS); + } + + // 2.1 插入付款单 + ErpFinancePaymentDO payment = BeanUtils.toBean(createReqVO, ErpFinancePaymentDO.class, in -> in + .setNo(no).setStatus(ErpAuditStatus.PROCESS.getStatus())); + calculateTotalPrice(payment, paymentItems); + financePaymentMapper.insert(payment); + // 2.2 插入付款单项 + paymentItems.forEach(o -> o.setPaymentId(payment.getId())); + financePaymentItemMapper.insertBatch(paymentItems); + return payment.getId(); + } + + @Override + @Transactional(rollbackFor = Exception.class) + public void updateFinancePayment(ErpFinancePaymentSaveReqVO updateReqVO) { + // 1.1 校验存在 + ErpFinancePaymentDO payment = validateFinancePaymentExists(updateReqVO.getId()); + if (ErpAuditStatus.APPROVE.getStatus().equals(payment.getStatus())) { + throw exception(SALE_ORDER_UPDATE_FAIL_APPROVE, payment.getNo()); + } + // 1.2 校验供应商 + supplierService.validateSupplier(updateReqVO.getSupplierId()); + // 1.3 校验结算账户 + if (updateReqVO.getAccountId() != null) { + accountService.validateAccount(updateReqVO.getAccountId()); + } + // 1.4 校验财务人员 + if (updateReqVO.getFinanceUserId() != null) { + adminUserApi.validateUser(updateReqVO.getFinanceUserId()); + } + // 1.5 校验付款单项的有效性 + List paymentItems = validateFinancePaymentItems(updateReqVO.getItems()); + + // 2.1 更新付款单 + ErpFinancePaymentDO updateObj = BeanUtils.toBean(updateReqVO, ErpFinancePaymentDO.class); + calculateTotalPrice(updateObj, paymentItems); + financePaymentMapper.updateById(updateObj); + // 2.2 更新付款单项 + updateFinancePaymentItemList(updateReqVO.getId(), paymentItems); + } + + private void calculateTotalPrice(ErpFinancePaymentDO payment, List paymentItems) { + payment.setTotalPrice(getSumValue(paymentItems, ErpFinancePaymentItemDO::getPaymentPrice, BigDecimal::add, BigDecimal.ZERO)); + payment.setPaymentPrice(payment.getTotalPrice().subtract(payment.getDiscountPrice())); + } + + @Override + @Transactional(rollbackFor = Exception.class) + public void updateFinancePaymentStatus(Long id, Integer status) { + boolean approve = ErpAuditStatus.APPROVE.getStatus().equals(status); + // 1.1 校验存在 + ErpFinancePaymentDO payment = validateFinancePaymentExists(id); + // 1.2 校验状态 + if (payment.getStatus().equals(status)) { + throw exception(approve ? SALE_ORDER_APPROVE_FAIL : SALE_ORDER_PROCESS_FAIL); + } + + // 2. 更新状态 + int updateCount = financePaymentMapper.updateByIdAndStatus(id, payment.getStatus(), + new ErpFinancePaymentDO().setStatus(status)); + if (updateCount == 0) { + throw exception(approve ? SALE_ORDER_APPROVE_FAIL : SALE_ORDER_PROCESS_FAIL); + } + } + + private List validateFinancePaymentItems(List list) { + return convertList(list, o -> BeanUtils.toBean(o, ErpFinancePaymentItemDO.class, item -> { + if (ObjectUtil.equal(item.getBizType(), ErpBizTypeEnum.PURCHASE_IN.getType())) { + ErpPurchaseInDO purchaseIn = purchaseInService.validatePurchaseIn(item.getBizId()); + item.setTotalPrice(purchaseIn.getTotalPrice()).setBizNo(purchaseIn.getNo()); + } else if (ObjectUtil.equal(item.getBizType(), ErpBizTypeEnum.PURCHASE_RETURN.getType())) { + ErpPurchaseReturnDO purchaseReturn = purchaseReturnService.validatePurchaseReturn(item.getBizId()); + item.setTotalPrice(purchaseReturn.getTotalPrice()).setBizNo(purchaseReturn.getNo()); + } else { + throw new IllegalArgumentException("业务类型不正确:" + item.getBizType()); + } + })); + } + + private void updateFinancePaymentItemList(Long id, List newList) { + // 第一步,对比新老数据,获得添加、修改、删除的列表 + List oldList = financePaymentItemMapper.selectListByPaymentId(id); + List> diffList = diffList(oldList, newList, // id 不同,就认为是不同的记录 + (oldVal, newVal) -> oldVal.getId().equals(newVal.getId())); + + // 第二步,批量添加、修改、删除 + if (CollUtil.isNotEmpty(diffList.get(0))) { + diffList.get(0).forEach(o -> o.setPaymentId(id)); + financePaymentItemMapper.insertBatch(diffList.get(0)); + } + if (CollUtil.isNotEmpty(diffList.get(1))) { + financePaymentItemMapper.updateBatch(diffList.get(1)); + } + if (CollUtil.isNotEmpty(diffList.get(2))) { + financePaymentItemMapper.deleteBatchIds(convertList(diffList.get(2), ErpFinancePaymentItemDO::getId)); + } + } + + @Override + @Transactional(rollbackFor = Exception.class) + public void deleteFinancePayment(List ids) { + // 1. 校验不处于已审批 + List payments = financePaymentMapper.selectBatchIds(ids); + if (CollUtil.isEmpty(payments)) { + return; + } + payments.forEach(payment -> { + if (ErpAuditStatus.APPROVE.getStatus().equals(payment.getStatus())) { + throw exception(SALE_ORDER_DELETE_FAIL_APPROVE, payment.getNo()); + } + }); + + // 2. 遍历删除,并记录操作日志 + payments.forEach(payment -> { + // 2.1 删除付款单 + financePaymentMapper.deleteById(payment.getId()); + // 2.2 删除付款单项 + financePaymentItemMapper.deleteByPaymentId(payment.getId()); + }); + } + + private ErpFinancePaymentDO validateFinancePaymentExists(Long id) { + ErpFinancePaymentDO payment = financePaymentMapper.selectById(id); + if (payment == null) { + throw exception(SALE_ORDER_NOT_EXISTS); + } + return payment; + } + + @Override + public ErpFinancePaymentDO getFinancePayment(Long id) { + return financePaymentMapper.selectById(id); + } + + @Override + public PageResult getFinancePaymentPage(ErpFinancePaymentPageReqVO pageReqVO) { + return financePaymentMapper.selectPage(pageReqVO); + } + + // ==================== 付款单项 ==================== + + @Override + public List getFinancePaymentItemListByPaymentId(Long paymentId) { + return financePaymentItemMapper.selectListByPaymentId(paymentId); + } + + @Override + public List getFinancePaymentItemListByPaymentIds(Collection paymentIds) { + if (CollUtil.isEmpty(paymentIds)) { + return Collections.emptyList(); + } + return financePaymentItemMapper.selectListByPaymentIds(paymentIds); + } + +} \ No newline at end of file diff --git a/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/service/purchase/ErpPurchaseInService.java b/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/service/purchase/ErpPurchaseInService.java index 12ad08a3c..2c892ccd0 100644 --- a/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/service/purchase/ErpPurchaseInService.java +++ b/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/service/purchase/ErpPurchaseInService.java @@ -55,6 +55,14 @@ public interface ErpPurchaseInService { */ ErpPurchaseInDO getPurchaseIn(Long id); + /** + * 校验采购入库,已经审核通过 + * + * @param id 编号 + * @return 采购入库 + */ + ErpPurchaseInDO validatePurchaseIn(Long id); + /** * 获得采购入库分页 * diff --git a/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/service/purchase/ErpPurchaseInServiceImpl.java b/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/service/purchase/ErpPurchaseInServiceImpl.java index 7bb009f9a..04d92a713 100644 --- a/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/service/purchase/ErpPurchaseInServiceImpl.java +++ b/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/service/purchase/ErpPurchaseInServiceImpl.java @@ -78,7 +78,7 @@ public class ErpPurchaseInServiceImpl implements ErpPurchaseInService { List purchaseInItems = validatePurchaseInItems(createReqVO.getItems()); // 1.3 校验结算账户 accountService.validateAccount(createReqVO.getAccountId()); - // 1.4 生成调拨单号,并校验唯一性 + // 1.4 生成入库单号,并校验唯一性 String no = noRedisDAO.generate(ErpNoRedisDAO.PURCHASE_IN_NO_PREFIX); if (purchaseInMapper.selectByNo(no) != null) { throw exception(PURCHASE_IN_NO_EXISTS); @@ -163,6 +163,7 @@ public class ErpPurchaseInServiceImpl implements ErpPurchaseInService { if (purchaseIn.getStatus().equals(status)) { throw exception(approve ? PURCHASE_IN_APPROVE_FAIL : PURCHASE_IN_PROCESS_FAIL); } + // TODO 芋艿:稍后加下校验 // 2. 更新状态 int updateCount = purchaseInMapper.updateByIdAndStatus(id, purchaseIn.getStatus(), @@ -260,6 +261,15 @@ public class ErpPurchaseInServiceImpl implements ErpPurchaseInService { return purchaseInMapper.selectById(id); } + @Override + public ErpPurchaseInDO validatePurchaseIn(Long id) { + ErpPurchaseInDO purchaseIn = validatePurchaseInExists(id); + if (ObjectUtil.notEqual(purchaseIn.getStatus(), ErpAuditStatus.APPROVE.getStatus())) { + throw exception(PURCHASE_IN_NOT_APPROVE); + } + return purchaseIn; + } + @Override public PageResult getPurchaseInPage(ErpPurchaseInPageReqVO pageReqVO) { return purchaseInMapper.selectPage(pageReqVO); diff --git a/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/service/purchase/ErpPurchaseOrderServiceImpl.java b/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/service/purchase/ErpPurchaseOrderServiceImpl.java index 0c0790734..74b5b18d2 100644 --- a/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/service/purchase/ErpPurchaseOrderServiceImpl.java +++ b/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/service/purchase/ErpPurchaseOrderServiceImpl.java @@ -68,7 +68,7 @@ public class ErpPurchaseOrderServiceImpl implements ErpPurchaseOrderService { if (createReqVO.getAccountId() != null) { accountService.validateAccount(createReqVO.getAccountId()); } - // 1.4 生成调拨单号,并校验唯一性 + // 1.4 生成订单号,并校验唯一性 String no = noRedisDAO.generate(ErpNoRedisDAO.PURCHASE_ORDER_NO_PREFIX); if (purchaseOrderMapper.selectByNo(no) != null) { throw exception(PURCHASE_ORDER_NO_EXISTS); diff --git a/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/service/purchase/ErpPurchaseReturnService.java b/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/service/purchase/ErpPurchaseReturnService.java index b8e0ad665..cd6f26e25 100644 --- a/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/service/purchase/ErpPurchaseReturnService.java +++ b/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/service/purchase/ErpPurchaseReturnService.java @@ -55,6 +55,14 @@ public interface ErpPurchaseReturnService { */ ErpPurchaseReturnDO getPurchaseReturn(Long id); + /** + * 校验采购退货,已经审核通过 + * + * @param id 编号 + * @return 采购退货 + */ + ErpPurchaseReturnDO validatePurchaseReturn(Long id); + /** * 获得采购退货分页 * diff --git a/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/service/purchase/ErpPurchaseReturnServiceImpl.java b/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/service/purchase/ErpPurchaseReturnServiceImpl.java index 716ae88f2..1d33db69a 100644 --- a/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/service/purchase/ErpPurchaseReturnServiceImpl.java +++ b/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/service/purchase/ErpPurchaseReturnServiceImpl.java @@ -74,7 +74,7 @@ public class ErpPurchaseReturnServiceImpl implements ErpPurchaseReturnService { List purchaseReturnItems = validatePurchaseReturnItems(createReqVO.getItems()); // 1.3 校验结算账户 accountService.validateAccount(createReqVO.getAccountId()); - // 1.4 生成调拨单号,并校验唯一性 + // 1.4 生成退货单号,并校验唯一性 String no = noRedisDAO.generate(ErpNoRedisDAO.PURCHASE_RETURN_NO_PREFIX); if (purchaseReturnMapper.selectByNo(no) != null) { throw exception(PURCHASE_RETURN_NO_EXISTS); @@ -159,6 +159,7 @@ public class ErpPurchaseReturnServiceImpl implements ErpPurchaseReturnService { if (purchaseReturn.getStatus().equals(status)) { throw exception(approve ? PURCHASE_RETURN_APPROVE_FAIL : PURCHASE_RETURN_PROCESS_FAIL); } + // TODO 芋艿:稍后加下校验 // 2. 更新状态 int updateCount = purchaseReturnMapper.updateByIdAndStatus(id, purchaseReturn.getStatus(), @@ -256,6 +257,15 @@ public class ErpPurchaseReturnServiceImpl implements ErpPurchaseReturnService { return purchaseReturnMapper.selectById(id); } + @Override + public ErpPurchaseReturnDO validatePurchaseReturn(Long id) { + ErpPurchaseReturnDO purchaseReturn = getPurchaseReturn(id); + if (ObjectUtil.notEqual(purchaseReturn.getStatus(), ErpAuditStatus.APPROVE.getStatus())) { + throw exception(PURCHASE_RETURN_NOT_APPROVE); + } + return purchaseReturn; + } + @Override public PageResult getPurchaseReturnPage(ErpPurchaseReturnPageReqVO pageReqVO) { return purchaseReturnMapper.selectPage(pageReqVO); diff --git a/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/service/sale/ErpSaleOrderServiceImpl.java b/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/service/sale/ErpSaleOrderServiceImpl.java index 03b51125c..592fe5fe7 100644 --- a/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/service/sale/ErpSaleOrderServiceImpl.java +++ b/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/service/sale/ErpSaleOrderServiceImpl.java @@ -76,7 +76,7 @@ public class ErpSaleOrderServiceImpl implements ErpSaleOrderService { if (createReqVO.getSaleUserId() != null) { adminUserApi.validateUser(createReqVO.getSaleUserId()); } - // 1.5 生成调拨单号,并校验唯一性 + // 1.5 生成订单号,并校验唯一性 String no = noRedisDAO.generate(ErpNoRedisDAO.SALE_ORDER_NO_PREFIX); if (saleOrderMapper.selectByNo(no) != null) { throw exception(SALE_ORDER_NO_EXISTS); diff --git a/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/service/sale/ErpSaleOutServiceImpl.java b/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/service/sale/ErpSaleOutServiceImpl.java index 03743f0bd..ab0496892 100644 --- a/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/service/sale/ErpSaleOutServiceImpl.java +++ b/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/service/sale/ErpSaleOutServiceImpl.java @@ -82,7 +82,7 @@ public class ErpSaleOutServiceImpl implements ErpSaleOutService { if (createReqVO.getSaleUserId() != null) { adminUserApi.validateUser(createReqVO.getSaleUserId()); } - // 1.5 生成调拨单号,并校验唯一性 + // 1.5 生成出库单号,并校验唯一性 String no = noRedisDAO.generate(ErpNoRedisDAO.SALE_OUT_NO_PREFIX); if (saleOutMapper.selectByNo(no) != null) { throw exception(SALE_OUT_NO_EXISTS); diff --git a/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/service/sale/ErpSaleReturnServiceImpl.java b/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/service/sale/ErpSaleReturnServiceImpl.java index ae5775551..2c680ac45 100644 --- a/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/service/sale/ErpSaleReturnServiceImpl.java +++ b/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/service/sale/ErpSaleReturnServiceImpl.java @@ -82,7 +82,7 @@ public class ErpSaleReturnServiceImpl implements ErpSaleReturnService { if (createReqVO.getSaleUserId() != null) { adminUserApi.validateUser(createReqVO.getSaleUserId()); } - // 1.5 生成调拨单号,并校验唯一性 + // 1.5 生成退货单号,并校验唯一性 String no = noRedisDAO.generate(ErpNoRedisDAO.SALE_RETURN_NO_PREFIX); if (saleReturnMapper.selectByNo(no) != null) { throw exception(SALE_RETURN_NO_EXISTS); diff --git a/yudao-module-erp/yudao-module-erp-biz/src/test/java/cn/iocoder/yudao/module/erp/service/finance/ErpAccountServiceImplTest.java b/yudao-module-erp/yudao-module-erp-biz/src/test/java/cn/iocoder/yudao/module/erp/service/finance/ErpAccountServiceImplTest.java deleted file mode 100644 index 19fc9f313..000000000 --- a/yudao-module-erp/yudao-module-erp-biz/src/test/java/cn/iocoder/yudao/module/erp/service/finance/ErpAccountServiceImplTest.java +++ /dev/null @@ -1,142 +0,0 @@ -package cn.iocoder.yudao.module.erp.service.finance; - -import org.junit.jupiter.api.Disabled; -import org.junit.jupiter.api.Test; -import org.springframework.boot.test.mock.mockito.MockBean; - -import jakarta.annotation.Resource; - -import cn.iocoder.yudao.framework.test.core.ut.BaseDbUnitTest; - -import cn.iocoder.yudao.module.erp.controller.admin.finance.vo.*; -import cn.iocoder.yudao.module.erp.dal.dataobject.finance.ErpAccountDO; -import cn.iocoder.yudao.module.erp.dal.mysql.finance.ErpAccountMapper; -import cn.iocoder.yudao.framework.common.pojo.PageResult; - -import jakarta.annotation.Resource; -import org.springframework.context.annotation.Import; -import java.util.*; -import java.time.LocalDateTime; - -import static cn.hutool.core.util.RandomUtil.*; -import static cn.iocoder.yudao.module.erp.enums.ErrorCodeConstants.*; -import static cn.iocoder.yudao.framework.test.core.util.AssertUtils.*; -import static cn.iocoder.yudao.framework.test.core.util.RandomUtils.*; -import static cn.iocoder.yudao.framework.common.util.date.LocalDateTimeUtils.*; -import static cn.iocoder.yudao.framework.common.util.object.ObjectUtils.*; -import static cn.iocoder.yudao.framework.common.util.date.DateUtils.*; -import static org.junit.jupiter.api.Assertions.*; -import static org.mockito.Mockito.*; - -/** - * {@link ErpAccountServiceImpl} 的单元测试类 - * - * @author 芋道源码 - */ -@Import(ErpAccountServiceImpl.class) -public class ErpAccountServiceImplTest extends BaseDbUnitTest { - - @Resource - private ErpAccountServiceImpl accountService; - - @Resource - private ErpAccountMapper accountMapper; - - @Test - public void testCreateAccount_success() { - // 准备参数 - ErpAccountSaveReqVO createReqVO = randomPojo(ErpAccountSaveReqVO.class).setId(null); - - // 调用 - Long accountId = accountService.createAccount(createReqVO); - // 断言 - assertNotNull(accountId); - // 校验记录的属性是否正确 - ErpAccountDO account = accountMapper.selectById(accountId); - assertPojoEquals(createReqVO, account, "id"); - } - - @Test - public void testUpdateAccount_success() { - // mock 数据 - ErpAccountDO dbAccount = randomPojo(ErpAccountDO.class); - accountMapper.insert(dbAccount);// @Sql: 先插入出一条存在的数据 - // 准备参数 - ErpAccountSaveReqVO updateReqVO = randomPojo(ErpAccountSaveReqVO.class, o -> { - o.setId(dbAccount.getId()); // 设置更新的 ID - }); - - // 调用 - accountService.updateAccount(updateReqVO); - // 校验是否更新正确 - ErpAccountDO account = accountMapper.selectById(updateReqVO.getId()); // 获取最新的 - assertPojoEquals(updateReqVO, account); - } - - @Test - public void testUpdateAccount_notExists() { - // 准备参数 - ErpAccountSaveReqVO updateReqVO = randomPojo(ErpAccountSaveReqVO.class); - - // 调用, 并断言异常 - assertServiceException(() -> accountService.updateAccount(updateReqVO), ACCOUNT_NOT_EXISTS); - } - - @Test - public void testDeleteAccount_success() { - // mock 数据 - ErpAccountDO dbAccount = randomPojo(ErpAccountDO.class); - accountMapper.insert(dbAccount);// @Sql: 先插入出一条存在的数据 - // 准备参数 - Long id = dbAccount.getId(); - - // 调用 - accountService.deleteAccount(id); - // 校验数据不存在了 - assertNull(accountMapper.selectById(id)); - } - - @Test - public void testDeleteAccount_notExists() { - // 准备参数 - Long id = randomLongId(); - - // 调用, 并断言异常 - assertServiceException(() -> accountService.deleteAccount(id), ACCOUNT_NOT_EXISTS); - } - - @Test - @Disabled // TODO 请修改 null 为需要的值,然后删除 @Disabled 注解 - public void testGetAccountPage() { - // mock 数据 - ErpAccountDO dbAccount = randomPojo(ErpAccountDO.class, o -> { // 等会查询到 - o.setNo(null); - o.setRemark(null); - o.setStatus(null); - o.setName(null); - }); - accountMapper.insert(dbAccount); - // 测试 no 不匹配 - accountMapper.insert(cloneIgnoreId(dbAccount, o -> o.setNo(null))); - // 测试 remark 不匹配 - accountMapper.insert(cloneIgnoreId(dbAccount, o -> o.setRemark(null))); - // 测试 status 不匹配 - accountMapper.insert(cloneIgnoreId(dbAccount, o -> o.setStatus(null))); - // 测试 name 不匹配 - accountMapper.insert(cloneIgnoreId(dbAccount, o -> o.setName(null))); - // 准备参数 - ErpAccountPageReqVO reqVO = new ErpAccountPageReqVO(); - reqVO.setNo(null); - reqVO.setRemark(null); - reqVO.setStatus(null); - reqVO.setName(null); - - // 调用 - PageResult pageResult = accountService.getAccountPage(reqVO); - // 断言 - assertEquals(1, pageResult.getTotal()); - assertEquals(1, pageResult.getList().size()); - assertPojoEquals(dbAccount, pageResult.getList().get(0)); - } - -} \ No newline at end of file diff --git a/yudao-module-erp/yudao-module-erp-biz/src/test/java/cn/iocoder/yudao/module/erp/service/product/ErpProductUnitServiceImplTest.java b/yudao-module-erp/yudao-module-erp-biz/src/test/java/cn/iocoder/yudao/module/erp/service/product/ErpProductUnitServiceImplTest.java deleted file mode 100644 index c4023df0e..000000000 --- a/yudao-module-erp/yudao-module-erp-biz/src/test/java/cn/iocoder/yudao/module/erp/service/product/ErpProductUnitServiceImplTest.java +++ /dev/null @@ -1,131 +0,0 @@ -package cn.iocoder.yudao.module.erp.service.product; - -import cn.iocoder.yudao.module.erp.controller.admin.product.vo.unit.ErpProductUnitPageReqVO; -import cn.iocoder.yudao.module.erp.controller.admin.product.vo.unit.ErpProductUnitSaveReqVO; -import org.junit.jupiter.api.Disabled; -import org.junit.jupiter.api.Test; - -import jakarta.annotation.Resource; - -import cn.iocoder.yudao.framework.test.core.ut.BaseDbUnitTest; - -import cn.iocoder.yudao.module.erp.dal.dataobject.product.ErpProductUnitDO; -import cn.iocoder.yudao.module.erp.dal.mysql.product.ErpProductUnitMapper; -import cn.iocoder.yudao.framework.common.pojo.PageResult; - -import org.springframework.context.annotation.Import; - -import static cn.iocoder.yudao.framework.test.core.util.AssertUtils.*; -import static cn.iocoder.yudao.framework.test.core.util.RandomUtils.*; -import static cn.iocoder.yudao.framework.common.util.date.LocalDateTimeUtils.*; -import static cn.iocoder.yudao.framework.common.util.object.ObjectUtils.*; -import static org.junit.jupiter.api.Assertions.*; - -/** - * {@link ErpProductUnitServiceImpl} 的单元测试类 - * - * @author 芋道源码 - */ -@Import(ErpProductUnitServiceImpl.class) -public class ErpProductUnitServiceImplTest extends BaseDbUnitTest { - - @Resource - private ErpProductUnitServiceImpl productUnitService; - - @Resource - private ErpProductUnitMapper productUnitMapper; - - @Test - public void testCreateProductUnit_success() { - // 准备参数 - ErpProductUnitSaveReqVO createReqVO = randomPojo(ErpProductUnitSaveReqVO.class).setId(null); - - // 调用 - Long productUnitId = productUnitService.createProductUnit(createReqVO); - // 断言 - assertNotNull(productUnitId); - // 校验记录的属性是否正确 - ErpProductUnitDO productUnit = productUnitMapper.selectById(productUnitId); - assertPojoEquals(createReqVO, productUnit, "id"); - } - - @Test - public void testUpdateProductUnit_success() { - // mock 数据 - ErpProductUnitDO dbProductUnit = randomPojo(ErpProductUnitDO.class); - productUnitMapper.insert(dbProductUnit);// @Sql: 先插入出一条存在的数据 - // 准备参数 - ErpProductUnitSaveReqVO updateReqVO = randomPojo(ErpProductUnitSaveReqVO.class, o -> { - o.setId(dbProductUnit.getId()); // 设置更新的 ID - }); - - // 调用 - productUnitService.updateProductUnit(updateReqVO); - // 校验是否更新正确 - ErpProductUnitDO productUnit = productUnitMapper.selectById(updateReqVO.getId()); // 获取最新的 - assertPojoEquals(updateReqVO, productUnit); - } - - @Test - public void testUpdateProductUnit_notExists() { - // 准备参数 - ErpProductUnitSaveReqVO updateReqVO = randomPojo(ErpProductUnitSaveReqVO.class); - - // 调用, 并断言异常 - assertServiceException(() -> productUnitService.updateProductUnit(updateReqVO), PRODUCT_UNIT_NOT_EXISTS); - } - - @Test - public void testDeleteProductUnit_success() { - // mock 数据 - ErpProductUnitDO dbProductUnit = randomPojo(ErpProductUnitDO.class); - productUnitMapper.insert(dbProductUnit);// @Sql: 先插入出一条存在的数据 - // 准备参数 - Long id = dbProductUnit.getId(); - - // 调用 - productUnitService.deleteProductUnit(id); - // 校验数据不存在了 - assertNull(productUnitMapper.selectById(id)); - } - - @Test - public void testDeleteProductUnit_notExists() { - // 准备参数 - Long id = randomLongId(); - - // 调用, 并断言异常 - assertServiceException(() -> productUnitService.deleteProductUnit(id), PRODUCT_UNIT_NOT_EXISTS); - } - - @Test - @Disabled // TODO 请修改 null 为需要的值,然后删除 @Disabled 注解 - public void testGetProductUnitPage() { - // mock 数据 - ErpProductUnitDO dbProductUnit = randomPojo(ErpProductUnitDO.class, o -> { // 等会查询到 - o.setName(null); - o.setStatus(null); - o.setCreateTime(null); - }); - productUnitMapper.insert(dbProductUnit); - // 测试 name 不匹配 - productUnitMapper.insert(cloneIgnoreId(dbProductUnit, o -> o.setName(null))); - // 测试 status 不匹配 - productUnitMapper.insert(cloneIgnoreId(dbProductUnit, o -> o.setStatus(null))); - // 测试 createTime 不匹配 - productUnitMapper.insert(cloneIgnoreId(dbProductUnit, o -> o.setCreateTime(null))); - // 准备参数 - ErpProductUnitPageReqVO reqVO = new ErpProductUnitPageReqVO(); - reqVO.setName(null); - reqVO.setStatus(null); - reqVO.setCreateTime(buildBetweenTime(2023, 2, 1, 2023, 2, 28)); - - // 调用 - PageResult pageResult = productUnitService.getProductUnitPage(reqVO); - // 断言 - assertEquals(1, pageResult.getTotal()); - assertEquals(1, pageResult.getList().size()); - assertPojoEquals(dbProductUnit, pageResult.getList().get(0)); - } - -} \ No newline at end of file diff --git a/yudao-module-erp/yudao-module-erp-biz/src/test/java/cn/iocoder/yudao/module/erp/service/product/ProductServiceImplTest.java b/yudao-module-erp/yudao-module-erp-biz/src/test/java/cn/iocoder/yudao/module/erp/service/product/ProductServiceImplTest.java deleted file mode 100644 index 5045dbfb0..000000000 --- a/yudao-module-erp/yudao-module-erp-biz/src/test/java/cn/iocoder/yudao/module/erp/service/product/ProductServiceImplTest.java +++ /dev/null @@ -1,131 +0,0 @@ -package cn.iocoder.yudao.module.erp.service.product; - -import cn.iocoder.yudao.module.erp.controller.admin.product.vo.product.ErpProductPageReqVO; -import cn.iocoder.yudao.module.erp.controller.admin.product.vo.product.ProductSaveReqVO; -import org.junit.jupiter.api.Disabled; -import org.junit.jupiter.api.Test; - -import jakarta.annotation.Resource; - -import cn.iocoder.yudao.framework.test.core.ut.BaseDbUnitTest; - -import cn.iocoder.yudao.module.erp.dal.dataobject.product.ErpProductDO; -import cn.iocoder.yudao.module.erp.dal.mysql.product.ErpProductMapper; -import cn.iocoder.yudao.framework.common.pojo.PageResult; - -import org.springframework.context.annotation.Import; - -import static cn.iocoder.yudao.framework.test.core.util.AssertUtils.*; -import static cn.iocoder.yudao.framework.test.core.util.RandomUtils.*; -import static cn.iocoder.yudao.framework.common.util.date.LocalDateTimeUtils.*; -import static cn.iocoder.yudao.framework.common.util.object.ObjectUtils.*; -import static org.junit.jupiter.api.Assertions.*; - -/** - * {@link ErpProductServiceImpl} 的单元测试类 - * - * @author 芋道源码 - */ -@Import(ErpProductServiceImpl.class) -public class ProductServiceImplTest extends BaseDbUnitTest { - - @Resource - private ErpProductServiceImpl productService; - - @Resource - private ErpProductMapper productMapper; - - @Test - public void testCreateProduct_success() { - // 准备参数 - ProductSaveReqVO createReqVO = randomPojo(ProductSaveReqVO.class).setId(null); - - // 调用 - Long productId = productService.createProduct(createReqVO); - // 断言 - assertNotNull(productId); - // 校验记录的属性是否正确 - ErpProductDO product = productMapper.selectById(productId); - assertPojoEquals(createReqVO, product, "id"); - } - - @Test - public void testUpdateProduct_success() { - // mock 数据 - ErpProductDO dbProduct = randomPojo(ErpProductDO.class); - productMapper.insert(dbProduct);// @Sql: 先插入出一条存在的数据 - // 准备参数 - ProductSaveReqVO updateReqVO = randomPojo(ProductSaveReqVO.class, o -> { - o.setId(dbProduct.getId()); // 设置更新的 ID - }); - - // 调用 - productService.updateProduct(updateReqVO); - // 校验是否更新正确 - ErpProductDO product = productMapper.selectById(updateReqVO.getId()); // 获取最新的 - assertPojoEquals(updateReqVO, product); - } - - @Test - public void testUpdateProduct_notExists() { - // 准备参数 - ProductSaveReqVO updateReqVO = randomPojo(ProductSaveReqVO.class); - - // 调用, 并断言异常 - assertServiceException(() -> productService.updateProduct(updateReqVO), PRODUCT_NOT_EXISTS); - } - - @Test - public void testDeleteProduct_success() { - // mock 数据 - ErpProductDO dbProduct = randomPojo(ErpProductDO.class); - productMapper.insert(dbProduct);// @Sql: 先插入出一条存在的数据 - // 准备参数 - Long id = dbProduct.getId(); - - // 调用 - productService.deleteProduct(id); - // 校验数据不存在了 - assertNull(productMapper.selectById(id)); - } - - @Test - public void testDeleteProduct_notExists() { - // 准备参数 - Long id = randomLongId(); - - // 调用, 并断言异常 - assertServiceException(() -> productService.deleteProduct(id), PRODUCT_NOT_EXISTS); - } - - @Test - @Disabled // TODO 请修改 null 为需要的值,然后删除 @Disabled 注解 - public void testGetProductPage() { - // mock 数据 - ErpProductDO dbProduct = randomPojo(ErpProductDO.class, o -> { // 等会查询到 - o.setName(null); - o.setCategoryId(null); - o.setCreateTime(null); - }); - productMapper.insert(dbProduct); - // 测试 name 不匹配 - productMapper.insert(cloneIgnoreId(dbProduct, o -> o.setName(null))); - // 测试 categoryId 不匹配 - productMapper.insert(cloneIgnoreId(dbProduct, o -> o.setCategoryId(null))); - // 测试 createTime 不匹配 - productMapper.insert(cloneIgnoreId(dbProduct, o -> o.setCreateTime(null))); - // 准备参数 - ErpProductPageReqVO reqVO = new ErpProductPageReqVO(); - reqVO.setName(null); - reqVO.setCategoryId(null); - reqVO.setCreateTime(buildBetweenTime(2023, 2, 1, 2023, 2, 28)); - - // 调用 - PageResult pageResult = productService.getProductVOPage(reqVO); - // 断言 - assertEquals(1, pageResult.getTotal()); - assertEquals(1, pageResult.getList().size()); - assertPojoEquals(dbProduct, pageResult.getList().get(0)); - } - -} \ No newline at end of file diff --git a/yudao-module-erp/yudao-module-erp-biz/src/test/java/cn/iocoder/yudao/module/erp/service/sale/ErpCustomerServiceImplTest.java b/yudao-module-erp/yudao-module-erp-biz/src/test/java/cn/iocoder/yudao/module/erp/service/sale/ErpCustomerServiceImplTest.java deleted file mode 100644 index caee693cc..000000000 --- a/yudao-module-erp/yudao-module-erp-biz/src/test/java/cn/iocoder/yudao/module/erp/service/sale/ErpCustomerServiceImplTest.java +++ /dev/null @@ -1,131 +0,0 @@ -package cn.iocoder.yudao.module.erp.service.sale; - -import cn.iocoder.yudao.module.erp.controller.admin.sale.vo.customer.ErpCustomerPageReqVO; -import cn.iocoder.yudao.module.erp.controller.admin.sale.vo.customer.ErpCustomerSaveReqVO; -import org.junit.jupiter.api.Disabled; -import org.junit.jupiter.api.Test; - -import jakarta.annotation.Resource; - -import cn.iocoder.yudao.framework.test.core.ut.BaseDbUnitTest; - -import cn.iocoder.yudao.module.erp.dal.dataobject.sale.ErpCustomerDO; -import cn.iocoder.yudao.module.erp.dal.mysql.sale.ErpCustomerMapper; -import cn.iocoder.yudao.framework.common.pojo.PageResult; - -import org.springframework.context.annotation.Import; - -import static cn.iocoder.yudao.module.erp.enums.ErrorCodeConstants.*; -import static cn.iocoder.yudao.framework.test.core.util.AssertUtils.*; -import static cn.iocoder.yudao.framework.test.core.util.RandomUtils.*; -import static cn.iocoder.yudao.framework.common.util.object.ObjectUtils.*; -import static org.junit.jupiter.api.Assertions.*; - -/** - * {@link ErpCustomerServiceImpl} 的单元测试类 - * - * @author 芋道源码 - */ -@Import(ErpCustomerServiceImpl.class) -public class ErpCustomerServiceImplTest extends BaseDbUnitTest { - - @Resource - private ErpCustomerServiceImpl customerService; - - @Resource - private ErpCustomerMapper customerMapper; - - @Test - public void testCreateCustomer_success() { - // 准备参数 - ErpCustomerSaveReqVO createReqVO = randomPojo(ErpCustomerSaveReqVO.class).setId(null); - - // 调用 - Long customerId = customerService.createCustomer(createReqVO); - // 断言 - assertNotNull(customerId); - // 校验记录的属性是否正确 - ErpCustomerDO customer = customerMapper.selectById(customerId); - assertPojoEquals(createReqVO, customer, "id"); - } - - @Test - public void testUpdateCustomer_success() { - // mock 数据 - ErpCustomerDO dbCustomer = randomPojo(ErpCustomerDO.class); - customerMapper.insert(dbCustomer);// @Sql: 先插入出一条存在的数据 - // 准备参数 - ErpCustomerSaveReqVO updateReqVO = randomPojo(ErpCustomerSaveReqVO.class, o -> { - o.setId(dbCustomer.getId()); // 设置更新的 ID - }); - - // 调用 - customerService.updateCustomer(updateReqVO); - // 校验是否更新正确 - ErpCustomerDO customer = customerMapper.selectById(updateReqVO.getId()); // 获取最新的 - assertPojoEquals(updateReqVO, customer); - } - - @Test - public void testUpdateCustomer_notExists() { - // 准备参数 - ErpCustomerSaveReqVO updateReqVO = randomPojo(ErpCustomerSaveReqVO.class); - - // 调用, 并断言异常 - assertServiceException(() -> customerService.updateCustomer(updateReqVO), CUSTOMER_NOT_EXISTS); - } - - @Test - public void testDeleteCustomer_success() { - // mock 数据 - ErpCustomerDO dbCustomer = randomPojo(ErpCustomerDO.class); - customerMapper.insert(dbCustomer);// @Sql: 先插入出一条存在的数据 - // 准备参数 - Long id = dbCustomer.getId(); - - // 调用 - customerService.deleteCustomer(id); - // 校验数据不存在了 - assertNull(customerMapper.selectById(id)); - } - - @Test - public void testDeleteCustomer_notExists() { - // 准备参数 - Long id = randomLongId(); - - // 调用, 并断言异常 - assertServiceException(() -> customerService.deleteCustomer(id), CUSTOMER_NOT_EXISTS); - } - - @Test - @Disabled // TODO 请修改 null 为需要的值,然后删除 @Disabled 注解 - public void testGetCustomerPage() { - // mock 数据 - ErpCustomerDO dbCustomer = randomPojo(ErpCustomerDO.class, o -> { // 等会查询到 - o.setName(null); - o.setMobile(null); - o.setTelephone(null); - }); - customerMapper.insert(dbCustomer); - // 测试 name 不匹配 - customerMapper.insert(cloneIgnoreId(dbCustomer, o -> o.setName(null))); - // 测试 mobile 不匹配 - customerMapper.insert(cloneIgnoreId(dbCustomer, o -> o.setMobile(null))); - // 测试 telephone 不匹配 - customerMapper.insert(cloneIgnoreId(dbCustomer, o -> o.setTelephone(null))); - // 准备参数 - ErpCustomerPageReqVO reqVO = new ErpCustomerPageReqVO(); - reqVO.setName(null); - reqVO.setMobile(null); - reqVO.setTelephone(null); - - // 调用 - PageResult pageResult = customerService.getCustomerPage(reqVO); - // 断言 - assertEquals(1, pageResult.getTotal()); - assertEquals(1, pageResult.getList().size()); - assertPojoEquals(dbCustomer, pageResult.getList().get(0)); - } - -} \ No newline at end of file diff --git a/yudao-module-erp/yudao-module-erp-biz/src/test/java/cn/iocoder/yudao/module/erp/service/stock/ErpWarehouseServiceImplTest.java b/yudao-module-erp/yudao-module-erp-biz/src/test/java/cn/iocoder/yudao/module/erp/service/stock/ErpWarehouseServiceImplTest.java deleted file mode 100644 index fa74620e2..000000000 --- a/yudao-module-erp/yudao-module-erp-biz/src/test/java/cn/iocoder/yudao/module/erp/service/stock/ErpWarehouseServiceImplTest.java +++ /dev/null @@ -1,126 +0,0 @@ -package cn.iocoder.yudao.module.erp.service.stock; - -import cn.iocoder.yudao.module.erp.controller.admin.stock.vo.warehouse.ErpWarehousePageReqVO; -import cn.iocoder.yudao.module.erp.controller.admin.stock.vo.warehouse.ErpWarehouseSaveReqVO; -import org.junit.jupiter.api.Disabled; -import org.junit.jupiter.api.Test; - -import jakarta.annotation.Resource; - -import cn.iocoder.yudao.framework.test.core.ut.BaseDbUnitTest; - -import cn.iocoder.yudao.module.erp.dal.dataobject.stock.ErpWarehouseDO; -import cn.iocoder.yudao.module.erp.dal.mysql.stock.ErpWarehouseMapper; -import cn.iocoder.yudao.framework.common.pojo.PageResult; - -import org.springframework.context.annotation.Import; - -import static cn.iocoder.yudao.framework.test.core.util.AssertUtils.*; -import static cn.iocoder.yudao.framework.test.core.util.RandomUtils.*; -import static cn.iocoder.yudao.framework.common.util.object.ObjectUtils.*; -import static org.junit.jupiter.api.Assertions.*; - -/** - * {@link ErpWarehouseServiceImpl} 的单元测试类 - * - * @author 芋道源码 - */ -@Import(ErpWarehouseServiceImpl.class) -public class ErpWarehouseServiceImplTest extends BaseDbUnitTest { - - @Resource - private ErpWarehouseServiceImpl warehouseService; - - @Resource - private ErpWarehouseMapper warehouseMapper; - - @Test - public void testCreateWarehouse_success() { - // 准备参数 - ErpWarehouseSaveReqVO createReqVO = randomPojo(ErpWarehouseSaveReqVO.class).setId(null); - - // 调用 - Long warehouseId = warehouseService.createWarehouse(createReqVO); - // 断言 - assertNotNull(warehouseId); - // 校验记录的属性是否正确 - ErpWarehouseDO warehouse = warehouseMapper.selectById(warehouseId); - assertPojoEquals(createReqVO, warehouse, "id"); - } - - @Test - public void testUpdateWarehouse_success() { - // mock 数据 - ErpWarehouseDO dbWarehouse = randomPojo(ErpWarehouseDO.class); - warehouseMapper.insert(dbWarehouse);// @Sql: 先插入出一条存在的数据 - // 准备参数 - ErpWarehouseSaveReqVO updateReqVO = randomPojo(ErpWarehouseSaveReqVO.class, o -> { - o.setId(dbWarehouse.getId()); // 设置更新的 ID - }); - - // 调用 - warehouseService.updateWarehouse(updateReqVO); - // 校验是否更新正确 - ErpWarehouseDO warehouse = warehouseMapper.selectById(updateReqVO.getId()); // 获取最新的 - assertPojoEquals(updateReqVO, warehouse); - } - - @Test - public void testUpdateWarehouse_notExists() { - // 准备参数 - ErpWarehouseSaveReqVO updateReqVO = randomPojo(ErpWarehouseSaveReqVO.class); - - // 调用, 并断言异常 - assertServiceException(() -> warehouseService.updateWarehouse(updateReqVO), WAREHOUSE_NOT_EXISTS); - } - - @Test - public void testDeleteWarehouse_success() { - // mock 数据 - ErpWarehouseDO dbWarehouse = randomPojo(ErpWarehouseDO.class); - warehouseMapper.insert(dbWarehouse);// @Sql: 先插入出一条存在的数据 - // 准备参数 - Long id = dbWarehouse.getId(); - - // 调用 - warehouseService.deleteWarehouse(id); - // 校验数据不存在了 - assertNull(warehouseMapper.selectById(id)); - } - - @Test - public void testDeleteWarehouse_notExists() { - // 准备参数 - Long id = randomLongId(); - - // 调用, 并断言异常 - assertServiceException(() -> warehouseService.deleteWarehouse(id), WAREHOUSE_NOT_EXISTS); - } - - @Test - @Disabled // TODO 请修改 null 为需要的值,然后删除 @Disabled 注解 - public void testGetWarehousePage() { - // mock 数据 - ErpWarehouseDO dbWarehouse = randomPojo(ErpWarehouseDO.class, o -> { // 等会查询到 - o.setName(null); - o.setStatus(null); - }); - warehouseMapper.insert(dbWarehouse); - // 测试 name 不匹配 - warehouseMapper.insert(cloneIgnoreId(dbWarehouse, o -> o.setName(null))); - // 测试 status 不匹配 - warehouseMapper.insert(cloneIgnoreId(dbWarehouse, o -> o.setStatus(null))); - // 准备参数 - ErpWarehousePageReqVO reqVO = new ErpWarehousePageReqVO(); - reqVO.setName(null); - reqVO.setStatus(null); - - // 调用 - PageResult pageResult = warehouseService.getWarehousePage(reqVO); - // 断言 - assertEquals(1, pageResult.getTotal()); - assertEquals(1, pageResult.getList().size()); - assertPojoEquals(dbWarehouse, pageResult.getList().get(0)); - } - -} \ No newline at end of file From 9e3858aea70c16aa596f1b0c055c30e1359038cf Mon Sep 17 00:00:00 2001 From: YunaiV Date: Wed, 14 Feb 2024 17:13:48 +0800 Subject: [PATCH 108/119] =?UTF-8?q?=E2=9C=A8=20ERP=EF=BC=9A=E5=AE=8C?= =?UTF-8?q?=E6=88=90=20payment=20=E4=BB=98=E6=AC=BE=E5=8D=95=E7=9A=84?= =?UTF-8?q?=E9=80=BB=E8=BE=91=20100%?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../util/collection/CollectionUtils.java | 4 ++ .../module/erp/enums/ErrorCodeConstants.java | 5 ++ .../finance/ErpFinancePaymentController.java | 10 +++- .../vo/payment/ErpFinancePaymentRespVO.java | 2 + .../payment/ErpFinancePaymentSaveReqVO.java | 4 -- .../finance/ErpFinancePaymentItemMapper.java | 18 ++++++- .../mysql/purchase/ErpPurchaseInMapper.java | 4 +- .../purchase/ErpPurchaseReturnMapper.java | 5 +- .../service/finance/ErpAccountService.java | 22 ++++++++ .../finance/ErpAccountServiceImpl.java | 6 +++ .../finance/ErpFinancePaymentServiceImpl.java | 52 +++++++++++++++---- .../purchase/ErpPurchaseInService.java | 9 ++++ .../purchase/ErpPurchaseInServiceImpl.java | 17 +++++- .../purchase/ErpPurchaseReturnService.java | 9 ++++ .../ErpPurchaseReturnServiceImpl.java | 17 +++++- 15 files changed, 163 insertions(+), 21 deletions(-) diff --git a/yudao-framework/yudao-common/src/main/java/cn/iocoder/yudao/framework/common/util/collection/CollectionUtils.java b/yudao-framework/yudao-common/src/main/java/cn/iocoder/yudao/framework/common/util/collection/CollectionUtils.java index 4fd6203f8..8ffd21ccc 100644 --- a/yudao-framework/yudao-common/src/main/java/cn/iocoder/yudao/framework/common/util/collection/CollectionUtils.java +++ b/yudao-framework/yudao-common/src/main/java/cn/iocoder/yudao/framework/common/util/collection/CollectionUtils.java @@ -311,4 +311,8 @@ public class CollectionUtils { return obj == null ? Collections.emptyList() : Collections.singleton(obj); } + public static List newArrayList(List> list) { + return list.stream().flatMap(Collection::stream).collect(Collectors.toList()); + } + } diff --git a/yudao-module-erp/yudao-module-erp-api/src/main/java/cn/iocoder/yudao/module/erp/enums/ErrorCodeConstants.java b/yudao-module-erp/yudao-module-erp-api/src/main/java/cn/iocoder/yudao/module/erp/enums/ErrorCodeConstants.java index 3fafa752b..580539f97 100644 --- a/yudao-module-erp/yudao-module-erp-api/src/main/java/cn/iocoder/yudao/module/erp/enums/ErrorCodeConstants.java +++ b/yudao-module-erp/yudao-module-erp-api/src/main/java/cn/iocoder/yudao/module/erp/enums/ErrorCodeConstants.java @@ -34,6 +34,8 @@ ErrorCode PURCHASE_ORDER_ITEM_RETURN_FAIL_IN_EXCEED = new ErrorCode(1_030_101_00 ErrorCode PURCHASE_IN_NO_EXISTS = new ErrorCode(1_030_102_004, "生成入库单失败,请重新提交"); ErrorCode PURCHASE_IN_UPDATE_FAIL_APPROVE = new ErrorCode(1_030_102_005, "采购入库单({})已审核,无法修改"); ErrorCode PURCHASE_IN_NOT_APPROVE = new ErrorCode(1_030_102_006, "采购入库单未审核,无法操作"); + ErrorCode PURCHASE_IN_FAIL_PAYMENT_PRICE_EXCEED = new ErrorCode(1_030_102_007, "付款金额({})超过采购入库单总金额({})"); + ErrorCode PURCHASE_IN_PROCESS_FAIL_EXISTS_PAYMENT = new ErrorCode(1_030_102_008, "反审核失败,已存在对应的付款单"); // ========== ERP 采购退货(1-030-103-000) ========== ErrorCode PURCHASE_RETURN_NOT_EXISTS = new ErrorCode(1_030_103_000, "采购退货单不存在"); @@ -43,6 +45,8 @@ ErrorCode PURCHASE_ORDER_ITEM_RETURN_FAIL_IN_EXCEED = new ErrorCode(1_030_101_00 ErrorCode PURCHASE_RETURN_NO_EXISTS = new ErrorCode(1_030_103_004, "生成退货单失败,请重新提交"); ErrorCode PURCHASE_RETURN_UPDATE_FAIL_APPROVE = new ErrorCode(1_030_103_005, "采购退货单({})已审核,无法修改"); ErrorCode PURCHASE_RETURN_NOT_APPROVE = new ErrorCode(1_030_103_006, "采购退货单未审核,无法操作"); + ErrorCode PURCHASE_RETURN_FAIL_REFUND_PRICE_EXCEED = new ErrorCode(1_030_103_007, "退款金额({})超过采购退货单总金额({})"); + ErrorCode PURCHASE_RETURN_PROCESS_FAIL_EXISTS_REFUND = new ErrorCode(1_030_103_008, "反审核失败,已存在对应的退款单"); // ========== ERP 客户(1-030-200-000)========== ErrorCode CUSTOMER_NOT_EXISTS = new ErrorCode(1_020_200_000, "客户不存在"); @@ -145,5 +149,6 @@ ErrorCode PURCHASE_ORDER_ITEM_RETURN_FAIL_IN_EXCEED = new ErrorCode(1_030_101_00 ErrorCode FINANCE_PAYMENT_PROCESS_FAIL = new ErrorCode(1_030_601_002, "反审核失败,只有已审核的付款单才能反审核"); ErrorCode FINANCE_PAYMENT_APPROVE_FAIL = new ErrorCode(1_030_601_003, "审核失败,只有未审核的付款单才能审核"); ErrorCode FINANCE_PAYMENT_NO_EXISTS = new ErrorCode(1_030_601_004, "生成付款单号失败,请重新提交"); + ErrorCode FINANCE_PAYMENT_UPDATE_FAIL_APPROVE = new ErrorCode(1_030_601_005, "付款单({})已审核,无法修改"); } diff --git a/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/controller/admin/finance/ErpFinancePaymentController.java b/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/controller/admin/finance/ErpFinancePaymentController.java index a4d16898b..b1f028a28 100644 --- a/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/controller/admin/finance/ErpFinancePaymentController.java +++ b/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/controller/admin/finance/ErpFinancePaymentController.java @@ -12,9 +12,11 @@ import cn.iocoder.yudao.framework.operatelog.core.annotations.OperateLog; import cn.iocoder.yudao.module.erp.controller.admin.finance.vo.payment.ErpFinancePaymentPageReqVO; import cn.iocoder.yudao.module.erp.controller.admin.finance.vo.payment.ErpFinancePaymentRespVO; import cn.iocoder.yudao.module.erp.controller.admin.finance.vo.payment.ErpFinancePaymentSaveReqVO; +import cn.iocoder.yudao.module.erp.dal.dataobject.finance.ErpAccountDO; import cn.iocoder.yudao.module.erp.dal.dataobject.finance.ErpFinancePaymentDO; import cn.iocoder.yudao.module.erp.dal.dataobject.finance.ErpFinancePaymentItemDO; import cn.iocoder.yudao.module.erp.dal.dataobject.purchase.ErpSupplierDO; +import cn.iocoder.yudao.module.erp.service.finance.ErpAccountService; import cn.iocoder.yudao.module.erp.service.finance.ErpFinancePaymentService; import cn.iocoder.yudao.module.erp.service.purchase.ErpSupplierService; import cn.iocoder.yudao.module.system.api.user.AdminUserApi; @@ -48,6 +50,8 @@ public class ErpFinancePaymentController { private ErpFinancePaymentService financePaymentService; @Resource private ErpSupplierService supplierService; + @Resource + private ErpAccountService accountService; @Resource private AdminUserApi adminUserApi; @@ -130,13 +134,17 @@ public class ErpFinancePaymentController { // 1.2 供应商信息 Map supplierMap = supplierService.getSupplierMap( convertSet(pageResult.getList(), ErpFinancePaymentDO::getSupplierId)); - // 1.3 管理员信息 + // 1.3 结算账户信息 + Map accountMap = accountService.getAccountMap( + convertSet(pageResult.getList(), ErpFinancePaymentDO::getAccountId)); + // 1.4 管理员信息 Map userMap = adminUserApi.getUserMap(convertListByFlatMap(pageResult.getList(), contact -> Stream.of(NumberUtils.parseLong(contact.getCreator()), contact.getFinanceUserId()))); // 2. 开始拼接 return BeanUtils.toBean(pageResult, ErpFinancePaymentRespVO.class, payment -> { payment.setItems(BeanUtils.toBean(financePaymentItemMap.get(payment.getId()), ErpFinancePaymentRespVO.Item.class)); MapUtils.findAndThen(supplierMap, payment.getSupplierId(), supplier -> payment.setSupplierName(supplier.getName())); + MapUtils.findAndThen(accountMap, payment.getAccountId(), account -> payment.setAccountName(account.getName())); MapUtils.findAndThen(userMap, Long.parseLong(payment.getCreator()), user -> payment.setCreatorName(user.getNickname())); MapUtils.findAndThen(userMap, payment.getFinanceUserId(), user -> payment.setFinanceUserName(user.getNickname())); }); diff --git a/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/controller/admin/finance/vo/payment/ErpFinancePaymentRespVO.java b/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/controller/admin/finance/vo/payment/ErpFinancePaymentRespVO.java index 323d86db5..4dbb4566b 100644 --- a/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/controller/admin/finance/vo/payment/ErpFinancePaymentRespVO.java +++ b/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/controller/admin/finance/vo/payment/ErpFinancePaymentRespVO.java @@ -37,6 +37,8 @@ public class ErpFinancePaymentRespVO { @Schema(description = "付款账户编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "28989") private Long accountId; + @Schema(description = "付款账户名称", requiredMode = Schema.RequiredMode.REQUIRED, example = "张三") + private String accountName; @Schema(description = "合计价格,单位:元", requiredMode = Schema.RequiredMode.REQUIRED, example = "13832") private BigDecimal totalPrice; diff --git a/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/controller/admin/finance/vo/payment/ErpFinancePaymentSaveReqVO.java b/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/controller/admin/finance/vo/payment/ErpFinancePaymentSaveReqVO.java index ab74c83b1..d7e3ddb27 100644 --- a/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/controller/admin/finance/vo/payment/ErpFinancePaymentSaveReqVO.java +++ b/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/controller/admin/finance/vo/payment/ErpFinancePaymentSaveReqVO.java @@ -17,10 +17,6 @@ public class ErpFinancePaymentSaveReqVO { @Schema(description = "编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "23752") private Long id; - @Schema(description = "付款单号", requiredMode = Schema.RequiredMode.REQUIRED, example = "FKD888") - @NotEmpty(message = "付款单号不能为空") - private String no; - @Schema(description = "付款时间", requiredMode = Schema.RequiredMode.REQUIRED) @NotNull(message = "付款时间不能为空") private LocalDateTime paymentTime; diff --git a/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/dal/mysql/finance/ErpFinancePaymentItemMapper.java b/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/dal/mysql/finance/ErpFinancePaymentItemMapper.java index 646d07976..7787e8d70 100644 --- a/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/dal/mysql/finance/ErpFinancePaymentItemMapper.java +++ b/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/dal/mysql/finance/ErpFinancePaymentItemMapper.java @@ -1,11 +1,16 @@ package cn.iocoder.yudao.module.erp.dal.mysql.finance; +import cn.hutool.core.collection.CollUtil; +import cn.hutool.core.map.MapUtil; import cn.iocoder.yudao.framework.mybatis.core.mapper.BaseMapperX; import cn.iocoder.yudao.module.erp.dal.dataobject.finance.ErpFinancePaymentItemDO; +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.List; +import java.util.Map; /** * ERP 付款单项 Mapper @@ -23,8 +28,17 @@ public interface ErpFinancePaymentItemMapper extends BaseMapperX> result = selectMaps(new QueryWrapper() + .select("SUM(payment_price) AS paymentPriceSum") + .eq("biz_id", bizId) + .eq("biz_type", bizType)); + // 获得数量 + if (CollUtil.isEmpty(result)) { + return BigDecimal.ZERO; + } + return BigDecimal.valueOf(MapUtil.getDouble(result.get(0), "paymentPriceSum", 0D)); } } \ No newline at end of file diff --git a/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/dal/mysql/purchase/ErpPurchaseInMapper.java b/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/dal/mysql/purchase/ErpPurchaseInMapper.java index cd227c351..c155d8cbe 100644 --- a/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/dal/mysql/purchase/ErpPurchaseInMapper.java +++ b/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/dal/mysql/purchase/ErpPurchaseInMapper.java @@ -7,6 +7,7 @@ import cn.iocoder.yudao.framework.mybatis.core.query.MPJLambdaWrapperX; import cn.iocoder.yudao.module.erp.controller.admin.purchase.vo.in.ErpPurchaseInPageReqVO; import cn.iocoder.yudao.module.erp.dal.dataobject.purchase.ErpPurchaseInDO; import cn.iocoder.yudao.module.erp.dal.dataobject.purchase.ErpPurchaseInItemDO; +import cn.iocoder.yudao.module.erp.enums.ErpAuditStatus; import com.baomidou.mybatisplus.core.conditions.update.LambdaUpdateWrapper; import org.apache.ibatis.annotations.Mapper; @@ -41,7 +42,8 @@ public interface ErpPurchaseInMapper extends BaseMapperX { query.apply("t.payment_price = t.total_price"); } if (Boolean.TRUE.equals(reqVO.getPaymentEnable())) { - query.apply("t.payment_price < t.total_price"); + query.eq(ErpPurchaseInDO::getStatus, ErpAuditStatus.APPROVE.getStatus()) + .apply("t.payment_price < t.total_price"); } if (reqVO.getWarehouseId() != null || reqVO.getProductId() != null) { query.leftJoin(ErpPurchaseInItemDO.class, ErpPurchaseInItemDO::getInId, ErpPurchaseInDO::getId) diff --git a/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/dal/mysql/purchase/ErpPurchaseReturnMapper.java b/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/dal/mysql/purchase/ErpPurchaseReturnMapper.java index aa3c9ad5f..689a55dfd 100644 --- a/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/dal/mysql/purchase/ErpPurchaseReturnMapper.java +++ b/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/dal/mysql/purchase/ErpPurchaseReturnMapper.java @@ -4,8 +4,10 @@ import cn.iocoder.yudao.framework.common.pojo.PageResult; import cn.iocoder.yudao.framework.mybatis.core.mapper.BaseMapperX; import cn.iocoder.yudao.framework.mybatis.core.query.MPJLambdaWrapperX; import cn.iocoder.yudao.module.erp.controller.admin.purchase.vo.returns.ErpPurchaseReturnPageReqVO; +import cn.iocoder.yudao.module.erp.dal.dataobject.purchase.ErpPurchaseInDO; import cn.iocoder.yudao.module.erp.dal.dataobject.purchase.ErpPurchaseReturnDO; import cn.iocoder.yudao.module.erp.dal.dataobject.purchase.ErpPurchaseReturnItemDO; +import cn.iocoder.yudao.module.erp.enums.ErpAuditStatus; import com.baomidou.mybatisplus.core.conditions.update.LambdaUpdateWrapper; import org.apache.ibatis.annotations.Mapper; @@ -40,7 +42,8 @@ public interface ErpPurchaseReturnMapper extends BaseMapperX getAccountListByStatus(Integer status); + /** + * 获得结算账户列表 + * + * @param ids 编号数组 + * @return 结算账户列表 + */ + List getAccountList(Collection ids); + + /** + * 获得结算账户 Map + * + * @param ids 编号数组 + * @return 结算账户 Map + */ + default Map getAccountMap(Collection ids) { + return convertMap(getAccountList(ids), ErpAccountDO::getId); + } + /** * 获得结算账户分页 * diff --git a/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/service/finance/ErpAccountServiceImpl.java b/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/service/finance/ErpAccountServiceImpl.java index bc5dafa24..9a8e85828 100644 --- a/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/service/finance/ErpAccountServiceImpl.java +++ b/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/service/finance/ErpAccountServiceImpl.java @@ -11,6 +11,7 @@ import jakarta.annotation.Resource; import org.springframework.stereotype.Service; import org.springframework.validation.annotation.Validated; +import java.util.Collection; import java.util.List; import static cn.iocoder.yudao.framework.common.exception.util.ServiceExceptionUtil.exception; @@ -98,6 +99,11 @@ public class ErpAccountServiceImpl implements ErpAccountService { return accountMapper.selectListByStatus(status); } + @Override + public List getAccountList(Collection ids) { + return accountMapper.selectBatchIds(ids); + } + @Override public PageResult getAccountPage(ErpAccountPageReqVO pageReqVO) { return accountMapper.selectPage(pageReqVO); diff --git a/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/service/finance/ErpFinancePaymentServiceImpl.java b/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/service/finance/ErpFinancePaymentServiceImpl.java index a20a35742..68121763c 100644 --- a/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/service/finance/ErpFinancePaymentServiceImpl.java +++ b/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/service/finance/ErpFinancePaymentServiceImpl.java @@ -1,8 +1,10 @@ package cn.iocoder.yudao.module.erp.service.finance; import cn.hutool.core.collection.CollUtil; +import cn.hutool.core.lang.Assert; import cn.hutool.core.util.ObjectUtil; import cn.iocoder.yudao.framework.common.pojo.PageResult; +import cn.iocoder.yudao.framework.common.util.collection.CollectionUtils; import cn.iocoder.yudao.framework.common.util.object.BeanUtils; import cn.iocoder.yudao.module.erp.controller.admin.finance.vo.payment.ErpFinancePaymentPageReqVO; import cn.iocoder.yudao.module.erp.controller.admin.finance.vo.payment.ErpFinancePaymentSaveReqVO; @@ -68,7 +70,8 @@ public class ErpFinancePaymentServiceImpl implements ErpFinancePaymentService { @Transactional(rollbackFor = Exception.class) public Long createFinancePayment(ErpFinancePaymentSaveReqVO createReqVO) { // 1.1 校验订单项的有效性 - List paymentItems = validateFinancePaymentItems(createReqVO.getItems()); + List paymentItems = validateFinancePaymentItems( + createReqVO.getSupplierId(), createReqVO.getItems()); // 1.2 校验供应商 supplierService.validateSupplier(createReqVO.getSupplierId()); // 1.3 校验结算账户 @@ -102,7 +105,7 @@ public class ErpFinancePaymentServiceImpl implements ErpFinancePaymentService { // 1.1 校验存在 ErpFinancePaymentDO payment = validateFinancePaymentExists(updateReqVO.getId()); if (ErpAuditStatus.APPROVE.getStatus().equals(payment.getStatus())) { - throw exception(SALE_ORDER_UPDATE_FAIL_APPROVE, payment.getNo()); + throw exception(FINANCE_PAYMENT_UPDATE_FAIL_APPROVE, payment.getNo()); } // 1.2 校验供应商 supplierService.validateSupplier(updateReqVO.getSupplierId()); @@ -115,7 +118,8 @@ public class ErpFinancePaymentServiceImpl implements ErpFinancePaymentService { adminUserApi.validateUser(updateReqVO.getFinanceUserId()); } // 1.5 校验付款单项的有效性 - List paymentItems = validateFinancePaymentItems(updateReqVO.getItems()); + List paymentItems = validateFinancePaymentItems( + updateReqVO.getSupplierId(), updateReqVO.getItems()); // 2.1 更新付款单 ErpFinancePaymentDO updateObj = BeanUtils.toBean(updateReqVO, ErpFinancePaymentDO.class); @@ -123,6 +127,9 @@ public class ErpFinancePaymentServiceImpl implements ErpFinancePaymentService { financePaymentMapper.updateById(updateObj); // 2.2 更新付款单项 updateFinancePaymentItemList(updateReqVO.getId(), paymentItems); + + // 3. 更新采购入库、退货的付款金额情况 + updatePurchasePrice(paymentItems); } private void calculateTotalPrice(ErpFinancePaymentDO payment, List paymentItems) { @@ -138,25 +145,29 @@ public class ErpFinancePaymentServiceImpl implements ErpFinancePaymentService { ErpFinancePaymentDO payment = validateFinancePaymentExists(id); // 1.2 校验状态 if (payment.getStatus().equals(status)) { - throw exception(approve ? SALE_ORDER_APPROVE_FAIL : SALE_ORDER_PROCESS_FAIL); + throw exception(approve ? FINANCE_PAYMENT_APPROVE_FAIL : FINANCE_PAYMENT_PROCESS_FAIL); } // 2. 更新状态 int updateCount = financePaymentMapper.updateByIdAndStatus(id, payment.getStatus(), new ErpFinancePaymentDO().setStatus(status)); if (updateCount == 0) { - throw exception(approve ? SALE_ORDER_APPROVE_FAIL : SALE_ORDER_PROCESS_FAIL); + throw exception(approve ? FINANCE_PAYMENT_APPROVE_FAIL : FINANCE_PAYMENT_PROCESS_FAIL); } } - private List validateFinancePaymentItems(List list) { + private List validateFinancePaymentItems( + Long supplierId, + List list) { return convertList(list, o -> BeanUtils.toBean(o, ErpFinancePaymentItemDO.class, item -> { if (ObjectUtil.equal(item.getBizType(), ErpBizTypeEnum.PURCHASE_IN.getType())) { ErpPurchaseInDO purchaseIn = purchaseInService.validatePurchaseIn(item.getBizId()); + Assert.equals(purchaseIn.getSupplierId(), supplierId, "供应商必须相同"); item.setTotalPrice(purchaseIn.getTotalPrice()).setBizNo(purchaseIn.getNo()); } else if (ObjectUtil.equal(item.getBizType(), ErpBizTypeEnum.PURCHASE_RETURN.getType())) { ErpPurchaseReturnDO purchaseReturn = purchaseReturnService.validatePurchaseReturn(item.getBizId()); - item.setTotalPrice(purchaseReturn.getTotalPrice()).setBizNo(purchaseReturn.getNo()); + Assert.equals(purchaseReturn.getSupplierId(), supplierId, "供应商必须相同"); + item.setTotalPrice(purchaseReturn.getTotalPrice().negate()).setBizNo(purchaseReturn.getNo()); } else { throw new IllegalArgumentException("业务类型不正确:" + item.getBizType()); } @@ -180,6 +191,23 @@ public class ErpFinancePaymentServiceImpl implements ErpFinancePaymentService { if (CollUtil.isNotEmpty(diffList.get(2))) { financePaymentItemMapper.deleteBatchIds(convertList(diffList.get(2), ErpFinancePaymentItemDO::getId)); } + + // 第三步,更新采购入库、退货的付款金额情况 + updatePurchasePrice(CollectionUtils.newArrayList(diffList)); + } + + private void updatePurchasePrice(List paymentItems) { + paymentItems.forEach(paymentItem -> { + BigDecimal totalPaymentPrice = financePaymentItemMapper.selectPaymentPriceSumByBizIdAndBizType( + paymentItem.getBizId(), paymentItem.getBizType()); + if (ErpBizTypeEnum.PURCHASE_IN.getType().equals(paymentItem.getBizType())) { + purchaseInService.updatePurchaseInPaymentPrice(paymentItem.getBizId(), totalPaymentPrice); + } else if (ErpBizTypeEnum.PURCHASE_RETURN.getType().equals(paymentItem.getBizType())) { + purchaseReturnService.updatePurchaseReturnRefundPrice(paymentItem.getBizId(), totalPaymentPrice.negate()); + } else { + throw new IllegalArgumentException("业务类型不正确:" + paymentItem.getBizType()); + } + }); } @Override @@ -192,7 +220,7 @@ public class ErpFinancePaymentServiceImpl implements ErpFinancePaymentService { } payments.forEach(payment -> { if (ErpAuditStatus.APPROVE.getStatus().equals(payment.getStatus())) { - throw exception(SALE_ORDER_DELETE_FAIL_APPROVE, payment.getNo()); + throw exception(FINANCE_PAYMENT_DELETE_FAIL_APPROVE, payment.getNo()); } }); @@ -201,14 +229,18 @@ public class ErpFinancePaymentServiceImpl implements ErpFinancePaymentService { // 2.1 删除付款单 financePaymentMapper.deleteById(payment.getId()); // 2.2 删除付款单项 - financePaymentItemMapper.deleteByPaymentId(payment.getId()); + List paymentItems = financePaymentItemMapper.selectListByPaymentId(payment.getId()); + financePaymentItemMapper.deleteBatchIds(convertSet(paymentItems, ErpFinancePaymentItemDO::getId)); + + // 2.3 更新采购入库、退货的付款金额情况 + updatePurchasePrice(paymentItems); }); } private ErpFinancePaymentDO validateFinancePaymentExists(Long id) { ErpFinancePaymentDO payment = financePaymentMapper.selectById(id); if (payment == null) { - throw exception(SALE_ORDER_NOT_EXISTS); + throw exception(FINANCE_PAYMENT_NOT_EXISTS); } return payment; } diff --git a/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/service/purchase/ErpPurchaseInService.java b/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/service/purchase/ErpPurchaseInService.java index 2c892ccd0..37aa452cd 100644 --- a/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/service/purchase/ErpPurchaseInService.java +++ b/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/service/purchase/ErpPurchaseInService.java @@ -7,6 +7,7 @@ import cn.iocoder.yudao.module.erp.dal.dataobject.purchase.ErpPurchaseInDO; import cn.iocoder.yudao.module.erp.dal.dataobject.purchase.ErpPurchaseInItemDO; import jakarta.validation.Valid; +import java.math.BigDecimal; import java.util.Collection; import java.util.List; @@ -40,6 +41,14 @@ public interface ErpPurchaseInService { */ void updatePurchaseInStatus(Long id, Integer status); + /** + * 更新采购入库的付款金额 + * + * @param id 编号 + * @param paymentPrice 付款金额 + */ + void updatePurchaseInPaymentPrice(Long id, BigDecimal paymentPrice); + /** * 删除采购入库 * diff --git a/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/service/purchase/ErpPurchaseInServiceImpl.java b/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/service/purchase/ErpPurchaseInServiceImpl.java index 04d92a713..b2ac729ed 100644 --- a/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/service/purchase/ErpPurchaseInServiceImpl.java +++ b/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/service/purchase/ErpPurchaseInServiceImpl.java @@ -163,7 +163,10 @@ public class ErpPurchaseInServiceImpl implements ErpPurchaseInService { if (purchaseIn.getStatus().equals(status)) { throw exception(approve ? PURCHASE_IN_APPROVE_FAIL : PURCHASE_IN_PROCESS_FAIL); } - // TODO 芋艿:稍后加下校验 + // 1.3 校验已付款 + if (approve && purchaseIn.getPaymentPrice().compareTo(BigDecimal.ZERO) > 0) { + throw exception(PURCHASE_IN_PROCESS_FAIL_EXISTS_PAYMENT); + } // 2. 更新状态 int updateCount = purchaseInMapper.updateByIdAndStatus(id, purchaseIn.getStatus(), @@ -184,6 +187,18 @@ public class ErpPurchaseInServiceImpl implements ErpPurchaseInService { }); } + @Override + public void updatePurchaseInPaymentPrice(Long id, BigDecimal paymentPrice) { + ErpPurchaseInDO purchaseIn = purchaseInMapper.selectById(id); + if (purchaseIn.getPaymentPrice().equals(paymentPrice)) { + return; + } + if (paymentPrice.compareTo(purchaseIn.getTotalPrice()) > 0) { + throw exception(PURCHASE_IN_FAIL_PAYMENT_PRICE_EXCEED, purchaseIn.getTotalPrice(), paymentPrice); + } + purchaseInMapper.updateById(new ErpPurchaseInDO().setId(id).setPaymentPrice(paymentPrice)); + } + private List validatePurchaseInItems(List list) { // 1. 校验产品存在 List productList = productService.validProductList( diff --git a/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/service/purchase/ErpPurchaseReturnService.java b/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/service/purchase/ErpPurchaseReturnService.java index cd6f26e25..b6826fa88 100644 --- a/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/service/purchase/ErpPurchaseReturnService.java +++ b/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/service/purchase/ErpPurchaseReturnService.java @@ -7,6 +7,7 @@ import cn.iocoder.yudao.module.erp.dal.dataobject.purchase.ErpPurchaseReturnDO; import cn.iocoder.yudao.module.erp.dal.dataobject.purchase.ErpPurchaseReturnItemDO; import jakarta.validation.Valid; +import java.math.BigDecimal; import java.util.Collection; import java.util.List; @@ -40,6 +41,14 @@ public interface ErpPurchaseReturnService { */ void updatePurchaseReturnStatus(Long id, Integer status); + /** + * 更新采购退货的退款金额 + * + * @param id 编号 + * @param refundPrice 退款金额 + */ + void updatePurchaseReturnRefundPrice(Long id, BigDecimal refundPrice); + /** * 删除采购退货 * diff --git a/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/service/purchase/ErpPurchaseReturnServiceImpl.java b/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/service/purchase/ErpPurchaseReturnServiceImpl.java index 1d33db69a..109916249 100644 --- a/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/service/purchase/ErpPurchaseReturnServiceImpl.java +++ b/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/service/purchase/ErpPurchaseReturnServiceImpl.java @@ -159,7 +159,10 @@ public class ErpPurchaseReturnServiceImpl implements ErpPurchaseReturnService { if (purchaseReturn.getStatus().equals(status)) { throw exception(approve ? PURCHASE_RETURN_APPROVE_FAIL : PURCHASE_RETURN_PROCESS_FAIL); } - // TODO 芋艿:稍后加下校验 + // 1.3 校验已退款 + if (approve && purchaseReturn.getRefundPrice().compareTo(BigDecimal.ZERO) > 0) { + throw exception(PURCHASE_RETURN_PROCESS_FAIL_EXISTS_REFUND); + } // 2. 更新状态 int updateCount = purchaseReturnMapper.updateByIdAndStatus(id, purchaseReturn.getStatus(), @@ -180,6 +183,18 @@ public class ErpPurchaseReturnServiceImpl implements ErpPurchaseReturnService { }); } + @Override + public void updatePurchaseReturnRefundPrice(Long id, BigDecimal refundPrice) { + ErpPurchaseReturnDO purchaseReturn = purchaseReturnMapper.selectById(id); + if (purchaseReturn.getRefundPrice().equals(refundPrice)) { + return; + } + if (refundPrice.compareTo(purchaseReturn.getTotalPrice()) > 0) { + throw exception(PURCHASE_RETURN_FAIL_REFUND_PRICE_EXCEED, purchaseReturn.getTotalPrice(), refundPrice); + } + purchaseReturnMapper.updateById(new ErpPurchaseReturnDO().setId(id).setRefundPrice(refundPrice)); + } + private List validatePurchaseReturnItems(List list) { // 1. 校验产品存在 List productList = productService.validProductList( From 33f654b73b78d617bc65ef6f230144edecb24a97 Mon Sep 17 00:00:00 2001 From: YunaiV Date: Thu, 15 Feb 2024 09:16:11 +0800 Subject: [PATCH 109/119] =?UTF-8?q?=E2=9C=A8=20ERP=EF=BC=9A=E9=94=80?= =?UTF-8?q?=E5=94=AE=E8=AE=A2=E5=8D=95=E7=9A=84=20receiptPrice=20=E8=B0=83?= =?UTF-8?q?=E6=95=B4=EF=BC=8C=E4=B8=BA=E6=8E=A5=E5=85=A5=E8=B4=A2=E5=8A=A1?= =?UTF-8?q?=E7=9A=84=E6=94=B6=E6=AC=BE=E5=8D=95=E5=81=9A=E5=87=86=E5=A4=87?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../sale/vo/out/ErpSaleOutPageReqVO.java | 11 ++++++++-- .../admin/sale/vo/out/ErpSaleOutRespVO.java | 10 +++------- .../sale/vo/out/ErpSaleOutSaveReqVO.java | 4 ---- .../vo/returns/ErpSaleReturnPageReqVO.java | 10 ++++++++++ .../sale/vo/returns/ErpSaleReturnRespVO.java | 10 +++------- .../vo/returns/ErpSaleReturnSaveReqVO.java | 4 ---- .../finance/ErpFinanceReceiptDO.java | 4 ++++ .../dataobject/purchase/ErpPurchaseInDO.java | 2 +- .../purchase/ErpPurchaseReturnDO.java | 2 +- .../erp/dal/dataobject/sale/ErpSaleOutDO.java | 20 +++++++------------ .../dal/dataobject/sale/ErpSaleReturnDO.java | 19 +++++++----------- .../erp/dal/mysql/sale/ErpSaleOutMapper.java | 16 ++++++++++----- .../dal/mysql/sale/ErpSaleReturnMapper.java | 12 +++++++++++ .../service/sale/ErpSaleOutServiceImpl.java | 5 +---- .../sale/ErpSaleReturnServiceImpl.java | 5 +---- 15 files changed, 70 insertions(+), 64 deletions(-) create mode 100644 yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/dal/dataobject/finance/ErpFinanceReceiptDO.java diff --git a/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/controller/admin/sale/vo/out/ErpSaleOutPageReqVO.java b/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/controller/admin/sale/vo/out/ErpSaleOutPageReqVO.java index c422a6088..5afeeea84 100644 --- a/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/controller/admin/sale/vo/out/ErpSaleOutPageReqVO.java +++ b/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/controller/admin/sale/vo/out/ErpSaleOutPageReqVO.java @@ -17,6 +17,10 @@ import static cn.iocoder.yudao.framework.common.util.date.DateUtils.FORMAT_YEAR_ @ToString(callSuper = true) public class ErpSaleOutPageReqVO extends PageParam { + public static final Integer RECEIPT_STATUS_NONE = 0; + public static final Integer RECEIPT_STATUS_PART = 1; + public static final Integer RECEIPT_STATUS_ALL = 2; + @Schema(description = "销售单编号", example = "XS001") private String no; @@ -45,8 +49,11 @@ public class ErpSaleOutPageReqVO extends PageParam { @Schema(description = "结算账号编号", example = "1") private Long accountId; - @Schema(description = "是否欠款", example = "true") - private Boolean debtStatus; + @Schema(description = "收款状态", example = "1") + private Integer receiptStatus; + + @Schema(description = "是否可收款", example = "true") + private Boolean receiptEnable; // 对应 receiptStatus = [0, 1] @Schema(description = "销售单号", example = "1") private String orderNo; diff --git a/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/controller/admin/sale/vo/out/ErpSaleOutRespVO.java b/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/controller/admin/sale/vo/out/ErpSaleOutRespVO.java index 4f6cc49ab..bc15a1339 100644 --- a/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/controller/admin/sale/vo/out/ErpSaleOutRespVO.java +++ b/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/controller/admin/sale/vo/out/ErpSaleOutRespVO.java @@ -55,6 +55,8 @@ public class ErpSaleOutRespVO { @Schema(description = "最终合计价格", requiredMode = Schema.RequiredMode.REQUIRED, example = "24906") @ExcelProperty("最终合计价格") private BigDecimal totalPrice; + @Schema(description = "已收款金额,单位:元", requiredMode = Schema.RequiredMode.REQUIRED, example = "7127") + private BigDecimal receiptPrice; @Schema(description = "合计产品价格,单位:元", requiredMode = Schema.RequiredMode.REQUIRED, example = "7127") private BigDecimal totalProductPrice; @@ -68,15 +70,9 @@ public class ErpSaleOutRespVO { @Schema(description = "优惠金额,单位:元", requiredMode = Schema.RequiredMode.REQUIRED, example = "7127") private BigDecimal discountPrice; - @Schema(description = "定金金额,单位:元", requiredMode = Schema.RequiredMode.REQUIRED, example = "7127") + @Schema(description = "其它金额,单位:元", requiredMode = Schema.RequiredMode.REQUIRED, example = "7127") private BigDecimal otherPrice; - @Schema(description = "本次收款,单位:元", requiredMode = Schema.RequiredMode.REQUIRED, example = "7127") - private BigDecimal payPrice; - @Schema(description = "本次欠款,单位:元", requiredMode = Schema.RequiredMode.REQUIRED, example = "666") - private BigDecimal debtPrice; - - @Schema(description = "附件地址", example = "https://www.iocoder.cn") @ExcelProperty("附件地址") private String fileUrl; diff --git a/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/controller/admin/sale/vo/out/ErpSaleOutSaveReqVO.java b/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/controller/admin/sale/vo/out/ErpSaleOutSaveReqVO.java index ac09f6bf1..3a2216a33 100644 --- a/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/controller/admin/sale/vo/out/ErpSaleOutSaveReqVO.java +++ b/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/controller/admin/sale/vo/out/ErpSaleOutSaveReqVO.java @@ -35,10 +35,6 @@ public class ErpSaleOutSaveReqVO { @Schema(description = "其它金额,单位:元", example = "7127") private BigDecimal otherPrice; - @Schema(description = "本次收款,单位:元", requiredMode = Schema.RequiredMode.REQUIRED, example = "7127") - @NotNull(message = "本次收款不能为空") - private BigDecimal payPrice; - @Schema(description = "附件地址", example = "https://www.iocoder.cn") private String fileUrl; diff --git a/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/controller/admin/sale/vo/returns/ErpSaleReturnPageReqVO.java b/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/controller/admin/sale/vo/returns/ErpSaleReturnPageReqVO.java index db4f73f5b..a9be73beb 100644 --- a/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/controller/admin/sale/vo/returns/ErpSaleReturnPageReqVO.java +++ b/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/controller/admin/sale/vo/returns/ErpSaleReturnPageReqVO.java @@ -17,6 +17,10 @@ import static cn.iocoder.yudao.framework.common.util.date.DateUtils.FORMAT_YEAR_ @ToString(callSuper = true) public class ErpSaleReturnPageReqVO extends PageParam { + public static final Integer REFUND_STATUS_NONE = 0; + public static final Integer REFUND_STATUS_PART = 1; + public static final Integer REFUND_STATUS_ALL = 2; + @Schema(description = "销售单编号", example = "XS001") private String no; @@ -48,4 +52,10 @@ public class ErpSaleReturnPageReqVO extends PageParam { @Schema(description = "销售单号", example = "1") private String orderNo; + @Schema(description = "退款状态", example = "1") + private Integer refundStatus; + + @Schema(description = "是否可退款", example = "true") + private Boolean refundEnable; // 对应 refundStatus = [0, 1] + } \ No newline at end of file diff --git a/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/controller/admin/sale/vo/returns/ErpSaleReturnRespVO.java b/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/controller/admin/sale/vo/returns/ErpSaleReturnRespVO.java index 0a7801de1..ba52f4f80 100644 --- a/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/controller/admin/sale/vo/returns/ErpSaleReturnRespVO.java +++ b/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/controller/admin/sale/vo/returns/ErpSaleReturnRespVO.java @@ -55,6 +55,8 @@ public class ErpSaleReturnRespVO { @Schema(description = "最终合计价格", requiredMode = Schema.RequiredMode.REQUIRED, example = "24906") @ExcelProperty("最终合计价格") private BigDecimal totalPrice; + @Schema(description = "已退款金额,单位:元", requiredMode = Schema.RequiredMode.REQUIRED, example = "7127") + private BigDecimal refundPrice; @Schema(description = "合计产品价格,单位:元", requiredMode = Schema.RequiredMode.REQUIRED, example = "7127") private BigDecimal totalProductPrice; @@ -68,15 +70,9 @@ public class ErpSaleReturnRespVO { @Schema(description = "优惠金额,单位:元", requiredMode = Schema.RequiredMode.REQUIRED, example = "7127") private BigDecimal discountPrice; - @Schema(description = "定金金额,单位:元", requiredMode = Schema.RequiredMode.REQUIRED, example = "7127") + @Schema(description = "其它金额,单位:元", requiredMode = Schema.RequiredMode.REQUIRED, example = "7127") private BigDecimal otherPrice; - @Schema(description = "本次退款,单位:元", requiredMode = Schema.RequiredMode.REQUIRED, example = "7127") - private BigDecimal refundPrice; - @Schema(description = "本次欠款,单位:元", requiredMode = Schema.RequiredMode.REQUIRED, example = "666") - private BigDecimal debtPrice; - - @Schema(description = "附件地址", example = "https://www.iocoder.cn") @ExcelProperty("附件地址") private String fileUrl; diff --git a/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/controller/admin/sale/vo/returns/ErpSaleReturnSaveReqVO.java b/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/controller/admin/sale/vo/returns/ErpSaleReturnSaveReqVO.java index 837a4b509..81c046f7d 100644 --- a/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/controller/admin/sale/vo/returns/ErpSaleReturnSaveReqVO.java +++ b/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/controller/admin/sale/vo/returns/ErpSaleReturnSaveReqVO.java @@ -35,10 +35,6 @@ public class ErpSaleReturnSaveReqVO { @Schema(description = "其它金额,单位:元", example = "7127") private BigDecimal otherPrice; - @Schema(description = "本次退款,单位:元", requiredMode = Schema.RequiredMode.REQUIRED, example = "7127") - @NotNull(message = "本次退款不能为空") - private BigDecimal refundPrice; - @Schema(description = "附件地址", example = "https://www.iocoder.cn") private String fileUrl; diff --git a/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/dal/dataobject/finance/ErpFinanceReceiptDO.java b/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/dal/dataobject/finance/ErpFinanceReceiptDO.java new file mode 100644 index 000000000..d4180a888 --- /dev/null +++ b/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/dal/dataobject/finance/ErpFinanceReceiptDO.java @@ -0,0 +1,4 @@ +package cn.iocoder.yudao.module.erp.dal.dataobject.finance; + +public class ErpFinanceReceiptDO { +} diff --git a/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/dal/dataobject/purchase/ErpPurchaseInDO.java b/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/dal/dataobject/purchase/ErpPurchaseInDO.java index a16844d3e..b8186f509 100644 --- a/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/dal/dataobject/purchase/ErpPurchaseInDO.java +++ b/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/dal/dataobject/purchase/ErpPurchaseInDO.java @@ -83,7 +83,7 @@ public class ErpPurchaseInDO extends BaseDO { /** * 已支付金额,单位:元 * - * 目的:和 TODO erp_finance_payment 结合,记录已支付金额 + * 目的:和 {@link cn.iocoder.yudao.module.erp.dal.dataobject.finance.ErpFinancePaymentDO} 结合,记录已支付金额 */ private BigDecimal paymentPrice; diff --git a/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/dal/dataobject/purchase/ErpPurchaseReturnDO.java b/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/dal/dataobject/purchase/ErpPurchaseReturnDO.java index a1c8cc4d5..4189e0adc 100644 --- a/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/dal/dataobject/purchase/ErpPurchaseReturnDO.java +++ b/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/dal/dataobject/purchase/ErpPurchaseReturnDO.java @@ -83,7 +83,7 @@ public class ErpPurchaseReturnDO extends BaseDO { /** * 已退款金额,单位:元 * - * 目的:和 TODO erp_finance_payment 结合,记录已退款金额 + * 目的:和 {@link cn.iocoder.yudao.module.erp.dal.dataobject.finance.ErpFinancePaymentDO} 结合,记录已支付金额 */ private BigDecimal refundPrice; diff --git a/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/dal/dataobject/sale/ErpSaleOutDO.java b/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/dal/dataobject/sale/ErpSaleOutDO.java index 4bf567159..65b9d941f 100644 --- a/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/dal/dataobject/sale/ErpSaleOutDO.java +++ b/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/dal/dataobject/sale/ErpSaleOutDO.java @@ -83,9 +83,15 @@ public class ErpSaleOutDO extends BaseDO { /** * 最终合计价格,单位:元 * - * totalPrice = totalProductPrice + totalTaxPrice - discountPrice + * totalPrice = totalProductPrice + totalTaxPrice - discountPrice + otherPrice */ private BigDecimal totalPrice; + /** + * 已收款金额,单位:元 + * + * 目的:和 {@link cn.iocoder.yudao.module.erp.dal.dataobject.finance.ErpFinanceReceiptDO} 结合,记录已收款金额 + */ + private BigDecimal receiptPrice; /** * 合计产品价格,单位:元 @@ -110,18 +116,6 @@ public class ErpSaleOutDO extends BaseDO { */ private BigDecimal otherPrice; - // TODO 芋艿:receiptPrice - /** - * 本次收款,单位:元 - * - * payPrice = totalPrice + otherPrice - debtPrice - */ - private BigDecimal payPrice; - /** - * 本次欠款,单位:元 - */ - private BigDecimal debtPrice; - /** * 附件地址 */ diff --git a/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/dal/dataobject/sale/ErpSaleReturnDO.java b/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/dal/dataobject/sale/ErpSaleReturnDO.java index 2ee54363c..ba41ac91b 100644 --- a/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/dal/dataobject/sale/ErpSaleReturnDO.java +++ b/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/dal/dataobject/sale/ErpSaleReturnDO.java @@ -83,9 +83,15 @@ public class ErpSaleReturnDO extends BaseDO { /** * 最终合计价格,单位:元 * - * totalPrice = totalProductPrice + totalTaxPrice - discountPrice + * totalPrice = totalProductPrice + totalTaxPrice - discountPrice + otherPrice */ private BigDecimal totalPrice; + /** + * 已退款金额,单位:元 + * + * 目的:和 {@link cn.iocoder.yudao.module.erp.dal.dataobject.finance.ErpFinanceReceiptDO} 结合,记录已退款金额 + */ + private BigDecimal refundPrice; /** * 合计产品价格,单位:元 @@ -110,17 +116,6 @@ public class ErpSaleReturnDO extends BaseDO { */ private BigDecimal otherPrice; - /** - * 本次收款,单位:元 - * - * refundPrice = totalPrice + otherPrice - debtPrice - */ - private BigDecimal refundPrice; - /** - * 本次欠款,单位:元 - */ - private BigDecimal debtPrice; - /** * 附件地址 */ diff --git a/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/dal/mysql/sale/ErpSaleOutMapper.java b/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/dal/mysql/sale/ErpSaleOutMapper.java index e530557fb..d5b640b4c 100644 --- a/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/dal/mysql/sale/ErpSaleOutMapper.java +++ b/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/dal/mysql/sale/ErpSaleOutMapper.java @@ -10,8 +10,8 @@ import cn.iocoder.yudao.module.erp.dal.dataobject.sale.ErpSaleOutItemDO; import com.baomidou.mybatisplus.core.conditions.update.LambdaUpdateWrapper; import org.apache.ibatis.annotations.Mapper; -import java.math.BigDecimal; import java.util.List; +import java.util.Objects; /** * ERP 销售出库 Mapper @@ -32,10 +32,16 @@ public interface ErpSaleOutMapper extends BaseMapperX { .eqIfPresent(ErpSaleOutDO::getAccountId, reqVO.getAccountId()) .likeIfPresent(ErpSaleOutDO::getOrderNo, reqVO.getOrderNo()) .orderByDesc(ErpSaleOutDO::getId); - if (Boolean.TRUE.equals(reqVO.getDebtStatus())) { - query.gt(ErpSaleOutDO::getDebtPrice, BigDecimal.ZERO); - } else if (Boolean.FALSE.equals(reqVO.getDebtStatus())) { - query.eq(ErpSaleOutDO::getDebtPrice, BigDecimal.ZERO); + // 收款状态。为什么需要 t. 的原因,是因为联表查询时,需要指定表名,不然会报字段不存在的错误 + if (Objects.equals(reqVO.getReceiptStatus(), ErpSaleOutPageReqVO.RECEIPT_STATUS_NONE)) { + query.eq(ErpSaleOutDO::getReceiptPrice, 0); + } else if (Objects.equals(reqVO.getReceiptStatus(), ErpSaleOutPageReqVO.RECEIPT_STATUS_PART)) { + query.gt(ErpSaleOutDO::getReceiptPrice, 0).apply("t.receipt_price < t.total_price"); + } else if (Objects.equals(reqVO.getReceiptStatus(), ErpSaleOutPageReqVO.RECEIPT_STATUS_ALL)) { + query.apply("t.receipt_price = t.total_price"); + } + if (Boolean.TRUE.equals(reqVO.getReceiptEnable())) { + query.apply("t.receipt_price < t.total_price"); } if (reqVO.getWarehouseId() != null || reqVO.getProductId() != null) { query.leftJoin(ErpSaleOutItemDO.class, ErpSaleOutItemDO::getOutId, ErpSaleOutDO::getId) diff --git a/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/dal/mysql/sale/ErpSaleReturnMapper.java b/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/dal/mysql/sale/ErpSaleReturnMapper.java index 2ca45900c..8efe761b7 100644 --- a/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/dal/mysql/sale/ErpSaleReturnMapper.java +++ b/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/dal/mysql/sale/ErpSaleReturnMapper.java @@ -11,6 +11,7 @@ import com.baomidou.mybatisplus.core.conditions.update.LambdaUpdateWrapper; import org.apache.ibatis.annotations.Mapper; import java.util.List; +import java.util.Objects; /** * ERP 销售退货 Mapper @@ -31,6 +32,17 @@ public interface ErpSaleReturnMapper extends BaseMapperX { .eqIfPresent(ErpSaleReturnDO::getAccountId, reqVO.getAccountId()) .likeIfPresent(ErpSaleReturnDO::getOrderNo, reqVO.getOrderNo()) .orderByDesc(ErpSaleReturnDO::getId); + // 退款状态。为什么需要 t. 的原因,是因为联表查询时,需要指定表名,不然会报字段不存在的错误 + if (Objects.equals(reqVO.getRefundStatus(), ErpSaleReturnPageReqVO.REFUND_STATUS_NONE)) { + query.eq(ErpSaleReturnDO::getRefundPrice, 0); + } else if (Objects.equals(reqVO.getRefundStatus(), ErpSaleReturnPageReqVO.REFUND_STATUS_PART)) { + query.gt(ErpSaleReturnDO::getRefundPrice, 0).apply("t.refund_price < t.total_price"); + } else if (Objects.equals(reqVO.getRefundStatus(), ErpSaleReturnPageReqVO.REFUND_STATUS_ALL)) { + query.apply("t.refund_price = t.total_price"); + } + if (Boolean.TRUE.equals(reqVO.getRefundEnable())) { + query.apply("t.refund_price < t.total_price"); + } if (reqVO.getWarehouseId() != null || reqVO.getProductId() != null) { query.leftJoin(ErpSaleReturnItemDO.class, ErpSaleReturnItemDO::getReturnId, ErpSaleReturnDO::getId) .eq(reqVO.getWarehouseId() != null, ErpSaleReturnItemDO::getWarehouseId, reqVO.getWarehouseId()) diff --git a/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/service/sale/ErpSaleOutServiceImpl.java b/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/service/sale/ErpSaleOutServiceImpl.java index ab0496892..4338c9e83 100644 --- a/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/service/sale/ErpSaleOutServiceImpl.java +++ b/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/service/sale/ErpSaleOutServiceImpl.java @@ -148,10 +148,7 @@ public class ErpSaleOutServiceImpl implements ErpSaleOutService { saleOut.setDiscountPercent(BigDecimal.ZERO); } saleOut.setDiscountPrice(MoneyUtils.priceMultiplyPercent(saleOut.getTotalPrice(), saleOut.getDiscountPercent())); - saleOut.setTotalPrice(saleOut.getTotalPrice().subtract(saleOut.getDiscountPrice())); - // 计算应收金额 - BigDecimal allPrice = saleOut.getTotalPrice().add(saleOut.getOtherPrice()); - saleOut.setDebtPrice(allPrice.subtract(saleOut.getPayPrice())); + saleOut.setTotalPrice(saleOut.getTotalPrice().subtract(saleOut.getDiscountPrice().add(saleOut.getOtherPrice()))); } private void updateSaleOrderOutCount(Long orderId) { diff --git a/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/service/sale/ErpSaleReturnServiceImpl.java b/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/service/sale/ErpSaleReturnServiceImpl.java index 2c680ac45..0c5313256 100644 --- a/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/service/sale/ErpSaleReturnServiceImpl.java +++ b/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/service/sale/ErpSaleReturnServiceImpl.java @@ -148,10 +148,7 @@ public class ErpSaleReturnServiceImpl implements ErpSaleReturnService { saleReturn.setDiscountPercent(BigDecimal.ZERO); } saleReturn.setDiscountPrice(MoneyUtils.priceMultiplyPercent(saleReturn.getTotalPrice(), saleReturn.getDiscountPercent())); - saleReturn.setTotalPrice(saleReturn.getTotalPrice().subtract(saleReturn.getDiscountPrice())); - // 计算应退金额 - BigDecimal allPrice = saleReturn.getTotalPrice().add(saleReturn.getOtherPrice()); - saleReturn.setDebtPrice(allPrice.subtract(saleReturn.getRefundPrice())); + saleReturn.setTotalPrice(saleReturn.getTotalPrice().subtract(saleReturn.getDiscountPrice().add(saleReturn.getOtherPrice()))); } private void updateSaleOrderReturnCount(Long orderId) { From f93bad282f4985695244a111cbbcb13c5e6c5d1f Mon Sep 17 00:00:00 2001 From: YunaiV Date: Thu, 15 Feb 2024 19:28:54 +0800 Subject: [PATCH 110/119] =?UTF-8?q?=E2=9C=A8=20ERP=EF=BC=9A=E5=88=9D?= =?UTF-8?q?=E5=A7=8B=E5=8C=96=20receipt=20=E6=94=B6=E6=AC=BE=E5=8D=95?= =?UTF-8?q?=E7=9A=84=E9=80=BB=E8=BE=91=2030%?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../module/erp/enums/ErrorCodeConstants.java | 14 + .../finance/ErpFinanceReceiptController.java | 153 ++++++++++ .../payment/ErpFinancePaymentPageReqVO.java | 2 +- .../vo/payment/ErpFinancePaymentRespVO.java | 4 +- .../payment/ErpFinancePaymentSaveReqVO.java | 4 +- .../receipt/ErpFinanceReceiptPageReqVO.java | 48 +++ .../vo/receipt/ErpFinanceReceiptRespVO.java | 97 +++++++ .../receipt/ErpFinanceReceiptSaveReqVO.java | 74 +++++ .../finance/ErpFinancePaymentItemDO.java | 4 +- .../finance/ErpFinanceReceiptDO.java | 86 +++++- .../finance/ErpFinanceReceiptItemDO.java | 75 +++++ .../finance/ErpFinanceReceiptItemMapper.java | 44 +++ .../finance/ErpFinanceReceiptMapper.java | 48 +++ .../erp/dal/redis/no/ErpNoRedisDAO.java | 4 + .../finance/ErpFinanceReceiptService.java | 84 ++++++ .../finance/ErpFinanceReceiptServiceImpl.java | 273 ++++++++++++++++++ .../purchase/ErpPurchaseInServiceImpl.java | 2 +- .../ErpPurchaseReturnServiceImpl.java | 2 +- .../erp/service/sale/ErpSaleOutService.java | 18 ++ .../service/sale/ErpSaleOutServiceImpl.java | 25 ++ .../service/sale/ErpSaleReturnService.java | 17 ++ .../sale/ErpSaleReturnServiceImpl.java | 25 ++ 22 files changed, 1092 insertions(+), 11 deletions(-) create mode 100644 yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/controller/admin/finance/ErpFinanceReceiptController.java create mode 100644 yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/controller/admin/finance/vo/receipt/ErpFinanceReceiptPageReqVO.java create mode 100644 yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/controller/admin/finance/vo/receipt/ErpFinanceReceiptRespVO.java create mode 100644 yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/controller/admin/finance/vo/receipt/ErpFinanceReceiptSaveReqVO.java create mode 100644 yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/dal/dataobject/finance/ErpFinanceReceiptItemDO.java create mode 100644 yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/dal/mysql/finance/ErpFinanceReceiptItemMapper.java create mode 100644 yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/dal/mysql/finance/ErpFinanceReceiptMapper.java create mode 100644 yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/service/finance/ErpFinanceReceiptService.java create mode 100644 yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/service/finance/ErpFinanceReceiptServiceImpl.java diff --git a/yudao-module-erp/yudao-module-erp-api/src/main/java/cn/iocoder/yudao/module/erp/enums/ErrorCodeConstants.java b/yudao-module-erp/yudao-module-erp-api/src/main/java/cn/iocoder/yudao/module/erp/enums/ErrorCodeConstants.java index 580539f97..65f64c2f5 100644 --- a/yudao-module-erp/yudao-module-erp-api/src/main/java/cn/iocoder/yudao/module/erp/enums/ErrorCodeConstants.java +++ b/yudao-module-erp/yudao-module-erp-api/src/main/java/cn/iocoder/yudao/module/erp/enums/ErrorCodeConstants.java @@ -72,6 +72,9 @@ ErrorCode PURCHASE_ORDER_ITEM_RETURN_FAIL_IN_EXCEED = new ErrorCode(1_030_101_00 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, "销售出库单({})已审核,无法修改"); + ErrorCode SALE_OUT_NOT_APPROVE = new ErrorCode(1_020_202_006, "销售出库单未审核,无法操作"); + ErrorCode SALE_OUT_FAIL_RECEIPT_PRICE_EXCEED = new ErrorCode(1_020_202_007, "收款金额({})超过销售出库单总金额({})"); + ErrorCode SALE_OUT_PROCESS_FAIL_EXISTS_RECEIPT = new ErrorCode(1_020_202_008, "反审核失败,已存在对应的收款单"); // ========== ERP 销售退货(1-030-203-000) ========== ErrorCode SALE_RETURN_NOT_EXISTS = new ErrorCode(1_020_203_000, "销售退货单不存在"); @@ -80,6 +83,9 @@ ErrorCode PURCHASE_ORDER_ITEM_RETURN_FAIL_IN_EXCEED = new ErrorCode(1_030_101_00 ErrorCode SALE_RETURN_APPROVE_FAIL = new ErrorCode(1_020_203_003, "审核失败,只有未审核的退货单才能审核"); ErrorCode SALE_RETURN_NO_EXISTS = new ErrorCode(1_020_203_004, "生成退货单失败,请重新提交"); ErrorCode SALE_RETURN_UPDATE_FAIL_APPROVE = new ErrorCode(1_020_203_005, "销售退货单({})已审核,无法修改"); + ErrorCode SALE_RETURN_NOT_APPROVE = new ErrorCode(1_020_203_006, "销售退货单未审核,无法操作"); + ErrorCode SALE_RETURN_FAIL_REFUND_PRICE_EXCEED = new ErrorCode(1_020_203_007, "退款金额({})超过销售退货单总金额({})"); + ErrorCode SALE_RETURN_PROCESS_FAIL_EXISTS_REFUND = new ErrorCode(1_020_203_008, "反审核失败,已存在对应的退款单"); // ========== ERP 仓库 1-030-400-000 ========== ErrorCode WAREHOUSE_NOT_EXISTS = new ErrorCode(1_030_400_000, "仓库不存在"); @@ -151,4 +157,12 @@ ErrorCode PURCHASE_ORDER_ITEM_RETURN_FAIL_IN_EXCEED = new ErrorCode(1_030_101_00 ErrorCode FINANCE_PAYMENT_NO_EXISTS = new ErrorCode(1_030_601_004, "生成付款单号失败,请重新提交"); ErrorCode FINANCE_PAYMENT_UPDATE_FAIL_APPROVE = new ErrorCode(1_030_601_005, "付款单({})已审核,无法修改"); + // ========== ERP 收款单 1-030-602-000 ========== + ErrorCode FINANCE_RECEIPT_NOT_EXISTS = new ErrorCode(1_030_602_000, "收款单不存在"); + ErrorCode FINANCE_RECEIPT_DELETE_FAIL_APPROVE = new ErrorCode(1_030_602_001, "收款单({})已审核,无法删除"); + ErrorCode FINANCE_RECEIPT_PROCESS_FAIL = new ErrorCode(1_030_602_002, "反审核失败,只有已审核的收款单才能反审核"); + ErrorCode FINANCE_RECEIPT_APPROVE_FAIL = new ErrorCode(1_030_602_003, "审核失败,只有未审核的收款单才能审核"); + ErrorCode FINANCE_RECEIPT_NO_EXISTS = new ErrorCode(1_030_602_004, "生成收款单号失败,请重新提交"); + ErrorCode FINANCE_RECEIPT_UPDATE_FAIL_APPROVE = new ErrorCode(1_030_602_005, "收款单({})已审核,无法修改"); + } diff --git a/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/controller/admin/finance/ErpFinanceReceiptController.java b/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/controller/admin/finance/ErpFinanceReceiptController.java new file mode 100644 index 000000000..d36ab3990 --- /dev/null +++ b/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/controller/admin/finance/ErpFinanceReceiptController.java @@ -0,0 +1,153 @@ +package cn.iocoder.yudao.module.erp.controller.admin.finance; + +import cn.hutool.core.collection.CollUtil; +import cn.iocoder.yudao.framework.common.pojo.CommonResult; +import cn.iocoder.yudao.framework.common.pojo.PageParam; +import cn.iocoder.yudao.framework.common.pojo.PageResult; +import cn.iocoder.yudao.framework.common.util.collection.MapUtils; +import cn.iocoder.yudao.framework.common.util.number.NumberUtils; +import cn.iocoder.yudao.framework.common.util.object.BeanUtils; +import cn.iocoder.yudao.framework.excel.core.util.ExcelUtils; +import cn.iocoder.yudao.framework.operatelog.core.annotations.OperateLog; +import cn.iocoder.yudao.module.erp.controller.admin.finance.vo.receipt.ErpFinanceReceiptPageReqVO; +import cn.iocoder.yudao.module.erp.controller.admin.finance.vo.receipt.ErpFinanceReceiptRespVO; +import cn.iocoder.yudao.module.erp.controller.admin.finance.vo.receipt.ErpFinanceReceiptSaveReqVO; +import cn.iocoder.yudao.module.erp.dal.dataobject.finance.ErpAccountDO; +import cn.iocoder.yudao.module.erp.dal.dataobject.finance.ErpFinanceReceiptDO; +import cn.iocoder.yudao.module.erp.dal.dataobject.finance.ErpFinanceReceiptItemDO; +import cn.iocoder.yudao.module.erp.dal.dataobject.sale.ErpCustomerDO; +import cn.iocoder.yudao.module.erp.service.finance.ErpAccountService; +import cn.iocoder.yudao.module.erp.service.finance.ErpFinanceReceiptService; +import cn.iocoder.yudao.module.erp.service.sale.ErpCustomerService; +import cn.iocoder.yudao.module.system.api.user.AdminUserApi; +import cn.iocoder.yudao.module.system.api.user.dto.AdminUserRespDTO; +import io.swagger.v3.oas.annotations.Operation; +import io.swagger.v3.oas.annotations.Parameter; +import io.swagger.v3.oas.annotations.tags.Tag; +import jakarta.annotation.Resource; +import jakarta.servlet.http.HttpServletResponse; +import jakarta.validation.Valid; +import org.springframework.security.access.prepost.PreAuthorize; +import org.springframework.validation.annotation.Validated; +import org.springframework.web.bind.annotation.*; + +import java.io.IOException; +import java.util.List; +import java.util.Map; +import java.util.stream.Stream; + +import static cn.iocoder.yudao.framework.common.pojo.CommonResult.success; +import static cn.iocoder.yudao.framework.common.util.collection.CollectionUtils.*; +import static cn.iocoder.yudao.framework.operatelog.core.enums.OperateTypeEnum.EXPORT; + +@Tag(name = "管理后台 - ERP 收款单") +@RestController +@RequestMapping("/erp/finance-receipt") +@Validated +public class ErpFinanceReceiptController { + + @Resource + private ErpFinanceReceiptService financeReceiptService; + @Resource + private ErpCustomerService customerService; + @Resource + private ErpAccountService accountService; + + @Resource + private AdminUserApi adminUserApi; + + @PostMapping("/create") + @Operation(summary = "创建收款单") + @PreAuthorize("@ss.hasPermission('erp:finance-receipt:create')") + public CommonResult createFinanceReceipt(@Valid @RequestBody ErpFinanceReceiptSaveReqVO createReqVO) { + return success(financeReceiptService.createFinanceReceipt(createReqVO)); + } + + @PutMapping("/update") + @Operation(summary = "更新收款单") + @PreAuthorize("@ss.hasPermission('erp:finance-receipt:update')") + public CommonResult updateFinanceReceipt(@Valid @RequestBody ErpFinanceReceiptSaveReqVO updateReqVO) { + financeReceiptService.updateFinanceReceipt(updateReqVO); + return success(true); + } + + @PutMapping("/update-status") + @Operation(summary = "更新收款单的状态") + @PreAuthorize("@ss.hasPermission('erp:finance-receipt:update-status')") + public CommonResult updateFinanceReceiptStatus(@RequestParam("id") Long id, + @RequestParam("status") Integer status) { + financeReceiptService.updateFinanceReceiptStatus(id, status); + return success(true); + } + + @DeleteMapping("/delete") + @Operation(summary = "删除收款单") + @Parameter(name = "ids", description = "编号数组", required = true) + @PreAuthorize("@ss.hasPermission('erp:finance-receipt:delete')") + public CommonResult deleteFinanceReceipt(@RequestParam("ids") List ids) { + financeReceiptService.deleteFinanceReceipt(ids); + return success(true); + } + + @GetMapping("/get") + @Operation(summary = "获得收款单") + @Parameter(name = "id", description = "编号", required = true, example = "1024") + @PreAuthorize("@ss.hasPermission('erp:finance-receipt:query')") + public CommonResult getFinanceReceipt(@RequestParam("id") Long id) { + ErpFinanceReceiptDO receipt = financeReceiptService.getFinanceReceipt(id); + if (receipt == null) { + return success(null); + } + List receiptItemList = financeReceiptService.getFinanceReceiptItemListByReceiptId(id); + return success(BeanUtils.toBean(receipt, ErpFinanceReceiptRespVO.class, financeReceiptVO -> + financeReceiptVO.setItems(BeanUtils.toBean(receiptItemList, ErpFinanceReceiptRespVO.Item.class)))); + } + + @GetMapping("/page") + @Operation(summary = "获得收款单分页") + @PreAuthorize("@ss.hasPermission('erp:finance-receipt:query')") + public CommonResult> getFinanceReceiptPage(@Valid ErpFinanceReceiptPageReqVO pageReqVO) { + PageResult pageResult = financeReceiptService.getFinanceReceiptPage(pageReqVO); + return success(buildFinanceReceiptVOPageResult(pageResult)); + } + + @GetMapping("/export-excel") + @Operation(summary = "导出收款单 Excel") + @PreAuthorize("@ss.hasPermission('erp:finance-receipt:export')") + @OperateLog(type = EXPORT) + public void exportFinanceReceiptExcel(@Valid ErpFinanceReceiptPageReqVO pageReqVO, + HttpServletResponse response) throws IOException { + pageReqVO.setPageSize(PageParam.PAGE_SIZE_NONE); + List list = buildFinanceReceiptVOPageResult(financeReceiptService.getFinanceReceiptPage(pageReqVO)).getList(); + // 导出 Excel + ExcelUtils.write(response, "收款单.xls", "数据", ErpFinanceReceiptRespVO.class, list); + } + + private PageResult buildFinanceReceiptVOPageResult(PageResult pageResult) { + if (CollUtil.isEmpty(pageResult.getList())) { + return PageResult.empty(pageResult.getTotal()); + } + // 1.1 收款项 + List receiptItemList = financeReceiptService.getFinanceReceiptItemListByReceiptIds( + convertSet(pageResult.getList(), ErpFinanceReceiptDO::getId)); + Map> financeReceiptItemMap = convertMultiMap(receiptItemList, ErpFinanceReceiptItemDO::getReceiptId); + // 1.2 客户信息 + Map customerMap = customerService.getCustomerMap( + convertSet(pageResult.getList(), ErpFinanceReceiptDO::getCustomerId)); + // 1.3 结算账户信息 + Map accountMap = accountService.getAccountMap( + convertSet(pageResult.getList(), ErpFinanceReceiptDO::getAccountId)); + // 1.4 管理员信息 + Map userMap = adminUserApi.getUserMap(convertListByFlatMap(pageResult.getList(), + contact -> Stream.of(NumberUtils.parseLong(contact.getCreator()), contact.getFinanceUserId()))); + // 2. 开始拼接 + return BeanUtils.toBean(pageResult, ErpFinanceReceiptRespVO.class, receipt -> { + receipt.setItems(BeanUtils.toBean(financeReceiptItemMap.get(receipt.getId()), ErpFinanceReceiptRespVO.Item.class)); + MapUtils.findAndThen(customerMap, receipt.getCustomerId(), customer -> receipt.setCustomerName(customer.getName())); + MapUtils.findAndThen(accountMap, receipt.getAccountId(), account -> receipt.setAccountName(account.getName())); + MapUtils.findAndThen(userMap, Long.parseLong(receipt.getCreator()), user -> receipt.setCreatorName(user.getNickname())); + MapUtils.findAndThen(userMap, receipt.getFinanceUserId(), user -> receipt.setFinanceUserName(user.getNickname())); + }); + } + +} diff --git a/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/controller/admin/finance/vo/payment/ErpFinancePaymentPageReqVO.java b/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/controller/admin/finance/vo/payment/ErpFinancePaymentPageReqVO.java index 39a0f9505..b5618cadc 100644 --- a/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/controller/admin/finance/vo/payment/ErpFinancePaymentPageReqVO.java +++ b/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/controller/admin/finance/vo/payment/ErpFinancePaymentPageReqVO.java @@ -17,7 +17,7 @@ import static cn.iocoder.yudao.framework.common.util.date.DateUtils.FORMAT_YEAR_ @ToString(callSuper = true) public class ErpFinancePaymentPageReqVO extends PageParam { - @Schema(description = "采购单编号", example = "XS001") + @Schema(description = "付款单编号", example = "XS001") private String no; @Schema(description = "付款时间") diff --git a/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/controller/admin/finance/vo/payment/ErpFinancePaymentRespVO.java b/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/controller/admin/finance/vo/payment/ErpFinancePaymentRespVO.java index 4dbb4566b..43820a7d2 100644 --- a/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/controller/admin/finance/vo/payment/ErpFinancePaymentRespVO.java +++ b/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/controller/admin/finance/vo/payment/ErpFinancePaymentRespVO.java @@ -79,10 +79,10 @@ public class ErpFinancePaymentRespVO { @Schema(description = "业务单号", requiredMode = Schema.RequiredMode.REQUIRED, example = "11756") private String bizNo; - @Schema(description = "应付欠款,单位:分", requiredMode = Schema.RequiredMode.REQUIRED, example = "10000") + @Schema(description = "应付金额,单位:分", requiredMode = Schema.RequiredMode.REQUIRED, example = "10000") private BigDecimal totalPrice; - @Schema(description = "已付欠款,单位:分", requiredMode = Schema.RequiredMode.REQUIRED, example = "10000") + @Schema(description = "已付金额,单位:分", requiredMode = Schema.RequiredMode.REQUIRED, example = "10000") private BigDecimal paidPrice; @Schema(description = "本次付款,单位:分", requiredMode = Schema.RequiredMode.REQUIRED, example = "10000") diff --git a/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/controller/admin/finance/vo/payment/ErpFinancePaymentSaveReqVO.java b/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/controller/admin/finance/vo/payment/ErpFinancePaymentSaveReqVO.java index d7e3ddb27..e50577b25 100644 --- a/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/controller/admin/finance/vo/payment/ErpFinancePaymentSaveReqVO.java +++ b/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/controller/admin/finance/vo/payment/ErpFinancePaymentSaveReqVO.java @@ -58,8 +58,8 @@ public class ErpFinancePaymentSaveReqVO { @NotNull(message = "业务编号不能为空") private Long bizId; - @Schema(description = "已付欠款,单位:分", requiredMode = Schema.RequiredMode.REQUIRED, example = "10000") - @NotNull(message = "已付欠款不能为空") + @Schema(description = "已付金额,单位:分", requiredMode = Schema.RequiredMode.REQUIRED, example = "10000") + @NotNull(message = "已付金额不能为空") private BigDecimal paidPrice; @Schema(description = "本次付款,单位:分", requiredMode = Schema.RequiredMode.REQUIRED, example = "10000") diff --git a/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/controller/admin/finance/vo/receipt/ErpFinanceReceiptPageReqVO.java b/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/controller/admin/finance/vo/receipt/ErpFinanceReceiptPageReqVO.java new file mode 100644 index 000000000..d3e938c66 --- /dev/null +++ b/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/controller/admin/finance/vo/receipt/ErpFinanceReceiptPageReqVO.java @@ -0,0 +1,48 @@ +package cn.iocoder.yudao.module.erp.controller.admin.finance.vo.receipt; + +import cn.iocoder.yudao.framework.common.pojo.PageParam; +import io.swagger.v3.oas.annotations.media.Schema; +import lombok.Data; +import lombok.EqualsAndHashCode; +import lombok.ToString; +import org.springframework.format.annotation.DateTimeFormat; + +import java.time.LocalDateTime; + +import static cn.iocoder.yudao.framework.common.util.date.DateUtils.FORMAT_YEAR_MONTH_DAY_HOUR_MINUTE_SECOND; + +@Schema(description = "管理后台 - ERP 收款单分页 Request VO") +@Data +@EqualsAndHashCode(callSuper = true) +@ToString(callSuper = true) +public class ErpFinanceReceiptPageReqVO extends PageParam { + + @Schema(description = "收款单编号", example = "XS001") + private String no; + + @Schema(description = "收款时间") + @DateTimeFormat(pattern = FORMAT_YEAR_MONTH_DAY_HOUR_MINUTE_SECOND) + private LocalDateTime[] receiptTime; + + @Schema(description = "客户编号", example = "1724") + private Long customerId; + + @Schema(description = "创建者", example = "666") + private String creator; + + @Schema(description = "财务人员编号", example = "888") + private String financeUserId; + + @Schema(description = "收款账户编号", example = "31189") + private Long accountId; + + @Schema(description = "收款状态", example = "2") + private Integer status; + + @Schema(description = "备注", example = "你猜") + private String remark; + + @Schema(description = "业务编号", example = "123") + private String bizNo; + +} \ No newline at end of file diff --git a/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/controller/admin/finance/vo/receipt/ErpFinanceReceiptRespVO.java b/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/controller/admin/finance/vo/receipt/ErpFinanceReceiptRespVO.java new file mode 100644 index 000000000..5c7133fe6 --- /dev/null +++ b/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/controller/admin/finance/vo/receipt/ErpFinanceReceiptRespVO.java @@ -0,0 +1,97 @@ +package cn.iocoder.yudao.module.erp.controller.admin.finance.vo.receipt; + +import com.alibaba.excel.annotation.ExcelProperty; +import io.swagger.v3.oas.annotations.media.Schema; +import jakarta.validation.constraints.NotNull; +import lombok.Data; + +import java.math.BigDecimal; +import java.time.LocalDateTime; +import java.util.List; + +@Schema(description = "管理后台 - ERP 收款单 Response VO") +@Data +public class ErpFinanceReceiptRespVO { + + @Schema(description = "编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "23752") + private Long id; + + @Schema(description = "收款单号", requiredMode = Schema.RequiredMode.REQUIRED, example = "FKD888") + private String no; + + @Schema(description = "收款状态", requiredMode = Schema.RequiredMode.REQUIRED, example = "1") + private Integer status; + + @Schema(description = "收款时间", requiredMode = Schema.RequiredMode.REQUIRED) + private LocalDateTime receiptTime; + + @Schema(description = "财务人员编号", example = "19690") + private Long financeUserId; + @Schema(description = "财务人员名称", example = "张三") + private String financeUserName; + + @Schema(description = "客户编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "29399") + private Long customerId; + @Schema(description = "客户名称", requiredMode = Schema.RequiredMode.REQUIRED, example = "小番茄公司") + private String customerName; + + @Schema(description = "收款账户编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "28989") + private Long accountId; + @Schema(description = "收款账户名称", requiredMode = Schema.RequiredMode.REQUIRED, example = "张三") + private String accountName; + + @Schema(description = "合计价格,单位:元", requiredMode = Schema.RequiredMode.REQUIRED, example = "13832") + private BigDecimal totalPrice; + + @Schema(description = "优惠金额,单位:元", requiredMode = Schema.RequiredMode.REQUIRED, example = "11600") + private BigDecimal discountPrice; + + @Schema(description = "实际价格,单位:元", requiredMode = Schema.RequiredMode.REQUIRED, example = "10000") + private BigDecimal receiptPrice; + + @Schema(description = "备注", example = "你猜") + private String remark; + + @Schema(description = "创建人", example = "芋道") + private String creator; + @Schema(description = "创建人名称", example = "芋道") + private String creatorName; + + @Schema(description = "创建时间", requiredMode = Schema.RequiredMode.REQUIRED) + @ExcelProperty("创建时间") + private LocalDateTime createTime; + + @Schema(description = "收款项列表", requiredMode = Schema.RequiredMode.REQUIRED) + private List items; + + @Data + public static class Item { + + @Schema(description = "收款项编号", example = "11756") + private Long id; + + @Schema(description = "业务类型", requiredMode = Schema.RequiredMode.REQUIRED, example = "1") + private Integer bizType; + + @Schema(description = "业务编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "11756") + private Long bizId; + + @Schema(description = "业务单号", requiredMode = Schema.RequiredMode.REQUIRED, example = "11756") + private String bizNo; + + @Schema(description = "应收金额,单位:分", requiredMode = Schema.RequiredMode.REQUIRED, example = "10000") + private BigDecimal totalPrice; + + @Schema(description = "已收金额,单位:分", requiredMode = Schema.RequiredMode.REQUIRED, example = "10000") + private BigDecimal receiptedPrice; + + @Schema(description = "本次收款,单位:分", requiredMode = Schema.RequiredMode.REQUIRED, example = "10000") + @NotNull(message = "本次收款不能为空") + private BigDecimal receiptPrice; + + @Schema(description = "备注", example = "随便") + private String remark; + + } + +} \ No newline at end of file diff --git a/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/controller/admin/finance/vo/receipt/ErpFinanceReceiptSaveReqVO.java b/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/controller/admin/finance/vo/receipt/ErpFinanceReceiptSaveReqVO.java new file mode 100644 index 000000000..126edf805 --- /dev/null +++ b/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/controller/admin/finance/vo/receipt/ErpFinanceReceiptSaveReqVO.java @@ -0,0 +1,74 @@ +package cn.iocoder.yudao.module.erp.controller.admin.finance.vo.receipt; + +import io.swagger.v3.oas.annotations.media.Schema; +import jakarta.validation.Valid; +import jakarta.validation.constraints.NotEmpty; +import jakarta.validation.constraints.NotNull; +import lombok.Data; + +import java.math.BigDecimal; +import java.time.LocalDateTime; +import java.util.List; + +@Schema(description = "管理后台 - ERP 收款单新增/修改 Request VO") +@Data +public class ErpFinanceReceiptSaveReqVO { + + @Schema(description = "编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "23752") + private Long id; + + @Schema(description = "收款时间", requiredMode = Schema.RequiredMode.REQUIRED) + @NotNull(message = "收款时间不能为空") + private LocalDateTime receiptTime; + + @Schema(description = "财务人员编号", example = "19690") + private Long financeUserId; + + @Schema(description = "客户编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "29399") + @NotNull(message = "客户编号不能为空") + private Long customerId; + + @Schema(description = "收款账户编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "28989") + @NotNull(message = "收款账户编号不能为空") + private Long accountId; + + @Schema(description = "优惠金额,单位:元", requiredMode = Schema.RequiredMode.REQUIRED, example = "11600") + @NotNull(message = "优惠金额不能为空") + private BigDecimal discountPrice; + + @Schema(description = "备注", example = "你猜") + private String remark; + + @Schema(description = "收款项列表", requiredMode = Schema.RequiredMode.REQUIRED) + @NotEmpty(message = "收款项列表不能为空") + @Valid + private List items; + + @Data + public static class Item { + + @Schema(description = "收款项编号", example = "11756") + private Long id; + + @Schema(description = "业务类型", requiredMode = Schema.RequiredMode.REQUIRED, example = "1") + @NotNull(message = "业务类型不能为空") + private Integer bizType; + + @Schema(description = "业务编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "11756") + @NotNull(message = "业务编号不能为空") + private Long bizId; + + @Schema(description = "已收金额,单位:分", requiredMode = Schema.RequiredMode.REQUIRED, example = "10000") + @NotNull(message = "已收金额不能为空") + private BigDecimal receiptedPrice; + + @Schema(description = "本次收款,单位:分", requiredMode = Schema.RequiredMode.REQUIRED, example = "10000") + @NotNull(message = "本次收款不能为空") + private BigDecimal receiptPrice; + + @Schema(description = "备注", example = "随便") + private String remark; + + } + +} \ No newline at end of file diff --git a/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/dal/dataobject/finance/ErpFinancePaymentItemDO.java b/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/dal/dataobject/finance/ErpFinancePaymentItemDO.java index fc3ed1ada..dd5bc5f69 100644 --- a/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/dal/dataobject/finance/ErpFinancePaymentItemDO.java +++ b/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/dal/dataobject/finance/ErpFinancePaymentItemDO.java @@ -56,11 +56,11 @@ public class ErpFinancePaymentItemDO extends BaseDO { private String bizNo; /** - * 应付欠款,单位:分 + * 应付金额,单位:分 */ private BigDecimal totalPrice; /** - * 已付欠款,单位:分 + * 已付金额,单位:分 */ private BigDecimal paidPrice; /** diff --git a/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/dal/dataobject/finance/ErpFinanceReceiptDO.java b/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/dal/dataobject/finance/ErpFinanceReceiptDO.java index d4180a888..46a559505 100644 --- a/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/dal/dataobject/finance/ErpFinanceReceiptDO.java +++ b/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/dal/dataobject/finance/ErpFinanceReceiptDO.java @@ -1,4 +1,86 @@ package cn.iocoder.yudao.module.erp.dal.dataobject.finance; -public class ErpFinanceReceiptDO { -} +import cn.iocoder.yudao.framework.mybatis.core.dataobject.BaseDO; +import cn.iocoder.yudao.module.erp.dal.dataobject.sale.ErpCustomerDO; +import com.baomidou.mybatisplus.annotation.KeySequence; +import com.baomidou.mybatisplus.annotation.TableId; +import com.baomidou.mybatisplus.annotation.TableName; +import lombok.*; + +import java.math.BigDecimal; +import java.time.LocalDateTime; + +/** + * ERP 收款单 DO + * + * @author 芋道源码 + */ +@TableName("erp_finance_receipt") +@KeySequence("erp_finance_receipt_seq") // 用于 Oracle、PostgreSQL、Kingbase、DB2、H2 数据库的主键自增。如果是 MySQL 等数据库,可不写。 +@Data +@EqualsAndHashCode(callSuper = true) +@ToString(callSuper = true) +@Builder +@NoArgsConstructor +@AllArgsConstructor +public class ErpFinanceReceiptDO extends BaseDO { + + /** + * 编号 + */ + @TableId + private Long id; + /** + * 收款单号 + */ + private String no; + /** + * 收款状态 + * + * 枚举 {@link cn.iocoder.yudao.module.erp.enums.ErpAuditStatus} + */ + private Integer status; + /** + * 收款时间 + */ + private LocalDateTime receiptTime; + /** + * 财务人员编号 + * + * 关联 AdminUserDO 的 id 字段 + */ + private Long financeUserId; + /** + * 客户编号 + * + * 关联 {@link ErpCustomerDO#getId()} + */ + private Long customerId; + /** + * 收款账户编号 + * + * 关联 {@link ErpAccountDO#getId()} + */ + private Long accountId; + + /** + * 合计价格,单位:元 + */ + private BigDecimal totalPrice; + /** + * 优惠金额,单位:元 + */ + private BigDecimal discountPrice; + /** + * 实付金额,单位:分 + * + * receiptPrice = totalPrice - discountPrice + */ + private BigDecimal receiptPrice; + + /** + * 备注 + */ + private String remark; + +} \ No newline at end of file diff --git a/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/dal/dataobject/finance/ErpFinanceReceiptItemDO.java b/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/dal/dataobject/finance/ErpFinanceReceiptItemDO.java new file mode 100644 index 000000000..575f9c76c --- /dev/null +++ b/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/dal/dataobject/finance/ErpFinanceReceiptItemDO.java @@ -0,0 +1,75 @@ +package cn.iocoder.yudao.module.erp.dal.dataobject.finance; + +import cn.iocoder.yudao.framework.mybatis.core.dataobject.BaseDO; +import cn.iocoder.yudao.module.erp.dal.dataobject.sale.ErpSaleOutDO; +import com.baomidou.mybatisplus.annotation.KeySequence; +import com.baomidou.mybatisplus.annotation.TableId; +import com.baomidou.mybatisplus.annotation.TableName; +import lombok.*; + +import java.math.BigDecimal; + +/** + * ERP 收款项 DO + * + * @author 芋道源码 + */ +@TableName("erp_finance_payment_item") +@KeySequence("erp_finance_payment_item_seq") // 用于 Oracle、PostgreSQL、Kingbase、DB2、H2 数据库的主键自增。如果是 MySQL 等数据库,可不写。 +@Data +@EqualsAndHashCode(callSuper = true) +@ToString(callSuper = true) +@Builder +@NoArgsConstructor +@AllArgsConstructor +public class ErpFinanceReceiptItemDO extends BaseDO { + + /** + * 入库项编号 + */ + @TableId + private Long id; + /** + * 收款单编号 + * + * 关联 {@link ErpFinanceReceiptDO#getId()} + */ + private Long receiptId; + + /** + * 业务类型 + * + * 枚举 {@link cn.iocoder.yudao.module.erp.enums.common.ErpBizTypeEnum} 的销售出库、退货 + */ + private Integer bizType; + /** + * 业务编号 + * + * 例如说:{@link ErpSaleOutDO#getId()} + */ + private Long bizId; + /** + * 业务单号 + * + * 例如说:{@link ErpSaleOutDO#getNo()} + */ + private String bizNo; + + /** + * 应收金额,单位:分 + */ + private BigDecimal totalPrice; + /** + * 已收金额,单位:分 + */ + private BigDecimal receiptedPrice; + /** + * 本次收款,单位:分 + */ + private BigDecimal receiptPrice; + /** + * 备注 + */ + private String remark; + +} \ No newline at end of file diff --git a/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/dal/mysql/finance/ErpFinanceReceiptItemMapper.java b/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/dal/mysql/finance/ErpFinanceReceiptItemMapper.java new file mode 100644 index 000000000..cb6082b0e --- /dev/null +++ b/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/dal/mysql/finance/ErpFinanceReceiptItemMapper.java @@ -0,0 +1,44 @@ +package cn.iocoder.yudao.module.erp.dal.mysql.finance; + +import cn.hutool.core.collection.CollUtil; +import cn.hutool.core.map.MapUtil; +import cn.iocoder.yudao.framework.mybatis.core.mapper.BaseMapperX; +import cn.iocoder.yudao.module.erp.dal.dataobject.finance.ErpFinanceReceiptItemDO; +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.List; +import java.util.Map; + +/** + * ERP 收款单项 Mapper + * + * @author 芋道源码 + */ +@Mapper +public interface ErpFinanceReceiptItemMapper extends BaseMapperX { + + default List selectListByReceiptId(Long receiptId) { + return selectList(ErpFinanceReceiptItemDO::getReceiptId, receiptId); + } + + default List selectListByReceiptIds(Collection receiptIds) { + return selectList(ErpFinanceReceiptItemDO::getReceiptId, receiptIds); + } + + default BigDecimal selectReceiptPriceSumByBizIdAndBizType(Long bizId, Integer bizType) { + // SQL sum 查询 + List> result = selectMaps(new QueryWrapper() + .select("SUM(receipt_price) AS receiptPriceSum") + .eq("biz_id", bizId) + .eq("biz_type", bizType)); + // 获得数量 + if (CollUtil.isEmpty(result)) { + return BigDecimal.ZERO; + } + return BigDecimal.valueOf(MapUtil.getDouble(result.get(0), "receiptPriceSum", 0D)); + } + +} \ No newline at end of file diff --git a/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/dal/mysql/finance/ErpFinanceReceiptMapper.java b/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/dal/mysql/finance/ErpFinanceReceiptMapper.java new file mode 100644 index 000000000..d895adea4 --- /dev/null +++ b/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/dal/mysql/finance/ErpFinanceReceiptMapper.java @@ -0,0 +1,48 @@ +package cn.iocoder.yudao.module.erp.dal.mysql.finance; + +import cn.iocoder.yudao.framework.common.pojo.PageResult; +import cn.iocoder.yudao.framework.mybatis.core.mapper.BaseMapperX; +import cn.iocoder.yudao.framework.mybatis.core.query.MPJLambdaWrapperX; +import cn.iocoder.yudao.module.erp.controller.admin.finance.vo.receipt.ErpFinanceReceiptPageReqVO; +import cn.iocoder.yudao.module.erp.dal.dataobject.finance.ErpFinanceReceiptDO; +import cn.iocoder.yudao.module.erp.dal.dataobject.finance.ErpFinanceReceiptItemDO; +import com.baomidou.mybatisplus.core.conditions.update.LambdaUpdateWrapper; +import org.apache.ibatis.annotations.Mapper; + +/** + * ERP 收款单 Mapper + * + * @author 芋道源码 + */ +@Mapper +public interface ErpFinanceReceiptMapper extends BaseMapperX { + + default PageResult selectPage(ErpFinanceReceiptPageReqVO reqVO) { + MPJLambdaWrapperX query = new MPJLambdaWrapperX() + .likeIfPresent(ErpFinanceReceiptDO::getNo, reqVO.getNo()) + .betweenIfPresent(ErpFinanceReceiptDO::getReceiptTime, reqVO.getReceiptTime()) + .eqIfPresent(ErpFinanceReceiptDO::getCustomerId, reqVO.getCustomerId()) + .eqIfPresent(ErpFinanceReceiptDO::getCreator, reqVO.getCreator()) + .eqIfPresent(ErpFinanceReceiptDO::getFinanceUserId, reqVO.getFinanceUserId()) + .eqIfPresent(ErpFinanceReceiptDO::getAccountId, reqVO.getAccountId()) + .eqIfPresent(ErpFinanceReceiptDO::getStatus, reqVO.getStatus()) + .likeIfPresent(ErpFinanceReceiptDO::getRemark, reqVO.getRemark()) + .orderByDesc(ErpFinanceReceiptDO::getId); + if (reqVO.getBizNo() != null) { + query.leftJoin(ErpFinanceReceiptItemDO.class, ErpFinanceReceiptItemDO::getReceiptId, ErpFinanceReceiptDO::getId) + .eq(reqVO.getBizNo() != null, ErpFinanceReceiptItemDO::getBizNo, reqVO.getBizNo()) + .groupBy(ErpFinanceReceiptDO::getId); // 避免 1 对多查询,产生相同的 1 + } + return selectJoinPage(reqVO, ErpFinanceReceiptDO.class, query); + } + + default int updateByIdAndStatus(Long id, Integer status, ErpFinanceReceiptDO updateObj) { + return update(updateObj, new LambdaUpdateWrapper() + .eq(ErpFinanceReceiptDO::getId, id).eq(ErpFinanceReceiptDO::getStatus, status)); + } + + default ErpFinanceReceiptDO selectByNo(String no) { + return selectOne(ErpFinanceReceiptDO::getNo, no); + } + +} \ No newline at end of file diff --git a/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/dal/redis/no/ErpNoRedisDAO.java b/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/dal/redis/no/ErpNoRedisDAO.java index d99990133..98fb8e8ff 100644 --- a/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/dal/redis/no/ErpNoRedisDAO.java +++ b/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/dal/redis/no/ErpNoRedisDAO.java @@ -68,6 +68,10 @@ public class ErpNoRedisDAO { * 付款单 {@link cn.iocoder.yudao.module.erp.dal.dataobject.finance.ErpFinancePaymentDO} */ public static final String FINANCE_PAYMENT_NO_PREFIX = "FKD"; + /** + * 收款单 {@link cn.iocoder.yudao.module.erp.dal.dataobject.finance.ErpFinanceReceiptDO} + */ + public static final String FINANCE_RECEIPT_NO_PREFIX = "SKD"; @Resource private StringRedisTemplate stringRedisTemplate; diff --git a/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/service/finance/ErpFinanceReceiptService.java b/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/service/finance/ErpFinanceReceiptService.java new file mode 100644 index 000000000..179648195 --- /dev/null +++ b/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/service/finance/ErpFinanceReceiptService.java @@ -0,0 +1,84 @@ +package cn.iocoder.yudao.module.erp.service.finance; + +import cn.iocoder.yudao.framework.common.pojo.PageResult; +import cn.iocoder.yudao.module.erp.controller.admin.finance.vo.receipt.ErpFinanceReceiptPageReqVO; +import cn.iocoder.yudao.module.erp.controller.admin.finance.vo.receipt.ErpFinanceReceiptSaveReqVO; +import cn.iocoder.yudao.module.erp.dal.dataobject.finance.ErpFinanceReceiptDO; +import cn.iocoder.yudao.module.erp.dal.dataobject.finance.ErpFinanceReceiptItemDO; +import jakarta.validation.Valid; + +import java.util.Collection; +import java.util.List; + +/** + * ERP 收款单 Service 接口 + * + * @author 芋道源码 + */ +public interface ErpFinanceReceiptService { + + /** + * 创建收款单 + * + * @param createReqVO 创建信息 + * @return 编号 + */ + Long createFinanceReceipt(@Valid ErpFinanceReceiptSaveReqVO createReqVO); + + /** + * 更新收款单 + * + * @param updateReqVO 更新信息 + */ + void updateFinanceReceipt(@Valid ErpFinanceReceiptSaveReqVO updateReqVO); + + /** + * 更新收款单的状态 + * + * @param id 编号 + * @param status 状态 + */ + void updateFinanceReceiptStatus(Long id, Integer status); + + /** + * 删除收款单 + * + * @param ids 编号数组 + */ + void deleteFinanceReceipt(List ids); + + /** + * 获得收款单 + * + * @param id 编号 + * @return 收款单 + */ + ErpFinanceReceiptDO getFinanceReceipt(Long id); + + /** + * 获得收款单分页 + * + * @param pageReqVO 分页查询 + * @return 收款单分页 + */ + PageResult getFinanceReceiptPage(ErpFinanceReceiptPageReqVO pageReqVO); + + // ==================== 收款单项 ==================== + + /** + * 获得收款单项列表 + * + * @param receiptId 收款单编号 + * @return 收款单项列表 + */ + List getFinanceReceiptItemListByReceiptId(Long receiptId); + + /** + * 获得收款单项 List + * + * @param receiptIds 收款单编号数组 + * @return 收款单项 List + */ + List getFinanceReceiptItemListByReceiptIds(Collection receiptIds); + +} \ No newline at end of file diff --git a/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/service/finance/ErpFinanceReceiptServiceImpl.java b/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/service/finance/ErpFinanceReceiptServiceImpl.java new file mode 100644 index 000000000..7fcad31eb --- /dev/null +++ b/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/service/finance/ErpFinanceReceiptServiceImpl.java @@ -0,0 +1,273 @@ +package cn.iocoder.yudao.module.erp.service.finance; + +import cn.hutool.core.collection.CollUtil; +import cn.hutool.core.lang.Assert; +import cn.hutool.core.util.ObjectUtil; +import cn.iocoder.yudao.framework.common.pojo.PageResult; +import cn.iocoder.yudao.framework.common.util.collection.CollectionUtils; +import cn.iocoder.yudao.framework.common.util.object.BeanUtils; +import cn.iocoder.yudao.module.erp.controller.admin.finance.vo.receipt.ErpFinanceReceiptPageReqVO; +import cn.iocoder.yudao.module.erp.controller.admin.finance.vo.receipt.ErpFinanceReceiptSaveReqVO; +import cn.iocoder.yudao.module.erp.dal.dataobject.finance.ErpFinanceReceiptDO; +import cn.iocoder.yudao.module.erp.dal.dataobject.finance.ErpFinanceReceiptItemDO; +import cn.iocoder.yudao.module.erp.dal.dataobject.sale.ErpSaleOutDO; +import cn.iocoder.yudao.module.erp.dal.dataobject.sale.ErpSaleReturnDO; +import cn.iocoder.yudao.module.erp.dal.mysql.finance.ErpFinanceReceiptItemMapper; +import cn.iocoder.yudao.module.erp.dal.mysql.finance.ErpFinanceReceiptMapper; +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.common.ErpBizTypeEnum; +import cn.iocoder.yudao.module.erp.service.sale.ErpCustomerService; +import cn.iocoder.yudao.module.erp.service.sale.ErpSaleOutService; +import cn.iocoder.yudao.module.erp.service.sale.ErpSaleReturnService; +import cn.iocoder.yudao.module.system.api.user.AdminUserApi; +import jakarta.annotation.Resource; +import org.springframework.stereotype.Service; +import org.springframework.transaction.annotation.Transactional; +import org.springframework.validation.annotation.Validated; + +import java.math.BigDecimal; +import java.util.Collection; +import java.util.Collections; +import java.util.List; + +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.module.erp.enums.ErrorCodeConstants.*; + +// TODO 芋艿:记录操作日志 + +/** + * ERP 收款单 Service 实现类 + * + * @author 芋道源码 + */ +@Service +@Validated +public class ErpFinanceReceiptServiceImpl implements ErpFinanceReceiptService { + + @Resource + private ErpFinanceReceiptMapper financeReceiptMapper; + @Resource + private ErpFinanceReceiptItemMapper financeReceiptItemMapper; + + @Resource + private ErpNoRedisDAO noRedisDAO; + + @Resource + private ErpCustomerService customerService; + @Resource + private ErpAccountService accountService; + @Resource + private ErpSaleOutService saleOutService; + @Resource + private ErpSaleReturnService saleReturnService; + + @Resource + private AdminUserApi adminUserApi; + + @Override + @Transactional(rollbackFor = Exception.class) + public Long createFinanceReceipt(ErpFinanceReceiptSaveReqVO createReqVO) { + // 1.1 校验订单项的有效性 + List receiptItems = validateFinanceReceiptItems( + createReqVO.getCustomerId(), createReqVO.getItems()); + // 1.2 校验客户 + customerService.validateCustomer(createReqVO.getCustomerId()); + // 1.3 校验结算账户 + if (createReqVO.getAccountId() != null) { + accountService.validateAccount(createReqVO.getAccountId()); + } + // 1.4 校验财务人员 + if (createReqVO.getFinanceUserId() != null) { + adminUserApi.validateUser(createReqVO.getFinanceUserId()); + } + // 1.5 生成收款单号,并校验唯一性 + String no = noRedisDAO.generate(ErpNoRedisDAO.FINANCE_RECEIPT_NO_PREFIX); + if (financeReceiptMapper.selectByNo(no) != null) { + throw exception(FINANCE_RECEIPT_NO_EXISTS); + } + + // 2.1 插入收款单 + ErpFinanceReceiptDO receipt = BeanUtils.toBean(createReqVO, ErpFinanceReceiptDO.class, in -> in + .setNo(no).setStatus(ErpAuditStatus.PROCESS.getStatus())); + calculateTotalPrice(receipt, receiptItems); + financeReceiptMapper.insert(receipt); + // 2.2 插入收款单项 + receiptItems.forEach(o -> o.setReceiptId(receipt.getId())); + financeReceiptItemMapper.insertBatch(receiptItems); + return receipt.getId(); + } + + @Override + @Transactional(rollbackFor = Exception.class) + public void updateFinanceReceipt(ErpFinanceReceiptSaveReqVO updateReqVO) { + // 1.1 校验存在 + ErpFinanceReceiptDO receipt = validateFinanceReceiptExists(updateReqVO.getId()); + if (ErpAuditStatus.APPROVE.getStatus().equals(receipt.getStatus())) { + throw exception(FINANCE_RECEIPT_UPDATE_FAIL_APPROVE, receipt.getNo()); + } + // 1.2 校验客户 + customerService.validateCustomer(updateReqVO.getCustomerId()); + // 1.3 校验结算账户 + if (updateReqVO.getAccountId() != null) { + accountService.validateAccount(updateReqVO.getAccountId()); + } + // 1.4 校验财务人员 + if (updateReqVO.getFinanceUserId() != null) { + adminUserApi.validateUser(updateReqVO.getFinanceUserId()); + } + // 1.5 校验收款单项的有效性 + List receiptItems = validateFinanceReceiptItems( + updateReqVO.getCustomerId(), updateReqVO.getItems()); + + // 2.1 更新收款单 + ErpFinanceReceiptDO updateObj = BeanUtils.toBean(updateReqVO, ErpFinanceReceiptDO.class); + calculateTotalPrice(updateObj, receiptItems); + financeReceiptMapper.updateById(updateObj); + // 2.2 更新收款单项 + updateFinanceReceiptItemList(updateReqVO.getId(), receiptItems); + + // 3. 更新销售出库、退货的收款金额情况 + updateSalePrice(receiptItems); + } + + private void calculateTotalPrice(ErpFinanceReceiptDO receipt, List receiptItems) { + receipt.setTotalPrice(getSumValue(receiptItems, ErpFinanceReceiptItemDO::getReceiptPrice, BigDecimal::add, BigDecimal.ZERO)); + receipt.setReceiptPrice(receipt.getTotalPrice().subtract(receipt.getDiscountPrice())); + } + + @Override + @Transactional(rollbackFor = Exception.class) + public void updateFinanceReceiptStatus(Long id, Integer status) { + boolean approve = ErpAuditStatus.APPROVE.getStatus().equals(status); + // 1.1 校验存在 + ErpFinanceReceiptDO receipt = validateFinanceReceiptExists(id); + // 1.2 校验状态 + if (receipt.getStatus().equals(status)) { + throw exception(approve ? FINANCE_RECEIPT_APPROVE_FAIL : FINANCE_RECEIPT_PROCESS_FAIL); + } + + // 2. 更新状态 + int updateCount = financeReceiptMapper.updateByIdAndStatus(id, receipt.getStatus(), + new ErpFinanceReceiptDO().setStatus(status)); + if (updateCount == 0) { + throw exception(approve ? FINANCE_RECEIPT_APPROVE_FAIL : FINANCE_RECEIPT_PROCESS_FAIL); + } + } + + private List validateFinanceReceiptItems( + Long customerId, + List list) { + return convertList(list, o -> BeanUtils.toBean(o, ErpFinanceReceiptItemDO.class, item -> { + if (ObjectUtil.equal(item.getBizType(), ErpBizTypeEnum.SALE_OUT.getType())) { + ErpSaleOutDO saleOut = saleOutService.validateSaleOut(item.getBizId()); + Assert.equals(saleOut.getCustomerId(), customerId, "客户必须相同"); + item.setTotalPrice(saleOut.getTotalPrice()).setBizNo(saleOut.getNo()); + } else if (ObjectUtil.equal(item.getBizType(), ErpBizTypeEnum.SALE_RETURN.getType())) { + ErpSaleReturnDO saleReturn = saleReturnService.validateSaleReturn(item.getBizId()); + Assert.equals(saleReturn.getCustomerId(), customerId, "客户必须相同"); + item.setTotalPrice(saleReturn.getTotalPrice().negate()).setBizNo(saleReturn.getNo()); + } else { + throw new IllegalArgumentException("业务类型不正确:" + item.getBizType()); + } + })); + } + + private void updateFinanceReceiptItemList(Long id, List newList) { + // 第一步,对比新老数据,获得添加、修改、删除的列表 + List oldList = financeReceiptItemMapper.selectListByReceiptId(id); + List> diffList = diffList(oldList, newList, // id 不同,就认为是不同的记录 + (oldVal, newVal) -> oldVal.getId().equals(newVal.getId())); + + // 第二步,批量添加、修改、删除 + if (CollUtil.isNotEmpty(diffList.get(0))) { + diffList.get(0).forEach(o -> o.setReceiptId(id)); + financeReceiptItemMapper.insertBatch(diffList.get(0)); + } + if (CollUtil.isNotEmpty(diffList.get(1))) { + financeReceiptItemMapper.updateBatch(diffList.get(1)); + } + if (CollUtil.isNotEmpty(diffList.get(2))) { + financeReceiptItemMapper.deleteBatchIds(convertList(diffList.get(2), ErpFinanceReceiptItemDO::getId)); + } + + // 第三步,更新销售出库、退货的收款金额情况 + updateSalePrice(CollectionUtils.newArrayList(diffList)); + } + + private void updateSalePrice(List receiptItems) { + receiptItems.forEach(receiptItem -> { + BigDecimal totalReceiptPrice = financeReceiptItemMapper.selectReceiptPriceSumByBizIdAndBizType( + receiptItem.getBizId(), receiptItem.getBizType()); + if (ErpBizTypeEnum.SALE_OUT.getType().equals(receiptItem.getBizType())) { + saleOutService.updateSaleInReceiptPrice(receiptItem.getBizId(), totalReceiptPrice); + } else if (ErpBizTypeEnum.SALE_RETURN.getType().equals(receiptItem.getBizType())) { + saleReturnService.updateSaleReturnRefundPrice(receiptItem.getBizId(), totalReceiptPrice.negate()); + } else { + throw new IllegalArgumentException("业务类型不正确:" + receiptItem.getBizType()); + } + }); + } + + @Override + @Transactional(rollbackFor = Exception.class) + public void deleteFinanceReceipt(List ids) { + // 1. 校验不处于已审批 + List receipts = financeReceiptMapper.selectBatchIds(ids); + if (CollUtil.isEmpty(receipts)) { + return; + } + receipts.forEach(receipt -> { + if (ErpAuditStatus.APPROVE.getStatus().equals(receipt.getStatus())) { + throw exception(FINANCE_RECEIPT_DELETE_FAIL_APPROVE, receipt.getNo()); + } + }); + + // 2. 遍历删除,并记录操作日志 + receipts.forEach(receipt -> { + // 2.1 删除收款单 + financeReceiptMapper.deleteById(receipt.getId()); + // 2.2 删除收款单项 + List receiptItems = financeReceiptItemMapper.selectListByReceiptId(receipt.getId()); + financeReceiptItemMapper.deleteBatchIds(convertSet(receiptItems, ErpFinanceReceiptItemDO::getId)); + + // 2.3 更新销售出库、退货的收款金额情况 + updateSalePrice(receiptItems); + }); + } + + private ErpFinanceReceiptDO validateFinanceReceiptExists(Long id) { + ErpFinanceReceiptDO receipt = financeReceiptMapper.selectById(id); + if (receipt == null) { + throw exception(FINANCE_RECEIPT_NOT_EXISTS); + } + return receipt; + } + + @Override + public ErpFinanceReceiptDO getFinanceReceipt(Long id) { + return financeReceiptMapper.selectById(id); + } + + @Override + public PageResult getFinanceReceiptPage(ErpFinanceReceiptPageReqVO pageReqVO) { + return financeReceiptMapper.selectPage(pageReqVO); + } + + // ==================== 收款单项 ==================== + + @Override + public List getFinanceReceiptItemListByReceiptId(Long receiptId) { + return financeReceiptItemMapper.selectListByReceiptId(receiptId); + } + + @Override + public List getFinanceReceiptItemListByReceiptIds(Collection receiptIds) { + if (CollUtil.isEmpty(receiptIds)) { + return Collections.emptyList(); + } + return financeReceiptItemMapper.selectListByReceiptIds(receiptIds); + } + +} \ No newline at end of file diff --git a/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/service/purchase/ErpPurchaseInServiceImpl.java b/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/service/purchase/ErpPurchaseInServiceImpl.java index b2ac729ed..5d6ad6230 100644 --- a/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/service/purchase/ErpPurchaseInServiceImpl.java +++ b/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/service/purchase/ErpPurchaseInServiceImpl.java @@ -194,7 +194,7 @@ public class ErpPurchaseInServiceImpl implements ErpPurchaseInService { return; } if (paymentPrice.compareTo(purchaseIn.getTotalPrice()) > 0) { - throw exception(PURCHASE_IN_FAIL_PAYMENT_PRICE_EXCEED, purchaseIn.getTotalPrice(), paymentPrice); + throw exception(PURCHASE_IN_FAIL_PAYMENT_PRICE_EXCEED, paymentPrice, purchaseIn.getTotalPrice()); } purchaseInMapper.updateById(new ErpPurchaseInDO().setId(id).setPaymentPrice(paymentPrice)); } diff --git a/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/service/purchase/ErpPurchaseReturnServiceImpl.java b/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/service/purchase/ErpPurchaseReturnServiceImpl.java index 109916249..05960e896 100644 --- a/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/service/purchase/ErpPurchaseReturnServiceImpl.java +++ b/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/service/purchase/ErpPurchaseReturnServiceImpl.java @@ -190,7 +190,7 @@ public class ErpPurchaseReturnServiceImpl implements ErpPurchaseReturnService { return; } if (refundPrice.compareTo(purchaseReturn.getTotalPrice()) > 0) { - throw exception(PURCHASE_RETURN_FAIL_REFUND_PRICE_EXCEED, purchaseReturn.getTotalPrice(), refundPrice); + throw exception(PURCHASE_RETURN_FAIL_REFUND_PRICE_EXCEED, refundPrice, purchaseReturn.getTotalPrice()); } purchaseReturnMapper.updateById(new ErpPurchaseReturnDO().setId(id).setRefundPrice(refundPrice)); } diff --git a/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/service/sale/ErpSaleOutService.java b/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/service/sale/ErpSaleOutService.java index 60ea7912f..616f77837 100644 --- a/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/service/sale/ErpSaleOutService.java +++ b/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/service/sale/ErpSaleOutService.java @@ -7,6 +7,7 @@ import cn.iocoder.yudao.module.erp.dal.dataobject.sale.ErpSaleOutDO; import cn.iocoder.yudao.module.erp.dal.dataobject.sale.ErpSaleOutItemDO; import jakarta.validation.Valid; +import java.math.BigDecimal; import java.util.Collection; import java.util.List; @@ -40,6 +41,14 @@ public interface ErpSaleOutService { */ void updateSaleOutStatus(Long id, Integer status); + /** + * 更新销售出库的收款金额 + * + * @param id 编号 + * @param receiptPrice 收款金额 + */ + void updateSaleInReceiptPrice(Long id, BigDecimal receiptPrice); + /** * 删除销售出库 * @@ -55,6 +64,14 @@ public interface ErpSaleOutService { */ ErpSaleOutDO getSaleOut(Long id); + /** + * 校验销售出库,已经审核通过 + * + * @param id 编号 + * @return 销售出库 + */ + ErpSaleOutDO validateSaleOut(Long id); + /** * 获得销售出库分页 * @@ -81,4 +98,5 @@ public interface ErpSaleOutService { */ List getSaleOutItemListByOutIds(Collection outIds); + } \ No newline at end of file diff --git a/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/service/sale/ErpSaleOutServiceImpl.java b/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/service/sale/ErpSaleOutServiceImpl.java index 4338c9e83..02cac9c13 100644 --- a/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/service/sale/ErpSaleOutServiceImpl.java +++ b/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/service/sale/ErpSaleOutServiceImpl.java @@ -171,6 +171,10 @@ public class ErpSaleOutServiceImpl implements ErpSaleOutService { if (saleOut.getStatus().equals(status)) { throw exception(approve ? SALE_OUT_APPROVE_FAIL : SALE_OUT_PROCESS_FAIL); } + // 1.3 校验已退款 + if (approve && saleOut.getReceiptPrice().compareTo(BigDecimal.ZERO) > 0) { + throw exception(SALE_OUT_PROCESS_FAIL_EXISTS_RECEIPT); + } // 2. 更新状态 int updateCount = saleOutMapper.updateByIdAndStatus(id, saleOut.getStatus(), @@ -191,6 +195,18 @@ public class ErpSaleOutServiceImpl implements ErpSaleOutService { }); } + @Override + public void updateSaleInReceiptPrice(Long id, BigDecimal receiptPrice) { + ErpSaleOutDO saleOut = saleOutMapper.selectById(id); + if (saleOut.getReceiptPrice().equals(receiptPrice)) { + return; + } + if (receiptPrice.compareTo(saleOut.getTotalPrice()) > 0) { + throw exception(SALE_OUT_FAIL_RECEIPT_PRICE_EXCEED, receiptPrice, saleOut.getTotalPrice()); + } + saleOutMapper.updateById(new ErpSaleOutDO().setId(id).setReceiptPrice(receiptPrice)); + } + private List validateSaleOutItems(List list) { // 1. 校验产品存在 List productList = productService.validProductList( @@ -268,6 +284,15 @@ public class ErpSaleOutServiceImpl implements ErpSaleOutService { return saleOutMapper.selectById(id); } + @Override + public ErpSaleOutDO validateSaleOut(Long id) { + ErpSaleOutDO saleOut = validateSaleOut(id); + if (ObjectUtil.notEqual(saleOut.getStatus(), ErpAuditStatus.APPROVE.getStatus())) { + throw exception(SALE_OUT_NOT_APPROVE); + } + return saleOut; + } + @Override public PageResult getSaleOutPage(ErpSaleOutPageReqVO pageReqVO) { return saleOutMapper.selectPage(pageReqVO); diff --git a/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/service/sale/ErpSaleReturnService.java b/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/service/sale/ErpSaleReturnService.java index 2186bba54..bc192a17c 100644 --- a/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/service/sale/ErpSaleReturnService.java +++ b/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/service/sale/ErpSaleReturnService.java @@ -7,6 +7,7 @@ import cn.iocoder.yudao.module.erp.dal.dataobject.sale.ErpSaleReturnDO; import cn.iocoder.yudao.module.erp.dal.dataobject.sale.ErpSaleReturnItemDO; import jakarta.validation.Valid; +import java.math.BigDecimal; import java.util.Collection; import java.util.List; @@ -40,6 +41,14 @@ public interface ErpSaleReturnService { */ void updateSaleReturnStatus(Long id, Integer status); + /** + * 更新销售退货的退款金额 + * + * @param id 编号 + * @param refundPrice 退款金额 + */ + void updateSaleReturnRefundPrice(Long id, BigDecimal refundPrice); + /** * 删除销售退货 * @@ -55,6 +64,14 @@ public interface ErpSaleReturnService { */ ErpSaleReturnDO getSaleReturn(Long id); + /** + * 校验销售退货,已经审核通过 + * + * @param id 编号 + * @return 销售退货 + */ + ErpSaleReturnDO validateSaleReturn(Long id); + /** * 获得销售退货分页 * diff --git a/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/service/sale/ErpSaleReturnServiceImpl.java b/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/service/sale/ErpSaleReturnServiceImpl.java index 0c5313256..85d798e72 100644 --- a/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/service/sale/ErpSaleReturnServiceImpl.java +++ b/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/service/sale/ErpSaleReturnServiceImpl.java @@ -171,6 +171,10 @@ public class ErpSaleReturnServiceImpl implements ErpSaleReturnService { if (saleReturn.getStatus().equals(status)) { throw exception(approve ? SALE_RETURN_APPROVE_FAIL : SALE_RETURN_PROCESS_FAIL); } + // 1.3 校验已退款 + if (approve && saleReturn.getRefundPrice().compareTo(BigDecimal.ZERO) > 0) { + throw exception(SALE_RETURN_PROCESS_FAIL_EXISTS_REFUND); + } // 2. 更新状态 int updateCount = saleReturnMapper.updateByIdAndStatus(id, saleReturn.getStatus(), @@ -191,6 +195,18 @@ public class ErpSaleReturnServiceImpl implements ErpSaleReturnService { }); } + @Override + public void updateSaleReturnRefundPrice(Long id, BigDecimal refundPrice) { + ErpSaleReturnDO saleReturn = saleReturnMapper.selectById(id); + if (saleReturn.getRefundPrice().equals(refundPrice)) { + return; + } + if (refundPrice.compareTo(saleReturn.getTotalPrice()) > 0) { + throw exception(SALE_RETURN_FAIL_REFUND_PRICE_EXCEED, refundPrice, saleReturn.getTotalPrice()); + } + saleReturnMapper.updateById(new ErpSaleReturnDO().setId(id).setRefundPrice(refundPrice)); + } + private List validateSaleReturnItems(List list) { // 1. 校验产品存在 List productList = productService.validProductList( @@ -268,6 +284,15 @@ public class ErpSaleReturnServiceImpl implements ErpSaleReturnService { return saleReturnMapper.selectById(id); } + @Override + public ErpSaleReturnDO validateSaleReturn(Long id) { + ErpSaleReturnDO saleReturn = validateSaleReturnExists(id); + if (ObjectUtil.notEqual(saleReturn.getStatus(), ErpAuditStatus.APPROVE.getStatus())) { + throw exception(SALE_RETURN_NOT_APPROVE); + } + return saleReturn; + } + @Override public PageResult getSaleReturnPage(ErpSaleReturnPageReqVO pageReqVO) { return saleReturnMapper.selectPage(pageReqVO); From eefd787de6dc731adc36cf1a4a845578cae53fea Mon Sep 17 00:00:00 2001 From: YunaiV Date: Fri, 16 Feb 2024 08:13:21 +0800 Subject: [PATCH 111/119] =?UTF-8?q?=E2=9C=A8=20ERP=EF=BC=9A=E5=88=9D?= =?UTF-8?q?=E5=A7=8B=E5=8C=96=20receipt=20=E6=94=B6=E6=AC=BE=E5=8D=95?= =?UTF-8?q?=E7=9A=84=E9=80=BB=E8=BE=91=20100%?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../erp/dal/dataobject/finance/ErpFinanceReceiptItemDO.java | 4 ++-- .../yudao/module/erp/dal/mysql/sale/ErpSaleOutMapper.java | 4 +++- .../module/erp/dal/mysql/sale/ErpSaleReturnMapper.java | 5 ++++- .../erp/service/finance/ErpFinancePaymentServiceImpl.java | 6 +++--- .../erp/service/finance/ErpFinanceReceiptServiceImpl.java | 6 +++--- .../module/erp/service/sale/ErpSaleOutServiceImpl.java | 2 +- 6 files changed, 16 insertions(+), 11 deletions(-) diff --git a/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/dal/dataobject/finance/ErpFinanceReceiptItemDO.java b/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/dal/dataobject/finance/ErpFinanceReceiptItemDO.java index 575f9c76c..87f051d5c 100644 --- a/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/dal/dataobject/finance/ErpFinanceReceiptItemDO.java +++ b/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/dal/dataobject/finance/ErpFinanceReceiptItemDO.java @@ -14,8 +14,8 @@ import java.math.BigDecimal; * * @author 芋道源码 */ -@TableName("erp_finance_payment_item") -@KeySequence("erp_finance_payment_item_seq") // 用于 Oracle、PostgreSQL、Kingbase、DB2、H2 数据库的主键自增。如果是 MySQL 等数据库,可不写。 +@TableName("erp_finance_receipt_item") +@KeySequence("erp_finance_receipt_item_seq") // 用于 Oracle、PostgreSQL、Kingbase、DB2、H2 数据库的主键自增。如果是 MySQL 等数据库,可不写。 @Data @EqualsAndHashCode(callSuper = true) @ToString(callSuper = true) diff --git a/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/dal/mysql/sale/ErpSaleOutMapper.java b/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/dal/mysql/sale/ErpSaleOutMapper.java index d5b640b4c..128913fcd 100644 --- a/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/dal/mysql/sale/ErpSaleOutMapper.java +++ b/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/dal/mysql/sale/ErpSaleOutMapper.java @@ -7,6 +7,7 @@ import cn.iocoder.yudao.framework.mybatis.core.query.MPJLambdaWrapperX; import cn.iocoder.yudao.module.erp.controller.admin.sale.vo.out.ErpSaleOutPageReqVO; 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.enums.ErpAuditStatus; import com.baomidou.mybatisplus.core.conditions.update.LambdaUpdateWrapper; import org.apache.ibatis.annotations.Mapper; @@ -41,7 +42,8 @@ public interface ErpSaleOutMapper extends BaseMapperX { query.apply("t.receipt_price = t.total_price"); } if (Boolean.TRUE.equals(reqVO.getReceiptEnable())) { - query.apply("t.receipt_price < t.total_price"); + query.eq(ErpSaleOutDO::getStatus, ErpAuditStatus.APPROVE.getStatus()) + .apply("t.receipt_price < t.total_price"); } if (reqVO.getWarehouseId() != null || reqVO.getProductId() != null) { query.leftJoin(ErpSaleOutItemDO.class, ErpSaleOutItemDO::getOutId, ErpSaleOutDO::getId) diff --git a/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/dal/mysql/sale/ErpSaleReturnMapper.java b/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/dal/mysql/sale/ErpSaleReturnMapper.java index 8efe761b7..867b45499 100644 --- a/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/dal/mysql/sale/ErpSaleReturnMapper.java +++ b/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/dal/mysql/sale/ErpSaleReturnMapper.java @@ -5,8 +5,10 @@ import cn.iocoder.yudao.framework.common.pojo.PageResult; import cn.iocoder.yudao.framework.mybatis.core.mapper.BaseMapperX; import cn.iocoder.yudao.framework.mybatis.core.query.MPJLambdaWrapperX; import cn.iocoder.yudao.module.erp.controller.admin.sale.vo.returns.ErpSaleReturnPageReqVO; +import cn.iocoder.yudao.module.erp.dal.dataobject.sale.ErpSaleOutDO; import cn.iocoder.yudao.module.erp.dal.dataobject.sale.ErpSaleReturnDO; import cn.iocoder.yudao.module.erp.dal.dataobject.sale.ErpSaleReturnItemDO; +import cn.iocoder.yudao.module.erp.enums.ErpAuditStatus; import com.baomidou.mybatisplus.core.conditions.update.LambdaUpdateWrapper; import org.apache.ibatis.annotations.Mapper; @@ -41,7 +43,8 @@ public interface ErpSaleReturnMapper extends BaseMapperX { query.apply("t.refund_price = t.total_price"); } if (Boolean.TRUE.equals(reqVO.getRefundEnable())) { - query.apply("t.refund_price < t.total_price"); + query.eq(ErpSaleOutDO::getStatus, ErpAuditStatus.APPROVE.getStatus()) + .apply("t.refund_price < t.total_price"); } if (reqVO.getWarehouseId() != null || reqVO.getProductId() != null) { query.leftJoin(ErpSaleReturnItemDO.class, ErpSaleReturnItemDO::getReturnId, ErpSaleReturnDO::getId) diff --git a/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/service/finance/ErpFinancePaymentServiceImpl.java b/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/service/finance/ErpFinancePaymentServiceImpl.java index 68121763c..ab94dad53 100644 --- a/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/service/finance/ErpFinancePaymentServiceImpl.java +++ b/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/service/finance/ErpFinancePaymentServiceImpl.java @@ -96,6 +96,9 @@ public class ErpFinancePaymentServiceImpl implements ErpFinancePaymentService { // 2.2 插入付款单项 paymentItems.forEach(o -> o.setPaymentId(payment.getId())); financePaymentItemMapper.insertBatch(paymentItems); + + // 3. 更新采购入库、退货的付款金额情况 + updatePurchasePrice(paymentItems); return payment.getId(); } @@ -127,9 +130,6 @@ public class ErpFinancePaymentServiceImpl implements ErpFinancePaymentService { financePaymentMapper.updateById(updateObj); // 2.2 更新付款单项 updateFinancePaymentItemList(updateReqVO.getId(), paymentItems); - - // 3. 更新采购入库、退货的付款金额情况 - updatePurchasePrice(paymentItems); } private void calculateTotalPrice(ErpFinancePaymentDO payment, List paymentItems) { diff --git a/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/service/finance/ErpFinanceReceiptServiceImpl.java b/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/service/finance/ErpFinanceReceiptServiceImpl.java index 7fcad31eb..42b81d876 100644 --- a/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/service/finance/ErpFinanceReceiptServiceImpl.java +++ b/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/service/finance/ErpFinanceReceiptServiceImpl.java @@ -96,6 +96,9 @@ public class ErpFinanceReceiptServiceImpl implements ErpFinanceReceiptService { // 2.2 插入收款单项 receiptItems.forEach(o -> o.setReceiptId(receipt.getId())); financeReceiptItemMapper.insertBatch(receiptItems); + + // 3. 更新销售出库、退货的收款金额情况 + updateSalePrice(receiptItems); return receipt.getId(); } @@ -127,9 +130,6 @@ public class ErpFinanceReceiptServiceImpl implements ErpFinanceReceiptService { financeReceiptMapper.updateById(updateObj); // 2.2 更新收款单项 updateFinanceReceiptItemList(updateReqVO.getId(), receiptItems); - - // 3. 更新销售出库、退货的收款金额情况 - updateSalePrice(receiptItems); } private void calculateTotalPrice(ErpFinanceReceiptDO receipt, List receiptItems) { diff --git a/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/service/sale/ErpSaleOutServiceImpl.java b/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/service/sale/ErpSaleOutServiceImpl.java index 02cac9c13..d930c16bf 100644 --- a/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/service/sale/ErpSaleOutServiceImpl.java +++ b/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/service/sale/ErpSaleOutServiceImpl.java @@ -286,7 +286,7 @@ public class ErpSaleOutServiceImpl implements ErpSaleOutService { @Override public ErpSaleOutDO validateSaleOut(Long id) { - ErpSaleOutDO saleOut = validateSaleOut(id); + ErpSaleOutDO saleOut = validateSaleOutExists(id); if (ObjectUtil.notEqual(saleOut.getStatus(), ErpAuditStatus.APPROVE.getStatus())) { throw exception(SALE_OUT_NOT_APPROVE); } From 94153cb59efafd656e0fa0e68eb81e24bb4462a2 Mon Sep 17 00:00:00 2001 From: YunaiV Date: Sat, 17 Feb 2024 10:10:09 +0800 Subject: [PATCH 112/119] =?UTF-8?q?=E2=9C=A8=20=E5=A2=9E=E5=8A=A0=20ERP=20?= =?UTF-8?q?=E7=B3=BB=E7=BB=9F=E7=9A=84=E4=BB=8B=E7=BB=8D?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .image/common/erp-feature.png | Bin 0 -> 47016 bytes README.md | 36 +++++++++++------- .../banner/core/BannerApplicationRunner.java | 4 ++ .../core/handler/GlobalExceptionHandler.java | 8 +++- .../module/erp/framework/package-info.java | 6 +++ .../web/config/ErpWebConfiguration.java | 24 ++++++++++++ .../erp/framework/web/package-info.java | 4 ++ yudao-server/pom.xml | 10 ++--- .../server/controller/DefaultController.java | 6 +++ 9 files changed, 79 insertions(+), 19 deletions(-) create mode 100644 .image/common/erp-feature.png create mode 100644 yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/framework/package-info.java create mode 100644 yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/framework/web/config/ErpWebConfiguration.java create mode 100644 yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/framework/web/package-info.java diff --git a/.image/common/erp-feature.png b/.image/common/erp-feature.png new file mode 100644 index 0000000000000000000000000000000000000000..d30b30eed9d4e072c61ebf3bb63809b2b5593078 GIT binary patch literal 47016 zcmeFZXHb+)7dEJ(0wN%wNE#5yIp-uQ3_0g0IfD!Wk|ijThA25GLmmOi86<}xNS3U? z5QZ=khav8b&-?B^-?u-uws!Z&R((~}T|>|5?$do@pT6#i&`<*t-lMvA5n7XL-MUIK5EYcD2M~?$5MG&CV*Bc<_47VuR;Bx$VSd*vgvqhK2y2#3Vg$bDx~4LrtD@k$PbPYj#mK~@ z8AtH}zv-F}ch6|cu0+WXihisLKrgH7zV*U1e3q#q1a~4VQeP8XuWefXG3+sqS!xu; z2SqDVGP0HsU{6+#{|;dDhOa{r^ooKxKz9As?FiWQMpxGmmG(j5rTx#yKy!cnHGlYpf4MXTniJixMMtJ~{ak4TnweLw zwSYPE`q|?NG^_Ny2UJ8w^!gdS1vIBdU(c2L`mb6{UpG@;&&B)u;s1w>xWj4k85fh2 z>hlv4UbmZc@yh<2iS8Ik(*CP*#vIP4Y<6v9=J zVx3y2BmTYKdQE7;@RXiqULuXe+&Sr*P(o4?Ck8E(1lKR`uUKKR=^a)utZ39 zKt#t@I(Nzb2|g9)|2|UjcWyr8fq^imH?`GfkEQTbo1ZiT=5%Wr~ z#-2mx@7Sz;^;uh(v+d|&LrL9`r(agJEg1ynD(7e7H}-B z@#=S|cHwaIv7hfT<*SoCeM%wQ5M+(*z*SvjX4~u0^Qm_;LBBrR$UMj@kMw7-8PH8Y z32iB@6qM$@D0Jnw{)v|+9#Ft(*!W!7Wsx11NWQ;YIfYSLda>EK&9KV0dC`c%QLjpDxw=blAly0a#cziTb6=mQxzue=|j`9|1z_G#VnvUB@Y zofkUd<4<~GI%yq~ra)6Kx!vR(l;B}N(PhZXCM0NKcfI@MAw@k(#L!Wr&04 z>E*QBPiyXDU@l)QWyL_zU{;-m>UihJ(e_ZyHOm~6`nQTPCcpiL%)k9K+3x!v#PSr( zhQBVwF;3Y9%oh=|mSSt5MFwihLrR_2h}IMJXHKl*1&uV{i7c7EPbuDEvMth{%-~0z(S)J(7+eZGhT3CLq?Kbvjbwg~d|+*ZvI66SASTHvdi;@UDO z7YIXWwuW@)KhH05Q|U$r{nX!1tR)@(Tn zZb$JPu*w?Mvt9(1590k#Ochb?*f?Bx`+uCvoO>$gz=VB6qSz`tan9$UWc0E(b7C>H zty|qwY8rGg|Fxz;R9CEHNg(LUGD?U+K1Sg2SqwM0VV^wVsd-AERpcjD__5zFjignc zZLIXKa5_LoZA&OO=swLgEfzS5UQJMHu{L_Ova3GiFL4u}8s zb^EpbqhHtvxgc-+lmnv^fe z({IyALnaDo6jh{_nK0QTUq%k5sA%b13PN1FV)wf;86 zTBXU2!>IMOQsgv|X`UVWlK<@n9;Jvy!eFXc?}6JDf2{A)vd!>A#(z0k#2hmim*pH2 zgT%u~cd&a!t~4+rFUb#j^Vl2=lbckVpn*%{B`$uHg4XrR(@@j=)gbnw9Wjr`Nii9< zr_JiIGQjq^49y;CeSVFvYgQ@`I`UR^I^L1_ycqrn%`bjH&Y7g^G^Kp_o58UkZCvNd z5v&j^s*=M84j5q`GHRJ><{T zCaQ!2<1JwGHgpBfzQ_8oX%2=0(4WOy-FdE|%#o3wO8VROAMNkL-prsGg^!c5r8lem zFw#eh(}rF2I)-iTRaRSU|I!yGPGldn9=jH+BotiGhmG2kqR4N*g+s=ou01}G^fT#7 zZ8%%PE-*tR*!5P1gt-MJzjIz!uMB@1*W^p*rQ%~guX)BJnkf3O#%+5wGpzwB4kP6u z$oj&O%q-X1ou3Yi`TtWCY*{_tDi1j>fLQwz@48JCDH7DQye!_||6|eo+q66vq1ml8 z$ppceb+_W+u1*wJq1;jzfAxI*$y2r?OGF!4+ox~zZWT))KQ>q%1QPe&`JZRF-aqkU zb;Za_g?RtQO2+OyHX)p&%Ko5vNIWCZNgpSHAxf={q!`uZJ`THgh9aweQH$p5)vk zXAOSYYp&%-Tu|UMaG;=bXyM`hW7Yo0kKc}MBqVc_9;VRKV>)Nw`~Z#EF?Miy1`bc# z-(;!B@Sj{EET1M#p;h?DwShY3TBTeYC^+k`sxG$fsm4*IeR$*mURq@-#3t8t6fQxeXW(qaGQYN8WFGG zV!L0xDQ(jp2b-%y7mXnFKc{;8I1gx^{trs1EGB;ZzWL*2lsvhjPyO^ciG!LW0b-9WMs6m*oDi9!72R>1tk6-nTp1+Tpl*Ya9eVMiP8B(LpcTF35hQBMh=8+}+4TxCmX7 z4$+Yaw=Z36B_J8+QhbnuhD+2VD2NVBPb!Vi$(1SDSTT-rm~K zA|rF_k39O(X0gd%XTJm7UM%GO|01UZ*7W~8xrNb4`5mhOhlU{@3kv3#;D?&m33kdq zW;X}{vinzo_?^5C_XB1Aik9j6X+mil_xd^JWY6j-)gpD8AW#I@NTs+RGvAl4GkxM~ z!RYs}f;W!tZtvNqR^zs%0O=VU?=9u)REg$qZvKf+z4QfIL~S29*(Cb@nQKQQ+e2|P zwR(9~4E`#dlNGI0$dljJ#2h~>a5F8wwxe%l;h$vPP*Fq{{U7N%5H~mWgbBv3gY@Oa z83es3Mfw!F{V}Fvp%FQg1_7@tLpIsy^0{yI)Z!>uySaAiB* zBSkkm`{{o8^(n4-*pJ`DdQa9wipvbvB_$5ZU8#P?xe3BQF#bCNxcGOk%yp|e2T|k~f%G1c}C6Ql;NQ*}b35H1u_M(q`p5L3AFR(Z8%g@iW zmOe#?Og{$3E4yZZtael`BJ6`ele%I%oi{7hq~Y~Ki93O%gV6Q(|q-y;4 z|G&1}<8a-(lb0Uex1cDzmc#W>|Euf&i`%66 zpz7D_pfsP)1oY6)E4vk1fxTMKXJ+kNiV_uHCUDq;=UR4)D2}ypRp!taV)rar z!Ci_P(2wJvX-J;;ZOMw=3uFb$Mr%UVdUsMdFlrA-`R{_3Hl^4uj{b1Zc&$97r)Ppp z-<&zz5tMrgdk+!ZC#9!ff4xFas+$jA-dKb~Ru5l1e?AabY{v#pqX2lZN`m3yyRTV( z=$}w&eLc$oPUOktdn}+*z_Pb*+MwYWxh#)(1bmIJn2`P^sY~hT5#+3_A=QFk>Ojx* z3ylrHq3nI+M|Uk&aP&B!fSD8nBrDY#P=1jl*pm;CE>WNm@K;~euBiY`O``^81-yDD za8kb}q+q$G;!1)I5+YeY0*b8$oawI#qsgwR$OkmnK0qFJT@wPD3=lH(Tpyp+2#~BE z|Ljn7;`O|M)~{Ss0s5ZQ@P+0MA3&)158+35fXi#{2Ie)OA=eD%{X^I#dQAmbla1^D z?PX-Bq`+2_tbO9oO|n^}Jf%9lC*pUh5v3=AuG%IeMx0s%c+?A z>OWRD(rmrgf;8&?&r}TNApwM10EMRITdvkuxIlOOzug&@Ujj2aXh8iH-|qE&1yQDd z?jwl?n8pYH&rF9xRtfYf2y8>1f=3cbIj`bghXI`228JSp(cJV9qyO^mFK2y9ykx*W zD@4|vGjzo7q>%R&c#J=C$JggXhFLSmyW4$w7`#yD^PT0(`eK$7#Is+RXAScFc}Kw` zND%UQcW1bMDL}}7re?0Ab^AD{!Jds6oS>aBcp7hkA4wzSv-e{^_6cCxc=Ta$B1pLb zkE%dx1J-L}ziz1mDr@xrd}h>w0xj3gFM%ET&-X9?_pe$1+vh=of|yd)y7%f{)LWnI zbDab&GXuE5q}H@fZK3P^_}Svv)iOPn#K~B!&lp+hb}RBI z>~;n?!W)^UcSV}ht*F#Ns2KQ0(~Qx?&ya=Az)W4?n@J2Ut+OKjE5Al zOPCy~>0zfDEAIgTpOQ)43B!Xe#WlbPZ%A_>`xz9?YSqjRX_-ghg8KBi?wuhR!Qj+)$`3CocLf?!mhH z%FAK32QwI0-|W>EqJZ-$SX_BO5x)O%S&jduE=wZmYTrfT*ww^Cwz|T6>xiOVGoR9afI7acBq_Jk4EzIP^TnakNq!9&R4HUQ?}_UW%Wjy#NLW!SP>)(t1^mI8dw z`5zT0gG3S6#C1=jGlh6iTwY!;u|PBblAo`#<*rFW;$!u`((q|cq*rtrudLVZlEsXx zE%H=Xt4fcd;ec^UOE_Sd(_yk8)J6iIYvWT&DB|UZq`gm1B?J|fe2x{)TDpvnS7LE` ziTc9W5?e;xy3H|cZlfrDF^Kr=*|}?nDneS=Wr=l#@a$s?9c(iH7{a|)4b-|UUCk35 zg;0p8zS3m=^SkVNB}~0MG&M=_KS*-kswdE8lh34&u*-R6f_U(GXbq1K8V|R}&8M7= zoMve8np?fwZYJ;C^a(VctwrZfZn7m;`lUaZDqT`ZE;Y4aWB7vOx!;qRp%fYY+`3m^ zg1WEgr^00D6|>Z_$gb%pvw$;1H? zHfrx7);M3Kd^W|SZr^zx!wBSsh8VlG6e82rjD$~l8`F>SUVnik@R&RFf2ykYk1vh0 z#tP>6pU4tnJJFQ`ZkOv;JW+a_nrNxO%hV(`+OeM#2p?x|h8?G8MBP&YL0BqP4YkBRrz^%Le*mBF8Vjjpaq+eV$ ztjm7g8GifDEe6FA+P3Y|%H44l#8jKoj<{;`h-P_@TINQ;<;}=rcR!0}adK$LD#u&Q+o3Dg)I_CJ|Iyjy=*&X?; ziBo#+$9} z3ybC4-JB}cgnwZckTI^swVXO{*q>YSf0|gJeo*WkcX$Uuj*w`(&{^X)`lbD0N#U@c zRXJ|A z%q-Lv7&b70c@T}{V)7_}6v~lkdCtSKp<2M9_O)?bF4Q<}~t|m9>=$Q{xxKMk?EpwAj zu{ko9*sI_?!U;vO#%^{Q@fTNC3k3poF^#lrHD;rTI_^HYr3;f&LRxmGn$uA6FyE71 zv~*%OJh^0g1M=n=<$&c>miD|MyleI6+wW{&&7$ZeR?SfYMr2|ea&M*})He#Fmd&S{ zwLLX~G91qAZuTTq$rM)&#Hf*bLNZL9CSp7x1A`7)YH)Z__(`A`gj_c^rPQ#j714oI z){)v?2#Pyy8Sve*4=x`lqUArhB4*rSlxkQG>aw>pjDMl}^67b!d3siX+30S|nNpca zcd5PSy`#y>3#P4FXN_gc+ebHZtrlIGosw^*PxSVeg~soN3?G`%F4bV5a)L()(gFBsC{Hc`h}dNuTqE`_5PU7&}bmmU=xMmz`|SI`b+* zSHJDnI%?K$yQx)cqKmk~1-Nox5fs9B*Y?H6L;QBS@fj3SBkdLoKcfO9#asG6zl<{i9jE6sUsD)hF>Xyw_KW$BVzZ384 zS!_B*)r`0)XZgy&L;rlLCvc=*-55dJXlrNdIeiG+*?puNQPyLs6~ja&rsK~*5%E0K zo8@i4sSlm?Mio#AuT+ai z>pg#UN<_nXCPX5#U!_Nf5^;8&A^H}}R%Kfx-r}MjmRbMW}fjEzuoTmIstlG~nWV0ogn$wr_F1$3*(9FHV*Iz=vL?561FgI3`D8}U z6=&giZ{wm+WU|OUvA|{ZvdTCa9V<-Eg4Yu?^4TK0mSns@6C9g$G%@PnVXFyUyfM+A z&zHeDW@U}Z>VzC@y7W70>$$3PD2`q}R+v>clPs8Jdl#QhUMgXKwXh7h36DjS$=_D< zUWyXKsIy?2&7*!gV=vdEcm^6}4*#eX@5yMfz@@!6Dtjj&lLReNp}hv%c-R3k8Pjn; z0i9P5vw>MSNg+4_1MK)Mv5pCI6&dhCXDv_F<9JVFk-pqV$~L3>`fqkd^|M%(_euz} zi~B`$&cE2=sHzOWR|4KgP9huidZTlKM>9#8S|{_GGDi+avjfgJNTQ@YHONv-QT`s& zmsus9HQ<~;rP;!vYs$ZJSxWTf_9|XWeJcBnN;{sf7iUWF-Z%;2vQ69;wLowT z?IP(6|L@5I9E22sP^!5|ZKU|d8FjYIXOIfLwCH!Lx|Q#Z4!yQVnC_sfKTRV#JP$r} z>bn`OWLbu5Do!Z&k)VWL&MQD^D3*DwXUfc%!tQ#Wul6tcidc6kY|6Y%^);zi@NxKA z|Gw@%Oku$fqaO=XqdCO3dO^a-oF+P#yE%Lda+|-x=z@|sHe%ozK6@vXa$XOo_5A(} zXpzTvy^U`X;wo1a6Z-C!H4&^*&3B|#>$D_y=I6UA#bwg!BYT8WpU#sn2VZ`FBifA1 zknSsmgP1OxK&g66+FIUIcHMaf?PZ;NP@##Ma$@$Y@uC`u$ujeT==|bPpZmxbSOV26 z-ztSA!440eV$=Lp1eA?wq|=D&CzsD$(-fTEv<2&78%;TB4NL>T2wB`Cdd9b)xdGp1G z{tfq)NvpmDcNs6p!+{kMWZ#Vs6MRC$oRZJ*HM6D?DxJ)qiQVFH?J_uaVLsJK68}OY z45{{>>)FYe`1X`&@IXkhy`T95I0pS9zcLX9cvHAi#Nq@g6Fauq?q^?oNujwEt$>oM z`ExlHjuSr5ote2N841APNL03PY!G^*RFefLz5=33cU769ME<52-M4GidhjuHx`>Q+p{vV2ZXGEMmCsk&{9%_d?5{apN<%2t$%!z`3R?!3L-Uk9cvZMP0^I^?^LM zCa#F<(gqHdfQll&n~eXg$5Y?^4tHJf>xHa_T`bPHjs{Q66_JD(m9%YiNjR5Lojyyo zFQ~iv>noA6T_m*p24#Dsrvw7)+Nm)1rC@5>btn;a^tzFz20cF{VYBN!8+^gA^UFS4 zsj$jw$tx$|4SG^vb^Uw)6SZ3xdl^gqoH-X#Idz@)rt58n5|*?uw}Qp%L>%idRXeLi zUJJ}6M8jsh>Mem?KPyl^2YPK9(6J$q800ER&g)H}^t}3Tk9opf+$P*4Sixw(q}I~Z z#az`Jq}F8d+l`Z(=vt;(;p&W3D!0HEqScK#bYPsjHZvAEt+v1k34;zF(zG=lRf+{t zuYT-B|9S`A_c~kQ?7(?&ARP2^0l)cUjEoq+I=pj(SbQ{Q95rkrmVddZPdFAjx_@kR z(J5#heb2&ZzL|-DGlxJJ{qrf>zFc6s>6taw&rJ0@;&dB#?t-?>_#%C?*KHvF=AmSM zt+=VtDytZ~3x{LrT(e%TdG?c#R-C(to|I3NT7rJRB@up{kT=r|;QDWbQ&-C2!(*o@ zP-%4g10PT+UyoIv=21GK4zf4S=gFai_K7NAY8L%^ArXZ3BGAri64Jpqti&d z#}8q&xkO&5Sz{@Ab++Sv2Tw}k0uUQMKLSdrQqlQQvxD$Vj#@Y{cURVGv5mwO`Z_ma z6H>qN7$*NV+Gi8iqaG(@B;lB;WhdEZmA=-5w*ACbRcL%%8Y=#NQMDTWfIL8A)qZcE zDf!ecJY5U3|Bgtka}K-$ew(kpSi^Q*e?Nw9bWoAB6EiO=7M@1|3jCRH{W zE0p47;S7-ImA@D~6M>jWOhMBGN0o(k-a7hUVrA|X)&8h=>6j>%K6^)lMCfZ#UCqz( zd}_Pu*MkP0R9rfN+BDanfRk4+&Va`u+_lkhne&X={&kvrK%9;ExPn=oe=+aHU^vw) zc`T6-mfwcMb&O;H`sExHr{c!0igTsO za3PZBO+Hz^Qe6bE7Eu^o$Ku`>HDu1$QO#59^kL-yG_AqqWwvx>n=n3&Nj%DuzWxRU zoCP&P53c_RaXU04s9GPv48#+u;qkV;-5bc4o+z4pM!1wwXY~_=j*4n46Z)1h(QF-^ zoW7Myw5AB-mdlaMORitKgoNFI=@o@LDoT@h)HvrN=Y5OkLzdQd zSCfT%yShmb-&9?%=vR3g{hsQu0LbT>c@A*!R$c-uB}+=Pm$>A#!lka&a#`(21S+6n zB@p6sXmE&AK2zxtl~428qeQ28pkzqga--;09Oau^zb-_-@J@q4{)KE+lKbzA3o3}q z21*Fwx>ARn@(IRLw35zYrx=~f#c^RGY9Xy1YLNQdOYN+lB-on}aj~s2_NeW5FwBU; z8LV?+1wgGl2`=y}o2{3RA^)AnSNb-2>Nr{<-{6E zOTr!Fy!?8TRjuJ@R{C38mbCrL1bfNTw@kbr7O9~iVV{=w*Lhqxz^S@nL~>uBIVCaB z;37W33sB$b0&{eglE3EFsKTlbdVZ7ouxhp3?X~|(gzNsn-{K|yQSOTrTGYJ9R#~ai z{9d4k=|np=#Ic;tRG));xlwIf;@4gixI7L7947Am3Ho68W-w0j?_^PI=JT%2YXsu z&T#dNKuZjqvdO`d0)?J}$KGPNV{mvgw&{3dsON}Kp^I2hNUWnqp4e4sAnC&tKd6Q^ z^df?_Y#~k5vxKTqzMO?tJzH9}pX4@8i@fdYSG9>Sln_dBDHtc<84oe{s-PRLU#?^f z&vymVg7EaV9HQOLFNpYt`#)9TPNS&Dy2SK$Cv}^if=*NCvTh~|kqIyXSZSpdt{%KI z_rCBnO}-oyCE{2Hdg52o`-x*ZK`Xy4)o$PUT#Ci!o5on3YlFx zFAwT3rWJ7-zH>3xj_+P8>ko7nxn5xLz+iXhWpt`Y2 zU%mKI&fwXT;?PM^v4(FMBa3Xq8 zb!ZW>fpdF3XxcTG0Ux9W7x|iush;LCs?{k?vc6mHgIO5innTMReU&T(oO;UOk>>ii z`azx{^oLbRRI-l|NH1Kxa8mg|S^@Q0ZMPL<6Q4zm?+#(UOd#$XJu3tX#(~Mx)1p5V zwX_nr&O|~;j)|rJv@G(KzM25F?4~w;)ov-U3#LjMnV5YR;8>*=Z;8xb`YbDb)*rWm zQ5IX?lX&~e$h5OBgM5aqflt07HCyZ$EZCOlZBhw2Ffl3XSGMd?x%x&FdmN;2 zX?4a{V5}J37J&*f(_!4QH8~;MZgFtr$A(joL>radnCwa<*((!CN8DY*@h?D_TF0rP z+4fEVw;~-E0#n}AzYt~D($^jzLIu;j^5AR<(_&j_SVe|?x zFBUI@cEn&veiV?eWz?xnQ&kuetmWTx&2+f*@6!}k-5B!JwEJDjgktR2^}ZPm3ER3A zeN?VkRcrLZe9(@%ATbpqJ0?GnNCDrzQFHQKV9BM<>nG1yz*nad<%#8NPO?I^3TNEl zf=P=c_kKji?c9KcZ=RtqX``z(stxXJ&X*S2G)do4N`a*rwFm5u6F={($X?!dk3Jx!hhq=}CdU4EI`i>US9!AhB5GSO zGWt`7y4lIcAAKvB2~UN!>5$akU}TZzxE?B*0w2iPA z^kANMP7TV-Z~s+h!S`6VO8$qtTbZ%Xm8q6Il-dbP6vy!OtzBTt@S#|hjud##Igp2U zAf5~g0C{jw&sXNWOFIszAYql&{^01tYWo8?)v)}X9^qJ;Aq`~~VfzU!=}XZR@fpEI zb@@WmvtdVj_rWfFlvr}&MS(Sw(ES;=Kd&fdY!bY3jrBgn(sH@Xdg-v-=)u6;yC1S< z-YC4AOexZ;?`C3wMogEENjp`JsJ2zwa1^W$!Wjpg})p= zutB`sa+VQ!<&it=dDWBsX=Pn;zzDf2uu)3Ldbs+HJs7zI5A=RI1<0`uz7K`cv>;btre@L%H+B*<&g!zj)x``^4yK`vS_e>&TG##V6Ew{ z&TQk~C%iwV`beze5%8pK<$%1ZWS)T4!~?aVDzBjS``b+9n|lN5IllwlNHeZ))VdAj zdir+2A`@|p$^3&E80wjz!%0X^Bh7CxE}!NgJ`qGm}ckhDP;X^deSe2j)w-ggsev@LU~w1}0rC zn9oio-y3ard?Vu&V!cSj>lij#_zWHreD6_ETy2|IrL#H#B^%g5Ie;x>iwbs^3GYkBNwp*C6@ap3@+9@Nf&2xp_=-L>d!?WZ zXX4QMLXX;38f#2jBN}=w+x2g2zV>%997ffa5txIqH|N5taKwF9F!Spl>Qk4P+!r!Y z=eP5`I20oqm}AZ7>$b-gVDel#cQ$_HH+3yyOhmt0B{6{JJ?kwJ$xFt-v_JFZGnG=X zX6beNCNHil=ssYHlQM&?&6##cmdJ|v&}J8*^`4my_e$VsJrPJqX=j8kRoW&A=Hge2 zaJyP3^CatBytrFLM$}A%;HGLHBJ?}lbeeJ99%6F9#SNgTX8I9A;Ppy;p;Wn8jck;% z6u4MZNZDwtyrtkN~S<0-izbEi^Ls8;=wn5J$tux zG+VvJiqPXp;h2pmZrJ^T+x9X7%{dn%vdvhIoBTUjxr%E!k)7l!Id46GKQro+=+_2Us zKw5lYnolJS31f;0kEZyY|N3`jEhK5}KjB^Qne%J(*Vb@1<5dQVafQad*xe)~mSS6uB0o)ykR?T z&L8R~bOhoBl;5OcH|CkT6uAkWV2HK#c7qRU{wY_l+q~V@8GB9l&&6h<(~$cVX`{tP zrL{J)A1q*CU)c<2mcJIA1QU@C^avAJ=yK|Hd(&veo@MwBSo~g&)ITu$G2USPQ*N zUKwiBV51}jzaFEhI&so2c0x5~oL&Bgc6_uH-xk9Z0=Ow{83Aq=xI25J6X+Q}zzO(= zaA!wXdYxFl1aI+(dSLUaw|;b2f@01$B38KOh6d9`z+TPG;g9j9MBl-wTWEKzKhcBc z9~_T4m#Rst>qfuf?XX|8y)DwQJ5%1aBa|l3>oQ#bvDd3~Aw$rmL?u;RPS_R0Bmc{B zUhar;ZHs&8Rra|_Muu17kGQx)1KO6ioB}-Maphh{kIin>U)qlkEjW6Ln~1tChJz@? z8sDybwed4*x3?I%ya=duiJ4~?Fw0)ufkq}(6gXrPBy%NulC);smJDnQ_`J}$M?DsL zMw9j)Kw0AHoF6dyr1yy9-}3x(quMH?#!6teX+yg;>mb#2rp4R5hBq7=u;IM)phA|b zw%YN69q~|#;pf%ho#T|Z6z!bQ&|V^gS_#4d%^R;RBOYx}Bo)kg%c*7Q67b(>fT#+U zY~(9#wP(jg-;m1e?^n!zPgO>9)JIzHDSILR2Nswa(MI;1wynOfz)flS#R%$+LF?K4 z?UAuXZ`g#Q?5!=v{+F*!dW5>zX0NyV^9~&eeYHWmvNV`2ztjO~ZkT zaF?WBW>9LM_~sKyNbQckP*8OWXcY=GKkumj^gX=l1r00G-Y3|811=~|b zm~1#{+1%UoRR<0!&jegwQt@WbgkHDhCtrKrrW9HJFHuAP0Tn%X&wJVz!+mLj} zUu#3pDL8kiHXLqmZAS;2gBv>`CqdvpT8`lCG3HmR&hh>EPYbHt8pKrrR*IdHF z61tQKx#sZjna1@p6N(Y)hP8=xWCQW4l>dOtfESHK3ID;bdCQ7bvN13|1Tb@Cz)B0R zv2OrUjhhuLY!eoC3m|&>A6Oj#a+|+{>???l(|86DU4z%IVRVE8@lBs;W|Bxq@BJ5h z2f#ytaUhSA7&7>uKfehO{e!jp3(wmPfmmzHE3g7Yf3bZ3Y-^vX2Gn@~5C0A@*?$mq z*D%utg8#+z|Jv!h$bZy>Kcop?1i2RKL`vqZIBYJ#&^t`~=>m)akZE{g{^GOyz6{3R za(zJP;hJj)xwMh^)f(0ozJIi(*T4KonQIQ0kd7NS7WB=TB~AI;s{KhSALO{Ca8&xS z$81xJ2WAn18goB7*)NTfMmP8$guK~YRHl`T)gIAzG2yCuJXo`BYDdA9$K!z$zOk7)f6ibWY=&S>u`WA+YYvA5sI>YX?z#a$J>WGWqn04g zF~~Eg@O7?AH}mU=r$6Ol3YhkDW!t{d#f=4i3#DI;LF?{c#j|m5xfEjqHousjaW4uV z12Jv0q-JStnxfq}awO^*<{moE*8+aR;y`L*IJLVY2_Bg_;jKs4Wh2m1KH(nv%Icvvi8>iSkvWTnytTs$mS1201Kug&5PwOQ4 zoh~JnDN*8!-pd{C*wq!2lFO~L=eV*{K@TU?ZgCq+;{tFeUHKTg!V`Y5<~8IJ(=hzW zn9`#|c?^90GSm$b^!#$?ppVDuf_K%xz!99w#;z<=2OT9%nGeMRNVIWs8e?2SYFn(N zKsc1{hnnr2xwTCG+!%ffMG5&|66WAh9{$QmB$8)wxe8FYdKT50qvT=XmB2bLr=gFB(Il z(|H&7jp|+iAwrplg@;C4>i6kE@~o^7s!JAqaHhVJr?yZ~2>{xTXmF1LL+=*%y6=hT zSb6U3+D!gTX5GuuDKh9(9x{q)Icvv9h10FY=~C;#7qv4@HqJGwTF>WmOEK8@TiHG3 znR>qw$#C`=AwxuBU6}9v#UPm`$M1XfwZ{vCSIh}Mw_jW%dbo1})4>-3aEE=!OR`n< zYO+xVyWCGS7J^m#n40{nUtbn6uO`;CcZ5o3YcaQqu?l2?E5h$W#TP?yc)QwMFLEYt zP8+a*q114-z@zo}aIa#_eQGhSfbwM~_5pL5K>#_n!T9~AY)~uu4;)9l-#>&645WSu zvC;!fO*LNkUF?2$AoKjtK)LqIHgVgTiW4ri4;%0%`G^NY9dKKMrWS@Iz1f}8cDgE2 zp89&nES{+i?GfY01Ll#LY8?S!x4O8WKsi^icV1fOC8jKC>hg%upNfh37Awh-=`~co zbXyap(-Z61bXBK`vnOCN5AuUKxU~P^h7J-BrhccDorxr#B$;0WdzNDjfMBE{06x&L zSf{w4`l2S0n5;le6J(jMq<=gx+F=ugTwinf^aF`7*XmJC%R44ffPVjM(U~u|WzIDh zAqBiR__TWfar$urTvlbn!Rc3X&;dI0?we;KcqqE2mMN?%W!B)D|B&mr^x@d7{)!KB z`BOI0HI5N(<+53+JAo|>+~)eDONs52$nnW3UuYiQpK%3Hwc5#MKUVPYM@#)s+i6Dc zIng^c+Y4@Sj@7Qx(V8QkVkM@9#Z$bl+A+FqvM=)F;O08&u|#TmRp(MU>Nx%+>&zQ{%o2|wjt}?azF6TyZU;~0z{)IN3huuHSMPjxf~;|th{p}u1iz!X z7^{c^qRBY+ac4(sT4brOu2BU)zS!r~>u$#MH**9r2AH zgBf*s%?ESp`JcTiXRFXRumuy|V|L$PVb#d;=o#b(M3($nq)zY0oyMfYF~6{Y8YR)_ zmg?!(?(BVhT!7V|uKoQsE}f=Z`lF`HJZ%Di#_yJ$*ye}J~k;XJys=NRe zs(zVlEFVn?r$qyGcgQN|)4A%aVdG{E&jh`(Jikqp4eFv(K6Y$a9rtZ)(?;C+uTUDu z`8?dpJ<-<1TJK%)k!$F+)LpAT)Tp)ONkUyR8_5 z{q>uH6->_zL*gAojehpr996Ec$66L^*F{*56Gi&$`>%BRU7a;-%QUKI-3D&4RUqqZ z^c;eQqiNz!1>y?Sb)`W*Ts>ox2&p4TYd|NZ0`v#0cv{xPBLt_mB6|&?p8$Di2^3U+ z6sTrM7}wZM204GOaj={G7(+7XgPv*1X+Asq>WF$!Rt~(AGTmaK)AB5sA7xDvJM`Ig zxr$jehq(=#6RQipQ7~04A#3^Vc=Xy1nAT zy(G!={$8@~cwvuv+EW;FbRt&yaq%%|Cm-IdQX*^d2@IO8GI7?6Ch z+Jdh_Tl=xLX#@}OiwM=;-BJ37A!<~a`nkZ{Ldxkhsu@z99Xz1M5~%k?#wlS2!m~8y zVs%B*tRaMEvSgvpZyqG=SWP8M1=Q!gsl_kZz?6x95*Y|hetp~u`E&ATv(pieHkKGP zSMK{Krd()XG})A-q@qKJy6C&iq{DImh>ABeHCMmYYI;}6*{IgR4eR_%9lCfCK%ORP zm7X&2$w{&0!%*``cnqy7utStw;J724^gplCXY-1+Co`@4M#(#C*zzmFfVf? z8L#o@IUgu+S7jV;+05(ZJ4zibws(dj%0W$iZZ$n~&E^jjpy_p|lg7BC0#Qrv0QruX zNB$$<*BbKW$3Px9AxJow0ugOxQ0xTI1ZjFkuq6LsxmTBPOQjrLiCA!at!4SGX697ndW^m@Y3|d(iVq_y!>SV zIP^!lNAU0*tL&SD6L2b7@J-g0SuM*_`G9<<`bw?VKUr=2!U>g!QOZPzh>9CL!-pNe zjdt)nnFo?5#}Oc)wiGy$-;m#9QO{x47Q{y_HpPkueaG|nQaxRoMzPb1IL;a+7TwWm z?(&{>>+zsXAQv-gc1&y3n{CcA=)W(MW}p(bhyZ5Lw#PL7+X93vBa zB);EMXr!^Q_n!_{m^833-;wavW+5IjzFf|_Wkb^lW;khttfuLCPbhEI?$~^Pr2;>Y zT&f9rjAZSyuBU0a-LhHVgBLr>Yngths|$~uSo42l?>~c@4&VMkRKzaDh6n~w0gc>e7Ge*)ysR?khwv=@@tori6AJ%qZ~?t1js?5(Dx zGyXUhb)T&i*50`+{b`5z5(R%z6W8*N)Eg+jdTxLJ}Re3BEu6v)I_jXaAnW!qB8^+0K8|~TDQhy z)^~yCXW~8M(EEWNvvECa>MJsVj}2Ut+@u4e3iKadtY^#7K+6X}vIrl!uW6UxW>*Sj zOwi4rDsAzvgeBd4lzZ)4*4`ra17vq)d>T11>Erg#T>|})KImRI`kVxU9u_If#l2^GXV4zkH{A47rOh@EdXn@wp8> zm=sC&;LavZ_EBl5xk36j{S9-6%9nNvXcNEvJ%^*_4T*4U$=#5jhCVs-7HylMR?jFI zD>wU|z_e_8Jwt2g2vJ{Kl*4g+Fa?&s4A~S9EIgBjhQX{21E>qW%Z}$T zC)$hErkho~{gKpro9_qhvx&U})56m>@3Kd!?jl8DG>)Z$R>9Grd(fG`Qt`xMsyOkp zx3B1RE~9FmJ*VaLjg?;^DG=y4aOqX%&be-wY(ekN(JKGfytG}R!0ea$Zhu4M3^sa9 zg5FQKD8u6jF>w9*1`(vc-rAFy!4I`8+u;1XnAx{&QBek2cA0eIjuvO=cMKC6f8wD zLP8EH=^tN@=Dyn29*~4&B1wTHqCIpJ83#L$+Ium+A`3eUnuNbZ=?(RI>N)H3)v-S% z=b73)c_dK}<}2-N4<<&fIv^VJqD~7D6W;U7TT^xBHE|tZTeUviZX!MNuSnD#RuQ2+ z$gvL~A44p|{nr)Gli-glO~$p0o?Y6zVwiUlac^gtZV^u^li{8H7^|7PWJ_ecr%0K_ zn`F>zm68uu!(HRYB+!+KJb$7)R{Xfu@j~NJaHrOdU&)Xks5ujLLysx4d{?V&C+pFB zMJnwS(w`n%Cx4J)Txa?vw?X0yf|J%)%0MKDCfz%?3DE!EyV@M#rLcjY$cv844pygq zHd*@W>o=>|ZIpg>4y)QhTUhMw819`;(tpkBPIEAMtx2aw&m))x{)|b_H)<^lt+Z_w z%|i=+Lt2a1=b4$69;cNk@J-fV&tbbyJ=L)Aa4Ci_Nq7D0w>N5puIb*qGc>C2`eM~w z_0=~zU0#AotFs@=S5G;Z!ZQ>JRqaEKbC(BdkzH4%H?XBuylK-jjoFPlwT@rsyVX>0 ze-Bb!UHD4!9>Q-mrkW>9885hZEq1{IccQ;?p^+@gRGQIpiXu?(8gneHaG|Xv!t-_+ z8Ao~!&Hkn@H`?*jL+61UmARI`X`UCS19%b8rYCn+B2`+}=C6olFM9Y7*XATH#Z~wY ztYe>lgaP2-$L-4lUsP)L68ZNxA)7TjORRH`kx_IlvW7VVYlAED`pBKVzB)C{!Dh>e zOFQ9;19bYR!Uo@ck@w)5VsCFU-U+drDDNeRmENW-ZAajbbH(p39oM3P` zDgIroEV9w?Q8>o?GW6xBzG5oIKztT`jv>`lXL9N5?SY@r#kI47)Z##InxO6sSs5ASlg`>vE)2VjccgN*mny!Af@58zwE{L zP|!zN@a0*9N*Qjhpqb;(XVuqH^C+>3Mf9EWr)oEXFEHpJDI4Zo5c)ZR&6$0C=S`30-Q~`D3r9Zu!b(7;KlKHM;NB!-?fFq1n)UWyZk|`x$=&1KOGIc> z&^t;xk?-kSoZ83R#FS$L_{#v~{k4e-wM1+1XPylh3n!31^X58QO)2Gq?+dr*@1no< z3;1-{p-q7)b-toG*WXc%@y6XyjuTfOveRK1EvAmr=eGBHU88gxLI1V&nJc$8s-l&D zxrzCqP&9w^?u{9%VqwP+$=W>j39J=Er@|7gX4d^i@XtURJup37Buq{P%{16VFb<5f z4X&^)H##W@vIGb%(ih5U ze>h63RSUrw6mhL7@c0Ktr6dElUq4ItI4KGAWlgMvq2)zk7y|k-vFVCf+it-hl7%NL z^Do-BiM3hZV!2>2EWL(&0JnD8oAmA^)-*Yvf_w%IwKcN-xv4iOm(}qf>$ev-Jed9f zZ1YN@V5Y=}=dG0UORIz7D;|ou^Z~lfGxq*S2CCBoT^iwo!N8wqVz|QxK|W9(`xZML zePDYpX6=0P)DUeNPZ70tEw3*qR;Url;`-L+lYli#;SDYh?rdVxfwAkGR1eN{dLx90 zQx%=XFZZC(5^y|xIQGN)_ys}IJm|LWi79dFRz#a|j=AHwNFh%h(Blj7)JHsaeN5U6 zTUM;Ec`F}i4a$;FnA{CB^A4hE)4{tWa*WGbfPkbQnsoAAm^g{nCXGD0{taGVq$`Jk z(KIqhC9y?O_v@63$)z>!b#mX#)*0@Y0RMWaPZhMFA zgH6HNlRDy-r=v4cYFvVCdRU3=@yokEfN<2Z)F=pFvRM&(`+eb98crEkUVq8%(A#cG zDUZj0I%q0AC7db;w>D8PX(!>0;3A<&{ucFv@hDhkme8XVU*Q`+W=~0{9#d_~#kdEM zDQU%f8~T<4H+=obi7w}77dK+!a$Tnqf}m^tRryY@MJOBC{1?~G4L1xQWflFk)@&yE zFIMA$mgB3o_!}J1M@(q&Z9mht{pC`GKMnY$clX)@MSu$er1}I@OQAjgHUy$i^(72Vlog{@kWW4;7}C;tA2Om`=Jh`t=Dkj#`!n1b-Z;IF`CSbH9Ft9ZCy-eH=Yf zVuc%b;-Jul#uZjX+ANj||9QZ+G0HKAanPZ2xSOB>OSqIVcr)WexQ|kf6XpL9O$q-) z>HYsZ5Ba~sj&+~8uJbrfXm##ApXl}G1r<~% zu=eV7$Sk#yLE~yn>TD+J+KVS;x)M9H*T{Z#gA9ue-eR+U9U3vCkES(ryo;DHQ|l<* z^6;MUv#!jeLLuf><@&Tc#5&8@tS2gN`ZDOH+5n_IFgHhyl0AJP$yw0*waTkK!;aga z>dlay0p1I>C&DETpJZudj&bCJkH9ycO|*T+<5D-iKa5)Yp5?+Jh3-u*2p+kyS-YLC z;Uny_#tH%^wnpg@e?rJ0!V^fY8(jaY{$_MW#e52-QwKm5Ki8gStZon2&qrWSl9Y>& zOA6<^2|;(bRF&jTamXyaeHI#C%byB1_2-JP!17XaadKC(^1Y&ahXkU$iMhr@?T_FX1#UqPpVoL zPpNMa(WI?=Ii%M4K2!jO7DP@DFGef%Wje@1-B#bf8y%zC-hx$~xrH|bZXi#yJ-l|> zC5uJa`VPGl?i}r-ZN#T9veX0OX-B*j*@f817*kAj=+}r^qqch;^HK_M4?ta6R$czv z9~1Y5`fqlrsYnmy5Ga#EfHCMf+et+_r_bP+VX5^2Zf3q;FZeE}Asd6|W?Jr4VT(C( zzENgZSG&~nYxIP>oQ%KHq*pnOcG_C=kv(Iq=wyk!c)^? zkJ{5V@%Gq~%r3*~o^5f!2+5-;=p?>lZWm0~*sw|-cjhM=ul)JAXAk7X--0DDX{ncj z&ASrw%8JBHS5|4FyzVWJr1?j18!FmaxQ5HG}H`Hx!rQ=v$sx={f1vX{L283 zmS-C;HYHrSc%AfoV8fLQ6R$|lhdzVGBskrI;u4%t@))Q;Gbi+0>3pTkd*k@v>mCNAtlZ2^Dw;VC(GMlbs*9_cKwnLGAA@;L#vzU{xNfkc{6z{ z1GXzRP3!p?GeukN*FrcKWr9DCdp!)n6=mrj4gP>B50>f(K05~4W@lVeYYt5u^$_B% zo90xJl;lVSLG3ZGhW}=drlrZ-*j#p6j9Ej(56g!Bq)L7JqnKn(ZtcSWjhdI@MzLVGZqK$JjET zse$X{BFp`_klfL0F%8Ce3AZmYY8`IU zPYBz~H>`{jEmgCmti5DLcXIdW@9~{3Ns%L&Zt77?e<~EgedtNH8IUxg+ z05URy1$IPpCD`9&TP8}}k68mzuuy=-+&_wwp<}&?T9-gGGI;I8+KiN|0DIb_DyQfx zo0fZzwsqNSms~Qq#1_Vma{w2wH#b-B`FQTJqQJOt^%EGTskrrkrs7>}m5ff6m6&$f z!~H`yu(L`KHCKNwz<5u2re3D;>U zTc8ifpGFmEKP0Cu53$j>LMh%}cj(U%24DPQd4cRce+wCFU-jE~^xL|smkV6u#dvqg z9Yk|)SCvy@b%tiHvzsA2(Pq3Z0Ou;XBAW$I1uKaaffsbzLR$a|2cCoqp((-0{cs zhh!kes88V4y6Epbfkuouc9esCIFHAyE7o|h@ne{Tp{&zQqxl#I%(F7wj2+hc5hC@K z5Ur?ZDsL9}jtXk5>2_+Yrw@_yCf z-*iu4LwEn1i?SB#BWw<6^9B{&ejMkt0A3~Vpf{C;u3>$Os8J^=;eG|3qn#ODdszV) z3e>fB3=;8g^Ji)p@DwnSIoEh@gGA>ns!9XjyO=rW7nfa!v&MnjHcdOgrLW4G`z#*; zS6SQ~>N1NLr4-vL7%x^*(j^}u@%7X8F)@cUhHr&DA;HlVN;WN8z_`Bb1!XQVO(Wmr$L`|;Ft~7?g4_V$s|NPB%Z~vqs;_A#^ zUEeSn1q_H{p6%uX4NqUXmwAa;ztuU5&0_rgV02|)a76g6*-Uxj)M9N~b7Zzgj(zzc za#=jmQA59!xa+Xz-?sUpPcfQYs7ygG^7efA zVXe8~E$2Y5qCZr52M~{EHxmn@nVr1x6Lca$pDZG7%~}lALY2@tud|{`@?J0-)^R6# znNlVXyIUDX<*sH0lndC3=t_j+E-gEidRqsZZ2ly-!{sOOQ)l*}8vIR`Bi&aCkA_c-UU~Uqhi%`=*g+anLE^*L zKdRRew=%@d38?Pv?p?xS=jqC%d=fT2$Hx*IW*1B^@gk1T*0_9k<%0p;6>rf;jH|Ot zG-#fDr$A?2gq? zb5uf4muEeevYy@?i5QWESLH`!Vnn`hAhxOK<*62S^9{r-r}`0BGv8LzXW7^kS5 zP=Bib*r}|hjhae9h?d`__A0a8fz%oWta|L-X6o+iKN_6;*w_-cx)P4cYy7$EOQR|2 z8EsSCYU$NiPmLc3^0I#!MZB(%IM#KfQ{Vfh^d%6Cy|A_xb>USmVt=tBtpC2HGLsT9 z!zMk+YI0CraBW+!>YE7pEB(LH_wSBr4HER$^_UgBIubKJX@BnWni_X?3+B*8H}Snh zxV1;b@`_%6YSJEO2oBuURagAzFaa7W3>FQ)eXqe{E826;-eBSpA<=eN?AUH_pN`hT znS`mPc8QuQv0*NKm(Z!Ie!fG%W}Im-oBzs_{?GTEUwx}lK&F0-HXRB$e=ssbe6e!H zRjAq#7Z$5yO^X5w zhEUWmJMx(`_aWNgiD0q_bVK;?y%}ikp(+R*k$dSih3Nm zwI9iP^EOs^e%9f!*|8`|T}xf=PxH#K3lrRkPXCehqJ<8HN)|DDOuZpdjAiZLO0V{u zJNO=H%~#26_+pT~FuF^f1F;=HXI2-6E-)xvp;OhUYz|dKqA-;ns6}oAlcq{thaB&b zS()fPdSS;v4&9RN&l9(o2@CAZ2Qde96LTBAT(Z!qE5Kcz_i zws9fyLqK@q^c6(kU)+QO_P;m}v-8wEItrB8SHD~+-A(ky}`C1jK z+w&)?fLnYlmHhdBT9B0DzOVx8U*07&MX4$S6fwdYUjqMd=I+SV>#Lc5?yvNHIEQqd z=eHN?5o21j%C_n@XX^LCw*K}=yXyHOI@BtXQ89+6U9)QYLpZM?Kg5#srSCqddflaH#@)16LVZ7?s@+uKRmq08QS`@fEQiOO-A>%F zUhUKQB}zdwE_AP&+9(zFMm7&VPr=bRD}#)4zSCBflhMW2;<0ta%dR(lyq*r#)F{Fj zd8p`dSC8kgS&ysX>*9wL*Nm=lY5MvFZF;tpeu3ZlGlGwS+UGBqfs{FP$)iLONYUAi7Fw6!y_vsv2^i8Q01nP?rR4PK^DF zONkdYC}5xSTFf_%Cl1K&{mp6W{ZvcG8u8!!kuc8!?JKP5&h z#1dlf*D)tMOYq`H{dHD`(#0fz(C%p@vTQf4Ktgg-KlUQcPkFgdDTm5-vFeLEb(}CP z(}hndpjC^1FKXTBc{_dWb-}F6{cDY`NZ0MHCY>D zZ+q$kq{KT%iyufjUo{u1HcoUZU9VjU;UkAte{!g+O(RR>H3190-cn0-Y%U8-3li#l zGyVp8hFd4(MOAYsYHhgXw;q1umFE7yO_Ii7*vfTRp={0is@+p`ea4X#A7t6RKR?{V zVE|l!kDBwtg*`_oU>>LW=P$~~Cov!|d^K1aP`{5bdaU0|m>0y_Lka@8Y)8sROD{Vv zKC#L_!talYdmlHd^JdKZ5}jh`S?C;o;*Msp0Gf)M&D3wTTWl%3n0qjoYr6fdZRHFH zl(72&q>h~vw9>wnQ-_%&)Kn%rzpm!DdKs_#rV@Luc}q}PY3b)agnSmd%T=9Pq48(N zu{qlrq=)hvPpiyD_+;%aWjSK&7 zUbb1Ak0p7U-NDIXR^?@`8T$VDebu(O_wkokCWI0<%i@7w-?(|4~Lfm z*M?k=fl9I4aYESq*D-x{sb`9Go+)5D9sjP$tA`eA$q&$RyOs=(B>Gt(;W& zU7LP6y!}zEknK0^spFIWhNrpg&0OUxe-`4~i3`=9hd-e{m+JHD7R8e{v=d1UGYp)* zE>yn~y5>OkgkGB50F5%~qYv;;7O#X}mOg|$9J_() zyL+~eo-^G*-3Yn@`y%j(@zwn%m9dxqKITHx&7U`Cuk`wXw@3=f>0W_7M3IC(7kbI} z=--=f*j|BI$}9M%u=S3 zixo8G2#|L@%J+$t>|X>_t>L&(*f> zA~i*^Xvf2!&g)~Ho&u8$f|g;su_&Qd`^WkO(aTvZX-&Oa_*24yZaa%@9;u5vwvKcm z9*^tV3-bSPx?wLW6Jg+Wxvk$Ytn1{!_P)ui>S=wnBnt&}eEMXXRN1R^6oIvE2r+Wp zvH3WP0w@Dm^B~5CmHrXJ!^WXUwu>$zth*Mqsp;kTC@D(<#5gVX9!rgC< zG(;XGj20ix*eO?m{xR1n>5X|oLe#8riwC`bn@kqG)N9%$7V27_;o0>`wwTvDBSVi< zt61i-LM-iTmu{=u8UP!x^SSS4a6ELNB#zv7et-G2n$esqIV>$F`l9GwZ~cb*RA;#< zQG-U%{aeP7q7*n|R}rEo%RfA0#4~CS{d2?Cl}8uAWh|FozZhxb!_MUH7#;HRbEjNZ zLAG2Z+pbAp;PN6gK$An!+vY$|8l)#Hxc4vGny&x3m_&T-pC`T4>eJ3iU63qzNP3Af za$<fG0;Y~x6s8a+{-z}ribzClH@$|XeK26 z18*_av$v zE~C zHz$nM*x+{NM~2{mXw}(Fh0&E_t7a=@_wdKI%yxsS%2nPt>%?4}GJf5%Ws@aW%VR%I zW@A55rPw%rdldBY$^N8`YS#gUCWBW*XX$m|GusM)dF1>xde z6i|T7<3{5Ds}-q!t4<-dJbJh$>{6msjV-VdKO>;DsGRXhwq`z!VL~)K?>>zx9h@YY zbn84{_XIJhtN$khC2oI#jOLkKhmOzFU>}dSO})AMPNd@gd#^zeTIT|cAOPc&>T)Vw zjlYje(<-_a1~vA^n@efedVUo>AnMm`GCl#+)G)mlv!vg|;sxCl7h~Xli14&Ye4uP7 z44A2*NH%pm&`G5v;#N!Rj(D|#EvK_`Qe;a6wtrCloittfTa~g11+&Vvocr9l>zXbt z>RWW?{65El_d2|^$tu-~)cvq-{un zBY8(vp5N>lHgrU`P+@N#kpK;lOTx;>;3A%AOP&1n=lC$y{;1xEB|Ib74n6ObCcsqY zU`_PSo`ILXZGV@wi+zka;bB*>e43+H5u0LDMN4v6p5%4O&0Fy7^HbV+&Ef)hvVk!U zQ=Vs(5=C+d^y7S3!13%3=(kR^D8(&Zg^gY6A#9mzh+#v~A)^{JxrC&05@%g}!XdPT z8WWy9xY8M=uWNF!I*O7G($!rHT*sVrRbiX&s%px8Vx+T7{UC*pMjiB2TXr7FinAU_ zxtrJ9`sX{&j=8r-7er7k4R;RfBiq}G=DIRNmo=^oJ1v6_R?%Wu<$+EcnoA72EZe>A zk${HR0hkA)S2le7K~g%VXM4u5qPva`WaU|~)=;iKqmuPi9^W&RZ^~+>u+23)vNph7 z$StVvA|uG~%*qtdFLdhmh4R8wSRi6YC;1T-w2V6Y*Da0zI)9vRC!|@v_dbfoo>xjA zJ51Bes5_Q8%~wlJ0A2qYRmVQ@r{i7+E3c>0{Q$wR{Mduk@qOUfTh!MzZSOFB{KV&bq{F zo$_^y@|xWh{KiE;(&k7-rH#Y+N}^XNY=tsu`((Ral?+JwJAg6O(rl>YKF{ zHjykCGRGuL>rHa+tE-!P`|U|vTAl9sBhBpmt9NtXSqsHM?NKyiCL-@HvSr}f4itnZ zmIHU=Xi+=-2n7PTK4gHVqf5OIxc2S=041a^E$1rBa2o(C``oQLb8o*Z@Fpco6zpxV z`fFN3oAi$;TxTeb**71%a!5FEruIfj_~lKX8g zJ5f5kT#+k+n~c`E##hZ)TzW)yCyFV@w&$n%<>`9z)LL-5xCc_{&(ST z(`Vz)sNeRATFtS3acFY9+w&HBiRK9T5CJL|I&pVU9>#N+%4tRy)DQ(sZO2`o?Y=-q zud6xrPD};s?t5-sSX;}VE{rS)mN?*W7NU&=V7<|2#|0~ya+`~(4&eeMcR7Q2v5XM( ziO(}Cl!q4itF=96Ks0akHGN!ipn=^_Euh}`qiC5%S$K|6*X%lknlu^ILK?@;X0+ic4q8D#5@7BINRX+w;Wqd2BWDZj@cQ1>2fjS+&MvG*;g;#1e!_xdd;^~ z`vhW{qQd>C%xYM+PnW#a;P_Hp$h>!Meq5%c{Ny#QhdvXjte851Cy$kob=my@KuL7i zQ_mR|BsZHJGScABt&g9<`nJh@g%4CKnlJbJ6vpDVrbQ2C^C$M#(`goF)1CZ)cx0Z{ zmBL)7B;3`M|#^lJQQdS3jn;bC)XXUQeL zM?kA0v;31Ud4X-6L(3UAjyKy;d9wavX{5`Q$`rt%96c#V$#q$QxR|A0vN?xWY7 z!vQ~l>W3dAYAwIi^VfOEU0ApLW1YC$h8lob{?TKyHvOn>l%3dN>`uPn;@EGXcF=Bc zNSp(tOv z;CxoAZfeRC+o$%+@8PLAoR^fJQ~q8bq69Ev?t1aygP!osn5(x<+E=K;hOcQZun$GV zQ-(*E4-(t$1`#zBE7QLtXm}I7=nPM1535A$sZ}*QKBp*{E&O`DGqFsK+UXRTGbG4- z4U05g$)&;En0s4o6-LqO6n&90M@^WUY5B0m3<VQ2l9iN*2oOFW*0OB6A zDw3PPeryVILwQ_#Jxg?Qk$=<1yHj!UE!Oe8Ct9`KVm=rBQ@+wBm?`X%<@8I{7JI5T zXm@p*d3=@*3iCg$o|BJ0PrQFXy>?bZ9qUxD{uH<{Y&Z3m&1j+{O*PfRomUidT$!ff z>#*~8D{Mdf$nmt@meue_RAezsmwZrFqdJ*uO$5Q)3BkW+LjT$S2~TC84WbupRPY>r z$m&6Pfrtbvi~Z8x30PaX9b&zs!xCIgDkcDsA1%eT)s3Y9EbEWdm!ZjIinuxgvt zo>1ei=&b;~$|%oZCMv+i?wv4hnaQfqO{HqaO(e@VhjNiyZQ$W=Y(I@1R)s(VUnH}f%y(+odOf?u z$$r67zkh8@?Qwin^w_z?gYCW8!Lk-z!v&c$_)^`**$sJtwBCg0Kt$Vo&sdnp@yLyNst}c-I?05CMNv&K1 zg#z-#awcB~{edPbpWwNB^rpmxF_y<#`W)T9!$etM;ZS{tI$l1_XW&^*@1;V(mC>is zp-NlPVd_IEu7=uXWwO9oXypN$%o!}R>u-lR`H0g^#nwKJA(muZJcHT{qNnO5HA{OP z;)EX`Z?-o-hAclLXQ<{G?t(fcaH%3zCsdrIinTi_7Uu=bw>)V;{w0lT?Yl|2_V7db z(PHcPJ7u&5drlKT6qa&VHBCnhs2RTuWDQR^6Y)LogT)UxW=@_q&SnDk&SYT30V56u zUR4;v%*{OAq!-kuPBqzAPt3agA8Z-F$p?ITA!vVG2p$B%*WJQd_yh`l6C(nqdy#)! z2QgeH#{fa?d^*xzzlHI-a|PD>FkyD7rTNwJSV~2T(=ff+-&FK;G2-%aPnK?jv66vj z-91<)6lUk^M-l!(G8}7M0H}HKuSv+mo%>AaLvm;Eb>9Fs81gzjC~SrZTLH&vYO^0= zD|Nz8w*c_UcMJ5a7Fn0~?&Kt$R#Y*_xPzV5X!ls3 zcUDI8{dMtlcC3|9--ew&T%P)MU%*BcAtGdQh?pJ4iVps+)T?!a+T4S7_hq_!kRiQn z9adg8zn(h!HZIIwVh-^3Gph9XvUP9bk$8;9&1t%}KHC3cd=_h~78kXg*My(nFxyjW{sHyKt63LesZJ*kVwEQB<$N^0jI?AKow|K$o zfUE7halquP47Ju3@4$G2_TuK=$<~UlBjMw);qbhqPrK5;#(Y=m;<9e9wZ?t@)s7I| znxf*J=i1l$S=C|6%{z_Ol)yW!hcz}!yG`BCVo#WD+Z(yI!k%~VgS_E`q@Tz_N=uMn z_~*;ybo4#Emi^TZ!WOdHf{84t^7Qz<9KRIUX&pC%XGnk7&EDAucEXf$*vR$byqXG+ zDTXs)<?oS&p1yZ&zV zmeXo^DKe$AAP4|sm@2ob|#z3(k+M;J>LJJ zot7V=9!jK}vZnt}4zHb$y+(Zt`=n@J7K%9LP=6GyG3{mH7I*wQ=VHlfA#Dezj_cDLq2+8v+Juijpuq=vk2BCJ zr^}KX)60961Pqpem89d)$NlXeyQX&j9^|mG*H`MsYvNsq#-|6MeV{z znVQoleHo|EmrV!T>CuNEB1(rl96t}zf#z2dJJbDT{UesPyBJcj505WVJj>x+_7u%K z)y^aKv=D^w*Iz`Rr#zVq5e8@RPMx(eixQ96x8HS7?7e94P~OdtJ&m_7r&9UcAnq%N0Y1x^|bt8dGGa zH(MAQuq8@)P;E~lCfw4j=Q{L<;RhwBUqGud^?$3#g>E~It zWmM*z3Hbdk%d2PlTX=8BP`|TL%c3(jxhlu< z$hz9F*eZ6}Z1`}DL+7sf`s5G6?gWO49zFpU#dtHnfF;F0F26UfK{ZY^RDUkN=%Y`c zG5&{ezG)i0V2FwARsAwX z>C>=!eW}6Y;dW+?kUo#9Hohm$AB(2+N~H5zG#=2}p{a zUh+bgBX>aBged;^p5F~Y{mr*AyQfq1W?*xt2uhQs!De*%0&B%;+0hks3(%N>B-hrF@}Pi$@b$u+{8m|1pa)}(!dIqx=*~Te`cE?P{JCGZ{*!J!_g?G&LbRT{A^)EvNpkMp*>?CpNW*i_IsTI_ym0Od z^M4YB=gt*<`cI1RfByM@bKU>HIP9y#mENb{$QZ<0Y&J$J^aa*OW+3sx)=>#UJ_Ce= z2ApB!9$ihxnfC*=Ps8t$0D&Uf)aY$ix@d+D8JzaG^+e3Y)i&o|jsp0K!=Ub$8fx>5 z;98ravh1z)75zI*hkYi2yM>i&EkL%-CDXg1E=t&~{*omz?aw_xG_p~8=eBYOr-BRy zM_dhl%J@qrkPLui213NB$1dGpLwpkm6kDjod+t2~Oiu_vT#y}xEvpv^Ci`(zNsi~9 zkDVzER)>39jLu|4dm!7zw4vt*rs&KjP@Q+WAeJZnZXtU&S9-w)TjW1I9m$*%jRdHw zR!3CMEUV^lZecnWeL7#B>cj0nC{#CJJ9V5O` zP{Y)%C19PlR)A!Z4(hJ;C%8o-y3p|2ohP>Z9Iy*fx^~Qfcr*k|r5OIyhZ#Vo)wr1P zFVBp@(^|d3Z^mJwTlqs3Vr>}M7lh$;dbbd-XAlL0+m~MaMbJXl~rdf5z zQO1&XygAw;?ep2Z0gEjjOgsJFi1AJaaT(Hi(j>u9*WFV0WTBi;?Fs{4%c?cmt+*h*TvyR0Mhtk-3QUhhsJqOZk%XALWr7G57woS9xhE7ji z%tW*R9nuCU4!je{Y+we4q$`_^htO{8s!prpl6C^I_@x&J^*7l&+D|%&fEv$u1DLJL zX~=f;fmELGUA+PuU;m&85UJ}F+VMIV4C zJm$Dz{5__QjzwZcO%eFd6bhud=cY0p*p;isi}~5Rp+!oQW)$en`KgNCRo(`I=edUX z;D6FO@c7Kgv-rka8~ULiFLubJ2fEMC)z1rzuV6RK!j(@oMr@{mnI$QOTw(2pLp>%u zIb5`0&4^!`T|J-CxJB8y<19%FWF(d)ZP1;(nX(GW)u|X$J9$J40;H_C(Fc2!viF-m zrECJv#m?rTh~tb_?HT==4s&d+OC&)hi?IO=W#LmwI5kQh1(9N2_OGccU!7t*Q_t68 zQO6?8J|}%iM4y}FFaQrNW@(lKKm1M9&*x_fR_^l`qeuBXS*ER|SHH`lZBw3nbkrlN+}zugCU3HEz^^o#F&Y3KFNLLT z*SL}mSY5}h187OX++sYRwKYIFb>*~zV93+NY16208nI}fgFmu_1Vs^nc>1-oXJ^&Sg0W)_UoPs2CP29nJx zqs9E9yBz|^M$aadJAhnIMN5JVG;-NsKssXF2lgF^%GW37!PwdOD3HZ zICbh?iOVFb$wg-^Ld{B=RWb^YaX(T=^PH;1VHLhmoW;54ac4K`Dq?3@qOB{o2W}FL z?kW_n!2xg4qhfr6omx7%G;+)L6YteCvc0>Oa&p*V9Rvb~dBOHN0Dzn7?K@Q5X(bc4 z=9g#ET1U4SgSk28nu z(<5toWpwfK?+Z;T^FXN8my~j!GT$#^^xF16PuB>*ysxt_U1X%o-Um(;RA%N43g{KDn@e9(CRm?H6Awo<~b&U)g#bCNFwvj+l^7&1f zj#rb)J)q1TD|e08t8(hKF|0=P>TL~OTGX}o;_y181fEB9^XFSiEHUiF(PFBdv><5_ zhvU|=+NTtt@N-*<z4H}o`Z+*&X% zoK{1O(p&W0gSE4=YEO7a?k7c1Kink$e{1hMqncW{ZG&DLDA+wz3m_ei^p1!a0Tt;W zU3!%&z1X5hAV_ZkR6sBj7zFkh z$==y}mAU4eOO%+*=e^UT%WshHgx3R_MJ5p2ZRK|AgO@6_&GjTyZs0Qc6zJK z{CcfceBJ>rB=PM<2dgJ;rxgJ_DbL>>B0R=07B$C^HN=p4g=cC?e6F~TYdiE-n3S4y5%pFu8 z4jeHOJ6%?@8!x$(s@P)oGyLcemlQ^$W5J3Lp^$rzSkJJ1Q-Kgs`>WOETVD8*H;xY| zG8i^p8curDy=~lOC|KZ0pyzf4W@{p|%p(MZn|{>PJUXkH*)-17^P+wm;!~}5p=|Q* zH9x4oyK)QtFaw^}N+fnz$)VNiscLSso%wpEzq(z10rM}ufc4^jJj?kF=3b+S zgD!uh2o#)UPsZ9V$?oMmXmP(x)!H5zh1=$yx7B0j56o>?ZjWDUbTR?sv3_as-qT4H zZ~L1(o^!G%$4WRUYi_s6_{}ve1~AS=Xr(s0Cx(tV9Ip$tPz zzxRNY+PUMc#;hjvEN`WNjf!ioT)j1gxzyLM%FrBm$0teg^4j)43xy^|myQQD=wuSypqcBwo9YVjZz_M_kwDXR{sJ_>4YOP;8@#2Wp9pjbWht1}# zO3qaq7A?{#XcDfC+{&G!PD$Ma>C)tTox+@?aEE9epR*(*$eXA`-x) zaK7=KMo`F_rEq&w#^we$n_FSxg-%CtxWUtza&$fqPwGrF81od+N;^k%T%qoCNv+mM zWm7b0cW?h{a})R9GW0Yt;BNnR-m6@>_Uy@0$DE}0w{%lGF*Ug*zTSMy=!1-YgBD)x ztVM*{C{*+<=B37kC8R=RP?Q0{M4yUPN+r#_2h&{7%cWSbFvditcn#>asbopm53iu2P9)wI2Ifv}i_{p)L`8DgT#NqQUy^N&4X#d6YoIz3)*cI#`TD_?^QuZYxL|Q+S4-{! z8)!pRlO-RJ{UUZROT&18p}?FF`^nTt&TH;+H-(2Of&cF7@M8Oc&pGDcQ;TPLYjazn zYxG_uMX7SuPZLNvD9&SC0GLJ3bjf5To>7-{?vx38#K1ZEE#sX~Z}O5k4KPD>mQ4T9 zQ*6@f&#U+&Z_GfixpI72{*MrGv%#XYLhmbUVxJr|^=aC7>l}Vj_uslXcZ=}kCEl~v zh|r(Pd!cR?ca5gJ%|nd@_W-^_{&bt{JDIT9|E$44+WZ+&?YET0i)@oAz10&|-~W)K z9vYlOuJ8jb(*ad8g)eZEcEOh_=hsev zFBzGy+w2zmHOFp|W1h0k?Q^%USw9nFbD($@D(=6Pdi2b-ey`6@z)VZ77VYA1rC<5u z)J#p$e!55n=qkt(Dy>WJh&kb<#390uoAd5j0->gr5hX_0YpC7=He?!cxO7EcoClEE~h7a%IEeM49Q_g=K_=?kc>ZNa^L7M_1}6Es$FoXU^Mg$1r}&s?It@&@2lQS;;VI&3(9lWtX$Gr{DpA?` zh1_%FlSn>`Tka%Js8A2V*YQh$`%CN2({1Rg&FY|G<|Yq?HG=!~{zko#)Fy0Ti#ig( zhAhXD4LY0899z?9=fN@~;Ca2mXvzyrm%7G6&wFq4nS!WIGY_=HZi>bWBXMJ6&&CkC z8@Y}ipz3253$6%Hmsb-WsJH;8rcsYno@=yGeH5zC?UgnA5Nqmxxh>cEVAUh;MPxyP zdZTPnB5PGCMRwD56Fn0LCH)^l_q<<~4mDnY;jMS$wX(Qa`$4spi(f1mm`&>dYLNv zDrK|D1?WPj$4|o$UR_k-Sdw*;D#YbUsZc=6XrJZ;MV4?W%?2bDtmhkBaYyb*V~6TE z^nHNEDdRqu=-gA%Qc>kvUP%nRjJUeY$p()pG(QA?@>@)`{|!KPgv7`#QA>Z>SJr==aohT&FdkMaSwZd@DK-`E_BFO z!Y&IMRhp>Be;8@rZN2EyJ!ifkAKa51_s-zGUoK;s74$e!g6U%k$ND4>#tyB|*TTec z**e#ZFmP9YxWuilPtRNa%2)CNNUs%Bt%{pBa%$I{1-c6#qB?J56!mDMm=YfpF$V(SJ|V+$`Td}462jPc>6Svgs+d ziXl_?Au^9aP!25wi0QT*{w8?k*bI(51IcL(f~Iu$nrjn#J+tv-%<|zwY5HJ=V{#zj zrp8Wd_dlqP(}Mm%xiPlDHh!ebtpofflFIELi97c<9znK~<#*YEAsQw-8Tg(@NhvlP z(s5(w@07tjU?2GnG9X?(JPx^{3Wzf_Dius*V-ybgGy(T$-=qo0F~K?PCMkX^xYO-) z$V_Ol>t+e2-2aB+7H>lT&MM(nx8g*?d2Tb7cx6#}17j;3O_Y0STy&jgbpjhE zqQIN9F+bBuyWCZ$VXa$U)S}+a?&1-6W99#NWB;{n_9UGBqwM}Jf~j5E(i$q;gk9GC z?u5~!Z-eRbR)po>a#!EABy)q?=&Jl6{(@^!Ak}IS+wZEA?|db6yL>Y6YP(68C4f8OmdJVG1?+RXn+=4C;-Qd}D|w9n%Ih#F`X4TP;#h_!O-7g@ z!j=b8NB5J8EH)!&5uW6ySgsg+)#xKgXhti#f5LE~Ir9iux@fM? zZ=2Zm&Gv2!q>;$0UAuu?z`++yZ=L=6>{MFaKEz<)Ufh6Ten=osF3=7P!Me&eR=`}x zaTk|^qu?p^W>Xzm&s%|cOY`)hxhH1}#u}^rMH-s+NuudoM1io)XN*UIdqe+BE}KkP zeG%>myc=+2^;0ivS1X4hpygPWKl}F$O-ozUwRbr4itF4)Wv(SaAP2rE@9pHNAD{ZF zIChrh4AvS3xzy}~!hl9Pgu|)5Itc#I z)+vzbyP$sg_11U#3#u>Ur8ZqX&$alZdCE-@0_TJ82sE?B(F6{#jAoy8{j0hPVsFdz zSjV>*5X$m6w0@}E0w1wveEz)%6mgXXF!y?=s8h{?QmHimu+!^rD^$#JG+QhiPm^>A ze4r$Rzz1!JX{DzY(OiM^0DWwH($Ylz`d2Yg-^rUY?mO>$^jTiakYUP%{Gk8fm!FV# zzyF=jkF#h)mc_~EpSh`&QVe031w!;Hi&8-9;#V|CB?ZD>UEX{IY8>kpia z&o^@LcS|n){YwUK(|s14z=B}{W_5MFvpj(tiT(onsUG60t#yIg8L9unLd6IScJ+pMyFD>Op#)MiFzPkZ8uhSDZs!aJfK>N>J^1&-Nf;TPzPCZ}BvB zoG;X@Hh^f;*-+Dk)>B!A_Xsr=HUT&V`=4%8QuZ%;I6z`p?AX`f3?@#*W*d(o`?LQ{ z)&MHJH-Tz)yg#lz&8iU`62J;>LdcAZA^vL;YrU`uR{B>F*hOiSqfNO$rKDXQ?1{^- z)ZPI4#*NGUlX#*Yzt-EgJ%c47*@3SVvrX`d8CBmOjUM9C`CdV5YMSrXC{?H21_9zl z%@98>n% z$7Xlh`{*JoA5vby#8@Jq_+``fs)GCk5<7yk+>0-dgLKx;JeaWv3*~W=dF(IL&WJ z?5Wd5X`T(FA)_46R@~l8CH%8`u8V;f_pLTHtjlah=SSeT?B$siT_wIM!X{qya zefQFQDOmE*KE!d;fApFsXdXnDptts3rD2K*n@j0fxy|l5(zCgau=OT_#Mx4}CO-8D8-C0?g$7KKb$%VJf%PHR5NRrs-9xri^zCR|^^<7CuVZ_a_{(^=WhkRP=6*Bxd<=>a zEZG;f`t@u6J=@g*01PbBXtSMR509A{EgeOhiCb!Rl@lPRP#~49|Jf>EC&C79W@5h< zV2~v`Z2vj>n|5iin3zd{#b;4b?=C@zyA{KK_t&5m6a>IRyx8s?fDFVP%rk~-s0`>P z)l(pT(1zWQR7;=CDt>H|uVX}lJ~eq!sVYX*vCCo1uR<0wu^$?hVVUv09vB(iO*{uM zZn0u^t)X?w%uQp1y`0>^<# z-Qv4Bdz6SriNW=_t^_}7K=_zp0q$`$MLP2}JBm5MU0GCVI;!>C$$KSpyiSt&VwJMA zuCHfjcXpsJEY=25w@`icrTRIifGt4&Ze=1V=V7|x}8$-lRKrd>XA?xPs4UD-}jO38fv*NmLpbd~Rl zmF=Jdb-O^vpm1{ym+W<>Y^~}w-TnthJST`6R1q^Q*K(z+@1Rw1!S)q}cesR3AtSt? z{K|5F#ZYMw8@s&Gxw#Z+?uvDy@zfe|Kn~04de;!QvzKs_o_=Btv$rrHL>kFOJY+M7&KmywW-|NKJtgg4yxjPmNz2?83f3q>1GrUqd*vyz#~nd#k!87+`K6t?k2D+vWJxR2cWT~OcGtsUF7hnaZ17A+^zyi zG=d;AdN?$i{|dT*aNojkb;<&-3hPoCos7YDXZiJ9ByEMBA==&s>bIr>wD zL+|=3qjb{4I+V6e*AhiaLr$QMvg>)tZ&+*Gey>o$LluM9%w}dAj)T;%RF##o)$hv} zabmVDYU$PDU{UqwXhVVXX8gVDpUS^q>Mcyszkd4m~SaZBg6 z@~gH{+3v*)?GeL+3rwfCG4DI1?^P|%&aZ`U2{e~%=DK&ZE+^q?RXQVWLmrxLYC$>LJNr-sLJ8K)S=VtBB#@pdqZZZ{oR}BPL%m{2z@nXr{?D!o85u!I;XJ6 z{Xbm(Kq6wjgu^)zll-(hml=t`Xu>OXQ8Yq2o%T;_Haa)OD{xi~())e|-e;q`tIdYQ zu+r~7K=4+-Yi{_mu7&3pMc*mr5RyHDK!oBt&x$@<%5c`RW|P2ki2UPkxN0~5*pipw z8S%GtczE_95N;Fb5;i^zhfV&aQQoc}fv+d65eNiP*YjPG+e0`qBI8}xDOH~RaO7o{ zWF}jK8^*&kyiR9WkxBSl(p?^(CNtsqo%}BR#FqxGRenkIeU~1kgD2s5Nq)ceIW%mh zDd~=NIEqZBo=fFIAg=NulbN2r>ndQrQ6$WaELsyS_r1SBe+nrp;|`zNw`?v$==n9P ziR=E{_YAshM&Da4aE%%^7MH-=SeKw~9Z>qUlD?cC&Z!p7r6$`gisph}`2Ik`tLWJO cXRrFw$Fdb8-A<~|J{Cev_0IKzYZj0H9r)ODb^rhX literal 0 HcmV?d00001 diff --git a/README.md b/README.md index 99aa50650..a4a059acd 100644 --- a/README.md +++ b/README.md @@ -128,6 +128,8 @@ * 数据报表 * 商城系统 * 微信公众号 +* ERP 系统 +* CRM 系统 > 友情提示:本项目基于 RuoYi-Vue 修改,**重构优化**后端的代码,**美化**前端的界面。 > @@ -247,23 +249,31 @@ | 🚀 | 会员分组 | 对会员进行分组,用于用户画像、内容推送等运营手段 | | 🚀 | 积分签到 | 回馈给签到、消费等行为的积分,会员可订单抵现、积分兑换等途径消耗 | +### ERP 系统 + +![功能图](/.image/common/erp-preview.png) + +演示地址: + ## 🐨 技术栈 ### 模块 -| 项目 | 说明 | -|--------------------------------------------------------------------------|--------------------| -| `yudao-dependencies` | Maven 依赖版本管理 | -| `yudao-framework` | Java 框架拓展 | -| `yudao-server` | 管理后台 + 用户 APP 的服务端 | -| `yudao-module-system` | 系统功能的 Module 模块 | -| `yudao-module-member` | 会员中心的 Module 模块 | -| `yudao-module-infra` | 基础设施的 Module 模块 | -| `yudao-module-bpm` | 工作流程的 Module 模块 | -| `yudao-module-pay` | 支付系统的 Module 模块 | -| `yudao-module-mall` | 商城系统的 Module 模块 | -| `yudao-module-mp` | 微信公众号的 Module 模块 | -| `yudao-module-report` | 大屏报表 Module 模块 | +| 项目 | 说明 | +|-----------------------|--------------------| +| `yudao-dependencies` | Maven 依赖版本管理 | +| `yudao-framework` | Java 框架拓展 | +| `yudao-server` | 管理后台 + 用户 APP 的服务端 | +| `yudao-module-system` | 系统功能的 Module 模块 | +| `yudao-module-member` | 会员中心的 Module 模块 | +| `yudao-module-infra` | 基础设施的 Module 模块 | +| `yudao-module-bpm` | 工作流程的 Module 模块 | +| `yudao-module-pay` | 支付系统的 Module 模块 | +| `yudao-module-mall` | 商城系统的 Module 模块 | +| `yudao-module-erp` | ERP 系统的 Module 模块 | +| `yudao-module-crm` | CRM 系统的 Module 模块 | +| `yudao-module-mp` | 微信公众号的 Module 模块 | +| `yudao-module-report` | 大屏报表 Module 模块 | ### 框架 diff --git a/yudao-framework/yudao-spring-boot-starter-web/src/main/java/cn/iocoder/yudao/framework/banner/core/BannerApplicationRunner.java b/yudao-framework/yudao-spring-boot-starter-web/src/main/java/cn/iocoder/yudao/framework/banner/core/BannerApplicationRunner.java index 19aaf046c..028ac8d71 100644 --- a/yudao-framework/yudao-spring-boot-starter-web/src/main/java/cn/iocoder/yudao/framework/banner/core/BannerApplicationRunner.java +++ b/yudao-framework/yudao-spring-boot-starter-web/src/main/java/cn/iocoder/yudao/framework/banner/core/BannerApplicationRunner.java @@ -46,6 +46,10 @@ public class BannerApplicationRunner implements ApplicationRunner { if (isNotPresent("cn.iocoder.yudao.module.trade.framework.web.config.TradeWebConfiguration")) { System.out.println("[商城系统 yudao-module-mall - 已禁用][参考 https://doc.iocoder.cn/mall/build/ 开启]"); } + // ERP 系统 + if (isNotPresent("cn.iocoder.yudao.module.erp.framework.web.config.ErpWebConfiguration")) { + System.out.println("[ERP 系统 yudao-module-erp - 已禁用][参考 https://doc.iocoder.cn/erp/build/ 开启]"); + } // 支付平台 if (isNotPresent("cn.iocoder.yudao.module.pay.framework.pay.config.PayConfiguration")) { System.out.println("[支付系统 yudao-module-pay - 已禁用][参考 https://doc.iocoder.cn/pay/build/ 开启]"); diff --git a/yudao-framework/yudao-spring-boot-starter-web/src/main/java/cn/iocoder/yudao/framework/web/core/handler/GlobalExceptionHandler.java b/yudao-framework/yudao-spring-boot-starter-web/src/main/java/cn/iocoder/yudao/framework/web/core/handler/GlobalExceptionHandler.java index c26628b9a..c3a8f0c62 100644 --- a/yudao-framework/yudao-spring-boot-starter-web/src/main/java/cn/iocoder/yudao/framework/web/core/handler/GlobalExceptionHandler.java +++ b/yudao-framework/yudao-spring-boot-starter-web/src/main/java/cn/iocoder/yudao/framework/web/core/handler/GlobalExceptionHandler.java @@ -313,7 +313,13 @@ public class GlobalExceptionHandler { return CommonResult.error(NOT_IMPLEMENTED.getCode(), "[商城系统 yudao-module-mall - 已禁用][参考 https://doc.iocoder.cn/mall/build/ 开启]"); } - // 5. 支付平台 + // 5. ERP 系统 + if (message.contains("erp_")) { + log.error("[ERP 系统 yudao-module-erp - 表结构未导入][参考 https://doc.iocoder.cn/erp/build/ 开启]"); + return CommonResult.error(NOT_IMPLEMENTED.getCode(), + "[ERP 系统 yudao-module-erp - 表结构未导入][参考 https://doc.iocoder.cn/erp/build/ 开启]"); + } + // 6. 支付平台 if (message.contains("pay_")) { log.error("[支付模块 yudao-module-pay - 表结构未导入][参考 https://doc.iocoder.cn/pay/build/ 开启]"); return CommonResult.error(NOT_IMPLEMENTED.getCode(), diff --git a/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/framework/package-info.java b/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/framework/package-info.java new file mode 100644 index 000000000..af7bc123c --- /dev/null +++ b/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/framework/package-info.java @@ -0,0 +1,6 @@ +/** + * 属于 erp 模块的 framework 封装 + * + * @author 芋道源码 + */ +package cn.iocoder.yudao.module.erp.framework; diff --git a/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/framework/web/config/ErpWebConfiguration.java b/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/framework/web/config/ErpWebConfiguration.java new file mode 100644 index 000000000..f87e04047 --- /dev/null +++ b/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/framework/web/config/ErpWebConfiguration.java @@ -0,0 +1,24 @@ +package cn.iocoder.yudao.module.erp.framework.web.config; + +import cn.iocoder.yudao.framework.swagger.config.YudaoSwaggerAutoConfiguration; +import org.springdoc.core.models.GroupedOpenApi; +import org.springframework.context.annotation.Bean; +import org.springframework.context.annotation.Configuration; + +/** + * erp 模块的 web 组件的 Configuration + * + * @author 芋道源码 + */ +@Configuration(proxyBeanMethods = false) +public class ErpWebConfiguration { + + /** + * erp 模块的 API 分组 + */ + @Bean + public GroupedOpenApi tradeGroupedOpenApi() { + return YudaoSwaggerAutoConfiguration.buildGroupedOpenApi("erp"); + } + +} diff --git a/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/framework/web/package-info.java b/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/framework/web/package-info.java new file mode 100644 index 000000000..70f70c035 --- /dev/null +++ b/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/framework/web/package-info.java @@ -0,0 +1,4 @@ +/** + * trade 模块的 web 配置 + */ +package cn.iocoder.yudao.module.erp.framework.web; diff --git a/yudao-server/pom.xml b/yudao-server/pom.xml index ff17b298d..4ead0bba8 100644 --- a/yudao-server/pom.xml +++ b/yudao-server/pom.xml @@ -88,11 +88,11 @@ - - cn.iocoder.boot - yudao-module-crm-biz - ${revision} - + + + + + diff --git a/yudao-server/src/main/java/cn/iocoder/yudao/server/controller/DefaultController.java b/yudao-server/src/main/java/cn/iocoder/yudao/server/controller/DefaultController.java index ab626b1e7..7aba89997 100644 --- a/yudao-server/src/main/java/cn/iocoder/yudao/server/controller/DefaultController.java +++ b/yudao-server/src/main/java/cn/iocoder/yudao/server/controller/DefaultController.java @@ -35,6 +35,12 @@ public class DefaultController { "[商城系统 yudao-module-mall - 已禁用][参考 https://doc.iocoder.cn/mall/build/ 开启]"); } + @RequestMapping("/admin-api/erp/**") + public CommonResult erp404() { + return CommonResult.error(NOT_IMPLEMENTED.getCode(), + "[ERP 模块 yudao-module-erp - 已禁用][参考 https://doc.iocoder.cn/erp/build/ 开启]"); + } + @RequestMapping(value = {"/admin-api/report/**"}) public CommonResult report404() { return CommonResult.error(NOT_IMPLEMENTED.getCode(), From c777237d93986daf208f82794956cd96d8414843 Mon Sep 17 00:00:00 2001 From: YunaiV Date: Sat, 17 Feb 2024 10:11:04 +0800 Subject: [PATCH 113/119] =?UTF-8?q?=E2=9C=A8=20=E5=A2=9E=E5=8A=A0=20ERP=20?= =?UTF-8?q?=E7=B3=BB=E7=BB=9F=E7=9A=84=E4=BB=8B=E7=BB=8D?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index a4a059acd..1ec492f83 100644 --- a/README.md +++ b/README.md @@ -251,7 +251,7 @@ ### ERP 系统 -![功能图](/.image/common/erp-preview.png) +![功能图](/.image/common/erp-feature.png) 演示地址: From 5955f39e24aa0de718ac91f33f1539ed78a2cbaf Mon Sep 17 00:00:00 2001 From: YunaiV Date: Sat, 17 Feb 2024 18:02:48 +0800 Subject: [PATCH 114/119] =?UTF-8?q?=F0=9F=93=96=20CRM=EF=BC=9Acode=20revie?= =?UTF-8?q?w=20=E5=BE=85=E5=8A=9E=E9=A1=B9=E7=9B=AE=E7=9A=84=E5=AE=9E?= =?UTF-8?q?=E7=8E=B0?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../contract/vo/CrmContractPageReqVO.java | 8 ++++++++ .../vo/plan/CrmReceivablePlanPageReqVO.java | 18 ++++++++++++------ .../vo/receivable/CrmReceivablePageReqVO.java | 2 ++ .../dal/mysql/contract/CrmContractMapper.java | 7 ++----- .../receivable/CrmReceivablePlanMapper.java | 12 +++++------- 5 files changed, 29 insertions(+), 18 deletions(-) diff --git a/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/controller/admin/contract/vo/CrmContractPageReqVO.java b/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/controller/admin/contract/vo/CrmContractPageReqVO.java index 70529198a..c61a64ccf 100644 --- a/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/controller/admin/contract/vo/CrmContractPageReqVO.java +++ b/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/controller/admin/contract/vo/CrmContractPageReqVO.java @@ -2,6 +2,7 @@ package cn.iocoder.yudao.module.crm.controller.admin.contract.vo; import cn.iocoder.yudao.framework.common.pojo.PageParam; import cn.iocoder.yudao.framework.common.validation.InEnum; +import cn.iocoder.yudao.module.crm.enums.common.CrmAuditStatusEnum; import cn.iocoder.yudao.module.crm.enums.common.CrmSceneTypeEnum; import io.swagger.v3.oas.annotations.media.Schema; import lombok.Data; @@ -14,7 +15,13 @@ import lombok.ToString; @ToString(callSuper = true) public class CrmContractPageReqVO extends PageParam { + /** + * 过期类型 - 即将过期 + */ public static final Integer EXPIRY_TYPE_ABOUT_TO_EXPIRE = 1; + /** + * 过期类型 - 已过期 + */ public static final Integer EXPIRY_TYPE_EXPIRED = 2; @Schema(description = "合同编号", example = "XYZ008") @@ -34,6 +41,7 @@ public class CrmContractPageReqVO extends PageParam { private Integer sceneType; // 场景类型,为 null 时则表示全部 @Schema(description = "审批状态", example = "20") + @InEnum(CrmAuditStatusEnum.class) private Integer auditStatus; @Schema(description = "过期类型", example = "1") diff --git a/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/controller/admin/receivable/vo/plan/CrmReceivablePlanPageReqVO.java b/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/controller/admin/receivable/vo/plan/CrmReceivablePlanPageReqVO.java index a041fa030..3675fba1f 100644 --- a/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/controller/admin/receivable/vo/plan/CrmReceivablePlanPageReqVO.java +++ b/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/controller/admin/receivable/vo/plan/CrmReceivablePlanPageReqVO.java @@ -14,12 +14,18 @@ import lombok.ToString; @ToString(callSuper = true) public class CrmReceivablePlanPageReqVO extends PageParam { - // 待回款 - public final static Integer REMIND_NEEDED = 1; - // 已逾期 - public final static Integer REMIND_EXPIRED = 2; - // 已回款 - public final static Integer REMIND_RECEIVED = 3; + /** + * 提醒类型 - 待回款 + */ + public final static Integer REMIND_TYPE_NEEDED = 1; + /** + * 提醒类型 - 已逾期 + */ + public final static Integer REMIND_TYPE_EXPIRED = 2; + /** + * 提醒类型 - 已回款 + */ + public final static Integer REMIND_TYPE_RECEIVED = 3; @Schema(description = "客户编号", example = "18026") private Long customerId; diff --git a/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/controller/admin/receivable/vo/receivable/CrmReceivablePageReqVO.java b/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/controller/admin/receivable/vo/receivable/CrmReceivablePageReqVO.java index d47ca83f0..e1fe83087 100644 --- a/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/controller/admin/receivable/vo/receivable/CrmReceivablePageReqVO.java +++ b/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/controller/admin/receivable/vo/receivable/CrmReceivablePageReqVO.java @@ -2,6 +2,7 @@ package cn.iocoder.yudao.module.crm.controller.admin.receivable.vo.receivable; import cn.iocoder.yudao.framework.common.pojo.PageParam; import cn.iocoder.yudao.framework.common.validation.InEnum; +import cn.iocoder.yudao.module.crm.enums.common.CrmAuditStatusEnum; import cn.iocoder.yudao.module.crm.enums.common.CrmSceneTypeEnum; import io.swagger.v3.oas.annotations.media.Schema; import lombok.Data; @@ -28,6 +29,7 @@ public class CrmReceivablePageReqVO extends PageParam { private Integer sceneType; // 场景类型,为 null 时则表示全部 @Schema(description = "审批状态", example = "20") + @InEnum(CrmAuditStatusEnum.class) private Integer auditStatus; } diff --git a/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/dal/mysql/contract/CrmContractMapper.java b/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/dal/mysql/contract/CrmContractMapper.java index d553962ee..3ecd93fcb 100644 --- a/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/dal/mysql/contract/CrmContractMapper.java +++ b/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/dal/mysql/contract/CrmContractMapper.java @@ -58,18 +58,15 @@ public interface CrmContractMapper extends BaseMapperX { // Backlog: 即将到期的合同 LocalDateTime beginOfToday = LocalDateTimeUtil.beginOfDay(LocalDateTime.now()); LocalDateTime endOfToday = LocalDateTimeUtil.endOfDay(LocalDateTime.now()); - if (CrmContractPageReqVO.EXPIRY_TYPE_ABOUT_TO_EXPIRE.equals(pageReqVO.getExpiryType())) { - // 即将到期 + if (CrmContractPageReqVO.EXPIRY_TYPE_ABOUT_TO_EXPIRE.equals(pageReqVO.getExpiryType())) { // 即将到期 // TODO: @芋艿 需要配置 提前提醒天数 int REMIND_DAYS = 20; query.eq(CrmContractDO::getAuditStatus, CrmAuditStatusEnum.APPROVE.getStatus()) .between(CrmContractDO::getEndTime, beginOfToday, endOfToday.plusDays(REMIND_DAYS)); - } else if (CrmContractPageReqVO.EXPIRY_TYPE_EXPIRED.equals(pageReqVO.getExpiryType())) { - // 已到期 + } else if (CrmContractPageReqVO.EXPIRY_TYPE_EXPIRED.equals(pageReqVO.getExpiryType())) { // 已到期 query.eq(CrmContractDO::getAuditStatus, CrmAuditStatusEnum.APPROVE.getStatus()) .lt(CrmContractDO::getEndTime, endOfToday); } - return selectJoinPage(pageReqVO, CrmContractDO.class, query); } diff --git a/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/dal/mysql/receivable/CrmReceivablePlanMapper.java b/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/dal/mysql/receivable/CrmReceivablePlanMapper.java index 618a95750..b21d30c12 100644 --- a/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/dal/mysql/receivable/CrmReceivablePlanMapper.java +++ b/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/dal/mysql/receivable/CrmReceivablePlanMapper.java @@ -51,23 +51,21 @@ public interface CrmReceivablePlanMapper extends BaseMapperX Date: Sat, 17 Feb 2024 18:14:28 +0800 Subject: [PATCH 115/119] =?UTF-8?q?=F0=9F=93=96=20CRM=EF=BC=9Acode=20revie?= =?UTF-8?q?w=20=E5=95=86=E4=B8=9A=E6=99=BA=E8=83=BD=E7=9A=84=E6=8E=92?= =?UTF-8?q?=E8=A1=8C=E7=89=88?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../crm/dal/mysql/bi/CrmBiRankingMapper.java | 1 + .../crm/service/bi/CrmBiRankingService.java | 1 + .../mapper/bi/CrmBiRankingMapper.xml | 22 ++++++++++--------- 3 files changed, 14 insertions(+), 10 deletions(-) diff --git a/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/dal/mysql/bi/CrmBiRankingMapper.java b/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/dal/mysql/bi/CrmBiRankingMapper.java index 75dbc7a8a..9b71df7b6 100644 --- a/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/dal/mysql/bi/CrmBiRankingMapper.java +++ b/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/dal/mysql/bi/CrmBiRankingMapper.java @@ -77,4 +77,5 @@ public interface CrmBiRankingMapper { * @return 跟进客户数排行榜 */ List selectFollowCustomerCountRank(CrmBiRankReqVO rankReqVO); + } diff --git a/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/service/bi/CrmBiRankingService.java b/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/service/bi/CrmBiRankingService.java index 5520911a3..2ff28d385 100644 --- a/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/service/bi/CrmBiRankingService.java +++ b/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/service/bi/CrmBiRankingService.java @@ -76,4 +76,5 @@ public interface CrmBiRankingService { * @return 跟进客户数排行榜 */ List getFollowCustomerCountRank(CrmBiRankReqVO rankReqVO); + } diff --git a/yudao-module-crm/yudao-module-crm-biz/src/main/resources/mapper/bi/CrmBiRankingMapper.xml b/yudao-module-crm/yudao-module-crm-biz/src/main/resources/mapper/bi/CrmBiRankingMapper.xml index f8e5737a5..10030e0a7 100644 --- a/yudao-module-crm/yudao-module-crm-biz/src/main/resources/mapper/bi/CrmBiRankingMapper.xml +++ b/yudao-module-crm/yudao-module-crm-biz/src/main/resources/mapper/bi/CrmBiRankingMapper.xml @@ -13,7 +13,7 @@ #{userId} AND order_date between #{times[0],javaType=java.time.LocalDateTime} and - #{times[1],javaType=java.time.LocalDateTime} + #{times[1],javaType=java.time.LocalDateTime} GROUP BY owner_user_id @@ -28,7 +28,7 @@ #{userId} AND return_time between #{times[0],javaType=java.time.LocalDateTime} and - #{times[1],javaType=java.time.LocalDateTime} + #{times[1],javaType=java.time.LocalDateTime} GROUP BY owner_user_id @@ -43,7 +43,7 @@ #{userId} AND order_date between #{times[0],javaType=java.time.LocalDateTime} and - #{times[1],javaType=java.time.LocalDateTime} + #{times[1],javaType=java.time.LocalDateTime} GROUP BY owner_user_id @@ -59,7 +59,7 @@ #{userId} AND order_date between #{times[0],javaType=java.time.LocalDateTime} and - #{times[1],javaType=java.time.LocalDateTime} + #{times[1],javaType=java.time.LocalDateTime} GROUP BY owner_user_id @@ -73,7 +73,7 @@ #{userId} AND create_time between #{times[0],javaType=java.time.LocalDateTime} and - #{times[1],javaType=java.time.LocalDateTime} + #{times[1],javaType=java.time.LocalDateTime} GROUP BY owner_user_id @@ -87,14 +87,15 @@ #{userId} AND create_time between #{times[0],javaType=java.time.LocalDateTime} and - #{times[1],javaType=java.time.LocalDateTime} + #{times[1],javaType=java.time.LocalDateTime} GROUP BY owner_user_id From 0fba56cda88f443e4fd2fb651a99ef5cfba349de Mon Sep 17 00:00:00 2001 From: YunaiV Date: Sat, 17 Feb 2024 19:14:48 +0800 Subject: [PATCH 116/119] =?UTF-8?q?=F0=9F=93=96=20CRM=EF=BC=9Acode=20revie?= =?UTF-8?q?w=20=E5=90=88=E5=90=8C=E9=80=BB=E8=BE=91?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../business/vo/business/CrmBusinessSaveReqVO.java | 3 ++- .../admin/contract/CrmContractController.java | 3 ++- .../admin/contract/vo/CrmContractRespVO.java | 1 + .../crm/convert/contract/CrmContractConvert.java | 5 ++--- .../dataobject/contract/CrmContractProductDO.java | 2 ++ .../mysql/business/CrmBusinessProductMapper.java | 10 ++++++---- .../mysql/contract/CrmContractProductMapper.java | 1 + .../service/business/CrmBusinessServiceImpl.java | 13 +++++++------ .../business/bo/CrmBusinessUpdateProductReqBO.java | 1 + .../service/contract/CrmContractServiceImpl.java | 11 +++++++---- .../service/customer/CrmCustomerServiceImpl.java | 4 ++-- 11 files changed, 33 insertions(+), 21 deletions(-) diff --git a/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/controller/admin/business/vo/business/CrmBusinessSaveReqVO.java b/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/controller/admin/business/vo/business/CrmBusinessSaveReqVO.java index c3b167ef1..0be6264eb 100644 --- a/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/controller/admin/business/vo/business/CrmBusinessSaveReqVO.java +++ b/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/controller/admin/business/vo/business/CrmBusinessSaveReqVO.java @@ -77,6 +77,7 @@ public class CrmBusinessSaveReqVO { @Schema(description = "联系人编号", example = "110") private Long contactId; // 使用场景,在【联系人详情】添加商机时,如果需要关联两者,需要传递 contactId 字段 + // TODO @puhui999:传递 items 就行啦; @Schema(description = "产品列表") private List productItems; @@ -86,7 +87,7 @@ public class CrmBusinessSaveReqVO { @AllArgsConstructor public static class CrmBusinessProductItem { - @Schema(description = "产品编号", example = "20529") + @Schema(description = "产品编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "20529") @NotNull(message = "产品编号不能为空") private Long id; diff --git a/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/controller/admin/contract/CrmContractController.java b/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/controller/admin/contract/CrmContractController.java index 7574e534a..ace5d1817 100644 --- a/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/controller/admin/contract/CrmContractController.java +++ b/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/controller/admin/contract/CrmContractController.java @@ -46,6 +46,7 @@ import static cn.iocoder.yudao.framework.common.pojo.CommonResult.success; import static cn.iocoder.yudao.framework.common.util.collection.CollectionUtils.*; import static cn.iocoder.yudao.framework.operatelog.core.enums.OperateTypeEnum.EXPORT; import static cn.iocoder.yudao.framework.security.core.util.SecurityFrameworkUtils.getLoginUserId; +import static java.util.Collections.singletonList; @Tag(name = "管理后台 - CRM 合同") @RestController @@ -102,7 +103,7 @@ public class CrmContractController { } // 2. 拼接合同信息 - List respVOList = buildContractDetailList(Collections.singletonList(contract)); + List respVOList = buildContractDetailList(singletonList(contract)); return success(respVOList.get(0)); } diff --git a/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/controller/admin/contract/vo/CrmContractRespVO.java b/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/controller/admin/contract/vo/CrmContractRespVO.java index 6b60afc2a..da6239414 100644 --- a/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/controller/admin/contract/vo/CrmContractRespVO.java +++ b/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/controller/admin/contract/vo/CrmContractRespVO.java @@ -132,6 +132,7 @@ public class CrmContractRespVO { @Schema(description = "产品列表") private List productItems; + // TODO @puhui999:可以直接叫 Item @Schema(description = "产品列表") @Data @NoArgsConstructor diff --git a/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/convert/contract/CrmContractConvert.java b/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/convert/contract/CrmContractConvert.java index 444876040..0d2e49934 100644 --- a/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/convert/contract/CrmContractConvert.java +++ b/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/convert/contract/CrmContractConvert.java @@ -61,9 +61,8 @@ public interface CrmContractConvert { List productList) { respVO.setProductItems(CollectionUtils.convertList(productList, product -> { CrmContractRespVO.CrmContractProductItemRespVO productItemRespVO = BeanUtils.toBean(product, CrmContractRespVO.CrmContractProductItemRespVO.class); - findAndThen(contractProductMap, product.getId(), contractProduct -> { - productItemRespVO.setCount(contractProduct.getCount()).setDiscountPercent(contractProduct.getDiscountPercent()); - }); + findAndThen(contractProductMap, product.getId(), contractProduct -> + productItemRespVO.setCount(contractProduct.getCount()).setDiscountPercent(contractProduct.getDiscountPercent())); return productItemRespVO; })); } diff --git a/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/dal/dataobject/contract/CrmContractProductDO.java b/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/dal/dataobject/contract/CrmContractProductDO.java index f0f506857..bc977c78f 100644 --- a/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/dal/dataobject/contract/CrmContractProductDO.java +++ b/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/dal/dataobject/contract/CrmContractProductDO.java @@ -57,6 +57,8 @@ public class CrmContractProductDO extends BaseDO { private Integer discountPercent; /** * 总计价格(折扣后价格) + * + * TODO @puhui999:可以写下计算公式哈; */ private Integer totalPrice; diff --git a/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/dal/mysql/business/CrmBusinessProductMapper.java b/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/dal/mysql/business/CrmBusinessProductMapper.java index 35fccdbdf..2d1471c73 100644 --- a/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/dal/mysql/business/CrmBusinessProductMapper.java +++ b/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/dal/mysql/business/CrmBusinessProductMapper.java @@ -16,15 +16,17 @@ import java.util.List; @Mapper public interface CrmBusinessProductMapper extends BaseMapperX { - default void deleteByBusinessId(Long id) { // TODO @lzxhqs:第一个方法,和类之间最好空一行; - delete(CrmBusinessProductDO::getBusinessId, id); + // TODO @puhui999:用不到的方法,看看是不是删除哈 + default void deleteByBusinessId(Long getBusinessId) { // TODO @lzxhqs:第一个方法,和类之间最好空一行; + delete(CrmBusinessProductDO::getBusinessId, getBusinessId); } - default CrmBusinessProductDO selectByBusinessId(Long id) { - return selectOne(CrmBusinessProductDO::getBusinessId, id); + default CrmBusinessProductDO selectByBusinessId(Long getBusinessId) { + return selectOne(CrmBusinessProductDO::getBusinessId, getBusinessId); } default List selectListByBusinessId(Long businessId) { + // TODO @puhui999:可以简化,selectList(CrmBusinessProductDO::getBusinessId, businessId) return selectList(new LambdaQueryWrapperX().eq(CrmBusinessProductDO::getBusinessId, businessId)); } diff --git a/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/dal/mysql/contract/CrmContractProductMapper.java b/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/dal/mysql/contract/CrmContractProductMapper.java index fd6347a9e..814024125 100644 --- a/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/dal/mysql/contract/CrmContractProductMapper.java +++ b/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/dal/mysql/contract/CrmContractProductMapper.java @@ -16,6 +16,7 @@ import java.util.List; @Mapper public interface CrmContractProductMapper extends BaseMapperX { + // TODO @puhui999:用不到的方法,看看是不是删除哈 default void deleteByContractId(Long contractId) { // TODO @lzxhqs:第一个方法,和类之间最好空一行; delete(CrmContractProductDO::getContractId, contractId); } diff --git a/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/service/business/CrmBusinessServiceImpl.java b/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/service/business/CrmBusinessServiceImpl.java index 5f80e5337..535578fd2 100644 --- a/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/service/business/CrmBusinessServiceImpl.java +++ b/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/service/business/CrmBusinessServiceImpl.java @@ -81,13 +81,13 @@ public class CrmBusinessServiceImpl implements CrmBusinessService { businessMapper.insert(business); // 1.2 插入商机关联商品 if (CollUtil.isNotEmpty(createReqVO.getProductItems())) { // 如果有的话 - List productList = convertBusinessProductList(createReqVO.getProductItems(), business.getId()); + List productList = buildBusinessProductList(createReqVO.getProductItems(), business.getId()); businessProductMapper.insertBatch(productList); // 更新合同商品总金额 businessMapper.updateById(new CrmBusinessDO().setId(business.getId()).setProductPrice( getSumValue(productList, CrmBusinessProductDO::getTotalPrice, Integer::sum))); } - // TODO 商机待定:在联系人的详情页,如果直接【新建商机】,则需要关联下。这里要搞个 CrmContactBusinessDO 表 + // TODO @puhui999:在联系人的详情页,如果直接【新建商机】,则需要关联下。这里要搞个 CrmContactBusinessDO 表 createContactBusiness(business.getId(), createReqVO.getContactId()); // 2. 创建数据权限 @@ -95,7 +95,7 @@ public class CrmBusinessServiceImpl implements CrmBusinessService { permissionService.createPermission(new CrmPermissionCreateReqBO().setBizType(CrmBizTypeEnum.CRM_BUSINESS.getType()) .setBizId(business.getId()).setUserId(userId).setLevel(CrmPermissionLevelEnum.OWNER.getLevel())); - // 4. 记录操作日志上下文 + // 3. 记录操作日志上下文 LogRecordContext.putVariable("business", business); return business.getId(); } @@ -121,7 +121,7 @@ public class CrmBusinessServiceImpl implements CrmBusinessService { CrmBusinessDO updateObj = BeanUtils.toBean(updateReqVO, CrmBusinessDO.class); businessMapper.updateById(updateObj); // 2.2 更新商机关联商品 - List productList = convertBusinessProductList(updateReqVO.getProductItems(), updateObj.getId()); + List productList = buildBusinessProductList(updateReqVO.getProductItems(), updateObj.getId()); updateBusinessProduct(productList, updateObj.getId()); // TODO @商机待定:如果状态发生变化,插入商机状态变更记录表 @@ -175,7 +175,8 @@ public class CrmBusinessServiceImpl implements CrmBusinessService { } } - private List convertBusinessProductList(List productItems, Long businessId) { + private List buildBusinessProductList(List productItems, + Long businessId) { // 校验商品存在 Set productIds = convertSet(productItems, CrmBusinessSaveReqVO.CrmBusinessProductItem::getId); List productList = productService.getProductList(productIds); @@ -235,7 +236,7 @@ public class CrmBusinessServiceImpl implements CrmBusinessService { @Override public void updateBusinessProduct(CrmBusinessUpdateProductReqBO updateProductReqBO) { // 更新商机关联商品 - List productList = convertBusinessProductList( + List productList = buildBusinessProductList( BeanUtils.toBean(updateProductReqBO.getProductItems(), CrmBusinessSaveReqVO.CrmBusinessProductItem.class), updateProductReqBO.getId()); updateBusinessProduct(productList, updateProductReqBO.getId()); } diff --git a/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/service/business/bo/CrmBusinessUpdateProductReqBO.java b/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/service/business/bo/CrmBusinessUpdateProductReqBO.java index 4291df262..34b2fa381 100644 --- a/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/service/business/bo/CrmBusinessUpdateProductReqBO.java +++ b/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/service/business/bo/CrmBusinessUpdateProductReqBO.java @@ -23,6 +23,7 @@ public class CrmBusinessUpdateProductReqBO { @NotNull(message = "商机编号不能为空") private Long id; + // TODO @芋艿:再想想 @NotEmpty(message = "产品列表不能为空") private List productItems; diff --git a/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/service/contract/CrmContractServiceImpl.java b/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/service/contract/CrmContractServiceImpl.java index fbf736699..79d05263c 100644 --- a/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/service/contract/CrmContractServiceImpl.java +++ b/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/service/contract/CrmContractServiceImpl.java @@ -61,7 +61,10 @@ import static cn.iocoder.yudao.module.system.enums.ErrorCodeConstants.USER_NOT_E @Validated public class CrmContractServiceImpl implements CrmContractService { - public static final String CONTRACT_APPROVE = "contract-approve"; // 合同审批流程标识 + /** + * BPM 合同审批流程标识 + */ + public static final String CONTRACT_APPROVE = "contract-approve"; @Resource private CrmContractMapper contractMapper; @@ -149,11 +152,11 @@ public class CrmContractServiceImpl implements CrmContractService { List newProductList = convertContractProductList(updateReqVO, contractId); List oldProductList = contractProductMapper.selectListByContractId(contractId); List> diffList = diffList(oldProductList, newProductList, (oldObj, newObj) -> { - boolean equal = ObjUtil.equal(oldObj.getProductId(), newObj.getProductId()); - if (equal) { + boolean match = ObjUtil.equal(oldObj.getProductId(), newObj.getProductId()); + if (match) { newObj.setId(oldObj.getId()); // 设置一下老的编号更新时需要使用 } - return equal; + return match; }); if (CollUtil.isNotEmpty(diffList.get(0))) { contractProductMapper.insertBatch(diffList.get(0)); diff --git a/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/service/customer/CrmCustomerServiceImpl.java b/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/service/customer/CrmCustomerServiceImpl.java index 8230ba4e2..bc02a6b71 100644 --- a/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/service/customer/CrmCustomerServiceImpl.java +++ b/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/service/customer/CrmCustomerServiceImpl.java @@ -266,10 +266,10 @@ public class CrmCustomerServiceImpl implements CrmCustomerService { CrmCustomerDO customer = initCustomer(importCustomer, importReqVO.getOwnerUserId()); customerMapper.insert(customer); respVO.getCreateCustomerNames().add(importCustomer.getName()); + // 1.2 创建数据权限 if (importReqVO.getOwnerUserId() != null) { - // 1.2 创建数据权限 permissionService.createPermission(new CrmPermissionCreateReqBO().setBizType(CrmBizTypeEnum.CRM_CUSTOMER.getType()) - .setBizId(customer.getId()).setUserId(importReqVO.getOwnerUserId()).setLevel(CrmPermissionLevelEnum.OWNER.getLevel())); // 设置当前操作的人为负责人 + .setBizId(customer.getId()).setUserId(importReqVO.getOwnerUserId()).setLevel(CrmPermissionLevelEnum.OWNER.getLevel())); } // 1.3 记录操作日志 getSelf().importCustomerLog(customer, false); From 63f322cb177a85b8e899bd15758a2f4c600fb041 Mon Sep 17 00:00:00 2001 From: YunaiV Date: Sat, 17 Feb 2024 20:35:48 +0800 Subject: [PATCH 117/119] =?UTF-8?q?=F0=9F=93=96=20CRM=EF=BC=9Acode=20revie?= =?UTF-8?q?w=20=E5=89=8D=E7=AB=AF=E7=9B=B4=E6=8E=A5=E4=B8=8A=E4=BC=A0?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../framework/file/core/client/FileClient.java | 6 +++--- ...ignedUrlBO.java => FilePresignedUrlRespDTO.java} | 8 +++++--- .../framework/file/core/client/s3/S3FileClient.java | 13 +++++-------- .../infra/controller/admin/file/FileController.java | 10 +++++----- .../admin/file/vo/file/FileCreateReqVO.java | 2 +- .../admin/file/vo/file/FilePresignedUrlRespVO.java | 10 ++++++++-- .../module/infra/service/file/FileService.java | 4 ++-- .../module/infra/service/file/FileServiceImpl.java | 11 +++++------ 8 files changed, 34 insertions(+), 30 deletions(-) rename yudao-framework/yudao-spring-boot-starter-file/src/main/java/cn/iocoder/yudao/framework/file/core/client/s3/{FilePresignedUrlBO.java => FilePresignedUrlRespDTO.java} (79%) diff --git a/yudao-framework/yudao-spring-boot-starter-file/src/main/java/cn/iocoder/yudao/framework/file/core/client/FileClient.java b/yudao-framework/yudao-spring-boot-starter-file/src/main/java/cn/iocoder/yudao/framework/file/core/client/FileClient.java index 81b7049db..2944ca72c 100644 --- a/yudao-framework/yudao-spring-boot-starter-file/src/main/java/cn/iocoder/yudao/framework/file/core/client/FileClient.java +++ b/yudao-framework/yudao-spring-boot-starter-file/src/main/java/cn/iocoder/yudao/framework/file/core/client/FileClient.java @@ -1,6 +1,6 @@ package cn.iocoder.yudao.framework.file.core.client; -import cn.iocoder.yudao.framework.file.core.client.s3.FilePresignedUrlBO; +import cn.iocoder.yudao.framework.file.core.client.s3.FilePresignedUrlRespDTO; /** * 文件客户端 @@ -45,10 +45,10 @@ public interface FileClient { /** * 获得文件预签名地址 * - * @param fileName 文件名称 + * @param path 相对路径 * @return 文件预签名地址 */ - default FilePresignedUrlBO getPresignedObjectUrl(String fileName) throws Exception { + default FilePresignedUrlRespDTO getPresignedObjectUrl(String path) throws Exception { throw new UnsupportedOperationException("不支持的操作"); } diff --git a/yudao-framework/yudao-spring-boot-starter-file/src/main/java/cn/iocoder/yudao/framework/file/core/client/s3/FilePresignedUrlBO.java b/yudao-framework/yudao-spring-boot-starter-file/src/main/java/cn/iocoder/yudao/framework/file/core/client/s3/FilePresignedUrlRespDTO.java similarity index 79% rename from yudao-framework/yudao-spring-boot-starter-file/src/main/java/cn/iocoder/yudao/framework/file/core/client/s3/FilePresignedUrlBO.java rename to yudao-framework/yudao-spring-boot-starter-file/src/main/java/cn/iocoder/yudao/framework/file/core/client/s3/FilePresignedUrlRespDTO.java index ce5f748d8..6048494ed 100644 --- a/yudao-framework/yudao-spring-boot-starter-file/src/main/java/cn/iocoder/yudao/framework/file/core/client/s3/FilePresignedUrlBO.java +++ b/yudao-framework/yudao-spring-boot-starter-file/src/main/java/cn/iocoder/yudao/framework/file/core/client/s3/FilePresignedUrlRespDTO.java @@ -5,17 +5,19 @@ import lombok.Data; import lombok.NoArgsConstructor; /** - * 文件预签名地址 BO + * 文件预签名地址 Response DTO * * @author owen */ +@Data @AllArgsConstructor @NoArgsConstructor -@Data -public class FilePresignedUrlBO { +public class FilePresignedUrlRespDTO { /** * 文件上传 URL(用于上传) + * + * 例如说: */ private String uploadUrl; diff --git a/yudao-framework/yudao-spring-boot-starter-file/src/main/java/cn/iocoder/yudao/framework/file/core/client/s3/S3FileClient.java b/yudao-framework/yudao-spring-boot-starter-file/src/main/java/cn/iocoder/yudao/framework/file/core/client/s3/S3FileClient.java index 8144ec7a8..e7b470bad 100644 --- a/yudao-framework/yudao-spring-boot-starter-file/src/main/java/cn/iocoder/yudao/framework/file/core/client/s3/S3FileClient.java +++ b/yudao-framework/yudao-spring-boot-starter-file/src/main/java/cn/iocoder/yudao/framework/file/core/client/s3/S3FileClient.java @@ -120,18 +120,15 @@ public class S3FileClient extends AbstractFileClient { } @Override - public FilePresignedUrlBO getPresignedObjectUrl(String fileName) throws Exception { + public FilePresignedUrlRespDTO getPresignedObjectUrl(String path) throws Exception { String uploadUrl = client.getPresignedObjectUrl(GetPresignedObjectUrlArgs.builder() .method(Method.PUT) .bucket(config.getBucket()) - .object(fileName) - /** - * 过期时间(秒数)取值范围:1秒 ~ 7天 - * {@link GetPresignedObjectUrlArgs.Builder#validateExpiry(int)} - */ - .expiry(10, TimeUnit.MINUTES) + .object(path) + .expiry(10, TimeUnit.MINUTES) // 过期时间(秒数)取值范围:1 秒 ~ 7 天 .build() ); - return new FilePresignedUrlBO(uploadUrl, config.getDomain() + "/" + fileName); + return new FilePresignedUrlRespDTO(uploadUrl, config.getDomain() + "/" + path); } + } diff --git a/yudao-module-infra/yudao-module-infra-biz/src/main/java/cn/iocoder/yudao/module/infra/controller/admin/file/FileController.java b/yudao-module-infra/yudao-module-infra-biz/src/main/java/cn/iocoder/yudao/module/infra/controller/admin/file/FileController.java index 0ebaffb05..7e1dea2e8 100644 --- a/yudao-module-infra/yudao-module-infra-biz/src/main/java/cn/iocoder/yudao/module/infra/controller/admin/file/FileController.java +++ b/yudao-module-infra/yudao-module-infra-biz/src/main/java/cn/iocoder/yudao/module/infra/controller/admin/file/FileController.java @@ -39,7 +39,7 @@ public class FileController { private FileService fileService; @PostMapping("/upload") - @Operation(summary = "上传文件") + @Operation(summary = "上传文件", description = "模式一:后端上传文件") @OperateLog(logArgs = false) // 上传文件,没有记录操作日志的必要 public CommonResult uploadFile(FileUploadReqVO uploadReqVO) throws Exception { MultipartFile file = uploadReqVO.getFile(); @@ -48,13 +48,13 @@ public class FileController { } @GetMapping("/presigned-url") - @Operation(summary = "获取文件预签名地址") - public CommonResult getFilePresignedUrl(@RequestParam("fileName") String fileName) throws Exception { - return success(fileService.getFilePresignedUrl(fileName)); + @Operation(summary = "获取文件预签名地址", description = "模式二:前端上传文件:用于前端直接上传七牛、阿里云 OSS 等文件存储器") + public CommonResult getFilePresignedUrl(@RequestParam("path") String path) throws Exception { + return success(fileService.getFilePresignedUrl(path)); } @PostMapping("/create") - @Operation(summary = "创建文件") + @Operation(summary = "创建文件", description = "模式二:前端上传文件:配合 presigned-url 接口,记录上传了上传的文件") public CommonResult createFile(@Valid @RequestBody FileCreateReqVO createReqVO) { return success(fileService.createFile(createReqVO)); } diff --git a/yudao-module-infra/yudao-module-infra-biz/src/main/java/cn/iocoder/yudao/module/infra/controller/admin/file/vo/file/FileCreateReqVO.java b/yudao-module-infra/yudao-module-infra-biz/src/main/java/cn/iocoder/yudao/module/infra/controller/admin/file/vo/file/FileCreateReqVO.java index 3486e573a..5daa3972e 100644 --- a/yudao-module-infra/yudao-module-infra-biz/src/main/java/cn/iocoder/yudao/module/infra/controller/admin/file/vo/file/FileCreateReqVO.java +++ b/yudao-module-infra/yudao-module-infra-biz/src/main/java/cn/iocoder/yudao/module/infra/controller/admin/file/vo/file/FileCreateReqVO.java @@ -24,7 +24,7 @@ public class FileCreateReqVO { @Schema(description = "文件 URL", requiredMode = Schema.RequiredMode.REQUIRED, example = "https://www.iocoder.cn/yudao.jpg") private String url; - @Schema(description = "文件MIME类型", example = "application/octet-stream") + @Schema(description = "文件 MIME 类型", example = "application/octet-stream") private String type; @Schema(description = "文件大小", example = "2048", requiredMode = Schema.RequiredMode.REQUIRED) diff --git a/yudao-module-infra/yudao-module-infra-biz/src/main/java/cn/iocoder/yudao/module/infra/controller/admin/file/vo/file/FilePresignedUrlRespVO.java b/yudao-module-infra/yudao-module-infra-biz/src/main/java/cn/iocoder/yudao/module/infra/controller/admin/file/vo/file/FilePresignedUrlRespVO.java index 7115db129..926133ebc 100644 --- a/yudao-module-infra/yudao-module-infra-biz/src/main/java/cn/iocoder/yudao/module/infra/controller/admin/file/vo/file/FilePresignedUrlRespVO.java +++ b/yudao-module-infra/yudao-module-infra-biz/src/main/java/cn/iocoder/yudao/module/infra/controller/admin/file/vo/file/FilePresignedUrlRespVO.java @@ -14,10 +14,16 @@ public class FilePresignedUrlRespVO { @Schema(description = "配置编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "11") private Long configId; - @Schema(description = "文件上传 URL", requiredMode = Schema.RequiredMode.REQUIRED, example = "https://www.iocoder.cn/yudao.jpg") + @Schema(description = "文件上传 URL", requiredMode = Schema.RequiredMode.REQUIRED, example = "https://s3.cn-south-1.qiniucs.com/ruoyi-vue-pro/758d3a5387507358c7236de4c8f96de1c7f5097ff6a7722b34772fb7b76b140f.png?X-Amz-Algorithm=AWS4-HMAC-SHA256&X-Amz-Credential=3TvrJ70gl2Gt6IBe7_IZT1F6i_k0iMuRtyEv4EyS%2F20240217%2Fcn-south-1%2Fs3%2Faws4_request&X-Amz-Date=20240217T123222Z&X-Amz-Expires=600&X-Amz-SignedHeaders=host&X-Amz-Signature=a29f33770ab79bf523ccd4034d0752ac545f3c2a3b17baa1eb4e280cfdccfda5") private String uploadUrl; - @Schema(description = "文件 URL", requiredMode = Schema.RequiredMode.REQUIRED, example = "https://www.iocoder.cn/yudao.jpg") + /** + * 为什么要返回 url 字段? + * + * 前端上传完文件后,需要使用该 URL 进行访问 + */ + @Schema(description = "文件访问 URL", requiredMode = Schema.RequiredMode.REQUIRED, + example = "https://test.yudao.iocoder.cn/758d3a5387507358c7236de4c8f96de1c7f5097ff6a7722b34772fb7b76b140f.png") private String url; } diff --git a/yudao-module-infra/yudao-module-infra-biz/src/main/java/cn/iocoder/yudao/module/infra/service/file/FileService.java b/yudao-module-infra/yudao-module-infra-biz/src/main/java/cn/iocoder/yudao/module/infra/service/file/FileService.java index b6d40dcb5..3ca9a2419 100644 --- a/yudao-module-infra/yudao-module-infra-biz/src/main/java/cn/iocoder/yudao/module/infra/service/file/FileService.java +++ b/yudao-module-infra/yudao-module-infra-biz/src/main/java/cn/iocoder/yudao/module/infra/service/file/FileService.java @@ -58,9 +58,9 @@ public interface FileService { /** * 生成文件预签名地址信息 * - * @param fileName 文件名称 + * @param path 文件路径 * @return 预签名地址信息 */ - FilePresignedUrlRespVO getFilePresignedUrl(String fileName) throws Exception; + FilePresignedUrlRespVO getFilePresignedUrl(String path) throws Exception; } diff --git a/yudao-module-infra/yudao-module-infra-biz/src/main/java/cn/iocoder/yudao/module/infra/service/file/FileServiceImpl.java b/yudao-module-infra/yudao-module-infra-biz/src/main/java/cn/iocoder/yudao/module/infra/service/file/FileServiceImpl.java index 8b4922a78..f7c4b0b8e 100644 --- a/yudao-module-infra/yudao-module-infra-biz/src/main/java/cn/iocoder/yudao/module/infra/service/file/FileServiceImpl.java +++ b/yudao-module-infra/yudao-module-infra-biz/src/main/java/cn/iocoder/yudao/module/infra/service/file/FileServiceImpl.java @@ -6,7 +6,7 @@ import cn.iocoder.yudao.framework.common.pojo.PageResult; import cn.iocoder.yudao.framework.common.util.io.FileUtils; import cn.iocoder.yudao.framework.common.util.object.BeanUtils; import cn.iocoder.yudao.framework.file.core.client.FileClient; -import cn.iocoder.yudao.framework.file.core.client.s3.FilePresignedUrlBO; +import cn.iocoder.yudao.framework.file.core.client.s3.FilePresignedUrlRespDTO; import cn.iocoder.yudao.framework.file.core.utils.FileTypeUtils; import cn.iocoder.yudao.module.infra.controller.admin.file.vo.file.FileCreateReqVO; import cn.iocoder.yudao.module.infra.controller.admin.file.vo.file.FilePageReqVO; @@ -71,10 +71,8 @@ public class FileServiceImpl implements FileService { @Override public Long createFile(FileCreateReqVO createReqVO) { - // 插入 FileDO file = BeanUtils.toBean(createReqVO, FileDO.class); fileMapper.insert(file); - // 返回 return file.getId(); } @@ -108,10 +106,11 @@ public class FileServiceImpl implements FileService { } @Override - public FilePresignedUrlRespVO getFilePresignedUrl(String fileName) throws Exception { + public FilePresignedUrlRespVO getFilePresignedUrl(String path) throws Exception { FileClient fileClient = fileConfigService.getMasterFileClient(); - FilePresignedUrlBO bo = fileClient.getPresignedObjectUrl(fileName); - return BeanUtils.toBean(bo, FilePresignedUrlRespVO.class, f -> f.setConfigId(fileClient.getId())); + FilePresignedUrlRespDTO presignedObjectUrl = fileClient.getPresignedObjectUrl(path); + return BeanUtils.toBean(presignedObjectUrl, FilePresignedUrlRespVO.class, + object -> object.setConfigId(fileClient.getId())); } } From 20f8cb1606e503749245e13863b26b13627aba60 Mon Sep 17 00:00:00 2001 From: YunaiV Date: Sat, 17 Feb 2024 21:01:59 +0800 Subject: [PATCH 118/119] =?UTF-8?q?=E2=9C=A8=202.0.1=20=E7=89=88=E6=9C=AC?= =?UTF-8?q?=E5=8F=91=E5=B8=83=E5=87=86=E5=A4=87?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- pom.xml | 8 +- sql/mysql/ruoyi-vue-pro.sql | 216 +++++++++++++++++++++++++++++++----- yudao-dependencies/pom.xml | 2 +- yudao-server/pom.xml | 20 ++-- 4 files changed, 206 insertions(+), 40 deletions(-) diff --git a/pom.xml b/pom.xml index 5cf738c52..3a66524bc 100644 --- a/pom.xml +++ b/pom.xml @@ -16,13 +16,13 @@ yudao-module-system yudao-module-infra - yudao-module-bpm + - yudao-module-crm - yudao-module-erp + + @@ -32,7 +32,7 @@ https://github.com/YunaiV/ruoyi-vue-pro - 2.0.0-snapshot + 2.0.1-snapshot 21 ${java.version} diff --git a/sql/mysql/ruoyi-vue-pro.sql b/sql/mysql/ruoyi-vue-pro.sql index 0a01aa9dc..3306b7c72 100644 --- a/sql/mysql/ruoyi-vue-pro.sql +++ b/sql/mysql/ruoyi-vue-pro.sql @@ -11,7 +11,7 @@ Target Server Version : 80200 (8.2.0) File Encoding : 65001 - Date: 26/01/2024 20:11:43 + Date: 17/02/2024 21:00:07 */ SET NAMES utf8mb4; @@ -385,7 +385,7 @@ CREATE TABLE `infra_api_error_log` ( `deleted` bit(1) NOT NULL DEFAULT b'0' COMMENT '是否删除', `tenant_id` bigint NOT NULL DEFAULT 0 COMMENT '租户编号', PRIMARY KEY (`id`) USING BTREE -) ENGINE = InnoDB AUTO_INCREMENT = 15093 CHARACTER SET = utf8mb4 COLLATE = utf8mb4_unicode_ci COMMENT = '系统异常日志'; +) ENGINE = InnoDB AUTO_INCREMENT = 15324 CHARACTER SET = utf8mb4 COLLATE = utf8mb4_unicode_ci COMMENT = '系统异常日志'; -- ---------------------------- -- Records of infra_api_error_log @@ -423,7 +423,7 @@ CREATE TABLE `infra_codegen_column` ( `update_time` datetime NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP COMMENT '更新时间', `deleted` bit(1) NOT NULL DEFAULT b'0' COMMENT '是否删除', PRIMARY KEY (`id`) USING BTREE -) ENGINE = InnoDB AUTO_INCREMENT = 2015 CHARACTER SET = utf8mb4 COLLATE = utf8mb4_unicode_ci COMMENT = '代码生成表字段定义'; +) ENGINE = InnoDB AUTO_INCREMENT = 2248 CHARACTER SET = utf8mb4 COLLATE = utf8mb4_unicode_ci COMMENT = '代码生成表字段定义'; -- ---------------------------- -- Records of infra_codegen_column @@ -461,7 +461,7 @@ CREATE TABLE `infra_codegen_table` ( `update_time` datetime NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP COMMENT '更新时间', `deleted` bit(1) NOT NULL DEFAULT b'0' COMMENT '是否删除', PRIMARY KEY (`id`) USING BTREE -) ENGINE = InnoDB AUTO_INCREMENT = 156 CHARACTER SET = utf8mb4 COLLATE = utf8mb4_unicode_ci COMMENT = '代码生成表定义'; +) ENGINE = InnoDB AUTO_INCREMENT = 171 CHARACTER SET = utf8mb4 COLLATE = utf8mb4_unicode_ci COMMENT = '代码生成表定义'; -- ---------------------------- -- Records of infra_codegen_table @@ -690,7 +690,7 @@ CREATE TABLE `infra_file` ( `update_time` datetime NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP COMMENT '更新时间', `deleted` bit(1) NOT NULL DEFAULT b'0' COMMENT '是否删除', PRIMARY KEY (`id`) USING BTREE -) ENGINE = InnoDB AUTO_INCREMENT = 1242 CHARACTER SET = utf8mb4 COLLATE = utf8mb4_unicode_ci COMMENT = '文件表'; +) ENGINE = InnoDB AUTO_INCREMENT = 1261 CHARACTER SET = utf8mb4 COLLATE = utf8mb4_unicode_ci COMMENT = '文件表'; -- ---------------------------- -- Records of infra_file @@ -879,7 +879,7 @@ CREATE TABLE `system_dict_data` ( `update_time` datetime NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP COMMENT '更新时间', `deleted` bit(1) NOT NULL DEFAULT b'0' COMMENT '是否删除', PRIMARY KEY (`id`) USING BTREE -) ENGINE = InnoDB AUTO_INCREMENT = 1486 CHARACTER SET = utf8mb4 COLLATE = utf8mb4_unicode_ci COMMENT = '字典数据表'; +) ENGINE = InnoDB AUTO_INCREMENT = 1508 CHARACTER SET = utf8mb4 COLLATE = utf8mb4_unicode_ci COMMENT = '字典数据表'; -- ---------------------------- -- Records of system_dict_data @@ -1236,6 +1236,28 @@ INSERT INTO `system_dict_data` (`id`, `sort`, `label`, `value`, `dict_type`, `st INSERT INTO `system_dict_data` (`id`, `sort`, `label`, `value`, `dict_type`, `status`, `color_type`, `css_class`, `remark`, `creator`, `create_time`, `updater`, `update_time`, `deleted`) VALUES (1483, 3, '转账成功', '20', 'pay_transfer_status', 0, 'success', '', '', '1', '2023-10-28 16:23:50', '1', '2023-10-28 16:23:50', b'0'); INSERT INTO `system_dict_data` (`id`, `sort`, `label`, `value`, `dict_type`, `status`, `color_type`, `css_class`, `remark`, `creator`, `create_time`, `updater`, `update_time`, `deleted`) VALUES (1484, 2, '转账进行中', '10', 'pay_transfer_status', 0, 'info', '', '', '1', '2023-10-28 16:23:12', '1', '2023-10-28 16:23:12', b'0'); INSERT INTO `system_dict_data` (`id`, `sort`, `label`, `value`, `dict_type`, `status`, `color_type`, `css_class`, `remark`, `creator`, `create_time`, `updater`, `update_time`, `deleted`) VALUES (1485, 1, '等待转账', '0', 'pay_transfer_status', 0, 'default', '', '', '1', '2023-10-28 16:21:43', '1', '2023-10-28 16:23:22', b'0'); +INSERT INTO `system_dict_data` (`id`, `sort`, `label`, `value`, `dict_type`, `status`, `color_type`, `css_class`, `remark`, `creator`, `create_time`, `updater`, `update_time`, `deleted`) VALUES (1486, 10, '其它入库', '10', 'erp_stock_record_biz_type', 0, '', '', '', '1', '2024-02-05 18:07:25', '1', '2024-02-05 18:07:43', b'0'); +INSERT INTO `system_dict_data` (`id`, `sort`, `label`, `value`, `dict_type`, `status`, `color_type`, `css_class`, `remark`, `creator`, `create_time`, `updater`, `update_time`, `deleted`) VALUES (1487, 11, '其它入库(作废)', '11', 'erp_stock_record_biz_type', 0, 'danger', '', '', '1', '2024-02-05 18:08:07', '1', '2024-02-05 19:20:16', b'0'); +INSERT INTO `system_dict_data` (`id`, `sort`, `label`, `value`, `dict_type`, `status`, `color_type`, `css_class`, `remark`, `creator`, `create_time`, `updater`, `update_time`, `deleted`) VALUES (1488, 20, '其它出库', '20', 'erp_stock_record_biz_type', 0, '', '', '', '1', '2024-02-05 18:08:51', '1', '2024-02-05 18:08:51', b'0'); +INSERT INTO `system_dict_data` (`id`, `sort`, `label`, `value`, `dict_type`, `status`, `color_type`, `css_class`, `remark`, `creator`, `create_time`, `updater`, `update_time`, `deleted`) VALUES (1489, 21, '其它出库(作废)', '21', 'erp_stock_record_biz_type', 0, 'danger', '', '', '1', '2024-02-05 18:09:00', '1', '2024-02-05 19:20:10', b'0'); +INSERT INTO `system_dict_data` (`id`, `sort`, `label`, `value`, `dict_type`, `status`, `color_type`, `css_class`, `remark`, `creator`, `create_time`, `updater`, `update_time`, `deleted`) VALUES (1490, 10, '未审核', '10', 'erp_audit_status', 0, 'default', '', '', '1', '2024-02-06 00:00:21', '1', '2024-02-06 00:00:21', b'0'); +INSERT INTO `system_dict_data` (`id`, `sort`, `label`, `value`, `dict_type`, `status`, `color_type`, `css_class`, `remark`, `creator`, `create_time`, `updater`, `update_time`, `deleted`) VALUES (1491, 20, '已审核', '20', 'erp_audit_status', 0, 'success', '', '', '1', '2024-02-06 00:00:35', '1', '2024-02-06 00:00:35', b'0'); +INSERT INTO `system_dict_data` (`id`, `sort`, `label`, `value`, `dict_type`, `status`, `color_type`, `css_class`, `remark`, `creator`, `create_time`, `updater`, `update_time`, `deleted`) VALUES (1492, 30, '调拨入库', '30', 'erp_stock_record_biz_type', 0, '', '', '', '1', '2024-02-07 20:34:19', '1', '2024-02-07 12:36:31', b'0'); +INSERT INTO `system_dict_data` (`id`, `sort`, `label`, `value`, `dict_type`, `status`, `color_type`, `css_class`, `remark`, `creator`, `create_time`, `updater`, `update_time`, `deleted`) VALUES (1493, 31, '调拨入库(作废)', '31', 'erp_stock_record_biz_type', 0, 'danger', '', '', '1', '2024-02-07 20:34:29', '1', '2024-02-07 20:37:11', b'0'); +INSERT INTO `system_dict_data` (`id`, `sort`, `label`, `value`, `dict_type`, `status`, `color_type`, `css_class`, `remark`, `creator`, `create_time`, `updater`, `update_time`, `deleted`) VALUES (1494, 32, '调拨出库', '32', 'erp_stock_record_biz_type', 0, '', '', '', '1', '2024-02-07 20:34:38', '1', '2024-02-07 12:36:33', b'0'); +INSERT INTO `system_dict_data` (`id`, `sort`, `label`, `value`, `dict_type`, `status`, `color_type`, `css_class`, `remark`, `creator`, `create_time`, `updater`, `update_time`, `deleted`) VALUES (1495, 33, '调拨出库(作废)', '33', 'erp_stock_record_biz_type', 0, 'danger', '', '', '1', '2024-02-07 20:34:49', '1', '2024-02-07 20:37:06', b'0'); +INSERT INTO `system_dict_data` (`id`, `sort`, `label`, `value`, `dict_type`, `status`, `color_type`, `css_class`, `remark`, `creator`, `create_time`, `updater`, `update_time`, `deleted`) VALUES (1496, 40, '盘盈入库', '40', 'erp_stock_record_biz_type', 0, '', '', '', '1', '2024-02-08 08:53:00', '1', '2024-02-08 08:53:09', b'0'); +INSERT INTO `system_dict_data` (`id`, `sort`, `label`, `value`, `dict_type`, `status`, `color_type`, `css_class`, `remark`, `creator`, `create_time`, `updater`, `update_time`, `deleted`) VALUES (1497, 41, '盘盈入库(作废)', '41', 'erp_stock_record_biz_type', 0, 'danger', '', '', '1', '2024-02-08 08:53:39', '1', '2024-02-16 19:40:54', b'0'); +INSERT INTO `system_dict_data` (`id`, `sort`, `label`, `value`, `dict_type`, `status`, `color_type`, `css_class`, `remark`, `creator`, `create_time`, `updater`, `update_time`, `deleted`) VALUES (1498, 42, '盘亏出库', '42', 'erp_stock_record_biz_type', 0, '', '', '', '1', '2024-02-08 08:54:16', '1', '2024-02-08 08:54:16', b'0'); +INSERT INTO `system_dict_data` (`id`, `sort`, `label`, `value`, `dict_type`, `status`, `color_type`, `css_class`, `remark`, `creator`, `create_time`, `updater`, `update_time`, `deleted`) VALUES (1499, 43, '盘亏出库(作废)', '43', 'erp_stock_record_biz_type', 0, 'danger', '', '', '1', '2024-02-08 08:54:31', '1', '2024-02-16 19:40:46', b'0'); +INSERT INTO `system_dict_data` (`id`, `sort`, `label`, `value`, `dict_type`, `status`, `color_type`, `css_class`, `remark`, `creator`, `create_time`, `updater`, `update_time`, `deleted`) VALUES (1500, 50, '销售出库', '50', 'erp_stock_record_biz_type', 0, '', '', '', '1', '2024-02-11 21:47:25', '1', '2024-02-11 21:50:40', b'0'); +INSERT INTO `system_dict_data` (`id`, `sort`, `label`, `value`, `dict_type`, `status`, `color_type`, `css_class`, `remark`, `creator`, `create_time`, `updater`, `update_time`, `deleted`) VALUES (1501, 51, '销售出库(作废)', '51', 'erp_stock_record_biz_type', 0, 'danger', '', '', '1', '2024-02-11 21:47:37', '1', '2024-02-11 21:51:12', b'0'); +INSERT INTO `system_dict_data` (`id`, `sort`, `label`, `value`, `dict_type`, `status`, `color_type`, `css_class`, `remark`, `creator`, `create_time`, `updater`, `update_time`, `deleted`) VALUES (1502, 60, '销售退货入库', '60', 'erp_stock_record_biz_type', 0, '', '', '', '1', '2024-02-12 06:51:05', '1', '2024-02-12 06:51:05', b'0'); +INSERT INTO `system_dict_data` (`id`, `sort`, `label`, `value`, `dict_type`, `status`, `color_type`, `css_class`, `remark`, `creator`, `create_time`, `updater`, `update_time`, `deleted`) VALUES (1503, 61, '销售退货入库(作废)', '61', 'erp_stock_record_biz_type', 0, 'danger', '', '', '1', '2024-02-12 06:51:18', '1', '2024-02-12 06:51:18', b'0'); +INSERT INTO `system_dict_data` (`id`, `sort`, `label`, `value`, `dict_type`, `status`, `color_type`, `css_class`, `remark`, `creator`, `create_time`, `updater`, `update_time`, `deleted`) VALUES (1504, 70, '采购入库', '70', 'erp_stock_record_biz_type', 0, '', '', '', '1', '2024-02-16 13:10:02', '1', '2024-02-16 13:10:02', b'0'); +INSERT INTO `system_dict_data` (`id`, `sort`, `label`, `value`, `dict_type`, `status`, `color_type`, `css_class`, `remark`, `creator`, `create_time`, `updater`, `update_time`, `deleted`) VALUES (1505, 71, '采购入库(作废)', '71', 'erp_stock_record_biz_type', 0, 'danger', '', '', '1', '2024-02-16 13:10:10', '1', '2024-02-16 19:40:40', b'0'); +INSERT INTO `system_dict_data` (`id`, `sort`, `label`, `value`, `dict_type`, `status`, `color_type`, `css_class`, `remark`, `creator`, `create_time`, `updater`, `update_time`, `deleted`) VALUES (1506, 80, '采购退货出库', '80', 'erp_stock_record_biz_type', 0, '', '', '', '1', '2024-02-16 13:10:17', '1', '2024-02-16 13:10:17', b'0'); +INSERT INTO `system_dict_data` (`id`, `sort`, `label`, `value`, `dict_type`, `status`, `color_type`, `css_class`, `remark`, `creator`, `create_time`, `updater`, `update_time`, `deleted`) VALUES (1507, 81, '采购退货出库(作废)', '81', 'erp_stock_record_biz_type', 0, 'danger', '', '', '1', '2024-02-16 13:10:26', '1', '2024-02-16 19:40:33', b'0'); COMMIT; -- ---------------------------- @@ -1256,7 +1278,7 @@ CREATE TABLE `system_dict_type` ( `deleted_time` datetime NULL DEFAULT NULL COMMENT '删除时间', PRIMARY KEY (`id`) USING BTREE, UNIQUE INDEX `dict_type`(`type` ASC) USING BTREE -) ENGINE = InnoDB AUTO_INCREMENT = 611 CHARACTER SET = utf8mb4 COLLATE = utf8mb4_unicode_ci COMMENT = '字典类型表'; +) ENGINE = InnoDB AUTO_INCREMENT = 613 CHARACTER SET = utf8mb4 COLLATE = utf8mb4_unicode_ci COMMENT = '字典类型表'; -- ---------------------------- -- Records of system_dict_type @@ -1343,6 +1365,8 @@ INSERT INTO `system_dict_type` (`id`, `name`, `type`, `status`, `remark`, `creat INSERT INTO `system_dict_type` (`id`, `name`, `type`, `status`, `remark`, `creator`, `create_time`, `updater`, `update_time`, `deleted`, `deleted_time`) VALUES (608, 'CRM 跟进方式', 'crm_follow_up_type', 0, '', '1', '2024-01-15 20:48:05', '1', '2024-01-15 20:48:05', b'0', '1970-01-01 00:00:00'); INSERT INTO `system_dict_type` (`id`, `name`, `type`, `status`, `remark`, `creator`, `create_time`, `updater`, `update_time`, `deleted`, `deleted_time`) VALUES (609, '支付转账类型', 'pay_transfer_type', 0, '', '1', '2023-10-28 16:27:18', '1', '2023-10-28 16:27:18', b'0', '1970-01-01 00:00:00'); INSERT INTO `system_dict_type` (`id`, `name`, `type`, `status`, `remark`, `creator`, `create_time`, `updater`, `update_time`, `deleted`, `deleted_time`) VALUES (610, '转账订单状态', 'pay_transfer_status', 0, '', '1', '2023-10-28 16:18:32', '1', '2023-10-28 16:18:32', b'0', '1970-01-01 00:00:00'); +INSERT INTO `system_dict_type` (`id`, `name`, `type`, `status`, `remark`, `creator`, `create_time`, `updater`, `update_time`, `deleted`, `deleted_time`) VALUES (611, 'ERP 库存明细的业务类型', 'erp_stock_record_biz_type', 0, 'ERP 库存明细的业务类型', '1', '2024-02-05 18:07:02', '1', '2024-02-05 18:07:02', b'0', '1970-01-01 00:00:00'); +INSERT INTO `system_dict_type` (`id`, `name`, `type`, `status`, `remark`, `creator`, `create_time`, `updater`, `update_time`, `deleted`, `deleted_time`) VALUES (612, 'ERP 审批状态', 'erp_audit_status', 0, '', '1', '2024-02-06 00:00:07', '1', '2024-02-06 00:00:07', b'0', '1970-01-01 00:00:00'); COMMIT; -- ---------------------------- @@ -1391,7 +1415,7 @@ CREATE TABLE `system_login_log` ( `deleted` bit(1) NOT NULL DEFAULT b'0' COMMENT '是否删除', `tenant_id` bigint NOT NULL DEFAULT 0 COMMENT '租户编号', PRIMARY KEY (`id`) USING BTREE -) ENGINE = InnoDB AUTO_INCREMENT = 2861 CHARACTER SET = utf8mb4 COLLATE = utf8mb4_unicode_ci COMMENT = '系统访问记录'; +) ENGINE = InnoDB AUTO_INCREMENT = 2906 CHARACTER SET = utf8mb4 COLLATE = utf8mb4_unicode_ci COMMENT = '系统访问记录'; -- ---------------------------- -- Records of system_login_log @@ -1521,7 +1545,7 @@ CREATE TABLE `system_menu` ( `update_time` datetime NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP COMMENT '更新时间', `deleted` bit(1) NOT NULL DEFAULT b'0' COMMENT '是否删除', PRIMARY KEY (`id`) USING BTREE -) ENGINE = InnoDB AUTO_INCREMENT = 2560 CHARACTER SET = utf8mb4 COLLATE = utf8mb4_unicode_ci COMMENT = '菜单权限表'; +) ENGINE = InnoDB AUTO_INCREMENT = 2702 CHARACTER SET = utf8mb4 COLLATE = utf8mb4_unicode_ci COMMENT = '菜单权限表'; -- ---------------------------- -- Records of system_menu @@ -2013,44 +2037,44 @@ INSERT INTO `system_menu` (`id`, `name`, `permission`, `type`, `sort`, `parent_i INSERT INTO `system_menu` (`id`, `name`, `permission`, `type`, `sort`, `parent_id`, `path`, `icon`, `component`, `component_name`, `status`, `visible`, `keep_alive`, `always_show`, `creator`, `create_time`, `updater`, `update_time`, `deleted`) VALUES (2388, '商城首页', '', 2, 1, 2362, 'home', 'ep:home-filled', 'mall/home/index', 'MallHome', 0, b'1', b'1', b'1', '', '2023-10-16 12:10:33', '', '2023-10-16 12:10:33', b'0'); INSERT INTO `system_menu` (`id`, `name`, `permission`, `type`, `sort`, `parent_id`, `path`, `icon`, `component`, `component_name`, `status`, `visible`, `keep_alive`, `always_show`, `creator`, `create_time`, `updater`, `update_time`, `deleted`) VALUES (2389, '核销订单', '', 2, 2, 2166, 'pick-up-order', 'ep:list', 'mall/trade/delivery/pickUpOrder/index', 'PickUpOrder', 0, b'1', b'1', b'1', '', '2023-10-19 16:09:51', '', '2023-10-19 16:09:51', b'0'); INSERT INTO `system_menu` (`id`, `name`, `permission`, `type`, `sort`, `parent_id`, `path`, `icon`, `component`, `component_name`, `status`, `visible`, `keep_alive`, `always_show`, `creator`, `create_time`, `updater`, `update_time`, `deleted`) VALUES (2390, '优惠活动', '', 1, 99, 2030, 'youhui', 'ep:aim', '', '', 0, b'1', b'1', b'1', '1', '2023-10-21 19:23:49', '1', '2023-10-21 19:23:49', b'0'); -INSERT INTO `system_menu` (`id`, `name`, `permission`, `type`, `sort`, `parent_id`, `path`, `icon`, `component`, `component_name`, `status`, `visible`, `keep_alive`, `always_show`, `creator`, `create_time`, `updater`, `update_time`, `deleted`) VALUES (2391, '客户管理', '', 2, 0, 2397, 'customer', 'fa:address-book-o', 'crm/customer/index', 'CrmCustomer', 0, b'1', b'1', b'1', '', '2023-10-29 09:04:21', '1', '2024-01-15 21:27:42', b'0'); +INSERT INTO `system_menu` (`id`, `name`, `permission`, `type`, `sort`, `parent_id`, `path`, `icon`, `component`, `component_name`, `status`, `visible`, `keep_alive`, `always_show`, `creator`, `create_time`, `updater`, `update_time`, `deleted`) VALUES (2391, '客户管理', '', 2, 10, 2397, 'customer', 'fa:address-book-o', 'crm/customer/index', 'CrmCustomer', 0, b'1', b'1', b'1', '', '2023-10-29 09:04:21', '1', '2024-02-17 17:13:32', b'0'); INSERT INTO `system_menu` (`id`, `name`, `permission`, `type`, `sort`, `parent_id`, `path`, `icon`, `component`, `component_name`, `status`, `visible`, `keep_alive`, `always_show`, `creator`, `create_time`, `updater`, `update_time`, `deleted`) VALUES (2392, '客户查询', 'crm:customer:query', 3, 1, 2391, '', '', '', NULL, 0, b'1', b'1', b'1', '', '2023-10-29 09:04:21', '', '2023-10-29 09:04:21', b'0'); INSERT INTO `system_menu` (`id`, `name`, `permission`, `type`, `sort`, `parent_id`, `path`, `icon`, `component`, `component_name`, `status`, `visible`, `keep_alive`, `always_show`, `creator`, `create_time`, `updater`, `update_time`, `deleted`) VALUES (2393, '客户创建', 'crm:customer:create', 3, 2, 2391, '', '', '', NULL, 0, b'1', b'1', b'1', '', '2023-10-29 09:04:21', '', '2023-10-29 09:04:21', b'0'); INSERT INTO `system_menu` (`id`, `name`, `permission`, `type`, `sort`, `parent_id`, `path`, `icon`, `component`, `component_name`, `status`, `visible`, `keep_alive`, `always_show`, `creator`, `create_time`, `updater`, `update_time`, `deleted`) VALUES (2394, '客户更新', 'crm:customer:update', 3, 3, 2391, '', '', '', NULL, 0, b'1', b'1', b'1', '', '2023-10-29 09:04:21', '', '2023-10-29 09:04:21', b'0'); INSERT INTO `system_menu` (`id`, `name`, `permission`, `type`, `sort`, `parent_id`, `path`, `icon`, `component`, `component_name`, `status`, `visible`, `keep_alive`, `always_show`, `creator`, `create_time`, `updater`, `update_time`, `deleted`) VALUES (2395, '客户删除', 'crm:customer:delete', 3, 4, 2391, '', '', '', NULL, 0, b'1', b'1', b'1', '', '2023-10-29 09:04:21', '', '2023-10-29 09:04:21', b'0'); INSERT INTO `system_menu` (`id`, `name`, `permission`, `type`, `sort`, `parent_id`, `path`, `icon`, `component`, `component_name`, `status`, `visible`, `keep_alive`, `always_show`, `creator`, `create_time`, `updater`, `update_time`, `deleted`) VALUES (2396, '客户导出', 'crm:customer:export', 3, 5, 2391, '', '', '', NULL, 0, b'1', b'1', b'1', '', '2023-10-29 09:04:21', '', '2023-10-29 09:04:21', b'0'); -INSERT INTO `system_menu` (`id`, `name`, `permission`, `type`, `sort`, `parent_id`, `path`, `icon`, `component`, `component_name`, `status`, `visible`, `keep_alive`, `always_show`, `creator`, `create_time`, `updater`, `update_time`, `deleted`) VALUES (2397, '客户管理系统', '', 1, 200, 0, '/crm', 'ep:avatar', '', '', 0, b'1', b'1', b'1', '1', '2023-10-29 17:08:30', '1', '2023-10-29 17:08:30', b'0'); -INSERT INTO `system_menu` (`id`, `name`, `permission`, `type`, `sort`, `parent_id`, `path`, `icon`, `component`, `component_name`, `status`, `visible`, `keep_alive`, `always_show`, `creator`, `create_time`, `updater`, `update_time`, `deleted`) VALUES (2398, '合同管理', '', 2, 1, 2397, 'contract', 'ep:notebook', 'crm/contract/index', 'CrmContract', 0, b'1', b'1', b'1', '', '2023-10-29 10:50:41', '1', '2023-10-29 18:55:53', b'0'); +INSERT INTO `system_menu` (`id`, `name`, `permission`, `type`, `sort`, `parent_id`, `path`, `icon`, `component`, `component_name`, `status`, `visible`, `keep_alive`, `always_show`, `creator`, `create_time`, `updater`, `update_time`, `deleted`) VALUES (2397, 'CRM 系统', '', 1, 200, 0, '/crm', 'ep:avatar', '', '', 0, b'1', b'1', b'1', '1', '2023-10-29 17:08:30', '1', '2024-02-04 15:37:31', b'0'); +INSERT INTO `system_menu` (`id`, `name`, `permission`, `type`, `sort`, `parent_id`, `path`, `icon`, `component`, `component_name`, `status`, `visible`, `keep_alive`, `always_show`, `creator`, `create_time`, `updater`, `update_time`, `deleted`) VALUES (2398, '合同管理', '', 2, 50, 2397, 'contract', 'ep:notebook', 'crm/contract/index', 'CrmContract', 0, b'1', b'1', b'1', '', '2023-10-29 10:50:41', '1', '2024-02-17 17:15:09', b'0'); INSERT INTO `system_menu` (`id`, `name`, `permission`, `type`, `sort`, `parent_id`, `path`, `icon`, `component`, `component_name`, `status`, `visible`, `keep_alive`, `always_show`, `creator`, `create_time`, `updater`, `update_time`, `deleted`) VALUES (2399, '合同查询', 'crm:contract:query', 3, 1, 2398, '', '', '', NULL, 0, b'1', b'1', b'1', '', '2023-10-29 10:50:41', '', '2023-10-29 10:50:41', b'0'); INSERT INTO `system_menu` (`id`, `name`, `permission`, `type`, `sort`, `parent_id`, `path`, `icon`, `component`, `component_name`, `status`, `visible`, `keep_alive`, `always_show`, `creator`, `create_time`, `updater`, `update_time`, `deleted`) VALUES (2400, '合同创建', 'crm:contract:create', 3, 2, 2398, '', '', '', NULL, 0, b'1', b'1', b'1', '', '2023-10-29 10:50:41', '', '2023-10-29 10:50:41', b'0'); INSERT INTO `system_menu` (`id`, `name`, `permission`, `type`, `sort`, `parent_id`, `path`, `icon`, `component`, `component_name`, `status`, `visible`, `keep_alive`, `always_show`, `creator`, `create_time`, `updater`, `update_time`, `deleted`) VALUES (2401, '合同更新', 'crm:contract:update', 3, 3, 2398, '', '', '', NULL, 0, b'1', b'1', b'1', '', '2023-10-29 10:50:41', '', '2023-10-29 10:50:41', b'0'); INSERT INTO `system_menu` (`id`, `name`, `permission`, `type`, `sort`, `parent_id`, `path`, `icon`, `component`, `component_name`, `status`, `visible`, `keep_alive`, `always_show`, `creator`, `create_time`, `updater`, `update_time`, `deleted`) VALUES (2402, '合同删除', 'crm:contract:delete', 3, 4, 2398, '', '', '', NULL, 0, b'1', b'1', b'1', '', '2023-10-29 10:50:41', '', '2023-10-29 10:50:41', b'0'); INSERT INTO `system_menu` (`id`, `name`, `permission`, `type`, `sort`, `parent_id`, `path`, `icon`, `component`, `component_name`, `status`, `visible`, `keep_alive`, `always_show`, `creator`, `create_time`, `updater`, `update_time`, `deleted`) VALUES (2403, '合同导出', 'crm:contract:export', 3, 5, 2398, '', '', '', NULL, 0, b'1', b'1', b'1', '', '2023-10-29 10:50:41', '', '2023-10-29 10:50:41', b'0'); -INSERT INTO `system_menu` (`id`, `name`, `permission`, `type`, `sort`, `parent_id`, `path`, `icon`, `component`, `component_name`, `status`, `visible`, `keep_alive`, `always_show`, `creator`, `create_time`, `updater`, `update_time`, `deleted`) VALUES (2404, '线索管理', '', 2, 0, 2397, 'clue', 'fa:pagelines', 'crm/clue/index', 'CrmClue', 0, b'1', b'1', b'1', '', '2023-10-29 11:06:29', '1', '2023-10-29 19:08:35', b'0'); +INSERT INTO `system_menu` (`id`, `name`, `permission`, `type`, `sort`, `parent_id`, `path`, `icon`, `component`, `component_name`, `status`, `visible`, `keep_alive`, `always_show`, `creator`, `create_time`, `updater`, `update_time`, `deleted`) VALUES (2404, '线索管理', '', 2, 8, 2397, 'clue', 'fa:pagelines', 'crm/clue/index', 'CrmClue', 0, b'1', b'1', b'1', '', '2023-10-29 11:06:29', '1', '2024-02-17 17:15:41', b'0'); INSERT INTO `system_menu` (`id`, `name`, `permission`, `type`, `sort`, `parent_id`, `path`, `icon`, `component`, `component_name`, `status`, `visible`, `keep_alive`, `always_show`, `creator`, `create_time`, `updater`, `update_time`, `deleted`) VALUES (2405, '线索查询', 'crm:clue:query', 3, 1, 2404, '', '', '', NULL, 0, b'1', b'1', b'1', '', '2023-10-29 11:06:29', '', '2023-10-29 11:06:29', b'0'); INSERT INTO `system_menu` (`id`, `name`, `permission`, `type`, `sort`, `parent_id`, `path`, `icon`, `component`, `component_name`, `status`, `visible`, `keep_alive`, `always_show`, `creator`, `create_time`, `updater`, `update_time`, `deleted`) VALUES (2406, '线索创建', 'crm:clue:create', 3, 2, 2404, '', '', '', NULL, 0, b'1', b'1', b'1', '', '2023-10-29 11:06:29', '', '2023-10-29 11:06:29', b'0'); INSERT INTO `system_menu` (`id`, `name`, `permission`, `type`, `sort`, `parent_id`, `path`, `icon`, `component`, `component_name`, `status`, `visible`, `keep_alive`, `always_show`, `creator`, `create_time`, `updater`, `update_time`, `deleted`) VALUES (2407, '线索更新', 'crm:clue:update', 3, 3, 2404, '', '', '', NULL, 0, b'1', b'1', b'1', '', '2023-10-29 11:06:29', '', '2023-10-29 11:06:29', b'0'); INSERT INTO `system_menu` (`id`, `name`, `permission`, `type`, `sort`, `parent_id`, `path`, `icon`, `component`, `component_name`, `status`, `visible`, `keep_alive`, `always_show`, `creator`, `create_time`, `updater`, `update_time`, `deleted`) VALUES (2408, '线索删除', 'crm:clue:delete', 3, 4, 2404, '', '', '', NULL, 0, b'1', b'1', b'1', '', '2023-10-29 11:06:29', '', '2023-10-29 11:06:29', b'0'); INSERT INTO `system_menu` (`id`, `name`, `permission`, `type`, `sort`, `parent_id`, `path`, `icon`, `component`, `component_name`, `status`, `visible`, `keep_alive`, `always_show`, `creator`, `create_time`, `updater`, `update_time`, `deleted`) VALUES (2409, '线索导出', 'crm:clue:export', 3, 5, 2404, '', '', '', NULL, 0, b'1', b'1', b'1', '', '2023-10-29 11:06:29', '', '2023-10-29 11:06:29', b'0'); -INSERT INTO `system_menu` (`id`, `name`, `permission`, `type`, `sort`, `parent_id`, `path`, `icon`, `component`, `component_name`, `status`, `visible`, `keep_alive`, `always_show`, `creator`, `create_time`, `updater`, `update_time`, `deleted`) VALUES (2410, '商机管理', '', 2, 0, 2397, 'business', 'fa:bus', 'crm/business/index', 'CrmBusiness', 0, b'1', b'1', b'1', '', '2023-10-29 11:12:35', '1', '2023-10-29 19:13:01', b'0'); +INSERT INTO `system_menu` (`id`, `name`, `permission`, `type`, `sort`, `parent_id`, `path`, `icon`, `component`, `component_name`, `status`, `visible`, `keep_alive`, `always_show`, `creator`, `create_time`, `updater`, `update_time`, `deleted`) VALUES (2410, '商机管理', '', 2, 40, 2397, 'business', 'fa:bus', 'crm/business/index', 'CrmBusiness', 0, b'1', b'1', b'1', '', '2023-10-29 11:12:35', '1', '2024-02-17 17:14:55', b'0'); INSERT INTO `system_menu` (`id`, `name`, `permission`, `type`, `sort`, `parent_id`, `path`, `icon`, `component`, `component_name`, `status`, `visible`, `keep_alive`, `always_show`, `creator`, `create_time`, `updater`, `update_time`, `deleted`) VALUES (2411, '商机查询', 'crm:business:query', 3, 1, 2410, '', '', '', NULL, 0, b'1', b'1', b'1', '', '2023-10-29 11:12:35', '', '2023-10-29 11:12:35', b'0'); INSERT INTO `system_menu` (`id`, `name`, `permission`, `type`, `sort`, `parent_id`, `path`, `icon`, `component`, `component_name`, `status`, `visible`, `keep_alive`, `always_show`, `creator`, `create_time`, `updater`, `update_time`, `deleted`) VALUES (2412, '商机创建', 'crm:business:create', 3, 2, 2410, '', '', '', NULL, 0, b'1', b'1', b'1', '', '2023-10-29 11:12:35', '', '2023-10-29 11:12:35', b'0'); INSERT INTO `system_menu` (`id`, `name`, `permission`, `type`, `sort`, `parent_id`, `path`, `icon`, `component`, `component_name`, `status`, `visible`, `keep_alive`, `always_show`, `creator`, `create_time`, `updater`, `update_time`, `deleted`) VALUES (2413, '商机更新', 'crm:business:update', 3, 3, 2410, '', '', '', NULL, 0, b'1', b'1', b'1', '', '2023-10-29 11:12:35', '', '2023-10-29 11:12:35', b'0'); INSERT INTO `system_menu` (`id`, `name`, `permission`, `type`, `sort`, `parent_id`, `path`, `icon`, `component`, `component_name`, `status`, `visible`, `keep_alive`, `always_show`, `creator`, `create_time`, `updater`, `update_time`, `deleted`) VALUES (2414, '商机删除', 'crm:business:delete', 3, 4, 2410, '', '', '', NULL, 0, b'1', b'1', b'1', '', '2023-10-29 11:12:35', '', '2023-10-29 11:12:35', b'0'); INSERT INTO `system_menu` (`id`, `name`, `permission`, `type`, `sort`, `parent_id`, `path`, `icon`, `component`, `component_name`, `status`, `visible`, `keep_alive`, `always_show`, `creator`, `create_time`, `updater`, `update_time`, `deleted`) VALUES (2415, '商机导出', 'crm:business:export', 3, 5, 2410, '', '', '', NULL, 0, b'1', b'1', b'1', '', '2023-10-29 11:12:35', '', '2023-10-29 11:12:35', b'0'); -INSERT INTO `system_menu` (`id`, `name`, `permission`, `type`, `sort`, `parent_id`, `path`, `icon`, `component`, `component_name`, `status`, `visible`, `keep_alive`, `always_show`, `creator`, `create_time`, `updater`, `update_time`, `deleted`) VALUES (2416, '联系人管理', '', 2, 0, 2397, 'contact', 'fa:address-book-o', 'crm/contact/index', 'CrmContact', 0, b'1', b'1', b'1', '', '2023-10-29 11:14:56', '1', '2023-12-01 19:39:50', b'0'); +INSERT INTO `system_menu` (`id`, `name`, `permission`, `type`, `sort`, `parent_id`, `path`, `icon`, `component`, `component_name`, `status`, `visible`, `keep_alive`, `always_show`, `creator`, `create_time`, `updater`, `update_time`, `deleted`) VALUES (2416, '联系人管理', '', 2, 20, 2397, 'contact', 'fa:address-book-o', 'crm/contact/index', 'CrmContact', 0, b'1', b'1', b'1', '', '2023-10-29 11:14:56', '1', '2024-02-17 17:13:49', b'0'); INSERT INTO `system_menu` (`id`, `name`, `permission`, `type`, `sort`, `parent_id`, `path`, `icon`, `component`, `component_name`, `status`, `visible`, `keep_alive`, `always_show`, `creator`, `create_time`, `updater`, `update_time`, `deleted`) VALUES (2417, '联系人查询', 'crm:contact:query', 3, 1, 2416, '', '', '', NULL, 0, b'1', b'1', b'1', '', '2023-10-29 11:14:56', '', '2023-10-29 11:14:56', b'0'); INSERT INTO `system_menu` (`id`, `name`, `permission`, `type`, `sort`, `parent_id`, `path`, `icon`, `component`, `component_name`, `status`, `visible`, `keep_alive`, `always_show`, `creator`, `create_time`, `updater`, `update_time`, `deleted`) VALUES (2418, '联系人创建', 'crm:contact:create', 3, 2, 2416, '', '', '', NULL, 0, b'1', b'1', b'1', '', '2023-10-29 11:14:56', '', '2023-10-29 11:14:56', b'0'); INSERT INTO `system_menu` (`id`, `name`, `permission`, `type`, `sort`, `parent_id`, `path`, `icon`, `component`, `component_name`, `status`, `visible`, `keep_alive`, `always_show`, `creator`, `create_time`, `updater`, `update_time`, `deleted`) VALUES (2419, '联系人更新', 'crm:contact:update', 3, 3, 2416, '', '', '', NULL, 0, b'1', b'1', b'1', '', '2023-10-29 11:14:56', '', '2023-10-29 11:14:56', b'0'); INSERT INTO `system_menu` (`id`, `name`, `permission`, `type`, `sort`, `parent_id`, `path`, `icon`, `component`, `component_name`, `status`, `visible`, `keep_alive`, `always_show`, `creator`, `create_time`, `updater`, `update_time`, `deleted`) VALUES (2420, '联系人删除', 'crm:contact:delete', 3, 4, 2416, '', '', '', NULL, 0, b'1', b'1', b'1', '', '2023-10-29 11:14:56', '', '2023-10-29 11:14:56', b'0'); INSERT INTO `system_menu` (`id`, `name`, `permission`, `type`, `sort`, `parent_id`, `path`, `icon`, `component`, `component_name`, `status`, `visible`, `keep_alive`, `always_show`, `creator`, `create_time`, `updater`, `update_time`, `deleted`) VALUES (2421, '联系人导出', 'crm:contact:export', 3, 5, 2416, '', '', '', NULL, 0, b'1', b'1', b'1', '', '2023-10-29 11:14:56', '', '2023-10-29 11:14:56', b'0'); -INSERT INTO `system_menu` (`id`, `name`, `permission`, `type`, `sort`, `parent_id`, `path`, `icon`, `component`, `component_name`, `status`, `visible`, `keep_alive`, `always_show`, `creator`, `create_time`, `updater`, `update_time`, `deleted`) VALUES (2422, '回款管理', '', 2, 0, 2397, 'receivable', 'ep:money', 'crm/receivable/index', 'CrmReceivable', 0, b'1', b'1', b'1', '', '2023-10-29 11:18:09', '1', '2023-10-29 19:18:52', b'0'); +INSERT INTO `system_menu` (`id`, `name`, `permission`, `type`, `sort`, `parent_id`, `path`, `icon`, `component`, `component_name`, `status`, `visible`, `keep_alive`, `always_show`, `creator`, `create_time`, `updater`, `update_time`, `deleted`) VALUES (2422, '回款管理', '', 2, 60, 2397, 'receivable', 'ep:money', 'crm/receivable/index', 'CrmReceivable', 0, b'1', b'1', b'1', '', '2023-10-29 11:18:09', '1', '2024-02-17 17:16:18', b'0'); INSERT INTO `system_menu` (`id`, `name`, `permission`, `type`, `sort`, `parent_id`, `path`, `icon`, `component`, `component_name`, `status`, `visible`, `keep_alive`, `always_show`, `creator`, `create_time`, `updater`, `update_time`, `deleted`) VALUES (2423, '回款管理查询', 'crm:receivable:query', 3, 1, 2422, '', '', '', NULL, 0, b'1', b'1', b'1', '', '2023-10-29 11:18:09', '', '2023-10-29 11:18:09', b'0'); INSERT INTO `system_menu` (`id`, `name`, `permission`, `type`, `sort`, `parent_id`, `path`, `icon`, `component`, `component_name`, `status`, `visible`, `keep_alive`, `always_show`, `creator`, `create_time`, `updater`, `update_time`, `deleted`) VALUES (2424, '回款管理创建', 'crm:receivable:create', 3, 2, 2422, '', '', '', NULL, 0, b'1', b'1', b'1', '', '2023-10-29 11:18:09', '', '2023-10-29 11:18:09', b'0'); INSERT INTO `system_menu` (`id`, `name`, `permission`, `type`, `sort`, `parent_id`, `path`, `icon`, `component`, `component_name`, `status`, `visible`, `keep_alive`, `always_show`, `creator`, `create_time`, `updater`, `update_time`, `deleted`) VALUES (2425, '回款管理更新', 'crm:receivable:update', 3, 3, 2422, '', '', '', NULL, 0, b'1', b'1', b'1', '', '2023-10-29 11:18:09', '', '2023-10-29 11:18:09', b'0'); INSERT INTO `system_menu` (`id`, `name`, `permission`, `type`, `sort`, `parent_id`, `path`, `icon`, `component`, `component_name`, `status`, `visible`, `keep_alive`, `always_show`, `creator`, `create_time`, `updater`, `update_time`, `deleted`) VALUES (2426, '回款管理删除', 'crm:receivable:delete', 3, 4, 2422, '', '', '', NULL, 0, b'1', b'1', b'1', '', '2023-10-29 11:18:09', '', '2023-10-29 11:18:09', b'0'); INSERT INTO `system_menu` (`id`, `name`, `permission`, `type`, `sort`, `parent_id`, `path`, `icon`, `component`, `component_name`, `status`, `visible`, `keep_alive`, `always_show`, `creator`, `create_time`, `updater`, `update_time`, `deleted`) VALUES (2427, '回款管理导出', 'crm:receivable:export', 3, 5, 2422, '', '', '', NULL, 0, b'1', b'1', b'1', '', '2023-10-29 11:18:09', '', '2023-10-29 11:18:09', b'0'); -INSERT INTO `system_menu` (`id`, `name`, `permission`, `type`, `sort`, `parent_id`, `path`, `icon`, `component`, `component_name`, `status`, `visible`, `keep_alive`, `always_show`, `creator`, `create_time`, `updater`, `update_time`, `deleted`) VALUES (2428, '回款计划', '', 2, 0, 2397, 'receivable-plan', 'fa:money', 'crm/receivable/plan/index', 'CrmReceivablePlan', 0, b'1', b'1', b'1', '', '2023-10-29 11:18:09', '1', '2023-12-01 19:55:48', b'0'); +INSERT INTO `system_menu` (`id`, `name`, `permission`, `type`, `sort`, `parent_id`, `path`, `icon`, `component`, `component_name`, `status`, `visible`, `keep_alive`, `always_show`, `creator`, `create_time`, `updater`, `update_time`, `deleted`) VALUES (2428, '回款计划', '', 2, 61, 2397, 'receivable-plan', 'fa:money', 'crm/receivable/plan/index', 'CrmReceivablePlan', 0, b'1', b'1', b'1', '', '2023-10-29 11:18:09', '1', '2024-02-17 17:16:11', b'0'); INSERT INTO `system_menu` (`id`, `name`, `permission`, `type`, `sort`, `parent_id`, `path`, `icon`, `component`, `component_name`, `status`, `visible`, `keep_alive`, `always_show`, `creator`, `create_time`, `updater`, `update_time`, `deleted`) VALUES (2429, '回款计划查询', 'crm:receivable-plan:query', 3, 1, 2428, '', '', '', NULL, 0, b'1', b'1', b'1', '', '2023-10-29 11:18:09', '', '2023-10-29 11:18:09', b'0'); INSERT INTO `system_menu` (`id`, `name`, `permission`, `type`, `sort`, `parent_id`, `path`, `icon`, `component`, `component_name`, `status`, `visible`, `keep_alive`, `always_show`, `creator`, `create_time`, `updater`, `update_time`, `deleted`) VALUES (2430, '回款计划创建', 'crm:receivable-plan:create', 3, 2, 2428, '', '', '', NULL, 0, b'1', b'1', b'1', '', '2023-10-29 11:18:09', '', '2023-10-29 11:18:09', b'0'); INSERT INTO `system_menu` (`id`, `name`, `permission`, `type`, `sort`, `parent_id`, `path`, `icon`, `component`, `component_name`, `status`, `visible`, `keep_alive`, `always_show`, `creator`, `create_time`, `updater`, `update_time`, `deleted`) VALUES (2431, '回款计划更新', 'crm:receivable-plan:update', 3, 3, 2428, '', '', '', NULL, 0, b'1', b'1', b'1', '', '2023-10-29 11:18:09', '', '2023-10-29 11:18:09', b'0'); @@ -2103,7 +2127,7 @@ INSERT INTO `system_menu` (`id`, `name`, `permission`, `type`, `sort`, `parent_i INSERT INTO `system_menu` (`id`, `name`, `permission`, `type`, `sort`, `parent_id`, `path`, `icon`, `component`, `component_name`, `status`, `visible`, `keep_alive`, `always_show`, `creator`, `create_time`, `updater`, `update_time`, `deleted`) VALUES (2521, '客户限制配置更新', 'crm:customer-limit-config:update', 3, 3, 2518, '', '', '', NULL, 0, b'1', b'1', b'1', '', '2023-11-18 13:33:53', '', '2023-11-18 13:33:53', b'0'); INSERT INTO `system_menu` (`id`, `name`, `permission`, `type`, `sort`, `parent_id`, `path`, `icon`, `component`, `component_name`, `status`, `visible`, `keep_alive`, `always_show`, `creator`, `create_time`, `updater`, `update_time`, `deleted`) VALUES (2522, '客户限制配置删除', 'crm:customer-limit-config:delete', 3, 4, 2518, '', '', '', NULL, 0, b'1', b'1', b'1', '', '2023-11-18 13:33:53', '', '2023-11-18 13:33:53', b'0'); INSERT INTO `system_menu` (`id`, `name`, `permission`, `type`, `sort`, `parent_id`, `path`, `icon`, `component`, `component_name`, `status`, `visible`, `keep_alive`, `always_show`, `creator`, `create_time`, `updater`, `update_time`, `deleted`) VALUES (2523, '客户限制配置导出', 'crm:customer-limit-config:export', 3, 5, 2518, '', '', '', NULL, 0, b'1', b'1', b'1', '', '2023-11-18 13:33:53', '', '2023-11-18 13:33:53', b'0'); -INSERT INTO `system_menu` (`id`, `name`, `permission`, `type`, `sort`, `parent_id`, `path`, `icon`, `component`, `component_name`, `status`, `visible`, `keep_alive`, `always_show`, `creator`, `create_time`, `updater`, `update_time`, `deleted`) VALUES (2524, '系统配置', '', 1, 99, 2397, 'config', 'ep:connection', '', '', 0, b'1', b'1', b'1', '1', '2023-11-18 21:58:00', '1', '2023-11-18 21:58:00', b'0'); +INSERT INTO `system_menu` (`id`, `name`, `permission`, `type`, `sort`, `parent_id`, `path`, `icon`, `component`, `component_name`, `status`, `visible`, `keep_alive`, `always_show`, `creator`, `create_time`, `updater`, `update_time`, `deleted`) VALUES (2524, '系统配置', '', 1, 999, 2397, 'config', 'ep:connection', '', '', 0, b'1', b'1', b'1', '1', '2023-11-18 21:58:00', '1', '2024-02-17 17:14:34', b'0'); INSERT INTO `system_menu` (`id`, `name`, `permission`, `type`, `sort`, `parent_id`, `path`, `icon`, `component`, `component_name`, `status`, `visible`, `keep_alive`, `always_show`, `creator`, `create_time`, `updater`, `update_time`, `deleted`) VALUES (2525, 'WebSocket 测试', '', 2, 7, 2, 'websocket', 'ep:connection', 'infra/webSocket/index', 'InfraWebSocket', 0, b'1', b'1', b'1', '1', '2023-11-23 19:41:55', '1', '2023-11-24 19:22:30', b'0'); INSERT INTO `system_menu` (`id`, `name`, `permission`, `type`, `sort`, `parent_id`, `path`, `icon`, `component`, `component_name`, `status`, `visible`, `keep_alive`, `always_show`, `creator`, `create_time`, `updater`, `update_time`, `deleted`) VALUES (2526, '产品管理', '', 2, 10, 2397, 'product', 'fa:product-hunt', 'crm/product/index', 'CrmProduct', 0, b'1', b'1', b'1', '1', '2023-12-05 22:45:26', '1', '2023-12-05 22:46:45', b'0'); INSERT INTO `system_menu` (`id`, `name`, `permission`, `type`, `sort`, `parent_id`, `path`, `icon`, `component`, `component_name`, `status`, `visible`, `keep_alive`, `always_show`, `creator`, `create_time`, `updater`, `update_time`, `deleted`) VALUES (2527, '产品查询', 'crm:product:query', 3, 1, 2526, '', '', '', '', 0, b'1', b'1', b'1', '1', '2023-12-05 22:47:16', '1', '2023-12-05 22:47:16', b'0'); @@ -2125,7 +2149,7 @@ INSERT INTO `system_menu` (`id`, `name`, `permission`, `type`, `sort`, `parent_i INSERT INTO `system_menu` (`id`, `name`, `permission`, `type`, `sort`, `parent_id`, `path`, `icon`, `component`, `component_name`, `status`, `visible`, `keep_alive`, `always_show`, `creator`, `create_time`, `updater`, `update_time`, `deleted`) VALUES (2543, '关联商机', 'crm:contact:create-business', 3, 10, 2416, '', '', '', '', 0, b'1', b'1', b'1', '1', '2024-01-02 17:28:25', '1', '2024-01-02 17:28:25', b'0'); INSERT INTO `system_menu` (`id`, `name`, `permission`, `type`, `sort`, `parent_id`, `path`, `icon`, `component`, `component_name`, `status`, `visible`, `keep_alive`, `always_show`, `creator`, `create_time`, `updater`, `update_time`, `deleted`) VALUES (2544, '取关商机', 'crm:contact:delete-business', 3, 11, 2416, '', '', '', '', 0, b'1', b'1', b'1', '1', '2024-01-02 17:28:43', '1', '2024-01-02 17:28:51', b'0'); INSERT INTO `system_menu` (`id`, `name`, `permission`, `type`, `sort`, `parent_id`, `path`, `icon`, `component`, `component_name`, `status`, `visible`, `keep_alive`, `always_show`, `creator`, `create_time`, `updater`, `update_time`, `deleted`) VALUES (2545, '商品统计', '', 2, 3, 2358, 'product', 'fa:product-hunt', 'statistics/product/index', 'ProductStatistics', 0, b'1', b'1', b'1', '', '2023-12-15 18:54:28', '1', '2024-01-17 23:11:54', b'0'); -INSERT INTO `system_menu` (`id`, `name`, `permission`, `type`, `sort`, `parent_id`, `path`, `icon`, `component`, `component_name`, `status`, `visible`, `keep_alive`, `always_show`, `creator`, `create_time`, `updater`, `update_time`, `deleted`) VALUES (2546, '客户公海', '', 2, -1, 2397, 'customer/pool', 'fa-solid:swimming-pool', 'crm/customer/pool/index', 'CrmCustomerPool', 0, b'1', b'1', b'1', '1', '2024-01-15 21:29:34', '1', '2023-12-29 19:47:32', b'0'); +INSERT INTO `system_menu` (`id`, `name`, `permission`, `type`, `sort`, `parent_id`, `path`, `icon`, `component`, `component_name`, `status`, `visible`, `keep_alive`, `always_show`, `creator`, `create_time`, `updater`, `update_time`, `deleted`) VALUES (2546, '客户公海', '', 2, 30, 2397, 'customer/pool', 'fa-solid:swimming-pool', 'crm/customer/pool/index', 'CrmCustomerPool', 0, b'1', b'1', b'1', '1', '2024-01-15 21:29:34', '1', '2024-02-17 17:14:18', b'0'); INSERT INTO `system_menu` (`id`, `name`, `permission`, `type`, `sort`, `parent_id`, `path`, `icon`, `component`, `component_name`, `status`, `visible`, `keep_alive`, `always_show`, `creator`, `create_time`, `updater`, `update_time`, `deleted`) VALUES (2547, '订单查询', 'trade:order:query', 3, 1, 2076, '', '', '', '', 0, b'1', b'1', b'1', '1', '2024-01-16 08:52:00', '1', '2024-01-16 08:52:00', b'0'); INSERT INTO `system_menu` (`id`, `name`, `permission`, `type`, `sort`, `parent_id`, `path`, `icon`, `component`, `component_name`, `status`, `visible`, `keep_alive`, `always_show`, `creator`, `create_time`, `updater`, `update_time`, `deleted`) VALUES (2548, '订单更新', 'trade:order:update', 3, 2, 2076, '', '', '', '', 0, b'1', b'1', b'1', '1', '2024-01-16 08:52:21', '1', '2024-01-16 08:52:21', b'0'); INSERT INTO `system_menu` (`id`, `name`, `permission`, `type`, `sort`, `parent_id`, `path`, `icon`, `component`, `component_name`, `status`, `visible`, `keep_alive`, `always_show`, `creator`, `create_time`, `updater`, `update_time`, `deleted`) VALUES (2549, '支付&退款案例', '', 2, 1, 2161, 'order', 'fa:paypal', 'pay/demo/order/index', '', 0, b'1', b'1', b'1', '1', '2024-01-18 23:45:00', '1', '2024-01-18 23:47:21', b'0'); @@ -2139,6 +2163,148 @@ INSERT INTO `system_menu` (`id`, `name`, `permission`, `type`, `sort`, `parent_i INSERT INTO `system_menu` (`id`, `name`, `permission`, `type`, `sort`, `parent_id`, `path`, `icon`, `component`, `component_name`, `status`, `visible`, `keep_alive`, `always_show`, `creator`, `create_time`, `updater`, `update_time`, `deleted`) VALUES (2557, '钱包余额', '', 2, 1, 2551, 'wallet-balance', 'fa:leaf', 'pay/wallet/balance/index', 'WalletBalance', 0, b'1', b'1', b'1', '', '2023-12-29 02:32:54', '', '2023-12-29 02:32:54', b'0'); INSERT INTO `system_menu` (`id`, `name`, `permission`, `type`, `sort`, `parent_id`, `path`, `icon`, `component`, `component_name`, `status`, `visible`, `keep_alive`, `always_show`, `creator`, `create_time`, `updater`, `update_time`, `deleted`) VALUES (2558, '钱包余额查询', 'pay:wallet:query', 3, 1, 2557, '', '', '', NULL, 0, b'1', b'1', b'1', '', '2023-12-29 02:32:54', '', '2023-12-29 02:32:54', b'0'); INSERT INTO `system_menu` (`id`, `name`, `permission`, `type`, `sort`, `parent_id`, `path`, `icon`, `component`, `component_name`, `status`, `visible`, `keep_alive`, `always_show`, `creator`, `create_time`, `updater`, `update_time`, `deleted`) VALUES (2559, '转账订单', '', 2, 3, 1117, 'transfer', 'ep:credit-card', 'pay/transfer/index', 'PayTransfer', 0, b'1', b'1', b'1', '', '2023-12-29 02:32:54', '', '2023-12-29 02:32:54', b'0'); +INSERT INTO `system_menu` (`id`, `name`, `permission`, `type`, `sort`, `parent_id`, `path`, `icon`, `component`, `component_name`, `status`, `visible`, `keep_alive`, `always_show`, `creator`, `create_time`, `updater`, `update_time`, `deleted`) VALUES (2560, '商业智能', '', 1, 200, 2397, 'bi', 'ep:data-line', '', '', 0, b'1', b'1', b'1', '1', '2024-01-26 22:50:35', '1', '2024-02-17 17:14:39', b'0'); +INSERT INTO `system_menu` (`id`, `name`, `permission`, `type`, `sort`, `parent_id`, `path`, `icon`, `component`, `component_name`, `status`, `visible`, `keep_alive`, `always_show`, `creator`, `create_time`, `updater`, `update_time`, `deleted`) VALUES (2561, '排行榜', '', 2, 1, 2560, 'ranking', 'fa:area-chart', 'crm/bi/rank/index', 'BiRanking', 0, b'1', b'1', b'1', '1', '2024-01-26 22:52:09', '1', '2024-02-03 01:10:43', b'0'); +INSERT INTO `system_menu` (`id`, `name`, `permission`, `type`, `sort`, `parent_id`, `path`, `icon`, `component`, `component_name`, `status`, `visible`, `keep_alive`, `always_show`, `creator`, `create_time`, `updater`, `update_time`, `deleted`) VALUES (2562, '客户导入', 'crm:customer:import', 3, 6, 2391, '', '', '', '', 0, b'1', b'1', b'1', '1', '2024-02-01 13:09:00', '1', '2024-02-01 13:09:05', b'0'); +INSERT INTO `system_menu` (`id`, `name`, `permission`, `type`, `sort`, `parent_id`, `path`, `icon`, `component`, `component_name`, `status`, `visible`, `keep_alive`, `always_show`, `creator`, `create_time`, `updater`, `update_time`, `deleted`) VALUES (2563, 'ERP 系统', '', 1, 300, 0, '/erp', 'fa-solid:store', '', '', 0, b'1', b'1', b'1', '1', '2024-02-04 15:37:25', '1', '2024-02-04 15:37:25', b'0'); +INSERT INTO `system_menu` (`id`, `name`, `permission`, `type`, `sort`, `parent_id`, `path`, `icon`, `component`, `component_name`, `status`, `visible`, `keep_alive`, `always_show`, `creator`, `create_time`, `updater`, `update_time`, `deleted`) VALUES (2564, '产品管理', '', 1, 40, 2563, 'product', 'fa:product-hunt', '', '', 0, b'1', b'1', b'1', '1', '2024-02-04 15:38:43', '1', '2024-02-04 15:38:43', b'0'); +INSERT INTO `system_menu` (`id`, `name`, `permission`, `type`, `sort`, `parent_id`, `path`, `icon`, `component`, `component_name`, `status`, `visible`, `keep_alive`, `always_show`, `creator`, `create_time`, `updater`, `update_time`, `deleted`) VALUES (2565, '产品信息', '', 2, 0, 2564, 'product', 'fa-solid:apple-alt', 'erp/product/product/index', 'ErpProduct', 0, b'1', b'1', b'1', '', '2024-02-04 07:52:15', '1', '2024-02-05 14:42:11', b'0'); +INSERT INTO `system_menu` (`id`, `name`, `permission`, `type`, `sort`, `parent_id`, `path`, `icon`, `component`, `component_name`, `status`, `visible`, `keep_alive`, `always_show`, `creator`, `create_time`, `updater`, `update_time`, `deleted`) VALUES (2566, '产品查询', 'erp:product:query', 3, 1, 2565, '', '', '', '', 0, b'1', b'1', b'1', '', '2024-02-04 07:52:15', '1', '2024-02-04 17:21:57', b'0'); +INSERT INTO `system_menu` (`id`, `name`, `permission`, `type`, `sort`, `parent_id`, `path`, `icon`, `component`, `component_name`, `status`, `visible`, `keep_alive`, `always_show`, `creator`, `create_time`, `updater`, `update_time`, `deleted`) VALUES (2567, '产品创建', 'erp:product:create', 3, 2, 2565, '', '', '', '', 0, b'1', b'1', b'1', '', '2024-02-04 07:52:15', '1', '2024-02-04 17:22:12', b'0'); +INSERT INTO `system_menu` (`id`, `name`, `permission`, `type`, `sort`, `parent_id`, `path`, `icon`, `component`, `component_name`, `status`, `visible`, `keep_alive`, `always_show`, `creator`, `create_time`, `updater`, `update_time`, `deleted`) VALUES (2568, '产品更新', 'erp:product:update', 3, 3, 2565, '', '', '', '', 0, b'1', b'1', b'1', '', '2024-02-04 07:52:15', '1', '2024-02-04 17:22:16', b'0'); +INSERT INTO `system_menu` (`id`, `name`, `permission`, `type`, `sort`, `parent_id`, `path`, `icon`, `component`, `component_name`, `status`, `visible`, `keep_alive`, `always_show`, `creator`, `create_time`, `updater`, `update_time`, `deleted`) VALUES (2569, '产品删除', 'erp:product:delete', 3, 4, 2565, '', '', '', '', 0, b'1', b'1', b'1', '', '2024-02-04 07:52:15', '1', '2024-02-04 17:22:22', b'0'); +INSERT INTO `system_menu` (`id`, `name`, `permission`, `type`, `sort`, `parent_id`, `path`, `icon`, `component`, `component_name`, `status`, `visible`, `keep_alive`, `always_show`, `creator`, `create_time`, `updater`, `update_time`, `deleted`) VALUES (2570, '产品导出', 'erp:product:export', 3, 5, 2565, '', '', '', '', 0, b'1', b'1', b'1', '', '2024-02-04 07:52:15', '1', '2024-02-04 17:22:26', b'0'); +INSERT INTO `system_menu` (`id`, `name`, `permission`, `type`, `sort`, `parent_id`, `path`, `icon`, `component`, `component_name`, `status`, `visible`, `keep_alive`, `always_show`, `creator`, `create_time`, `updater`, `update_time`, `deleted`) VALUES (2571, '产品分类', '', 2, 1, 2564, 'product-category', 'fa:certificate', 'erp/product/category/index', 'ErpProductCategory', 0, b'1', b'1', b'1', '', '2024-02-04 09:21:04', '1', '2024-02-04 17:24:58', b'0'); +INSERT INTO `system_menu` (`id`, `name`, `permission`, `type`, `sort`, `parent_id`, `path`, `icon`, `component`, `component_name`, `status`, `visible`, `keep_alive`, `always_show`, `creator`, `create_time`, `updater`, `update_time`, `deleted`) VALUES (2572, '分类查询', 'erp:product-category:query', 3, 1, 2571, '', '', '', NULL, 0, b'1', b'1', b'1', '', '2024-02-04 09:21:04', '', '2024-02-04 09:21:04', b'0'); +INSERT INTO `system_menu` (`id`, `name`, `permission`, `type`, `sort`, `parent_id`, `path`, `icon`, `component`, `component_name`, `status`, `visible`, `keep_alive`, `always_show`, `creator`, `create_time`, `updater`, `update_time`, `deleted`) VALUES (2573, '分类创建', 'erp:product-category:create', 3, 2, 2571, '', '', '', NULL, 0, b'1', b'1', b'1', '', '2024-02-04 09:21:04', '', '2024-02-04 09:21:04', b'0'); +INSERT INTO `system_menu` (`id`, `name`, `permission`, `type`, `sort`, `parent_id`, `path`, `icon`, `component`, `component_name`, `status`, `visible`, `keep_alive`, `always_show`, `creator`, `create_time`, `updater`, `update_time`, `deleted`) VALUES (2574, '分类更新', 'erp:product-category:update', 3, 3, 2571, '', '', '', NULL, 0, b'1', b'1', b'1', '', '2024-02-04 09:21:04', '', '2024-02-04 09:21:04', b'0'); +INSERT INTO `system_menu` (`id`, `name`, `permission`, `type`, `sort`, `parent_id`, `path`, `icon`, `component`, `component_name`, `status`, `visible`, `keep_alive`, `always_show`, `creator`, `create_time`, `updater`, `update_time`, `deleted`) VALUES (2575, '分类删除', 'erp:product-category:delete', 3, 4, 2571, '', '', '', NULL, 0, b'1', b'1', b'1', '', '2024-02-04 09:21:04', '', '2024-02-04 09:21:04', b'0'); +INSERT INTO `system_menu` (`id`, `name`, `permission`, `type`, `sort`, `parent_id`, `path`, `icon`, `component`, `component_name`, `status`, `visible`, `keep_alive`, `always_show`, `creator`, `create_time`, `updater`, `update_time`, `deleted`) VALUES (2576, '分类导出', 'erp:product-category:export', 3, 5, 2571, '', '', '', NULL, 0, b'1', b'1', b'1', '', '2024-02-04 09:21:04', '', '2024-02-04 09:21:04', b'0'); +INSERT INTO `system_menu` (`id`, `name`, `permission`, `type`, `sort`, `parent_id`, `path`, `icon`, `component`, `component_name`, `status`, `visible`, `keep_alive`, `always_show`, `creator`, `create_time`, `updater`, `update_time`, `deleted`) VALUES (2577, '产品单位', '', 2, 2, 2564, 'unit', 'ep:opportunity', 'erp/product/unit/index', 'ErpProductUnit', 0, b'1', b'1', b'1', '', '2024-02-04 11:54:08', '1', '2024-02-04 19:54:37', b'0'); +INSERT INTO `system_menu` (`id`, `name`, `permission`, `type`, `sort`, `parent_id`, `path`, `icon`, `component`, `component_name`, `status`, `visible`, `keep_alive`, `always_show`, `creator`, `create_time`, `updater`, `update_time`, `deleted`) VALUES (2578, '单位查询', 'erp:product-unit:query', 3, 1, 2577, '', '', '', NULL, 0, b'1', b'1', b'1', '', '2024-02-04 11:54:08', '', '2024-02-04 11:54:08', b'0'); +INSERT INTO `system_menu` (`id`, `name`, `permission`, `type`, `sort`, `parent_id`, `path`, `icon`, `component`, `component_name`, `status`, `visible`, `keep_alive`, `always_show`, `creator`, `create_time`, `updater`, `update_time`, `deleted`) VALUES (2579, '单位创建', 'erp:product-unit:create', 3, 2, 2577, '', '', '', NULL, 0, b'1', b'1', b'1', '', '2024-02-04 11:54:08', '', '2024-02-04 11:54:08', b'0'); +INSERT INTO `system_menu` (`id`, `name`, `permission`, `type`, `sort`, `parent_id`, `path`, `icon`, `component`, `component_name`, `status`, `visible`, `keep_alive`, `always_show`, `creator`, `create_time`, `updater`, `update_time`, `deleted`) VALUES (2580, '单位更新', 'erp:product-unit:update', 3, 3, 2577, '', '', '', NULL, 0, b'1', b'1', b'1', '', '2024-02-04 11:54:08', '', '2024-02-04 11:54:08', b'0'); +INSERT INTO `system_menu` (`id`, `name`, `permission`, `type`, `sort`, `parent_id`, `path`, `icon`, `component`, `component_name`, `status`, `visible`, `keep_alive`, `always_show`, `creator`, `create_time`, `updater`, `update_time`, `deleted`) VALUES (2581, '单位删除', 'erp:product-unit:delete', 3, 4, 2577, '', '', '', NULL, 0, b'1', b'1', b'1', '', '2024-02-04 11:54:08', '', '2024-02-04 11:54:08', b'0'); +INSERT INTO `system_menu` (`id`, `name`, `permission`, `type`, `sort`, `parent_id`, `path`, `icon`, `component`, `component_name`, `status`, `visible`, `keep_alive`, `always_show`, `creator`, `create_time`, `updater`, `update_time`, `deleted`) VALUES (2582, '单位导出', 'erp:product-unit:export', 3, 5, 2577, '', '', '', NULL, 0, b'1', b'1', b'1', '', '2024-02-04 11:54:08', '', '2024-02-04 11:54:08', b'0'); +INSERT INTO `system_menu` (`id`, `name`, `permission`, `type`, `sort`, `parent_id`, `path`, `icon`, `component`, `component_name`, `status`, `visible`, `keep_alive`, `always_show`, `creator`, `create_time`, `updater`, `update_time`, `deleted`) VALUES (2583, '库存管理', '', 1, 30, 2563, 'stock', 'fa:window-restore', '', '', 0, b'1', b'1', b'1', '1', '2024-02-05 00:29:37', '1', '2024-02-05 00:29:37', b'0'); +INSERT INTO `system_menu` (`id`, `name`, `permission`, `type`, `sort`, `parent_id`, `path`, `icon`, `component`, `component_name`, `status`, `visible`, `keep_alive`, `always_show`, `creator`, `create_time`, `updater`, `update_time`, `deleted`) VALUES (2584, '仓库信息', '', 2, 0, 2583, 'warehouse', 'ep:house', 'erp/stock/warehouse/index', 'ErpWarehouse', 0, b'1', b'1', b'1', '', '2024-02-04 17:12:09', '1', '2024-02-05 01:12:53', b'0'); +INSERT INTO `system_menu` (`id`, `name`, `permission`, `type`, `sort`, `parent_id`, `path`, `icon`, `component`, `component_name`, `status`, `visible`, `keep_alive`, `always_show`, `creator`, `create_time`, `updater`, `update_time`, `deleted`) VALUES (2585, '仓库查询', 'erp:warehouse:query', 3, 1, 2584, '', '', '', NULL, 0, b'1', b'1', b'1', '', '2024-02-04 17:12:09', '', '2024-02-04 17:12:09', b'0'); +INSERT INTO `system_menu` (`id`, `name`, `permission`, `type`, `sort`, `parent_id`, `path`, `icon`, `component`, `component_name`, `status`, `visible`, `keep_alive`, `always_show`, `creator`, `create_time`, `updater`, `update_time`, `deleted`) VALUES (2586, '仓库创建', 'erp:warehouse:create', 3, 2, 2584, '', '', '', NULL, 0, b'1', b'1', b'1', '', '2024-02-04 17:12:09', '', '2024-02-04 17:12:09', b'0'); +INSERT INTO `system_menu` (`id`, `name`, `permission`, `type`, `sort`, `parent_id`, `path`, `icon`, `component`, `component_name`, `status`, `visible`, `keep_alive`, `always_show`, `creator`, `create_time`, `updater`, `update_time`, `deleted`) VALUES (2587, '仓库更新', 'erp:warehouse:update', 3, 3, 2584, '', '', '', NULL, 0, b'1', b'1', b'1', '', '2024-02-04 17:12:09', '', '2024-02-04 17:12:09', b'0'); +INSERT INTO `system_menu` (`id`, `name`, `permission`, `type`, `sort`, `parent_id`, `path`, `icon`, `component`, `component_name`, `status`, `visible`, `keep_alive`, `always_show`, `creator`, `create_time`, `updater`, `update_time`, `deleted`) VALUES (2588, '仓库删除', 'erp:warehouse:delete', 3, 4, 2584, '', '', '', NULL, 0, b'1', b'1', b'1', '', '2024-02-04 17:12:09', '', '2024-02-04 17:12:09', b'0'); +INSERT INTO `system_menu` (`id`, `name`, `permission`, `type`, `sort`, `parent_id`, `path`, `icon`, `component`, `component_name`, `status`, `visible`, `keep_alive`, `always_show`, `creator`, `create_time`, `updater`, `update_time`, `deleted`) VALUES (2589, '仓库导出', 'erp:warehouse:export', 3, 5, 2584, '', '', '', NULL, 0, b'1', b'1', b'1', '', '2024-02-04 17:12:09', '', '2024-02-04 17:12:09', b'0'); +INSERT INTO `system_menu` (`id`, `name`, `permission`, `type`, `sort`, `parent_id`, `path`, `icon`, `component`, `component_name`, `status`, `visible`, `keep_alive`, `always_show`, `creator`, `create_time`, `updater`, `update_time`, `deleted`) VALUES (2590, '产品库存', '', 2, 1, 2583, 'stock', 'ep:coffee', 'erp/stock/stock/index', 'ErpStock', 0, b'1', b'1', b'1', '', '2024-02-05 06:40:50', '1', '2024-02-05 14:42:44', b'0'); +INSERT INTO `system_menu` (`id`, `name`, `permission`, `type`, `sort`, `parent_id`, `path`, `icon`, `component`, `component_name`, `status`, `visible`, `keep_alive`, `always_show`, `creator`, `create_time`, `updater`, `update_time`, `deleted`) VALUES (2591, '库存查询', 'erp:stock:query', 3, 1, 2590, '', '', '', NULL, 0, b'1', b'1', b'1', '', '2024-02-05 06:40:50', '', '2024-02-05 06:40:50', b'0'); +INSERT INTO `system_menu` (`id`, `name`, `permission`, `type`, `sort`, `parent_id`, `path`, `icon`, `component`, `component_name`, `status`, `visible`, `keep_alive`, `always_show`, `creator`, `create_time`, `updater`, `update_time`, `deleted`) VALUES (2592, '库存导出', 'erp:stock:export', 3, 5, 2590, '', '', '', NULL, 0, b'1', b'1', b'1', '', '2024-02-05 06:40:50', '', '2024-02-05 06:40:50', b'0'); +INSERT INTO `system_menu` (`id`, `name`, `permission`, `type`, `sort`, `parent_id`, `path`, `icon`, `component`, `component_name`, `status`, `visible`, `keep_alive`, `always_show`, `creator`, `create_time`, `updater`, `update_time`, `deleted`) VALUES (2593, '出入库明细', '', 2, 2, 2583, 'record', 'fa-solid:blog', 'erp/stock/record/index', 'ErpStockRecord', 0, b'1', b'1', b'1', '', '2024-02-05 10:27:21', '1', '2024-02-06 17:26:11', b'0'); +INSERT INTO `system_menu` (`id`, `name`, `permission`, `type`, `sort`, `parent_id`, `path`, `icon`, `component`, `component_name`, `status`, `visible`, `keep_alive`, `always_show`, `creator`, `create_time`, `updater`, `update_time`, `deleted`) VALUES (2594, '库存明细查询', 'erp:stock-record:query', 3, 1, 2593, '', '', '', NULL, 0, b'1', b'1', b'1', '', '2024-02-05 10:27:21', '', '2024-02-05 10:27:21', b'0'); +INSERT INTO `system_menu` (`id`, `name`, `permission`, `type`, `sort`, `parent_id`, `path`, `icon`, `component`, `component_name`, `status`, `visible`, `keep_alive`, `always_show`, `creator`, `create_time`, `updater`, `update_time`, `deleted`) VALUES (2595, '库存明细导出', 'erp:stock-record:export', 3, 5, 2593, '', '', '', NULL, 0, b'1', b'1', b'1', '', '2024-02-05 10:27:21', '', '2024-02-05 10:27:21', b'0'); +INSERT INTO `system_menu` (`id`, `name`, `permission`, `type`, `sort`, `parent_id`, `path`, `icon`, `component`, `component_name`, `status`, `visible`, `keep_alive`, `always_show`, `creator`, `create_time`, `updater`, `update_time`, `deleted`) VALUES (2596, '其它入库', '', 2, 3, 2583, 'in', 'ep:zoom-in', 'erp/stock/in/index', 'ErpStockIn', 0, b'1', b'1', b'1', '', '2024-02-05 16:08:56', '1', '2024-02-07 19:06:51', b'0'); +INSERT INTO `system_menu` (`id`, `name`, `permission`, `type`, `sort`, `parent_id`, `path`, `icon`, `component`, `component_name`, `status`, `visible`, `keep_alive`, `always_show`, `creator`, `create_time`, `updater`, `update_time`, `deleted`) VALUES (2597, '其它入库单查询', 'erp:stock-in:query', 3, 1, 2596, '', '', '', NULL, 0, b'1', b'1', b'1', '', '2024-02-05 16:08:56', '', '2024-02-05 16:08:56', b'0'); +INSERT INTO `system_menu` (`id`, `name`, `permission`, `type`, `sort`, `parent_id`, `path`, `icon`, `component`, `component_name`, `status`, `visible`, `keep_alive`, `always_show`, `creator`, `create_time`, `updater`, `update_time`, `deleted`) VALUES (2598, '其它入库单创建', 'erp:stock-in:create', 3, 2, 2596, '', '', '', NULL, 0, b'1', b'1', b'1', '', '2024-02-05 16:08:56', '', '2024-02-05 16:08:56', b'0'); +INSERT INTO `system_menu` (`id`, `name`, `permission`, `type`, `sort`, `parent_id`, `path`, `icon`, `component`, `component_name`, `status`, `visible`, `keep_alive`, `always_show`, `creator`, `create_time`, `updater`, `update_time`, `deleted`) VALUES (2599, '其它入库单更新', 'erp:stock-in:update', 3, 3, 2596, '', '', '', NULL, 0, b'1', b'1', b'1', '', '2024-02-05 16:08:56', '', '2024-02-05 16:08:56', b'0'); +INSERT INTO `system_menu` (`id`, `name`, `permission`, `type`, `sort`, `parent_id`, `path`, `icon`, `component`, `component_name`, `status`, `visible`, `keep_alive`, `always_show`, `creator`, `create_time`, `updater`, `update_time`, `deleted`) VALUES (2600, '其它入库单删除', 'erp:stock-in:delete', 3, 4, 2596, '', '', '', NULL, 0, b'1', b'1', b'1', '', '2024-02-05 16:08:56', '', '2024-02-05 16:08:56', b'0'); +INSERT INTO `system_menu` (`id`, `name`, `permission`, `type`, `sort`, `parent_id`, `path`, `icon`, `component`, `component_name`, `status`, `visible`, `keep_alive`, `always_show`, `creator`, `create_time`, `updater`, `update_time`, `deleted`) VALUES (2601, '其它入库单导出', 'erp:stock-in:export', 3, 5, 2596, '', '', '', NULL, 0, b'1', b'1', b'1', '', '2024-02-05 16:08:56', '', '2024-02-05 16:08:56', b'0'); +INSERT INTO `system_menu` (`id`, `name`, `permission`, `type`, `sort`, `parent_id`, `path`, `icon`, `component`, `component_name`, `status`, `visible`, `keep_alive`, `always_show`, `creator`, `create_time`, `updater`, `update_time`, `deleted`) VALUES (2602, '采购管理', '', 1, 10, 2563, 'purchase', 'fa:buysellads', '', '', 0, b'1', b'1', b'1', '1', '2024-02-06 16:01:01', '1', '2024-02-06 16:01:23', b'0'); +INSERT INTO `system_menu` (`id`, `name`, `permission`, `type`, `sort`, `parent_id`, `path`, `icon`, `component`, `component_name`, `status`, `visible`, `keep_alive`, `always_show`, `creator`, `create_time`, `updater`, `update_time`, `deleted`) VALUES (2603, '供应商信息', '', 2, 4, 2602, 'supplier', 'fa:superpowers', 'erp/purchase/supplier/index', 'ErpSupplier', 0, b'1', b'1', b'1', '', '2024-02-06 08:21:55', '1', '2024-02-06 16:22:25', b'0'); +INSERT INTO `system_menu` (`id`, `name`, `permission`, `type`, `sort`, `parent_id`, `path`, `icon`, `component`, `component_name`, `status`, `visible`, `keep_alive`, `always_show`, `creator`, `create_time`, `updater`, `update_time`, `deleted`) VALUES (2604, '供应商查询', 'erp:supplier:query', 3, 1, 2603, '', '', '', NULL, 0, b'1', b'1', b'1', '', '2024-02-06 08:21:55', '', '2024-02-06 08:21:55', b'0'); +INSERT INTO `system_menu` (`id`, `name`, `permission`, `type`, `sort`, `parent_id`, `path`, `icon`, `component`, `component_name`, `status`, `visible`, `keep_alive`, `always_show`, `creator`, `create_time`, `updater`, `update_time`, `deleted`) VALUES (2605, '供应商创建', 'erp:supplier:create', 3, 2, 2603, '', '', '', NULL, 0, b'1', b'1', b'1', '', '2024-02-06 08:21:55', '', '2024-02-06 08:21:55', b'0'); +INSERT INTO `system_menu` (`id`, `name`, `permission`, `type`, `sort`, `parent_id`, `path`, `icon`, `component`, `component_name`, `status`, `visible`, `keep_alive`, `always_show`, `creator`, `create_time`, `updater`, `update_time`, `deleted`) VALUES (2606, '供应商更新', 'erp:supplier:update', 3, 3, 2603, '', '', '', NULL, 0, b'1', b'1', b'1', '', '2024-02-06 08:21:55', '', '2024-02-06 08:21:55', b'0'); +INSERT INTO `system_menu` (`id`, `name`, `permission`, `type`, `sort`, `parent_id`, `path`, `icon`, `component`, `component_name`, `status`, `visible`, `keep_alive`, `always_show`, `creator`, `create_time`, `updater`, `update_time`, `deleted`) VALUES (2607, '供应商删除', 'erp:supplier:delete', 3, 4, 2603, '', '', '', NULL, 0, b'1', b'1', b'1', '', '2024-02-06 08:21:55', '', '2024-02-06 08:21:55', b'0'); +INSERT INTO `system_menu` (`id`, `name`, `permission`, `type`, `sort`, `parent_id`, `path`, `icon`, `component`, `component_name`, `status`, `visible`, `keep_alive`, `always_show`, `creator`, `create_time`, `updater`, `update_time`, `deleted`) VALUES (2608, '供应商导出', 'erp:supplier:export', 3, 5, 2603, '', '', '', NULL, 0, b'1', b'1', b'1', '', '2024-02-06 08:21:55', '', '2024-02-06 08:21:55', b'0'); +INSERT INTO `system_menu` (`id`, `name`, `permission`, `type`, `sort`, `parent_id`, `path`, `icon`, `component`, `component_name`, `status`, `visible`, `keep_alive`, `always_show`, `creator`, `create_time`, `updater`, `update_time`, `deleted`) VALUES (2609, '其它入库单审批', 'erp:stock-in:update-status', 3, 6, 2596, '', '', '', NULL, 0, b'1', b'1', b'1', '', '2024-02-05 16:08:56', '', '2024-02-05 16:08:56', b'0'); +INSERT INTO `system_menu` (`id`, `name`, `permission`, `type`, `sort`, `parent_id`, `path`, `icon`, `component`, `component_name`, `status`, `visible`, `keep_alive`, `always_show`, `creator`, `create_time`, `updater`, `update_time`, `deleted`) VALUES (2610, '其它出库', '', 2, 4, 2583, 'out', 'ep:zoom-out', 'erp/stock/out/index', 'ErpStockOut', 0, b'1', b'1', b'1', '', '2024-02-05 16:08:56', '1', '2024-02-07 19:06:55', b'0'); +INSERT INTO `system_menu` (`id`, `name`, `permission`, `type`, `sort`, `parent_id`, `path`, `icon`, `component`, `component_name`, `status`, `visible`, `keep_alive`, `always_show`, `creator`, `create_time`, `updater`, `update_time`, `deleted`) VALUES (2611, '其它出库单查询', 'erp:stock-out:query', 3, 1, 2610, '', '', '', NULL, 0, b'1', b'1', b'1', '', '2024-02-05 16:08:56', '', '2024-02-07 06:43:39', b'0'); +INSERT INTO `system_menu` (`id`, `name`, `permission`, `type`, `sort`, `parent_id`, `path`, `icon`, `component`, `component_name`, `status`, `visible`, `keep_alive`, `always_show`, `creator`, `create_time`, `updater`, `update_time`, `deleted`) VALUES (2612, '其它出库单创建', 'erp:stock-out:create', 3, 2, 2610, '', '', '', NULL, 0, b'1', b'1', b'1', '', '2024-02-05 16:08:56', '', '2024-02-07 06:43:42', b'0'); +INSERT INTO `system_menu` (`id`, `name`, `permission`, `type`, `sort`, `parent_id`, `path`, `icon`, `component`, `component_name`, `status`, `visible`, `keep_alive`, `always_show`, `creator`, `create_time`, `updater`, `update_time`, `deleted`) VALUES (2613, '其它出库单更新', 'erp:stock-out:update', 3, 3, 2610, '', '', '', NULL, 0, b'1', b'1', b'1', '', '2024-02-05 16:08:56', '', '2024-02-07 06:43:44', b'0'); +INSERT INTO `system_menu` (`id`, `name`, `permission`, `type`, `sort`, `parent_id`, `path`, `icon`, `component`, `component_name`, `status`, `visible`, `keep_alive`, `always_show`, `creator`, `create_time`, `updater`, `update_time`, `deleted`) VALUES (2614, '其它出库单删除', 'erp:stock-out:delete', 3, 4, 2610, '', '', '', NULL, 0, b'1', b'1', b'1', '', '2024-02-05 16:08:56', '', '2024-02-07 06:43:56', b'0'); +INSERT INTO `system_menu` (`id`, `name`, `permission`, `type`, `sort`, `parent_id`, `path`, `icon`, `component`, `component_name`, `status`, `visible`, `keep_alive`, `always_show`, `creator`, `create_time`, `updater`, `update_time`, `deleted`) VALUES (2615, '其它出库单导出', 'erp:stock-out:export', 3, 5, 2610, '', '', '', NULL, 0, b'1', b'1', b'1', '', '2024-02-05 16:08:56', '', '2024-02-07 06:43:57', b'0'); +INSERT INTO `system_menu` (`id`, `name`, `permission`, `type`, `sort`, `parent_id`, `path`, `icon`, `component`, `component_name`, `status`, `visible`, `keep_alive`, `always_show`, `creator`, `create_time`, `updater`, `update_time`, `deleted`) VALUES (2616, '其它出库单审批', 'erp:stock-out:update-status', 3, 6, 2610, '', '', '', NULL, 0, b'1', b'1', b'1', '', '2024-02-05 16:08:56', '', '2024-02-07 06:43:58', b'0'); +INSERT INTO `system_menu` (`id`, `name`, `permission`, `type`, `sort`, `parent_id`, `path`, `icon`, `component`, `component_name`, `status`, `visible`, `keep_alive`, `always_show`, `creator`, `create_time`, `updater`, `update_time`, `deleted`) VALUES (2617, '销售管理', '', 1, 20, 2563, 'sale', 'fa:sellsy', '', '', 0, b'1', b'1', b'1', '1', '2024-02-07 15:12:32', '1', '2024-02-07 15:12:32', b'0'); +INSERT INTO `system_menu` (`id`, `name`, `permission`, `type`, `sort`, `parent_id`, `path`, `icon`, `component`, `component_name`, `status`, `visible`, `keep_alive`, `always_show`, `creator`, `create_time`, `updater`, `update_time`, `deleted`) VALUES (2618, '客户信息', '', 2, 4, 2617, 'customer', 'ep:avatar', 'erp/sale/customer/index', 'ErpCustomer', 0, b'1', b'1', b'1', '', '2024-02-07 07:21:45', '1', '2024-02-07 15:22:25', b'0'); +INSERT INTO `system_menu` (`id`, `name`, `permission`, `type`, `sort`, `parent_id`, `path`, `icon`, `component`, `component_name`, `status`, `visible`, `keep_alive`, `always_show`, `creator`, `create_time`, `updater`, `update_time`, `deleted`) VALUES (2619, '客户查询', 'erp:customer:query', 3, 1, 2618, '', '', '', NULL, 0, b'1', b'1', b'1', '', '2024-02-07 07:21:45', '', '2024-02-07 07:21:45', b'0'); +INSERT INTO `system_menu` (`id`, `name`, `permission`, `type`, `sort`, `parent_id`, `path`, `icon`, `component`, `component_name`, `status`, `visible`, `keep_alive`, `always_show`, `creator`, `create_time`, `updater`, `update_time`, `deleted`) VALUES (2620, '客户创建', 'erp:customer:create', 3, 2, 2618, '', '', '', NULL, 0, b'1', b'1', b'1', '', '2024-02-07 07:21:45', '', '2024-02-07 07:21:45', b'0'); +INSERT INTO `system_menu` (`id`, `name`, `permission`, `type`, `sort`, `parent_id`, `path`, `icon`, `component`, `component_name`, `status`, `visible`, `keep_alive`, `always_show`, `creator`, `create_time`, `updater`, `update_time`, `deleted`) VALUES (2621, '客户更新', 'erp:customer:update', 3, 3, 2618, '', '', '', NULL, 0, b'1', b'1', b'1', '', '2024-02-07 07:21:45', '', '2024-02-07 07:21:45', b'0'); +INSERT INTO `system_menu` (`id`, `name`, `permission`, `type`, `sort`, `parent_id`, `path`, `icon`, `component`, `component_name`, `status`, `visible`, `keep_alive`, `always_show`, `creator`, `create_time`, `updater`, `update_time`, `deleted`) VALUES (2622, '客户删除', 'erp:customer:delete', 3, 4, 2618, '', '', '', NULL, 0, b'1', b'1', b'1', '', '2024-02-07 07:21:45', '', '2024-02-07 07:21:45', b'0'); +INSERT INTO `system_menu` (`id`, `name`, `permission`, `type`, `sort`, `parent_id`, `path`, `icon`, `component`, `component_name`, `status`, `visible`, `keep_alive`, `always_show`, `creator`, `create_time`, `updater`, `update_time`, `deleted`) VALUES (2623, '客户导出', 'erp:customer:export', 3, 5, 2618, '', '', '', NULL, 0, b'1', b'1', b'1', '', '2024-02-07 07:21:45', '', '2024-02-07 07:21:45', b'0'); +INSERT INTO `system_menu` (`id`, `name`, `permission`, `type`, `sort`, `parent_id`, `path`, `icon`, `component`, `component_name`, `status`, `visible`, `keep_alive`, `always_show`, `creator`, `create_time`, `updater`, `update_time`, `deleted`) VALUES (2624, '库存调拨', '', 2, 5, 2583, 'move', 'ep:folder-remove', 'erp/stock/move/index', 'ErpStockMove', 0, b'1', b'1', b'1', '', '2024-02-05 16:08:56', '1', '2024-02-16 18:53:55', b'0'); +INSERT INTO `system_menu` (`id`, `name`, `permission`, `type`, `sort`, `parent_id`, `path`, `icon`, `component`, `component_name`, `status`, `visible`, `keep_alive`, `always_show`, `creator`, `create_time`, `updater`, `update_time`, `deleted`) VALUES (2625, '库存调度单查询', 'erp:stock-move:query', 3, 1, 2624, '', '', '', NULL, 0, b'1', b'1', b'1', '', '2024-02-05 16:08:56', '', '2024-02-07 11:12:49', b'0'); +INSERT INTO `system_menu` (`id`, `name`, `permission`, `type`, `sort`, `parent_id`, `path`, `icon`, `component`, `component_name`, `status`, `visible`, `keep_alive`, `always_show`, `creator`, `create_time`, `updater`, `update_time`, `deleted`) VALUES (2626, '库存调度单创建', 'erp:stock-move:create', 3, 2, 2624, '', '', '', NULL, 0, b'1', b'1', b'1', '', '2024-02-05 16:08:56', '', '2024-02-07 11:12:52', b'0'); +INSERT INTO `system_menu` (`id`, `name`, `permission`, `type`, `sort`, `parent_id`, `path`, `icon`, `component`, `component_name`, `status`, `visible`, `keep_alive`, `always_show`, `creator`, `create_time`, `updater`, `update_time`, `deleted`) VALUES (2627, '库存调度单更新', 'erp:stock-move:update', 3, 3, 2624, '', '', '', NULL, 0, b'1', b'1', b'1', '', '2024-02-05 16:08:56', '', '2024-02-07 11:12:55', b'0'); +INSERT INTO `system_menu` (`id`, `name`, `permission`, `type`, `sort`, `parent_id`, `path`, `icon`, `component`, `component_name`, `status`, `visible`, `keep_alive`, `always_show`, `creator`, `create_time`, `updater`, `update_time`, `deleted`) VALUES (2628, '库存调度单删除', 'erp:stock-move:delete', 3, 4, 2624, '', '', '', NULL, 0, b'1', b'1', b'1', '', '2024-02-05 16:08:56', '', '2024-02-07 11:12:57', b'0'); +INSERT INTO `system_menu` (`id`, `name`, `permission`, `type`, `sort`, `parent_id`, `path`, `icon`, `component`, `component_name`, `status`, `visible`, `keep_alive`, `always_show`, `creator`, `create_time`, `updater`, `update_time`, `deleted`) VALUES (2629, '库存调度单导出', 'erp:stock-move:export', 3, 5, 2624, '', '', '', NULL, 0, b'1', b'1', b'1', '', '2024-02-05 16:08:56', '', '2024-02-07 11:12:59', b'0'); +INSERT INTO `system_menu` (`id`, `name`, `permission`, `type`, `sort`, `parent_id`, `path`, `icon`, `component`, `component_name`, `status`, `visible`, `keep_alive`, `always_show`, `creator`, `create_time`, `updater`, `update_time`, `deleted`) VALUES (2630, '库存调度单审批', 'erp:stock-move:update-status', 3, 6, 2624, '', '', '', NULL, 0, b'1', b'1', b'1', '', '2024-02-05 16:08:56', '', '2024-02-07 11:13:03', b'0'); +INSERT INTO `system_menu` (`id`, `name`, `permission`, `type`, `sort`, `parent_id`, `path`, `icon`, `component`, `component_name`, `status`, `visible`, `keep_alive`, `always_show`, `creator`, `create_time`, `updater`, `update_time`, `deleted`) VALUES (2631, '库存盘点', '', 2, 6, 2583, 'check', 'ep:circle-check-filled', 'erp/stock/check/index', 'ErpStockCheck', 0, b'1', b'1', b'1', '', '2024-02-05 16:08:56', '1', '2024-02-08 08:31:09', b'0'); +INSERT INTO `system_menu` (`id`, `name`, `permission`, `type`, `sort`, `parent_id`, `path`, `icon`, `component`, `component_name`, `status`, `visible`, `keep_alive`, `always_show`, `creator`, `create_time`, `updater`, `update_time`, `deleted`) VALUES (2632, '库存盘点单查询', 'erp:stock-check:query', 3, 1, 2631, '', '', '', NULL, 0, b'1', b'1', b'1', '', '2024-02-05 16:08:56', '', '2024-02-07 11:12:49', b'0'); +INSERT INTO `system_menu` (`id`, `name`, `permission`, `type`, `sort`, `parent_id`, `path`, `icon`, `component`, `component_name`, `status`, `visible`, `keep_alive`, `always_show`, `creator`, `create_time`, `updater`, `update_time`, `deleted`) VALUES (2633, '库存盘点单创建', 'erp:stock-check:create', 3, 2, 2631, '', '', '', NULL, 0, b'1', b'1', b'1', '', '2024-02-05 16:08:56', '', '2024-02-07 11:12:52', b'0'); +INSERT INTO `system_menu` (`id`, `name`, `permission`, `type`, `sort`, `parent_id`, `path`, `icon`, `component`, `component_name`, `status`, `visible`, `keep_alive`, `always_show`, `creator`, `create_time`, `updater`, `update_time`, `deleted`) VALUES (2634, '库存盘点单更新', 'erp:stock-check:update', 3, 3, 2631, '', '', '', NULL, 0, b'1', b'1', b'1', '', '2024-02-05 16:08:56', '', '2024-02-07 11:12:55', b'0'); +INSERT INTO `system_menu` (`id`, `name`, `permission`, `type`, `sort`, `parent_id`, `path`, `icon`, `component`, `component_name`, `status`, `visible`, `keep_alive`, `always_show`, `creator`, `create_time`, `updater`, `update_time`, `deleted`) VALUES (2635, '库存盘点单删除', 'erp:stock-check:delete', 3, 4, 2631, '', '', '', NULL, 0, b'1', b'1', b'1', '', '2024-02-05 16:08:56', '', '2024-02-07 11:12:57', b'0'); +INSERT INTO `system_menu` (`id`, `name`, `permission`, `type`, `sort`, `parent_id`, `path`, `icon`, `component`, `component_name`, `status`, `visible`, `keep_alive`, `always_show`, `creator`, `create_time`, `updater`, `update_time`, `deleted`) VALUES (2636, '库存盘点单导出', 'erp:stock-check:export', 3, 5, 2631, '', '', '', NULL, 0, b'1', b'1', b'1', '', '2024-02-05 16:08:56', '', '2024-02-07 11:12:59', b'0'); +INSERT INTO `system_menu` (`id`, `name`, `permission`, `type`, `sort`, `parent_id`, `path`, `icon`, `component`, `component_name`, `status`, `visible`, `keep_alive`, `always_show`, `creator`, `create_time`, `updater`, `update_time`, `deleted`) VALUES (2637, '库存盘点单审批', 'erp:stock-check:update-status', 3, 6, 2631, '', '', '', NULL, 0, b'1', b'1', b'1', '', '2024-02-05 16:08:56', '', '2024-02-07 11:13:03', b'0'); +INSERT INTO `system_menu` (`id`, `name`, `permission`, `type`, `sort`, `parent_id`, `path`, `icon`, `component`, `component_name`, `status`, `visible`, `keep_alive`, `always_show`, `creator`, `create_time`, `updater`, `update_time`, `deleted`) VALUES (2638, '销售订单', '', 2, 1, 2617, 'order', 'fa:first-order', 'erp/sale/order/index', 'ErpSaleOrder', 0, b'1', b'1', b'1', '', '2024-02-05 16:08:56', '1', '2024-02-10 21:59:20', b'0'); +INSERT INTO `system_menu` (`id`, `name`, `permission`, `type`, `sort`, `parent_id`, `path`, `icon`, `component`, `component_name`, `status`, `visible`, `keep_alive`, `always_show`, `creator`, `create_time`, `updater`, `update_time`, `deleted`) VALUES (2639, '销售订单查询', 'erp:sale-order:query', 3, 1, 2638, '', '', '', NULL, 0, b'1', b'1', b'1', '', '2024-02-05 16:08:56', '', '2024-02-07 11:12:49', b'0'); +INSERT INTO `system_menu` (`id`, `name`, `permission`, `type`, `sort`, `parent_id`, `path`, `icon`, `component`, `component_name`, `status`, `visible`, `keep_alive`, `always_show`, `creator`, `create_time`, `updater`, `update_time`, `deleted`) VALUES (2640, '销售订单创建', 'erp:sale-order:create', 3, 2, 2638, '', '', '', NULL, 0, b'1', b'1', b'1', '', '2024-02-05 16:08:56', '', '2024-02-07 11:12:52', b'0'); +INSERT INTO `system_menu` (`id`, `name`, `permission`, `type`, `sort`, `parent_id`, `path`, `icon`, `component`, `component_name`, `status`, `visible`, `keep_alive`, `always_show`, `creator`, `create_time`, `updater`, `update_time`, `deleted`) VALUES (2641, '销售订单更新', 'erp:sale-order:update', 3, 3, 2638, '', '', '', NULL, 0, b'1', b'1', b'1', '', '2024-02-05 16:08:56', '', '2024-02-07 11:12:55', b'0'); +INSERT INTO `system_menu` (`id`, `name`, `permission`, `type`, `sort`, `parent_id`, `path`, `icon`, `component`, `component_name`, `status`, `visible`, `keep_alive`, `always_show`, `creator`, `create_time`, `updater`, `update_time`, `deleted`) VALUES (2642, '销售订单删除', 'erp:sale-order:delete', 3, 4, 2638, '', '', '', NULL, 0, b'1', b'1', b'1', '', '2024-02-05 16:08:56', '', '2024-02-07 11:12:57', b'0'); +INSERT INTO `system_menu` (`id`, `name`, `permission`, `type`, `sort`, `parent_id`, `path`, `icon`, `component`, `component_name`, `status`, `visible`, `keep_alive`, `always_show`, `creator`, `create_time`, `updater`, `update_time`, `deleted`) VALUES (2643, '销售订单导出', 'erp:sale-order:export', 3, 5, 2638, '', '', '', NULL, 0, b'1', b'1', b'1', '', '2024-02-05 16:08:56', '', '2024-02-07 11:12:59', b'0'); +INSERT INTO `system_menu` (`id`, `name`, `permission`, `type`, `sort`, `parent_id`, `path`, `icon`, `component`, `component_name`, `status`, `visible`, `keep_alive`, `always_show`, `creator`, `create_time`, `updater`, `update_time`, `deleted`) VALUES (2644, '销售订单审批', 'erp:sale-order:update-status', 3, 6, 2638, '', '', '', NULL, 0, b'1', b'1', b'1', '', '2024-02-05 16:08:56', '', '2024-02-07 11:13:03', b'0'); +INSERT INTO `system_menu` (`id`, `name`, `permission`, `type`, `sort`, `parent_id`, `path`, `icon`, `component`, `component_name`, `status`, `visible`, `keep_alive`, `always_show`, `creator`, `create_time`, `updater`, `update_time`, `deleted`) VALUES (2645, '财务管理', '', 1, 50, 2563, 'finance', 'ep:money', '', '', 0, b'1', b'1', b'1', '1', '2024-02-10 08:05:58', '1', '2024-02-10 08:06:07', b'0'); +INSERT INTO `system_menu` (`id`, `name`, `permission`, `type`, `sort`, `parent_id`, `path`, `icon`, `component`, `component_name`, `status`, `visible`, `keep_alive`, `always_show`, `creator`, `create_time`, `updater`, `update_time`, `deleted`) VALUES (2646, '结算账户', '', 2, 10, 2645, 'account', 'fa:universal-access', 'erp/finance/account/index', 'ErpAccount', 0, b'1', b'1', b'1', '', '2024-02-10 00:15:07', '1', '2024-02-14 08:24:31', b'0'); +INSERT INTO `system_menu` (`id`, `name`, `permission`, `type`, `sort`, `parent_id`, `path`, `icon`, `component`, `component_name`, `status`, `visible`, `keep_alive`, `always_show`, `creator`, `create_time`, `updater`, `update_time`, `deleted`) VALUES (2647, '结算账户查询', 'erp:account:query', 3, 1, 2646, '', '', '', NULL, 0, b'1', b'1', b'1', '', '2024-02-10 00:15:07', '', '2024-02-10 00:15:07', b'0'); +INSERT INTO `system_menu` (`id`, `name`, `permission`, `type`, `sort`, `parent_id`, `path`, `icon`, `component`, `component_name`, `status`, `visible`, `keep_alive`, `always_show`, `creator`, `create_time`, `updater`, `update_time`, `deleted`) VALUES (2648, '结算账户创建', 'erp:account:create', 3, 2, 2646, '', '', '', NULL, 0, b'1', b'1', b'1', '', '2024-02-10 00:15:07', '', '2024-02-10 00:15:07', b'0'); +INSERT INTO `system_menu` (`id`, `name`, `permission`, `type`, `sort`, `parent_id`, `path`, `icon`, `component`, `component_name`, `status`, `visible`, `keep_alive`, `always_show`, `creator`, `create_time`, `updater`, `update_time`, `deleted`) VALUES (2649, '结算账户更新', 'erp:account:update', 3, 3, 2646, '', '', '', NULL, 0, b'1', b'1', b'1', '', '2024-02-10 00:15:07', '', '2024-02-10 00:15:07', b'0'); +INSERT INTO `system_menu` (`id`, `name`, `permission`, `type`, `sort`, `parent_id`, `path`, `icon`, `component`, `component_name`, `status`, `visible`, `keep_alive`, `always_show`, `creator`, `create_time`, `updater`, `update_time`, `deleted`) VALUES (2650, '结算账户删除', 'erp:account:delete', 3, 4, 2646, '', '', '', NULL, 0, b'1', b'1', b'1', '', '2024-02-10 00:15:07', '', '2024-02-10 00:15:07', b'0'); +INSERT INTO `system_menu` (`id`, `name`, `permission`, `type`, `sort`, `parent_id`, `path`, `icon`, `component`, `component_name`, `status`, `visible`, `keep_alive`, `always_show`, `creator`, `create_time`, `updater`, `update_time`, `deleted`) VALUES (2651, '结算账户导出', 'erp:account:export', 3, 5, 2646, '', '', '', NULL, 0, b'1', b'1', b'1', '', '2024-02-10 00:15:07', '', '2024-02-10 00:15:07', b'0'); +INSERT INTO `system_menu` (`id`, `name`, `permission`, `type`, `sort`, `parent_id`, `path`, `icon`, `component`, `component_name`, `status`, `visible`, `keep_alive`, `always_show`, `creator`, `create_time`, `updater`, `update_time`, `deleted`) VALUES (2652, '销售出库', '', 2, 2, 2617, 'out', 'ep:sold-out', 'erp/sale/out/index', 'ErpSaleOut', 0, b'1', b'1', b'1', '', '2024-02-05 16:08:56', '1', '2024-02-10 22:02:07', b'0'); +INSERT INTO `system_menu` (`id`, `name`, `permission`, `type`, `sort`, `parent_id`, `path`, `icon`, `component`, `component_name`, `status`, `visible`, `keep_alive`, `always_show`, `creator`, `create_time`, `updater`, `update_time`, `deleted`) VALUES (2653, '销售出库查询', 'erp:sale-out:query', 3, 1, 2652, '', '', '', NULL, 0, b'1', b'1', b'1', '', '2024-02-05 16:08:56', '', '2024-02-07 11:12:49', b'0'); +INSERT INTO `system_menu` (`id`, `name`, `permission`, `type`, `sort`, `parent_id`, `path`, `icon`, `component`, `component_name`, `status`, `visible`, `keep_alive`, `always_show`, `creator`, `create_time`, `updater`, `update_time`, `deleted`) VALUES (2654, '销售出库创建', 'erp:sale-out:create', 3, 2, 2652, '', '', '', NULL, 0, b'1', b'1', b'1', '', '2024-02-05 16:08:56', '', '2024-02-07 11:12:52', b'0'); +INSERT INTO `system_menu` (`id`, `name`, `permission`, `type`, `sort`, `parent_id`, `path`, `icon`, `component`, `component_name`, `status`, `visible`, `keep_alive`, `always_show`, `creator`, `create_time`, `updater`, `update_time`, `deleted`) VALUES (2655, '销售出库更新', 'erp:sale-out:update', 3, 3, 2652, '', '', '', NULL, 0, b'1', b'1', b'1', '', '2024-02-05 16:08:56', '', '2024-02-07 11:12:55', b'0'); +INSERT INTO `system_menu` (`id`, `name`, `permission`, `type`, `sort`, `parent_id`, `path`, `icon`, `component`, `component_name`, `status`, `visible`, `keep_alive`, `always_show`, `creator`, `create_time`, `updater`, `update_time`, `deleted`) VALUES (2656, '销售出库删除', 'erp:sale-out:delete', 3, 4, 2652, '', '', '', NULL, 0, b'1', b'1', b'1', '', '2024-02-05 16:08:56', '', '2024-02-07 11:12:57', b'0'); +INSERT INTO `system_menu` (`id`, `name`, `permission`, `type`, `sort`, `parent_id`, `path`, `icon`, `component`, `component_name`, `status`, `visible`, `keep_alive`, `always_show`, `creator`, `create_time`, `updater`, `update_time`, `deleted`) VALUES (2657, '销售出库导出', 'erp:sale-out:export', 3, 5, 2652, '', '', '', NULL, 0, b'1', b'1', b'1', '', '2024-02-05 16:08:56', '', '2024-02-07 11:12:59', b'0'); +INSERT INTO `system_menu` (`id`, `name`, `permission`, `type`, `sort`, `parent_id`, `path`, `icon`, `component`, `component_name`, `status`, `visible`, `keep_alive`, `always_show`, `creator`, `create_time`, `updater`, `update_time`, `deleted`) VALUES (2658, '销售出库审批', 'erp:sale-out:update-status', 3, 6, 2652, '', '', '', NULL, 0, b'1', b'1', b'1', '', '2024-02-05 16:08:56', '', '2024-02-07 11:13:03', b'0'); +INSERT INTO `system_menu` (`id`, `name`, `permission`, `type`, `sort`, `parent_id`, `path`, `icon`, `component`, `component_name`, `status`, `visible`, `keep_alive`, `always_show`, `creator`, `create_time`, `updater`, `update_time`, `deleted`) VALUES (2659, '销售退货', '', 2, 3, 2617, 'return', 'fa-solid:bone', 'erp/sale/return/index', 'ErpSaleReturn', 0, b'1', b'1', b'1', '', '2024-02-05 16:08:56', '1', '2024-02-12 06:12:58', b'0'); +INSERT INTO `system_menu` (`id`, `name`, `permission`, `type`, `sort`, `parent_id`, `path`, `icon`, `component`, `component_name`, `status`, `visible`, `keep_alive`, `always_show`, `creator`, `create_time`, `updater`, `update_time`, `deleted`) VALUES (2660, '销售退货查询', 'erp:sale-return:query', 3, 1, 2659, '', '', '', NULL, 0, b'1', b'1', b'1', '', '2024-02-05 16:08:56', '', '2024-02-07 11:12:49', b'0'); +INSERT INTO `system_menu` (`id`, `name`, `permission`, `type`, `sort`, `parent_id`, `path`, `icon`, `component`, `component_name`, `status`, `visible`, `keep_alive`, `always_show`, `creator`, `create_time`, `updater`, `update_time`, `deleted`) VALUES (2661, '销售退货创建', 'erp:sale-return:create', 3, 2, 2659, '', '', '', NULL, 0, b'1', b'1', b'1', '', '2024-02-05 16:08:56', '', '2024-02-07 11:12:52', b'0'); +INSERT INTO `system_menu` (`id`, `name`, `permission`, `type`, `sort`, `parent_id`, `path`, `icon`, `component`, `component_name`, `status`, `visible`, `keep_alive`, `always_show`, `creator`, `create_time`, `updater`, `update_time`, `deleted`) VALUES (2662, '销售退货更新', 'erp:sale-return:update', 3, 3, 2659, '', '', '', NULL, 0, b'1', b'1', b'1', '', '2024-02-05 16:08:56', '', '2024-02-07 11:12:55', b'0'); +INSERT INTO `system_menu` (`id`, `name`, `permission`, `type`, `sort`, `parent_id`, `path`, `icon`, `component`, `component_name`, `status`, `visible`, `keep_alive`, `always_show`, `creator`, `create_time`, `updater`, `update_time`, `deleted`) VALUES (2663, '销售退货删除', 'erp:sale-return:delete', 3, 4, 2659, '', '', '', NULL, 0, b'1', b'1', b'1', '', '2024-02-05 16:08:56', '', '2024-02-07 11:12:57', b'0'); +INSERT INTO `system_menu` (`id`, `name`, `permission`, `type`, `sort`, `parent_id`, `path`, `icon`, `component`, `component_name`, `status`, `visible`, `keep_alive`, `always_show`, `creator`, `create_time`, `updater`, `update_time`, `deleted`) VALUES (2664, '销售退货导出', 'erp:sale-return:export', 3, 5, 2659, '', '', '', NULL, 0, b'1', b'1', b'1', '', '2024-02-05 16:08:56', '', '2024-02-07 11:12:59', b'0'); +INSERT INTO `system_menu` (`id`, `name`, `permission`, `type`, `sort`, `parent_id`, `path`, `icon`, `component`, `component_name`, `status`, `visible`, `keep_alive`, `always_show`, `creator`, `create_time`, `updater`, `update_time`, `deleted`) VALUES (2665, '销售退货审批', 'erp:sale-return:update-status', 3, 6, 2659, '', '', '', NULL, 0, b'1', b'1', b'1', '', '2024-02-05 16:08:56', '', '2024-02-07 11:13:03', b'0'); +INSERT INTO `system_menu` (`id`, `name`, `permission`, `type`, `sort`, `parent_id`, `path`, `icon`, `component`, `component_name`, `status`, `visible`, `keep_alive`, `always_show`, `creator`, `create_time`, `updater`, `update_time`, `deleted`) VALUES (2666, '采购订单', '', 2, 1, 2602, 'order', 'fa-solid:border-all', 'erp/purchase/order/index', 'ErpPurchaseOrder', 0, b'1', b'1', b'1', '', '2024-02-05 16:08:56', '1', '2024-02-12 08:51:49', b'0'); +INSERT INTO `system_menu` (`id`, `name`, `permission`, `type`, `sort`, `parent_id`, `path`, `icon`, `component`, `component_name`, `status`, `visible`, `keep_alive`, `always_show`, `creator`, `create_time`, `updater`, `update_time`, `deleted`) VALUES (2667, '采购订单查询', 'erp:purchase-order:query', 3, 1, 2666, '', '', '', NULL, 0, b'1', b'1', b'1', '', '2024-02-05 16:08:56', '', '2024-02-12 00:45:17', b'0'); +INSERT INTO `system_menu` (`id`, `name`, `permission`, `type`, `sort`, `parent_id`, `path`, `icon`, `component`, `component_name`, `status`, `visible`, `keep_alive`, `always_show`, `creator`, `create_time`, `updater`, `update_time`, `deleted`) VALUES (2668, '采购订单创建', 'erp:purchase-order:create', 3, 2, 2666, '', '', '', NULL, 0, b'1', b'1', b'1', '', '2024-02-05 16:08:56', '', '2024-02-12 00:44:54', b'0'); +INSERT INTO `system_menu` (`id`, `name`, `permission`, `type`, `sort`, `parent_id`, `path`, `icon`, `component`, `component_name`, `status`, `visible`, `keep_alive`, `always_show`, `creator`, `create_time`, `updater`, `update_time`, `deleted`) VALUES (2669, '采购订单更新', 'erp:purchase-order:update', 3, 3, 2666, '', '', '', NULL, 0, b'1', b'1', b'1', '', '2024-02-05 16:08:56', '', '2024-02-12 00:44:58', b'0'); +INSERT INTO `system_menu` (`id`, `name`, `permission`, `type`, `sort`, `parent_id`, `path`, `icon`, `component`, `component_name`, `status`, `visible`, `keep_alive`, `always_show`, `creator`, `create_time`, `updater`, `update_time`, `deleted`) VALUES (2670, '采购订单删除', 'erp:purchase-order:delete', 3, 4, 2666, '', '', '', NULL, 0, b'1', b'1', b'1', '', '2024-02-05 16:08:56', '', '2024-02-12 00:45:00', b'0'); +INSERT INTO `system_menu` (`id`, `name`, `permission`, `type`, `sort`, `parent_id`, `path`, `icon`, `component`, `component_name`, `status`, `visible`, `keep_alive`, `always_show`, `creator`, `create_time`, `updater`, `update_time`, `deleted`) VALUES (2671, '采购订单导出', 'erp:purchase-order:export', 3, 5, 2666, '', '', '', NULL, 0, b'1', b'1', b'1', '', '2024-02-05 16:08:56', '', '2024-02-12 00:45:05', b'0'); +INSERT INTO `system_menu` (`id`, `name`, `permission`, `type`, `sort`, `parent_id`, `path`, `icon`, `component`, `component_name`, `status`, `visible`, `keep_alive`, `always_show`, `creator`, `create_time`, `updater`, `update_time`, `deleted`) VALUES (2672, '采购订单审批', 'erp:purchase-order:update-status', 3, 6, 2666, '', '', '', NULL, 0, b'1', b'1', b'1', '', '2024-02-05 16:08:56', '', '2024-02-12 00:45:08', b'0'); +INSERT INTO `system_menu` (`id`, `name`, `permission`, `type`, `sort`, `parent_id`, `path`, `icon`, `component`, `component_name`, `status`, `visible`, `keep_alive`, `always_show`, `creator`, `create_time`, `updater`, `update_time`, `deleted`) VALUES (2673, '采购入库', '', 2, 2, 2602, 'in', 'fa-solid:gopuram', 'erp/purchase/in/index', 'ErpPurchaseIn', 0, b'1', b'1', b'1', '', '2024-02-05 16:08:56', '1', '2024-02-12 11:19:27', b'0'); +INSERT INTO `system_menu` (`id`, `name`, `permission`, `type`, `sort`, `parent_id`, `path`, `icon`, `component`, `component_name`, `status`, `visible`, `keep_alive`, `always_show`, `creator`, `create_time`, `updater`, `update_time`, `deleted`) VALUES (2674, '采购入库查询', 'erp:purchase-in:query', 3, 1, 2673, '', '', '', NULL, 0, b'1', b'1', b'1', '', '2024-02-05 16:08:56', '', '2024-02-12 00:45:17', b'0'); +INSERT INTO `system_menu` (`id`, `name`, `permission`, `type`, `sort`, `parent_id`, `path`, `icon`, `component`, `component_name`, `status`, `visible`, `keep_alive`, `always_show`, `creator`, `create_time`, `updater`, `update_time`, `deleted`) VALUES (2675, '采购入库创建', 'erp:purchase-in:create', 3, 2, 2673, '', '', '', NULL, 0, b'1', b'1', b'1', '', '2024-02-05 16:08:56', '', '2024-02-12 00:44:54', b'0'); +INSERT INTO `system_menu` (`id`, `name`, `permission`, `type`, `sort`, `parent_id`, `path`, `icon`, `component`, `component_name`, `status`, `visible`, `keep_alive`, `always_show`, `creator`, `create_time`, `updater`, `update_time`, `deleted`) VALUES (2676, '采购入库更新', 'erp:purchase-in:update', 3, 3, 2673, '', '', '', NULL, 0, b'1', b'1', b'1', '', '2024-02-05 16:08:56', '', '2024-02-12 00:44:58', b'0'); +INSERT INTO `system_menu` (`id`, `name`, `permission`, `type`, `sort`, `parent_id`, `path`, `icon`, `component`, `component_name`, `status`, `visible`, `keep_alive`, `always_show`, `creator`, `create_time`, `updater`, `update_time`, `deleted`) VALUES (2677, '采购入库删除', 'erp:purchase-in:delete', 3, 4, 2673, '', '', '', NULL, 0, b'1', b'1', b'1', '', '2024-02-05 16:08:56', '', '2024-02-12 00:45:00', b'0'); +INSERT INTO `system_menu` (`id`, `name`, `permission`, `type`, `sort`, `parent_id`, `path`, `icon`, `component`, `component_name`, `status`, `visible`, `keep_alive`, `always_show`, `creator`, `create_time`, `updater`, `update_time`, `deleted`) VALUES (2678, '采购入库导出', 'erp:purchase-in:export', 3, 5, 2673, '', '', '', NULL, 0, b'1', b'1', b'1', '', '2024-02-05 16:08:56', '', '2024-02-12 00:45:05', b'0'); +INSERT INTO `system_menu` (`id`, `name`, `permission`, `type`, `sort`, `parent_id`, `path`, `icon`, `component`, `component_name`, `status`, `visible`, `keep_alive`, `always_show`, `creator`, `create_time`, `updater`, `update_time`, `deleted`) VALUES (2679, '采购入库审批', 'erp:purchase-in:update-status', 3, 6, 2673, '', '', '', NULL, 0, b'1', b'1', b'1', '', '2024-02-05 16:08:56', '', '2024-02-12 00:45:08', b'0'); +INSERT INTO `system_menu` (`id`, `name`, `permission`, `type`, `sort`, `parent_id`, `path`, `icon`, `component`, `component_name`, `status`, `visible`, `keep_alive`, `always_show`, `creator`, `create_time`, `updater`, `update_time`, `deleted`) VALUES (2680, '采购退货', '', 2, 3, 2602, 'return', 'ep:minus', 'erp/purchase/return/index', 'ErpPurchaseReturn', 0, b'1', b'1', b'1', '', '2024-02-05 16:08:56', '1', '2024-02-12 20:51:02', b'0'); +INSERT INTO `system_menu` (`id`, `name`, `permission`, `type`, `sort`, `parent_id`, `path`, `icon`, `component`, `component_name`, `status`, `visible`, `keep_alive`, `always_show`, `creator`, `create_time`, `updater`, `update_time`, `deleted`) VALUES (2681, '采购退货查询', 'erp:purchase-return:query', 3, 1, 2680, '', '', '', NULL, 0, b'1', b'1', b'1', '', '2024-02-05 16:08:56', '', '2024-02-12 00:45:17', b'0'); +INSERT INTO `system_menu` (`id`, `name`, `permission`, `type`, `sort`, `parent_id`, `path`, `icon`, `component`, `component_name`, `status`, `visible`, `keep_alive`, `always_show`, `creator`, `create_time`, `updater`, `update_time`, `deleted`) VALUES (2682, '采购退货创建', 'erp:purchase-return:create', 3, 2, 2680, '', '', '', NULL, 0, b'1', b'1', b'1', '', '2024-02-05 16:08:56', '', '2024-02-12 00:44:54', b'0'); +INSERT INTO `system_menu` (`id`, `name`, `permission`, `type`, `sort`, `parent_id`, `path`, `icon`, `component`, `component_name`, `status`, `visible`, `keep_alive`, `always_show`, `creator`, `create_time`, `updater`, `update_time`, `deleted`) VALUES (2683, '采购退货更新', 'erp:purchase-return:update', 3, 3, 2680, '', '', '', NULL, 0, b'1', b'1', b'1', '', '2024-02-05 16:08:56', '', '2024-02-12 00:44:58', b'0'); +INSERT INTO `system_menu` (`id`, `name`, `permission`, `type`, `sort`, `parent_id`, `path`, `icon`, `component`, `component_name`, `status`, `visible`, `keep_alive`, `always_show`, `creator`, `create_time`, `updater`, `update_time`, `deleted`) VALUES (2684, '采购退货删除', 'erp:purchase-return:delete', 3, 4, 2680, '', '', '', NULL, 0, b'1', b'1', b'1', '', '2024-02-05 16:08:56', '', '2024-02-12 00:45:00', b'0'); +INSERT INTO `system_menu` (`id`, `name`, `permission`, `type`, `sort`, `parent_id`, `path`, `icon`, `component`, `component_name`, `status`, `visible`, `keep_alive`, `always_show`, `creator`, `create_time`, `updater`, `update_time`, `deleted`) VALUES (2685, '采购退货导出', 'erp:purchase-return:export', 3, 5, 2680, '', '', '', NULL, 0, b'1', b'1', b'1', '', '2024-02-05 16:08:56', '', '2024-02-12 00:45:05', b'0'); +INSERT INTO `system_menu` (`id`, `name`, `permission`, `type`, `sort`, `parent_id`, `path`, `icon`, `component`, `component_name`, `status`, `visible`, `keep_alive`, `always_show`, `creator`, `create_time`, `updater`, `update_time`, `deleted`) VALUES (2686, '采购退货审批', 'erp:purchase-return:update-status', 3, 6, 2680, '', '', '', NULL, 0, b'1', b'1', b'1', '', '2024-02-05 16:08:56', '', '2024-02-12 00:45:08', b'0'); +INSERT INTO `system_menu` (`id`, `name`, `permission`, `type`, `sort`, `parent_id`, `path`, `icon`, `component`, `component_name`, `status`, `visible`, `keep_alive`, `always_show`, `creator`, `create_time`, `updater`, `update_time`, `deleted`) VALUES (2687, '付款单', '', 2, 1, 2645, 'payment', 'ep:caret-right', 'erp/finance/payment/index', 'ErpFinancePayment', 0, b'1', b'1', b'1', '', '2024-02-05 16:08:56', '1', '2024-02-14 08:24:23', b'0'); +INSERT INTO `system_menu` (`id`, `name`, `permission`, `type`, `sort`, `parent_id`, `path`, `icon`, `component`, `component_name`, `status`, `visible`, `keep_alive`, `always_show`, `creator`, `create_time`, `updater`, `update_time`, `deleted`) VALUES (2688, '付款单查询', 'erp:finance-payment:query', 3, 1, 2687, '', '', '', NULL, 0, b'1', b'1', b'1', '', '2024-02-05 16:08:56', '', '2024-02-12 00:45:17', b'0'); +INSERT INTO `system_menu` (`id`, `name`, `permission`, `type`, `sort`, `parent_id`, `path`, `icon`, `component`, `component_name`, `status`, `visible`, `keep_alive`, `always_show`, `creator`, `create_time`, `updater`, `update_time`, `deleted`) VALUES (2689, '付款单创建', 'erp:finance-payment:create', 3, 2, 2687, '', '', '', NULL, 0, b'1', b'1', b'1', '', '2024-02-05 16:08:56', '', '2024-02-12 00:44:54', b'0'); +INSERT INTO `system_menu` (`id`, `name`, `permission`, `type`, `sort`, `parent_id`, `path`, `icon`, `component`, `component_name`, `status`, `visible`, `keep_alive`, `always_show`, `creator`, `create_time`, `updater`, `update_time`, `deleted`) VALUES (2690, '付款单更新', 'erp:finance-payment:update', 3, 3, 2687, '', '', '', NULL, 0, b'1', b'1', b'1', '', '2024-02-05 16:08:56', '', '2024-02-12 00:44:58', b'0'); +INSERT INTO `system_menu` (`id`, `name`, `permission`, `type`, `sort`, `parent_id`, `path`, `icon`, `component`, `component_name`, `status`, `visible`, `keep_alive`, `always_show`, `creator`, `create_time`, `updater`, `update_time`, `deleted`) VALUES (2691, '付款单删除', 'erp:finance-payment:delete', 3, 4, 2687, '', '', '', NULL, 0, b'1', b'1', b'1', '', '2024-02-05 16:08:56', '', '2024-02-12 00:45:00', b'0'); +INSERT INTO `system_menu` (`id`, `name`, `permission`, `type`, `sort`, `parent_id`, `path`, `icon`, `component`, `component_name`, `status`, `visible`, `keep_alive`, `always_show`, `creator`, `create_time`, `updater`, `update_time`, `deleted`) VALUES (2692, '付款单导出', 'erp:finance-payment:export', 3, 5, 2687, '', '', '', NULL, 0, b'1', b'1', b'1', '', '2024-02-05 16:08:56', '', '2024-02-12 00:45:05', b'0'); +INSERT INTO `system_menu` (`id`, `name`, `permission`, `type`, `sort`, `parent_id`, `path`, `icon`, `component`, `component_name`, `status`, `visible`, `keep_alive`, `always_show`, `creator`, `create_time`, `updater`, `update_time`, `deleted`) VALUES (2693, '付款单审批', 'erp:finance-payment:update-status', 3, 6, 2687, '', '', '', NULL, 0, b'1', b'1', b'1', '', '2024-02-05 16:08:56', '', '2024-02-12 00:45:08', b'0'); +INSERT INTO `system_menu` (`id`, `name`, `permission`, `type`, `sort`, `parent_id`, `path`, `icon`, `component`, `component_name`, `status`, `visible`, `keep_alive`, `always_show`, `creator`, `create_time`, `updater`, `update_time`, `deleted`) VALUES (2694, '收款单', '', 2, 2, 2645, 'receipt', 'ep:expand', 'erp/finance/receipt/index', 'ErpFinanceReceipt', 0, b'1', b'1', b'1', '', '2024-02-05 16:08:56', '1', '2024-02-15 19:35:45', b'0'); +INSERT INTO `system_menu` (`id`, `name`, `permission`, `type`, `sort`, `parent_id`, `path`, `icon`, `component`, `component_name`, `status`, `visible`, `keep_alive`, `always_show`, `creator`, `create_time`, `updater`, `update_time`, `deleted`) VALUES (2695, '收款单查询', 'erp:finance-receipt:query', 3, 1, 2694, '', '', '', NULL, 0, b'1', b'1', b'1', '', '2024-02-05 16:08:56', '', '2024-02-12 00:45:17', b'0'); +INSERT INTO `system_menu` (`id`, `name`, `permission`, `type`, `sort`, `parent_id`, `path`, `icon`, `component`, `component_name`, `status`, `visible`, `keep_alive`, `always_show`, `creator`, `create_time`, `updater`, `update_time`, `deleted`) VALUES (2696, '收款单创建', 'erp:finance-receipt:create', 3, 2, 2694, '', '', '', NULL, 0, b'1', b'1', b'1', '', '2024-02-05 16:08:56', '', '2024-02-12 00:44:54', b'0'); +INSERT INTO `system_menu` (`id`, `name`, `permission`, `type`, `sort`, `parent_id`, `path`, `icon`, `component`, `component_name`, `status`, `visible`, `keep_alive`, `always_show`, `creator`, `create_time`, `updater`, `update_time`, `deleted`) VALUES (2697, '收款单更新', 'erp:finance-receipt:update', 3, 3, 2694, '', '', '', NULL, 0, b'1', b'1', b'1', '', '2024-02-05 16:08:56', '', '2024-02-12 00:44:58', b'0'); +INSERT INTO `system_menu` (`id`, `name`, `permission`, `type`, `sort`, `parent_id`, `path`, `icon`, `component`, `component_name`, `status`, `visible`, `keep_alive`, `always_show`, `creator`, `create_time`, `updater`, `update_time`, `deleted`) VALUES (2698, '收款单删除', 'erp:finance-receipt:delete', 3, 4, 2694, '', '', '', NULL, 0, b'1', b'1', b'1', '', '2024-02-05 16:08:56', '', '2024-02-12 00:45:00', b'0'); +INSERT INTO `system_menu` (`id`, `name`, `permission`, `type`, `sort`, `parent_id`, `path`, `icon`, `component`, `component_name`, `status`, `visible`, `keep_alive`, `always_show`, `creator`, `create_time`, `updater`, `update_time`, `deleted`) VALUES (2699, '收款单导出', 'erp:finance-receipt:export', 3, 5, 2694, '', '', '', NULL, 0, b'1', b'1', b'1', '', '2024-02-05 16:08:56', '', '2024-02-12 00:45:05', b'0'); +INSERT INTO `system_menu` (`id`, `name`, `permission`, `type`, `sort`, `parent_id`, `path`, `icon`, `component`, `component_name`, `status`, `visible`, `keep_alive`, `always_show`, `creator`, `create_time`, `updater`, `update_time`, `deleted`) VALUES (2700, '收款单审批', 'erp:finance-receipt:update-status', 3, 6, 2694, '', '', '', NULL, 0, b'1', b'1', b'1', '', '2024-02-05 16:08:56', '', '2024-02-12 00:45:08', b'0'); +INSERT INTO `system_menu` (`id`, `name`, `permission`, `type`, `sort`, `parent_id`, `path`, `icon`, `component`, `component_name`, `status`, `visible`, `keep_alive`, `always_show`, `creator`, `create_time`, `updater`, `update_time`, `deleted`) VALUES (2701, '待办事项', '', 2, 0, 2397, 'backlog', 'fa-solid:tasks', 'crm/backlog/index', 'CrmBacklog', 0, b'1', b'1', b'1', '1', '2024-02-17 17:17:11', '1', '2024-02-17 17:17:11', b'0'); COMMIT; -- ---------------------------- @@ -2259,7 +2425,7 @@ CREATE TABLE `system_oauth2_access_token` ( PRIMARY KEY (`id`) USING BTREE, INDEX `idx_access_token`(`access_token` ASC) USING BTREE, INDEX `idx_refresh_token`(`refresh_token` ASC) USING BTREE -) ENGINE = InnoDB AUTO_INCREMENT = 4335 CHARACTER SET = utf8mb4 COLLATE = utf8mb4_unicode_ci COMMENT = 'OAuth2 访问令牌'; +) ENGINE = InnoDB AUTO_INCREMENT = 4781 CHARACTER SET = utf8mb4 COLLATE = utf8mb4_unicode_ci COMMENT = 'OAuth2 访问令牌'; -- ---------------------------- -- Records of system_oauth2_access_token @@ -2381,7 +2547,7 @@ CREATE TABLE `system_oauth2_refresh_token` ( `deleted` bit(1) NOT NULL DEFAULT b'0' COMMENT '是否删除', `tenant_id` bigint NOT NULL DEFAULT 0 COMMENT '租户编号', PRIMARY KEY (`id`) USING BTREE -) ENGINE = InnoDB AUTO_INCREMENT = 1309 CHARACTER SET = utf8mb4 COLLATE = utf8mb4_unicode_ci COMMENT = 'OAuth2 刷新令牌'; +) ENGINE = InnoDB AUTO_INCREMENT = 1346 CHARACTER SET = utf8mb4 COLLATE = utf8mb4_unicode_ci COMMENT = 'OAuth2 刷新令牌'; -- ---------------------------- -- Records of system_oauth2_refresh_token @@ -2421,7 +2587,7 @@ CREATE TABLE `system_operate_log` ( `deleted` bit(1) NOT NULL DEFAULT b'0' COMMENT '是否删除', `tenant_id` bigint NOT NULL DEFAULT 0 COMMENT '租户编号', PRIMARY KEY (`id`) USING BTREE -) ENGINE = InnoDB AUTO_INCREMENT = 9706 CHARACTER SET = utf8mb4 COLLATE = utf8mb4_unicode_ci COMMENT = '操作日志记录'; +) ENGINE = InnoDB AUTO_INCREMENT = 10187 CHARACTER SET = utf8mb4 COLLATE = utf8mb4_unicode_ci COMMENT = '操作日志记录'; -- ---------------------------- -- Records of system_operate_log @@ -2454,7 +2620,7 @@ CREATE TABLE `system_operate_log_v2` ( `deleted` bit(1) NOT NULL DEFAULT b'0' COMMENT '是否删除', `tenant_id` bigint NOT NULL DEFAULT 0 COMMENT '租户编号', PRIMARY KEY (`id`) USING BTREE -) ENGINE = InnoDB AUTO_INCREMENT = 8888 CHARACTER SET = utf8mb4 COLLATE = utf8mb4_unicode_ci COMMENT = '操作日志记录 V2 版本'; +) ENGINE = InnoDB AUTO_INCREMENT = 8892 CHARACTER SET = utf8mb4 COLLATE = utf8mb4_unicode_ci COMMENT = '操作日志记录 V2 版本'; -- ---------------------------- -- Records of system_operate_log_v2 @@ -4517,7 +4683,7 @@ CREATE TABLE `system_sms_log` ( `update_time` datetime NOT NULL DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP COMMENT '更新时间', `deleted` bit(1) NOT NULL DEFAULT b'0' COMMENT '是否删除', PRIMARY KEY (`id`) USING BTREE -) ENGINE = InnoDB AUTO_INCREMENT = 586 CHARACTER SET = utf8mb4 COLLATE = utf8mb4_unicode_ci COMMENT = '短信日志'; +) ENGINE = InnoDB AUTO_INCREMENT = 588 CHARACTER SET = utf8mb4 COLLATE = utf8mb4_unicode_ci COMMENT = '短信日志'; -- ---------------------------- -- Records of system_sms_log @@ -4826,7 +4992,7 @@ CREATE TABLE `system_users` ( -- Records of system_users -- ---------------------------- BEGIN; -INSERT INTO `system_users` (`id`, `username`, `password`, `nickname`, `remark`, `dept_id`, `post_ids`, `email`, `mobile`, `sex`, `avatar`, `status`, `login_ip`, `login_date`, `creator`, `create_time`, `updater`, `update_time`, `deleted`, `tenant_id`) VALUES (1, 'admin', '$2a$10$mRMIYLDtRHlf6.9ipiqH1.Z.bh/R9dO9d5iHiGYPigi6r5KOoR2Wm', '芋道源码', '管理员', 103, '[1]', 'aoteman@126.com', '18818260277', 2, 'http://127.0.0.1:48080/admin-api/infra/file/4/get/37e56010ecbee472cdd821ac4b608e151e62a74d9633f15d085aee026eedeb60.png', 0, '0:0:0:0:0:0:0:1', '2024-01-22 21:01:28', 'admin', '2021-01-05 17:03:47', NULL, '2024-01-22 21:01:28', b'0', 1); +INSERT INTO `system_users` (`id`, `username`, `password`, `nickname`, `remark`, `dept_id`, `post_ids`, `email`, `mobile`, `sex`, `avatar`, `status`, `login_ip`, `login_date`, `creator`, `create_time`, `updater`, `update_time`, `deleted`, `tenant_id`) VALUES (1, 'admin', '$2a$10$mRMIYLDtRHlf6.9ipiqH1.Z.bh/R9dO9d5iHiGYPigi6r5KOoR2Wm', '芋道源码', '管理员', 103, '[1]', 'aoteman@126.com', '18818260277', 2, 'http://127.0.0.1:48080/admin-api/infra/file/4/get/37e56010ecbee472cdd821ac4b608e151e62a74d9633f15d085aee026eedeb60.png', 0, '0:0:0:0:0:0:0:1', '2024-02-17 17:10:34', 'admin', '2021-01-05 17:03:47', NULL, '2024-02-17 17:10:34', b'0', 1); INSERT INTO `system_users` (`id`, `username`, `password`, `nickname`, `remark`, `dept_id`, `post_ids`, `email`, `mobile`, `sex`, `avatar`, `status`, `login_ip`, `login_date`, `creator`, `create_time`, `updater`, `update_time`, `deleted`, `tenant_id`) VALUES (100, 'yudao', '$2a$10$11U48RhyJ5pSBYWSn12AD./ld671.ycSzJHbyrtpeoMeYiw31eo8a', '芋道', '不要吓我', 104, '[1]', 'yudao@iocoder.cn', '15601691300', 1, '', 1, '127.0.0.1', '2022-07-09 23:03:33', '', '2021-01-07 09:07:17', NULL, '2022-07-09 23:03:33', b'0', 1); INSERT INTO `system_users` (`id`, `username`, `password`, `nickname`, `remark`, `dept_id`, `post_ids`, `email`, `mobile`, `sex`, `avatar`, `status`, `login_ip`, `login_date`, `creator`, `create_time`, `updater`, `update_time`, `deleted`, `tenant_id`) VALUES (103, 'yuanma', '$2a$10$YMpimV4T6BtDhIaA8jSW.u8UTGBeGhc/qwXP4oxoMr4mOw9.qttt6', '源码', NULL, 106, NULL, 'yuanma@iocoder.cn', '15601701300', 0, '', 0, '127.0.0.1', '2022-07-08 01:26:27', '', '2021-01-13 23:50:35', NULL, '2022-07-08 01:26:27', b'0', 1); INSERT INTO `system_users` (`id`, `username`, `password`, `nickname`, `remark`, `dept_id`, `post_ids`, `email`, `mobile`, `sex`, `avatar`, `status`, `login_ip`, `login_date`, `creator`, `create_time`, `updater`, `update_time`, `deleted`, `tenant_id`) VALUES (104, 'test', '$2a$10$GP8zvqHB//TekuzYZSBYAuBQJiNq1.fxQVDYJ.uBCOnWCtDVKE4H6', '测试号', NULL, 107, '[1,2]', '111@qq.com', '15601691200', 1, '', 0, '0:0:0:0:0:0:0:1', '2023-09-24 18:21:19', '', '2021-01-21 02:13:53', NULL, '2023-09-24 18:21:19', b'0', 1); diff --git a/yudao-dependencies/pom.xml b/yudao-dependencies/pom.xml index 9f641c1d0..0344bfda5 100644 --- a/yudao-dependencies/pom.xml +++ b/yudao-dependencies/pom.xml @@ -14,7 +14,7 @@ https://github.com/YunaiV/ruoyi-vue-pro - 2.0.0-snapshot + 2.0.1-snapshot 1.5.0 3.2.2 diff --git a/yudao-server/pom.xml b/yudao-server/pom.xml index 4ead0bba8..bc850b590 100644 --- a/yudao-server/pom.xml +++ b/yudao-server/pom.xml @@ -46,11 +46,11 @@ - - cn.iocoder.boot - yudao-module-bpm-biz - ${revision} - + + + + + @@ -95,11 +95,11 @@ - - cn.iocoder.boot - yudao-module-erp-biz - ${revision} - + + + + + From fb66b2768ef6bf76922ac8ac89261b1a67cf83d3 Mon Sep 17 00:00:00 2001 From: YunaiV Date: Sat, 17 Feb 2024 21:41:02 +0800 Subject: [PATCH 119/119] =?UTF-8?q?=E2=9C=A8=202.0.1=20=E7=89=88=E6=9C=AC?= =?UTF-8?q?=E5=8F=91=E5=B8=83=E5=87=86=E5=A4=87?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- pom.xml | 5 ++-- yudao-dependencies/pom.xml | 2 +- .../admin/definition/BpmModelController.java | 4 +-- .../BpmProcessInstanceCopyController.java | 4 +-- .../BpmProcessInstanceCopyCreateReqVO.java | 4 +-- .../listener/BpmServiceResultListener.java | 2 +- .../core/handler/MultiInstanceHandler.java | 5 ++-- .../candidate/BpmCandidateSourceInfo.java | 4 +-- .../service/definition/BpmModelService.java | 3 ++- .../definition/BpmModelServiceImpl.java | 4 +-- .../BpmProcessDefinitionServiceImpl.java | 4 +-- .../bpm/service/task/BpmTaskService.java | 2 +- .../bpm/service/task/BpmTaskServiceImpl.java | 4 +-- .../cc/BpmProcessInstanceCopyServiceImpl.java | 7 ++--- .../admin/bi/CrmBiRankController.java | 4 +-- .../admin/bi/vo/CrmBiRankReqVO.java | 4 +-- .../vo/business/CrmBusinessSaveReqVO.java | 2 +- .../admin/clue/vo/CrmClueSaveReqVO.java | 6 ++--- .../contract/vo/CrmContractSaveReqVO.java | 2 +- .../customer/vo/CrmCustomerImportReqVO.java | 3 ++- .../operatelog/CrmOperateLogController.java | 4 +-- .../operatelog/vo/CrmOperateLogPageReqVO.java | 3 ++- .../CrmReceivablePlanController.java | 6 ++--- .../customer/CrmCustomerAutoPutPoolJob.java | 3 ++- .../service/bi/CrmBiRankingServiceImpl.java | 2 +- .../service/business/CrmBusinessService.java | 2 +- .../business/CrmBusinessServiceImpl.java | 2 +- .../bo/CrmBusinessUpdateProductReqBO.java | 4 +-- .../crm/service/clue/CrmClueService.java | 2 +- .../crm/service/clue/CrmClueServiceImpl.java | 2 +- .../service/contact/CrmContactService.java | 2 +- .../contact/CrmContactServiceImpl.java | 2 +- .../service/contract/CrmContractService.java | 2 +- .../listener/CrmContractResultListener.java | 3 ++- .../service/customer/CrmCustomerService.java | 2 +- .../customer/CrmCustomerServiceImpl.java | 2 +- .../customer/bo/CrmCustomerCreateReqBO.java | 6 ++--- .../followup/CrmFollowUpRecordService.java | 2 +- .../CrmFollowUpRecordServiceImpl.java | 2 +- .../followup/bo/CrmFollowUpCreateReqBO.java | 4 +-- .../message/CrmBacklogServiceImpl.java | 3 ++- .../permission/CrmPermissionServiceImpl.java | 2 +- .../CrmReceivablePlanServiceImpl.java | 4 +-- .../receivable/CrmReceivableServiceImpl.java | 3 +-- .../admin/finance/ErpAccountController.java | 6 ++--- .../finance/ErpFinancePaymentController.java | 6 ++--- .../finance/ErpFinanceReceiptController.java | 6 ++--- .../vo/account/ErpAccountSaveReqVO.java | 5 ++-- .../vo/payment/ErpFinancePaymentRespVO.java | 2 +- .../payment/ErpFinancePaymentSaveReqVO.java | 6 ++--- .../vo/receipt/ErpFinanceReceiptRespVO.java | 2 +- .../receipt/ErpFinanceReceiptSaveReqVO.java | 6 ++--- .../product/ErpProductCategoryController.java | 6 ++--- .../admin/product/ErpProductController.java | 6 ++--- .../product/ErpProductUnitController.java | 6 ++--- .../category/ErpProductCategorySaveReqVO.java | 5 ++-- .../product/vo/product/ProductSaveReqVO.java | 4 +-- .../vo/unit/ErpProductUnitSaveReqVO.java | 5 ++-- .../purchase/ErpPurchaseInController.java | 6 ++--- .../purchase/ErpPurchaseOrderController.java | 6 ++--- .../purchase/ErpPurchaseReturnController.java | 6 ++--- .../admin/purchase/ErpSupplierController.java | 6 ++--- .../purchase/vo/in/ErpPurchaseInRespVO.java | 2 +- .../vo/in/ErpPurchaseInSaveReqVO.java | 2 +- .../vo/order/ErpPurchaseOrderRespVO.java | 2 +- .../vo/order/ErpPurchaseOrderSaveReqVO.java | 2 +- .../vo/returns/ErpPurchaseReturnRespVO.java | 2 +- .../returns/ErpPurchaseReturnSaveReqVO.java | 2 +- .../vo/supplier/ErpSupplierSaveReqVO.java | 6 ++--- .../admin/sale/ErpCustomerController.java | 6 ++--- .../admin/sale/ErpSaleOrderController.java | 6 ++--- .../admin/sale/ErpSaleOutController.java | 6 ++--- .../admin/sale/ErpSaleReturnController.java | 6 ++--- .../vo/customer/ErpCustomerSaveReqVO.java | 4 +-- .../sale/vo/order/ErpSaleOrderRespVO.java | 2 +- .../sale/vo/order/ErpSaleOrderSaveReqVO.java | 2 +- .../admin/sale/vo/out/ErpSaleOutRespVO.java | 2 +- .../sale/vo/out/ErpSaleOutSaveReqVO.java | 2 +- .../sale/vo/returns/ErpSaleReturnRespVO.java | 2 +- .../vo/returns/ErpSaleReturnSaveReqVO.java | 2 +- .../admin/stock/ErpStockCheckController.java | 6 ++--- .../admin/stock/ErpStockController.java | 6 ++--- .../admin/stock/ErpStockInController.java | 8 +++--- .../admin/stock/ErpStockMoveController.java | 6 ++--- .../admin/stock/ErpStockOutController.java | 6 ++--- .../admin/stock/ErpStockRecordController.java | 6 ++--- .../admin/stock/ErpWarehouseController.java | 6 ++--- .../stock/vo/check/ErpStockCheckRespVO.java | 2 +- .../vo/check/ErpStockCheckSaveReqVO.java | 6 ++--- .../stock/vo/in/ErpStockInSaveReqVO.java | 6 ++--- .../stock/vo/move/ErpStockMoveSaveReqVO.java | 8 +++--- .../stock/vo/out/ErpStockOutSaveReqVO.java | 6 ++--- .../vo/warehouse/ErpWarehouseSaveReqVO.java | 4 +-- .../erp/dal/redis/no/ErpNoRedisDAO.java | 2 +- .../web/config/ErpWebConfiguration.java | 4 +-- .../service/finance/ErpAccountService.java | 2 +- .../finance/ErpAccountServiceImpl.java | 5 ++-- .../finance/ErpFinancePaymentService.java | 2 +- .../finance/ErpFinancePaymentServiceImpl.java | 2 +- .../finance/ErpFinanceReceiptService.java | 2 +- .../finance/ErpFinanceReceiptServiceImpl.java | 2 +- .../product/ErpProductCategoryService.java | 2 +- .../ErpProductCategoryServiceImpl.java | 26 +++++++++---------- .../service/product/ErpProductService.java | 2 +- .../product/ErpProductServiceImpl.java | 13 +++++++--- .../product/ErpProductUnitService.java | 2 +- .../product/ErpProductUnitServiceImpl.java | 2 +- .../purchase/ErpPurchaseInService.java | 2 +- .../purchase/ErpPurchaseInServiceImpl.java | 2 +- .../purchase/ErpPurchaseOrderService.java | 2 +- .../purchase/ErpPurchaseOrderServiceImpl.java | 2 +- .../purchase/ErpPurchaseReturnService.java | 2 +- .../ErpPurchaseReturnServiceImpl.java | 2 +- .../service/purchase/ErpSupplierService.java | 2 +- .../purchase/ErpSupplierServiceImpl.java | 5 ++-- .../erp/service/sale/ErpCustomerService.java | 2 +- .../service/sale/ErpCustomerServiceImpl.java | 2 +- .../erp/service/sale/ErpSaleOrderService.java | 2 +- .../service/sale/ErpSaleOrderServiceImpl.java | 2 +- .../erp/service/sale/ErpSaleOutService.java | 2 +- .../service/sale/ErpSaleOutServiceImpl.java | 2 +- .../service/sale/ErpSaleReturnService.java | 2 +- .../sale/ErpSaleReturnServiceImpl.java | 2 +- .../service/stock/ErpStockCheckService.java | 2 +- .../stock/ErpStockCheckServiceImpl.java | 2 +- .../erp/service/stock/ErpStockInService.java | 2 +- .../service/stock/ErpStockInServiceImpl.java | 2 +- .../service/stock/ErpStockMoveService.java | 2 +- .../stock/ErpStockMoveServiceImpl.java | 2 +- .../erp/service/stock/ErpStockOutService.java | 2 +- .../service/stock/ErpStockOutServiceImpl.java | 2 +- .../service/stock/ErpStockRecordService.java | 3 ++- .../stock/ErpStockRecordServiceImpl.java | 2 +- .../service/stock/ErpStockServiceImpl.java | 2 +- .../service/stock/ErpWarehouseService.java | 2 +- .../stock/ErpWarehouseServiceImpl.java | 6 ++--- .../stock/bo/ErpStockRecordCreateReqBO.java | 2 +- .../controller/admin/file/FileController.java | 11 ++++---- .../admin/file/vo/file/FileCreateReqVO.java | 3 ++- .../infra/service/file/FileServiceImpl.java | 3 ++- .../ProductCommentServiceImplTest.java | 2 +- .../admin/notice/vo/NoticeSaveReqVO.java | 6 ++--- 142 files changed, 278 insertions(+), 256 deletions(-) diff --git a/pom.xml b/pom.xml index 93251fd1a..16382ecb4 100644 --- a/pom.xml +++ b/pom.xml @@ -15,13 +15,14 @@ yudao-module-system yudao-module-infra - + yudao-module-member + @@ -31,7 +32,7 @@ https://github.com/YunaiV/ruoyi-vue-pro - 2.0.0-jdk8-snapshot + 2.0.1-jdk8-snapshot 1.8 ${java.version} diff --git a/yudao-dependencies/pom.xml b/yudao-dependencies/pom.xml index b885dda31..509e45eb7 100644 --- a/yudao-dependencies/pom.xml +++ b/yudao-dependencies/pom.xml @@ -14,7 +14,7 @@ https://github.com/YunaiV/ruoyi-vue-pro - 2.0.0-jdk8-snapshot + 2.0.1-jdk8-snapshot 1.5.0 2.7.18 diff --git a/yudao-module-bpm/yudao-module-bpm-biz/src/main/java/cn/iocoder/yudao/module/bpm/controller/admin/definition/BpmModelController.java b/yudao-module-bpm/yudao-module-bpm-biz/src/main/java/cn/iocoder/yudao/module/bpm/controller/admin/definition/BpmModelController.java index 4e7195ccd..9915cef7e 100644 --- a/yudao-module-bpm/yudao-module-bpm-biz/src/main/java/cn/iocoder/yudao/module/bpm/controller/admin/definition/BpmModelController.java +++ b/yudao-module-bpm/yudao-module-bpm-biz/src/main/java/cn/iocoder/yudao/module/bpm/controller/admin/definition/BpmModelController.java @@ -9,12 +9,12 @@ import cn.iocoder.yudao.module.bpm.service.definition.BpmModelService; import io.swagger.v3.oas.annotations.Operation; import io.swagger.v3.oas.annotations.Parameter; import io.swagger.v3.oas.annotations.tags.Tag; -import jakarta.annotation.Resource; -import jakarta.validation.Valid; import org.springframework.security.access.prepost.PreAuthorize; import org.springframework.validation.annotation.Validated; import org.springframework.web.bind.annotation.*; +import javax.annotation.Resource; +import javax.validation.Valid; import java.io.IOException; import static cn.iocoder.yudao.framework.common.pojo.CommonResult.success; diff --git a/yudao-module-bpm/yudao-module-bpm-biz/src/main/java/cn/iocoder/yudao/module/bpm/controller/admin/task/BpmProcessInstanceCopyController.java b/yudao-module-bpm/yudao-module-bpm-biz/src/main/java/cn/iocoder/yudao/module/bpm/controller/admin/task/BpmProcessInstanceCopyController.java index e1ad107ab..ec7b67e27 100644 --- a/yudao-module-bpm/yudao-module-bpm-biz/src/main/java/cn/iocoder/yudao/module/bpm/controller/admin/task/BpmProcessInstanceCopyController.java +++ b/yudao-module-bpm/yudao-module-bpm-biz/src/main/java/cn/iocoder/yudao/module/bpm/controller/admin/task/BpmProcessInstanceCopyController.java @@ -15,12 +15,12 @@ import cn.iocoder.yudao.module.system.api.user.AdminUserApi; import cn.iocoder.yudao.module.system.api.user.dto.AdminUserRespDTO; import io.swagger.v3.oas.annotations.Operation; import io.swagger.v3.oas.annotations.tags.Tag; -import jakarta.annotation.Resource; -import jakarta.validation.Valid; import org.springframework.security.access.prepost.PreAuthorize; import org.springframework.validation.annotation.Validated; import org.springframework.web.bind.annotation.*; +import javax.annotation.Resource; +import javax.validation.Valid; import java.util.Map; import java.util.stream.Stream; diff --git a/yudao-module-bpm/yudao-module-bpm-biz/src/main/java/cn/iocoder/yudao/module/bpm/controller/admin/task/vo/instance/BpmProcessInstanceCopyCreateReqVO.java b/yudao-module-bpm/yudao-module-bpm-biz/src/main/java/cn/iocoder/yudao/module/bpm/controller/admin/task/vo/instance/BpmProcessInstanceCopyCreateReqVO.java index 3a1b1d45c..359fa0065 100644 --- a/yudao-module-bpm/yudao-module-bpm-biz/src/main/java/cn/iocoder/yudao/module/bpm/controller/admin/task/vo/instance/BpmProcessInstanceCopyCreateReqVO.java +++ b/yudao-module-bpm/yudao-module-bpm-biz/src/main/java/cn/iocoder/yudao/module/bpm/controller/admin/task/vo/instance/BpmProcessInstanceCopyCreateReqVO.java @@ -1,8 +1,8 @@ package cn.iocoder.yudao.module.bpm.controller.admin.task.vo.instance; import io.swagger.v3.oas.annotations.media.Schema; -import jakarta.validation.constraints.NotBlank; -import jakarta.validation.constraints.NotEmpty; +import javax.validation.constraints.NotBlank; +import javax.validation.constraints.NotEmpty; import lombok.Data; @Schema(description = "管理后台 - 流程实例抄送的创建 Request VO") diff --git a/yudao-module-bpm/yudao-module-bpm-biz/src/main/java/cn/iocoder/yudao/module/bpm/framework/bpm/listener/BpmServiceResultListener.java b/yudao-module-bpm/yudao-module-bpm-biz/src/main/java/cn/iocoder/yudao/module/bpm/framework/bpm/listener/BpmServiceResultListener.java index 34a045a23..49de046a2 100644 --- a/yudao-module-bpm/yudao-module-bpm-biz/src/main/java/cn/iocoder/yudao/module/bpm/framework/bpm/listener/BpmServiceResultListener.java +++ b/yudao-module-bpm/yudao-module-bpm-biz/src/main/java/cn/iocoder/yudao/module/bpm/framework/bpm/listener/BpmServiceResultListener.java @@ -5,10 +5,10 @@ import cn.iocoder.yudao.framework.common.util.object.BeanUtils; import cn.iocoder.yudao.module.bpm.api.listener.BpmResultListenerApi; import cn.iocoder.yudao.module.bpm.api.listener.dto.BpmResultListenerRespDTO; import cn.iocoder.yudao.module.bpm.framework.bpm.core.event.BpmProcessInstanceResultEvent; -import jakarta.annotation.Resource; import org.springframework.context.ApplicationListener; import org.springframework.stereotype.Component; +import javax.annotation.Resource; import java.util.List; // TODO @芋艿:后续改成支持 RPC diff --git a/yudao-module-bpm/yudao-module-bpm-biz/src/main/java/cn/iocoder/yudao/module/bpm/framework/flowable/core/handler/MultiInstanceHandler.java b/yudao-module-bpm/yudao-module-bpm-biz/src/main/java/cn/iocoder/yudao/module/bpm/framework/flowable/core/handler/MultiInstanceHandler.java index ee81a9cf4..87f3d9aa5 100644 --- a/yudao-module-bpm/yudao-module-bpm-biz/src/main/java/cn/iocoder/yudao/module/bpm/framework/flowable/core/handler/MultiInstanceHandler.java +++ b/yudao-module-bpm/yudao-module-bpm-biz/src/main/java/cn/iocoder/yudao/module/bpm/framework/flowable/core/handler/MultiInstanceHandler.java @@ -6,13 +6,13 @@ import cn.iocoder.yudao.framework.flowable.core.enums.BpmnModelConstants; import cn.iocoder.yudao.module.system.api.permission.PermissionApi; import cn.iocoder.yudao.module.system.api.user.AdminUserApi; import cn.iocoder.yudao.module.system.api.user.dto.AdminUserRespDTO; -import jakarta.annotation.Resource; import lombok.AllArgsConstructor; import org.flowable.bpmn.model.FlowElement; import org.flowable.bpmn.model.UserTask; import org.flowable.engine.delegate.DelegateExecution; import org.springframework.stereotype.Component; +import javax.annotation.Resource; import java.util.ArrayList; import java.util.LinkedHashSet; import java.util.List; @@ -45,7 +45,8 @@ public class MultiInstanceHandler { public Set getUserIds(DelegateExecution execution) { Set candidateUserIds = new LinkedHashSet<>(); FlowElement flowElement = execution.getCurrentFlowElement(); - if (ObjectUtil.isNotEmpty(flowElement) && flowElement instanceof UserTask userTask) { + if (ObjectUtil.isNotEmpty(flowElement) && flowElement instanceof UserTask) { + UserTask userTask = (UserTask) flowElement; String dataType = userTask.getAttributeValue(BpmnModelConstants.NAMESPACE, BpmnModelConstants.PROCESS_CUSTOM_DATA_TYPE); if ("USERS".equals(dataType) && CollUtil.isNotEmpty(userTask.getCandidateUsers())) { // 添加候选用户id diff --git a/yudao-module-bpm/yudao-module-bpm-biz/src/main/java/cn/iocoder/yudao/module/bpm/service/candidate/BpmCandidateSourceInfo.java b/yudao-module-bpm/yudao-module-bpm-biz/src/main/java/cn/iocoder/yudao/module/bpm/service/candidate/BpmCandidateSourceInfo.java index 0c5f099d6..ba5145f25 100644 --- a/yudao-module-bpm/yudao-module-bpm-biz/src/main/java/cn/iocoder/yudao/module/bpm/service/candidate/BpmCandidateSourceInfo.java +++ b/yudao-module-bpm/yudao-module-bpm-biz/src/main/java/cn/iocoder/yudao/module/bpm/service/candidate/BpmCandidateSourceInfo.java @@ -2,12 +2,12 @@ package cn.iocoder.yudao.module.bpm.service.candidate; import cn.iocoder.yudao.module.bpm.controller.admin.candidate.vo.BpmTaskCandidateRuleVO; import io.swagger.v3.oas.annotations.media.Schema; -import jakarta.validation.constraints.NotEmpty; -import jakarta.validation.constraints.NotNull; import lombok.AllArgsConstructor; import lombok.Data; import lombok.NoArgsConstructor; +import javax.validation.constraints.NotEmpty; +import javax.validation.constraints.NotNull; import java.util.HashSet; import java.util.Set; diff --git a/yudao-module-bpm/yudao-module-bpm-biz/src/main/java/cn/iocoder/yudao/module/bpm/service/definition/BpmModelService.java b/yudao-module-bpm/yudao-module-bpm-biz/src/main/java/cn/iocoder/yudao/module/bpm/service/definition/BpmModelService.java index bddd79081..d5cc5f071 100644 --- a/yudao-module-bpm/yudao-module-bpm-biz/src/main/java/cn/iocoder/yudao/module/bpm/service/definition/BpmModelService.java +++ b/yudao-module-bpm/yudao-module-bpm-biz/src/main/java/cn/iocoder/yudao/module/bpm/service/definition/BpmModelService.java @@ -2,9 +2,10 @@ package cn.iocoder.yudao.module.bpm.service.definition; import cn.iocoder.yudao.framework.common.pojo.PageResult; import cn.iocoder.yudao.module.bpm.controller.admin.definition.vo.model.*; -import jakarta.validation.Valid; import org.flowable.bpmn.model.BpmnModel; +import javax.validation.Valid; + /** * Flowable流程模型接口 * diff --git a/yudao-module-bpm/yudao-module-bpm-biz/src/main/java/cn/iocoder/yudao/module/bpm/service/definition/BpmModelServiceImpl.java b/yudao-module-bpm/yudao-module-bpm-biz/src/main/java/cn/iocoder/yudao/module/bpm/service/definition/BpmModelServiceImpl.java index 08f8acf6b..090a68f84 100644 --- a/yudao-module-bpm/yudao-module-bpm-biz/src/main/java/cn/iocoder/yudao/module/bpm/service/definition/BpmModelServiceImpl.java +++ b/yudao-module-bpm/yudao-module-bpm-biz/src/main/java/cn/iocoder/yudao/module/bpm/service/definition/BpmModelServiceImpl.java @@ -14,8 +14,6 @@ import cn.iocoder.yudao.module.bpm.dal.dataobject.definition.BpmFormDO; import cn.iocoder.yudao.module.bpm.enums.definition.BpmModelFormTypeEnum; import cn.iocoder.yudao.module.bpm.service.definition.dto.BpmModelMetaInfoRespDTO; import cn.iocoder.yudao.module.bpm.service.definition.dto.BpmProcessDefinitionCreateReqDTO; -import jakarta.annotation.Resource; -import jakarta.validation.Valid; import lombok.extern.slf4j.Slf4j; import org.flowable.bpmn.converter.BpmnXMLConverter; import org.flowable.bpmn.model.BpmnModel; @@ -31,6 +29,8 @@ import org.springframework.transaction.annotation.Transactional; import org.springframework.util.ObjectUtils; import org.springframework.validation.annotation.Validated; +import javax.annotation.Resource; +import javax.validation.Valid; import java.util.*; import static cn.iocoder.yudao.framework.common.exception.util.ServiceExceptionUtil.exception; diff --git a/yudao-module-bpm/yudao-module-bpm-biz/src/main/java/cn/iocoder/yudao/module/bpm/service/definition/BpmProcessDefinitionServiceImpl.java b/yudao-module-bpm/yudao-module-bpm-biz/src/main/java/cn/iocoder/yudao/module/bpm/service/definition/BpmProcessDefinitionServiceImpl.java index c9b3872cd..882f7f83a 100644 --- a/yudao-module-bpm/yudao-module-bpm-biz/src/main/java/cn/iocoder/yudao/module/bpm/service/definition/BpmProcessDefinitionServiceImpl.java +++ b/yudao-module-bpm/yudao-module-bpm-biz/src/main/java/cn/iocoder/yudao/module/bpm/service/definition/BpmProcessDefinitionServiceImpl.java @@ -17,8 +17,6 @@ import cn.iocoder.yudao.module.bpm.dal.dataobject.definition.BpmFormDO; import cn.iocoder.yudao.module.bpm.dal.dataobject.definition.BpmProcessDefinitionExtDO; import cn.iocoder.yudao.module.bpm.dal.mysql.definition.BpmProcessDefinitionExtMapper; import cn.iocoder.yudao.module.bpm.service.definition.dto.BpmProcessDefinitionCreateReqDTO; -import jakarta.annotation.Resource; -import jakarta.validation.Valid; import lombok.extern.slf4j.Slf4j; import org.flowable.bpmn.converter.BpmnXMLConverter; import org.flowable.bpmn.model.BpmnModel; @@ -31,6 +29,8 @@ import org.flowable.engine.repository.ProcessDefinitionQuery; import org.springframework.stereotype.Service; import org.springframework.validation.annotation.Validated; +import javax.annotation.Resource; +import javax.validation.Valid; import java.util.*; import static cn.iocoder.yudao.framework.common.exception.util.ServiceExceptionUtil.exception; diff --git a/yudao-module-bpm/yudao-module-bpm-biz/src/main/java/cn/iocoder/yudao/module/bpm/service/task/BpmTaskService.java b/yudao-module-bpm/yudao-module-bpm-biz/src/main/java/cn/iocoder/yudao/module/bpm/service/task/BpmTaskService.java index 97018451d..50b7f8e2f 100644 --- a/yudao-module-bpm/yudao-module-bpm-biz/src/main/java/cn/iocoder/yudao/module/bpm/service/task/BpmTaskService.java +++ b/yudao-module-bpm/yudao-module-bpm-biz/src/main/java/cn/iocoder/yudao/module/bpm/service/task/BpmTaskService.java @@ -4,9 +4,9 @@ import cn.iocoder.yudao.framework.common.pojo.PageResult; import cn.iocoder.yudao.framework.common.util.collection.CollectionUtils; import cn.iocoder.yudao.module.bpm.controller.admin.task.vo.task.*; import cn.iocoder.yudao.module.bpm.dal.dataobject.task.BpmTaskExtDO; -import jakarta.validation.Valid; import org.flowable.task.api.Task; +import javax.validation.Valid; import java.util.Collection; import java.util.List; import java.util.Map; diff --git a/yudao-module-bpm/yudao-module-bpm-biz/src/main/java/cn/iocoder/yudao/module/bpm/service/task/BpmTaskServiceImpl.java b/yudao-module-bpm/yudao-module-bpm-biz/src/main/java/cn/iocoder/yudao/module/bpm/service/task/BpmTaskServiceImpl.java index 6e9929d37..a3b01ba72 100644 --- a/yudao-module-bpm/yudao-module-bpm-biz/src/main/java/cn/iocoder/yudao/module/bpm/service/task/BpmTaskServiceImpl.java +++ b/yudao-module-bpm/yudao-module-bpm-biz/src/main/java/cn/iocoder/yudao/module/bpm/service/task/BpmTaskServiceImpl.java @@ -25,8 +25,6 @@ import cn.iocoder.yudao.module.system.api.dept.DeptApi; import cn.iocoder.yudao.module.system.api.dept.dto.DeptRespDTO; import cn.iocoder.yudao.module.system.api.user.AdminUserApi; import cn.iocoder.yudao.module.system.api.user.dto.AdminUserRespDTO; -import jakarta.annotation.Resource; -import jakarta.validation.Valid; import lombok.extern.slf4j.Slf4j; import org.flowable.bpmn.model.BpmnModel; import org.flowable.bpmn.model.FlowElement; @@ -51,6 +49,8 @@ import org.springframework.transaction.support.TransactionSynchronization; import org.springframework.transaction.support.TransactionSynchronizationManager; import org.springframework.util.Assert; +import javax.annotation.Resource; +import javax.validation.Valid; import java.time.LocalDateTime; import java.util.*; import java.util.stream.Stream; diff --git a/yudao-module-bpm/yudao-module-bpm-biz/src/main/java/cn/iocoder/yudao/module/bpm/service/task/cc/BpmProcessInstanceCopyServiceImpl.java b/yudao-module-bpm/yudao-module-bpm-biz/src/main/java/cn/iocoder/yudao/module/bpm/service/task/cc/BpmProcessInstanceCopyServiceImpl.java index 50d042cdc..d53319633 100644 --- a/yudao-module-bpm/yudao-module-bpm-biz/src/main/java/cn/iocoder/yudao/module/bpm/service/task/cc/BpmProcessInstanceCopyServiceImpl.java +++ b/yudao-module-bpm/yudao-module-bpm-biz/src/main/java/cn/iocoder/yudao/module/bpm/service/task/cc/BpmProcessInstanceCopyServiceImpl.java @@ -15,7 +15,6 @@ import cn.iocoder.yudao.module.bpm.service.candidate.BpmCandidateSourceInfoProce import cn.iocoder.yudao.module.bpm.service.task.BpmProcessInstanceService; import cn.iocoder.yudao.module.bpm.service.task.BpmTaskService; import cn.iocoder.yudao.module.bpm.service.task.cc.dto.BpmDelegateExecutionDTO; -import jakarta.annotation.Resource; import lombok.extern.slf4j.Slf4j; import org.flowable.engine.RuntimeService; import org.flowable.engine.delegate.DelegateExecution; @@ -25,6 +24,7 @@ import org.springframework.context.annotation.Lazy; import org.springframework.stereotype.Service; import org.springframework.validation.annotation.Validated; +import javax.annotation.Resource; import java.time.LocalDateTime; import java.util.ArrayList; import java.util.List; @@ -93,7 +93,7 @@ public class BpmProcessInstanceCopyServiceImpl implements BpmProcessInstanceCopy } copyDO.setStartUserId(Long.parseLong(processInstance.getStartUserId())); copyDO.setProcessInstanceName(processInstance.getName()); - copyDO.setCategory(processInstance.getProcessDefinitionCategory()); + copyDO.setCategory(null); // TODO 芋艿:貌似新版本,没 processInstance.getProcessDefinitionCategory() 字段? copyDO.setReason(sourceInfo.getReason()); copyDO.setCreator(sourceInfo.getCreator()); copyDO.setCreateTime(LocalDateTime.now()); @@ -126,7 +126,8 @@ public class BpmProcessInstanceCopyServiceImpl implements BpmProcessInstanceCopy BpmProcessInstanceCopyDO copy = new BpmProcessInstanceCopyDO() .setTaskId(reqVO.getTaskId()).setTaskName(task.getName()) .setProcessInstanceId(processInstanceId).setStartUserId(Long.valueOf(processInstance.getStartUserId())) - .setProcessInstanceName(processInstance.getName()).setCategory(processInstance.getProcessDefinitionCategory()) + .setProcessInstanceName(processInstance.getName()) + .setCategory(null) // TODO 芋艿:貌似新版本,没 processInstance.getProcessDefinitionCategory() 字段? .setReason(reqVO.getReason()); processInstanceCopyMapper.insert(copy); } diff --git a/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/controller/admin/bi/CrmBiRankController.java b/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/controller/admin/bi/CrmBiRankController.java index 21463aed0..ee7c506f0 100644 --- a/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/controller/admin/bi/CrmBiRankController.java +++ b/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/controller/admin/bi/CrmBiRankController.java @@ -6,14 +6,14 @@ import cn.iocoder.yudao.module.crm.controller.admin.bi.vo.CrmBiRankReqVO; import cn.iocoder.yudao.module.crm.service.bi.CrmBiRankingService; import io.swagger.v3.oas.annotations.Operation; import io.swagger.v3.oas.annotations.tags.Tag; -import jakarta.annotation.Resource; -import jakarta.validation.Valid; import org.springframework.security.access.prepost.PreAuthorize; import org.springframework.validation.annotation.Validated; import org.springframework.web.bind.annotation.GetMapping; import org.springframework.web.bind.annotation.RequestMapping; import org.springframework.web.bind.annotation.RestController; +import javax.annotation.Resource; +import javax.validation.Valid; import java.util.List; import static cn.iocoder.yudao.framework.common.pojo.CommonResult.success; diff --git a/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/controller/admin/bi/vo/CrmBiRankReqVO.java b/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/controller/admin/bi/vo/CrmBiRankReqVO.java index 6d36f6d6f..3f3fdc5fb 100644 --- a/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/controller/admin/bi/vo/CrmBiRankReqVO.java +++ b/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/controller/admin/bi/vo/CrmBiRankReqVO.java @@ -1,11 +1,11 @@ package cn.iocoder.yudao.module.crm.controller.admin.bi.vo; import io.swagger.v3.oas.annotations.media.Schema; -import jakarta.validation.constraints.NotEmpty; -import jakarta.validation.constraints.NotNull; import lombok.Data; import org.springframework.format.annotation.DateTimeFormat; +import javax.validation.constraints.NotEmpty; +import javax.validation.constraints.NotNull; import java.time.LocalDateTime; import java.util.List; diff --git a/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/controller/admin/business/vo/business/CrmBusinessSaveReqVO.java b/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/controller/admin/business/vo/business/CrmBusinessSaveReqVO.java index 0be6264eb..02fb2c870 100644 --- a/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/controller/admin/business/vo/business/CrmBusinessSaveReqVO.java +++ b/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/controller/admin/business/vo/business/CrmBusinessSaveReqVO.java @@ -5,12 +5,12 @@ import cn.iocoder.yudao.module.crm.enums.business.CrmBizEndStatus; import cn.iocoder.yudao.module.crm.framework.operatelog.core.CrmCustomerParseFunction; import com.mzt.logapi.starter.annotation.DiffLogField; import io.swagger.v3.oas.annotations.media.Schema; -import jakarta.validation.constraints.NotNull; import lombok.AllArgsConstructor; import lombok.Data; import lombok.NoArgsConstructor; import org.springframework.format.annotation.DateTimeFormat; +import javax.validation.constraints.NotNull; import java.math.BigDecimal; import java.time.LocalDateTime; import java.util.List; diff --git a/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/controller/admin/clue/vo/CrmClueSaveReqVO.java b/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/controller/admin/clue/vo/CrmClueSaveReqVO.java index 4ca004a59..25666083f 100644 --- a/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/controller/admin/clue/vo/CrmClueSaveReqVO.java +++ b/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/controller/admin/clue/vo/CrmClueSaveReqVO.java @@ -10,9 +10,9 @@ import cn.iocoder.yudao.module.crm.framework.operatelog.core.CrmCustomerLevelPar import cn.iocoder.yudao.module.crm.framework.operatelog.core.CrmCustomerSourceParseFunction; import com.mzt.logapi.starter.annotation.DiffLogField; import io.swagger.v3.oas.annotations.media.Schema; -import jakarta.validation.constraints.Email; -import jakarta.validation.constraints.NotEmpty; -import jakarta.validation.constraints.Size; +import javax.validation.constraints.Email; +import javax.validation.constraints.NotEmpty; +import javax.validation.constraints.Size; import lombok.Data; import org.springframework.format.annotation.DateTimeFormat; diff --git a/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/controller/admin/contract/vo/CrmContractSaveReqVO.java b/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/controller/admin/contract/vo/CrmContractSaveReqVO.java index 20b20580e..008beb0a1 100644 --- a/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/controller/admin/contract/vo/CrmContractSaveReqVO.java +++ b/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/controller/admin/contract/vo/CrmContractSaveReqVO.java @@ -6,12 +6,12 @@ import cn.iocoder.yudao.module.crm.framework.operatelog.core.CrmCustomerParseFun import cn.iocoder.yudao.module.crm.framework.operatelog.core.SysAdminUserParseFunction; import com.mzt.logapi.starter.annotation.DiffLogField; import io.swagger.v3.oas.annotations.media.Schema; -import jakarta.validation.constraints.NotNull; import lombok.AllArgsConstructor; import lombok.Data; import lombok.NoArgsConstructor; import org.springframework.format.annotation.DateTimeFormat; +import javax.validation.constraints.NotNull; import java.time.LocalDateTime; import java.util.List; diff --git a/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/controller/admin/customer/vo/CrmCustomerImportReqVO.java b/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/controller/admin/customer/vo/CrmCustomerImportReqVO.java index a396dc50b..85e8d2df4 100644 --- a/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/controller/admin/customer/vo/CrmCustomerImportReqVO.java +++ b/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/controller/admin/customer/vo/CrmCustomerImportReqVO.java @@ -1,11 +1,12 @@ package cn.iocoder.yudao.module.crm.controller.admin.customer.vo; import io.swagger.v3.oas.annotations.media.Schema; -import jakarta.validation.constraints.NotNull; import lombok.Builder; import lombok.Data; import org.springframework.web.multipart.MultipartFile; +import javax.validation.constraints.NotNull; + @Schema(description = "管理后台 - 客户导入 Request VO") @Data @Builder diff --git a/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/controller/admin/operatelog/CrmOperateLogController.java b/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/controller/admin/operatelog/CrmOperateLogController.java index 982ad3c0b..c541c1c0e 100644 --- a/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/controller/admin/operatelog/CrmOperateLogController.java +++ b/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/controller/admin/operatelog/CrmOperateLogController.java @@ -11,14 +11,14 @@ import cn.iocoder.yudao.module.system.api.logger.OperateLogApi; import cn.iocoder.yudao.module.system.api.logger.dto.OperateLogV2PageReqDTO; import io.swagger.v3.oas.annotations.Operation; import io.swagger.v3.oas.annotations.tags.Tag; -import jakarta.annotation.Resource; -import jakarta.validation.Valid; import org.springframework.security.access.prepost.PreAuthorize; import org.springframework.validation.annotation.Validated; import org.springframework.web.bind.annotation.GetMapping; import org.springframework.web.bind.annotation.RequestMapping; import org.springframework.web.bind.annotation.RestController; +import javax.annotation.Resource; +import javax.validation.Valid; import java.util.HashMap; import java.util.Map; diff --git a/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/controller/admin/operatelog/vo/CrmOperateLogPageReqVO.java b/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/controller/admin/operatelog/vo/CrmOperateLogPageReqVO.java index f49ccb38b..7bed826ae 100644 --- a/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/controller/admin/operatelog/vo/CrmOperateLogPageReqVO.java +++ b/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/controller/admin/operatelog/vo/CrmOperateLogPageReqVO.java @@ -4,11 +4,12 @@ import cn.iocoder.yudao.framework.common.pojo.PageParam; import cn.iocoder.yudao.framework.common.validation.InEnum; import cn.iocoder.yudao.module.crm.enums.common.CrmBizTypeEnum; import io.swagger.v3.oas.annotations.media.Schema; -import jakarta.validation.constraints.NotNull; import lombok.Data; import lombok.EqualsAndHashCode; import lombok.ToString; +import javax.validation.constraints.NotNull; + @Schema(description = "管理后台 - CRM 操作日志 Request VO") @Data @EqualsAndHashCode(callSuper = true) diff --git a/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/controller/admin/receivable/CrmReceivablePlanController.java b/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/controller/admin/receivable/CrmReceivablePlanController.java index 252d714f4..d26454b92 100644 --- a/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/controller/admin/receivable/CrmReceivablePlanController.java +++ b/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/controller/admin/receivable/CrmReceivablePlanController.java @@ -25,14 +25,14 @@ import cn.iocoder.yudao.module.system.api.user.dto.AdminUserRespDTO; import io.swagger.v3.oas.annotations.Operation; import io.swagger.v3.oas.annotations.Parameter; import io.swagger.v3.oas.annotations.tags.Tag; -import jakarta.annotation.Resource; -import jakarta.servlet.http.HttpServletResponse; -import jakarta.validation.Valid; import org.springframework.context.annotation.Lazy; import org.springframework.security.access.prepost.PreAuthorize; import org.springframework.validation.annotation.Validated; import org.springframework.web.bind.annotation.*; +import javax.annotation.Resource; +import javax.servlet.http.HttpServletResponse; +import javax.validation.Valid; import java.io.IOException; import java.util.List; import java.util.Map; diff --git a/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/job/customer/CrmCustomerAutoPutPoolJob.java b/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/job/customer/CrmCustomerAutoPutPoolJob.java index 6f5817015..06f8d745b 100644 --- a/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/job/customer/CrmCustomerAutoPutPoolJob.java +++ b/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/job/customer/CrmCustomerAutoPutPoolJob.java @@ -3,9 +3,10 @@ package cn.iocoder.yudao.module.crm.job.customer; import cn.iocoder.yudao.framework.quartz.core.handler.JobHandler; import cn.iocoder.yudao.framework.tenant.core.job.TenantJob; import cn.iocoder.yudao.module.crm.service.customer.CrmCustomerService; -import jakarta.annotation.Resource; import org.springframework.stereotype.Component; +import javax.annotation.Resource; + /** * 客户自动掉入公海 Job * diff --git a/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/service/bi/CrmBiRankingServiceImpl.java b/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/service/bi/CrmBiRankingServiceImpl.java index 60e1b4ecb..a365c6028 100644 --- a/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/service/bi/CrmBiRankingServiceImpl.java +++ b/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/service/bi/CrmBiRankingServiceImpl.java @@ -9,10 +9,10 @@ import cn.iocoder.yudao.module.system.api.dept.DeptApi; import cn.iocoder.yudao.module.system.api.dept.dto.DeptRespDTO; import cn.iocoder.yudao.module.system.api.user.AdminUserApi; import cn.iocoder.yudao.module.system.api.user.dto.AdminUserRespDTO; -import jakarta.annotation.Resource; import org.springframework.stereotype.Service; import org.springframework.validation.annotation.Validated; +import javax.annotation.Resource; import java.util.Collections; import java.util.Comparator; import java.util.List; diff --git a/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/service/business/CrmBusinessService.java b/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/service/business/CrmBusinessService.java index 683070d02..b01022670 100644 --- a/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/service/business/CrmBusinessService.java +++ b/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/service/business/CrmBusinessService.java @@ -9,8 +9,8 @@ import cn.iocoder.yudao.module.crm.dal.dataobject.contact.CrmContactDO; import cn.iocoder.yudao.module.crm.dal.dataobject.customer.CrmCustomerDO; import cn.iocoder.yudao.module.crm.service.business.bo.CrmBusinessUpdateProductReqBO; import cn.iocoder.yudao.module.crm.service.followup.bo.CrmUpdateFollowUpReqBO; -import jakarta.validation.Valid; +import javax.validation.Valid; import java.util.Collection; import java.util.List; diff --git a/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/service/business/CrmBusinessServiceImpl.java b/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/service/business/CrmBusinessServiceImpl.java index 535578fd2..1c651b9a1 100644 --- a/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/service/business/CrmBusinessServiceImpl.java +++ b/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/service/business/CrmBusinessServiceImpl.java @@ -30,12 +30,12 @@ import cn.iocoder.yudao.module.crm.service.product.CrmProductService; import com.mzt.logapi.context.LogRecordContext; import com.mzt.logapi.service.impl.DiffParseFunction; import com.mzt.logapi.starter.annotation.LogRecord; -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; +import javax.annotation.Resource; import java.util.Collection; import java.util.List; import java.util.Map; diff --git a/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/service/business/bo/CrmBusinessUpdateProductReqBO.java b/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/service/business/bo/CrmBusinessUpdateProductReqBO.java index 34b2fa381..a9f0f8bc7 100644 --- a/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/service/business/bo/CrmBusinessUpdateProductReqBO.java +++ b/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/service/business/bo/CrmBusinessUpdateProductReqBO.java @@ -1,12 +1,12 @@ package cn.iocoder.yudao.module.crm.service.business.bo; import io.swagger.v3.oas.annotations.media.Schema; -import jakarta.validation.constraints.NotEmpty; -import jakarta.validation.constraints.NotNull; import lombok.AllArgsConstructor; import lombok.Data; import lombok.NoArgsConstructor; +import javax.validation.constraints.NotEmpty; +import javax.validation.constraints.NotNull; import java.util.List; /** diff --git a/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/service/clue/CrmClueService.java b/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/service/clue/CrmClueService.java index 1472bf02f..239c8b7df 100644 --- a/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/service/clue/CrmClueService.java +++ b/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/service/clue/CrmClueService.java @@ -7,8 +7,8 @@ import cn.iocoder.yudao.module.crm.controller.admin.clue.vo.CrmClueTransferReqVO import cn.iocoder.yudao.module.crm.controller.admin.clue.vo.CrmClueTranslateReqVO; import cn.iocoder.yudao.module.crm.dal.dataobject.clue.CrmClueDO; import cn.iocoder.yudao.module.crm.service.followup.bo.CrmUpdateFollowUpReqBO; -import jakarta.validation.Valid; +import javax.validation.Valid; import java.util.Collection; import java.util.List; diff --git a/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/service/clue/CrmClueServiceImpl.java b/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/service/clue/CrmClueServiceImpl.java index dfb044f50..dfbf8f6a1 100644 --- a/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/service/clue/CrmClueServiceImpl.java +++ b/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/service/clue/CrmClueServiceImpl.java @@ -30,11 +30,11 @@ import cn.iocoder.yudao.module.system.api.user.AdminUserApi; import com.mzt.logapi.context.LogRecordContext; import com.mzt.logapi.service.impl.DiffParseFunction; import com.mzt.logapi.starter.annotation.LogRecord; -import jakarta.annotation.Resource; import org.springframework.stereotype.Service; import org.springframework.transaction.annotation.Transactional; import org.springframework.validation.annotation.Validated; +import javax.annotation.Resource; import java.util.*; import static cn.iocoder.yudao.framework.common.exception.util.ServiceExceptionUtil.exception; diff --git a/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/service/contact/CrmContactService.java b/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/service/contact/CrmContactService.java index d7688b8fb..693bba4eb 100644 --- a/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/service/contact/CrmContactService.java +++ b/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/service/contact/CrmContactService.java @@ -7,8 +7,8 @@ import cn.iocoder.yudao.module.crm.controller.admin.contact.vo.CrmContactTransfe import cn.iocoder.yudao.module.crm.dal.dataobject.contact.CrmContactDO; import cn.iocoder.yudao.module.crm.dal.dataobject.customer.CrmCustomerDO; import cn.iocoder.yudao.module.crm.service.followup.bo.CrmUpdateFollowUpReqBO; -import jakarta.validation.Valid; +import javax.validation.Valid; import java.util.Collection; import java.util.List; diff --git a/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/service/contact/CrmContactServiceImpl.java b/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/service/contact/CrmContactServiceImpl.java index 08ce78b81..e3d9e9bc1 100644 --- a/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/service/contact/CrmContactServiceImpl.java +++ b/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/service/contact/CrmContactServiceImpl.java @@ -24,12 +24,12 @@ import cn.iocoder.yudao.module.system.api.user.AdminUserApi; import com.mzt.logapi.context.LogRecordContext; import com.mzt.logapi.service.impl.DiffParseFunction; import com.mzt.logapi.starter.annotation.LogRecord; -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; +import javax.annotation.Resource; import java.util.Collection; import java.util.List; diff --git a/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/service/contract/CrmContractService.java b/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/service/contract/CrmContractService.java index 0bd527ae0..0d17550a8 100644 --- a/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/service/contract/CrmContractService.java +++ b/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/service/contract/CrmContractService.java @@ -9,8 +9,8 @@ import cn.iocoder.yudao.module.crm.dal.dataobject.contract.CrmContractDO; import cn.iocoder.yudao.module.crm.dal.dataobject.contract.CrmContractProductDO; import cn.iocoder.yudao.module.crm.dal.dataobject.customer.CrmCustomerDO; import cn.iocoder.yudao.module.crm.service.followup.bo.CrmUpdateFollowUpReqBO; -import jakarta.validation.Valid; +import javax.validation.Valid; import java.util.Collection; import java.util.List; diff --git a/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/service/contract/listener/CrmContractResultListener.java b/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/service/contract/listener/CrmContractResultListener.java index c5ee407bd..8f374ee7f 100644 --- a/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/service/contract/listener/CrmContractResultListener.java +++ b/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/service/contract/listener/CrmContractResultListener.java @@ -4,9 +4,10 @@ import cn.iocoder.yudao.module.bpm.api.listener.BpmResultListenerApi; import cn.iocoder.yudao.module.bpm.api.listener.dto.BpmResultListenerRespDTO; import cn.iocoder.yudao.module.crm.service.contract.CrmContractService; import cn.iocoder.yudao.module.crm.service.contract.CrmContractServiceImpl; -import jakarta.annotation.Resource; import org.springframework.stereotype.Component; +import javax.annotation.Resource; + // TODO @芋艿:后续改成支持 RPC /** * 合同审批的结果的监听器实现类 diff --git a/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/service/customer/CrmCustomerService.java b/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/service/customer/CrmCustomerService.java index 911260f76..a7740e0a9 100644 --- a/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/service/customer/CrmCustomerService.java +++ b/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/service/customer/CrmCustomerService.java @@ -6,8 +6,8 @@ import cn.iocoder.yudao.module.crm.dal.dataobject.customer.CrmCustomerDO; import cn.iocoder.yudao.module.crm.dal.dataobject.customer.CrmCustomerPoolConfigDO; import cn.iocoder.yudao.module.crm.service.customer.bo.CrmCustomerCreateReqBO; import cn.iocoder.yudao.module.crm.service.followup.bo.CrmUpdateFollowUpReqBO; -import jakarta.validation.Valid; +import javax.validation.Valid; import java.util.Collection; import java.util.List; diff --git a/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/service/customer/CrmCustomerServiceImpl.java b/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/service/customer/CrmCustomerServiceImpl.java index bc02a6b71..ef014ff16 100644 --- a/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/service/customer/CrmCustomerServiceImpl.java +++ b/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/service/customer/CrmCustomerServiceImpl.java @@ -32,13 +32,13 @@ import cn.iocoder.yudao.module.system.api.user.dto.AdminUserRespDTO; import com.mzt.logapi.context.LogRecordContext; import com.mzt.logapi.service.impl.DiffParseFunction; import com.mzt.logapi.starter.annotation.LogRecord; -import jakarta.annotation.Resource; import lombok.extern.slf4j.Slf4j; import org.springframework.context.annotation.Lazy; import org.springframework.stereotype.Service; import org.springframework.transaction.annotation.Transactional; import org.springframework.validation.annotation.Validated; +import javax.annotation.Resource; import java.time.LocalDateTime; import java.util.*; diff --git a/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/service/customer/bo/CrmCustomerCreateReqBO.java b/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/service/customer/bo/CrmCustomerCreateReqBO.java index 6d80b0e4c..7a1b35ca9 100644 --- a/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/service/customer/bo/CrmCustomerCreateReqBO.java +++ b/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/service/customer/bo/CrmCustomerCreateReqBO.java @@ -3,9 +3,9 @@ package cn.iocoder.yudao.module.crm.service.customer.bo; import cn.iocoder.yudao.framework.common.validation.Mobile; import cn.iocoder.yudao.framework.common.validation.Telephone; import cn.iocoder.yudao.module.crm.enums.DictTypeConstants; -import jakarta.validation.constraints.Email; -import jakarta.validation.constraints.NotEmpty; -import jakarta.validation.constraints.Size; +import javax.validation.constraints.Email; +import javax.validation.constraints.NotEmpty; +import javax.validation.constraints.Size; import lombok.Data; import java.time.LocalDateTime; diff --git a/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/service/followup/CrmFollowUpRecordService.java b/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/service/followup/CrmFollowUpRecordService.java index d2a7cb8f9..ec6c9aa0e 100644 --- a/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/service/followup/CrmFollowUpRecordService.java +++ b/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/service/followup/CrmFollowUpRecordService.java @@ -5,8 +5,8 @@ import cn.iocoder.yudao.module.crm.controller.admin.followup.vo.CrmFollowUpRecor import cn.iocoder.yudao.module.crm.controller.admin.followup.vo.CrmFollowUpRecordSaveReqVO; import cn.iocoder.yudao.module.crm.dal.dataobject.followup.CrmFollowUpRecordDO; import cn.iocoder.yudao.module.crm.service.followup.bo.CrmFollowUpCreateReqBO; -import jakarta.validation.Valid; +import javax.validation.Valid; import java.util.Collection; import java.util.List; diff --git a/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/service/followup/CrmFollowUpRecordServiceImpl.java b/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/service/followup/CrmFollowUpRecordServiceImpl.java index 88f0b887c..44708d0ab 100644 --- a/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/service/followup/CrmFollowUpRecordServiceImpl.java +++ b/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/service/followup/CrmFollowUpRecordServiceImpl.java @@ -19,7 +19,7 @@ import cn.iocoder.yudao.module.crm.service.customer.CrmCustomerService; import cn.iocoder.yudao.module.crm.service.followup.bo.CrmFollowUpCreateReqBO; import cn.iocoder.yudao.module.crm.service.followup.bo.CrmUpdateFollowUpReqBO; import cn.iocoder.yudao.module.crm.service.permission.CrmPermissionService; -import jakarta.annotation.Resource; +import javax.annotation.Resource; import org.springframework.context.annotation.Lazy; import org.springframework.stereotype.Service; import org.springframework.validation.annotation.Validated; diff --git a/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/service/followup/bo/CrmFollowUpCreateReqBO.java b/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/service/followup/bo/CrmFollowUpCreateReqBO.java index dec219e29..280bcad61 100644 --- a/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/service/followup/bo/CrmFollowUpCreateReqBO.java +++ b/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/service/followup/bo/CrmFollowUpCreateReqBO.java @@ -4,10 +4,10 @@ import cn.iocoder.yudao.module.crm.dal.dataobject.business.CrmBusinessDO; import cn.iocoder.yudao.module.crm.dal.dataobject.contact.CrmContactDO; import cn.iocoder.yudao.module.crm.enums.DictTypeConstants; import cn.iocoder.yudao.module.crm.enums.common.CrmBizTypeEnum; -import jakarta.validation.constraints.NotEmpty; -import jakarta.validation.constraints.NotNull; import lombok.Data; +import javax.validation.constraints.NotEmpty; +import javax.validation.constraints.NotNull; import java.time.LocalDateTime; import java.util.List; diff --git a/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/service/message/CrmBacklogServiceImpl.java b/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/service/message/CrmBacklogServiceImpl.java index 5c2417266..92170f7c0 100644 --- a/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/service/message/CrmBacklogServiceImpl.java +++ b/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/service/message/CrmBacklogServiceImpl.java @@ -4,10 +4,11 @@ import cn.iocoder.yudao.framework.common.pojo.PageResult; import cn.iocoder.yudao.module.crm.controller.admin.backlog.vo.CrmTodayCustomerPageReqVO; import cn.iocoder.yudao.module.crm.dal.dataobject.customer.CrmCustomerDO; import cn.iocoder.yudao.module.crm.dal.mysql.customer.CrmCustomerMapper; -import jakarta.annotation.Resource; import org.springframework.stereotype.Component; import org.springframework.validation.annotation.Validated; +import javax.annotation.Resource; + /** * 待办消息 Service 实现类 * diff --git a/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/service/permission/CrmPermissionServiceImpl.java b/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/service/permission/CrmPermissionServiceImpl.java index f16b2df46..a532b4cec 100644 --- a/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/service/permission/CrmPermissionServiceImpl.java +++ b/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/service/permission/CrmPermissionServiceImpl.java @@ -169,7 +169,7 @@ public class CrmPermissionServiceImpl implements CrmPermissionService { throw exception(CRM_PERMISSION_DELETE_FAIL); } // 校验操作人是否为负责人 - CrmPermissionDO permission = permissionMapper.selectByBizIdAndUserId(permissions.getFirst().getBizId(), userId); + CrmPermissionDO permission = permissionMapper.selectByBizIdAndUserId(permissions.get(0).getBizId(), userId); if (permission == null) { throw exception(CRM_PERMISSION_DELETE_DENIED); } diff --git a/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/service/receivable/CrmReceivablePlanServiceImpl.java b/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/service/receivable/CrmReceivablePlanServiceImpl.java index 9ac2e7f43..ffd24b24b 100644 --- a/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/service/receivable/CrmReceivablePlanServiceImpl.java +++ b/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/service/receivable/CrmReceivablePlanServiceImpl.java @@ -23,8 +23,8 @@ import cn.iocoder.yudao.module.crm.service.permission.bo.CrmPermissionCreateReqB import com.mzt.logapi.context.LogRecordContext; import com.mzt.logapi.service.impl.DiffParseFunction; import com.mzt.logapi.starter.annotation.LogRecord; -import jakarta.annotation.Resource; -import org.springframework.context.annotation.Lazy; +import javax.annotation.Resource; + import org.springframework.stereotype.Service; import org.springframework.validation.annotation.Validated; diff --git a/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/service/receivable/CrmReceivableServiceImpl.java b/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/service/receivable/CrmReceivableServiceImpl.java index effe0d720..8092ac3d0 100644 --- a/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/service/receivable/CrmReceivableServiceImpl.java +++ b/yudao-module-crm/yudao-module-crm-biz/src/main/java/cn/iocoder/yudao/module/crm/service/receivable/CrmReceivableServiceImpl.java @@ -26,11 +26,10 @@ import cn.iocoder.yudao.module.crm.service.permission.bo.CrmPermissionCreateReqB import com.mzt.logapi.context.LogRecordContext; import com.mzt.logapi.service.impl.DiffParseFunction; import com.mzt.logapi.starter.annotation.LogRecord; -import jakarta.annotation.Resource; -import org.springframework.context.annotation.Lazy; import org.springframework.stereotype.Service; import org.springframework.validation.annotation.Validated; +import javax.annotation.Resource; import java.util.Collection; import java.util.List; diff --git a/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/controller/admin/finance/ErpAccountController.java b/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/controller/admin/finance/ErpAccountController.java index 4c8c98058..066d2ec3e 100644 --- a/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/controller/admin/finance/ErpAccountController.java +++ b/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/controller/admin/finance/ErpAccountController.java @@ -16,13 +16,13 @@ import io.swagger.v3.oas.annotations.Operation; import io.swagger.v3.oas.annotations.Parameter; import io.swagger.v3.oas.annotations.Parameters; import io.swagger.v3.oas.annotations.tags.Tag; -import jakarta.annotation.Resource; -import jakarta.servlet.http.HttpServletResponse; -import jakarta.validation.Valid; import org.springframework.security.access.prepost.PreAuthorize; import org.springframework.validation.annotation.Validated; import org.springframework.web.bind.annotation.*; +import javax.annotation.Resource; +import javax.servlet.http.HttpServletResponse; +import javax.validation.Valid; import java.io.IOException; import java.util.List; diff --git a/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/controller/admin/finance/ErpFinancePaymentController.java b/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/controller/admin/finance/ErpFinancePaymentController.java index b1f028a28..e7d776b49 100644 --- a/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/controller/admin/finance/ErpFinancePaymentController.java +++ b/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/controller/admin/finance/ErpFinancePaymentController.java @@ -24,13 +24,13 @@ import cn.iocoder.yudao.module.system.api.user.dto.AdminUserRespDTO; import io.swagger.v3.oas.annotations.Operation; import io.swagger.v3.oas.annotations.Parameter; import io.swagger.v3.oas.annotations.tags.Tag; -import jakarta.annotation.Resource; -import jakarta.servlet.http.HttpServletResponse; -import jakarta.validation.Valid; import org.springframework.security.access.prepost.PreAuthorize; import org.springframework.validation.annotation.Validated; import org.springframework.web.bind.annotation.*; +import javax.annotation.Resource; +import javax.servlet.http.HttpServletResponse; +import javax.validation.Valid; import java.io.IOException; import java.util.List; import java.util.Map; diff --git a/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/controller/admin/finance/ErpFinanceReceiptController.java b/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/controller/admin/finance/ErpFinanceReceiptController.java index d36ab3990..7c5233e0f 100644 --- a/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/controller/admin/finance/ErpFinanceReceiptController.java +++ b/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/controller/admin/finance/ErpFinanceReceiptController.java @@ -24,13 +24,13 @@ import cn.iocoder.yudao.module.system.api.user.dto.AdminUserRespDTO; import io.swagger.v3.oas.annotations.Operation; import io.swagger.v3.oas.annotations.Parameter; import io.swagger.v3.oas.annotations.tags.Tag; -import jakarta.annotation.Resource; -import jakarta.servlet.http.HttpServletResponse; -import jakarta.validation.Valid; import org.springframework.security.access.prepost.PreAuthorize; import org.springframework.validation.annotation.Validated; import org.springframework.web.bind.annotation.*; +import javax.annotation.Resource; +import javax.servlet.http.HttpServletResponse; +import javax.validation.Valid; import java.io.IOException; import java.util.List; import java.util.Map; diff --git a/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/controller/admin/finance/vo/account/ErpAccountSaveReqVO.java b/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/controller/admin/finance/vo/account/ErpAccountSaveReqVO.java index 6f3556530..5b698bec6 100644 --- a/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/controller/admin/finance/vo/account/ErpAccountSaveReqVO.java +++ b/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/controller/admin/finance/vo/account/ErpAccountSaveReqVO.java @@ -3,10 +3,11 @@ package cn.iocoder.yudao.module.erp.controller.admin.finance.vo.account; import cn.iocoder.yudao.framework.common.enums.CommonStatusEnum; import cn.iocoder.yudao.framework.common.validation.InEnum; import io.swagger.v3.oas.annotations.media.Schema; -import jakarta.validation.constraints.NotEmpty; -import jakarta.validation.constraints.NotNull; import lombok.Data; +import javax.validation.constraints.NotEmpty; +import javax.validation.constraints.NotNull; + @Schema(description = "管理后台 - ERP 结算账户新增/修改 Request VO") @Data public class ErpAccountSaveReqVO { diff --git a/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/controller/admin/finance/vo/payment/ErpFinancePaymentRespVO.java b/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/controller/admin/finance/vo/payment/ErpFinancePaymentRespVO.java index 43820a7d2..2eeac5348 100644 --- a/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/controller/admin/finance/vo/payment/ErpFinancePaymentRespVO.java +++ b/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/controller/admin/finance/vo/payment/ErpFinancePaymentRespVO.java @@ -2,9 +2,9 @@ package cn.iocoder.yudao.module.erp.controller.admin.finance.vo.payment; import com.alibaba.excel.annotation.ExcelProperty; import io.swagger.v3.oas.annotations.media.Schema; -import jakarta.validation.constraints.NotNull; import lombok.Data; +import javax.validation.constraints.NotNull; import java.math.BigDecimal; import java.time.LocalDateTime; import java.util.List; diff --git a/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/controller/admin/finance/vo/payment/ErpFinancePaymentSaveReqVO.java b/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/controller/admin/finance/vo/payment/ErpFinancePaymentSaveReqVO.java index e50577b25..c13e54fb5 100644 --- a/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/controller/admin/finance/vo/payment/ErpFinancePaymentSaveReqVO.java +++ b/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/controller/admin/finance/vo/payment/ErpFinancePaymentSaveReqVO.java @@ -1,11 +1,11 @@ package cn.iocoder.yudao.module.erp.controller.admin.finance.vo.payment; import io.swagger.v3.oas.annotations.media.Schema; -import jakarta.validation.Valid; -import jakarta.validation.constraints.NotEmpty; -import jakarta.validation.constraints.NotNull; import lombok.Data; +import javax.validation.Valid; +import javax.validation.constraints.NotEmpty; +import javax.validation.constraints.NotNull; import java.math.BigDecimal; import java.time.LocalDateTime; import java.util.List; diff --git a/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/controller/admin/finance/vo/receipt/ErpFinanceReceiptRespVO.java b/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/controller/admin/finance/vo/receipt/ErpFinanceReceiptRespVO.java index 5c7133fe6..cb2b95d34 100644 --- a/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/controller/admin/finance/vo/receipt/ErpFinanceReceiptRespVO.java +++ b/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/controller/admin/finance/vo/receipt/ErpFinanceReceiptRespVO.java @@ -2,9 +2,9 @@ package cn.iocoder.yudao.module.erp.controller.admin.finance.vo.receipt; import com.alibaba.excel.annotation.ExcelProperty; import io.swagger.v3.oas.annotations.media.Schema; -import jakarta.validation.constraints.NotNull; import lombok.Data; +import javax.validation.constraints.NotNull; import java.math.BigDecimal; import java.time.LocalDateTime; import java.util.List; diff --git a/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/controller/admin/finance/vo/receipt/ErpFinanceReceiptSaveReqVO.java b/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/controller/admin/finance/vo/receipt/ErpFinanceReceiptSaveReqVO.java index 126edf805..e85912b43 100644 --- a/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/controller/admin/finance/vo/receipt/ErpFinanceReceiptSaveReqVO.java +++ b/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/controller/admin/finance/vo/receipt/ErpFinanceReceiptSaveReqVO.java @@ -1,11 +1,11 @@ package cn.iocoder.yudao.module.erp.controller.admin.finance.vo.receipt; import io.swagger.v3.oas.annotations.media.Schema; -import jakarta.validation.Valid; -import jakarta.validation.constraints.NotEmpty; -import jakarta.validation.constraints.NotNull; import lombok.Data; +import javax.validation.Valid; +import javax.validation.constraints.NotEmpty; +import javax.validation.constraints.NotNull; import java.math.BigDecimal; import java.time.LocalDateTime; import java.util.List; diff --git a/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/controller/admin/product/ErpProductCategoryController.java b/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/controller/admin/product/ErpProductCategoryController.java index 85f51c1c6..aaeb7cf9d 100644 --- a/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/controller/admin/product/ErpProductCategoryController.java +++ b/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/controller/admin/product/ErpProductCategoryController.java @@ -13,13 +13,13 @@ import cn.iocoder.yudao.module.erp.service.product.ErpProductCategoryService; import io.swagger.v3.oas.annotations.Operation; import io.swagger.v3.oas.annotations.Parameter; import io.swagger.v3.oas.annotations.tags.Tag; -import jakarta.annotation.Resource; -import jakarta.servlet.http.HttpServletResponse; -import jakarta.validation.Valid; import org.springframework.security.access.prepost.PreAuthorize; import org.springframework.validation.annotation.Validated; import org.springframework.web.bind.annotation.*; +import javax.annotation.Resource; +import javax.servlet.http.HttpServletResponse; +import javax.validation.Valid; import java.io.IOException; import java.util.List; diff --git a/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/controller/admin/product/ErpProductController.java b/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/controller/admin/product/ErpProductController.java index cde7bd704..093a6aa49 100644 --- a/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/controller/admin/product/ErpProductController.java +++ b/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/controller/admin/product/ErpProductController.java @@ -15,13 +15,13 @@ import cn.iocoder.yudao.module.erp.service.product.ErpProductService; import io.swagger.v3.oas.annotations.Operation; import io.swagger.v3.oas.annotations.Parameter; import io.swagger.v3.oas.annotations.tags.Tag; -import jakarta.annotation.Resource; -import jakarta.servlet.http.HttpServletResponse; -import jakarta.validation.Valid; import org.springframework.security.access.prepost.PreAuthorize; import org.springframework.validation.annotation.Validated; import org.springframework.web.bind.annotation.*; +import javax.annotation.Resource; +import javax.servlet.http.HttpServletResponse; +import javax.validation.Valid; import java.io.IOException; import java.util.List; diff --git a/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/controller/admin/product/ErpProductUnitController.java b/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/controller/admin/product/ErpProductUnitController.java index 0be3db01c..ceb5297d1 100644 --- a/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/controller/admin/product/ErpProductUnitController.java +++ b/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/controller/admin/product/ErpProductUnitController.java @@ -15,13 +15,13 @@ import cn.iocoder.yudao.module.erp.service.product.ErpProductUnitService; import io.swagger.v3.oas.annotations.Operation; import io.swagger.v3.oas.annotations.Parameter; import io.swagger.v3.oas.annotations.tags.Tag; -import jakarta.annotation.Resource; -import jakarta.servlet.http.HttpServletResponse; -import jakarta.validation.Valid; import org.springframework.security.access.prepost.PreAuthorize; import org.springframework.validation.annotation.Validated; import org.springframework.web.bind.annotation.*; +import javax.annotation.Resource; +import javax.servlet.http.HttpServletResponse; +import javax.validation.Valid; import java.io.IOException; import java.util.List; diff --git a/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/controller/admin/product/vo/category/ErpProductCategorySaveReqVO.java b/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/controller/admin/product/vo/category/ErpProductCategorySaveReqVO.java index a3c82dc93..1a5ba4e47 100644 --- a/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/controller/admin/product/vo/category/ErpProductCategorySaveReqVO.java +++ b/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/controller/admin/product/vo/category/ErpProductCategorySaveReqVO.java @@ -1,10 +1,11 @@ package cn.iocoder.yudao.module.erp.controller.admin.product.vo.category; import io.swagger.v3.oas.annotations.media.Schema; -import jakarta.validation.constraints.NotEmpty; -import jakarta.validation.constraints.NotNull; import lombok.Data; +import javax.validation.constraints.NotEmpty; +import javax.validation.constraints.NotNull; + @Schema(description = "管理后台 - ERP 产品分类新增/修改 Request VO") @Data public class ErpProductCategorySaveReqVO { diff --git a/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/controller/admin/product/vo/product/ProductSaveReqVO.java b/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/controller/admin/product/vo/product/ProductSaveReqVO.java index 6cf806e3e..cd34e88d9 100644 --- a/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/controller/admin/product/vo/product/ProductSaveReqVO.java +++ b/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/controller/admin/product/vo/product/ProductSaveReqVO.java @@ -1,10 +1,10 @@ package cn.iocoder.yudao.module.erp.controller.admin.product.vo.product; import io.swagger.v3.oas.annotations.media.Schema; -import jakarta.validation.constraints.NotEmpty; -import jakarta.validation.constraints.NotNull; import lombok.Data; +import javax.validation.constraints.NotEmpty; +import javax.validation.constraints.NotNull; import java.math.BigDecimal; @Schema(description = "管理后台 - ERP 产品新增/修改 Request VO") diff --git a/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/controller/admin/product/vo/unit/ErpProductUnitSaveReqVO.java b/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/controller/admin/product/vo/unit/ErpProductUnitSaveReqVO.java index e413ec1bf..dd4547849 100644 --- a/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/controller/admin/product/vo/unit/ErpProductUnitSaveReqVO.java +++ b/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/controller/admin/product/vo/unit/ErpProductUnitSaveReqVO.java @@ -3,10 +3,11 @@ package cn.iocoder.yudao.module.erp.controller.admin.product.vo.unit; import cn.iocoder.yudao.framework.common.enums.CommonStatusEnum; import cn.iocoder.yudao.framework.common.validation.InEnum; import io.swagger.v3.oas.annotations.media.Schema; -import jakarta.validation.constraints.NotEmpty; -import jakarta.validation.constraints.NotNull; import lombok.Data; +import javax.validation.constraints.NotEmpty; +import javax.validation.constraints.NotNull; + @Schema(description = "管理后台 - ERP 产品单位新增/修改 Request VO") @Data public class ErpProductUnitSaveReqVO { diff --git a/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/controller/admin/purchase/ErpPurchaseInController.java b/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/controller/admin/purchase/ErpPurchaseInController.java index d33c7ae4d..49a9d3fad 100644 --- a/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/controller/admin/purchase/ErpPurchaseInController.java +++ b/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/controller/admin/purchase/ErpPurchaseInController.java @@ -25,13 +25,13 @@ import cn.iocoder.yudao.module.system.api.user.dto.AdminUserRespDTO; import io.swagger.v3.oas.annotations.Operation; import io.swagger.v3.oas.annotations.Parameter; import io.swagger.v3.oas.annotations.tags.Tag; -import jakarta.annotation.Resource; -import jakarta.servlet.http.HttpServletResponse; -import jakarta.validation.Valid; import org.springframework.security.access.prepost.PreAuthorize; import org.springframework.validation.annotation.Validated; import org.springframework.web.bind.annotation.*; +import javax.annotation.Resource; +import javax.servlet.http.HttpServletResponse; +import javax.validation.Valid; import java.io.IOException; import java.math.BigDecimal; import java.util.List; diff --git a/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/controller/admin/purchase/ErpPurchaseOrderController.java b/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/controller/admin/purchase/ErpPurchaseOrderController.java index 203d2fec0..9a3c4d802 100644 --- a/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/controller/admin/purchase/ErpPurchaseOrderController.java +++ b/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/controller/admin/purchase/ErpPurchaseOrderController.java @@ -24,13 +24,13 @@ import cn.iocoder.yudao.module.system.api.user.dto.AdminUserRespDTO; import io.swagger.v3.oas.annotations.Operation; import io.swagger.v3.oas.annotations.Parameter; import io.swagger.v3.oas.annotations.tags.Tag; -import jakarta.annotation.Resource; -import jakarta.servlet.http.HttpServletResponse; -import jakarta.validation.Valid; import org.springframework.security.access.prepost.PreAuthorize; import org.springframework.validation.annotation.Validated; import org.springframework.web.bind.annotation.*; +import javax.annotation.Resource; +import javax.servlet.http.HttpServletResponse; +import javax.validation.Valid; import java.io.IOException; import java.math.BigDecimal; import java.util.List; diff --git a/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/controller/admin/purchase/ErpPurchaseReturnController.java b/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/controller/admin/purchase/ErpPurchaseReturnController.java index 0df31bcf1..bb26e213e 100644 --- a/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/controller/admin/purchase/ErpPurchaseReturnController.java +++ b/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/controller/admin/purchase/ErpPurchaseReturnController.java @@ -25,13 +25,13 @@ import cn.iocoder.yudao.module.system.api.user.dto.AdminUserRespDTO; import io.swagger.v3.oas.annotations.Operation; import io.swagger.v3.oas.annotations.Parameter; import io.swagger.v3.oas.annotations.tags.Tag; -import jakarta.annotation.Resource; -import jakarta.servlet.http.HttpServletResponse; -import jakarta.validation.Valid; import org.springframework.security.access.prepost.PreAuthorize; import org.springframework.validation.annotation.Validated; import org.springframework.web.bind.annotation.*; +import javax.annotation.Resource; +import javax.servlet.http.HttpServletResponse; +import javax.validation.Valid; import java.io.IOException; import java.math.BigDecimal; import java.util.List; diff --git a/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/controller/admin/purchase/ErpSupplierController.java b/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/controller/admin/purchase/ErpSupplierController.java index 88253286d..538cae927 100644 --- a/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/controller/admin/purchase/ErpSupplierController.java +++ b/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/controller/admin/purchase/ErpSupplierController.java @@ -15,13 +15,13 @@ import cn.iocoder.yudao.module.erp.service.purchase.ErpSupplierService; import io.swagger.v3.oas.annotations.Operation; import io.swagger.v3.oas.annotations.Parameter; import io.swagger.v3.oas.annotations.tags.Tag; -import jakarta.annotation.Resource; -import jakarta.servlet.http.HttpServletResponse; -import jakarta.validation.Valid; import org.springframework.security.access.prepost.PreAuthorize; import org.springframework.validation.annotation.Validated; import org.springframework.web.bind.annotation.*; +import javax.annotation.Resource; +import javax.servlet.http.HttpServletResponse; +import javax.validation.Valid; import java.io.IOException; import java.util.List; diff --git a/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/controller/admin/purchase/vo/in/ErpPurchaseInRespVO.java b/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/controller/admin/purchase/vo/in/ErpPurchaseInRespVO.java index beeeab869..530269df9 100644 --- a/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/controller/admin/purchase/vo/in/ErpPurchaseInRespVO.java +++ b/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/controller/admin/purchase/vo/in/ErpPurchaseInRespVO.java @@ -3,9 +3,9 @@ package cn.iocoder.yudao.module.erp.controller.admin.purchase.vo.in; import com.alibaba.excel.annotation.ExcelIgnoreUnannotated; import com.alibaba.excel.annotation.ExcelProperty; import io.swagger.v3.oas.annotations.media.Schema; -import jakarta.validation.constraints.NotNull; import lombok.Data; +import javax.validation.constraints.NotNull; import java.math.BigDecimal; import java.time.LocalDateTime; import java.util.List; diff --git a/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/controller/admin/purchase/vo/in/ErpPurchaseInSaveReqVO.java b/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/controller/admin/purchase/vo/in/ErpPurchaseInSaveReqVO.java index 80edeec6d..b4aa63006 100644 --- a/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/controller/admin/purchase/vo/in/ErpPurchaseInSaveReqVO.java +++ b/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/controller/admin/purchase/vo/in/ErpPurchaseInSaveReqVO.java @@ -1,9 +1,9 @@ package cn.iocoder.yudao.module.erp.controller.admin.purchase.vo.in; import io.swagger.v3.oas.annotations.media.Schema; -import jakarta.validation.constraints.NotNull; import lombok.Data; +import javax.validation.constraints.NotNull; import java.math.BigDecimal; import java.time.LocalDateTime; import java.util.List; diff --git a/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/controller/admin/purchase/vo/order/ErpPurchaseOrderRespVO.java b/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/controller/admin/purchase/vo/order/ErpPurchaseOrderRespVO.java index bc76720ee..2e5751635 100644 --- a/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/controller/admin/purchase/vo/order/ErpPurchaseOrderRespVO.java +++ b/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/controller/admin/purchase/vo/order/ErpPurchaseOrderRespVO.java @@ -3,9 +3,9 @@ package cn.iocoder.yudao.module.erp.controller.admin.purchase.vo.order; import com.alibaba.excel.annotation.ExcelIgnoreUnannotated; import com.alibaba.excel.annotation.ExcelProperty; import io.swagger.v3.oas.annotations.media.Schema; -import jakarta.validation.constraints.NotNull; import lombok.Data; +import javax.validation.constraints.NotNull; import java.math.BigDecimal; import java.time.LocalDateTime; import java.util.List; diff --git a/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/controller/admin/purchase/vo/order/ErpPurchaseOrderSaveReqVO.java b/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/controller/admin/purchase/vo/order/ErpPurchaseOrderSaveReqVO.java index 061ed9dcc..78b4d2e0e 100644 --- a/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/controller/admin/purchase/vo/order/ErpPurchaseOrderSaveReqVO.java +++ b/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/controller/admin/purchase/vo/order/ErpPurchaseOrderSaveReqVO.java @@ -1,9 +1,9 @@ package cn.iocoder.yudao.module.erp.controller.admin.purchase.vo.order; import io.swagger.v3.oas.annotations.media.Schema; -import jakarta.validation.constraints.NotNull; import lombok.Data; +import javax.validation.constraints.NotNull; import java.math.BigDecimal; import java.time.LocalDateTime; import java.util.List; diff --git a/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/controller/admin/purchase/vo/returns/ErpPurchaseReturnRespVO.java b/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/controller/admin/purchase/vo/returns/ErpPurchaseReturnRespVO.java index 223b9327e..1d20e43f7 100644 --- a/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/controller/admin/purchase/vo/returns/ErpPurchaseReturnRespVO.java +++ b/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/controller/admin/purchase/vo/returns/ErpPurchaseReturnRespVO.java @@ -3,9 +3,9 @@ package cn.iocoder.yudao.module.erp.controller.admin.purchase.vo.returns; import com.alibaba.excel.annotation.ExcelIgnoreUnannotated; import com.alibaba.excel.annotation.ExcelProperty; import io.swagger.v3.oas.annotations.media.Schema; -import jakarta.validation.constraints.NotNull; import lombok.Data; +import javax.validation.constraints.NotNull; import java.math.BigDecimal; import java.time.LocalDateTime; import java.util.List; diff --git a/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/controller/admin/purchase/vo/returns/ErpPurchaseReturnSaveReqVO.java b/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/controller/admin/purchase/vo/returns/ErpPurchaseReturnSaveReqVO.java index 9254bd583..0d6e55461 100644 --- a/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/controller/admin/purchase/vo/returns/ErpPurchaseReturnSaveReqVO.java +++ b/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/controller/admin/purchase/vo/returns/ErpPurchaseReturnSaveReqVO.java @@ -1,9 +1,9 @@ package cn.iocoder.yudao.module.erp.controller.admin.purchase.vo.returns; import io.swagger.v3.oas.annotations.media.Schema; -import jakarta.validation.constraints.NotNull; import lombok.Data; +import javax.validation.constraints.NotNull; import java.math.BigDecimal; import java.time.LocalDateTime; import java.util.List; diff --git a/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/controller/admin/purchase/vo/supplier/ErpSupplierSaveReqVO.java b/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/controller/admin/purchase/vo/supplier/ErpSupplierSaveReqVO.java index 2291de050..3c26ba9c1 100644 --- a/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/controller/admin/purchase/vo/supplier/ErpSupplierSaveReqVO.java +++ b/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/controller/admin/purchase/vo/supplier/ErpSupplierSaveReqVO.java @@ -5,11 +5,11 @@ import cn.iocoder.yudao.framework.common.validation.InEnum; import cn.iocoder.yudao.framework.common.validation.Mobile; import cn.iocoder.yudao.framework.common.validation.Telephone; import io.swagger.v3.oas.annotations.media.Schema; -import jakarta.validation.constraints.Email; -import jakarta.validation.constraints.NotEmpty; -import jakarta.validation.constraints.NotNull; import lombok.Data; +import javax.validation.constraints.Email; +import javax.validation.constraints.NotEmpty; +import javax.validation.constraints.NotNull; import java.math.BigDecimal; @Schema(description = "管理后台 - ERP 供应商新增/修改 Request VO") diff --git a/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/controller/admin/sale/ErpCustomerController.java b/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/controller/admin/sale/ErpCustomerController.java index 2c2886460..0b131c384 100644 --- a/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/controller/admin/sale/ErpCustomerController.java +++ b/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/controller/admin/sale/ErpCustomerController.java @@ -15,13 +15,13 @@ import cn.iocoder.yudao.module.erp.service.sale.ErpCustomerService; import io.swagger.v3.oas.annotations.Operation; import io.swagger.v3.oas.annotations.Parameter; import io.swagger.v3.oas.annotations.tags.Tag; -import jakarta.annotation.Resource; -import jakarta.servlet.http.HttpServletResponse; -import jakarta.validation.Valid; import org.springframework.security.access.prepost.PreAuthorize; import org.springframework.validation.annotation.Validated; import org.springframework.web.bind.annotation.*; +import javax.annotation.Resource; +import javax.servlet.http.HttpServletResponse; +import javax.validation.Valid; import java.io.IOException; import java.util.List; diff --git a/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/controller/admin/sale/ErpSaleOrderController.java b/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/controller/admin/sale/ErpSaleOrderController.java index 0ca56a45e..15d1fa84a 100644 --- a/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/controller/admin/sale/ErpSaleOrderController.java +++ b/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/controller/admin/sale/ErpSaleOrderController.java @@ -24,13 +24,13 @@ import cn.iocoder.yudao.module.system.api.user.dto.AdminUserRespDTO; import io.swagger.v3.oas.annotations.Operation; import io.swagger.v3.oas.annotations.Parameter; import io.swagger.v3.oas.annotations.tags.Tag; -import jakarta.annotation.Resource; -import jakarta.servlet.http.HttpServletResponse; -import jakarta.validation.Valid; import org.springframework.security.access.prepost.PreAuthorize; import org.springframework.validation.annotation.Validated; import org.springframework.web.bind.annotation.*; +import javax.annotation.Resource; +import javax.servlet.http.HttpServletResponse; +import javax.validation.Valid; import java.io.IOException; import java.math.BigDecimal; import java.util.List; diff --git a/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/controller/admin/sale/ErpSaleOutController.java b/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/controller/admin/sale/ErpSaleOutController.java index 5875ea39f..cdf1196da 100644 --- a/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/controller/admin/sale/ErpSaleOutController.java +++ b/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/controller/admin/sale/ErpSaleOutController.java @@ -25,13 +25,13 @@ import cn.iocoder.yudao.module.system.api.user.dto.AdminUserRespDTO; import io.swagger.v3.oas.annotations.Operation; import io.swagger.v3.oas.annotations.Parameter; import io.swagger.v3.oas.annotations.tags.Tag; -import jakarta.annotation.Resource; -import jakarta.servlet.http.HttpServletResponse; -import jakarta.validation.Valid; import org.springframework.security.access.prepost.PreAuthorize; import org.springframework.validation.annotation.Validated; import org.springframework.web.bind.annotation.*; +import javax.annotation.Resource; +import javax.servlet.http.HttpServletResponse; +import javax.validation.Valid; import java.io.IOException; import java.math.BigDecimal; import java.util.List; diff --git a/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/controller/admin/sale/ErpSaleReturnController.java b/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/controller/admin/sale/ErpSaleReturnController.java index 0dfba67e9..d5dbffe52 100644 --- a/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/controller/admin/sale/ErpSaleReturnController.java +++ b/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/controller/admin/sale/ErpSaleReturnController.java @@ -25,13 +25,13 @@ import cn.iocoder.yudao.module.system.api.user.dto.AdminUserRespDTO; import io.swagger.v3.oas.annotations.Operation; import io.swagger.v3.oas.annotations.Parameter; import io.swagger.v3.oas.annotations.tags.Tag; -import jakarta.annotation.Resource; -import jakarta.servlet.http.HttpServletResponse; -import jakarta.validation.Valid; import org.springframework.security.access.prepost.PreAuthorize; import org.springframework.validation.annotation.Validated; import org.springframework.web.bind.annotation.*; +import javax.annotation.Resource; +import javax.servlet.http.HttpServletResponse; +import javax.validation.Valid; import java.io.IOException; import java.math.BigDecimal; import java.util.List; diff --git a/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/controller/admin/sale/vo/customer/ErpCustomerSaveReqVO.java b/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/controller/admin/sale/vo/customer/ErpCustomerSaveReqVO.java index aef0b2df1..bff15474b 100644 --- a/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/controller/admin/sale/vo/customer/ErpCustomerSaveReqVO.java +++ b/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/controller/admin/sale/vo/customer/ErpCustomerSaveReqVO.java @@ -2,8 +2,8 @@ package cn.iocoder.yudao.module.erp.controller.admin.sale.vo.customer; import io.swagger.v3.oas.annotations.media.Schema; import lombok.*; -import java.util.*; -import jakarta.validation.constraints.*; + +import javax.validation.constraints.*; import java.math.BigDecimal; @Schema(description = "管理后台 - ERP 客户新增/修改 Request VO") diff --git a/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/controller/admin/sale/vo/order/ErpSaleOrderRespVO.java b/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/controller/admin/sale/vo/order/ErpSaleOrderRespVO.java index e5958a841..370ea09db 100644 --- a/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/controller/admin/sale/vo/order/ErpSaleOrderRespVO.java +++ b/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/controller/admin/sale/vo/order/ErpSaleOrderRespVO.java @@ -3,9 +3,9 @@ package cn.iocoder.yudao.module.erp.controller.admin.sale.vo.order; import com.alibaba.excel.annotation.ExcelIgnoreUnannotated; import com.alibaba.excel.annotation.ExcelProperty; import io.swagger.v3.oas.annotations.media.Schema; -import jakarta.validation.constraints.NotNull; import lombok.Data; +import javax.validation.constraints.NotNull; import java.math.BigDecimal; import java.time.LocalDateTime; import java.util.List; diff --git a/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/controller/admin/sale/vo/order/ErpSaleOrderSaveReqVO.java b/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/controller/admin/sale/vo/order/ErpSaleOrderSaveReqVO.java index e23a1fab3..f743a841a 100644 --- a/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/controller/admin/sale/vo/order/ErpSaleOrderSaveReqVO.java +++ b/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/controller/admin/sale/vo/order/ErpSaleOrderSaveReqVO.java @@ -1,9 +1,9 @@ package cn.iocoder.yudao.module.erp.controller.admin.sale.vo.order; import io.swagger.v3.oas.annotations.media.Schema; -import jakarta.validation.constraints.NotNull; import lombok.Data; +import javax.validation.constraints.NotNull; import java.math.BigDecimal; import java.time.LocalDateTime; import java.util.List; diff --git a/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/controller/admin/sale/vo/out/ErpSaleOutRespVO.java b/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/controller/admin/sale/vo/out/ErpSaleOutRespVO.java index bc15a1339..f852c411c 100644 --- a/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/controller/admin/sale/vo/out/ErpSaleOutRespVO.java +++ b/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/controller/admin/sale/vo/out/ErpSaleOutRespVO.java @@ -3,9 +3,9 @@ package cn.iocoder.yudao.module.erp.controller.admin.sale.vo.out; import com.alibaba.excel.annotation.ExcelIgnoreUnannotated; import com.alibaba.excel.annotation.ExcelProperty; import io.swagger.v3.oas.annotations.media.Schema; -import jakarta.validation.constraints.NotNull; import lombok.Data; +import javax.validation.constraints.NotNull; import java.math.BigDecimal; import java.time.LocalDateTime; import java.util.List; diff --git a/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/controller/admin/sale/vo/out/ErpSaleOutSaveReqVO.java b/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/controller/admin/sale/vo/out/ErpSaleOutSaveReqVO.java index 3a2216a33..61a87f6f4 100644 --- a/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/controller/admin/sale/vo/out/ErpSaleOutSaveReqVO.java +++ b/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/controller/admin/sale/vo/out/ErpSaleOutSaveReqVO.java @@ -1,9 +1,9 @@ package cn.iocoder.yudao.module.erp.controller.admin.sale.vo.out; import io.swagger.v3.oas.annotations.media.Schema; -import jakarta.validation.constraints.NotNull; import lombok.Data; +import javax.validation.constraints.NotNull; import java.math.BigDecimal; import java.time.LocalDateTime; import java.util.List; diff --git a/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/controller/admin/sale/vo/returns/ErpSaleReturnRespVO.java b/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/controller/admin/sale/vo/returns/ErpSaleReturnRespVO.java index ba52f4f80..2ca3384fa 100644 --- a/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/controller/admin/sale/vo/returns/ErpSaleReturnRespVO.java +++ b/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/controller/admin/sale/vo/returns/ErpSaleReturnRespVO.java @@ -3,7 +3,7 @@ package cn.iocoder.yudao.module.erp.controller.admin.sale.vo.returns; import com.alibaba.excel.annotation.ExcelIgnoreUnannotated; import com.alibaba.excel.annotation.ExcelProperty; import io.swagger.v3.oas.annotations.media.Schema; -import jakarta.validation.constraints.NotNull; +import javax.validation.constraints.NotNull; import lombok.Data; import java.math.BigDecimal; diff --git a/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/controller/admin/sale/vo/returns/ErpSaleReturnSaveReqVO.java b/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/controller/admin/sale/vo/returns/ErpSaleReturnSaveReqVO.java index 81c046f7d..44eb0df34 100644 --- a/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/controller/admin/sale/vo/returns/ErpSaleReturnSaveReqVO.java +++ b/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/controller/admin/sale/vo/returns/ErpSaleReturnSaveReqVO.java @@ -1,9 +1,9 @@ package cn.iocoder.yudao.module.erp.controller.admin.sale.vo.returns; import io.swagger.v3.oas.annotations.media.Schema; -import jakarta.validation.constraints.NotNull; import lombok.Data; +import javax.validation.constraints.NotNull; import java.math.BigDecimal; import java.time.LocalDateTime; import java.util.List; diff --git a/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/controller/admin/stock/ErpStockCheckController.java b/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/controller/admin/stock/ErpStockCheckController.java index 298ed54fa..6d907cef0 100644 --- a/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/controller/admin/stock/ErpStockCheckController.java +++ b/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/controller/admin/stock/ErpStockCheckController.java @@ -21,13 +21,13 @@ import cn.iocoder.yudao.module.system.api.user.dto.AdminUserRespDTO; import io.swagger.v3.oas.annotations.Operation; import io.swagger.v3.oas.annotations.Parameter; import io.swagger.v3.oas.annotations.tags.Tag; -import jakarta.annotation.Resource; -import jakarta.servlet.http.HttpServletResponse; -import jakarta.validation.Valid; import org.springframework.security.access.prepost.PreAuthorize; import org.springframework.validation.annotation.Validated; import org.springframework.web.bind.annotation.*; +import javax.annotation.Resource; +import javax.servlet.http.HttpServletResponse; +import javax.validation.Valid; import java.io.IOException; import java.util.List; import java.util.Map; diff --git a/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/controller/admin/stock/ErpStockController.java b/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/controller/admin/stock/ErpStockController.java index 912f59731..0ef9b0205 100644 --- a/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/controller/admin/stock/ErpStockController.java +++ b/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/controller/admin/stock/ErpStockController.java @@ -20,9 +20,6 @@ import io.swagger.v3.oas.annotations.Operation; import io.swagger.v3.oas.annotations.Parameter; import io.swagger.v3.oas.annotations.Parameters; import io.swagger.v3.oas.annotations.tags.Tag; -import jakarta.annotation.Resource; -import jakarta.servlet.http.HttpServletResponse; -import jakarta.validation.Valid; import org.springframework.security.access.prepost.PreAuthorize; import org.springframework.validation.annotation.Validated; import org.springframework.web.bind.annotation.GetMapping; @@ -30,6 +27,9 @@ import org.springframework.web.bind.annotation.RequestMapping; import org.springframework.web.bind.annotation.RequestParam; import org.springframework.web.bind.annotation.RestController; +import javax.annotation.Resource; +import javax.servlet.http.HttpServletResponse; +import javax.validation.Valid; import java.io.IOException; import java.math.BigDecimal; import java.util.List; diff --git a/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/controller/admin/stock/ErpStockInController.java b/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/controller/admin/stock/ErpStockInController.java index 8813da89a..4333c134c 100644 --- a/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/controller/admin/stock/ErpStockInController.java +++ b/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/controller/admin/stock/ErpStockInController.java @@ -12,10 +12,10 @@ import cn.iocoder.yudao.module.erp.controller.admin.product.vo.product.ErpProduc import cn.iocoder.yudao.module.erp.controller.admin.stock.vo.in.ErpStockInPageReqVO; import cn.iocoder.yudao.module.erp.controller.admin.stock.vo.in.ErpStockInRespVO; import cn.iocoder.yudao.module.erp.controller.admin.stock.vo.in.ErpStockInSaveReqVO; +import cn.iocoder.yudao.module.erp.dal.dataobject.purchase.ErpSupplierDO; import cn.iocoder.yudao.module.erp.dal.dataobject.stock.ErpStockDO; import cn.iocoder.yudao.module.erp.dal.dataobject.stock.ErpStockInDO; import cn.iocoder.yudao.module.erp.dal.dataobject.stock.ErpStockInItemDO; -import cn.iocoder.yudao.module.erp.dal.dataobject.purchase.ErpSupplierDO; import cn.iocoder.yudao.module.erp.service.product.ErpProductService; import cn.iocoder.yudao.module.erp.service.purchase.ErpSupplierService; import cn.iocoder.yudao.module.erp.service.stock.ErpStockInService; @@ -25,13 +25,13 @@ import cn.iocoder.yudao.module.system.api.user.dto.AdminUserRespDTO; import io.swagger.v3.oas.annotations.Operation; import io.swagger.v3.oas.annotations.Parameter; import io.swagger.v3.oas.annotations.tags.Tag; -import jakarta.annotation.Resource; -import jakarta.servlet.http.HttpServletResponse; -import jakarta.validation.Valid; import org.springframework.security.access.prepost.PreAuthorize; import org.springframework.validation.annotation.Validated; import org.springframework.web.bind.annotation.*; +import javax.annotation.Resource; +import javax.servlet.http.HttpServletResponse; +import javax.validation.Valid; import java.io.IOException; import java.math.BigDecimal; import java.util.List; diff --git a/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/controller/admin/stock/ErpStockMoveController.java b/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/controller/admin/stock/ErpStockMoveController.java index 1df3fd7fc..afe0505ae 100644 --- a/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/controller/admin/stock/ErpStockMoveController.java +++ b/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/controller/admin/stock/ErpStockMoveController.java @@ -23,13 +23,13 @@ import cn.iocoder.yudao.module.system.api.user.dto.AdminUserRespDTO; import io.swagger.v3.oas.annotations.Operation; import io.swagger.v3.oas.annotations.Parameter; import io.swagger.v3.oas.annotations.tags.Tag; -import jakarta.annotation.Resource; -import jakarta.servlet.http.HttpServletResponse; -import jakarta.validation.Valid; import org.springframework.security.access.prepost.PreAuthorize; import org.springframework.validation.annotation.Validated; import org.springframework.web.bind.annotation.*; +import javax.annotation.Resource; +import javax.servlet.http.HttpServletResponse; +import javax.validation.Valid; import java.io.IOException; import java.math.BigDecimal; import java.util.List; diff --git a/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/controller/admin/stock/ErpStockOutController.java b/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/controller/admin/stock/ErpStockOutController.java index 9ad592f1a..f55d37e5e 100644 --- a/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/controller/admin/stock/ErpStockOutController.java +++ b/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/controller/admin/stock/ErpStockOutController.java @@ -25,13 +25,13 @@ import cn.iocoder.yudao.module.system.api.user.dto.AdminUserRespDTO; import io.swagger.v3.oas.annotations.Operation; import io.swagger.v3.oas.annotations.Parameter; import io.swagger.v3.oas.annotations.tags.Tag; -import jakarta.annotation.Resource; -import jakarta.servlet.http.HttpServletResponse; -import jakarta.validation.Valid; import org.springframework.security.access.prepost.PreAuthorize; import org.springframework.validation.annotation.Validated; import org.springframework.web.bind.annotation.*; +import javax.annotation.Resource; +import javax.servlet.http.HttpServletResponse; +import javax.validation.Valid; import java.io.IOException; import java.math.BigDecimal; import java.util.List; diff --git a/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/controller/admin/stock/ErpStockRecordController.java b/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/controller/admin/stock/ErpStockRecordController.java index 6ed453894..0ca65536a 100644 --- a/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/controller/admin/stock/ErpStockRecordController.java +++ b/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/controller/admin/stock/ErpStockRecordController.java @@ -21,9 +21,6 @@ import cn.iocoder.yudao.module.system.api.user.dto.AdminUserRespDTO; import io.swagger.v3.oas.annotations.Operation; import io.swagger.v3.oas.annotations.Parameter; import io.swagger.v3.oas.annotations.tags.Tag; -import jakarta.annotation.Resource; -import jakarta.servlet.http.HttpServletResponse; -import jakarta.validation.Valid; import org.springframework.security.access.prepost.PreAuthorize; import org.springframework.validation.annotation.Validated; import org.springframework.web.bind.annotation.GetMapping; @@ -31,6 +28,9 @@ import org.springframework.web.bind.annotation.RequestMapping; import org.springframework.web.bind.annotation.RequestParam; import org.springframework.web.bind.annotation.RestController; +import javax.annotation.Resource; +import javax.servlet.http.HttpServletResponse; +import javax.validation.Valid; import java.io.IOException; import java.util.List; import java.util.Map; diff --git a/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/controller/admin/stock/ErpWarehouseController.java b/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/controller/admin/stock/ErpWarehouseController.java index 744f439f5..c9a3a8165 100644 --- a/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/controller/admin/stock/ErpWarehouseController.java +++ b/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/controller/admin/stock/ErpWarehouseController.java @@ -16,13 +16,13 @@ import io.swagger.v3.oas.annotations.Operation; import io.swagger.v3.oas.annotations.Parameter; import io.swagger.v3.oas.annotations.Parameters; import io.swagger.v3.oas.annotations.tags.Tag; -import jakarta.annotation.Resource; -import jakarta.servlet.http.HttpServletResponse; -import jakarta.validation.Valid; import org.springframework.security.access.prepost.PreAuthorize; import org.springframework.validation.annotation.Validated; import org.springframework.web.bind.annotation.*; +import javax.annotation.Resource; +import javax.servlet.http.HttpServletResponse; +import javax.validation.Valid; import java.io.IOException; import java.util.List; diff --git a/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/controller/admin/stock/vo/check/ErpStockCheckRespVO.java b/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/controller/admin/stock/vo/check/ErpStockCheckRespVO.java index af53e3c72..88b75bb9c 100644 --- a/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/controller/admin/stock/vo/check/ErpStockCheckRespVO.java +++ b/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/controller/admin/stock/vo/check/ErpStockCheckRespVO.java @@ -5,7 +5,7 @@ import cn.iocoder.yudao.framework.excel.core.convert.DictConvert; import com.alibaba.excel.annotation.ExcelIgnoreUnannotated; import com.alibaba.excel.annotation.ExcelProperty; import io.swagger.v3.oas.annotations.media.Schema; -import jakarta.validation.constraints.NotNull; +import javax.validation.constraints.NotNull; import lombok.Data; import java.math.BigDecimal; diff --git a/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/controller/admin/stock/vo/check/ErpStockCheckSaveReqVO.java b/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/controller/admin/stock/vo/check/ErpStockCheckSaveReqVO.java index 0af223fb5..80e126a28 100644 --- a/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/controller/admin/stock/vo/check/ErpStockCheckSaveReqVO.java +++ b/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/controller/admin/stock/vo/check/ErpStockCheckSaveReqVO.java @@ -1,11 +1,11 @@ package cn.iocoder.yudao.module.erp.controller.admin.stock.vo.check; import io.swagger.v3.oas.annotations.media.Schema; -import jakarta.validation.Valid; -import jakarta.validation.constraints.NotEmpty; -import jakarta.validation.constraints.NotNull; import lombok.Data; +import javax.validation.Valid; +import javax.validation.constraints.NotEmpty; +import javax.validation.constraints.NotNull; import java.math.BigDecimal; import java.time.LocalDateTime; import java.util.List; diff --git a/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/controller/admin/stock/vo/in/ErpStockInSaveReqVO.java b/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/controller/admin/stock/vo/in/ErpStockInSaveReqVO.java index 0187872c8..ef686d82c 100644 --- a/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/controller/admin/stock/vo/in/ErpStockInSaveReqVO.java +++ b/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/controller/admin/stock/vo/in/ErpStockInSaveReqVO.java @@ -1,11 +1,11 @@ package cn.iocoder.yudao.module.erp.controller.admin.stock.vo.in; import io.swagger.v3.oas.annotations.media.Schema; -import jakarta.validation.Valid; -import jakarta.validation.constraints.NotEmpty; -import jakarta.validation.constraints.NotNull; import lombok.Data; +import javax.validation.Valid; +import javax.validation.constraints.NotEmpty; +import javax.validation.constraints.NotNull; import java.math.BigDecimal; import java.time.LocalDateTime; import java.util.List; diff --git a/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/controller/admin/stock/vo/move/ErpStockMoveSaveReqVO.java b/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/controller/admin/stock/vo/move/ErpStockMoveSaveReqVO.java index 17a431561..dc803531b 100644 --- a/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/controller/admin/stock/vo/move/ErpStockMoveSaveReqVO.java +++ b/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/controller/admin/stock/vo/move/ErpStockMoveSaveReqVO.java @@ -3,12 +3,12 @@ package cn.iocoder.yudao.module.erp.controller.admin.stock.vo.move; import cn.hutool.core.util.ObjectUtil; import com.fasterxml.jackson.annotation.JsonIgnore; import io.swagger.v3.oas.annotations.media.Schema; -import jakarta.validation.Valid; -import jakarta.validation.constraints.AssertTrue; -import jakarta.validation.constraints.NotEmpty; -import jakarta.validation.constraints.NotNull; import lombok.Data; +import javax.validation.Valid; +import javax.validation.constraints.AssertTrue; +import javax.validation.constraints.NotEmpty; +import javax.validation.constraints.NotNull; import java.math.BigDecimal; import java.time.LocalDateTime; import java.util.List; diff --git a/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/controller/admin/stock/vo/out/ErpStockOutSaveReqVO.java b/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/controller/admin/stock/vo/out/ErpStockOutSaveReqVO.java index 5a903798e..263058709 100644 --- a/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/controller/admin/stock/vo/out/ErpStockOutSaveReqVO.java +++ b/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/controller/admin/stock/vo/out/ErpStockOutSaveReqVO.java @@ -1,11 +1,11 @@ package cn.iocoder.yudao.module.erp.controller.admin.stock.vo.out; import io.swagger.v3.oas.annotations.media.Schema; -import jakarta.validation.Valid; -import jakarta.validation.constraints.NotEmpty; -import jakarta.validation.constraints.NotNull; import lombok.Data; +import javax.validation.Valid; +import javax.validation.constraints.NotEmpty; +import javax.validation.constraints.NotNull; import java.math.BigDecimal; import java.time.LocalDateTime; import java.util.List; diff --git a/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/controller/admin/stock/vo/warehouse/ErpWarehouseSaveReqVO.java b/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/controller/admin/stock/vo/warehouse/ErpWarehouseSaveReqVO.java index 8a6f1ce78..5105360fe 100644 --- a/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/controller/admin/stock/vo/warehouse/ErpWarehouseSaveReqVO.java +++ b/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/controller/admin/stock/vo/warehouse/ErpWarehouseSaveReqVO.java @@ -3,8 +3,8 @@ package cn.iocoder.yudao.module.erp.controller.admin.stock.vo; import cn.iocoder.yudao.framework.common.enums.CommonStatusEnum; import cn.iocoder.yudao.framework.common.validation.InEnum; import io.swagger.v3.oas.annotations.media.Schema; -import jakarta.validation.constraints.NotEmpty; -import jakarta.validation.constraints.NotNull; +import javax.validation.constraints.NotEmpty; +import javax.validation.constraints.NotNull; import lombok.Data; import java.math.BigDecimal; diff --git a/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/dal/redis/no/ErpNoRedisDAO.java b/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/dal/redis/no/ErpNoRedisDAO.java index 98fb8e8ff..8214cf13d 100644 --- a/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/dal/redis/no/ErpNoRedisDAO.java +++ b/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/dal/redis/no/ErpNoRedisDAO.java @@ -3,10 +3,10 @@ package cn.iocoder.yudao.module.erp.dal.redis.no; import cn.hutool.core.date.DatePattern; import cn.hutool.core.date.DateUtil; import cn.iocoder.yudao.module.erp.dal.redis.RedisKeyConstants; -import jakarta.annotation.Resource; import org.springframework.data.redis.core.StringRedisTemplate; import org.springframework.stereotype.Repository; +import javax.annotation.Resource; import java.time.Duration; import java.time.LocalDateTime; diff --git a/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/framework/web/config/ErpWebConfiguration.java b/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/framework/web/config/ErpWebConfiguration.java index f87e04047..5d866a1b9 100644 --- a/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/framework/web/config/ErpWebConfiguration.java +++ b/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/framework/web/config/ErpWebConfiguration.java @@ -1,7 +1,7 @@ package cn.iocoder.yudao.module.erp.framework.web.config; import cn.iocoder.yudao.framework.swagger.config.YudaoSwaggerAutoConfiguration; -import org.springdoc.core.models.GroupedOpenApi; +import org.springdoc.core.GroupedOpenApi; import org.springframework.context.annotation.Bean; import org.springframework.context.annotation.Configuration; @@ -17,7 +17,7 @@ public class ErpWebConfiguration { * erp 模块的 API 分组 */ @Bean - public GroupedOpenApi tradeGroupedOpenApi() { + public GroupedOpenApi erpGroupedOpenApi() { return YudaoSwaggerAutoConfiguration.buildGroupedOpenApi("erp"); } diff --git a/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/service/finance/ErpAccountService.java b/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/service/finance/ErpAccountService.java index 502423fb2..9226e15c6 100644 --- a/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/service/finance/ErpAccountService.java +++ b/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/service/finance/ErpAccountService.java @@ -4,8 +4,8 @@ import cn.iocoder.yudao.framework.common.pojo.PageResult; import cn.iocoder.yudao.module.erp.controller.admin.finance.vo.account.ErpAccountPageReqVO; import cn.iocoder.yudao.module.erp.controller.admin.finance.vo.account.ErpAccountSaveReqVO; import cn.iocoder.yudao.module.erp.dal.dataobject.finance.ErpAccountDO; -import jakarta.validation.Valid; +import javax.validation.Valid; import java.util.Collection; import java.util.List; import java.util.Map; diff --git a/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/service/finance/ErpAccountServiceImpl.java b/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/service/finance/ErpAccountServiceImpl.java index 9a8e85828..578698b54 100644 --- a/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/service/finance/ErpAccountServiceImpl.java +++ b/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/service/finance/ErpAccountServiceImpl.java @@ -7,15 +7,16 @@ import cn.iocoder.yudao.module.erp.controller.admin.finance.vo.account.ErpAccoun import cn.iocoder.yudao.module.erp.controller.admin.finance.vo.account.ErpAccountSaveReqVO; import cn.iocoder.yudao.module.erp.dal.dataobject.finance.ErpAccountDO; import cn.iocoder.yudao.module.erp.dal.mysql.finance.ErpAccountMapper; -import jakarta.annotation.Resource; import org.springframework.stereotype.Service; import org.springframework.validation.annotation.Validated; +import javax.annotation.Resource; import java.util.Collection; import java.util.List; import static cn.iocoder.yudao.framework.common.exception.util.ServiceExceptionUtil.exception; -import static cn.iocoder.yudao.module.erp.enums.ErrorCodeConstants.*; +import static cn.iocoder.yudao.module.erp.enums.ErrorCodeConstants.ACCOUNT_NOT_ENABLE; +import static cn.iocoder.yudao.module.erp.enums.ErrorCodeConstants.ACCOUNT_NOT_EXISTS; /** * ERP 结算账户 Service 实现类 diff --git a/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/service/finance/ErpFinancePaymentService.java b/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/service/finance/ErpFinancePaymentService.java index b2f27917d..d66cfbea3 100644 --- a/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/service/finance/ErpFinancePaymentService.java +++ b/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/service/finance/ErpFinancePaymentService.java @@ -5,8 +5,8 @@ import cn.iocoder.yudao.module.erp.controller.admin.finance.vo.payment.ErpFinanc import cn.iocoder.yudao.module.erp.controller.admin.finance.vo.payment.ErpFinancePaymentSaveReqVO; import cn.iocoder.yudao.module.erp.dal.dataobject.finance.ErpFinancePaymentDO; import cn.iocoder.yudao.module.erp.dal.dataobject.finance.ErpFinancePaymentItemDO; -import jakarta.validation.Valid; +import javax.validation.Valid; import java.util.Collection; import java.util.List; diff --git a/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/service/finance/ErpFinancePaymentServiceImpl.java b/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/service/finance/ErpFinancePaymentServiceImpl.java index ab94dad53..c7ed6b77d 100644 --- a/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/service/finance/ErpFinancePaymentServiceImpl.java +++ b/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/service/finance/ErpFinancePaymentServiceImpl.java @@ -21,11 +21,11 @@ import cn.iocoder.yudao.module.erp.service.purchase.ErpPurchaseInService; import cn.iocoder.yudao.module.erp.service.purchase.ErpPurchaseReturnService; import cn.iocoder.yudao.module.erp.service.purchase.ErpSupplierService; import cn.iocoder.yudao.module.system.api.user.AdminUserApi; -import jakarta.annotation.Resource; import org.springframework.stereotype.Service; import org.springframework.transaction.annotation.Transactional; import org.springframework.validation.annotation.Validated; +import javax.annotation.Resource; import java.math.BigDecimal; import java.util.Collection; import java.util.Collections; diff --git a/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/service/finance/ErpFinanceReceiptService.java b/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/service/finance/ErpFinanceReceiptService.java index 179648195..8e24d5d34 100644 --- a/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/service/finance/ErpFinanceReceiptService.java +++ b/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/service/finance/ErpFinanceReceiptService.java @@ -5,8 +5,8 @@ import cn.iocoder.yudao.module.erp.controller.admin.finance.vo.receipt.ErpFinanc import cn.iocoder.yudao.module.erp.controller.admin.finance.vo.receipt.ErpFinanceReceiptSaveReqVO; import cn.iocoder.yudao.module.erp.dal.dataobject.finance.ErpFinanceReceiptDO; import cn.iocoder.yudao.module.erp.dal.dataobject.finance.ErpFinanceReceiptItemDO; -import jakarta.validation.Valid; +import javax.validation.Valid; import java.util.Collection; import java.util.List; diff --git a/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/service/finance/ErpFinanceReceiptServiceImpl.java b/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/service/finance/ErpFinanceReceiptServiceImpl.java index 42b81d876..031043a43 100644 --- a/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/service/finance/ErpFinanceReceiptServiceImpl.java +++ b/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/service/finance/ErpFinanceReceiptServiceImpl.java @@ -21,11 +21,11 @@ import cn.iocoder.yudao.module.erp.service.sale.ErpCustomerService; import cn.iocoder.yudao.module.erp.service.sale.ErpSaleOutService; import cn.iocoder.yudao.module.erp.service.sale.ErpSaleReturnService; import cn.iocoder.yudao.module.system.api.user.AdminUserApi; -import jakarta.annotation.Resource; import org.springframework.stereotype.Service; import org.springframework.transaction.annotation.Transactional; import org.springframework.validation.annotation.Validated; +import javax.annotation.Resource; import java.math.BigDecimal; import java.util.Collection; import java.util.Collections; diff --git a/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/service/product/ErpProductCategoryService.java b/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/service/product/ErpProductCategoryService.java index 2b11faf61..609bc4161 100644 --- a/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/service/product/ErpProductCategoryService.java +++ b/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/service/product/ErpProductCategoryService.java @@ -3,8 +3,8 @@ package cn.iocoder.yudao.module.erp.service.product; import cn.iocoder.yudao.module.erp.controller.admin.product.vo.category.ErpProductCategoryListReqVO; import cn.iocoder.yudao.module.erp.controller.admin.product.vo.category.ErpProductCategorySaveReqVO; import cn.iocoder.yudao.module.erp.dal.dataobject.product.ErpProductCategoryDO; -import jakarta.validation.Valid; +import javax.validation.Valid; import java.util.Collection; import java.util.List; import java.util.Map; diff --git a/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/service/product/ErpProductCategoryServiceImpl.java b/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/service/product/ErpProductCategoryServiceImpl.java index bad19a0ee..70062c0bb 100644 --- a/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/service/product/ErpProductCategoryServiceImpl.java +++ b/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/service/product/ErpProductCategoryServiceImpl.java @@ -5,11 +5,11 @@ import cn.iocoder.yudao.module.erp.controller.admin.product.vo.category.ErpProdu import cn.iocoder.yudao.module.erp.controller.admin.product.vo.category.ErpProductCategorySaveReqVO; import cn.iocoder.yudao.module.erp.dal.dataobject.product.ErpProductCategoryDO; import cn.iocoder.yudao.module.erp.dal.mysql.product.ErpProductCategoryMapper; -import jakarta.annotation.Resource; import org.springframework.context.annotation.Lazy; import org.springframework.stereotype.Service; import org.springframework.validation.annotation.Validated; +import javax.annotation.Resource; import java.util.Collection; import java.util.List; import java.util.Objects; @@ -27,7 +27,7 @@ import static cn.iocoder.yudao.module.erp.enums.ErrorCodeConstants.*; public class ErpProductCategoryServiceImpl implements ErpProductCategoryService { @Resource - private ErpProductCategoryMapper productCategoryMapper; + private ErpProductCategoryMapper erpProductCategoryMapper; @Resource @Lazy // 延迟加载,避免循环依赖 @@ -42,7 +42,7 @@ public class ErpProductCategoryServiceImpl implements ErpProductCategoryService // 插入 ErpProductCategoryDO category = BeanUtils.toBean(createReqVO, ErpProductCategoryDO.class); - productCategoryMapper.insert(category); + erpProductCategoryMapper.insert(category); // 返回 return category.getId(); } @@ -58,7 +58,7 @@ public class ErpProductCategoryServiceImpl implements ErpProductCategoryService // 更新 ErpProductCategoryDO updateObj = BeanUtils.toBean(updateReqVO, ErpProductCategoryDO.class); - productCategoryMapper.updateById(updateObj); + erpProductCategoryMapper.updateById(updateObj); } @Override @@ -66,7 +66,7 @@ public class ErpProductCategoryServiceImpl implements ErpProductCategoryService // 1.1 校验存在 validateProductCategoryExists(id); // 1.2 校验是否有子产品分类 - if (productCategoryMapper.selectCountByParentId(id) > 0) { + if (erpProductCategoryMapper.selectCountByParentId(id) > 0) { throw exception(PRODUCT_CATEGORY_EXITS_CHILDREN); } // 1.3 校验是否有产品 @@ -74,11 +74,11 @@ public class ErpProductCategoryServiceImpl implements ErpProductCategoryService throw exception(PRODUCT_CATEGORY_EXITS_PRODUCT); } // 2. 删除 - productCategoryMapper.deleteById(id); + erpProductCategoryMapper.deleteById(id); } private void validateProductCategoryExists(Long id) { - if (productCategoryMapper.selectById(id) == null) { + if (erpProductCategoryMapper.selectById(id) == null) { throw exception(PRODUCT_CATEGORY_NOT_EXISTS); } } @@ -92,7 +92,7 @@ public class ErpProductCategoryServiceImpl implements ErpProductCategoryService throw exception(PRODUCT_CATEGORY_PARENT_ERROR); } // 2. 父产品分类不存在 - ErpProductCategoryDO parentCategory = productCategoryMapper.selectById(parentId); + ErpProductCategoryDO parentCategory = erpProductCategoryMapper.selectById(parentId); if (parentCategory == null) { throw exception(PRODUCT_CATEGORY_PARENT_NOT_EXITS); } @@ -110,7 +110,7 @@ public class ErpProductCategoryServiceImpl implements ErpProductCategoryService if (parentId == null || ErpProductCategoryDO.PARENT_ID_ROOT.equals(parentId)) { break; } - parentCategory = productCategoryMapper.selectById(parentId); + parentCategory = erpProductCategoryMapper.selectById(parentId); if (parentCategory == null) { break; } @@ -118,7 +118,7 @@ public class ErpProductCategoryServiceImpl implements ErpProductCategoryService } private void validateProductCategoryNameUnique(Long id, Long parentId, String name) { - ErpProductCategoryDO productCategory = productCategoryMapper.selectByParentIdAndName(parentId, name); + ErpProductCategoryDO productCategory = erpProductCategoryMapper.selectByParentIdAndName(parentId, name); if (productCategory == null) { return; } @@ -133,17 +133,17 @@ public class ErpProductCategoryServiceImpl implements ErpProductCategoryService @Override public ErpProductCategoryDO getProductCategory(Long id) { - return productCategoryMapper.selectById(id); + return erpProductCategoryMapper.selectById(id); } @Override public List getProductCategoryList(ErpProductCategoryListReqVO listReqVO) { - return productCategoryMapper.selectList(listReqVO); + return erpProductCategoryMapper.selectList(listReqVO); } @Override public List getProductCategoryList(Collection ids) { - return productCategoryMapper.selectBatchIds(ids); + return erpProductCategoryMapper.selectBatchIds(ids); } } \ No newline at end of file diff --git a/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/service/product/ErpProductService.java b/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/service/product/ErpProductService.java index 778c7f29a..a947e3b9d 100644 --- a/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/service/product/ErpProductService.java +++ b/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/service/product/ErpProductService.java @@ -5,8 +5,8 @@ import cn.iocoder.yudao.module.erp.controller.admin.product.vo.product.ErpProduc import cn.iocoder.yudao.module.erp.controller.admin.product.vo.product.ErpProductRespVO; import cn.iocoder.yudao.module.erp.controller.admin.product.vo.product.ProductSaveReqVO; import cn.iocoder.yudao.module.erp.dal.dataobject.product.ErpProductDO; -import jakarta.validation.Valid; +import javax.validation.Valid; import java.util.Collection; import java.util.List; import java.util.Map; diff --git a/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/service/product/ErpProductServiceImpl.java b/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/service/product/ErpProductServiceImpl.java index cbe689c6a..c264b8e74 100644 --- a/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/service/product/ErpProductServiceImpl.java +++ b/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/service/product/ErpProductServiceImpl.java @@ -12,15 +12,20 @@ import cn.iocoder.yudao.module.erp.dal.dataobject.product.ErpProductCategoryDO; import cn.iocoder.yudao.module.erp.dal.dataobject.product.ErpProductDO; import cn.iocoder.yudao.module.erp.dal.dataobject.product.ErpProductUnitDO; import cn.iocoder.yudao.module.erp.dal.mysql.product.ErpProductMapper; -import jakarta.annotation.Resource; import org.springframework.stereotype.Service; import org.springframework.validation.annotation.Validated; -import java.util.*; +import javax.annotation.Resource; +import java.util.Collection; +import java.util.Collections; +import java.util.List; +import java.util.Map; 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.module.erp.enums.ErrorCodeConstants.*; +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.module.erp.enums.ErrorCodeConstants.PRODUCT_NOT_ENABLE; +import static cn.iocoder.yudao.module.erp.enums.ErrorCodeConstants.PRODUCT_NOT_EXISTS; /** * ERP 产品 Service 实现类 diff --git a/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/service/product/ErpProductUnitService.java b/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/service/product/ErpProductUnitService.java index 340278ab9..93776adac 100644 --- a/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/service/product/ErpProductUnitService.java +++ b/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/service/product/ErpProductUnitService.java @@ -4,8 +4,8 @@ import cn.iocoder.yudao.framework.common.pojo.PageResult; import cn.iocoder.yudao.module.erp.controller.admin.product.vo.unit.ErpProductUnitPageReqVO; import cn.iocoder.yudao.module.erp.controller.admin.product.vo.unit.ErpProductUnitSaveReqVO; import cn.iocoder.yudao.module.erp.dal.dataobject.product.ErpProductUnitDO; -import jakarta.validation.Valid; +import javax.validation.Valid; import java.util.Collection; import java.util.List; import java.util.Map; diff --git a/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/service/product/ErpProductUnitServiceImpl.java b/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/service/product/ErpProductUnitServiceImpl.java index 89ba6b08e..d2592a492 100644 --- a/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/service/product/ErpProductUnitServiceImpl.java +++ b/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/service/product/ErpProductUnitServiceImpl.java @@ -7,11 +7,11 @@ import cn.iocoder.yudao.module.erp.controller.admin.product.vo.unit.ErpProductUn import cn.iocoder.yudao.module.erp.dal.dataobject.product.ErpProductUnitDO; import cn.iocoder.yudao.module.erp.dal.mysql.product.ErpProductUnitMapper; import com.google.common.annotations.VisibleForTesting; -import jakarta.annotation.Resource; import org.springframework.context.annotation.Lazy; import org.springframework.stereotype.Service; import org.springframework.validation.annotation.Validated; +import javax.annotation.Resource; import java.util.Collection; import java.util.List; diff --git a/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/service/purchase/ErpPurchaseInService.java b/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/service/purchase/ErpPurchaseInService.java index 37aa452cd..6c994e894 100644 --- a/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/service/purchase/ErpPurchaseInService.java +++ b/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/service/purchase/ErpPurchaseInService.java @@ -5,8 +5,8 @@ import cn.iocoder.yudao.module.erp.controller.admin.purchase.vo.in.ErpPurchaseIn import cn.iocoder.yudao.module.erp.controller.admin.purchase.vo.in.ErpPurchaseInSaveReqVO; import cn.iocoder.yudao.module.erp.dal.dataobject.purchase.ErpPurchaseInDO; import cn.iocoder.yudao.module.erp.dal.dataobject.purchase.ErpPurchaseInItemDO; -import jakarta.validation.Valid; +import javax.validation.Valid; import java.math.BigDecimal; import java.util.Collection; import java.util.List; diff --git a/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/service/purchase/ErpPurchaseInServiceImpl.java b/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/service/purchase/ErpPurchaseInServiceImpl.java index 5d6ad6230..acbdb24db 100644 --- a/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/service/purchase/ErpPurchaseInServiceImpl.java +++ b/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/service/purchase/ErpPurchaseInServiceImpl.java @@ -21,12 +21,12 @@ import cn.iocoder.yudao.module.erp.service.product.ErpProductService; import cn.iocoder.yudao.module.erp.service.stock.ErpStockRecordService; import cn.iocoder.yudao.module.erp.service.stock.bo.ErpStockRecordCreateReqBO; 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; +import javax.annotation.Resource; import java.math.BigDecimal; import java.util.Collection; import java.util.Collections; diff --git a/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/service/purchase/ErpPurchaseOrderService.java b/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/service/purchase/ErpPurchaseOrderService.java index bfea076bb..29d5f6f3f 100644 --- a/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/service/purchase/ErpPurchaseOrderService.java +++ b/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/service/purchase/ErpPurchaseOrderService.java @@ -5,8 +5,8 @@ import cn.iocoder.yudao.module.erp.controller.admin.purchase.vo.order.ErpPurchas import cn.iocoder.yudao.module.erp.controller.admin.purchase.vo.order.ErpPurchaseOrderSaveReqVO; import cn.iocoder.yudao.module.erp.dal.dataobject.purchase.ErpPurchaseOrderDO; import cn.iocoder.yudao.module.erp.dal.dataobject.purchase.ErpPurchaseOrderItemDO; -import jakarta.validation.Valid; +import javax.validation.Valid; import java.math.BigDecimal; import java.util.Collection; import java.util.List; diff --git a/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/service/purchase/ErpPurchaseOrderServiceImpl.java b/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/service/purchase/ErpPurchaseOrderServiceImpl.java index 74b5b18d2..c585490b9 100644 --- a/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/service/purchase/ErpPurchaseOrderServiceImpl.java +++ b/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/service/purchase/ErpPurchaseOrderServiceImpl.java @@ -16,11 +16,11 @@ 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 jakarta.annotation.Resource; import org.springframework.stereotype.Service; import org.springframework.transaction.annotation.Transactional; import org.springframework.validation.annotation.Validated; +import javax.annotation.Resource; import java.math.BigDecimal; import java.util.Collection; import java.util.Collections; diff --git a/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/service/purchase/ErpPurchaseReturnService.java b/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/service/purchase/ErpPurchaseReturnService.java index b6826fa88..9c4a4ab3b 100644 --- a/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/service/purchase/ErpPurchaseReturnService.java +++ b/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/service/purchase/ErpPurchaseReturnService.java @@ -5,8 +5,8 @@ import cn.iocoder.yudao.module.erp.controller.admin.purchase.vo.returns.ErpPurch import cn.iocoder.yudao.module.erp.controller.admin.purchase.vo.returns.ErpPurchaseReturnSaveReqVO; import cn.iocoder.yudao.module.erp.dal.dataobject.purchase.ErpPurchaseReturnDO; import cn.iocoder.yudao.module.erp.dal.dataobject.purchase.ErpPurchaseReturnItemDO; -import jakarta.validation.Valid; +import javax.validation.Valid; import java.math.BigDecimal; import java.util.Collection; import java.util.List; diff --git a/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/service/purchase/ErpPurchaseReturnServiceImpl.java b/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/service/purchase/ErpPurchaseReturnServiceImpl.java index 05960e896..83238220c 100644 --- a/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/service/purchase/ErpPurchaseReturnServiceImpl.java +++ b/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/service/purchase/ErpPurchaseReturnServiceImpl.java @@ -20,12 +20,12 @@ import cn.iocoder.yudao.module.erp.service.finance.ErpAccountService; import cn.iocoder.yudao.module.erp.service.product.ErpProductService; import cn.iocoder.yudao.module.erp.service.stock.ErpStockRecordService; import cn.iocoder.yudao.module.erp.service.stock.bo.ErpStockRecordCreateReqBO; -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; +import javax.annotation.Resource; import java.math.BigDecimal; import java.util.Collection; import java.util.Collections; diff --git a/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/service/purchase/ErpSupplierService.java b/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/service/purchase/ErpSupplierService.java index 495474d13..f1afb6a16 100644 --- a/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/service/purchase/ErpSupplierService.java +++ b/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/service/purchase/ErpSupplierService.java @@ -4,8 +4,8 @@ import cn.iocoder.yudao.framework.common.pojo.PageResult; import cn.iocoder.yudao.module.erp.controller.admin.purchase.vo.supplier.ErpSupplierPageReqVO; import cn.iocoder.yudao.module.erp.controller.admin.purchase.vo.supplier.ErpSupplierSaveReqVO; import cn.iocoder.yudao.module.erp.dal.dataobject.purchase.ErpSupplierDO; -import jakarta.validation.Valid; +import javax.validation.Valid; import java.util.Collection; import java.util.List; import java.util.Map; diff --git a/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/service/purchase/ErpSupplierServiceImpl.java b/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/service/purchase/ErpSupplierServiceImpl.java index 1c90ff3f6..af6f2ac23 100644 --- a/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/service/purchase/ErpSupplierServiceImpl.java +++ b/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/service/purchase/ErpSupplierServiceImpl.java @@ -7,15 +7,16 @@ import cn.iocoder.yudao.module.erp.controller.admin.purchase.vo.supplier.ErpSupp import cn.iocoder.yudao.module.erp.controller.admin.purchase.vo.supplier.ErpSupplierSaveReqVO; import cn.iocoder.yudao.module.erp.dal.dataobject.purchase.ErpSupplierDO; import cn.iocoder.yudao.module.erp.dal.mysql.purchase.ErpSupplierMapper; -import jakarta.annotation.Resource; import org.springframework.stereotype.Service; import org.springframework.validation.annotation.Validated; +import javax.annotation.Resource; import java.util.Collection; import java.util.List; import static cn.iocoder.yudao.framework.common.exception.util.ServiceExceptionUtil.exception; -import static cn.iocoder.yudao.module.erp.enums.ErrorCodeConstants.*; +import static cn.iocoder.yudao.module.erp.enums.ErrorCodeConstants.SUPPLIER_NOT_ENABLE; +import static cn.iocoder.yudao.module.erp.enums.ErrorCodeConstants.SUPPLIER_NOT_EXISTS; /** * ERP 供应商 Service 实现类 diff --git a/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/service/sale/ErpCustomerService.java b/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/service/sale/ErpCustomerService.java index d047300e8..e70c09039 100644 --- a/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/service/sale/ErpCustomerService.java +++ b/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/service/sale/ErpCustomerService.java @@ -4,8 +4,8 @@ import cn.iocoder.yudao.framework.common.pojo.PageResult; import cn.iocoder.yudao.module.erp.controller.admin.sale.vo.customer.ErpCustomerPageReqVO; import cn.iocoder.yudao.module.erp.controller.admin.sale.vo.customer.ErpCustomerSaveReqVO; import cn.iocoder.yudao.module.erp.dal.dataobject.sale.ErpCustomerDO; -import jakarta.validation.Valid; +import javax.validation.Valid; import java.util.Collection; import java.util.List; import java.util.Map; diff --git a/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/service/sale/ErpCustomerServiceImpl.java b/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/service/sale/ErpCustomerServiceImpl.java index 73d2aa9d5..7df07fb39 100644 --- a/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/service/sale/ErpCustomerServiceImpl.java +++ b/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/service/sale/ErpCustomerServiceImpl.java @@ -7,10 +7,10 @@ import cn.iocoder.yudao.module.erp.controller.admin.sale.vo.customer.ErpCustomer import cn.iocoder.yudao.module.erp.controller.admin.sale.vo.customer.ErpCustomerSaveReqVO; import cn.iocoder.yudao.module.erp.dal.dataobject.sale.ErpCustomerDO; import cn.iocoder.yudao.module.erp.dal.mysql.sale.ErpCustomerMapper; -import jakarta.annotation.Resource; import org.springframework.stereotype.Service; import org.springframework.validation.annotation.Validated; +import javax.annotation.Resource; import java.util.Collection; import java.util.List; diff --git a/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/service/sale/ErpSaleOrderService.java b/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/service/sale/ErpSaleOrderService.java index c75f201f3..dad08944b 100644 --- a/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/service/sale/ErpSaleOrderService.java +++ b/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/service/sale/ErpSaleOrderService.java @@ -5,8 +5,8 @@ import cn.iocoder.yudao.module.erp.controller.admin.sale.vo.order.ErpSaleOrderPa import cn.iocoder.yudao.module.erp.controller.admin.sale.vo.order.ErpSaleOrderSaveReqVO; 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 javax.validation.Valid; import java.math.BigDecimal; import java.util.Collection; import java.util.List; diff --git a/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/service/sale/ErpSaleOrderServiceImpl.java b/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/service/sale/ErpSaleOrderServiceImpl.java index 592fe5fe7..7c25d067e 100644 --- a/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/service/sale/ErpSaleOrderServiceImpl.java +++ b/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/service/sale/ErpSaleOrderServiceImpl.java @@ -17,11 +17,11 @@ 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; import org.springframework.validation.annotation.Validated; +import javax.annotation.Resource; import java.math.BigDecimal; import java.util.Collection; import java.util.Collections; diff --git a/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/service/sale/ErpSaleOutService.java b/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/service/sale/ErpSaleOutService.java index 616f77837..a57f013fc 100644 --- a/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/service/sale/ErpSaleOutService.java +++ b/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/service/sale/ErpSaleOutService.java @@ -5,8 +5,8 @@ import cn.iocoder.yudao.module.erp.controller.admin.sale.vo.out.ErpSaleOutPageRe import cn.iocoder.yudao.module.erp.controller.admin.sale.vo.out.ErpSaleOutSaveReqVO; import cn.iocoder.yudao.module.erp.dal.dataobject.sale.ErpSaleOutDO; import cn.iocoder.yudao.module.erp.dal.dataobject.sale.ErpSaleOutItemDO; -import jakarta.validation.Valid; +import javax.validation.Valid; import java.math.BigDecimal; import java.util.Collection; import java.util.List; diff --git a/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/service/sale/ErpSaleOutServiceImpl.java b/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/service/sale/ErpSaleOutServiceImpl.java index d930c16bf..3cd476912 100644 --- a/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/service/sale/ErpSaleOutServiceImpl.java +++ b/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/service/sale/ErpSaleOutServiceImpl.java @@ -21,12 +21,12 @@ import cn.iocoder.yudao.module.erp.service.product.ErpProductService; import cn.iocoder.yudao.module.erp.service.stock.ErpStockRecordService; import cn.iocoder.yudao.module.erp.service.stock.bo.ErpStockRecordCreateReqBO; 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; +import javax.annotation.Resource; import java.math.BigDecimal; import java.util.Collection; import java.util.Collections; diff --git a/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/service/sale/ErpSaleReturnService.java b/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/service/sale/ErpSaleReturnService.java index bc192a17c..6f18dc07c 100644 --- a/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/service/sale/ErpSaleReturnService.java +++ b/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/service/sale/ErpSaleReturnService.java @@ -5,8 +5,8 @@ import cn.iocoder.yudao.module.erp.controller.admin.sale.vo.returns.ErpSaleRetur import cn.iocoder.yudao.module.erp.controller.admin.sale.vo.returns.ErpSaleReturnSaveReqVO; import cn.iocoder.yudao.module.erp.dal.dataobject.sale.ErpSaleReturnDO; import cn.iocoder.yudao.module.erp.dal.dataobject.sale.ErpSaleReturnItemDO; -import jakarta.validation.Valid; +import javax.validation.Valid; import java.math.BigDecimal; import java.util.Collection; import java.util.List; diff --git a/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/service/sale/ErpSaleReturnServiceImpl.java b/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/service/sale/ErpSaleReturnServiceImpl.java index 85d798e72..a10a73ad1 100644 --- a/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/service/sale/ErpSaleReturnServiceImpl.java +++ b/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/service/sale/ErpSaleReturnServiceImpl.java @@ -21,12 +21,12 @@ import cn.iocoder.yudao.module.erp.service.product.ErpProductService; import cn.iocoder.yudao.module.erp.service.stock.ErpStockRecordService; import cn.iocoder.yudao.module.erp.service.stock.bo.ErpStockRecordCreateReqBO; 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; +import javax.annotation.Resource; import java.math.BigDecimal; import java.util.Collection; import java.util.Collections; diff --git a/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/service/stock/ErpStockCheckService.java b/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/service/stock/ErpStockCheckService.java index 2f8a0f9ee..02a192165 100644 --- a/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/service/stock/ErpStockCheckService.java +++ b/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/service/stock/ErpStockCheckService.java @@ -5,8 +5,8 @@ import cn.iocoder.yudao.module.erp.controller.admin.stock.vo.check.ErpStockCheck import cn.iocoder.yudao.module.erp.controller.admin.stock.vo.check.ErpStockCheckSaveReqVO; import cn.iocoder.yudao.module.erp.dal.dataobject.stock.ErpStockCheckDO; import cn.iocoder.yudao.module.erp.dal.dataobject.stock.ErpStockCheckItemDO; -import jakarta.validation.Valid; +import javax.validation.Valid; import java.util.Collection; import java.util.List; diff --git a/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/service/stock/ErpStockCheckServiceImpl.java b/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/service/stock/ErpStockCheckServiceImpl.java index 49aca94d3..16afc71be 100644 --- a/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/service/stock/ErpStockCheckServiceImpl.java +++ b/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/service/stock/ErpStockCheckServiceImpl.java @@ -16,11 +16,11 @@ import cn.iocoder.yudao.module.erp.enums.ErpAuditStatus; import cn.iocoder.yudao.module.erp.enums.stock.ErpStockRecordBizTypeEnum; import cn.iocoder.yudao.module.erp.service.product.ErpProductService; import cn.iocoder.yudao.module.erp.service.stock.bo.ErpStockRecordCreateReqBO; -import jakarta.annotation.Resource; import org.springframework.stereotype.Service; import org.springframework.transaction.annotation.Transactional; import org.springframework.validation.annotation.Validated; +import javax.annotation.Resource; import java.math.BigDecimal; import java.util.Collection; import java.util.Collections; diff --git a/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/service/stock/ErpStockInService.java b/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/service/stock/ErpStockInService.java index 4e51545e4..65a5063e8 100644 --- a/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/service/stock/ErpStockInService.java +++ b/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/service/stock/ErpStockInService.java @@ -5,8 +5,8 @@ import cn.iocoder.yudao.module.erp.controller.admin.stock.vo.in.ErpStockInPageRe import cn.iocoder.yudao.module.erp.controller.admin.stock.vo.in.ErpStockInSaveReqVO; import cn.iocoder.yudao.module.erp.dal.dataobject.stock.ErpStockInDO; import cn.iocoder.yudao.module.erp.dal.dataobject.stock.ErpStockInItemDO; -import jakarta.validation.Valid; +import javax.validation.Valid; import java.util.Collection; import java.util.List; diff --git a/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/service/stock/ErpStockInServiceImpl.java b/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/service/stock/ErpStockInServiceImpl.java index 213fca8b8..85d93d881 100644 --- a/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/service/stock/ErpStockInServiceImpl.java +++ b/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/service/stock/ErpStockInServiceImpl.java @@ -17,11 +17,11 @@ import cn.iocoder.yudao.module.erp.enums.stock.ErpStockRecordBizTypeEnum; import cn.iocoder.yudao.module.erp.service.product.ErpProductService; import cn.iocoder.yudao.module.erp.service.purchase.ErpSupplierService; import cn.iocoder.yudao.module.erp.service.stock.bo.ErpStockRecordCreateReqBO; -import jakarta.annotation.Resource; import org.springframework.stereotype.Service; import org.springframework.transaction.annotation.Transactional; import org.springframework.validation.annotation.Validated; +import javax.annotation.Resource; import java.math.BigDecimal; import java.util.Collection; import java.util.Collections; diff --git a/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/service/stock/ErpStockMoveService.java b/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/service/stock/ErpStockMoveService.java index 8af13a639..b7d4ecf86 100644 --- a/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/service/stock/ErpStockMoveService.java +++ b/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/service/stock/ErpStockMoveService.java @@ -5,8 +5,8 @@ import cn.iocoder.yudao.module.erp.controller.admin.stock.vo.move.ErpStockMovePa import cn.iocoder.yudao.module.erp.controller.admin.stock.vo.move.ErpStockMoveSaveReqVO; import cn.iocoder.yudao.module.erp.dal.dataobject.stock.ErpStockMoveDO; import cn.iocoder.yudao.module.erp.dal.dataobject.stock.ErpStockMoveItemDO; -import jakarta.validation.Valid; +import javax.validation.Valid; import java.util.Collection; import java.util.List; diff --git a/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/service/stock/ErpStockMoveServiceImpl.java b/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/service/stock/ErpStockMoveServiceImpl.java index a0d8f79d4..d99d02618 100644 --- a/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/service/stock/ErpStockMoveServiceImpl.java +++ b/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/service/stock/ErpStockMoveServiceImpl.java @@ -16,11 +16,11 @@ import cn.iocoder.yudao.module.erp.enums.ErpAuditStatus; import cn.iocoder.yudao.module.erp.enums.stock.ErpStockRecordBizTypeEnum; import cn.iocoder.yudao.module.erp.service.product.ErpProductService; import cn.iocoder.yudao.module.erp.service.stock.bo.ErpStockRecordCreateReqBO; -import jakarta.annotation.Resource; import org.springframework.stereotype.Service; import org.springframework.transaction.annotation.Transactional; import org.springframework.validation.annotation.Validated; +import javax.annotation.Resource; import java.math.BigDecimal; import java.util.Collection; import java.util.Collections; diff --git a/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/service/stock/ErpStockOutService.java b/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/service/stock/ErpStockOutService.java index 558fb6948..ffd17fca1 100644 --- a/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/service/stock/ErpStockOutService.java +++ b/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/service/stock/ErpStockOutService.java @@ -5,8 +5,8 @@ import cn.iocoder.yudao.module.erp.controller.admin.stock.vo.out.ErpStockOutPage import cn.iocoder.yudao.module.erp.controller.admin.stock.vo.out.ErpStockOutSaveReqVO; import cn.iocoder.yudao.module.erp.dal.dataobject.stock.ErpStockOutDO; import cn.iocoder.yudao.module.erp.dal.dataobject.stock.ErpStockOutItemDO; -import jakarta.validation.Valid; +import javax.validation.Valid; import java.util.Collection; import java.util.List; diff --git a/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/service/stock/ErpStockOutServiceImpl.java b/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/service/stock/ErpStockOutServiceImpl.java index 9fa192465..aa7428c17 100644 --- a/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/service/stock/ErpStockOutServiceImpl.java +++ b/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/service/stock/ErpStockOutServiceImpl.java @@ -17,11 +17,11 @@ import cn.iocoder.yudao.module.erp.enums.stock.ErpStockRecordBizTypeEnum; import cn.iocoder.yudao.module.erp.service.product.ErpProductService; import cn.iocoder.yudao.module.erp.service.sale.ErpCustomerService; import cn.iocoder.yudao.module.erp.service.stock.bo.ErpStockRecordCreateReqBO; -import jakarta.annotation.Resource; import org.springframework.stereotype.Service; import org.springframework.transaction.annotation.Transactional; import org.springframework.validation.annotation.Validated; +import javax.annotation.Resource; import java.math.BigDecimal; import java.util.Collection; import java.util.Collections; diff --git a/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/service/stock/ErpStockRecordService.java b/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/service/stock/ErpStockRecordService.java index 506b992a4..aa9072e81 100644 --- a/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/service/stock/ErpStockRecordService.java +++ b/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/service/stock/ErpStockRecordService.java @@ -4,7 +4,8 @@ import cn.iocoder.yudao.framework.common.pojo.PageResult; import cn.iocoder.yudao.module.erp.controller.admin.stock.vo.record.ErpStockRecordPageReqVO; import cn.iocoder.yudao.module.erp.dal.dataobject.stock.ErpStockRecordDO; import cn.iocoder.yudao.module.erp.service.stock.bo.ErpStockRecordCreateReqBO; -import jakarta.validation.Valid; + +import javax.validation.Valid; /** * ERP 产品库存明细 Service 接口 diff --git a/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/service/stock/ErpStockRecordServiceImpl.java b/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/service/stock/ErpStockRecordServiceImpl.java index d84951c28..b4b3875da 100644 --- a/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/service/stock/ErpStockRecordServiceImpl.java +++ b/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/service/stock/ErpStockRecordServiceImpl.java @@ -6,11 +6,11 @@ import cn.iocoder.yudao.module.erp.controller.admin.stock.vo.record.ErpStockReco import cn.iocoder.yudao.module.erp.dal.dataobject.stock.ErpStockRecordDO; import cn.iocoder.yudao.module.erp.dal.mysql.stock.ErpStockRecordMapper; import cn.iocoder.yudao.module.erp.service.stock.bo.ErpStockRecordCreateReqBO; -import jakarta.annotation.Resource; import org.springframework.stereotype.Service; import org.springframework.transaction.annotation.Transactional; import org.springframework.validation.annotation.Validated; +import javax.annotation.Resource; import java.math.BigDecimal; /** diff --git a/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/service/stock/ErpStockServiceImpl.java b/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/service/stock/ErpStockServiceImpl.java index 654117047..dabe36fb9 100644 --- a/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/service/stock/ErpStockServiceImpl.java +++ b/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/service/stock/ErpStockServiceImpl.java @@ -5,10 +5,10 @@ import cn.iocoder.yudao.module.erp.controller.admin.stock.vo.stock.ErpStockPageR import cn.iocoder.yudao.module.erp.dal.dataobject.stock.ErpStockDO; import cn.iocoder.yudao.module.erp.dal.mysql.stock.ErpStockMapper; import cn.iocoder.yudao.module.erp.service.product.ErpProductService; -import jakarta.annotation.Resource; import org.springframework.stereotype.Service; import org.springframework.validation.annotation.Validated; +import javax.annotation.Resource; import java.math.BigDecimal; import static cn.iocoder.yudao.framework.common.exception.util.ServiceExceptionUtil.exception; diff --git a/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/service/stock/ErpWarehouseService.java b/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/service/stock/ErpWarehouseService.java index 872a698de..01e8df682 100644 --- a/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/service/stock/ErpWarehouseService.java +++ b/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/service/stock/ErpWarehouseService.java @@ -4,8 +4,8 @@ import cn.iocoder.yudao.framework.common.pojo.PageResult; import cn.iocoder.yudao.module.erp.controller.admin.stock.vo.ErpWarehouseSaveReqVO; import cn.iocoder.yudao.module.erp.controller.admin.stock.vo.warehouse.ErpWarehousePageReqVO; import cn.iocoder.yudao.module.erp.dal.dataobject.stock.ErpWarehouseDO; -import jakarta.validation.Valid; +import javax.validation.Valid; import java.util.Collection; import java.util.List; import java.util.Map; diff --git a/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/service/stock/ErpWarehouseServiceImpl.java b/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/service/stock/ErpWarehouseServiceImpl.java index fb4829146..789209cba 100644 --- a/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/service/stock/ErpWarehouseServiceImpl.java +++ b/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/service/stock/ErpWarehouseServiceImpl.java @@ -6,14 +6,13 @@ import cn.iocoder.yudao.framework.common.pojo.PageResult; import cn.iocoder.yudao.framework.common.util.object.BeanUtils; import cn.iocoder.yudao.module.erp.controller.admin.stock.vo.ErpWarehouseSaveReqVO; import cn.iocoder.yudao.module.erp.controller.admin.stock.vo.warehouse.ErpWarehousePageReqVO; -import cn.iocoder.yudao.module.erp.dal.dataobject.product.ErpProductDO; import cn.iocoder.yudao.module.erp.dal.dataobject.stock.ErpWarehouseDO; import cn.iocoder.yudao.module.erp.dal.mysql.stock.ErpWarehouseMapper; -import jakarta.annotation.Resource; import org.springframework.stereotype.Service; import org.springframework.transaction.annotation.Transactional; import org.springframework.validation.annotation.Validated; +import javax.annotation.Resource; import java.util.Collection; import java.util.Collections; import java.util.List; @@ -21,7 +20,8 @@ import java.util.Map; import static cn.iocoder.yudao.framework.common.exception.util.ServiceExceptionUtil.exception; import static cn.iocoder.yudao.framework.common.util.collection.CollectionUtils.convertMap; -import static cn.iocoder.yudao.module.erp.enums.ErrorCodeConstants.*; +import static cn.iocoder.yudao.module.erp.enums.ErrorCodeConstants.WAREHOUSE_NOT_ENABLE; +import static cn.iocoder.yudao.module.erp.enums.ErrorCodeConstants.WAREHOUSE_NOT_EXISTS; /** * ERP 仓库 Service 实现类 diff --git a/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/service/stock/bo/ErpStockRecordCreateReqBO.java b/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/service/stock/bo/ErpStockRecordCreateReqBO.java index 7006f10b5..40c62a4ef 100644 --- a/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/service/stock/bo/ErpStockRecordCreateReqBO.java +++ b/yudao-module-erp/yudao-module-erp-biz/src/main/java/cn/iocoder/yudao/module/erp/service/stock/bo/ErpStockRecordCreateReqBO.java @@ -1,6 +1,6 @@ package cn.iocoder.yudao.module.erp.service.stock.bo; -import jakarta.validation.constraints.NotNull; +import javax.validation.constraints.NotNull; import lombok.AllArgsConstructor; import lombok.Data; import lombok.NoArgsConstructor; diff --git a/yudao-module-infra/yudao-module-infra-biz/src/main/java/cn/iocoder/yudao/module/infra/controller/admin/file/FileController.java b/yudao-module-infra/yudao-module-infra-biz/src/main/java/cn/iocoder/yudao/module/infra/controller/admin/file/FileController.java index 7e1dea2e8..34522b881 100644 --- a/yudao-module-infra/yudao-module-infra-biz/src/main/java/cn/iocoder/yudao/module/infra/controller/admin/file/FileController.java +++ b/yudao-module-infra/yudao-module-infra-biz/src/main/java/cn/iocoder/yudao/module/infra/controller/admin/file/FileController.java @@ -14,11 +14,6 @@ import cn.iocoder.yudao.module.infra.service.file.FileService; import io.swagger.v3.oas.annotations.Operation; import io.swagger.v3.oas.annotations.Parameter; import io.swagger.v3.oas.annotations.tags.Tag; -import jakarta.annotation.Resource; -import jakarta.annotation.security.PermitAll; -import jakarta.servlet.http.HttpServletRequest; -import jakarta.servlet.http.HttpServletResponse; -import jakarta.validation.Valid; import lombok.extern.slf4j.Slf4j; import org.springframework.http.HttpStatus; import org.springframework.security.access.prepost.PreAuthorize; @@ -26,6 +21,12 @@ import org.springframework.validation.annotation.Validated; import org.springframework.web.bind.annotation.*; import org.springframework.web.multipart.MultipartFile; +import javax.annotation.Resource; +import javax.annotation.security.PermitAll; +import javax.servlet.http.HttpServletRequest; +import javax.servlet.http.HttpServletResponse; +import javax.validation.Valid; + import static cn.iocoder.yudao.framework.common.pojo.CommonResult.success; @Tag(name = "管理后台 - 文件存储") diff --git a/yudao-module-infra/yudao-module-infra-biz/src/main/java/cn/iocoder/yudao/module/infra/controller/admin/file/vo/file/FileCreateReqVO.java b/yudao-module-infra/yudao-module-infra-biz/src/main/java/cn/iocoder/yudao/module/infra/controller/admin/file/vo/file/FileCreateReqVO.java index 5daa3972e..24976189b 100644 --- a/yudao-module-infra/yudao-module-infra-biz/src/main/java/cn/iocoder/yudao/module/infra/controller/admin/file/vo/file/FileCreateReqVO.java +++ b/yudao-module-infra/yudao-module-infra-biz/src/main/java/cn/iocoder/yudao/module/infra/controller/admin/file/vo/file/FileCreateReqVO.java @@ -1,9 +1,10 @@ package cn.iocoder.yudao.module.infra.controller.admin.file.vo.file; import io.swagger.v3.oas.annotations.media.Schema; -import jakarta.validation.constraints.NotNull; import lombok.Data; +import javax.validation.constraints.NotNull; + @Schema(description = "管理后台 - 文件创建 Request VO") @Data public class FileCreateReqVO { diff --git a/yudao-module-infra/yudao-module-infra-biz/src/main/java/cn/iocoder/yudao/module/infra/service/file/FileServiceImpl.java b/yudao-module-infra/yudao-module-infra-biz/src/main/java/cn/iocoder/yudao/module/infra/service/file/FileServiceImpl.java index f7c4b0b8e..05e38e957 100644 --- a/yudao-module-infra/yudao-module-infra-biz/src/main/java/cn/iocoder/yudao/module/infra/service/file/FileServiceImpl.java +++ b/yudao-module-infra/yudao-module-infra-biz/src/main/java/cn/iocoder/yudao/module/infra/service/file/FileServiceImpl.java @@ -13,10 +13,11 @@ import cn.iocoder.yudao.module.infra.controller.admin.file.vo.file.FilePageReqVO import cn.iocoder.yudao.module.infra.controller.admin.file.vo.file.FilePresignedUrlRespVO; import cn.iocoder.yudao.module.infra.dal.dataobject.file.FileDO; import cn.iocoder.yudao.module.infra.dal.mysql.file.FileMapper; -import jakarta.annotation.Resource; import lombok.SneakyThrows; import org.springframework.stereotype.Service; +import javax.annotation.Resource; + import static cn.iocoder.yudao.framework.common.exception.util.ServiceExceptionUtil.exception; import static cn.iocoder.yudao.module.infra.enums.ErrorCodeConstants.FILE_NOT_EXISTS; diff --git a/yudao-module-mall/yudao-module-product-biz/src/test/java/cn/iocoder/yudao/module/product/service/comment/ProductCommentServiceImplTest.java b/yudao-module-mall/yudao-module-product-biz/src/test/java/cn/iocoder/yudao/module/product/service/comment/ProductCommentServiceImplTest.java index 1b92e21f2..eefe1a6c2 100644 --- a/yudao-module-mall/yudao-module-product-biz/src/test/java/cn/iocoder/yudao/module/product/service/comment/ProductCommentServiceImplTest.java +++ b/yudao-module-mall/yudao-module-product-biz/src/test/java/cn/iocoder/yudao/module/product/service/comment/ProductCommentServiceImplTest.java @@ -15,13 +15,13 @@ import cn.iocoder.yudao.module.product.dal.mysql.comment.ProductCommentMapper; import cn.iocoder.yudao.module.product.enums.comment.ProductCommentScoresEnum; import cn.iocoder.yudao.module.product.service.sku.ProductSkuService; import cn.iocoder.yudao.module.product.service.spu.ProductSpuService; -import jakarta.annotation.Resource; import org.junit.jupiter.api.Disabled; import org.junit.jupiter.api.Test; import org.springframework.boot.test.mock.mockito.MockBean; import org.springframework.context.annotation.Import; import org.springframework.context.annotation.Lazy; +import javax.annotation.Resource; import java.time.LocalDateTime; import java.util.Date; diff --git a/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/controller/admin/notice/vo/NoticeSaveReqVO.java b/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/controller/admin/notice/vo/NoticeSaveReqVO.java index 78794ed71..200aadd92 100644 --- a/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/controller/admin/notice/vo/NoticeSaveReqVO.java +++ b/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/controller/admin/notice/vo/NoticeSaveReqVO.java @@ -3,9 +3,9 @@ package cn.iocoder.yudao.module.system.controller.admin.notice.vo; import io.swagger.v3.oas.annotations.media.Schema; import lombok.Data; -import jakarta.validation.constraints.NotBlank; -import jakarta.validation.constraints.NotNull; -import jakarta.validation.constraints.Size; +import javax.validation.constraints.NotBlank; +import javax.validation.constraints.NotNull; +import javax.validation.constraints.Size; @Schema(description = "管理后台 - 通知公告创建/修改 Request VO") @Data