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 7e9579067..5fe9fdef6 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 @@ -474,6 +474,7 @@ public class ErrorCodeConstants { public static final ErrorCode RECHARGE_ACTIVE_NO_EXIST = new ErrorCode(1_002_045_010, "当前赠送金活动不存在"); public static final ErrorCode PRODUCTS_DETAIL_DURATION_UNIT_NOT_SUPPORT = new ErrorCode(1_002_045_011, "不支持的时长单位,请检查该定价规则的时长单位"); public static final ErrorCode ORG_PRODUCT_PURCHASE_WAIT_PAY_ERROR = new ErrorCode(1_002_045_012, "组织下存在当前产品的待支付记录,请确认或取消支付后再次发起软件购买"); + public static final ErrorCode PRODUCT_PRICE_NULL_ERROR = new ErrorCode(1_002_045_013, "产品建议价格为空,请联系客服"); //=========== 广告相关 1-002-046-000 ============ public static final ErrorCode ADVERTISEMENT_POSITION_NO_EXIST = new ErrorCode(1_002_046_001, "广告所选放置位置不存在"); diff --git a/cf-module-system/cf-module-system-biz/src/main/java/com/cf/imes/module/system/controller/admin/funds/products/ProductsController.java b/cf-module-system/cf-module-system-biz/src/main/java/com/cf/imes/module/system/controller/admin/funds/products/ProductsController.java index 68760a72d..b6c95683b 100644 --- a/cf-module-system/cf-module-system-biz/src/main/java/com/cf/imes/module/system/controller/admin/funds/products/ProductsController.java +++ b/cf-module-system/cf-module-system-biz/src/main/java/com/cf/imes/module/system/controller/admin/funds/products/ProductsController.java @@ -33,31 +33,30 @@ public class ProductsController { @PutMapping("") @Operation(summary = "新建产品") - public CommonResult createProducts(@RequestParam("productName") String productName) { - return success(productsService.create(productName)); + public CommonResult createProducts(@Valid @RequestBody ProductSaveReqVO updateReqVO) { + return success(productsService.create(updateReqVO)); } @PostMapping("") @Operation(summary = "更新产品") public CommonResult updateProducts(@Valid @RequestBody ProductSaveReqVO updateReqVO) { - ProductsDO productsDO = BeanUtils.toBean(updateReqVO, ProductsDO.class); - productsService.update(productsDO); + productsService.update(updateReqVO); return success(true); } @PostMapping("/freeze") @Operation(summary = "下架产品") public CommonResult freezeProducts(@Valid Long id) { - ProductsDO productsDO = new ProductsDO().setId(id).setStatus(ProductStatusEnum.PRODUCT_DELIS.getStatus()); - productsService.update(productsDO); + ProductSaveReqVO updateReqVO = new ProductSaveReqVO().setId(id).setStatus(ProductStatusEnum.PRODUCT_DELIS.getStatus()); + productsService.update(updateReqVO); return success(true); } @PostMapping("/melt") @Operation(summary = "上架产品") public CommonResult meltProducts(@Valid Long id) { - ProductsDO productsDO = new ProductsDO().setId(id).setStatus(ProductStatusEnum.PRODUCT_UPDATES.getStatus()); - productsService.update(productsDO); + ProductSaveReqVO updateReqVO = new ProductSaveReqVO().setId(id).setStatus(ProductStatusEnum.PRODUCT_UPDATES.getStatus()); + productsService.update(updateReqVO); return success(true); } diff --git a/cf-module-system/cf-module-system-biz/src/main/java/com/cf/imes/module/system/controller/admin/funds/products/ProductsDetailController.java b/cf-module-system/cf-module-system-biz/src/main/java/com/cf/imes/module/system/controller/admin/funds/products/ProductsDetailController.java index 651511a7a..af6ab6dea 100644 --- a/cf-module-system/cf-module-system-biz/src/main/java/com/cf/imes/module/system/controller/admin/funds/products/ProductsDetailController.java +++ b/cf-module-system/cf-module-system-biz/src/main/java/com/cf/imes/module/system/controller/admin/funds/products/ProductsDetailController.java @@ -74,8 +74,8 @@ public class ProductsDetailController { @Parameter(name = "organId", description = "组织编号", required = true, example = "1") @Parameter(name = "productId", description = "产品编号", required = true, example = "1") public CommonResult> getOrgProductDetailList(@RequestParam("organId") Long organId, @RequestParam("productId") Long productId) { - List pageResult = purchaseService.getOrgProductDetailList(organId, productId); - return success(BeanUtils.toBean(pageResult, ProductDetailsRespVO.class)); + List pageResult = purchaseService.getOrgProductDetailList(organId, productId); + return success(pageResult); } } diff --git a/cf-module-system/cf-module-system-biz/src/main/java/com/cf/imes/module/system/controller/admin/funds/products/vo/product/ProductRespVO.java b/cf-module-system/cf-module-system-biz/src/main/java/com/cf/imes/module/system/controller/admin/funds/products/vo/product/ProductRespVO.java index bbb8a5fec..bf996ce47 100644 --- a/cf-module-system/cf-module-system-biz/src/main/java/com/cf/imes/module/system/controller/admin/funds/products/vo/product/ProductRespVO.java +++ b/cf-module-system/cf-module-system-biz/src/main/java/com/cf/imes/module/system/controller/admin/funds/products/vo/product/ProductRespVO.java @@ -6,6 +6,7 @@ import com.cf.imes.module.system.validation.products.ProductStatus; import io.swagger.v3.oas.annotations.media.Schema; import lombok.Data; +import java.math.BigDecimal; import java.time.LocalDateTime; @Schema(description = "管理后台 - 产品表 products Response VO") @@ -34,4 +35,7 @@ public class ProductRespVO { @ExcelProperty("编辑时间") private LocalDateTime updateTime; + @Schema(description = "建议价格") + @ExcelProperty("建议价格") + private BigDecimal price; } diff --git a/cf-module-system/cf-module-system-biz/src/main/java/com/cf/imes/module/system/controller/admin/funds/products/vo/product/ProductSaveReqVO.java b/cf-module-system/cf-module-system-biz/src/main/java/com/cf/imes/module/system/controller/admin/funds/products/vo/product/ProductSaveReqVO.java index d4a6b9515..4c90b965c 100644 --- a/cf-module-system/cf-module-system-biz/src/main/java/com/cf/imes/module/system/controller/admin/funds/products/vo/product/ProductSaveReqVO.java +++ b/cf-module-system/cf-module-system-biz/src/main/java/com/cf/imes/module/system/controller/admin/funds/products/vo/product/ProductSaveReqVO.java @@ -2,11 +2,17 @@ package com.cf.imes.module.system.controller.admin.funds.products.vo.product; import com.cf.imes.module.system.validation.products.ProductStatus; import io.swagger.v3.oas.annotations.media.Schema; +import jakarta.validation.constraints.DecimalMax; +import jakarta.validation.constraints.DecimalMin; +import jakarta.validation.constraints.Digits; +import jakarta.validation.constraints.NotNull; import jakarta.validation.constraints.Size; import lombok.Data; import jakarta.validation.constraints.NotEmpty; +import java.math.BigDecimal; + @Schema(description = "管理后台 - 产品表 product新增/修改 Request VO") @Data public class ProductSaveReqVO { @@ -19,6 +25,13 @@ public class ProductSaveReqVO { @Size(max = 64, message = "产品名称长度不能超过64") private String productName; + @Schema(description = "产品建议价格") + @NotNull(message = "产品建议价格不能为空") + @DecimalMin(value = "0.01", message = "产品建议价格必须大于零") + @DecimalMax(value = "100000", message = "产品建议价格不能超过十万") + @Digits(integer = 6, fraction = 2, message = "产品建议价格格式不正确") + private BigDecimal price; + @Schema(description = "产品状态", requiredMode = Schema.RequiredMode.REQUIRED) @ProductStatus private Integer status; diff --git a/cf-module-system/cf-module-system-biz/src/main/java/com/cf/imes/module/system/controller/admin/funds/products/vo/productDetails/ProductDetailsRespVO.java b/cf-module-system/cf-module-system-biz/src/main/java/com/cf/imes/module/system/controller/admin/funds/products/vo/productDetails/ProductDetailsRespVO.java index 8487c7511..00369f3d4 100644 --- a/cf-module-system/cf-module-system-biz/src/main/java/com/cf/imes/module/system/controller/admin/funds/products/vo/productDetails/ProductDetailsRespVO.java +++ b/cf-module-system/cf-module-system-biz/src/main/java/com/cf/imes/module/system/controller/admin/funds/products/vo/productDetails/ProductDetailsRespVO.java @@ -25,7 +25,7 @@ public class ProductDetailsRespVO { private Integer purchaseType; @Schema(description = "购买时长", requiredMode = Schema.RequiredMode.REQUIRED, example = "1") - private String duration; + private Integer duration; @Schema(description = "产品时长单位,0:年、1:月", example = "1") private Integer durationUnit; diff --git a/cf-module-system/cf-module-system-biz/src/main/java/com/cf/imes/module/system/controller/admin/funds/products/vo/productDetails/ProductDetailsSaveReqVO.java b/cf-module-system/cf-module-system-biz/src/main/java/com/cf/imes/module/system/controller/admin/funds/products/vo/productDetails/ProductDetailsSaveReqVO.java index 5e4011988..11b808fa3 100644 --- a/cf-module-system/cf-module-system-biz/src/main/java/com/cf/imes/module/system/controller/admin/funds/products/vo/productDetails/ProductDetailsSaveReqVO.java +++ b/cf-module-system/cf-module-system-biz/src/main/java/com/cf/imes/module/system/controller/admin/funds/products/vo/productDetails/ProductDetailsSaveReqVO.java @@ -1,8 +1,7 @@ package com.cf.imes.module.system.controller.admin.funds.products.vo.productDetails; -import com.cf.imes.framework.common.validation.NumberValid; +import com.cf.imes.module.system.enums.products.ProductsPurchaseTypeEnum; import com.cf.imes.module.system.validation.products.ProductDurationUnitValid; -import com.cf.imes.module.system.validation.products.ProductType; import io.swagger.v3.oas.annotations.media.Schema; import jakarta.validation.constraints.DecimalMax; import jakarta.validation.constraints.DecimalMin; @@ -24,46 +23,28 @@ public class ProductDetailsSaveReqVO { private Long productId; @Schema(description = "购买方式", requiredMode = Schema.RequiredMode.REQUIRED, example = "0") - @NotNull(message = "购买方式不能为空") - @ProductType - private Integer purchaseType; + private Integer purchaseType = ProductsPurchaseTypeEnum.DURATION.getStatus(); @Schema(description = "产品时间,格式:时长值", requiredMode = Schema.RequiredMode.REQUIRED, example = "1") private String duration; - @Schema(description = "产品时长单位,0:年、1:月", example = "1") + @Schema(description = "产品时长单位,0:年", example = "1") @ProductDurationUnitValid private Integer durationUnit; @Schema(description = "产品产量", requiredMode = Schema.RequiredMode.REQUIRED, example = "") private BigDecimal output; - @Schema(description = "赠送时间,格式:时长值 - 时间单位", requiredMode = Schema.RequiredMode.REQUIRED, example = "1") - private String giftDuration; - - @Schema(description = "赠送时长单位,0:年、1:月", example = "1") - @ProductDurationUnitValid - private Integer giftDurationUnit; - @Schema(description = "赠送产量", requiredMode = Schema.RequiredMode.REQUIRED, example = "") private BigDecimal giftOutput; - @Schema(description = "产品原价", requiredMode = Schema.RequiredMode.REQUIRED, example = "100") - @NotNull(message = "产品原价不能为空") - @NumberValid(name = "产品原价") - private BigDecimal originalPrice; - @Schema(description = "折扣", requiredMode = Schema.RequiredMode.REQUIRED, example = "0.8") @DecimalMax(value = "100", message = "折扣必须小于等于100") @DecimalMin(value = "0", message = "折扣必须大于等于0") @Digits(integer = 3, fraction = 0, message = "折扣必须是0 ~ 100间的整数") + @NotNull(message = "折扣不能为空") private BigDecimal discount; - @Schema(description = "产品现价", requiredMode = Schema.RequiredMode.REQUIRED, example = "80") - @NotNull(message = "产品现价不能为空") - @NumberValid(name = "产品现价") - private BigDecimal currentPrice; - @Schema(description = "是否特惠", requiredMode = Schema.RequiredMode.REQUIRED, example = "true") private Boolean isDiscounted; diff --git a/cf-module-system/cf-module-system-biz/src/main/java/com/cf/imes/module/system/controller/admin/funds/purchase/vo/OrgEarliestPurchaseProductRespVO.java b/cf-module-system/cf-module-system-biz/src/main/java/com/cf/imes/module/system/controller/admin/funds/purchase/vo/OrgEarliestPurchaseProductRespVO.java index 18380bd05..7e2f5d9eb 100644 --- a/cf-module-system/cf-module-system-biz/src/main/java/com/cf/imes/module/system/controller/admin/funds/purchase/vo/OrgEarliestPurchaseProductRespVO.java +++ b/cf-module-system/cf-module-system-biz/src/main/java/com/cf/imes/module/system/controller/admin/funds/purchase/vo/OrgEarliestPurchaseProductRespVO.java @@ -1,6 +1,5 @@ package com.cf.imes.module.system.controller.admin.funds.purchase.vo; -import com.cf.imes.module.system.dal.dataobject.funds.products.ProductsDetailDO; import com.cf.imes.module.system.dal.dataobject.funds.purchase.PurchaseRecordDO; import lombok.AllArgsConstructor; import lombok.Data; @@ -18,9 +17,4 @@ public class OrgEarliestPurchaseProductRespVO { * 购买记录 */ private PurchaseRecordDO purchaseRecordDO; - - /** - * 产品定价规则 - */ - private ProductsDetailDO productsDetailDO; } 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 fc3d2805c..885136021 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 @@ -116,7 +116,7 @@ public class OrganController { Long organId = bean.getId(); // 查询当次列表组织下的所有购买记录 - List orgPurchaseList = BeanUtil.copyToList(purchaseService.getOrgPurchaseList(Set.of(organId)), OrganPagePurchaseRespVO.class); + List orgPurchaseList = BeanUtil.copyToList(purchaseService.getOrgPurchaseNotInitialList(Set.of(organId)), OrganPagePurchaseRespVO.class); // 查询购买记录下的延期记录 orgPurchaseList.forEach(p -> { List delayRecordsByPurchaseId = productDelayService.getRecordsByPurchaseId(p.getId(), organId); @@ -143,7 +143,7 @@ public class OrganController { Set organIds = bean.getList().stream().map(OrganRespVO::getId).collect(Collectors.toSet()); // 查询当次列表组织下的所有购买记录 - List orgPurchaseList = purchaseService.getOrgPurchaseList(organIds); + List orgPurchaseList = purchaseService.getOrgPurchaseNotInitialList(organIds); // 匹配到对应的组织下 bean.getList().forEach(e -> { List purchaseRespVOList = orgPurchaseList.stream() diff --git a/cf-module-system/cf-module-system-biz/src/main/java/com/cf/imes/module/system/controller/admin/organ/vo/organ/OrganCreateProductPurchaseReqVO.java b/cf-module-system/cf-module-system-biz/src/main/java/com/cf/imes/module/system/controller/admin/organ/vo/organ/OrganCreateProductPurchaseReqVO.java index 1c43f4b67..638dd8d24 100644 --- a/cf-module-system/cf-module-system-biz/src/main/java/com/cf/imes/module/system/controller/admin/organ/vo/organ/OrganCreateProductPurchaseReqVO.java +++ b/cf-module-system/cf-module-system-biz/src/main/java/com/cf/imes/module/system/controller/admin/organ/vo/organ/OrganCreateProductPurchaseReqVO.java @@ -8,7 +8,6 @@ import jakarta.validation.constraints.NotNull; import lombok.Data; import java.math.BigDecimal; -import java.time.LocalDate; @Schema(description = "管理后台 - 组织创建购买产品 Request VO") @Data @@ -17,18 +16,10 @@ public class OrganCreateProductPurchaseReqVO { @NotNull(message = "产品编号不能为空", groups = {OrganSaveCreateGroup.class}) private Long productId; - @Schema(description = "定价规则编号", example = "1") - @NotNull(message = "定价规则编号不能为空", groups = {OrganSaveCreateGroup.class}) - private Long productDetailsId; - @Schema(description = "产品购买金额,单位:元", requiredMode = Schema.RequiredMode.REQUIRED, example = "100") @NotNull(message = "产品购买金额不能为空", groups = {OrganSaveCreateGroup.class}) @DecimalMin(value = "0.01", message = "产品购买金额必须大于零") @DecimalMax(value = "100000", message = "产品购买金额不能超过十万") @Digits(integer = 6, fraction = 2, message = "产品购买金额格式不正确") private BigDecimal price; - - @Schema(description = "产品有效时间") - @NotNull(message = "产品有效时间不能为空", groups = {OrganSaveCreateGroup.class}) - private LocalDate productExpireDate; } diff --git a/cf-module-system/cf-module-system-biz/src/main/java/com/cf/imes/module/system/controller/admin/pay/vo/PayProductOrderUnifiedReqVO.java b/cf-module-system/cf-module-system-biz/src/main/java/com/cf/imes/module/system/controller/admin/pay/vo/PayProductOrderUnifiedReqVO.java index 59bbb5681..a7c1815f8 100644 --- a/cf-module-system/cf-module-system-biz/src/main/java/com/cf/imes/module/system/controller/admin/pay/vo/PayProductOrderUnifiedReqVO.java +++ b/cf-module-system/cf-module-system-biz/src/main/java/com/cf/imes/module/system/controller/admin/pay/vo/PayProductOrderUnifiedReqVO.java @@ -3,7 +3,6 @@ package com.cf.imes.module.system.controller.admin.pay.vo; import com.cf.imes.module.system.validation.pay.PayProductChannelCodeValid; 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; @@ -23,6 +22,10 @@ public class PayProductOrderUnifiedReqVO { @NotNull(message = "产品定价规则编号不能为空") private Long productDetailsId; + @Schema(description = "产品ID", requiredMode = Schema.RequiredMode.REQUIRED, example = "1") + @NotNull(message = "产品ID不能为空") + private Long productId; + @Schema(description = "产品支付渠道编码", requiredMode = Schema.RequiredMode.REQUIRED, example = "0") @PayProductChannelCodeValid @NotNull(message = "产品支付渠道编码不能为空") diff --git a/cf-module-system/cf-module-system-biz/src/main/java/com/cf/imes/module/system/dal/dataobject/funds/products/ProductsDO.java b/cf-module-system/cf-module-system-biz/src/main/java/com/cf/imes/module/system/dal/dataobject/funds/products/ProductsDO.java index 3ea4d72c9..1e6a2fe61 100644 --- a/cf-module-system/cf-module-system-biz/src/main/java/com/cf/imes/module/system/dal/dataobject/funds/products/ProductsDO.java +++ b/cf-module-system/cf-module-system-biz/src/main/java/com/cf/imes/module/system/dal/dataobject/funds/products/ProductsDO.java @@ -6,6 +6,8 @@ import com.baomidou.mybatisplus.annotation.TableName; import com.cf.imes.framework.mybatis.core.dataobject.BaseDO; import lombok.*; +import java.math.BigDecimal; + /** * 产品表 products DO @@ -47,6 +49,8 @@ public class ProductsDO extends BaseDO { */ private Integer softwareId; - - + /** + * 建议价格 + */ + private BigDecimal price; } diff --git a/cf-module-system/cf-module-system-biz/src/main/java/com/cf/imes/module/system/dal/dataobject/funds/products/ProductsDetailDO.java b/cf-module-system/cf-module-system-biz/src/main/java/com/cf/imes/module/system/dal/dataobject/funds/products/ProductsDetailDO.java index 962e9140a..22a8f6d8a 100644 --- a/cf-module-system/cf-module-system-biz/src/main/java/com/cf/imes/module/system/dal/dataobject/funds/products/ProductsDetailDO.java +++ b/cf-module-system/cf-module-system-biz/src/main/java/com/cf/imes/module/system/dal/dataobject/funds/products/ProductsDetailDO.java @@ -56,36 +56,16 @@ public class ProductsDetailDO extends BaseDO { @TableField("`output`") private BigDecimal output; - /** - * 赠送时间 - */ - private Integer giftDuration; - - /** - * 赠送时间单位 - */ - private Integer giftDurationUnit; - /** * 赠送产量 */ private BigDecimal giftOutput; - /** - * 产品原价 - */ - private BigDecimal originalPrice; - /** * 折扣 */ private BigDecimal discount; - /** - * 产品现价 - */ - private BigDecimal currentPrice; - /** * 是否特惠: 0否1是 */ diff --git a/cf-module-system/cf-module-system-biz/src/main/java/com/cf/imes/module/system/dal/mysql/funds/products/ProductsDetailMapper.java b/cf-module-system/cf-module-system-biz/src/main/java/com/cf/imes/module/system/dal/mysql/funds/products/ProductsDetailMapper.java index 7d4e1076a..e4f96f7fc 100644 --- a/cf-module-system/cf-module-system-biz/src/main/java/com/cf/imes/module/system/dal/mysql/funds/products/ProductsDetailMapper.java +++ b/cf-module-system/cf-module-system-biz/src/main/java/com/cf/imes/module/system/dal/mysql/funds/products/ProductsDetailMapper.java @@ -22,12 +22,9 @@ public interface ProductsDetailMapper extends BaseMapperX { .eqIfPresent(ProductsDetailDO::getPurchaseType, reqVO.getPurchaseType()) .eqIfPresent(ProductsDetailDO::getProductId, reqVO.getProductId()) .eqIfPresent(ProductsDetailDO::getDuration, reqVO.getDuration()) - .eqIfPresent(ProductsDetailDO::getGiftDuration, reqVO.getGiftDuration()) .eqIfPresent(ProductsDetailDO::getOutput, reqVO.getOutput()) .eqIfPresent(ProductsDetailDO::getGiftOutput, reqVO.getGiftOutput()) - .eqIfPresent(ProductsDetailDO::getOriginalPrice, reqVO.getOriginalPrice()) .eqIfPresent(ProductsDetailDO::getDiscount, reqVO.getDiscount()) - .eqIfPresent(ProductsDetailDO::getCurrentPrice, reqVO.getCurrentPrice()) .eqIfPresent(ProductsDetailDO::getIsDiscounted, reqVO.getIsDiscounted()) .eqIfPresent(ProductsDetailDO::getDeleted, false) ); diff --git a/cf-module-system/cf-module-system-biz/src/main/java/com/cf/imes/module/system/dal/mysql/funds/purchase/PurchaseRecordMapper.java b/cf-module-system/cf-module-system-biz/src/main/java/com/cf/imes/module/system/dal/mysql/funds/purchase/PurchaseRecordMapper.java index 151cd2104..492cbdb92 100644 --- a/cf-module-system/cf-module-system-biz/src/main/java/com/cf/imes/module/system/dal/mysql/funds/purchase/PurchaseRecordMapper.java +++ b/cf-module-system/cf-module-system-biz/src/main/java/com/cf/imes/module/system/dal/mysql/funds/purchase/PurchaseRecordMapper.java @@ -45,6 +45,7 @@ public interface PurchaseRecordMapper extends BaseMapperX { .eqIfPresent(PurchaseRecordDO::getPurchaseDuration, pageReqVO.getPurchaseDuration()) .betweenIfPresent(PurchaseRecordDO::getCreateTime, pageReqVO.getCreateTime()) .likeIfPresent(PurchaseRecordDO::getCreator, pageReqVO.getCreator()) + .ne(PurchaseRecordDO::getInitial, true) .orderByDesc(PurchaseRecordDO::getCreateTime)); } @@ -63,6 +64,7 @@ public interface PurchaseRecordMapper extends BaseMapperX { .eq(PurchaseRecordDO::getOrganId, SecurityFrameworkUtils.getUserOrganId()) .eq(PurchaseRecordDO::getDeleted, false) .in(PurchaseRecordDO::getIsInvocing, InvoiceStatusEnum.INVOICABLE.getCode(), InvoiceStatusEnum.INVOICINGFAILED.getCode()) + .ne(PurchaseRecordDO::getInitial, true) .orderByDesc(PurchaseRecordDO::getCreateTime) ); @@ -109,6 +111,7 @@ public interface PurchaseRecordMapper extends BaseMapperX { .eqIfPresent(PurchaseRecordDO::getOrganId, pageReqVO.getOrganId()) .eqIfPresent(PurchaseRecordDO::getCreator, pageReqVO.getOperator()) .eq(PurchaseRecordDO::getDeleted, false) + .ne(PurchaseRecordDO::getInitial, true) .orderByDesc(PurchaseRecordDO::getCreateTime) .select(PurchaseRecordDO::getId, PurchaseRecordDO::getOrganId, PurchaseRecordDO::getTotalAmount, PurchaseRecordDO::getAccountBalanceSpent, PurchaseRecordDO::getAlipaySpent, PurchaseRecordDO::getWechatSpent, PurchaseRecordDO::getGiftMoneySpent, PurchaseRecordDO::getCreator, PurchaseRecordDO::getCreateTime) diff --git a/cf-module-system/cf-module-system-biz/src/main/java/com/cf/imes/module/system/enums/pay/PayConstants.java b/cf-module-system/cf-module-system-biz/src/main/java/com/cf/imes/module/system/enums/pay/PayConstants.java index 376bb373c..e24e78b92 100644 --- a/cf-module-system/cf-module-system-biz/src/main/java/com/cf/imes/module/system/enums/pay/PayConstants.java +++ b/cf-module-system/cf-module-system-biz/src/main/java/com/cf/imes/module/system/enums/pay/PayConstants.java @@ -10,4 +10,6 @@ public class PayConstants { public static final String PAY_ORDER_PREFIX_FORMAT = "P%dO%s"; // 第三方支付流水号格式 public static final String PAY_PRODUCT_DETAIL_BUSINESSNO_PREFIX_FORMAT = "P%dD%s"; // 产品购买流水号格式 + + public static final String PAY_PRODUCT_DETAIL_AUTO_GENERATE_MONTH_ID_FORMAT = "1759029544%d"; // 1~12月定价规则自动生成ID格式 } \ No newline at end of file diff --git a/cf-module-system/cf-module-system-biz/src/main/java/com/cf/imes/module/system/enums/pay/ProductDurationUnitEnum.java b/cf-module-system/cf-module-system-biz/src/main/java/com/cf/imes/module/system/enums/pay/ProductDurationUnitEnum.java index 6e6184e75..716cbfc39 100644 --- a/cf-module-system/cf-module-system-biz/src/main/java/com/cf/imes/module/system/enums/pay/ProductDurationUnitEnum.java +++ b/cf-module-system/cf-module-system-biz/src/main/java/com/cf/imes/module/system/enums/pay/ProductDurationUnitEnum.java @@ -40,10 +40,6 @@ public enum ProductDurationUnitEnum implements IntArrayValuable, BaseEnum { return Objects.equals(YEAR.code, name); } - public static boolean isMonth(String name) { - return Objects.equals(MONTH.code, name); - } - public static ProductDurationUnitEnum fromStatus(Integer status) { return Arrays.stream(values()) .filter(bean -> Objects.equals(bean.code, status)) @@ -61,4 +57,13 @@ public enum ProductDurationUnitEnum implements IntArrayValuable, BaseEnum { ProductDurationUnitEnum unit = fromStatus(status); return unit != null ? unit.getDesc() : null; } + + /** + * 获取需要筛选的类型:年 + * + * @return + */ + public static ProductDurationUnitEnum[] validArr() { + return new ProductDurationUnitEnum[]{YEAR}; + } } diff --git a/cf-module-system/cf-module-system-biz/src/main/java/com/cf/imes/module/system/service/funds/organamount/OrganAmountServiceImpl.java b/cf-module-system/cf-module-system-biz/src/main/java/com/cf/imes/module/system/service/funds/organamount/OrganAmountServiceImpl.java index e8a51f6e5..c25895181 100644 --- a/cf-module-system/cf-module-system-biz/src/main/java/com/cf/imes/module/system/service/funds/organamount/OrganAmountServiceImpl.java +++ b/cf-module-system/cf-module-system-biz/src/main/java/com/cf/imes/module/system/service/funds/organamount/OrganAmountServiceImpl.java @@ -187,16 +187,11 @@ public class OrganAmountServiceImpl implements OrganAmountService { // 查询组织最晚还有效的产品购买记录 OrgEarliestPurchaseProductRespVO orgEarliestProductDetail = purchaseService.getOrgEarliestProductDetail(organId); if (ObjectUtil.isNotNull(orgEarliestProductDetail)) { - // 购买记录 + // 查询对应购买记录 PurchaseRecordDO purchaseRecordDO = orgEarliestProductDetail.getPurchaseRecordDO(); - // 购买记录关联的定价规则 - ProductsDetailDO productsDetailDO = orgEarliestProductDetail.getProductsDetailDO(); - organAmountRespVO.setProductEfficientDate(LocalDateTimeUtil.format(purchaseRecordDO.getEndTime(), NORM_DATETIME_FORMATTER)); - organAmountRespVO.setDuration(productsDetailDO.getDuration()); - organAmountRespVO.setDurationUnit(productsDetailDO.getDurationUnit()); - organAmountRespVO.setGiftDuration(productsDetailDO.getGiftDuration()); - organAmountRespVO.setGiftDurationUnit(productsDetailDO.getGiftDurationUnit()); + organAmountRespVO.setDuration(purchaseRecordDO.getPurchaseDuration()); + organAmountRespVO.setDurationUnit(purchaseRecordDO.getPurchaseDurationUnit()); } // 查询可开票金额 diff --git a/cf-module-system/cf-module-system-biz/src/main/java/com/cf/imes/module/system/service/funds/products/ProductsDetailService.java b/cf-module-system/cf-module-system-biz/src/main/java/com/cf/imes/module/system/service/funds/products/ProductsDetailService.java index da5d78cad..8dbb707a9 100644 --- a/cf-module-system/cf-module-system-biz/src/main/java/com/cf/imes/module/system/service/funds/products/ProductsDetailService.java +++ b/cf-module-system/cf-module-system-biz/src/main/java/com/cf/imes/module/system/service/funds/products/ProductsDetailService.java @@ -8,7 +8,7 @@ import com.cf.imes.module.system.dal.dataobject.funds.products.ProductsDetailDO; import jakarta.validation.Valid; -import java.util.List; +import java.math.BigDecimal; /** * 产品明细表 product_details Service 接口 @@ -67,4 +67,12 @@ public interface ProductsDetailService { * @param productId */ ProductsDO validateProductExist(Long productId); + + /** + * 获取产品1年定价的折扣 + * + * @param productId + * @return + */ + BigDecimal getProductDetailOneYearDiscount(Long productId); } diff --git a/cf-module-system/cf-module-system-biz/src/main/java/com/cf/imes/module/system/service/funds/products/ProductsDetailServiceImpl.java b/cf-module-system/cf-module-system-biz/src/main/java/com/cf/imes/module/system/service/funds/products/ProductsDetailServiceImpl.java index dc2a12229..baa2087c6 100644 --- a/cf-module-system/cf-module-system-biz/src/main/java/com/cf/imes/module/system/service/funds/products/ProductsDetailServiceImpl.java +++ b/cf-module-system/cf-module-system-biz/src/main/java/com/cf/imes/module/system/service/funds/products/ProductsDetailServiceImpl.java @@ -1,11 +1,14 @@ package com.cf.imes.module.system.service.funds.products; -import com.alibaba.nacos.common.utils.StringUtils; +import cn.hutool.core.util.ObjectUtil; +import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper; +import com.baomidou.mybatisplus.core.conditions.update.LambdaUpdateWrapper; import com.cf.imes.framework.common.exception.util.ServiceExceptionUtil; 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.framework.mybatis.core.query.LambdaQueryWrapperX; +import com.cf.imes.framework.mybatis.core.query.LambdaUpdateWrapperX; import com.cf.imes.module.system.controller.admin.funds.products.vo.productDetails.ProductDetailsPageReqVO; import com.cf.imes.module.system.controller.admin.funds.products.vo.productDetails.ProductDetailsSaveReqVO; import com.cf.imes.module.system.dal.dataobject.funds.products.ProductsDO; @@ -19,8 +22,8 @@ import org.springframework.stereotype.Service; import org.springframework.validation.annotation.Validated; import jakarta.annotation.Resource; + import java.math.BigDecimal; -import java.math.RoundingMode; import static com.cf.imes.framework.common.exception.util.ServiceExceptionUtil.exception; import static com.cf.imes.module.system.enums.ErrorCodeConstants.*; @@ -49,14 +52,7 @@ public class ProductsDetailServiceImpl implements ProductsDetailService { if (ProductsPurchaseTypeEnum.DURATION.getStatus().equals(createReqVO.getPurchaseType())) { // 校验时长 checkDuration(createReqVO.getDuration(), createReqVO.getDurationUnit()); - // 校验赠送时长 - String giftDuration = createReqVO.getGiftDuration(); - if (StringUtils.isNotEmpty(giftDuration)) { - checkDuration(giftDuration, createReqVO.getGiftDurationUnit()); - } - // 校验现价计算是否正确 - calculateDiscount(createReqVO.getOriginalPrice(), createReqVO.getCurrentPrice(), createReqVO.getDiscount()); // 查询是否有重复的定价 checkProductDetails(createReqVO); @@ -81,14 +77,6 @@ public class ProductsDetailServiceImpl implements ProductsDetailService { if (updateReqVO.getPurchaseType().equals(ProductsPurchaseTypeEnum.DURATION.getStatus())) { // 校验时长 checkDuration(updateReqVO.getDuration(), updateReqVO.getDurationUnit()); - // 校验赠送时长 - String giftDuration = updateReqVO.getGiftDuration(); - if (StringUtils.isNotEmpty(giftDuration)) { - checkDuration(giftDuration, updateReqVO.getGiftDurationUnit()); - } - - // 校验现价计算是否正确 - calculateDiscount(updateReqVO.getOriginalPrice(), updateReqVO.getCurrentPrice(), updateReqVO.getDiscount()); // 校验同时长是否还有其他的定价规则 checkProductDetails(updateReqVO); @@ -97,7 +85,12 @@ public class ProductsDetailServiceImpl implements ProductsDetailService { throw exception(PRODUCTS_OUTPUT_NOT_SUPPORT); } - productDetailsMapper.updateById(BeanUtils.toBean(updateReqVO, ProductsDetailDO.class)); + productDetailsMapper.update(new LambdaUpdateWrapper() + .eq(ProductsDetailDO::getId, updateReqVO.getId()) + .set(ProductsDetailDO::getDiscount, updateReqVO.getDiscount()) + .set(ProductsDetailDO::getDuration, updateReqVO.getDuration()) + .set(ProductsDetailDO::getDurationUnit, updateReqVO.getDurationUnit()) + ); } @Override @@ -228,22 +221,16 @@ public class ProductsDetailServiceImpl implements ProductsDetailService { } } - - /** - * 计算折扣是否正确 - * - * @param originalPrice 原价 - * @param currentPrice 当前价格 - * @param discount 折扣(百分比) - */ - private void calculateDiscount(BigDecimal originalPrice, BigDecimal currentPrice, BigDecimal discount) { - // 校验当前价格是否正确 - // 计算期望现价 = 原价 * 折扣 /100(保留2位小数) - BigDecimal expectedPrice = originalPrice.multiply(discount).divide(new BigDecimal(100)).setScale(2, RoundingMode.DOWN); - - if (currentPrice.compareTo(expectedPrice) != 0) { - throw ServiceExceptionUtil.exception(PRODUCTS_DETAIL_CURRENTPRICE_CALCULATE_ERROR, expectedPrice); + @Override + public BigDecimal getProductDetailOneYearDiscount(Long productId) { + ProductsDetailDO productsDetailDO = productDetailsMapper.selectOne(new LambdaQueryWrapper() + .eq(ProductsDetailDO::getProductId, productId) + .eq(ProductsDetailDO::getDuration, 1) + .eq(ProductsDetailDO::getDurationUnit, ProductDurationUnitEnum.YEAR.getCode())); + if (ObjectUtil.isNotNull(productsDetailDO)) { + return productsDetailDO.getDiscount(); + } else { + return BigDecimal.valueOf(100); } } - } diff --git a/cf-module-system/cf-module-system-biz/src/main/java/com/cf/imes/module/system/service/funds/products/ProductsService.java b/cf-module-system/cf-module-system-biz/src/main/java/com/cf/imes/module/system/service/funds/products/ProductsService.java index f6d482302..719de8aa9 100644 --- a/cf-module-system/cf-module-system-biz/src/main/java/com/cf/imes/module/system/service/funds/products/ProductsService.java +++ b/cf-module-system/cf-module-system-biz/src/main/java/com/cf/imes/module/system/service/funds/products/ProductsService.java @@ -2,6 +2,7 @@ package com.cf.imes.module.system.service.funds.products; import com.cf.imes.framework.common.pojo.PageResult; import com.cf.imes.module.system.controller.admin.funds.products.vo.product.ProductPageReqVO; +import com.cf.imes.module.system.controller.admin.funds.products.vo.product.ProductSaveReqVO; import com.cf.imes.module.system.dal.dataobject.funds.products.ProductsDO; import jakarta.validation.Valid; @@ -16,17 +17,17 @@ public interface ProductsService { /** * 创建产品 * - * @param productName 产品名称 + * @param saveReqVO * @return 编号 */ - Long create(@Valid String productName); + Long create(ProductSaveReqVO saveReqVO); /** * 更新产品 * * @param updateReqVO 更新信息 */ - void update(@Valid ProductsDO updateReqVO); + void update(ProductSaveReqVO updateReqVO); /** * 删除产品 diff --git a/cf-module-system/cf-module-system-biz/src/main/java/com/cf/imes/module/system/service/funds/products/ProductsServiceImpl.java b/cf-module-system/cf-module-system-biz/src/main/java/com/cf/imes/module/system/service/funds/products/ProductsServiceImpl.java index ae411a861..fd33cd0f5 100644 --- a/cf-module-system/cf-module-system-biz/src/main/java/com/cf/imes/module/system/service/funds/products/ProductsServiceImpl.java +++ b/cf-module-system/cf-module-system-biz/src/main/java/com/cf/imes/module/system/service/funds/products/ProductsServiceImpl.java @@ -3,8 +3,11 @@ package com.cf.imes.module.system.service.funds.products; import com.baomidou.mybatisplus.core.conditions.update.LambdaUpdateWrapper; 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.framework.mybatis.core.query.LambdaQueryWrapperX; +import com.cf.imes.framework.mybatis.core.query.LambdaUpdateWrapperX; import com.cf.imes.module.system.controller.admin.funds.products.vo.product.ProductPageReqVO; +import com.cf.imes.module.system.controller.admin.funds.products.vo.product.ProductSaveReqVO; import com.cf.imes.module.system.dal.dataobject.funds.products.ProductsDO; import com.cf.imes.module.system.dal.mysql.funds.products.ProductsMapper; import com.cf.imes.module.system.enums.products.ProductStatusEnum; @@ -32,12 +35,14 @@ public class ProductsServiceImpl implements ProductsService { private ProductsMapper productsMapper; @Override - public Long create(String productName) { + public Long create(ProductSaveReqVO createReqVO) { + String productName = createReqVO.getProductName(); // 校验产品名称唯一 validateProductNameUnique(null, productName); ProductsDO productsDO = new ProductsDO() .setProductName(productName) + .setPrice(createReqVO.getPrice()) .setStatus(ProductStatusEnum.PRODUCT_WAITING_UPDATES.getStatus()) .setSoftwareId(0); productsMapper.insert(productsDO); @@ -47,7 +52,7 @@ public class ProductsServiceImpl implements ProductsService { @Override - public void update(ProductsDO updateReqVO) { + public void update(ProductSaveReqVO updateReqVO) { Long updateReqVOId = updateReqVO.getId(); String productName = updateReqVO.getProductName(); // 目标状态 @@ -63,9 +68,14 @@ public class ProductsServiceImpl implements ProductsService { if (ProductStatusEnum.PRODUCT_UPDATES.getStatus().equals(status) && !ProductStatusEnum.isProductDelis(updateReqVOStatus)) { throw exception(PRODUCTS_NO_UPDATE); } - - productsMapper.updateById(updateReqVO); - + ProductsDO productsDO = BeanUtils.toBean(updateReqVO, ProductsDO.class); + productsMapper.updateById(productsDO); + productsMapper.update(new LambdaUpdateWrapperX() + .eq(ProductsDO::getId, updateReqVOId) + .setIfPresent(ProductsDO::getProductName, productName) + .setIfPresent(ProductsDO::getPrice, updateReqVO.getPrice()) + .set(ProductsDO::getStatus, updateReqVOStatus) + ); } diff --git a/cf-module-system/cf-module-system-biz/src/main/java/com/cf/imes/module/system/service/funds/purchase/PurchaseService.java b/cf-module-system/cf-module-system-biz/src/main/java/com/cf/imes/module/system/service/funds/purchase/PurchaseService.java index 9bf3719d8..84b635946 100644 --- a/cf-module-system/cf-module-system-biz/src/main/java/com/cf/imes/module/system/service/funds/purchase/PurchaseService.java +++ b/cf-module-system/cf-module-system-biz/src/main/java/com/cf/imes/module/system/service/funds/purchase/PurchaseService.java @@ -2,13 +2,13 @@ package com.cf.imes.module.system.service.funds.purchase; import com.cf.imes.framework.common.pojo.PageResult; import com.cf.imes.module.system.controller.admin.funds.organamount.vo.TotalSalesAmountRespVO; +import com.cf.imes.module.system.controller.admin.funds.products.vo.productDetails.ProductDetailsRespVO; import com.cf.imes.module.system.controller.admin.funds.purchase.vo.OrgEarliestPurchaseProductRespVO; import com.cf.imes.module.system.controller.admin.funds.purchase.vo.PurchaseRecordPageReqVO; import com.cf.imes.module.system.controller.admin.funds.purchase.vo.PurchaseRecordRespVO; import com.cf.imes.module.system.controller.admin.funds.purchase.vo.SalesDetailRespVO; import com.cf.imes.module.system.controller.admin.funds.purchase.vo.SalesDetailsPageReqVO; import com.cf.imes.module.system.controller.admin.organ.vo.organ.OrganCreateProductPurchaseReqVO; -import com.cf.imes.module.system.dal.dataobject.funds.products.ProductsDetailDO; import com.cf.imes.module.system.dal.dataobject.funds.purchase.PurchaseRecordDO; import java.math.BigDecimal; @@ -82,12 +82,12 @@ public interface PurchaseService { void createOrgInitProductPurchaseRecord(Long organId, List productPurchaseReqVOS); /** - * 查询组织下的产品购买记录 + * 查询组织下的非首购的产品购买记录 * * @param organIds * @return */ - List getOrgPurchaseList(Set organIds); + List getOrgPurchaseNotInitialList(Set organIds); /** * 查询销售总额 @@ -131,7 +131,7 @@ public interface PurchaseService { * @param organId * @return */ - List getOrgProductDetailList(Long organId, Long productId); + List getOrgProductDetailList(Long organId, Long productId); /** * 作废历史组织产品购买记录 diff --git a/cf-module-system/cf-module-system-biz/src/main/java/com/cf/imes/module/system/service/funds/purchase/PurchaseServiceImpl.java b/cf-module-system/cf-module-system-biz/src/main/java/com/cf/imes/module/system/service/funds/purchase/PurchaseServiceImpl.java index d8170ae4a..e995e9c58 100644 --- a/cf-module-system/cf-module-system-biz/src/main/java/com/cf/imes/module/system/service/funds/purchase/PurchaseServiceImpl.java +++ b/cf-module-system/cf-module-system-biz/src/main/java/com/cf/imes/module/system/service/funds/purchase/PurchaseServiceImpl.java @@ -13,6 +13,7 @@ import com.cf.imes.framework.common.util.object.BeanUtils; import com.cf.imes.module.system.controller.admin.funds.delay.vo.ProductDelayRespVO; import com.cf.imes.module.system.controller.admin.funds.organamount.vo.TotalSalesAmountRespVO; import com.cf.imes.module.system.controller.admin.funds.products.vo.productDetails.ProductDetailsPageReqVO; +import com.cf.imes.module.system.controller.admin.funds.products.vo.productDetails.ProductDetailsRespVO; import com.cf.imes.module.system.controller.admin.funds.purchase.vo.OrgEarliestPurchaseProductRespVO; import com.cf.imes.module.system.controller.admin.funds.purchase.vo.PurchaseRecordPageReqVO; import com.cf.imes.module.system.controller.admin.funds.purchase.vo.PurchaseRecordRespVO; @@ -23,7 +24,6 @@ import com.cf.imes.module.system.dal.dataobject.funds.products.ProductsDO; import com.cf.imes.module.system.dal.dataobject.funds.products.ProductsDetailDO; 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.products.ProductsDetailMapper; import com.cf.imes.module.system.dal.mysql.funds.purchase.PurchaseRecordMapper; import com.cf.imes.module.system.enums.pay.InvoiceStatusEnum; import com.cf.imes.module.system.enums.pay.PayProductChannelCodeEnum; @@ -46,7 +46,8 @@ import java.util.ArrayList; import java.util.List; import java.util.Set; -import static com.cf.imes.module.system.enums.ErrorCodeConstants.PRODUCTS_DETAIL_DURATION_UNIT_NOT_SUPPORT; +import static com.cf.imes.module.system.enums.ErrorCodeConstants.PRODUCT_PRICE_NULL_ERROR; +import static com.cf.imes.module.system.enums.pay.PayConstants.PAY_PRODUCT_DETAIL_AUTO_GENERATE_MONTH_ID_FORMAT; /** * @author 软件购买接口 实现类 @@ -58,9 +59,6 @@ public class PurchaseServiceImpl implements PurchaseService { @Resource private PurchaseRecordMapper purchaseRecordMapper; - @Resource - private ProductsDetailMapper productsDetailMapper; - @Resource private ProductsDetailService productsDetailService; @@ -139,7 +137,7 @@ public class PurchaseServiceImpl implements PurchaseService { // 延期记录是按自增id逆序的,第一条的延期后时间作为产品到期时间 purchaseRecordDO.setEndTime(recordsByPurchaseId.get(0).getDelayTime()); } - return new OrgEarliestPurchaseProductRespVO(purchaseRecordDO, productsDetailMapper.selectById(purchaseRecordDO.getProductDetailsId())); + return new OrgEarliestPurchaseProductRespVO(purchaseRecordDO); } return null; } @@ -152,53 +150,35 @@ public class PurchaseServiceImpl implements PurchaseService { @Override public void createOrgInitProductPurchaseRecord(Long organId, List productPurchaseReqVOS) { for (OrganCreateProductPurchaseReqVO purchaseReqVO : productPurchaseReqVOS) { - // 1、校验定价 - ProductsDetailDO productsDetailDO = productsDetailService.validateProductDetailsExists(purchaseReqVO.getProductDetailsId()); - - // 2、校验产品 - Long productId = productsDetailDO.getProductId(); + // 1、校验产品 + Long productId = purchaseReqVO.getProductId(); ProductsDO productsDO = productsDetailService.validateProductExist(productId); - // 3、创建购买记录 + // 2、创建购买记录 // 输入的价格 BigDecimal price = purchaseReqVO.getPrice(); - // 月均单价 - BigDecimal monthAverageAmount; - // 计算后总价 - BigDecimal totalAmount = price; - /** - * ①:首次订购满1年: - * 总价 = 输入金额 - * 月均单价 = 输入金额 / (12 * duration) - * ②:不满1年按月份计算 - * 总价 = 输入金额 - * 月均单价 = 输入金额 / duration - */ - Integer duration = productsDetailDO.getDuration(); - switch (ProductDurationUnitEnum.fromStatus(productsDetailDO.getDurationUnit())) { - case YEAR -> monthAverageAmount = price.divide(new BigDecimal(duration * 12), 2, RoundingMode.DOWN); - case MONTH -> monthAverageAmount = price.divide(new BigDecimal(duration), 2, RoundingMode.DOWN); - default -> throw new ServiceException(PRODUCTS_DETAIL_DURATION_UNIT_NOT_SUPPORT); - } + // 首次订购默认是1年的价格,月均单价/10(赠送两个月) + BigDecimal monthAverageAmount = price.divide(new BigDecimal(10), 2, RoundingMode.DOWN); + long purchaseId = IdUtil.getSnowflake(mybatisIdProperties.getWorkerId(), mybatisIdProperties.getDatacenterId()).nextId(); + + LocalDate now = LocalDate.now(); PurchaseRecordDO purchaseRecordDO = PurchaseRecordDO.builder() .id(purchaseId) .organId(organId) .productId(productId) .productName(productsDO.getProductName()) - .productDetailsId(productsDetailDO.getId()) - .purchaseDuration(duration) - .purchaseDurationUnit(productsDetailDO.getDurationUnit()) - .giftDuration(productsDetailDO.getGiftDuration()) - .giftDurationUnit(productsDetailDO.getGiftDurationUnit()) - .startTime(LocalDate.now()) - .endTime(purchaseReqVO.getProductExpireDate()) + .productDetailsId(0L) + .purchaseDuration(1) + .purchaseDurationUnit(ProductDurationUnitEnum.YEAR.getCode()) + .startTime(now) + // 组织创建时的套餐购买默认过期 + .endTime(now.minusDays(1)) .paymentMethod(PayProductChannelCodeEnum.ORGAN_CREATE.getCode()) - .totalAmount(totalAmount) + .totalAmount(price) .monthAverageAmount(monthAverageAmount) .originalAmount(price) - .isInvocing(InvoiceStatusEnum.INVOICABLE.getCode()) .initial(true) .status(PurchaseRecordStatusEnum.ACTIVE.getStatus()) .build(); @@ -207,10 +187,11 @@ public class PurchaseServiceImpl implements PurchaseService { } @Override - public List getOrgPurchaseList(Set organIds) { + public List getOrgPurchaseNotInitialList(Set organIds) { return purchaseRecordMapper.selectList(new LambdaQueryWrapper() .in(PurchaseRecordDO::getOrganId, organIds) .eq(PurchaseRecordDO::getStatus, PurchaseRecordStatusEnum.ACTIVE.getStatus()) + .ne(PurchaseRecordDO::getInitial, true) .eq(PurchaseRecordDO::getDeleted, false)); } @@ -265,9 +246,9 @@ public class PurchaseServiceImpl implements PurchaseService { } @Override - public List getOrgProductDetailList(Long organId, Long productId) { + public List getOrgProductDetailList(Long organId, Long productId) { // 校验产品 - productsDetailService.validateProductExist(productId); + ProductsDO productsDO = productsDetailService.validateProductExist(productId); // 查询产品下的所有定价规则 ProductDetailsPageReqVO pageReqVO = new ProductDetailsPageReqVO(); @@ -278,64 +259,110 @@ public class PurchaseServiceImpl implements PurchaseService { // 查询组织下的首次订购产品记录 PurchaseRecordDO orgInitialPurchaseRecord = getOrgInitialPurchaseRecord(organId, productId); if (ObjectUtil.isNull(orgInitialPurchaseRecord)) { - return page.getList(); + return getInitialProductDetailList(productsDO, page.getList()); } - List resultList = new ArrayList<>(); - for (ProductsDetailDO detailDO : page.getList()) { - ProductsDetailDO newDetailDO = BeanUtils.toBean(detailDO, ProductsDetailDO.class); + List resultList = new ArrayList<>(); - // 月均单价 - BigDecimal monthAverageAmount = orgInitialPurchaseRecord.getMonthAverageAmount(); + // 月均单价 + BigDecimal monthAverageAmount = orgInitialPurchaseRecord.getMonthAverageAmount(); + // 1年定价 + BigDecimal totalAmount = orgInitialPurchaseRecord.getTotalAmount(); + // 定价中有的,以年数量*组织定价*折扣展示 + List productDetailRespVOList = new ArrayList<>(); + for (ProductsDetailDO detailDO : page.getList()) { + ProductDetailsRespVO newDetailRespVO = BeanUtils.toBean(detailDO, ProductDetailsRespVO.class); // 折扣 BigDecimal discount = detailDO.getDiscount(); - // 需要支付的总价 - BigDecimal totalAmount; + // 重新计算购买价格 switch (ProductDurationUnitEnum.fromStatus(detailDO.getDurationUnit())) { - case YEAR -> totalAmount = monthAverageAmount - .multiply(new BigDecimal(10)) - .multiply(new BigDecimal(detailDO.getDuration())) - .multiply(discount) - .divide(new BigDecimal(100), 2, RoundingMode.DOWN); - case MONTH -> { - int months = detailDO.getDuration(); - if (months >= 12) { - // 转换成年 + 剩余月 - int years = months / 12; - int remainMonths = months % 12; + case YEAR -> { + Integer duration = detailDO.getDuration(); + // 原价 + BigDecimal originalPrice = totalAmount.multiply(BigDecimal.valueOf(duration)); + newDetailRespVO.setOriginalPrice(originalPrice); + // 折扣价格 + newDetailRespVO.setCurrentPrice(originalPrice.multiply(discount).divide(BigDecimal.valueOf(100), 2, RoundingMode.DOWN)); + productDetailRespVOList.add(newDetailRespVO); + } + default -> { + } + } + } + // 默认展示1到10月的价格 + for (int i = 1; i <= 10; i++) { + ProductDetailsRespVO detailRespVO = new ProductDetailsRespVO(); + detailRespVO.setId(Long.parseLong(String.format(PAY_PRODUCT_DETAIL_AUTO_GENERATE_MONTH_ID_FORMAT, i))); + detailRespVO.setProductId(productId); + detailRespVO.setDuration(i); + detailRespVO.setDurationUnit(ProductDurationUnitEnum.MONTH.getCode()); + // 价格:月均单价*月数量 + BigDecimal price = monthAverageAmount.multiply(BigDecimal.valueOf(i)); + // 有一年的折扣要把月价格做折算 + detailRespVO.setCurrentPrice(price); + detailRespVO.setOriginalPrice(price); + resultList.add(detailRespVO); + } + resultList.addAll(productDetailRespVOList); - // 整年部分:用年逻辑(10 个月价) - BigDecimal yearPart = monthAverageAmount - .multiply(new BigDecimal(10)) - .multiply(new BigDecimal(years)) - .multiply(discount) - .divide(new BigDecimal(100), 2, RoundingMode.DOWN); + return resultList; + } - // 剩余月部分:用月逻辑 - BigDecimal monthPart = remainMonths == 0 - ? BigDecimal.ZERO - : monthAverageAmount - .multiply(new BigDecimal(remainMonths)) - .multiply(discount) - .divide(new BigDecimal(100), 2, RoundingMode.DOWN); + /** + * 拼接没有首次购买记录的定价方式列表 + * + * @param productsDO + * @param productsDetailDOS + * @return + */ + private List getInitialProductDetailList(ProductsDO productsDO, List productsDetailDOS) { + List resultList = new ArrayList<>(); + // 没有首次购买记录的产品,展示的总价是产品建议价格 + // 1年定价 + BigDecimal totalAmount = productsDO.getPrice(); + if(ObjectUtil.isNull(totalAmount)) { + throw new ServiceException(PRODUCT_PRICE_NULL_ERROR); + } + // 月均单价 + BigDecimal monthAverageAmount = totalAmount.divide(new BigDecimal(10), 2, RoundingMode.DOWN); - totalAmount = yearPart.add(monthPart); - } else { - // 小于 12 个月直接按月逻辑 - totalAmount = monthAverageAmount - .multiply(new BigDecimal(months)) - .multiply(discount) - .divide(new BigDecimal(100), 2, RoundingMode.DOWN); - } + List productDetailRespVOList = new ArrayList<>(); + for (ProductsDetailDO detailDO : productsDetailDOS) { + ProductDetailsRespVO newDetailRespVO = BeanUtils.toBean(detailDO, ProductDetailsRespVO.class); + // 折扣 + BigDecimal discount = detailDO.getDiscount(); + // 重新计算购买价格 + switch (ProductDurationUnitEnum.fromStatus(detailDO.getDurationUnit())) { + case YEAR -> { + Integer duration = detailDO.getDuration(); + // 原价 + BigDecimal originalPrice = totalAmount.multiply(BigDecimal.valueOf(duration)); + newDetailRespVO.setOriginalPrice(originalPrice); + // 折扣价格 + newDetailRespVO.setCurrentPrice(originalPrice.multiply(discount).divide(BigDecimal.valueOf(100), 2, RoundingMode.DOWN)); + productDetailRespVOList.add(newDetailRespVO); + } + default -> { } - default -> throw new ServiceException(PRODUCTS_DETAIL_DURATION_UNIT_NOT_SUPPORT); } - newDetailDO.setCurrentPrice(totalAmount); - newDetailDO.setOriginalPrice(totalAmount); - resultList.add(newDetailDO); } + // 默认展示1到10月的价格 + for (int i = 1; i <= 10; i++) { + ProductDetailsRespVO detailRespVO = new ProductDetailsRespVO(); + detailRespVO.setId(Long.parseLong(String.format(PAY_PRODUCT_DETAIL_AUTO_GENERATE_MONTH_ID_FORMAT, i))); + detailRespVO.setProductId(productsDO.getId()); + detailRespVO.setDuration(i); + detailRespVO.setDurationUnit(ProductDurationUnitEnum.MONTH.getCode()); + // 价格:月均单价*月数量 + BigDecimal price = monthAverageAmount.multiply(BigDecimal.valueOf(i)); + // 有一年的折扣要把月价格做折算 + detailRespVO.setCurrentPrice(price); + detailRespVO.setOriginalPrice(price); + resultList.add(detailRespVO); + } + resultList.addAll(productDetailRespVOList); return resultList; } diff --git a/cf-module-system/cf-module-system-biz/src/main/java/com/cf/imes/module/system/service/pay/PayOrderServiceImpl.java b/cf-module-system/cf-module-system-biz/src/main/java/com/cf/imes/module/system/service/pay/PayOrderServiceImpl.java index f6bb70407..e6e80bcd2 100644 --- a/cf-module-system/cf-module-system-biz/src/main/java/com/cf/imes/module/system/service/pay/PayOrderServiceImpl.java +++ b/cf-module-system/cf-module-system-biz/src/main/java/com/cf/imes/module/system/service/pay/PayOrderServiceImpl.java @@ -38,6 +38,7 @@ import com.cf.imes.module.system.controller.admin.funds.products.vo.product.Prod import com.cf.imes.module.system.dal.dataobject.funds.delay.ProductDelayRecordDO; import com.cf.imes.module.system.dal.dataobject.organ.OrganizationDO; import com.cf.imes.module.system.dal.dataobject.pay.PayOrderRechargeDetailDO; +import com.cf.imes.module.system.enums.pay.ProductDurationUnitEnum; 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.controller.admin.pay.vo.PayProductOrderUnifiedReqVO; @@ -111,6 +112,9 @@ public class PayOrderServiceImpl implements PayOrderService { // 外部payNo正则 private static final Pattern pattern = Pattern.compile("P(\\d+)O"); + // 自动生成定价id正则 + private static final Pattern productDetailIdPattern = Pattern.compile("^1759029544(\\d+)$"); + @Resource private PayHandlerFactory payHandlerFactory; @@ -169,10 +173,12 @@ public class PayOrderServiceImpl implements PayOrderService { ValidationUtils.validate(validator, payProductOrderUnifiedReqVO); // 校验产品和产品明细 - ProductsDetailDO productsDetailDO = productsDetailService.validateProductDetailsExists(payProductOrderUnifiedReqVO.getProductDetailsId()); - Long productId = productsDetailDO.getProductId(); + Long productId = payProductOrderUnifiedReqVO.getProductId(); ProductsDO productsDO = productsDetailService.validateProductExist(productId); + // 解析产品定价明细 + ProductsDetailDO productsDetailDO = analyzeProductDetail(productId, payProductOrderUnifiedReqVO.getProductDetailsId()); + // 检查机构产品购买锁 String purchaseLockKey = String.format(RedisKeyConstants.PRODUCT_PURCHASE_LOCK_KEY, organId, productId); boolean lockResult = redisLockUtil.redissonLock(purchaseLockKey, chenfengCacheProperties.getLockWaitTime(), chenfengCacheProperties.getLockTimeout()); @@ -250,6 +256,30 @@ public class PayOrderServiceImpl implements PayOrderService { } } + /** + * 解析定价规则,年从数据库取,月就手动拼 + * + * @param productDetailId + * @return + */ + private ProductsDetailDO analyzeProductDetail(Long productId, Long productDetailId) { + // productDetailId符合规则PPAG%d + Matcher matcher = productDetailIdPattern.matcher(String.valueOf(productDetailId)); + if (matcher.find()) { + // 取PPAG后的数字,是订购月份 + String monthDuration = matcher.group(1); + ProductsDetailDO monthDetail = new ProductsDetailDO(); + monthDetail.setId(productDetailId); + monthDetail.setDuration(Integer.parseInt(monthDuration)); + monthDetail.setDurationUnit(ProductDurationUnitEnum.MONTH.getCode()); + // 获取产品下的1年的折扣 + monthDetail.setDiscount(productsDetailService.getProductDetailOneYearDiscount(productId)); + return monthDetail; + } else { + return productsDetailService.validateProductDetailsExists(productDetailId); + } + } + /** * 处理前序购买记录: * 1、需要第三方支付,当前购买记录状态为待支付,等第三方回调/超期轮训处理到的时候标记为成功还是失败 diff --git a/cf-module-system/cf-module-system-biz/src/main/java/com/cf/imes/module/system/service/pay/PayProductProcessor.java b/cf-module-system/cf-module-system-biz/src/main/java/com/cf/imes/module/system/service/pay/PayProductProcessor.java index 962cb5cbc..ee8e698d6 100644 --- a/cf-module-system/cf-module-system-biz/src/main/java/com/cf/imes/module/system/service/pay/PayProductProcessor.java +++ b/cf-module-system/cf-module-system-biz/src/main/java/com/cf/imes/module/system/service/pay/PayProductProcessor.java @@ -94,6 +94,9 @@ public class PayProductProcessor { // 本地订购产品的月均单价 private BigDecimal monthAverageAmount = BigDecimal.ZERO; + // 原始价格 + private BigDecimal originalPrice; + public PayProductProcessor(ProductsDO productsDO, ProductsDetailDO productsDetailDO, PurchaseRecordDO orgInitialPurchaseRecord, PreviouProductDelayRespVO previouProductDelayRespVO, OrganAmountDO organAmountDO, Long organId, ChenfengPayConfig payConfig, MybatisIdProperties mybatisIdProperties) { this.productsDO = productsDO; @@ -104,8 +107,7 @@ public class PayProductProcessor { previousPurchaseRecord = previouProductDelayRespVO.getPreviouPurchaseRecord(); // 上一次订购产品的结束时间进行计算 endTime = previousPurchaseRecord.getEndTime(); - endTime = calculateEndTime(productsDetailDO.getDuration(), productsDetailDO.getDurationUnit(), - productsDetailDO.getGiftDuration(), productsDetailDO.getGiftDurationUnit()); + endTime = calculateEndTime(productsDetailDO.getDuration(), productsDetailDO.getDurationUnit()); } this.organAmountDO = organAmountDO; this.organId = organId; @@ -125,9 +127,7 @@ public class PayProductProcessor { if (initialPurchaseExist) { price = computePrice(orgInitialPurchaseRecord, productsDetailDO); } else { - price = productsDetailDO.getCurrentPrice(); - // 首次订购计算月均单价 - monthAverageAmount = computeInitialProductPayMonthAverageAmount(price); + price = computeInitialProductPayAmount(); // 首次购买记录是空,那么当前就是首次订购 initialized = true; } @@ -184,13 +184,11 @@ public class PayProductProcessor { .productDetailsId(productsDetailDO.getId()) .purchaseDuration(productsDetailDO.getDuration()) .purchaseDurationUnit(productsDetailDO.getDurationUnit()) - .giftDuration(productsDetailDO.getGiftDuration()) - .giftDurationUnit(productsDetailDO.getGiftDurationUnit()) .startTime(startTime) .endTime(endTime) .paymentMethod(PayProductChannelCodeEnum.BALANCE_ONLY.getCode()) .totalAmount(price) - .originalAmount(productsDetailDO.getCurrentPrice()) + .originalAmount(originalPrice) .monthAverageAmount(monthAverageAmount) .accountBalanceSpent(price) .isInvocing(InvoiceStatusEnum.INVOICABLE.getCode()) @@ -244,13 +242,11 @@ public class PayProductProcessor { .productDetailsId(productsDetailDO.getId()) .purchaseDuration(productsDetailDO.getDuration()) .purchaseDurationUnit(productsDetailDO.getDurationUnit()) - .giftDuration(productsDetailDO.getGiftDuration()) - .giftDurationUnit(productsDetailDO.getGiftDurationUnit()) .startTime(startTime) .endTime(endTime) .paymentMethod(PayProductChannelCodeEnum.BALANCE_ONLY.getCode()) .totalAmount(price) - .originalAmount(productsDetailDO.getCurrentPrice()) + .originalAmount(originalPrice) .monthAverageAmount(monthAverageAmount) .accountBalanceSpent(price) .isInvocing(InvoiceStatusEnum.INVOICABLE.getCode()) @@ -301,13 +297,11 @@ public class PayProductProcessor { .productDetailsId(productsDetailDO.getId()) .purchaseDuration(productsDetailDO.getDuration()) .purchaseDurationUnit(productsDetailDO.getDurationUnit()) - .giftDuration(productsDetailDO.getGiftDuration()) - .giftDurationUnit(productsDetailDO.getGiftDurationUnit()) .startTime(startTime) .endTime(endTime) .paymentMethod(PayProductChannelCodeEnum.BALANCE_ONLY.getCode()) .totalAmount(price) - .originalAmount(productsDetailDO.getCurrentPrice()) + .originalAmount(originalPrice) .monthAverageAmount(monthAverageAmount) .alipaySpent(price) .initial(initialized) @@ -340,13 +334,11 @@ public class PayProductProcessor { .productDetailsId(productsDetailDO.getId()) .purchaseDuration(productsDetailDO.getDuration()) .purchaseDurationUnit(productsDetailDO.getDurationUnit()) - .giftDuration(productsDetailDO.getGiftDuration()) - .giftDurationUnit(productsDetailDO.getGiftDurationUnit()) .startTime(startTime) .endTime(endTime) .paymentMethod(PayProductChannelCodeEnum.BALANCE_ONLY.getCode()) .totalAmount(price) - .originalAmount(productsDetailDO.getCurrentPrice()) + .originalAmount(originalPrice) .monthAverageAmount(monthAverageAmount) .wechatSpent(price) .initial(initialized) @@ -384,13 +376,11 @@ public class PayProductProcessor { .productDetailsId(productsDetailDO.getId()) .purchaseDuration(productsDetailDO.getDuration()) .purchaseDurationUnit(productsDetailDO.getDurationUnit()) - .giftDuration(productsDetailDO.getGiftDuration()) - .giftDurationUnit(productsDetailDO.getGiftDurationUnit()) .startTime(startTime) .endTime(endTime) .paymentMethod(PayProductChannelCodeEnum.BALANCE_AND_GIFT.getCode()) .totalAmount(price) - .originalAmount(productsDetailDO.getCurrentPrice()) + .originalAmount(originalPrice) .monthAverageAmount(monthAverageAmount) .isInvocing(InvoiceStatusEnum.INVOICABLE.getCode()) .initial(initialized) @@ -464,13 +454,11 @@ public class PayProductProcessor { .productDetailsId(productsDetailDO.getId()) .purchaseDuration(productsDetailDO.getDuration()) .purchaseDurationUnit(productsDetailDO.getDurationUnit()) - .giftDuration(productsDetailDO.getGiftDuration()) - .giftDurationUnit(productsDetailDO.getGiftDurationUnit()) .startTime(startTime) .endTime(endTime) .paymentMethod(PayChannelCodeEnum.ALIPAY_PC.equals(payChannelCodeEnum) ? PayProductChannelCodeEnum.BALANCE_AND_GIFT_AND_ALIPAY.getCode() : PayProductChannelCodeEnum.BALANCE_AND_GIFT_AND_WECHAT.getCode()) .totalAmount(price) - .originalAmount(productsDetailDO.getCurrentPrice()) + .originalAmount(originalPrice) .monthAverageAmount(monthAverageAmount) .initial(initialized) .status(PurchaseRecordStatusEnum.ACTIVE.getStatus()) @@ -543,13 +531,11 @@ public class PayProductProcessor { .productDetailsId(productsDetailDO.getId()) .purchaseDuration(productsDetailDO.getDuration()) .purchaseDurationUnit(productsDetailDO.getDurationUnit()) - .giftDuration(productsDetailDO.getGiftDuration()) - .giftDurationUnit(productsDetailDO.getGiftDurationUnit()) .startTime(startTime) .endTime(endTime) .paymentMethod(PayChannelCodeEnum.ALIPAY_PC.equals(payChannelCodeEnum) ? PayProductChannelCodeEnum.GIFT_AND_ALIPAY.getCode() : PayProductChannelCodeEnum.GIFT_AND_WECHAT.getCode()) .totalAmount(price) - .originalAmount(productsDetailDO.getCurrentPrice()) + .originalAmount(originalPrice) .monthAverageAmount(monthAverageAmount) .initial(initialized) .status(PurchaseRecordStatusEnum.ACTIVE.getStatus()) @@ -624,13 +610,11 @@ public class PayProductProcessor { .productDetailsId(productsDetailDO.getId()) .purchaseDuration(productsDetailDO.getDuration()) .purchaseDurationUnit(productsDetailDO.getDurationUnit()) - .giftDuration(productsDetailDO.getGiftDuration()) - .giftDurationUnit(productsDetailDO.getGiftDurationUnit()) .startTime(startTime) .endTime(endTime) .paymentMethod(PayProductChannelCodeEnum.BALANCE_AND_GIFT.getCode()) .totalAmount(price) - .originalAmount(productsDetailDO.getCurrentPrice()) + .originalAmount(originalPrice) .monthAverageAmount(monthAverageAmount) .initial(initialized) .status(PurchaseRecordStatusEnum.ACTIVE.getStatus()) @@ -723,12 +707,9 @@ public class PayProductProcessor { * * @param duration * @param durationUnit - * @param giftDuration - * @param giftDurationUnit * @return */ - private LocalDate calculateEndTime(Integer duration, Integer durationUnit, - Integer giftDuration, Integer giftDurationUnit) { + private LocalDate calculateEndTime(Integer duration, Integer durationUnit) { LocalDate today = LocalDate.now(); // 1、 计算延期后的实际有效期 LocalDate maxDelayEnd = endTime; @@ -758,11 +739,6 @@ public class PayProductProcessor { endTime = addTime(purchaseStart, duration, durationUnit); } - // 加赠送时间 - if (ObjectUtil.isNotNull(giftDuration) && giftDurationUnit != null) { - endTime = addTime(endTime, giftDuration, giftDurationUnit); - } - // 5. 扣掉延期天数 long delayDays = 0L; if (CollUtil.isNotEmpty(delayRespVOList)) { @@ -889,7 +865,7 @@ public class PayProductProcessor { } /** - * 计算产品价格 + * 计算有首购记录的产品价格 * * @param orgInitialPurchaseRecord 首次购买记录 * @param productsDetailDO 本次购买产品的定价规则 @@ -899,52 +875,35 @@ public class PayProductProcessor { // 月均单价 monthAverageAmount = orgInitialPurchaseRecord.getMonthAverageAmount(); + // 首购的定价 + BigDecimal initialPurchaseRecordTotalAmount = orgInitialPurchaseRecord.getTotalAmount(); + // 定价规则的折扣 BigDecimal discount = productsDetailDO.getDiscount(); BigDecimal totalAmount; /** * ①:续费订购满1年: - * 总价 = 月均单价 * 10 * duration * 折扣 /100,保留两位小数 + * 原始价格 = 订购总价 * duration + * 现价 = 原始价格 * 折扣 /100,保留两位小数 * ②:不满1年按月份计算 - * 总价 = 月均单价 * duration * 折扣 /100,保留两位小数 + * 原始价格 = 月均单价 * duration + * 现价 = 原始价格 * 折扣 /100,保留两位小数 */ switch (ProductDurationUnitEnum.fromStatus(productsDetailDO.getDurationUnit())) { - case YEAR -> totalAmount = monthAverageAmount - .multiply(new BigDecimal(10)) - .multiply(new BigDecimal(productsDetailDO.getDuration())) - .multiply(discount) - .divide(new BigDecimal(100), 2, RoundingMode.DOWN); + case YEAR -> { + originalPrice = initialPurchaseRecordTotalAmount + .multiply(BigDecimal.valueOf(productsDetailDO.getDuration())); + totalAmount = originalPrice + .multiply(discount) + .divide(new BigDecimal(100), 2, RoundingMode.DOWN); + } case MONTH -> { - int months = productsDetailDO.getDuration(); - if (months >= 12) { - // 转换成年 + 剩余月 - int years = months / 12; - int remainMonths = months % 12; - - // 整年部分:用年逻辑(10 个月价) - BigDecimal yearPart = monthAverageAmount - .multiply(new BigDecimal(10)) - .multiply(new BigDecimal(years)) - .multiply(discount) - .divide(new BigDecimal(100), 2, RoundingMode.DOWN); - - // 剩余月部分:用月逻辑 - BigDecimal monthPart = remainMonths == 0 - ? BigDecimal.ZERO - : monthAverageAmount - .multiply(new BigDecimal(remainMonths)) - .multiply(discount) - .divide(new BigDecimal(100), 2, RoundingMode.DOWN); - - totalAmount = yearPart.add(monthPart); - } else { - // 小于 12 个月直接按月逻辑 - totalAmount = monthAverageAmount - .multiply(new BigDecimal(months)) - .multiply(discount) - .divide(new BigDecimal(100), 2, RoundingMode.DOWN); - } + originalPrice = monthAverageAmount + .multiply(BigDecimal.valueOf(productsDetailDO.getDuration())); + totalAmount = originalPrice + .multiply(discount) + .divide(new BigDecimal(100), 2, RoundingMode.DOWN); } default -> throw new ServiceException(PRODUCTS_DETAIL_DURATION_UNIT_NOT_SUPPORT); } @@ -953,17 +912,37 @@ public class PayProductProcessor { } /** - * 计算首次订购的月均单价 + * 计算首次订购的价格 */ - private BigDecimal computeInitialProductPayMonthAverageAmount(BigDecimal price) { + private BigDecimal computeInitialProductPayAmount() { + // 订购数量 Integer duration = productsDetailDO.getDuration(); - BigDecimal monthAverageAmount; + // 产品订购价格 + BigDecimal orgPurchasePrice = productsDO.getPrice(); + // 折扣 + BigDecimal discount = productsDetailDO.getDiscount(); + + BigDecimal totalAmount; switch (ProductDurationUnitEnum.fromStatus(productsDetailDO.getDurationUnit())) { - case YEAR -> monthAverageAmount = price.divide(new BigDecimal(duration * 12), 2, RoundingMode.DOWN); - case MONTH -> monthAverageAmount = price.divide(new BigDecimal(duration), 2, RoundingMode.DOWN); + case YEAR -> { + // 原价 + originalPrice = orgPurchasePrice.multiply(BigDecimal.valueOf(duration)); + // 折扣价格 = 原价 * 折扣 + totalAmount = originalPrice.multiply(discount); + // 月均单价 = 折扣价格 / 10 + monthAverageAmount = originalPrice.divide(new BigDecimal(10), 2, RoundingMode.DOWN); + } + case MONTH -> { + // 月均单价 = 订购价格 / 10 + monthAverageAmount = orgPurchasePrice.divide(new BigDecimal(10), 2, RoundingMode.DOWN); + // 原价 + originalPrice = monthAverageAmount.multiply(BigDecimal.valueOf(duration)); + // 折扣价格 = 原价 * 折扣 + totalAmount = originalPrice.multiply(discount); + } default -> throw new ServiceException(PRODUCTS_DETAIL_DURATION_UNIT_NOT_SUPPORT); } - return monthAverageAmount; + return totalAmount; } } diff --git a/cf-module-system/cf-module-system-biz/src/main/java/com/cf/imes/module/system/validation/products/ProductDurationUnitValidator.java b/cf-module-system/cf-module-system-biz/src/main/java/com/cf/imes/module/system/validation/products/ProductDurationUnitValidator.java index 1e4bb1946..1738905b8 100644 --- a/cf-module-system/cf-module-system-biz/src/main/java/com/cf/imes/module/system/validation/products/ProductDurationUnitValidator.java +++ b/cf-module-system/cf-module-system-biz/src/main/java/com/cf/imes/module/system/validation/products/ProductDurationUnitValidator.java @@ -20,7 +20,7 @@ public class ProductDurationUnitValidator implements ConstraintValidator