From 8532db692ae580cce2ccee19be6713cb7a368bc6 Mon Sep 17 00:00:00 2001 From: gaoqr <13665037151@163.com> Date: Mon, 15 Sep 2025 16:47:42 +0800 Subject: [PATCH] =?UTF-8?q?1=E3=80=81=E6=96=B0=E5=A2=9E=E4=BA=A7=E5=93=81?= =?UTF-8?q?=E8=B4=AD=E4=B9=B0=E8=AE=B0=E5=BD=95=E5=BB=B6=E6=9C=9F=E3=80=81?= =?UTF-8?q?=E5=BB=B6=E6=9C=9F=E8=AE=B0=E5=BD=95=E5=88=86=E9=A1=B5/?= =?UTF-8?q?=E5=AF=BC=E5=87=BA=E6=8E=A5=E5=8F=A3=EF=BC=9B2=E3=80=81?= =?UTF-8?q?=E6=96=B0=E5=A2=9E=E7=BB=84=E7=BB=87=E5=88=97=E8=A1=A8=E9=99=84?= =?UTF-8?q?=E5=B8=A6=E8=B4=AD=E4=B9=B0=E8=AE=B0=E5=BD=95=E4=B8=AD=E7=9A=84?= =?UTF-8?q?=E5=BB=B6=E6=9C=9F=E6=97=B6=E9=95=BF=E4=BF=A1=E6=81=AF=EF=BC=9B?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../system/enums/ErrorCodeConstants.java | 3 +- .../vo/BalanceDetailsRespVO.java | 1 + .../funds/delay/ProductDelayController.java | 61 +++++++ .../funds/delay/vo/ProductDelayPageReqVO.java | 37 +++++ .../funds/delay/vo/ProductDelayRespVO.java | 57 +++++++ .../funds/delay/vo/ProductDelaySaveReqVO.java | 34 ++++ .../admin/organ/OrganController.java | 21 ++- .../vo/organ/OrganPagePurchaseRespVO.java | 5 +- .../funds/delay/ProductDelayRecordDO.java | 79 +++++++++ .../funds/delay/ProductDelayRecordMapper.java | 31 ++++ .../funds/delay/ProductDelayService.java | 40 +++++ .../funds/delay/ProductDelayServiceImpl.java | 154 ++++++++++++++++++ 12 files changed, 519 insertions(+), 4 deletions(-) create mode 100644 cf-module-system/cf-module-system-biz/src/main/java/com/cf/imes/module/system/controller/admin/funds/delay/ProductDelayController.java create mode 100644 cf-module-system/cf-module-system-biz/src/main/java/com/cf/imes/module/system/controller/admin/funds/delay/vo/ProductDelayPageReqVO.java create mode 100644 cf-module-system/cf-module-system-biz/src/main/java/com/cf/imes/module/system/controller/admin/funds/delay/vo/ProductDelayRespVO.java create mode 100644 cf-module-system/cf-module-system-biz/src/main/java/com/cf/imes/module/system/controller/admin/funds/delay/vo/ProductDelaySaveReqVO.java create mode 100644 cf-module-system/cf-module-system-biz/src/main/java/com/cf/imes/module/system/dal/dataobject/funds/delay/ProductDelayRecordDO.java create mode 100644 cf-module-system/cf-module-system-biz/src/main/java/com/cf/imes/module/system/dal/mysql/funds/delay/ProductDelayRecordMapper.java create mode 100644 cf-module-system/cf-module-system-biz/src/main/java/com/cf/imes/module/system/service/funds/delay/ProductDelayService.java create mode 100644 cf-module-system/cf-module-system-biz/src/main/java/com/cf/imes/module/system/service/funds/delay/ProductDelayServiceImpl.java diff --git a/cf-module-system/cf-module-system-api/src/main/java/com/cf/imes/module/system/enums/ErrorCodeConstants.java b/cf-module-system/cf-module-system-api/src/main/java/com/cf/imes/module/system/enums/ErrorCodeConstants.java index 9699201c6..e6b886a45 100644 --- a/cf-module-system/cf-module-system-api/src/main/java/com/cf/imes/module/system/enums/ErrorCodeConstants.java +++ b/cf-module-system/cf-module-system-api/src/main/java/com/cf/imes/module/system/enums/ErrorCodeConstants.java @@ -485,5 +485,6 @@ public class ErrorCodeConstants { public static final ErrorCode PARSER_NO_EXIST = new ErrorCode(1_002_044_001, "当前解析器不存在,请重新选择"); public static final ErrorCode PARSER_TEMPLATE_NO_EXIST = new ErrorCode(1_002_044_002, "当前解析器模板不存在,请重新选择"); - + //=========== 产品延期管理 1-002-049-000 ============ + public static final ErrorCode PRODUCT_PURCHASE_NO_EXIST = new ErrorCode(1_002_049_001, "当前购买记录不存在,请检查"); } diff --git a/cf-module-system/cf-module-system-biz/src/main/java/com/cf/imes/module/system/controller/admin/funds/balancedetails/vo/BalanceDetailsRespVO.java b/cf-module-system/cf-module-system-biz/src/main/java/com/cf/imes/module/system/controller/admin/funds/balancedetails/vo/BalanceDetailsRespVO.java index 6a9e512c1..1b32bed0e 100644 --- a/cf-module-system/cf-module-system-biz/src/main/java/com/cf/imes/module/system/controller/admin/funds/balancedetails/vo/BalanceDetailsRespVO.java +++ b/cf-module-system/cf-module-system-biz/src/main/java/com/cf/imes/module/system/controller/admin/funds/balancedetails/vo/BalanceDetailsRespVO.java @@ -12,6 +12,7 @@ import java.math.BigDecimal; import java.time.LocalDateTime; @Data +@Schema(description = "管理后台 - 组织账户明细 Response VO") public class BalanceDetailsRespVO { @Schema(description = "组织名称") diff --git a/cf-module-system/cf-module-system-biz/src/main/java/com/cf/imes/module/system/controller/admin/funds/delay/ProductDelayController.java b/cf-module-system/cf-module-system-biz/src/main/java/com/cf/imes/module/system/controller/admin/funds/delay/ProductDelayController.java new file mode 100644 index 000000000..389b97c3d --- /dev/null +++ b/cf-module-system/cf-module-system-biz/src/main/java/com/cf/imes/module/system/controller/admin/funds/delay/ProductDelayController.java @@ -0,0 +1,61 @@ +package com.cf.imes.module.system.controller.admin.funds.delay; + +import com.cf.imes.framework.common.pojo.CommonResult; +import com.cf.imes.framework.common.pojo.PageParam; +import com.cf.imes.framework.common.pojo.PageResult; +import com.cf.imes.framework.excel.core.util.ExcelUtils; +import com.cf.imes.module.system.controller.admin.funds.delay.vo.ProductDelayPageReqVO; +import com.cf.imes.module.system.controller.admin.funds.delay.vo.ProductDelayRespVO; +import com.cf.imes.module.system.controller.admin.funds.delay.vo.ProductDelaySaveReqVO; +import com.cf.imes.module.system.service.funds.delay.ProductDelayService; +import io.swagger.v3.oas.annotations.Operation; +import io.swagger.v3.oas.annotations.tags.Tag; +import jakarta.annotation.Resource; +import jakarta.servlet.http.HttpServletResponse; +import jakarta.validation.Valid; +import org.springframework.validation.annotation.Validated; +import org.springframework.web.bind.annotation.GetMapping; +import org.springframework.web.bind.annotation.PutMapping; +import org.springframework.web.bind.annotation.RequestBody; +import org.springframework.web.bind.annotation.RequestMapping; +import org.springframework.web.bind.annotation.RestController; + +import java.io.IOException; +import java.util.List; + +import static com.cf.imes.framework.common.pojo.CommonResult.success; + +/** + * @author Gqr + * @since 2025/9/15 11:18 + */ +@Tag(name = "管理后台 - 产品延期管理") +@RestController +@RequestMapping("/system/product/delay") +@Validated +public class ProductDelayController { + @Resource + private ProductDelayService productDelayService; + + @PutMapping() + @Operation(summary = "新增组织延期") + public CommonResult createProductDelay(@RequestBody @Valid ProductDelaySaveReqVO productDelaySaveReqVO){ + return success(productDelayService.createProductDelay(productDelaySaveReqVO)); + } + + @GetMapping("/page") + @Operation(summary = "获取组织延期记录分页") + public CommonResult> getProductDelayPage(@Valid ProductDelayPageReqVO pageReqVO) { + return success(productDelayService.getPage(pageReqVO)); + } + + @GetMapping("/export") + @Operation(summary = "导出组织延期记录") + public void exportProductDelay(@Valid ProductDelayPageReqVO pageReqVO, + HttpServletResponse response) throws IOException { + pageReqVO.setPageSize(PageParam.PAGE_SIZE_NONE); + List list = productDelayService.getPage(pageReqVO).getList(); + // 导出 Excel + ExcelUtils.write(response, "延期记录表.xls", "数据", ProductDelayRespVO.class, list); + } +} diff --git a/cf-module-system/cf-module-system-biz/src/main/java/com/cf/imes/module/system/controller/admin/funds/delay/vo/ProductDelayPageReqVO.java b/cf-module-system/cf-module-system-biz/src/main/java/com/cf/imes/module/system/controller/admin/funds/delay/vo/ProductDelayPageReqVO.java new file mode 100644 index 000000000..7c8cdf2f8 --- /dev/null +++ b/cf-module-system/cf-module-system-biz/src/main/java/com/cf/imes/module/system/controller/admin/funds/delay/vo/ProductDelayPageReqVO.java @@ -0,0 +1,37 @@ +package com.cf.imes.module.system.controller.admin.funds.delay.vo; + +import com.cf.imes.framework.common.pojo.PageParam; +import io.swagger.v3.oas.annotations.media.Schema; +import jakarta.validation.constraints.Size; +import lombok.Data; +import lombok.EqualsAndHashCode; +import lombok.ToString; + +import java.time.LocalDate; + +/** + * @author Gqr + * @since 2025/9/15 14:36 + */ +@Schema(description = "管理后台 - 产品延期记录分页 Request VO") +@Data +@EqualsAndHashCode(callSuper = true) +@ToString(callSuper = true) +public class ProductDelayPageReqVO extends PageParam { + @Schema(description = "组织编号") + private Long organId; + + @Schema(description = "产品名称") + @Size(max = 64, message = "产品名称长度不能超过64个字符") + private String productName; + + @Schema(description = "延期时长") + private Integer delayDuration; + + @Schema(description = "操作时间") + private LocalDate[] createTime; + + @Schema(description = "操作人") + @Size(max = 64, message = "操作人长度不能超过64个字符") + private String operator; +} diff --git a/cf-module-system/cf-module-system-biz/src/main/java/com/cf/imes/module/system/controller/admin/funds/delay/vo/ProductDelayRespVO.java b/cf-module-system/cf-module-system-biz/src/main/java/com/cf/imes/module/system/controller/admin/funds/delay/vo/ProductDelayRespVO.java new file mode 100644 index 000000000..086e67d2c --- /dev/null +++ b/cf-module-system/cf-module-system-biz/src/main/java/com/cf/imes/module/system/controller/admin/funds/delay/vo/ProductDelayRespVO.java @@ -0,0 +1,57 @@ +package com.cf.imes.module.system.controller.admin.funds.delay.vo; + +import com.alibaba.excel.annotation.ExcelProperty; +import com.cf.imes.framework.excel.core.annotations.EnumFormat; +import com.cf.imes.framework.excel.core.convert.EnumConvert; +import com.cf.imes.module.system.enums.pay.DurationUnitEnum; +import com.fasterxml.jackson.annotation.JsonFormat; +import io.swagger.v3.oas.annotations.media.Schema; +import lombok.Data; + +import java.time.LocalDate; +import java.time.LocalDateTime; + +import static com.cf.imes.framework.common.util.date.DateUtils.FORMAT_YEAR_MONTH_DAY; +import static com.cf.imes.framework.common.util.date.DateUtils.TIME_ZONE_DEFAULT; + +/** + * @author Gqr + * @since 2025/9/15 14:45 + */ +@Data +@Schema(description = "管理后台 - 组织账户明细 Response VO") +public class ProductDelayRespVO { + @Schema(description = "组织名称") + @ExcelProperty("组织名称") + private String organName; + + @Schema(description = "产品名称") + @ExcelProperty("产品名称") + private String productName; + + @Schema(description = "延期时长") + @ExcelProperty("延期时长") + private Integer delayDuration; + + @Schema(description = "延期时长单位") + @ExcelProperty(value = "延期时长单位", converter = EnumConvert.class) + @EnumFormat(value = DurationUnitEnum.class) + private Integer delayDurationUnit; + + @Schema(description = "产品有效时间") + @ExcelProperty("产品有效时间") + @JsonFormat(pattern = FORMAT_YEAR_MONTH_DAY, timezone = TIME_ZONE_DEFAULT) + private LocalDate delayTime; + + @Schema(description = "备注") + @ExcelProperty("备注") + private String remark; + + @Schema(description = "操作时间") + @ExcelProperty("操作时间") + private LocalDateTime createTime; + + @Schema(description = "操作人") + @ExcelProperty("操作人") + private String creator; +} diff --git a/cf-module-system/cf-module-system-biz/src/main/java/com/cf/imes/module/system/controller/admin/funds/delay/vo/ProductDelaySaveReqVO.java b/cf-module-system/cf-module-system-biz/src/main/java/com/cf/imes/module/system/controller/admin/funds/delay/vo/ProductDelaySaveReqVO.java new file mode 100644 index 000000000..7fce30ab6 --- /dev/null +++ b/cf-module-system/cf-module-system-biz/src/main/java/com/cf/imes/module/system/controller/admin/funds/delay/vo/ProductDelaySaveReqVO.java @@ -0,0 +1,34 @@ +package com.cf.imes.module.system.controller.admin.funds.delay.vo; + +import com.cf.imes.module.system.validation.products.DurationUnitValid; +import io.swagger.v3.oas.annotations.media.Schema; +import jakarta.validation.constraints.NotNull; +import jakarta.validation.constraints.Size; +import lombok.Data; + +/** + * @author Gqr + * @since 2025/9/15 11:25 + */ +@Schema(description = "管理后台 - 产品延期创建 Request VO") +@Data +public class ProductDelaySaveReqVO { + @Schema(description = "组织编号") + @NotNull(message = "组织编号不能为空") + private Long organId; + + @Schema(description = "购买记录编号") + @NotNull(message = "购买记录编号不能为空") + private Long purchaseId; + + @Schema(description = "延期时长", requiredMode = Schema.RequiredMode.REQUIRED, example = "1") + private Integer delayDuration; + + @Schema(description = "延期时长单位,0:年、1:月、2:日", example = "1") + @DurationUnitValid + private Integer delayDurationUnit; + + @Schema(description = "备注") + @Size(max = 1024, message = "备注不能超过1024个字符") + private String remark; +} diff --git a/cf-module-system/cf-module-system-biz/src/main/java/com/cf/imes/module/system/controller/admin/organ/OrganController.java b/cf-module-system/cf-module-system-biz/src/main/java/com/cf/imes/module/system/controller/admin/organ/OrganController.java index 04516e797..fdf7cf46e 100644 --- a/cf-module-system/cf-module-system-biz/src/main/java/com/cf/imes/module/system/controller/admin/organ/OrganController.java +++ b/cf-module-system/cf-module-system-biz/src/main/java/com/cf/imes/module/system/controller/admin/organ/OrganController.java @@ -9,11 +9,14 @@ import com.cf.imes.framework.common.util.object.BeanUtils; import com.cf.imes.framework.excel.core.util.ExcelUtils; import com.cf.imes.framework.operatelog.core.annotations.OperateLog; import com.cf.imes.module.system.api.user.dto.OrganAdminUserRespDTO; +import com.cf.imes.module.system.controller.admin.funds.delay.vo.ProductDelayRespVO; import com.cf.imes.module.system.controller.admin.organ.vo.organ.*; import com.cf.imes.module.system.dal.dataobject.funds.purchase.PurchaseRecordDO; import com.cf.imes.module.system.dal.dataobject.organ.OrganizationDO; import com.cf.imes.module.system.dal.dataobject.organ.TenantPackageDO; import com.cf.imes.module.system.dal.mysql.organ.TenantPackageMapper; +import com.cf.imes.module.system.enums.pay.DurationUnitEnum; +import com.cf.imes.module.system.service.funds.delay.ProductDelayService; import com.cf.imes.module.system.service.funds.purchase.PurchaseService; import com.cf.imes.module.system.service.organ.OrganService; import com.cf.imes.module.system.service.user.AdminUserService; @@ -54,6 +57,9 @@ public class OrganController { @Resource private PurchaseService purchaseService; + @Resource + private ProductDelayService productDelayService; + @GetMapping("/get-id-by-name") @PermitAll @Operation(summary = "使用组织名,获得组织编号", description = "登录界面,根据用户的组织名,获得组织编号") @@ -130,10 +136,21 @@ public class OrganController { List orgPurchaseList = purchaseService.getOrgPurchaseList(organIds); // 匹配到对应的组织下 bean.getList().forEach(e -> { - e.setOrganPurchaseList(orgPurchaseList.stream() + List purchaseRespVOList = orgPurchaseList.stream() .filter(f -> Objects.equals(f.getOrganId(), e.getId())) .map(m -> BeanUtils.toBean(m, OrganPagePurchaseRespVO.class)) - .toList()); + .toList(); + // 查询购买记录下的延期记录 + purchaseRespVOList.forEach(p -> { + List delayRecordsByPurchaseId = productDelayService.getRecordsByPurchaseId(p.getId(), e.getId()); + if (CollUtil.isNotEmpty(delayRecordsByPurchaseId)) { + // 产品有效时间展示为第一项的计算延期时间 + p.setEndTime(delayRecordsByPurchaseId.get(0).getDelayTime()); + // 延期时长展示为延期记录的时长+单位,用顿号分隔 + p.setDelayDuration(delayRecordsByPurchaseId.stream().map(m -> m.getDelayDuration() + DurationUnitEnum.getDesc(m.getDelayDurationUnit())).collect(Collectors.joining("、"))); + } + }); + e.setOrganPurchaseList(purchaseRespVOList); }); return success(bean); } diff --git a/cf-module-system/cf-module-system-biz/src/main/java/com/cf/imes/module/system/controller/admin/organ/vo/organ/OrganPagePurchaseRespVO.java b/cf-module-system/cf-module-system-biz/src/main/java/com/cf/imes/module/system/controller/admin/organ/vo/organ/OrganPagePurchaseRespVO.java index 696e36bca..c2b302485 100644 --- a/cf-module-system/cf-module-system-biz/src/main/java/com/cf/imes/module/system/controller/admin/organ/vo/organ/OrganPagePurchaseRespVO.java +++ b/cf-module-system/cf-module-system-biz/src/main/java/com/cf/imes/module/system/controller/admin/organ/vo/organ/OrganPagePurchaseRespVO.java @@ -37,7 +37,10 @@ public class OrganPagePurchaseRespVO { @Schema(description = "订单总额") private BigDecimal totalAmount; - @Schema(description = "失效时间") + @Schema(description = "产品延期时长") + private String delayDuration; + + @Schema(description = "产品有效时间") @JsonFormat(pattern = FORMAT_YEAR_MONTH_DAY) private LocalDate endTime; diff --git a/cf-module-system/cf-module-system-biz/src/main/java/com/cf/imes/module/system/dal/dataobject/funds/delay/ProductDelayRecordDO.java b/cf-module-system/cf-module-system-biz/src/main/java/com/cf/imes/module/system/dal/dataobject/funds/delay/ProductDelayRecordDO.java new file mode 100644 index 000000000..0eb1d2045 --- /dev/null +++ b/cf-module-system/cf-module-system-biz/src/main/java/com/cf/imes/module/system/dal/dataobject/funds/delay/ProductDelayRecordDO.java @@ -0,0 +1,79 @@ +package com.cf.imes.module.system.dal.dataobject.funds.delay; + +import com.baomidou.mybatisplus.annotation.KeySequence; +import com.baomidou.mybatisplus.annotation.TableName; +import com.cf.imes.framework.mybatis.core.dataobject.BaseDO; +import lombok.AllArgsConstructor; +import lombok.Builder; +import lombok.Data; +import lombok.EqualsAndHashCode; +import lombok.NoArgsConstructor; +import lombok.ToString; + +import java.time.LocalDate; + +/** + * 产品延期记录product_delay_record DO + * + * @author Gqr + * @since 2025/9/15 11:11 + */ +@TableName(value = "product_delay_record") +@KeySequence("product_delay_record_seq") // 用于 Oracle、PostgreSQL、Kingbase、DB2、H2 数据库的主键自增。如果是 MySQL 等数据库,可不写。 +@Data +@EqualsAndHashCode(callSuper = true) +@ToString(callSuper = true) +@Builder +@NoArgsConstructor +@AllArgsConstructor +public class ProductDelayRecordDO extends BaseDO { + /** + * 主键,自增 + */ + private Long id; + + /** + * 组织ID + */ + private Long organId; + + /** + * 组织名称 + */ + private String organName; + + /** + * 产品名称 + */ + private String productName; + + /** + * 延期时长 + */ + private Integer delayDuration; + + /** + * 延期时长单位 + */ + private Integer delayDurationUnit; + + /** + * 产品结束时间 + */ + private LocalDate endTime; + + /** + * 延期后有效时长 + */ + private LocalDate delayTime; + + /** + * 购买记录单号 + */ + private Long purchaseId; + + /** + * 备注 + */ + private String remark; +} diff --git a/cf-module-system/cf-module-system-biz/src/main/java/com/cf/imes/module/system/dal/mysql/funds/delay/ProductDelayRecordMapper.java b/cf-module-system/cf-module-system-biz/src/main/java/com/cf/imes/module/system/dal/mysql/funds/delay/ProductDelayRecordMapper.java new file mode 100644 index 000000000..fdd08768a --- /dev/null +++ b/cf-module-system/cf-module-system-biz/src/main/java/com/cf/imes/module/system/dal/mysql/funds/delay/ProductDelayRecordMapper.java @@ -0,0 +1,31 @@ +package com.cf.imes.module.system.dal.mysql.funds.delay; + +import com.cf.imes.framework.common.pojo.PageResult; +import com.cf.imes.framework.mybatis.core.mapper.BaseMapperX; +import com.cf.imes.framework.mybatis.core.query.LambdaQueryWrapperX; +import com.cf.imes.module.system.controller.admin.funds.delay.vo.ProductDelayPageReqVO; +import com.cf.imes.module.system.dal.dataobject.funds.delay.ProductDelayRecordDO; +import org.apache.ibatis.annotations.Mapper; + +/** + * 产品延期记录 Mapper + * + * @author Gqr + * @since 2025/9/15 11:14 + */ +@Mapper +public interface ProductDelayRecordMapper extends BaseMapperX { + /** + * 分页查询延期记录 + * @param pageReqVO + * @return + */ + default PageResult selectPage(ProductDelayPageReqVO pageReqVO) { + return selectPage(pageReqVO, new LambdaQueryWrapperX() + .eqIfPresent(ProductDelayRecordDO::getOrganId, pageReqVO.getOrganId()) + .eqIfPresent(ProductDelayRecordDO::getProductName, pageReqVO.getProductName()) + .eqIfPresent(ProductDelayRecordDO::getDelayDuration, pageReqVO.getDelayDuration()) + .betweenIfPresent(ProductDelayRecordDO::getCreateTime, pageReqVO.getCreateTime()) + .eqIfPresent(ProductDelayRecordDO::getCreator, pageReqVO.getOperator())); + } +} diff --git a/cf-module-system/cf-module-system-biz/src/main/java/com/cf/imes/module/system/service/funds/delay/ProductDelayService.java b/cf-module-system/cf-module-system-biz/src/main/java/com/cf/imes/module/system/service/funds/delay/ProductDelayService.java new file mode 100644 index 000000000..bf3c15eb7 --- /dev/null +++ b/cf-module-system/cf-module-system-biz/src/main/java/com/cf/imes/module/system/service/funds/delay/ProductDelayService.java @@ -0,0 +1,40 @@ +package com.cf.imes.module.system.service.funds.delay; + +import com.cf.imes.framework.common.pojo.PageResult; +import com.cf.imes.module.system.controller.admin.funds.delay.vo.ProductDelayPageReqVO; +import com.cf.imes.module.system.controller.admin.funds.delay.vo.ProductDelayRespVO; +import com.cf.imes.module.system.controller.admin.funds.delay.vo.ProductDelaySaveReqVO; + +import java.util.List; + +/** + * 产品延期 Service + * + * @author Gqr + * @since 2025/9/15 11:21 + */ +public interface ProductDelayService { + /** + * 创建产品延期 + * + * @param productDelaySaveReqVO + */ + Long createProductDelay(ProductDelaySaveReqVO productDelaySaveReqVO); + + /** + * 获取组织产品延期分页 + * + * @param pageReqVO + * @return + */ + PageResult getPage(ProductDelayPageReqVO pageReqVO); + + /** + * 查询购买记录下的延期记录 + * + * @param purchaseId + * @param organId + * @return + */ + List getRecordsByPurchaseId(Long purchaseId, Long organId); +} diff --git a/cf-module-system/cf-module-system-biz/src/main/java/com/cf/imes/module/system/service/funds/delay/ProductDelayServiceImpl.java b/cf-module-system/cf-module-system-biz/src/main/java/com/cf/imes/module/system/service/funds/delay/ProductDelayServiceImpl.java new file mode 100644 index 000000000..8efaee9a1 --- /dev/null +++ b/cf-module-system/cf-module-system-biz/src/main/java/com/cf/imes/module/system/service/funds/delay/ProductDelayServiceImpl.java @@ -0,0 +1,154 @@ +package com.cf.imes.module.system.service.funds.delay; + +import cn.hutool.core.bean.BeanUtil; +import cn.hutool.core.util.ObjectUtil; +import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper; +import com.cf.imes.framework.common.pojo.PageResult; +import com.cf.imes.framework.common.util.Assert.AssertUtils; +import com.cf.imes.framework.common.util.object.BeanUtils; +import com.cf.imes.module.system.controller.admin.funds.delay.ProductDelayController; +import com.cf.imes.module.system.controller.admin.funds.delay.vo.ProductDelayPageReqVO; +import com.cf.imes.module.system.controller.admin.funds.delay.vo.ProductDelayRespVO; +import com.cf.imes.module.system.controller.admin.funds.delay.vo.ProductDelaySaveReqVO; +import com.cf.imes.module.system.dal.dataobject.funds.delay.ProductDelayRecordDO; +import com.cf.imes.module.system.dal.dataobject.funds.purchase.PurchaseRecordDO; +import com.cf.imes.module.system.dal.dataobject.organ.OrganizationDO; +import com.cf.imes.module.system.dal.mysql.funds.delay.ProductDelayRecordMapper; +import com.cf.imes.module.system.enums.pay.DurationUnitEnum; +import com.cf.imes.module.system.service.funds.products.ProductsDetailService; +import com.cf.imes.module.system.service.funds.purchase.PurchaseService; +import com.cf.imes.module.system.service.organ.OrganService; +import jakarta.annotation.Resource; +import org.springframework.beans.factory.annotation.Autowired; +import org.springframework.stereotype.Service; + +import java.time.LocalDate; +import java.util.List; + +import static com.cf.imes.module.system.enums.ErrorCodeConstants.PRODUCT_PURCHASE_NO_EXIST; + +/** + * 产品延期 ServiceImpl 实现类 + * + * @author Gqr + * @since 2025/9/15 11:22 + */ +@Service +public class ProductDelayServiceImpl implements ProductDelayService { + @Resource + private OrganService organService; + + @Resource + private PurchaseService purchaseService; + + @Resource + private ProductsDetailService productsDetailService; + + @Resource + private ProductDelayRecordMapper productDelayRecordMapper; + @Autowired + private ProductDelayController productDelayController; + + @Override + public Long createProductDelay(ProductDelaySaveReqVO productDelaySaveReqVO) { + Long organId = productDelaySaveReqVO.getOrganId(); + // 校验组织 + OrganizationDO organizationDO = organService.validOrgan(organId); + + // 获取产品购买记录 + Long purchaseId = productDelaySaveReqVO.getPurchaseId(); + PurchaseRecordDO purchaseRecordDO = purchaseService.getRecord(purchaseId); + AssertUtils.notEmpty(purchaseRecordDO, PRODUCT_PURCHASE_NO_EXIST); + + // 校验产品和定价规则 + productsDetailService.validateProductExist(purchaseRecordDO.getProductId()); + productsDetailService.validateProductDetailsExists(purchaseRecordDO.getProductDetailsId()); + + /** + * 查询是否有前序的延期记录: + * 1、如果有记录,延期有效期在其记录上叠加 + * 2、如果没有记录,取购买记录的结束时间作为延期的开始时间 + */ + ProductDelayRecordDO lastDelayRecordDO = productDelayRecordMapper.selectOne(new LambdaQueryWrapper() + .eq(ProductDelayRecordDO::getOrganId, organId) + .orderByDesc(ProductDelayRecordDO::getCreateTime) + .last("limit 1")); + + Integer delayDuration = productDelaySaveReqVO.getDelayDuration(); + Integer delayDurationUnit = productDelaySaveReqVO.getDelayDurationUnit(); + LocalDate endTime; + if(ObjectUtil.isNotNull(lastDelayRecordDO)) { + endTime = lastDelayRecordDO.getDelayTime(); + } else { + endTime = purchaseRecordDO.getEndTime(); + } + + // 计算延期后有效时间 + LocalDate delayTime = calculateEndTime(endTime, delayDuration, delayDurationUnit); + // 创建延期记录 + ProductDelayRecordDO productDelayRecordDO = ProductDelayRecordDO.builder() + .organId(organId) + .organName(organizationDO.getName()) + .productName(purchaseRecordDO.getProductName()) + .delayDuration(delayDuration) + .delayDurationUnit(delayDurationUnit) + .endTime(endTime) + .delayTime(delayTime) + .purchaseId(purchaseId) + .build(); + productDelayRecordMapper.insert(productDelayRecordDO); + return productDelayRecordDO.getId(); + } + + /** + * 计算延期时间 + * + * @param startTime + * @param duration + * @param durationUnit + * @return + */ + private static LocalDate calculateEndTime(LocalDate startTime, Integer duration, Integer durationUnit) { + if (ObjectUtil.isNotNull(duration) && ObjectUtil.isNotNull(durationUnit)) { + startTime = addTime(startTime, duration, durationUnit); + } + + return startTime; + } + + /** + * 基于时长和单位累加time + * + * @param time + * @param duration + * @param unit + * @return + */ + private static LocalDate addTime(LocalDate time, int duration, int unit) { + switch (DurationUnitEnum.fromStatus(unit)) { + case YEAR: + return time.plusYears(duration); + case MONTH: + return time.plusMonths(duration); + case DAY: + return time.plusDays(duration); + default: + return time; + } + } + + @Override + public PageResult getPage(ProductDelayPageReqVO pageReqVO) { + PageResult productDelayRecordDOPageResult = productDelayRecordMapper.selectPage(pageReqVO); + return new PageResult<>(BeanUtils.toBean(productDelayRecordDOPageResult.getList(), ProductDelayRespVO.class), productDelayRecordDOPageResult.getTotal()); + } + + @Override + public List getRecordsByPurchaseId(Long purchaseId, Long organId) { + return BeanUtil.copyToList(productDelayRecordMapper.selectList(new LambdaQueryWrapper() + .eq(ProductDelayRecordDO::getPurchaseId, purchaseId) + .eq(ProductDelayRecordDO::getOrganId, organId) + .orderByDesc(ProductDelayRecordDO::getId) + .select(ProductDelayRecordDO::getDelayDuration, ProductDelayRecordDO::getDelayDurationUnit, ProductDelayRecordDO::getDelayTime)), ProductDelayRespVO.class); + } +}