feat(REQ-2186): 产品管理相关接口实现
This commit is contained in:
parent
007e84a31c
commit
992b4a8801
@ -6,9 +6,9 @@
|
||||
|
||||
dev环境启动参数:
|
||||
-Dspring.datasource.url=jdbc:mysql://172.16.2.197:3311/pudge-dev?useUnicode=true&characterEncoding=utf8&allowMultiQueries=true&serverTimezone=Asia/Shanghai&useSSL=true&verifyServerCertificate=false&rewriteBatchedStatements=true
|
||||
-Drocketmq.name-server=114.116.202.128:9876
|
||||
-Drocketmq.name-server=172.16.2.82:9876
|
||||
-DCUSTOM_ENV=dev
|
||||
-Dspring.profiles.active=dev
|
||||
-Dspring.redis.host=123.249.44.111
|
||||
-Dspring.redis.host=172.16.2.23
|
||||
-Dspring.redis.port=31270
|
||||
-Dserver.port=8080
|
||||
@ -10,6 +10,9 @@ import cn.axzo.tyr.client.model.product.ProductSearchListReq;
|
||||
import cn.axzo.tyr.client.model.product.ProductSearchPageReq;
|
||||
import cn.axzo.tyr.client.model.product.ProductUpdateReq;
|
||||
import cn.axzo.tyr.client.model.product.ProductVO;
|
||||
import cn.axzo.tyr.client.model.req.ProductSaveReq;
|
||||
import cn.axzo.tyr.client.model.req.UpdateProductStatusReq;
|
||||
import cn.axzo.tyr.client.model.res.ChiefTerminalResp;
|
||||
import org.springframework.cloud.openfeign.FeignClient;
|
||||
import org.springframework.validation.annotation.Validated;
|
||||
import org.springframework.web.bind.annotation.DeleteMapping;
|
||||
@ -113,4 +116,33 @@ public interface ProductApi {
|
||||
*/
|
||||
@PostMapping("api/auth/product/feature/query")
|
||||
ApiResult<Map<Long, List<ProductFeatureRelationVO>>> queryProductFeatureRelationByWorkspace(@RequestBody Set<Long> workspaceIds);
|
||||
|
||||
|
||||
/**
|
||||
* 产品上下架
|
||||
*
|
||||
* @param req 产品id及状态
|
||||
* @return 是否更新成功
|
||||
*/
|
||||
@PostMapping("api/auth/product/updateStatus")
|
||||
ApiResult<Void> updateStatus(@Validated @RequestBody UpdateProductStatusReq req);
|
||||
|
||||
|
||||
/**
|
||||
* 保存、更新产品(v2版本)
|
||||
*
|
||||
* @param req 产品信息
|
||||
* @return 返回产品ID
|
||||
*/
|
||||
@PostMapping("api/auth/product/saveOrUpdate")
|
||||
ApiResult<Long> saveOrUpdate(@Validated @RequestBody ProductSaveReq req);
|
||||
|
||||
/**
|
||||
* 获取政务端列表
|
||||
*
|
||||
* @param terminal 政务端
|
||||
* @return {@link ChiefTerminalResp}
|
||||
*/
|
||||
@GetMapping("api/auth/product/getChiefTerminal")
|
||||
ApiResult<List<ChiefTerminalResp>> getChiefTerminal(@RequestParam @NotNull(message = "terminal不能为空") String terminal);
|
||||
}
|
||||
|
||||
@ -0,0 +1,60 @@
|
||||
package cn.axzo.tyr.client.model.enums;
|
||||
|
||||
import com.baomidou.mybatisplus.annotation.EnumValue;
|
||||
import com.fasterxml.jackson.annotation.JsonValue;
|
||||
import lombok.AllArgsConstructor;
|
||||
import lombok.Getter;
|
||||
|
||||
import java.util.Arrays;
|
||||
import java.util.Optional;
|
||||
|
||||
/**
|
||||
* @author likunpeng
|
||||
* @version 1.0
|
||||
* @date 2024/5/6
|
||||
*/
|
||||
@Getter
|
||||
@AllArgsConstructor
|
||||
public enum ProductModuleCategoryEnum {
|
||||
|
||||
/**
|
||||
* 产品版本
|
||||
*/
|
||||
PRODUCT_VERSION("PRODUCT_VERSION", "产品版本"),
|
||||
|
||||
/**
|
||||
* 增值服务包
|
||||
*/
|
||||
ADD_VALUE_SERVICE("ADD_VALUE_SERVICE", "增值服务包"),
|
||||
|
||||
/**
|
||||
* 通用产品
|
||||
*/
|
||||
GENERAL_SERVICE("GENERAL_SERVICE", "通用产品"),
|
||||
|
||||
/**
|
||||
* 硬件产品
|
||||
*/
|
||||
HARD_WARE("HARD_WARE", "硬件产品"),
|
||||
|
||||
;
|
||||
|
||||
@EnumValue
|
||||
@JsonValue
|
||||
private String code;
|
||||
private String desc;
|
||||
|
||||
/**
|
||||
* 通过value值获取枚举类型
|
||||
*
|
||||
* @param code code值
|
||||
* @return
|
||||
*/
|
||||
public static ProductModuleCategoryEnum getByCode(String code) {
|
||||
return Arrays.stream(values()).filter(l -> l.getCode().equals(code)).findFirst().orElse(null);
|
||||
}
|
||||
|
||||
public static String getDescByCode(String code) {
|
||||
return Optional.ofNullable(getByCode(code)).map(ProductModuleCategoryEnum::getDesc).orElse(null);
|
||||
}
|
||||
}
|
||||
@ -0,0 +1,72 @@
|
||||
package cn.axzo.tyr.client.model.enums;
|
||||
|
||||
import com.baomidou.mybatisplus.annotation.EnumValue;
|
||||
import com.fasterxml.jackson.annotation.JsonValue;
|
||||
import com.google.common.collect.Lists;
|
||||
import lombok.AllArgsConstructor;
|
||||
import lombok.Getter;
|
||||
|
||||
import java.util.Arrays;
|
||||
import java.util.List;
|
||||
import java.util.Optional;
|
||||
|
||||
/**
|
||||
* @author likunpeng
|
||||
* @version 1.0
|
||||
* @date 2024/5/6
|
||||
*/
|
||||
@Getter
|
||||
@AllArgsConstructor
|
||||
public enum WorkspaceTypeCodeEnum {
|
||||
|
||||
/**
|
||||
* 企业
|
||||
*/
|
||||
GENERAL_ENT("1", "企业"),
|
||||
|
||||
/**
|
||||
* 项目
|
||||
*/
|
||||
GENERAL_PROJECT("2", "项目"),
|
||||
|
||||
/**
|
||||
* 政务
|
||||
*/
|
||||
CHIEF("3", "政务"),
|
||||
|
||||
/**
|
||||
* 班组
|
||||
*/
|
||||
TEAM("5", "班组"),
|
||||
|
||||
/**
|
||||
* OMS
|
||||
*/
|
||||
OMS("6", "OMS"),
|
||||
|
||||
;
|
||||
|
||||
@EnumValue
|
||||
@JsonValue
|
||||
private String code;
|
||||
private String desc;
|
||||
|
||||
/**
|
||||
* 通过value值获取枚举类型
|
||||
*
|
||||
* @param code code值
|
||||
* @return
|
||||
*/
|
||||
public static WorkspaceTypeCodeEnum getByCode(String code) {
|
||||
return Arrays.stream(values()).filter(l -> l.getCode().equals(code)).findFirst().orElse(null);
|
||||
}
|
||||
|
||||
public static String getDescByCode(String code) {
|
||||
return Optional.ofNullable(getByCode(code)).map(WorkspaceTypeCodeEnum::getDesc).orElse(null);
|
||||
}
|
||||
|
||||
/**
|
||||
* 后台允许新增的租户类型
|
||||
*/
|
||||
public static final List<WorkspaceTypeCodeEnum> ALLOW_ADD_WORKSPACE_TYPE_CODE_ENUM = Lists.newArrayList(GENERAL_ENT, GENERAL_PROJECT, CHIEF);
|
||||
}
|
||||
@ -27,9 +27,18 @@ public class ProductSearchPageReq extends PageRequest {
|
||||
*/
|
||||
private Long dictWorkspaceTypeId;
|
||||
|
||||
/**
|
||||
* 租户编码(工作台编码)
|
||||
*/
|
||||
private Long dictWorkspaceTypeCode;
|
||||
|
||||
/**
|
||||
* 状态
|
||||
*/
|
||||
private Integer status;
|
||||
|
||||
/**
|
||||
* 产品类型
|
||||
*/
|
||||
private String productCategory;
|
||||
}
|
||||
|
||||
@ -97,4 +97,111 @@ public class ProductVO {
|
||||
*/
|
||||
private List<Integer> ouTypes;
|
||||
|
||||
/**
|
||||
* 产品类型
|
||||
* PRODUCT_VERSON:产品版本类型、ADD_VALUE_SERVICE:增值服务类型、
|
||||
* GENERAL_SERVICE:通用产品类型、HARD_WARE:硬件产品类型
|
||||
*/
|
||||
private String category;
|
||||
|
||||
/**
|
||||
* 产品类型名称
|
||||
*/
|
||||
private String productCategoryDesc;
|
||||
|
||||
/**
|
||||
* 版本升级序列(数字越小,版本越低,不能降级,只能升级) <企业、项目产品>
|
||||
*/
|
||||
private Integer version;
|
||||
|
||||
/**
|
||||
* 人数上限 <企业、项目产品>
|
||||
*/
|
||||
private Integer maxPersonCount;
|
||||
|
||||
/**
|
||||
* 最大项目数 <企业产品>
|
||||
*/
|
||||
private Integer maxWorkspaceCount;
|
||||
|
||||
/**
|
||||
* 价格(单位:分)
|
||||
*/
|
||||
private Long price;
|
||||
|
||||
/**
|
||||
* 产品详情
|
||||
*/
|
||||
private List<Sku> skus;
|
||||
|
||||
/**
|
||||
* 素材<仅硬件产品支持>
|
||||
*/
|
||||
private Material material;
|
||||
|
||||
/**
|
||||
* 功能范围(政务产品,只取根节点的featureId,后台取拉群所选根节点的所有子节点featureId)
|
||||
*/
|
||||
private FeatureScope featureScope;
|
||||
|
||||
@Data
|
||||
@Builder
|
||||
@NoArgsConstructor
|
||||
@AllArgsConstructor
|
||||
public static class Sku {
|
||||
|
||||
/**
|
||||
* SKU名称
|
||||
*/
|
||||
private String skuName;
|
||||
|
||||
/**
|
||||
* 规格型号
|
||||
*/
|
||||
private String model;
|
||||
|
||||
/**
|
||||
* 数量
|
||||
*/
|
||||
private Integer count;
|
||||
|
||||
/**
|
||||
* 单位
|
||||
*/
|
||||
private String unit;
|
||||
}
|
||||
|
||||
@Data
|
||||
@Builder
|
||||
@NoArgsConstructor
|
||||
@AllArgsConstructor
|
||||
public static class Material {
|
||||
|
||||
/**
|
||||
* 图片
|
||||
*/
|
||||
private List<String> images;
|
||||
|
||||
/**
|
||||
* 视频
|
||||
*/
|
||||
private List<String> videos;
|
||||
|
||||
/**
|
||||
* 详情大图
|
||||
*/
|
||||
private List<String> detailImages;
|
||||
}
|
||||
|
||||
@Data
|
||||
@Builder
|
||||
@NoArgsConstructor
|
||||
@AllArgsConstructor
|
||||
public static class FeatureScope {
|
||||
|
||||
/**
|
||||
* 政务端featureResourceId
|
||||
*/
|
||||
private Long chiefFeatureResourceId;
|
||||
}
|
||||
}
|
||||
|
||||
@ -0,0 +1,167 @@
|
||||
package cn.axzo.tyr.client.model.req;
|
||||
|
||||
import lombok.AllArgsConstructor;
|
||||
import lombok.Builder;
|
||||
import lombok.Data;
|
||||
import lombok.NoArgsConstructor;
|
||||
import org.hibernate.validator.constraints.Length;
|
||||
|
||||
import javax.validation.Valid;
|
||||
import javax.validation.constraints.Min;
|
||||
import javax.validation.constraints.NotBlank;
|
||||
import javax.validation.constraints.NotNull;
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* @author likunpeng
|
||||
* @version 1.0
|
||||
* @date 2024/4/26
|
||||
*/
|
||||
@Builder
|
||||
@Data
|
||||
@NoArgsConstructor
|
||||
@AllArgsConstructor
|
||||
public class ProductSaveReq {
|
||||
|
||||
/**
|
||||
* 产品ID
|
||||
*/
|
||||
private Long id;
|
||||
|
||||
/**
|
||||
* 产品名称
|
||||
*/
|
||||
@NotBlank(message = "产品名称不能为空")
|
||||
@Length(max = 35, message = "产品名称长度不能超过 35 个字符")
|
||||
private String productName;
|
||||
|
||||
/**
|
||||
* 产品icon
|
||||
*/
|
||||
@NotBlank(message = "产品icon不能为空")
|
||||
private String icon;
|
||||
|
||||
/**
|
||||
* 产品所属租户类型
|
||||
*/
|
||||
@NotNull(message = "租户类型不能为空")
|
||||
private Long dictWorkspaceTypeId;
|
||||
|
||||
/**
|
||||
* 产品类型
|
||||
*/
|
||||
@NotBlank(message = "产品类型不能为空")
|
||||
private String productCategory;
|
||||
|
||||
/**
|
||||
* 版本升级序列(数字越小,版本越低,不能降级,只能升级) <企业、项目产品>
|
||||
*/
|
||||
@Min(value = 0, message = "版本升级序列有误")
|
||||
private Integer version;
|
||||
|
||||
/**
|
||||
* 人数上限 <企业、项目产品>
|
||||
*/
|
||||
@Min(value = 0, message = "人数上限有误")
|
||||
private Integer maxPersonCount;
|
||||
|
||||
/**
|
||||
* 最大项目数 <企业产品>
|
||||
*/
|
||||
@Min(value = 0, message = "最大项目数有误")
|
||||
private Integer maxWorkspaceCount;
|
||||
|
||||
/**
|
||||
* 价格(单位:分) <企业、项目产品>
|
||||
*/
|
||||
@Min(value = 0, message = "价格有误")
|
||||
private Long price;
|
||||
|
||||
/**
|
||||
* SKU列表
|
||||
*/
|
||||
@Valid
|
||||
private List<Sku> skus;
|
||||
|
||||
/**
|
||||
* 素材<仅硬件产品支持>
|
||||
*/
|
||||
private Material material;
|
||||
|
||||
/**
|
||||
* 功能范围(政务产品,只取根节点的featureId,后台取拉群所选根节点的所有子节点featureId)
|
||||
*/
|
||||
private FeatureScope featureScope;
|
||||
|
||||
/**
|
||||
* 操作人
|
||||
*/
|
||||
private Long operator;
|
||||
|
||||
|
||||
@Data
|
||||
@Builder
|
||||
@NoArgsConstructor
|
||||
@AllArgsConstructor
|
||||
public static class Sku {
|
||||
|
||||
/**
|
||||
* SKU名称
|
||||
*/
|
||||
@NotNull(message = "SKU名称不能为空")
|
||||
private String skuName;
|
||||
|
||||
/**
|
||||
* 规格型号
|
||||
*/
|
||||
@NotBlank(message = "规格型号不能为空")
|
||||
private String model;
|
||||
|
||||
/**
|
||||
* 数量
|
||||
*/
|
||||
@NotNull(message = "数量不能为空")
|
||||
@Min(value = 1, message = "数量有误")
|
||||
private Integer count;
|
||||
|
||||
/**
|
||||
* 单位
|
||||
*/
|
||||
@NotBlank(message = "单位不能为空")
|
||||
private String unit;
|
||||
}
|
||||
|
||||
@Data
|
||||
@Builder
|
||||
@NoArgsConstructor
|
||||
@AllArgsConstructor
|
||||
public static class Material {
|
||||
|
||||
/**
|
||||
* 图片素材
|
||||
*/
|
||||
private List<String> images;
|
||||
|
||||
/**
|
||||
* 视频素材
|
||||
*/
|
||||
private List<String> videos;
|
||||
|
||||
/**
|
||||
* 详情介绍大图
|
||||
*/
|
||||
private List<String> detailImages;
|
||||
}
|
||||
|
||||
@Data
|
||||
@Builder
|
||||
@NoArgsConstructor
|
||||
@AllArgsConstructor
|
||||
public static class FeatureScope {
|
||||
|
||||
/**
|
||||
* 政务端featureResourceId
|
||||
*/
|
||||
private Long chiefFeatureResourceId;
|
||||
}
|
||||
}
|
||||
@ -0,0 +1,35 @@
|
||||
package cn.axzo.tyr.client.model.req;
|
||||
|
||||
import lombok.AllArgsConstructor;
|
||||
import lombok.Data;
|
||||
import lombok.NoArgsConstructor;
|
||||
|
||||
import javax.validation.constraints.Max;
|
||||
import javax.validation.constraints.Min;
|
||||
import javax.validation.constraints.NotNull;
|
||||
|
||||
/**
|
||||
* @author likunpeng
|
||||
* @version 1.0
|
||||
* @date 2024/4/26
|
||||
*/
|
||||
@Data
|
||||
@NoArgsConstructor
|
||||
@AllArgsConstructor
|
||||
public class UpdateProductStatusReq {
|
||||
|
||||
/**
|
||||
* 产品ID
|
||||
*/
|
||||
@NotNull(message = "产品ID不能为空")
|
||||
@Min(value = 1, message = "产品ID有误")
|
||||
private Long id;
|
||||
|
||||
/**
|
||||
* 状态
|
||||
*/
|
||||
@NotNull(message = "状态不能为空")
|
||||
@Min(value = 0, message = "状态有误")
|
||||
@Max(value = 1, message = "状态有误")
|
||||
private Integer status;
|
||||
}
|
||||
@ -0,0 +1,28 @@
|
||||
package cn.axzo.tyr.client.model.res;
|
||||
|
||||
import lombok.AllArgsConstructor;
|
||||
import lombok.Builder;
|
||||
import lombok.Data;
|
||||
import lombok.NoArgsConstructor;
|
||||
|
||||
/**
|
||||
* @author likunpeng
|
||||
* @version 1.0
|
||||
* @date 2024/4/30
|
||||
*/
|
||||
@Data
|
||||
@Builder
|
||||
@NoArgsConstructor
|
||||
@AllArgsConstructor
|
||||
public class ChiefTerminalResp {
|
||||
|
||||
/**
|
||||
* 功能资源ID
|
||||
*/
|
||||
private Long featureResourceId;
|
||||
|
||||
/**
|
||||
* 功能资源名称
|
||||
*/
|
||||
private String featureResourceName;
|
||||
}
|
||||
@ -11,6 +11,9 @@ import cn.axzo.tyr.client.model.product.ProductSearchListReq;
|
||||
import cn.axzo.tyr.client.model.product.ProductSearchPageReq;
|
||||
import cn.axzo.tyr.client.model.product.ProductUpdateReq;
|
||||
import cn.axzo.tyr.client.model.product.ProductVO;
|
||||
import cn.axzo.tyr.client.model.req.ProductSaveReq;
|
||||
import cn.axzo.tyr.client.model.req.UpdateProductStatusReq;
|
||||
import cn.axzo.tyr.client.model.res.ChiefTerminalResp;
|
||||
import cn.axzo.tyr.server.model.PermissionCacheKey;
|
||||
import cn.axzo.tyr.server.service.PermissionCacheService;
|
||||
import cn.axzo.tyr.server.service.ProductFeatureRelationService;
|
||||
@ -135,4 +138,37 @@ public class ProductController implements ProductApi {
|
||||
public ApiResult<Map<Long, List<ProductFeatureRelationVO>>> queryProductFeatureRelationByWorkspace(Set<Long> workspaceIds) {
|
||||
return ApiResult.ok(productFeatureRelationService.getByWorkspace(workspaceIds));
|
||||
}
|
||||
|
||||
/**
|
||||
* 产品上下架
|
||||
*
|
||||
* @param req 产品及状态信息
|
||||
* @return 返回是否更新成功
|
||||
*/
|
||||
@Override
|
||||
public ApiResult<Void> updateStatus(UpdateProductStatusReq req) {
|
||||
return productService.updateStatus(req);
|
||||
}
|
||||
|
||||
/**
|
||||
* 保存、更新产品(v2版本)
|
||||
*
|
||||
* @param req 产品信息
|
||||
* @return 返回产品ID
|
||||
*/
|
||||
@Override
|
||||
public ApiResult<Long> saveOrUpdate(ProductSaveReq req) {
|
||||
return productService.saveOrUpdate(req);
|
||||
}
|
||||
|
||||
/**
|
||||
* 获取政务端列表
|
||||
*
|
||||
* @param terminal 政务端
|
||||
* @return 返回端列表
|
||||
*/
|
||||
@Override
|
||||
public ApiResult<List<ChiefTerminalResp>> getChiefTerminal(String terminal) {
|
||||
return productService.getChiefTerminal(terminal);
|
||||
}
|
||||
}
|
||||
|
||||
@ -1,11 +1,11 @@
|
||||
package cn.axzo.tyr.server.repository.entity;
|
||||
|
||||
import cn.axzo.pokonyan.config.mybatisplus.BaseEntity;
|
||||
import cn.axzo.tyr.server.repository.handler.ProductModuleSkuHandler;
|
||||
import com.baomidou.mybatisplus.annotation.TableField;
|
||||
import com.baomidou.mybatisplus.annotation.TableName;
|
||||
import lombok.EqualsAndHashCode;
|
||||
import lombok.Getter;
|
||||
import lombok.Setter;
|
||||
import lombok.ToString;
|
||||
import com.baomidou.mybatisplus.extension.handlers.FastjsonTypeHandler;
|
||||
import lombok.*;
|
||||
import org.apache.commons.lang3.StringUtils;
|
||||
|
||||
import java.io.Serializable;
|
||||
@ -13,7 +13,6 @@ import java.util.ArrayList;
|
||||
import java.util.Arrays;
|
||||
import java.util.List;
|
||||
import java.util.stream.Collectors;
|
||||
import java.util.stream.Stream;
|
||||
|
||||
/**
|
||||
* saas-产品表(SaasProduct)表实体类
|
||||
@ -25,7 +24,7 @@ import java.util.stream.Stream;
|
||||
@Setter
|
||||
@ToString
|
||||
@EqualsAndHashCode(callSuper = true)
|
||||
@TableName("product_module")
|
||||
@TableName(value = "product_module", autoResultMap = true)
|
||||
public class ProductModule extends BaseEntity<ProductModule> {
|
||||
|
||||
/**
|
||||
@ -82,6 +81,56 @@ public class ProductModule extends BaseEntity<ProductModule> {
|
||||
*/
|
||||
private String ouType;
|
||||
|
||||
/**
|
||||
* 创建人
|
||||
*/
|
||||
private Long createBy;
|
||||
|
||||
/**
|
||||
* 修改人
|
||||
*/
|
||||
private Long updateBy;
|
||||
|
||||
/**
|
||||
* 产品类型
|
||||
* PRODUCT_VERSION:产品版本类型、ADD_VALUE_SERVICE:增值服务类型、
|
||||
* GENERAL_SERVICE:通用产品类型、HARD_WARE:硬件产品类型
|
||||
*/
|
||||
private String category;
|
||||
|
||||
/**
|
||||
* 版本升级序列(数字越小,版本越低,不能降级,只能升级) <企业、项目产品>
|
||||
*/
|
||||
private Integer version;
|
||||
|
||||
/**
|
||||
* 人数上限 <企业、项目产品>
|
||||
*/
|
||||
private Integer maxPersonCount;
|
||||
|
||||
/**
|
||||
* 最大项目数 <企业产品>
|
||||
*/
|
||||
private Integer maxWorkspaceCount;
|
||||
|
||||
/**
|
||||
* 价格(单位:分)
|
||||
*/
|
||||
private Long price;
|
||||
|
||||
/**
|
||||
* 产品详情 jsonList(skuNameSKU名称、model规格型号、count数量、unit单位)
|
||||
*/
|
||||
@TableField(value = "skus", typeHandler = ProductModuleSkuHandler.class)
|
||||
private List<Sku> skus;
|
||||
|
||||
/**
|
||||
* 素材<仅硬件产品支持>json类型
|
||||
* ({"miages":List<String>,"videos":List<String>,"detailImages":List<String>})
|
||||
*/
|
||||
@TableField(value = "material", typeHandler = FastjsonTypeHandler.class)
|
||||
private Material material;
|
||||
|
||||
/**
|
||||
* 获取主键值
|
||||
*
|
||||
@ -100,5 +149,54 @@ public class ProductModule extends BaseEntity<ProductModule> {
|
||||
return new ArrayList<>();
|
||||
}
|
||||
}
|
||||
|
||||
@Data
|
||||
@Builder
|
||||
@NoArgsConstructor
|
||||
@AllArgsConstructor
|
||||
public static class Sku {
|
||||
|
||||
/**
|
||||
* SKU名称
|
||||
*/
|
||||
private String skuName;
|
||||
|
||||
/**
|
||||
* 规格型号
|
||||
*/
|
||||
private String model;
|
||||
|
||||
/**
|
||||
* 数量
|
||||
*/
|
||||
private Integer count;
|
||||
|
||||
/**
|
||||
* 单位
|
||||
*/
|
||||
private String unit;
|
||||
}
|
||||
|
||||
@Data
|
||||
@Builder
|
||||
@NoArgsConstructor
|
||||
@AllArgsConstructor
|
||||
public static class Material {
|
||||
|
||||
/**
|
||||
* 图片
|
||||
*/
|
||||
private List<String> images;
|
||||
|
||||
/**
|
||||
* 视频
|
||||
*/
|
||||
private List<String> videos;
|
||||
|
||||
/**
|
||||
* 详情大图
|
||||
*/
|
||||
private List<String> detailImages;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@ -0,0 +1,42 @@
|
||||
package cn.axzo.tyr.server.repository.handler;
|
||||
|
||||
import com.alibaba.fastjson.JSON;
|
||||
import com.alibaba.fastjson.TypeReference;
|
||||
import org.apache.ibatis.type.BaseTypeHandler;
|
||||
import org.apache.ibatis.type.JdbcType;
|
||||
|
||||
import java.sql.CallableStatement;
|
||||
import java.sql.PreparedStatement;
|
||||
import java.sql.ResultSet;
|
||||
import java.sql.SQLException;
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* @author likunpeng
|
||||
* @date 2024/5/16
|
||||
* @version 1.0
|
||||
*/
|
||||
public abstract class ListTypeHandler<T> extends BaseTypeHandler<List<T>> {
|
||||
|
||||
@Override
|
||||
public void setNonNullParameter(PreparedStatement ps, int i, List<T> parameter, JdbcType jdbcType) throws SQLException {
|
||||
ps.setString(i, JSON.toJSONString(parameter));
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<T> getNullableResult(ResultSet rs, String columnName) throws SQLException {
|
||||
return rs.wasNull() ? null : JSON.parseObject(rs.getString(columnName), specificType());
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<T> getNullableResult(ResultSet rs, int columnIndex) throws SQLException {
|
||||
return rs.wasNull() ? null : JSON.parseObject(rs.getString(columnIndex), specificType());
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<T> getNullableResult(CallableStatement cs, int columnIndex) throws SQLException {
|
||||
return cs.wasNull() ? null : JSON.parseObject(cs.getString(columnIndex), specificType());
|
||||
}
|
||||
|
||||
protected abstract TypeReference<List<T>> specificType();
|
||||
}
|
||||
@ -0,0 +1,20 @@
|
||||
package cn.axzo.tyr.server.repository.handler;
|
||||
|
||||
import cn.axzo.tyr.server.repository.entity.ProductModule;
|
||||
import com.alibaba.fastjson.TypeReference;
|
||||
import org.apache.ibatis.type.MappedTypes;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* @author likunpeng
|
||||
* @version 1.0
|
||||
* @date 2024/5/6
|
||||
*/
|
||||
@MappedTypes({List.class})
|
||||
public class ProductModuleSkuHandler extends ListTypeHandler<ProductModule.Sku> {
|
||||
@Override
|
||||
protected TypeReference<List<ProductModule.Sku>> specificType() {
|
||||
return new TypeReference<List<ProductModule.Sku>>(){};
|
||||
}
|
||||
}
|
||||
@ -7,6 +7,9 @@ import cn.axzo.tyr.client.model.product.ProductSearchListReq;
|
||||
import cn.axzo.tyr.client.model.product.ProductSearchPageReq;
|
||||
import cn.axzo.tyr.client.model.product.ProductUpdateReq;
|
||||
import cn.axzo.tyr.client.model.product.ProductVO;
|
||||
import cn.axzo.tyr.client.model.req.ProductSaveReq;
|
||||
import cn.axzo.tyr.client.model.req.UpdateProductStatusReq;
|
||||
import cn.axzo.tyr.client.model.res.ChiefTerminalResp;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
@ -29,4 +32,10 @@ public interface ProductService {
|
||||
ApiResult<ProductVO> update(ProductUpdateReq req);
|
||||
|
||||
ApiResult<ProductVO> delete(Long id);
|
||||
|
||||
ApiResult<Void> updateStatus(UpdateProductStatusReq req);
|
||||
|
||||
ApiResult<Long> saveOrUpdate(ProductSaveReq req);
|
||||
|
||||
ApiResult<List<ChiefTerminalResp>> getChiefTerminal(String terminal);
|
||||
}
|
||||
|
||||
@ -51,4 +51,6 @@ public interface SaasFeatureResourceService {
|
||||
Set<Long> listAuthFree();
|
||||
|
||||
List<SaasFeatureResource> listNavMenu(String terminal);
|
||||
|
||||
List<SaasFeatureResource> listByParentIdAndTerminalAndIds(Long parentId, String terminal, List<Long> featureIds);
|
||||
}
|
||||
|
||||
@ -5,23 +5,31 @@ import cn.axzo.basics.common.util.AssertUtil;
|
||||
import cn.axzo.framework.domain.page.PageResp;
|
||||
import cn.axzo.framework.domain.web.result.ApiPageResult;
|
||||
import cn.axzo.framework.domain.web.result.ApiResult;
|
||||
import cn.axzo.tyr.client.model.product.ProductAddReq;
|
||||
import cn.axzo.tyr.client.model.product.ProductSearchListReq;
|
||||
import cn.axzo.tyr.client.model.product.ProductSearchPageReq;
|
||||
import cn.axzo.tyr.client.model.product.ProductUpdateReq;
|
||||
import cn.axzo.tyr.client.model.product.ProductVO;
|
||||
import cn.axzo.pokonyan.config.mybatisplus.BaseEntity;
|
||||
import cn.axzo.tyr.client.model.dict.response.BasicDictNodeResp;
|
||||
import cn.axzo.tyr.client.model.enums.ProductModuleCategoryEnum;
|
||||
import cn.axzo.tyr.client.model.enums.WorkspaceTypeCodeEnum;
|
||||
import cn.axzo.tyr.client.model.product.*;
|
||||
import cn.axzo.tyr.client.model.req.ProductSaveReq;
|
||||
import cn.axzo.tyr.client.model.req.UpdateProductStatusReq;
|
||||
import cn.axzo.tyr.client.model.res.ChiefTerminalResp;
|
||||
import cn.axzo.tyr.server.repository.entity.ProductModule;
|
||||
import cn.axzo.tyr.server.repository.dao.ProductModuleDao;
|
||||
import cn.axzo.tyr.server.repository.entity.SaasFeatureResource;
|
||||
import cn.axzo.tyr.server.service.ProductFeatureRelationService;
|
||||
import cn.axzo.tyr.server.service.ProductService;
|
||||
import cn.hutool.core.util.StrUtil;
|
||||
import cn.axzo.tyr.server.service.SaasBasicDictService;
|
||||
import cn.axzo.tyr.server.service.SaasFeatureResourceService;
|
||||
import cn.hutool.core.collection.CollectionUtil;
|
||||
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
|
||||
import com.baomidou.mybatisplus.core.metadata.IPage;
|
||||
import com.baomidou.mybatisplus.extension.conditions.query.LambdaQueryChainWrapper;
|
||||
import io.swagger.models.auth.In;
|
||||
import com.google.common.collect.Sets;
|
||||
import lombok.RequiredArgsConstructor;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import org.bouncycastle.util.Integers;
|
||||
import org.apache.commons.compress.utils.Lists;
|
||||
import org.springframework.stereotype.Service;
|
||||
import org.springframework.transaction.annotation.Transactional;
|
||||
import org.springframework.util.CollectionUtils;
|
||||
import org.springframework.util.StringUtils;
|
||||
|
||||
@ -40,6 +48,11 @@ import java.util.stream.Collectors;
|
||||
public class ProductServiceImpl implements ProductService {
|
||||
private final ProductModuleDao productModuleDao;
|
||||
private final ProductFeatureRelationService productFeatureRelationService;
|
||||
private final SaasFeatureResourceService saasFeatureResourceService;
|
||||
private final SaasBasicDictService saasBasicDictService;
|
||||
|
||||
// todo 政务端最终使用常量
|
||||
private final static String CHIEF_TERMINAL = "NT_CHIEF";
|
||||
|
||||
@Override
|
||||
public ApiResult<List<ProductVO>> list(ProductSearchListReq req) {
|
||||
@ -76,9 +89,15 @@ public class ProductServiceImpl implements ProductService {
|
||||
IPage<ProductModule> page = productModuleDao.lambdaQuery()
|
||||
.like(StringUtils.hasLength(req.getName()), ProductModule::getProductName, req.getName())
|
||||
.eq(Objects.nonNull(req.getDictWorkspaceTypeId()), ProductModule::getDictWorkspaceTypeId, req.getDictWorkspaceTypeId())
|
||||
.eq(Objects.nonNull(req.getDictWorkspaceTypeCode()), ProductModule::getDictWorkspaceTypeCode, req.getDictWorkspaceTypeCode())
|
||||
.eq(Objects.nonNull(req.getStatus()), ProductModule::getStatus, req.getStatus())
|
||||
.eq(org.apache.commons.lang3.StringUtils.isNotBlank(req.getProductCategory()), ProductModule::getCategory, req.getProductCategory())
|
||||
.page(req.toPage());
|
||||
List<ProductVO> list = BeanMapper.copyList(page.getRecords(), ProductVO.class);
|
||||
list.forEach(e -> {
|
||||
e.setProductCategoryDesc(ProductModuleCategoryEnum.getDescByCode(e.getCategory()));
|
||||
e.setDictWorkspaceTypeDesc(WorkspaceTypeCodeEnum.getDescByCode(e.getDictWorkspaceTypeCode()));
|
||||
});
|
||||
PageResp<ProductVO> data = PageResp.list(page.getCurrent(), page.getSize(), page.getTotal(), list);
|
||||
return ApiPageResult.ok(data);
|
||||
}
|
||||
@ -88,6 +107,23 @@ public class ProductServiceImpl implements ProductService {
|
||||
ProductModule byId = productModuleDao.getById(id);
|
||||
ProductVO productVO = BeanMapper.copyBean(byId, ProductVO.class);
|
||||
productVO.setOuTypes(byId.parseOuType());
|
||||
productVO.setProductCategoryDesc(ProductModuleCategoryEnum.getDescByCode(productVO.getCategory()));
|
||||
productVO.setDictWorkspaceTypeDesc(WorkspaceTypeCodeEnum.getDescByCode(productVO.getDictWorkspaceTypeCode()));
|
||||
productVO.setSkus(org.apache.commons.collections.CollectionUtils.isEmpty(byId.getSkus()) ? Collections.emptyList()
|
||||
: byId.getSkus().stream().map(e -> ProductVO.Sku.builder()
|
||||
.skuName(e.getSkuName())
|
||||
.model(e.getModel())
|
||||
.count(e.getCount())
|
||||
.unit(e.getUnit())
|
||||
.build()).collect(Collectors.toList()));
|
||||
productVO.setMaterial(Objects.isNull(byId.getMaterial()) ? null : ProductVO.Material.builder()
|
||||
.images(byId.getMaterial().getImages())
|
||||
.videos(byId.getMaterial().getVideos())
|
||||
.detailImages(byId.getMaterial().getDetailImages())
|
||||
.build());
|
||||
if (WorkspaceTypeCodeEnum.CHIEF.getCode().equals(productVO.getDictWorkspaceTypeCode())) {
|
||||
fillFeatureScope(productVO);
|
||||
}
|
||||
return ApiResult.ok(productVO);
|
||||
}
|
||||
|
||||
@ -137,4 +173,142 @@ public class ProductServiceImpl implements ProductService {
|
||||
productFeatureRelationService.removeByProductId(id);
|
||||
return ApiResult.ok(BeanMapper.copyBean(productModule, ProductVO.class));
|
||||
}
|
||||
|
||||
@Override
|
||||
public ApiResult<Void> updateStatus(UpdateProductStatusReq req) {
|
||||
ProductModule productModule = productModuleDao.getOne(new LambdaQueryWrapper<ProductModule>()
|
||||
.eq(BaseEntity::getId, req.getId())
|
||||
.eq(BaseEntity::getIsDelete, Boolean.FALSE)
|
||||
.last("LIMIT 1"));
|
||||
AssertUtil.notNull(productModule, "产品不存在");
|
||||
productModuleDao.lambdaUpdate()
|
||||
.eq(ProductModule::getId, req.getId())
|
||||
.set(ProductModule::getStatus, req.getStatus())
|
||||
.update();
|
||||
return ApiResult.ok();
|
||||
}
|
||||
|
||||
@Override
|
||||
@Transactional(rollbackFor = Exception.class)
|
||||
public ApiResult<Long> saveOrUpdate(ProductSaveReq req) {
|
||||
ProductModule productModule = new ProductModule();
|
||||
if (Objects.nonNull(req.getId())) {
|
||||
productModule = productModuleDao.getOne(new LambdaQueryWrapper<ProductModule>()
|
||||
.eq(BaseEntity::getId, req.getId())
|
||||
.eq(BaseEntity::getIsDelete, Boolean.FALSE)
|
||||
.last("LIMIT 1"));
|
||||
AssertUtil.notNull(productModule, "产品不存在");
|
||||
if (Objects.nonNull(req.getVersion()) && Objects.nonNull(productModule.getVersion())) {
|
||||
AssertUtil.isTrue(req.getVersion() >= productModule.getVersion(), "版本升级序列不允许降级");
|
||||
}
|
||||
}
|
||||
|
||||
validAndFillEntity(req, productModule);
|
||||
|
||||
if (Objects.nonNull(req.getId())) {
|
||||
productModule.setUpdateBy(req.getOperator());
|
||||
productModuleDao.updateById(productModule);
|
||||
} else {
|
||||
productModule.setCreateBy(req.getOperator());
|
||||
productModuleDao.save(productModule);
|
||||
}
|
||||
// 保存商品权限信息
|
||||
if (WorkspaceTypeCodeEnum.CHIEF.getCode().equals(productModule.getDictWorkspaceTypeCode())) {
|
||||
saveChiefFeatureResource(productModule.getId(), productModule.getDictWorkspaceTypeId(), productModule.getDictWorkspaceTypeCode(), req.getFeatureScope().getChiefFeatureResourceId());
|
||||
}
|
||||
return ApiResult.ok(productModule.getId());
|
||||
}
|
||||
|
||||
@Override
|
||||
public ApiResult<List<ChiefTerminalResp>> getChiefTerminal(String terminal) {
|
||||
List<SaasFeatureResource> featureResources = saasFeatureResourceService.listByParentIdAndTerminalAndIds(0L, terminal, null);
|
||||
List<ChiefTerminalResp> resps = CollectionUtil.isEmpty(featureResources) ? Collections.emptyList() : featureResources.stream().map(e -> ChiefTerminalResp.builder()
|
||||
.featureResourceId(e.getId())
|
||||
.featureResourceName(e.getFeatureName())
|
||||
.build()).collect(Collectors.toList());
|
||||
return ApiResult.ok(resps);
|
||||
}
|
||||
|
||||
private void validAndFillEntity(ProductSaveReq req, ProductModule productModule) {
|
||||
BasicDictNodeResp basicDictNodeResp = saasBasicDictService.getById(req.getDictWorkspaceTypeId());
|
||||
AssertUtil.notNull(basicDictNodeResp, "租户类型有误");
|
||||
WorkspaceTypeCodeEnum workspaceTypeCodeEnum = WorkspaceTypeCodeEnum.getByCode(basicDictNodeResp.getCode());
|
||||
AssertUtil.notNull(workspaceTypeCodeEnum, "租户类型有误");
|
||||
AssertUtil.isTrue(WorkspaceTypeCodeEnum.ALLOW_ADD_WORKSPACE_TYPE_CODE_ENUM.contains(workspaceTypeCodeEnum), "租户类型选择有误");
|
||||
// TODO 一期不允许创建企业、项目租户的产品
|
||||
AssertUtil.isFalse(WorkspaceTypeCodeEnum.GENERAL_ENT.equals(workspaceTypeCodeEnum) || WorkspaceTypeCodeEnum.GENERAL_PROJECT.equals(workspaceTypeCodeEnum), "企业、项目租户请在老页面创建产品");
|
||||
|
||||
ProductModuleCategoryEnum productModuleCategoryEnum = ProductModuleCategoryEnum.getByCode(req.getProductCategory());
|
||||
AssertUtil.notNull(productModuleCategoryEnum, "产品类型有误");
|
||||
|
||||
if (WorkspaceTypeCodeEnum.GENERAL_ENT.equals(workspaceTypeCodeEnum) || WorkspaceTypeCodeEnum.GENERAL_PROJECT.equals(workspaceTypeCodeEnum)) {
|
||||
AssertUtil.notNull(req.getVersion(), "版本升级序列不能为空");
|
||||
AssertUtil.notNull(req.getMaxPersonCount(), "人数上限不能为空");
|
||||
AssertUtil.notNull(req.getPrice(), "价格不能为空");
|
||||
}
|
||||
if (WorkspaceTypeCodeEnum.CHIEF.equals(workspaceTypeCodeEnum)) {
|
||||
AssertUtil.isTrue(Objects.nonNull(req.getFeatureScope()) && Objects.nonNull(req.getFeatureScope().getChiefFeatureResourceId())
|
||||
&& req.getFeatureScope().getChiefFeatureResourceId() > 0, "功能范围选择有误");
|
||||
}
|
||||
productModule.setProductName(req.getProductName());
|
||||
productModule.setIcon(req.getIcon());
|
||||
productModule.setDictWorkspaceTypeId(req.getDictWorkspaceTypeId());
|
||||
productModule.setDictWorkspaceTypeCode(workspaceTypeCodeEnum.getCode());
|
||||
productModule.setProductType(0);
|
||||
productModule.setStatus(0);
|
||||
productModule.setCategory(req.getProductCategory());
|
||||
productModule.setVersion(req.getVersion());
|
||||
productModule.setMaxPersonCount(req.getMaxPersonCount());
|
||||
productModule.setMaxWorkspaceCount(req.getMaxWorkspaceCount());
|
||||
productModule.setPrice(req.getPrice());
|
||||
productModule.setSkus(org.apache.commons.collections.CollectionUtils.isEmpty(req.getSkus()) ? Lists.newArrayList()
|
||||
: req.getSkus().stream().map(e -> ProductModule.Sku.builder()
|
||||
.skuName(e.getSkuName())
|
||||
.model(e.getModel())
|
||||
.count(e.getCount())
|
||||
.unit(e.getUnit())
|
||||
.build()).collect(Collectors.toList()));
|
||||
productModule.setMaterial(Optional.ofNullable(req.getMaterial()).map(e -> ProductModule.Material.builder()
|
||||
.images(e.getImages())
|
||||
.videos(e.getVideos())
|
||||
.detailImages(e.getDetailImages())
|
||||
.build()).orElse(ProductModule.Material.builder().build()));
|
||||
}
|
||||
|
||||
/**
|
||||
* 保存政务端产品功能权限
|
||||
*/
|
||||
private void saveChiefFeatureResource(Long productId, Long dictWorkspaceTypeId, String dictWorkspaceTypeCode, Long rootFeatureId) {
|
||||
SaasFeatureResource saasFeatureResource = saasFeatureResourceService.featureResourceById(rootFeatureId);
|
||||
AssertUtil.notNull(saasFeatureResource, "功能范围选择端不能为空");
|
||||
AssertUtil.isTrue(saasFeatureResource.getParentId() == 0 && CHIEF_TERMINAL.equals(saasFeatureResource.getTerminal()), "功能范围选择端有误");
|
||||
|
||||
List<SaasFeatureResource> saasFeatureResources = saasFeatureResourceService.listDescendant(rootFeatureId);
|
||||
ProductFeatureRelationUpdateReq req = new ProductFeatureRelationUpdateReq();
|
||||
req.setDictCodeId(dictWorkspaceTypeId);
|
||||
req.setDictCode(dictWorkspaceTypeCode);
|
||||
req.setProductModuleId(productId);
|
||||
req.setProductModuleId(productId);
|
||||
Set<Long> featureIds = org.apache.commons.collections.CollectionUtils.isEmpty(saasFeatureResources) ? Sets.newHashSet()
|
||||
: saasFeatureResources.stream().map(BaseEntity::getId).collect(Collectors.toSet());
|
||||
featureIds.add(saasFeatureResource.getId());
|
||||
req.getFeatureIds().addAll(featureIds);
|
||||
productFeatureRelationService.updateFeatureRelation(Collections.singletonList(req));
|
||||
}
|
||||
|
||||
private void fillFeatureScope(ProductVO product) {
|
||||
ProductFeatureRelationSearchReq req = new ProductFeatureRelationSearchReq();
|
||||
req.setProductModuleId(product.getId());
|
||||
req.setDictCodeId(product.getDictWorkspaceTypeId());
|
||||
req.setDictCode(product.getDictWorkspaceTypeCode());
|
||||
ApiResult<List<ProductFeatureRelationVO>> result = productFeatureRelationService.featureList(req);
|
||||
if (org.apache.commons.collections.CollectionUtils.isEmpty(result.getData())) {
|
||||
return;
|
||||
}
|
||||
List<Long> featureIds = result.getData().stream().map(ProductFeatureRelationVO::getFeatureId).collect(Collectors.toList());
|
||||
List<SaasFeatureResource> featureResources = saasFeatureResourceService.listByParentIdAndTerminalAndIds(0L, CHIEF_TERMINAL, featureIds);
|
||||
if (CollectionUtil.isNotEmpty(featureResources)) {
|
||||
product.setFeatureScope(ProductVO.FeatureScope.builder().chiefFeatureResourceId(featureResources.get(0).getId()).build());
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@ -479,4 +479,14 @@ public class SaasFeatureResourceServiceImpl implements SaasFeatureResourceServic
|
||||
.orderByAsc(SaasFeatureResource::getDisplayOrder)
|
||||
.list();
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<SaasFeatureResource> listByParentIdAndTerminalAndIds(Long parentId, String terminal, List<Long> featureIds) {
|
||||
return featureResourceDao.lambdaQuery()
|
||||
.eq(BaseEntity::getIsDelete, 0)
|
||||
.eq(Objects.nonNull(parentId), SaasFeatureResource::getParentId, parentId)
|
||||
.eq(StringUtils.isNotBlank(terminal), SaasFeatureResource::getTerminal, terminal)
|
||||
.in(CollectionUtil.isNotEmpty(featureIds), SaasFeatureResource::getId, featureIds)
|
||||
.list();
|
||||
}
|
||||
}
|
||||
|
||||
Loading…
Reference in New Issue
Block a user