You've already forked FrameTour-BE
feat(product): 实现商品类型能力配置管理功能
- 新增商品类型能力配置的增删改查接口 - 实现分页查询、分类查询、状态筛选等功能 - 支持批量初始化默认配置和缓存刷新 - 提供定价模式、重复检查策略等枚举选项接口 - 实现完整的参数校验和业务逻辑处理 - 添加详细的日志记录和异常处理机制
This commit is contained in:
@@ -0,0 +1,229 @@
|
||||
package com.ycwl.basic.product.controller;
|
||||
|
||||
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
|
||||
import com.ycwl.basic.utils.ApiResponse;
|
||||
import com.ycwl.basic.pricing.enums.ProductCategory;
|
||||
import com.ycwl.basic.product.capability.DuplicateCheckStrategy;
|
||||
import com.ycwl.basic.product.capability.PricingMode;
|
||||
import com.ycwl.basic.product.capability.ProductTypeCapability;
|
||||
import com.ycwl.basic.product.dto.EnumOptionResponse;
|
||||
import com.ycwl.basic.product.dto.ProductTypeCapabilityRequest;
|
||||
import com.ycwl.basic.product.dto.ProductTypeCapabilityResponse;
|
||||
import com.ycwl.basic.product.service.IProductTypeCapabilityManagementService;
|
||||
import com.ycwl.basic.product.service.IProductTypeCapabilityService;
|
||||
import lombok.RequiredArgsConstructor;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import org.springframework.web.bind.annotation.*;
|
||||
|
||||
import java.util.Arrays;
|
||||
import java.util.List;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
/**
|
||||
* 商品类型能力配置管理控制器
|
||||
* 提供管理端的配置管理功能
|
||||
*/
|
||||
@Slf4j
|
||||
@RestController
|
||||
@RequestMapping("/api/product/admin/capability")
|
||||
@RequiredArgsConstructor
|
||||
public class ProductTypeCapabilityController {
|
||||
|
||||
private final IProductTypeCapabilityManagementService managementService;
|
||||
private final IProductTypeCapabilityService capabilityService;
|
||||
|
||||
/**
|
||||
* 分页查询商品类型能力配置
|
||||
*/
|
||||
@GetMapping("/page")
|
||||
public ApiResponse<Page<ProductTypeCapabilityResponse>> queryByPage(
|
||||
@RequestParam(defaultValue = "1") int pageNum,
|
||||
@RequestParam(defaultValue = "10") int pageSize,
|
||||
@RequestParam(required = false) String productType,
|
||||
@RequestParam(required = false) String category,
|
||||
@RequestParam(required = false) Boolean isActive) {
|
||||
|
||||
Page<ProductTypeCapability> page = managementService.queryByPage(
|
||||
pageNum, pageSize, productType, category, isActive);
|
||||
|
||||
// 转换为响应DTO
|
||||
Page<ProductTypeCapabilityResponse> responsePage = new Page<>(page.getCurrent(), page.getSize(), page.getTotal());
|
||||
List<ProductTypeCapabilityResponse> responseList = page.getRecords().stream()
|
||||
.map(ProductTypeCapabilityResponse::fromEntity)
|
||||
.collect(Collectors.toList());
|
||||
responsePage.setRecords(responseList);
|
||||
|
||||
return ApiResponse.success(responsePage);
|
||||
}
|
||||
|
||||
/**
|
||||
* 查询所有商品类型能力配置
|
||||
*/
|
||||
@GetMapping("/list")
|
||||
public ApiResponse<List<ProductTypeCapabilityResponse>> queryAll(
|
||||
@RequestParam(defaultValue = "false") boolean includeInactive) {
|
||||
|
||||
List<ProductTypeCapability> capabilities = managementService.queryAll(includeInactive);
|
||||
List<ProductTypeCapabilityResponse> responseList = capabilities.stream()
|
||||
.map(ProductTypeCapabilityResponse::fromEntity)
|
||||
.collect(Collectors.toList());
|
||||
|
||||
return ApiResponse.success(responseList);
|
||||
}
|
||||
|
||||
/**
|
||||
* 根据分类查询商品类型能力配置
|
||||
*/
|
||||
@GetMapping("/category/{category}")
|
||||
public ApiResponse<List<ProductTypeCapabilityResponse>> queryByCategory(
|
||||
@PathVariable String category) {
|
||||
|
||||
List<ProductTypeCapability> capabilities = managementService.queryByCategory(category);
|
||||
List<ProductTypeCapabilityResponse> responseList = capabilities.stream()
|
||||
.map(ProductTypeCapabilityResponse::fromEntity)
|
||||
.collect(Collectors.toList());
|
||||
|
||||
return ApiResponse.success(responseList);
|
||||
}
|
||||
|
||||
/**
|
||||
* 根据ID查询配置详情
|
||||
*/
|
||||
@GetMapping("/{id}")
|
||||
public ApiResponse<ProductTypeCapabilityResponse> getById(
|
||||
@PathVariable Long id) {
|
||||
|
||||
ProductTypeCapability capability = managementService.getById(id);
|
||||
return ApiResponse.success(ProductTypeCapabilityResponse.fromEntity(capability));
|
||||
}
|
||||
|
||||
/**
|
||||
* 根据商品类型代码查询配置详情
|
||||
*/
|
||||
@GetMapping("/product-type/{productType}")
|
||||
public ApiResponse<ProductTypeCapabilityResponse> getByProductType(
|
||||
@PathVariable String productType) {
|
||||
|
||||
ProductTypeCapability capability = managementService.getByProductType(productType);
|
||||
return ApiResponse.success(ProductTypeCapabilityResponse.fromEntity(capability));
|
||||
}
|
||||
|
||||
/**
|
||||
* 创建商品类型能力配置
|
||||
*/
|
||||
@PostMapping
|
||||
public ApiResponse<ProductTypeCapabilityResponse> create(
|
||||
@RequestBody ProductTypeCapabilityRequest request) {
|
||||
|
||||
ProductTypeCapability capability = managementService.create(request);
|
||||
return ApiResponse.success(ProductTypeCapabilityResponse.fromEntity(capability));
|
||||
}
|
||||
|
||||
/**
|
||||
* 更新商品类型能力配置
|
||||
*/
|
||||
@PutMapping("/{id}")
|
||||
public ApiResponse<ProductTypeCapabilityResponse> update(
|
||||
@PathVariable Long id,
|
||||
@RequestBody ProductTypeCapabilityRequest request) {
|
||||
|
||||
ProductTypeCapability capability = managementService.update(id, request);
|
||||
return ApiResponse.success(ProductTypeCapabilityResponse.fromEntity(capability));
|
||||
}
|
||||
|
||||
/**
|
||||
* 删除商品类型能力配置
|
||||
*/
|
||||
@DeleteMapping("/{id}")
|
||||
public ApiResponse<Void> delete(
|
||||
@PathVariable Long id) {
|
||||
|
||||
managementService.delete(id);
|
||||
return ApiResponse.success(null);
|
||||
}
|
||||
|
||||
/**
|
||||
* 启用/禁用商品类型能力配置
|
||||
*/
|
||||
@PutMapping("/{id}/status")
|
||||
public ApiResponse<Void> updateStatus(
|
||||
@PathVariable Long id,
|
||||
@RequestParam Boolean isActive) {
|
||||
|
||||
managementService.updateStatus(id, isActive);
|
||||
return ApiResponse.success(null);
|
||||
}
|
||||
|
||||
/**
|
||||
* 批量初始化商品类型能力配置
|
||||
* 为所有已定义的商品类型创建默认配置
|
||||
*/
|
||||
@PostMapping("/init-defaults")
|
||||
public ApiResponse<Integer> initializeDefaultCapabilities() {
|
||||
|
||||
int count = managementService.initializeDefaultCapabilities();
|
||||
return ApiResponse.success(count);
|
||||
}
|
||||
|
||||
/**
|
||||
* 刷新所有缓存
|
||||
*/
|
||||
@PostMapping("/refresh-cache")
|
||||
public ApiResponse<Void> refreshCache() {
|
||||
|
||||
capabilityService.refreshCache();
|
||||
return ApiResponse.success(null);
|
||||
}
|
||||
|
||||
/**
|
||||
* 刷新指定商品类型的缓存
|
||||
*/
|
||||
@PostMapping("/refresh-cache/{productType}")
|
||||
public ApiResponse<Void> refreshCacheByProductType(
|
||||
@PathVariable String productType) {
|
||||
|
||||
capabilityService.refreshCache(productType);
|
||||
return ApiResponse.success(null);
|
||||
}
|
||||
|
||||
// ========== 枚举选项接口 ==========
|
||||
|
||||
/**
|
||||
* 获取定价模式枚举选项
|
||||
*/
|
||||
@GetMapping("/enums/pricing-modes")
|
||||
public ApiResponse<List<EnumOptionResponse>> getPricingModes() {
|
||||
|
||||
List<EnumOptionResponse> options = Arrays.stream(PricingMode.values())
|
||||
.map(mode -> new EnumOptionResponse(mode.getCode(), mode.getDescription()))
|
||||
.collect(Collectors.toList());
|
||||
|
||||
return ApiResponse.success(options);
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取重复检查策略枚举选项
|
||||
*/
|
||||
@GetMapping("/enums/duplicate-check-strategies")
|
||||
public ApiResponse<List<EnumOptionResponse>> getDuplicateCheckStrategies() {
|
||||
|
||||
List<EnumOptionResponse> options = Arrays.stream(DuplicateCheckStrategy.values())
|
||||
.map(strategy -> new EnumOptionResponse(strategy.getCode(), strategy.getDescription()))
|
||||
.collect(Collectors.toList());
|
||||
|
||||
return ApiResponse.success(options);
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取商品分类枚举选项
|
||||
*/
|
||||
@GetMapping("/enums/categories")
|
||||
public ApiResponse<List<EnumOptionResponse>> getCategories() {
|
||||
|
||||
List<EnumOptionResponse> options = Arrays.stream(ProductCategory.values())
|
||||
.map(category -> new EnumOptionResponse(category.getCode(), category.getDescription()))
|
||||
.collect(Collectors.toList());
|
||||
|
||||
return ApiResponse.success(options);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,25 @@
|
||||
package com.ycwl.basic.product.dto;
|
||||
|
||||
import lombok.AllArgsConstructor;
|
||||
import lombok.Data;
|
||||
import lombok.NoArgsConstructor;
|
||||
|
||||
/**
|
||||
* 枚举选项响应DTO
|
||||
* 用于前端下拉框等场景
|
||||
*/
|
||||
@Data
|
||||
@NoArgsConstructor
|
||||
@AllArgsConstructor
|
||||
public class EnumOptionResponse {
|
||||
|
||||
/**
|
||||
* 枚举代码
|
||||
*/
|
||||
private String code;
|
||||
|
||||
/**
|
||||
* 枚举描述
|
||||
*/
|
||||
private String description;
|
||||
}
|
||||
@@ -0,0 +1,91 @@
|
||||
package com.ycwl.basic.product.dto;
|
||||
|
||||
import lombok.Data;
|
||||
|
||||
import java.util.Map;
|
||||
|
||||
/**
|
||||
* 商品类型能力配置请求DTO
|
||||
*/
|
||||
@Data
|
||||
public class ProductTypeCapabilityRequest {
|
||||
|
||||
/**
|
||||
* 商品类型代码(唯一)
|
||||
* 如:VLOG_VIDEO, PHOTO_PRINT 等
|
||||
*/
|
||||
private String productType;
|
||||
|
||||
/**
|
||||
* 显示名称
|
||||
*/
|
||||
private String displayName;
|
||||
|
||||
/**
|
||||
* 商品分类
|
||||
* VLOG, PHOTO, VIDEO, PRINT, OTHER
|
||||
*/
|
||||
private String category;
|
||||
|
||||
// ========== 定价相关 ==========
|
||||
|
||||
/**
|
||||
* 定价模式
|
||||
* FIXED: 固定价格
|
||||
* QUANTITY_BASED: 基于数量
|
||||
* TIERED: 分层定价
|
||||
*/
|
||||
private String pricingMode;
|
||||
|
||||
/**
|
||||
* 是否支持阶梯定价
|
||||
*/
|
||||
private Boolean supportsTierPricing;
|
||||
|
||||
// ========== 购买限制 ==========
|
||||
|
||||
/**
|
||||
* 是否允许重复购买
|
||||
*/
|
||||
private Boolean allowDuplicatePurchase;
|
||||
|
||||
/**
|
||||
* 重复购买检查策略
|
||||
* NO_CHECK, CHECK_BY_VIDEO_ID, CHECK_BY_SET_ID, CUSTOM
|
||||
*/
|
||||
private String duplicateCheckStrategy;
|
||||
|
||||
// ========== 优惠能力 ==========
|
||||
|
||||
/**
|
||||
* 是否可使用优惠券
|
||||
*/
|
||||
private Boolean canUseCoupon;
|
||||
|
||||
/**
|
||||
* 是否可使用券码
|
||||
*/
|
||||
private Boolean canUseVoucher;
|
||||
|
||||
/**
|
||||
* 是否可使用一口价优惠
|
||||
*/
|
||||
private Boolean canUseOnePrice;
|
||||
|
||||
/**
|
||||
* 是否可参与打包优惠
|
||||
*/
|
||||
private Boolean canUseBundle;
|
||||
|
||||
// ========== 扩展属性 ==========
|
||||
|
||||
/**
|
||||
* 扩展属性(JSON 格式)
|
||||
*/
|
||||
private Map<String, Object> metadata;
|
||||
|
||||
/**
|
||||
* 是否启用
|
||||
*/
|
||||
private Boolean isActive;
|
||||
}
|
||||
@@ -0,0 +1,85 @@
|
||||
package com.ycwl.basic.product.dto;
|
||||
|
||||
import com.ycwl.basic.product.capability.ProductTypeCapability;
|
||||
import lombok.Data;
|
||||
|
||||
import java.time.LocalDateTime;
|
||||
import java.util.Map;
|
||||
|
||||
/**
|
||||
* 商品类型能力配置响应DTO
|
||||
*/
|
||||
@Data
|
||||
public class ProductTypeCapabilityResponse {
|
||||
|
||||
private Long id;
|
||||
private String productType;
|
||||
private String displayName;
|
||||
private String category;
|
||||
private String categoryDescription;
|
||||
|
||||
// 定价相关
|
||||
private String pricingMode;
|
||||
private String pricingModeDescription;
|
||||
private Boolean supportsTierPricing;
|
||||
|
||||
// 购买限制
|
||||
private Boolean allowDuplicatePurchase;
|
||||
private String duplicateCheckStrategy;
|
||||
private String duplicateCheckStrategyDescription;
|
||||
|
||||
// 优惠能力
|
||||
private Boolean canUseCoupon;
|
||||
private Boolean canUseVoucher;
|
||||
private Boolean canUseOnePrice;
|
||||
private Boolean canUseBundle;
|
||||
|
||||
// 扩展属性
|
||||
private Map<String, Object> metadata;
|
||||
private Boolean isActive;
|
||||
private LocalDateTime createdAt;
|
||||
private LocalDateTime updatedAt;
|
||||
|
||||
/**
|
||||
* 从实体转换为响应DTO
|
||||
*/
|
||||
public static ProductTypeCapabilityResponse fromEntity(ProductTypeCapability entity) {
|
||||
if (entity == null) {
|
||||
return null;
|
||||
}
|
||||
|
||||
ProductTypeCapabilityResponse response = new ProductTypeCapabilityResponse();
|
||||
response.setId(entity.getId());
|
||||
response.setProductType(entity.getProductType());
|
||||
response.setDisplayName(entity.getDisplayName());
|
||||
response.setCategory(entity.getCategory());
|
||||
|
||||
// 定价相关
|
||||
response.setPricingMode(entity.getPricingMode());
|
||||
if (entity.getPricingModeEnum() != null) {
|
||||
response.setPricingModeDescription(entity.getPricingModeEnum().getDescription());
|
||||
}
|
||||
response.setSupportsTierPricing(entity.getSupportsTierPricing());
|
||||
|
||||
// 购买限制
|
||||
response.setAllowDuplicatePurchase(entity.getAllowDuplicatePurchase());
|
||||
response.setDuplicateCheckStrategy(entity.getDuplicateCheckStrategy());
|
||||
if (entity.getDuplicateCheckStrategyEnum() != null) {
|
||||
response.setDuplicateCheckStrategyDescription(entity.getDuplicateCheckStrategyEnum().getDescription());
|
||||
}
|
||||
|
||||
// 优惠能力
|
||||
response.setCanUseCoupon(entity.getCanUseCoupon());
|
||||
response.setCanUseVoucher(entity.getCanUseVoucher());
|
||||
response.setCanUseOnePrice(entity.getCanUseOnePrice());
|
||||
response.setCanUseBundle(entity.getCanUseBundle());
|
||||
|
||||
// 扩展属性
|
||||
response.setMetadata(entity.getMetadata());
|
||||
response.setIsActive(entity.getIsActive());
|
||||
response.setCreatedAt(entity.getCreatedAt());
|
||||
response.setUpdatedAt(entity.getUpdatedAt());
|
||||
|
||||
return response;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,99 @@
|
||||
package com.ycwl.basic.product.service;
|
||||
|
||||
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
|
||||
import com.ycwl.basic.product.capability.ProductTypeCapability;
|
||||
import com.ycwl.basic.product.dto.ProductTypeCapabilityRequest;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* 商品类型能力配置管理服务接口
|
||||
* 用于管理端的配置管理功能
|
||||
*/
|
||||
public interface IProductTypeCapabilityManagementService {
|
||||
|
||||
/**
|
||||
* 分页查询商品类型能力配置
|
||||
*
|
||||
* @param pageNum 页码
|
||||
* @param pageSize 每页大小
|
||||
* @param productType 商品类型代码(可选,支持模糊查询)
|
||||
* @param category 商品分类(可选)
|
||||
* @param isActive 是否启用(可选)
|
||||
* @return 分页结果
|
||||
*/
|
||||
Page<ProductTypeCapability> queryByPage(int pageNum, int pageSize,
|
||||
String productType, String category, Boolean isActive);
|
||||
|
||||
/**
|
||||
* 查询所有商品类型能力配置
|
||||
*
|
||||
* @param includeInactive 是否包含禁用的配置
|
||||
* @return 配置列表
|
||||
*/
|
||||
List<ProductTypeCapability> queryAll(boolean includeInactive);
|
||||
|
||||
/**
|
||||
* 根据分类查询商品类型能力配置
|
||||
*
|
||||
* @param category 商品分类
|
||||
* @return 配置列表
|
||||
*/
|
||||
List<ProductTypeCapability> queryByCategory(String category);
|
||||
|
||||
/**
|
||||
* 根据ID查询配置详情
|
||||
*
|
||||
* @param id 配置ID
|
||||
* @return 配置详情
|
||||
*/
|
||||
ProductTypeCapability getById(Long id);
|
||||
|
||||
/**
|
||||
* 根据商品类型代码查询配置详情
|
||||
*
|
||||
* @param productType 商品类型代码
|
||||
* @return 配置详情
|
||||
*/
|
||||
ProductTypeCapability getByProductType(String productType);
|
||||
|
||||
/**
|
||||
* 创建商品类型能力配置
|
||||
*
|
||||
* @param request 请求参数
|
||||
* @return 创建的配置
|
||||
*/
|
||||
ProductTypeCapability create(ProductTypeCapabilityRequest request);
|
||||
|
||||
/**
|
||||
* 更新商品类型能力配置
|
||||
*
|
||||
* @param id 配置ID
|
||||
* @param request 请求参数
|
||||
* @return 更新后的配置
|
||||
*/
|
||||
ProductTypeCapability update(Long id, ProductTypeCapabilityRequest request);
|
||||
|
||||
/**
|
||||
* 删除商品类型能力配置
|
||||
*
|
||||
* @param id 配置ID
|
||||
*/
|
||||
void delete(Long id);
|
||||
|
||||
/**
|
||||
* 启用/禁用商品类型能力配置
|
||||
*
|
||||
* @param id 配置ID
|
||||
* @param isActive 是否启用
|
||||
*/
|
||||
void updateStatus(Long id, Boolean isActive);
|
||||
|
||||
/**
|
||||
* 批量初始化商品类型能力配置
|
||||
* 为所有已定义的商品类型创建默认配置
|
||||
*
|
||||
* @return 初始化的配置数量
|
||||
*/
|
||||
int initializeDefaultCapabilities();
|
||||
}
|
||||
@@ -0,0 +1,355 @@
|
||||
package com.ycwl.basic.product.service.impl;
|
||||
|
||||
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
|
||||
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
|
||||
import com.ycwl.basic.pricing.enums.ProductCategory;
|
||||
import com.ycwl.basic.pricing.enums.ProductType;
|
||||
import com.ycwl.basic.product.capability.DuplicateCheckStrategy;
|
||||
import com.ycwl.basic.product.capability.PricingMode;
|
||||
import com.ycwl.basic.product.capability.ProductTypeCapability;
|
||||
import com.ycwl.basic.product.dto.ProductTypeCapabilityRequest;
|
||||
import com.ycwl.basic.product.mapper.ProductTypeCapabilityMapper;
|
||||
import com.ycwl.basic.product.service.IProductTypeCapabilityManagementService;
|
||||
import com.ycwl.basic.product.service.IProductTypeCapabilityService;
|
||||
import lombok.RequiredArgsConstructor;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import org.springframework.stereotype.Service;
|
||||
import org.springframework.transaction.annotation.Transactional;
|
||||
|
||||
import java.time.LocalDateTime;
|
||||
import java.util.ArrayList;
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* 商品类型能力配置管理服务实现
|
||||
*/
|
||||
@Slf4j
|
||||
@Service
|
||||
@RequiredArgsConstructor
|
||||
public class ProductTypeCapabilityManagementServiceImpl implements IProductTypeCapabilityManagementService {
|
||||
|
||||
private final ProductTypeCapabilityMapper mapper;
|
||||
private final IProductTypeCapabilityService capabilityService;
|
||||
|
||||
@Override
|
||||
public Page<ProductTypeCapability> queryByPage(int pageNum, int pageSize,
|
||||
String productType, String category, Boolean isActive) {
|
||||
Page<ProductTypeCapability> page = new Page<>(pageNum, pageSize);
|
||||
LambdaQueryWrapper<ProductTypeCapability> queryWrapper = new LambdaQueryWrapper<>();
|
||||
|
||||
if (productType != null && !productType.trim().isEmpty()) {
|
||||
queryWrapper.like(ProductTypeCapability::getProductType, productType);
|
||||
}
|
||||
|
||||
if (category != null && !category.trim().isEmpty()) {
|
||||
queryWrapper.eq(ProductTypeCapability::getCategory, category);
|
||||
}
|
||||
|
||||
if (isActive != null) {
|
||||
queryWrapper.eq(ProductTypeCapability::getIsActive, isActive);
|
||||
}
|
||||
|
||||
queryWrapper.orderByDesc(ProductTypeCapability::getCreatedAt);
|
||||
|
||||
return mapper.selectPage(page, queryWrapper);
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<ProductTypeCapability> queryAll(boolean includeInactive) {
|
||||
LambdaQueryWrapper<ProductTypeCapability> queryWrapper = new LambdaQueryWrapper<>();
|
||||
|
||||
if (!includeInactive) {
|
||||
queryWrapper.eq(ProductTypeCapability::getIsActive, true);
|
||||
}
|
||||
|
||||
queryWrapper.orderBy(true, true, ProductTypeCapability::getCategory, ProductTypeCapability::getProductType);
|
||||
|
||||
return mapper.selectList(queryWrapper);
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<ProductTypeCapability> queryByCategory(String category) {
|
||||
if (category == null || category.trim().isEmpty()) {
|
||||
return new ArrayList<>();
|
||||
}
|
||||
|
||||
LambdaQueryWrapper<ProductTypeCapability> queryWrapper = new LambdaQueryWrapper<>();
|
||||
queryWrapper.eq(ProductTypeCapability::getCategory, category);
|
||||
queryWrapper.eq(ProductTypeCapability::getIsActive, true);
|
||||
queryWrapper.orderByAsc(ProductTypeCapability::getProductType);
|
||||
|
||||
return mapper.selectList(queryWrapper);
|
||||
}
|
||||
|
||||
@Override
|
||||
public ProductTypeCapability getById(Long id) {
|
||||
if (id == null) {
|
||||
throw new IllegalArgumentException("配置ID不能为空");
|
||||
}
|
||||
|
||||
ProductTypeCapability capability = mapper.selectById(id);
|
||||
if (capability == null) {
|
||||
throw new IllegalArgumentException("配置不存在: " + id);
|
||||
}
|
||||
|
||||
return capability;
|
||||
}
|
||||
|
||||
@Override
|
||||
public ProductTypeCapability getByProductType(String productType) {
|
||||
if (productType == null || productType.trim().isEmpty()) {
|
||||
throw new IllegalArgumentException("商品类型代码不能为空");
|
||||
}
|
||||
|
||||
return mapper.selectByProductType(productType);
|
||||
}
|
||||
|
||||
@Transactional(rollbackFor = Exception.class)
|
||||
@Override
|
||||
public ProductTypeCapability create(ProductTypeCapabilityRequest request) {
|
||||
validateRequest(request, true);
|
||||
|
||||
// 检查商品类型代码是否已存在
|
||||
ProductTypeCapability existing = mapper.selectByProductType(request.getProductType());
|
||||
if (existing != null) {
|
||||
throw new IllegalArgumentException("商品类型代码已存在: " + request.getProductType());
|
||||
}
|
||||
|
||||
ProductTypeCapability capability = convertToEntity(request);
|
||||
capability.setCreatedAt(LocalDateTime.now());
|
||||
capability.setUpdatedAt(LocalDateTime.now());
|
||||
|
||||
mapper.insert(capability);
|
||||
|
||||
// 刷新缓存
|
||||
capabilityService.refreshCache(capability.getProductType());
|
||||
|
||||
log.info("创建商品类型能力配置成功: {}", capability.getProductType());
|
||||
return capability;
|
||||
}
|
||||
|
||||
@Transactional(rollbackFor = Exception.class)
|
||||
@Override
|
||||
public ProductTypeCapability update(Long id, ProductTypeCapabilityRequest request) {
|
||||
validateRequest(request, false);
|
||||
|
||||
ProductTypeCapability capability = getById(id);
|
||||
|
||||
// 如果修改了商品类型代码,检查新代码是否已被使用
|
||||
if (request.getProductType() != null &&
|
||||
!request.getProductType().equals(capability.getProductType())) {
|
||||
ProductTypeCapability existing = mapper.selectByProductType(request.getProductType());
|
||||
if (existing != null && !existing.getId().equals(id)) {
|
||||
throw new IllegalArgumentException("商品类型代码已被使用: " + request.getProductType());
|
||||
}
|
||||
}
|
||||
|
||||
String oldProductType = capability.getProductType();
|
||||
updateEntityFromRequest(capability, request);
|
||||
capability.setUpdatedAt(LocalDateTime.now());
|
||||
|
||||
mapper.updateById(capability);
|
||||
|
||||
// 刷新缓存(如果商品类型代码改变了,需要刷新两个缓存)
|
||||
capabilityService.refreshCache(capability.getProductType());
|
||||
if (!oldProductType.equals(capability.getProductType())) {
|
||||
capabilityService.refreshCache(oldProductType);
|
||||
}
|
||||
|
||||
log.info("更新商品类型能力配置成功: {}", capability.getProductType());
|
||||
return capability;
|
||||
}
|
||||
|
||||
@Transactional(rollbackFor = Exception.class)
|
||||
@Override
|
||||
public void delete(Long id) {
|
||||
ProductTypeCapability capability = getById(id);
|
||||
|
||||
mapper.deleteById(id);
|
||||
|
||||
// 刷新缓存
|
||||
capabilityService.refreshCache(capability.getProductType());
|
||||
|
||||
log.info("删除商品类型能力配置成功: {}", capability.getProductType());
|
||||
}
|
||||
|
||||
@Transactional(rollbackFor = Exception.class)
|
||||
@Override
|
||||
public void updateStatus(Long id, Boolean isActive) {
|
||||
if (isActive == null) {
|
||||
throw new IllegalArgumentException("状态不能为空");
|
||||
}
|
||||
|
||||
ProductTypeCapability capability = getById(id);
|
||||
capability.setIsActive(isActive);
|
||||
capability.setUpdatedAt(LocalDateTime.now());
|
||||
|
||||
mapper.updateById(capability);
|
||||
|
||||
// 刷新缓存
|
||||
capabilityService.refreshCache(capability.getProductType());
|
||||
|
||||
log.info("更新商品类型能力配置状态成功: {}, isActive={}", capability.getProductType(), isActive);
|
||||
}
|
||||
|
||||
@Transactional(rollbackFor = Exception.class)
|
||||
@Override
|
||||
public int initializeDefaultCapabilities() {
|
||||
int count = 0;
|
||||
|
||||
for (ProductType productType : ProductType.values()) {
|
||||
// 检查是否已存在配置
|
||||
ProductTypeCapability existing = mapper.selectByProductType(productType.getCode());
|
||||
if (existing != null) {
|
||||
log.debug("商品类型 {} 已存在配置,跳过初始化", productType.getCode());
|
||||
continue;
|
||||
}
|
||||
|
||||
// 创建默认配置
|
||||
ProductTypeCapability capability = createDefaultCapability(productType);
|
||||
mapper.insert(capability);
|
||||
count++;
|
||||
|
||||
log.info("初始化商品类型能力配置: {}", productType.getCode());
|
||||
}
|
||||
|
||||
// 刷新所有缓存
|
||||
capabilityService.refreshCache();
|
||||
|
||||
log.info("商品类型能力配置批量初始化完成,共初始化 {} 个配置", count);
|
||||
return count;
|
||||
}
|
||||
|
||||
/**
|
||||
* 创建默认配置
|
||||
*/
|
||||
private ProductTypeCapability createDefaultCapability(ProductType productType) {
|
||||
ProductTypeCapability capability = new ProductTypeCapability();
|
||||
capability.setProductType(productType.getCode());
|
||||
capability.setDisplayName(productType.getDescription());
|
||||
capability.setCategory(productType.getCategoryCode());
|
||||
|
||||
// 根据分类设置默认的定价模式
|
||||
if (ProductCategory.PRINT == productType.getCategory()) {
|
||||
capability.setPricingMode(PricingMode.QUANTITY_BASED.getCode());
|
||||
capability.setSupportsTierPricing(true);
|
||||
capability.setAllowDuplicatePurchase(true);
|
||||
capability.setDuplicateCheckStrategy(DuplicateCheckStrategy.NO_CHECK.getCode());
|
||||
} else {
|
||||
capability.setPricingMode(PricingMode.FIXED.getCode());
|
||||
capability.setSupportsTierPricing(false);
|
||||
capability.setAllowDuplicatePurchase(false);
|
||||
capability.setDuplicateCheckStrategy(DuplicateCheckStrategy.CHECK_BY_SET_ID.getCode());
|
||||
}
|
||||
|
||||
// 优惠能力默认全部开启
|
||||
capability.setCanUseCoupon(true);
|
||||
capability.setCanUseVoucher(true);
|
||||
capability.setCanUseOnePrice(true);
|
||||
capability.setCanUseBundle(true);
|
||||
|
||||
capability.setIsActive(true);
|
||||
capability.setCreatedAt(LocalDateTime.now());
|
||||
capability.setUpdatedAt(LocalDateTime.now());
|
||||
|
||||
return capability;
|
||||
}
|
||||
|
||||
/**
|
||||
* 验证请求参数
|
||||
*/
|
||||
private void validateRequest(ProductTypeCapabilityRequest request, boolean isCreate) {
|
||||
if (request == null) {
|
||||
throw new IllegalArgumentException("请求参数不能为空");
|
||||
}
|
||||
|
||||
if (isCreate || request.getProductType() != null) {
|
||||
if (request.getProductType() == null || request.getProductType().trim().isEmpty()) {
|
||||
throw new IllegalArgumentException("商品类型代码不能为空");
|
||||
}
|
||||
}
|
||||
|
||||
if (request.getDisplayName() != null && request.getDisplayName().trim().isEmpty()) {
|
||||
throw new IllegalArgumentException("显示名称不能为空字符串");
|
||||
}
|
||||
|
||||
// 验证枚举值有效性
|
||||
if (request.getPricingMode() != null) {
|
||||
try {
|
||||
PricingMode.fromCode(request.getPricingMode());
|
||||
} catch (IllegalArgumentException e) {
|
||||
throw new IllegalArgumentException("无效的定价模式: " + request.getPricingMode());
|
||||
}
|
||||
}
|
||||
|
||||
if (request.getDuplicateCheckStrategy() != null) {
|
||||
try {
|
||||
DuplicateCheckStrategy.fromCode(request.getDuplicateCheckStrategy());
|
||||
} catch (IllegalArgumentException e) {
|
||||
throw new IllegalArgumentException("无效的重复检查策略: " + request.getDuplicateCheckStrategy());
|
||||
}
|
||||
}
|
||||
|
||||
if (request.getCategory() != null) {
|
||||
try {
|
||||
ProductCategory.fromCode(request.getCategory());
|
||||
} catch (IllegalArgumentException e) {
|
||||
throw new IllegalArgumentException("无效的商品分类: " + request.getCategory());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* 将请求转换为实体
|
||||
*/
|
||||
private ProductTypeCapability convertToEntity(ProductTypeCapabilityRequest request) {
|
||||
ProductTypeCapability capability = new ProductTypeCapability();
|
||||
updateEntityFromRequest(capability, request);
|
||||
return capability;
|
||||
}
|
||||
|
||||
/**
|
||||
* 从请求更新实体
|
||||
*/
|
||||
private void updateEntityFromRequest(ProductTypeCapability capability, ProductTypeCapabilityRequest request) {
|
||||
if (request.getProductType() != null) {
|
||||
capability.setProductType(request.getProductType());
|
||||
}
|
||||
if (request.getDisplayName() != null) {
|
||||
capability.setDisplayName(request.getDisplayName());
|
||||
}
|
||||
if (request.getCategory() != null) {
|
||||
capability.setCategory(request.getCategory());
|
||||
}
|
||||
if (request.getPricingMode() != null) {
|
||||
capability.setPricingMode(request.getPricingMode());
|
||||
}
|
||||
if (request.getSupportsTierPricing() != null) {
|
||||
capability.setSupportsTierPricing(request.getSupportsTierPricing());
|
||||
}
|
||||
if (request.getAllowDuplicatePurchase() != null) {
|
||||
capability.setAllowDuplicatePurchase(request.getAllowDuplicatePurchase());
|
||||
}
|
||||
if (request.getDuplicateCheckStrategy() != null) {
|
||||
capability.setDuplicateCheckStrategy(request.getDuplicateCheckStrategy());
|
||||
}
|
||||
if (request.getCanUseCoupon() != null) {
|
||||
capability.setCanUseCoupon(request.getCanUseCoupon());
|
||||
}
|
||||
if (request.getCanUseVoucher() != null) {
|
||||
capability.setCanUseVoucher(request.getCanUseVoucher());
|
||||
}
|
||||
if (request.getCanUseOnePrice() != null) {
|
||||
capability.setCanUseOnePrice(request.getCanUseOnePrice());
|
||||
}
|
||||
if (request.getCanUseBundle() != null) {
|
||||
capability.setCanUseBundle(request.getCanUseBundle());
|
||||
}
|
||||
if (request.getMetadata() != null) {
|
||||
capability.setMetadata(request.getMetadata());
|
||||
}
|
||||
if (request.getIsActive() != null) {
|
||||
capability.setIsActive(request.getIsActive());
|
||||
}
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user