diff --git a/src/main/java/com/ycwl/basic/pricing/entity/BaseEntity.java b/src/main/java/com/ycwl/basic/pricing/entity/BaseEntity.java deleted file mode 100644 index 849b036..0000000 --- a/src/main/java/com/ycwl/basic/pricing/entity/BaseEntity.java +++ /dev/null @@ -1,29 +0,0 @@ -package com.ycwl.basic.pricing.entity; - -import com.baomidou.mybatisplus.annotation.IdType; -import com.baomidou.mybatisplus.annotation.TableId; -import lombok.Data; - -import java.util.Date; - -/** - * 基础实体类 - */ -@Data -public class BaseEntity { - - @TableId(type = IdType.AUTO) - private Long id; - - private Date createdTime; - - private Date updatedTime; - - private Long createBy; - - private Long updateBy; - - private Integer deleted; - - private Date deletedAt; -} \ No newline at end of file diff --git a/src/main/java/com/ycwl/basic/pricing/entity/PriceBundleConfig.java b/src/main/java/com/ycwl/basic/pricing/entity/PriceBundleConfig.java index bd2e705..219a55a 100644 --- a/src/main/java/com/ycwl/basic/pricing/entity/PriceBundleConfig.java +++ b/src/main/java/com/ycwl/basic/pricing/entity/PriceBundleConfig.java @@ -1,23 +1,27 @@ package com.ycwl.basic.pricing.entity; -import com.baomidou.mybatisplus.annotation.TableName; +import com.baomidou.mybatisplus.annotation.IdType; import com.baomidou.mybatisplus.annotation.TableField; +import com.baomidou.mybatisplus.annotation.TableId; +import com.baomidou.mybatisplus.annotation.TableName; import com.ycwl.basic.pricing.dto.BundleProductItem; import com.ycwl.basic.pricing.handler.BundleProductListTypeHandler; import lombok.Data; -import lombok.EqualsAndHashCode; import org.apache.ibatis.type.JdbcType; import java.math.BigDecimal; +import java.util.Date; import java.util.List; /** * 一口价配置实体 */ @Data -@EqualsAndHashCode(callSuper = true) @TableName("price_bundle_config") -public class PriceBundleConfig extends BaseEntity { +public class PriceBundleConfig { + + @TableId(value = "id", type = IdType.AUTO) + private Long id; /** * 套餐名称 @@ -55,4 +59,18 @@ public class PriceBundleConfig extends BaseEntity { * 是否启用 */ private Boolean isActive; + + @TableField("create_time") + private Date createTime; + + @TableField("update_time") + private Date updateTime; + + private Long createBy; + + private Long updateBy; + + private Integer deleted; + + private Date deletedAt; } \ No newline at end of file diff --git a/src/main/java/com/ycwl/basic/pricing/entity/PriceCouponClaimRecord.java b/src/main/java/com/ycwl/basic/pricing/entity/PriceCouponClaimRecord.java index a48511d..dd5c24b 100644 --- a/src/main/java/com/ycwl/basic/pricing/entity/PriceCouponClaimRecord.java +++ b/src/main/java/com/ycwl/basic/pricing/entity/PriceCouponClaimRecord.java @@ -1,9 +1,11 @@ package com.ycwl.basic.pricing.entity; +import com.baomidou.mybatisplus.annotation.IdType; +import com.baomidou.mybatisplus.annotation.TableField; +import com.baomidou.mybatisplus.annotation.TableId; import com.baomidou.mybatisplus.annotation.TableName; import com.ycwl.basic.pricing.enums.CouponStatus; import lombok.Data; -import lombok.EqualsAndHashCode; import java.util.Date; @@ -11,9 +13,11 @@ import java.util.Date; * 优惠券领用记录实体 */ @Data -@EqualsAndHashCode(callSuper = true) @TableName("price_coupon_claim_record") -public class PriceCouponClaimRecord extends BaseEntity { +public class PriceCouponClaimRecord { + + @TableId(value = "id", type = IdType.AUTO) + private Long id; /** * 优惠券ID @@ -49,4 +53,14 @@ public class PriceCouponClaimRecord extends BaseEntity { * 景区ID - 记录优惠券在哪个景区被领取/使用 */ private String scenicId; + + @TableField("create_time") + private Date createTime; + + @TableField("update_time") + private Date updateTime; + + private Integer deleted; + + private Date deletedAt; } \ No newline at end of file diff --git a/src/main/java/com/ycwl/basic/pricing/entity/PriceCouponConfig.java b/src/main/java/com/ycwl/basic/pricing/entity/PriceCouponConfig.java index 386e6fe..06be0ce 100644 --- a/src/main/java/com/ycwl/basic/pricing/entity/PriceCouponConfig.java +++ b/src/main/java/com/ycwl/basic/pricing/entity/PriceCouponConfig.java @@ -1,20 +1,25 @@ package com.ycwl.basic.pricing.entity; +import com.baomidou.mybatisplus.annotation.IdType; +import com.baomidou.mybatisplus.annotation.TableField; +import com.baomidou.mybatisplus.annotation.TableId; import com.baomidou.mybatisplus.annotation.TableName; import com.ycwl.basic.pricing.enums.CouponType; import lombok.Data; -import lombok.EqualsAndHashCode; import java.math.BigDecimal; import java.time.LocalDateTime; +import java.util.Date; /** * 优惠券配置实体 */ @Data -@EqualsAndHashCode(callSuper = true) @TableName("price_coupon_config") -public class PriceCouponConfig extends BaseEntity { +public class PriceCouponConfig { + + @TableId(value = "id", type = IdType.AUTO) + private Long id; /** * 优惠券名称 @@ -75,4 +80,18 @@ public class PriceCouponConfig extends BaseEntity { * 景区ID - 限制优惠券只能在该景区使用 */ private String scenicId; + + @TableField("create_time") + private Date createTime; + + @TableField("update_time") + private Date updateTime; + + private Long createBy; + + private Long updateBy; + + private Integer deleted; + + private Date deletedAt; } \ No newline at end of file diff --git a/src/main/java/com/ycwl/basic/pricing/entity/PriceProductConfig.java b/src/main/java/com/ycwl/basic/pricing/entity/PriceProductConfig.java index 8fec5d8..4677774 100644 --- a/src/main/java/com/ycwl/basic/pricing/entity/PriceProductConfig.java +++ b/src/main/java/com/ycwl/basic/pricing/entity/PriceProductConfig.java @@ -1,18 +1,23 @@ package com.ycwl.basic.pricing.entity; +import com.baomidou.mybatisplus.annotation.IdType; +import com.baomidou.mybatisplus.annotation.TableField; +import com.baomidou.mybatisplus.annotation.TableId; import com.baomidou.mybatisplus.annotation.TableName; import lombok.Data; -import lombok.EqualsAndHashCode; import java.math.BigDecimal; +import java.util.Date; /** * 商品价格配置实体 */ @Data -@EqualsAndHashCode(callSuper = true) @TableName("price_product_config") -public class PriceProductConfig extends BaseEntity { +public class PriceProductConfig { + + @TableId(value = "id", type = IdType.AUTO) + private Long id; /** * 商品类型 @@ -53,4 +58,18 @@ public class PriceProductConfig extends BaseEntity { * 是否启用 */ private Boolean isActive; + + @TableField("create_time") + private Date createTime; + + @TableField("update_time") + private Date updateTime; + + private Long createBy; + + private Long updateBy; + + private Integer deleted; + + private Date deletedAt; } \ No newline at end of file diff --git a/src/main/java/com/ycwl/basic/pricing/entity/PriceTierConfig.java b/src/main/java/com/ycwl/basic/pricing/entity/PriceTierConfig.java index 4c76593..f3a3e95 100644 --- a/src/main/java/com/ycwl/basic/pricing/entity/PriceTierConfig.java +++ b/src/main/java/com/ycwl/basic/pricing/entity/PriceTierConfig.java @@ -1,18 +1,23 @@ package com.ycwl.basic.pricing.entity; +import com.baomidou.mybatisplus.annotation.IdType; +import com.baomidou.mybatisplus.annotation.TableField; +import com.baomidou.mybatisplus.annotation.TableId; import com.baomidou.mybatisplus.annotation.TableName; import lombok.Data; -import lombok.EqualsAndHashCode; import java.math.BigDecimal; +import java.util.Date; /** * 阶梯定价配置实体 */ @Data -@EqualsAndHashCode(callSuper = true) @TableName("price_tier_config") -public class PriceTierConfig extends BaseEntity { +public class PriceTierConfig { + + @TableId(value = "id", type = IdType.AUTO) + private Long id; /** * 商品类型 @@ -63,4 +68,18 @@ public class PriceTierConfig extends BaseEntity { * 是否启用 */ private Boolean isActive; + + @TableField("create_time") + private Date createTime; + + @TableField("update_time") + private Date updateTime; + + private Long createBy; + + private Long updateBy; + + private Integer deleted; + + private Date deletedAt; } \ No newline at end of file diff --git a/src/main/java/com/ycwl/basic/pricing/entity/PriceVoucherBatchConfig.java b/src/main/java/com/ycwl/basic/pricing/entity/PriceVoucherBatchConfig.java index a68510c..49e4724 100644 --- a/src/main/java/com/ycwl/basic/pricing/entity/PriceVoucherBatchConfig.java +++ b/src/main/java/com/ycwl/basic/pricing/entity/PriceVoucherBatchConfig.java @@ -1,10 +1,10 @@ package com.ycwl.basic.pricing.entity; import com.baomidou.mybatisplus.annotation.IdType; +import com.baomidou.mybatisplus.annotation.TableField; import com.baomidou.mybatisplus.annotation.TableId; import com.baomidou.mybatisplus.annotation.TableName; import lombok.Data; -import lombok.EqualsAndHashCode; import java.math.BigDecimal; import java.util.Date; @@ -13,9 +13,8 @@ import java.util.Date; * 券码批次配置实体 */ @Data -@EqualsAndHashCode(callSuper = true) @TableName("price_voucher_batch_config") -public class PriceVoucherBatchConfig extends BaseEntity { +public class PriceVoucherBatchConfig { @TableId(value = "id", type = IdType.AUTO) private Long id; @@ -65,8 +64,17 @@ public class PriceVoucherBatchConfig extends BaseEntity { */ private Integer status; - /** - * 创建人ID - */ + @TableField("create_time") + private Date createTime; + + @TableField("update_time") + private Date updateTime; + private Long createBy; + + private Long updateBy; + + private Integer deleted; + + private Date deletedAt; } \ No newline at end of file diff --git a/src/main/java/com/ycwl/basic/pricing/entity/PriceVoucherCode.java b/src/main/java/com/ycwl/basic/pricing/entity/PriceVoucherCode.java index 6efcbdc..1b59dc2 100644 --- a/src/main/java/com/ycwl/basic/pricing/entity/PriceVoucherCode.java +++ b/src/main/java/com/ycwl/basic/pricing/entity/PriceVoucherCode.java @@ -1,10 +1,10 @@ package com.ycwl.basic.pricing.entity; import com.baomidou.mybatisplus.annotation.IdType; +import com.baomidou.mybatisplus.annotation.TableField; import com.baomidou.mybatisplus.annotation.TableId; import com.baomidou.mybatisplus.annotation.TableName; import lombok.Data; -import lombok.EqualsAndHashCode; import java.util.Date; @@ -12,9 +12,8 @@ import java.util.Date; * 券码实体 */ @Data -@EqualsAndHashCode(callSuper = true) @TableName("price_voucher_code") -public class PriceVoucherCode extends BaseEntity { +public class PriceVoucherCode { @TableId(value = "id", type = IdType.AUTO) private Long id; @@ -58,4 +57,14 @@ public class PriceVoucherCode extends BaseEntity { * 使用备注 */ private String remark; + + @TableField("create_time") + private Date createTime; + + @TableField("update_time") + private Date updateTime; + + private Integer deleted; + + private Date deletedAt; } \ No newline at end of file diff --git a/src/main/java/com/ycwl/basic/pricing/service/impl/CouponServiceImpl.java b/src/main/java/com/ycwl/basic/pricing/service/impl/CouponServiceImpl.java index c28335c..82bbc13 100644 --- a/src/main/java/com/ycwl/basic/pricing/service/impl/CouponServiceImpl.java +++ b/src/main/java/com/ycwl/basic/pricing/service/impl/CouponServiceImpl.java @@ -152,7 +152,7 @@ public class CouponServiceImpl implements ICouponService { record.setStatus(CouponStatus.USED); record.setUseTime(useTime); record.setOrderId(request.getOrderId()); - record.setUpdatedTime(new Date()); + record.setUpdateTime(new Date()); // 如果请求中包含景区ID,记录到使用记录中 if (request.getScenicId() != null && !request.getScenicId().isEmpty()) { diff --git a/src/main/java/com/ycwl/basic/pricing/service/impl/PricingManagementServiceImpl.java b/src/main/java/com/ycwl/basic/pricing/service/impl/PricingManagementServiceImpl.java index 20f0fcc..ec402f4 100644 --- a/src/main/java/com/ycwl/basic/pricing/service/impl/PricingManagementServiceImpl.java +++ b/src/main/java/com/ycwl/basic/pricing/service/impl/PricingManagementServiceImpl.java @@ -35,8 +35,8 @@ public class PricingManagementServiceImpl implements IPricingManagementService { } } - config.setCreatedTime(new Date()); - config.setUpdatedTime(new Date()); + config.setCreateTime(new Date()); + config.setUpdateTime(new Date()); productConfigMapper.insertProductConfig(config); return config.getId(); } @@ -44,7 +44,7 @@ public class PricingManagementServiceImpl implements IPricingManagementService { @Override @Transactional public boolean updateProductConfig(PriceProductConfig config) { - config.setUpdatedTime(new Date()); + config.setUpdateTime(new Date()); return productConfigMapper.updateProductConfig(config) > 0; } @@ -58,8 +58,8 @@ public class PricingManagementServiceImpl implements IPricingManagementService { config.getProductType(), config.getMinQuantity(), config.getMaxQuantity()); } - config.setCreatedTime(new Date()); - config.setUpdatedTime(new Date()); + config.setCreateTime(new Date()); + config.setUpdateTime(new Date()); tierConfigMapper.insertTierConfig(config); return config.getId(); } @@ -67,15 +67,15 @@ public class PricingManagementServiceImpl implements IPricingManagementService { @Override @Transactional public boolean updateTierConfig(PriceTierConfig config) { - config.setUpdatedTime(new Date()); + config.setUpdateTime(new Date()); return tierConfigMapper.updateTierConfig(config) > 0; } @Override @Transactional public Long createCouponConfig(PriceCouponConfig config) { - config.setCreatedTime(new Date()); - config.setUpdatedTime(new Date()); + config.setCreateTime(new Date()); + config.setUpdateTime(new Date()); couponConfigMapper.insertCoupon(config); return config.getId(); } @@ -83,7 +83,7 @@ public class PricingManagementServiceImpl implements IPricingManagementService { @Override @Transactional public boolean updateCouponConfig(PriceCouponConfig config) { - config.setUpdatedTime(new Date()); + config.setUpdateTime(new Date()); return couponConfigMapper.updateCoupon(config) > 0; } @@ -91,8 +91,8 @@ public class PricingManagementServiceImpl implements IPricingManagementService { @Transactional public Long createCouponClaimRecord(PriceCouponClaimRecord record) { record.setClaimTime(new Date()); - record.setCreatedTime(new Date()); - record.setUpdatedTime(new Date()); + record.setCreateTime(new Date()); + record.setUpdateTime(new Date()); couponClaimRecordMapper.insertClaimRecord(record); return record.getId(); } @@ -100,15 +100,15 @@ public class PricingManagementServiceImpl implements IPricingManagementService { @Override @Transactional public boolean updateCouponClaimRecord(PriceCouponClaimRecord record) { - record.setUpdatedTime(new Date()); + record.setUpdateTime(new Date()); return couponClaimRecordMapper.updateClaimRecord(record) > 0; } @Override @Transactional public Long createBundleConfig(PriceBundleConfig config) { - config.setCreatedTime(new Date()); - config.setUpdatedTime(new Date()); + config.setCreateTime(new Date()); + config.setUpdateTime(new Date()); bundleConfigMapper.insertBundleConfig(config); return config.getId(); } @@ -116,7 +116,7 @@ public class PricingManagementServiceImpl implements IPricingManagementService { @Override @Transactional public boolean updateBundleConfig(PriceBundleConfig config) { - config.setUpdatedTime(new Date()); + config.setUpdateTime(new Date()); return bundleConfigMapper.updateBundleConfig(config) > 0; } diff --git a/src/main/java/com/ycwl/basic/pricing/service/impl/VoucherBatchServiceImpl.java b/src/main/java/com/ycwl/basic/pricing/service/impl/VoucherBatchServiceImpl.java index e430511..805fc5b 100644 --- a/src/main/java/com/ycwl/basic/pricing/service/impl/VoucherBatchServiceImpl.java +++ b/src/main/java/com/ycwl/basic/pricing/service/impl/VoucherBatchServiceImpl.java @@ -64,7 +64,7 @@ public class VoucherBatchServiceImpl implements VoucherBatchService { batch.setUsedCount(0); batch.setClaimedCount(0); batch.setStatus(1); - batch.setCreatedTime(new Date()); + batch.setCreateTime(new Date()); String userIdStr = BaseContextHandler.getUserId(); if (userIdStr != null) { batch.setCreateBy(Long.valueOf(userIdStr)); @@ -88,7 +88,7 @@ public class VoucherBatchServiceImpl implements VoucherBatchService { .eq(req.getBrokerId() != null, PriceVoucherBatchConfig::getBrokerId, req.getBrokerId()) .eq(req.getStatus() != null, PriceVoucherBatchConfig::getStatus, req.getStatus()) .like(StringUtils.hasText(req.getBatchName()), PriceVoucherBatchConfig::getBatchName, req.getBatchName()) - .orderByDesc(PriceVoucherBatchConfig::getCreatedTime); + .orderByDesc(PriceVoucherBatchConfig::getCreateTime); Page entityPage = voucherBatchMapper.selectPage(page, wrapper); @@ -174,7 +174,7 @@ public class VoucherBatchServiceImpl implements VoucherBatchService { .eq(PriceVoucherBatchConfig::getStatus, 1) .eq(PriceVoucherBatchConfig::getDeleted, 0) .apply("claimed_count < total_count") - .orderByDesc(PriceVoucherBatchConfig::getCreatedTime); + .orderByDesc(PriceVoucherBatchConfig::getCreateTime); return voucherBatchMapper.selectOne(wrapper); } diff --git a/src/main/java/com/ycwl/basic/pricing/service/impl/VoucherCodeServiceImpl.java b/src/main/java/com/ycwl/basic/pricing/service/impl/VoucherCodeServiceImpl.java index 1ca22e2..d3710b2 100644 --- a/src/main/java/com/ycwl/basic/pricing/service/impl/VoucherCodeServiceImpl.java +++ b/src/main/java/com/ycwl/basic/pricing/service/impl/VoucherCodeServiceImpl.java @@ -15,6 +15,7 @@ import com.ycwl.basic.pricing.mapper.PriceVoucherCodeMapper; import com.ycwl.basic.pricing.service.VoucherBatchService; import com.ycwl.basic.pricing.service.VoucherCodeService; import lombok.RequiredArgsConstructor; +import lombok.extern.slf4j.Slf4j; import org.springframework.beans.BeanUtils; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.context.annotation.Lazy; @@ -22,14 +23,23 @@ import org.springframework.stereotype.Service; import org.springframework.transaction.annotation.Transactional; import org.springframework.util.StringUtils; +import java.security.SecureRandom; import java.util.ArrayList; import java.util.Date; import java.util.List; -import java.util.UUID; +import java.util.Objects; +@Slf4j @Service public class VoucherCodeServiceImpl implements VoucherCodeService { + // 券码生成相关常量 + private static final String SAFE_CHARS = "23456789ABCDEFGHJKMNPQRTUVWXYZ"; + private static final char[] SAFE_CHARS_ARRAY = SAFE_CHARS.toCharArray(); + private static final int CODE_LENGTH = 6; + private static final int MAX_RETRY = 10; + private static final SecureRandom RANDOM = new SecureRandom(); + @Autowired private PriceVoucherCodeMapper voucherCodeMapper; @Autowired @@ -48,7 +58,7 @@ public class VoucherCodeServiceImpl implements VoucherCodeService { code.setScenicId(scenicId); code.setCode(generateVoucherCode()); code.setStatus(VoucherCodeStatus.UNCLAIMED.getCode()); - code.setCreatedTime(new Date()); + code.setCreateTime(new Date()); code.setDeleted(0); codes.add(code); } @@ -107,7 +117,7 @@ public class VoucherCodeServiceImpl implements VoucherCodeService { .eq(req.getFaceId() != null, PriceVoucherCode::getFaceId, req.getFaceId()) .eq(req.getStatus() != null, PriceVoucherCode::getStatus, req.getStatus()) .like(StringUtils.hasText(req.getCode()), PriceVoucherCode::getCode, req.getCode()) - .orderByDesc(PriceVoucherCode::getCreatedTime); + .orderByDesc(PriceVoucherCode::getId); Page entityPage = voucherCodeMapper.selectPage(page, wrapper); @@ -150,7 +160,7 @@ public class VoucherCodeServiceImpl implements VoucherCodeService { throw new BizException(404, "券码不存在"); } - if (code.getStatus() != VoucherCodeStatus.CLAIMED_UNUSED.getCode()) { + if (!Objects.equals(code.getStatus(), VoucherCodeStatus.CLAIMED_UNUSED.getCode())) { throw new BizException(400, "券码状态异常,无法使用"); } @@ -169,8 +179,56 @@ public class VoucherCodeServiceImpl implements VoucherCodeService { return count == 0; } + /** + * 生成6位安全券码(去除易混淆字符) + * 字符集:数字2-9 + 大写字母(去除0,1,I,L,O,S) + * + * @return 6位券码 + */ private String generateVoucherCode() { - return UUID.randomUUID().toString().replace("-", "").substring(0, 8).toUpperCase(); + for (int attempt = 0; attempt < MAX_RETRY; attempt++) { + String code = generateRandomCode(); + log.debug("生成券码候选: {} (尝试第{}次)", code, attempt + 1); + + if (!isCodeExists(code)) { + log.info("成功生成券码: {} (字符集大小: {}, 理论组合数: {})", + code, SAFE_CHARS.length(), Math.pow(SAFE_CHARS.length(), CODE_LENGTH)); + return code; + } + + log.warn("券码重复,重新生成: {}", code); + } + + // 如果重试次数用完仍有重复,抛出异常 + log.error("券码生成失败:达到最大重试次数 {}", MAX_RETRY); + throw new RuntimeException("券码生成失败:达到最大重试次数,请稍后重试"); + } + + /** + * 生成随机6位字符 + * + * @return 随机6位字符 + */ + private String generateRandomCode() { + StringBuilder code = new StringBuilder(CODE_LENGTH); + for (int i = 0; i < CODE_LENGTH; i++) { + int randomIndex = RANDOM.nextInt(SAFE_CHARS_ARRAY.length); + code.append(SAFE_CHARS_ARRAY[randomIndex]); + } + return code.toString(); + } + + /** + * 检查券码是否已存在 + * + * @param code 券码 + * @return 是否存在 + */ + private boolean isCodeExists(String code) { + LambdaQueryWrapper wrapper = new LambdaQueryWrapper<>(); + wrapper.eq(PriceVoucherCode::getCode, code) + .eq(PriceVoucherCode::getDeleted, 0); + return voucherCodeMapper.selectCount(wrapper) > 0; } private VoucherCodeResp convertToResp(PriceVoucherCode code, PriceVoucherBatchConfig batch) {