pageResult = productService.getProductPage(pageReqVO);
+ return success(BeanUtils.toBean(pageResult, IotProductRespVO.class));
}
}
\ No newline at end of file
diff --git a/yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/controller/admin/product/vo/IotProductPageReqVO.java b/yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/controller/admin/product/vo/IotProductPageReqVO.java
new file mode 100644
index 000000000..afc3aafa0
--- /dev/null
+++ b/yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/controller/admin/product/vo/IotProductPageReqVO.java
@@ -0,0 +1,22 @@
+package cn.iocoder.yudao.module.iot.controller.admin.product.vo;
+
+import cn.iocoder.yudao.framework.common.pojo.PageParam;
+import io.swagger.v3.oas.annotations.media.Schema;
+import lombok.Data;
+import lombok.EqualsAndHashCode;
+import lombok.ToString;
+
+// TODO @haohao:涉及到 iot 的拼写,要不都用 IoT,貌似更规范
+@Schema(description = "管理后台 - iot 产品分页 Request VO")
+@Data
+@EqualsAndHashCode(callSuper = true)
+@ToString(callSuper = true)
+public class IotProductPageReqVO extends PageParam {
+
+ @Schema(description = "产品名称", example = "李四")
+ private String name;
+
+ @Schema(description = "产品标识")
+ private String productKey;
+
+}
\ No newline at end of file
diff --git a/yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/controller/admin/product/vo/ProductRespVO.java b/yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/controller/admin/product/vo/IotProductRespVO.java
similarity index 98%
rename from yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/controller/admin/product/vo/ProductRespVO.java
rename to yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/controller/admin/product/vo/IotProductRespVO.java
index 1a60f0290..066efca93 100644
--- a/yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/controller/admin/product/vo/ProductRespVO.java
+++ b/yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/controller/admin/product/vo/IotProductRespVO.java
@@ -10,7 +10,7 @@ import java.time.LocalDateTime;
@Schema(description = "管理后台 - iot 产品 Response VO")
@Data
@ExcelIgnoreUnannotated
-public class ProductRespVO {
+public class IotProductRespVO {
@Schema(description = "产品ID", requiredMode = Schema.RequiredMode.REQUIRED, example = "26087")
@ExcelProperty("产品ID")
diff --git a/yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/controller/admin/product/vo/ProductSaveReqVO.java b/yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/controller/admin/product/vo/IotProductSaveReqVO.java
similarity index 85%
rename from yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/controller/admin/product/vo/ProductSaveReqVO.java
rename to yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/controller/admin/product/vo/IotProductSaveReqVO.java
index ecbbb03c9..ad01bcd03 100644
--- a/yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/controller/admin/product/vo/ProductSaveReqVO.java
+++ b/yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/controller/admin/product/vo/IotProductSaveReqVO.java
@@ -3,13 +3,13 @@ package cn.iocoder.yudao.module.iot.controller.admin.product.vo;
import cn.iocoder.yudao.framework.common.validation.InEnum;
import cn.iocoder.yudao.module.iot.enums.product.*;
import io.swagger.v3.oas.annotations.media.Schema;
-import lombok.*;
-import java.util.*;
-import jakarta.validation.constraints.*;
+import jakarta.validation.constraints.NotEmpty;
+import jakarta.validation.constraints.NotNull;
+import lombok.Data;
@Schema(description = "管理后台 - iot 产品新增/修改 Request VO")
@Data
-public class ProductSaveReqVO {
+public class IotProductSaveReqVO {
@Schema(description = "产品编号", requiredMode = Schema.RequiredMode.AUTO, example = "1")
private Long id;
@@ -26,15 +26,15 @@ public class ProductSaveReqVO {
@NotNull(message = "设备类型不能为空")
private Integer deviceType;
- @Schema(description = "联网方式", requiredMode = Schema.RequiredMode.REQUIRED,example = "0")
+ @Schema(description = "联网方式", requiredMode = Schema.RequiredMode.REQUIRED, example = "0")
@InEnum(value = IotNetTypeEnum.class, message = "联网方式必须是 {value}")
private Integer netType;
- @Schema(description = "接入网关协议", requiredMode = Schema.RequiredMode.REQUIRED,example = "0")
+ @Schema(description = "接入网关协议", requiredMode = Schema.RequiredMode.REQUIRED, example = "0")
@InEnum(value = IotProtocolTypeEnum.class, message = "接入网关协议必须是 {value}")
private Integer protocolType;
- @Schema(description = "数据格式",requiredMode = Schema.RequiredMode.REQUIRED, example = "0")
+ @Schema(description = "数据格式", requiredMode = Schema.RequiredMode.REQUIRED, example = "0")
@InEnum(value = IotDataFormatEnum.class, message = "数据格式必须是 {value}")
@NotNull(message = "数据格式不能为空")
private Integer dataFormat;
diff --git a/yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/controller/admin/product/vo/ProductPageReqVO.java b/yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/controller/admin/product/vo/ProductPageReqVO.java
deleted file mode 100644
index dc0ae9d65..000000000
--- a/yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/controller/admin/product/vo/ProductPageReqVO.java
+++ /dev/null
@@ -1,59 +0,0 @@
-package cn.iocoder.yudao.module.iot.controller.admin.product.vo;
-
-import cn.iocoder.yudao.framework.common.pojo.PageParam;
-import io.swagger.v3.oas.annotations.media.Schema;
-import lombok.Data;
-import lombok.EqualsAndHashCode;
-import lombok.ToString;
-import org.springframework.format.annotation.DateTimeFormat;
-
-import java.time.LocalDateTime;
-
-import static cn.iocoder.yudao.framework.common.util.date.DateUtils.FORMAT_YEAR_MONTH_DAY_HOUR_MINUTE_SECOND;
-
-// TODO @haohao:涉及到 iot 的拼写,要不都用 IoT,貌似更规范
-// TODO 芋艿:需要清理掉一些无用字段
-@Schema(description = "管理后台 - iot 产品分页 Request VO")
-@Data
-@EqualsAndHashCode(callSuper = true)
-@ToString(callSuper = true)
-public class ProductPageReqVO extends PageParam {
-
- @Schema(description = "产品名称", example = "李四")
- private String name;
-
- @Schema(description = "创建时间")
- @DateTimeFormat(pattern = FORMAT_YEAR_MONTH_DAY_HOUR_MINUTE_SECOND)
- private LocalDateTime[] createTime;
-
- @Schema(description = "产品标识")
- private String productKey;
-
- @Schema(description = "接入网关协议", example = "2")
- private Integer protocolType;
-
- @Schema(description = "协议编号(脚本解析 id)", example = "13177")
- private Long protocolId;
-
- @Schema(description = "产品所属品类标识符", example = "14237")
- private Long categoryId;
-
- @Schema(description = "产品描述", example = "你猜")
- private String description;
-
- @Schema(description = "数据校验级别", example = "1")
- private Integer validateType;
-
- @Schema(description = "产品状态", example = "1")
- private Integer status;
-
- @Schema(description = "设备类型", example = "2")
- private Integer deviceType;
-
- @Schema(description = "联网方式", example = "2")
- private Integer netType;
-
- @Schema(description = "数据格式", example = "0")
- private Integer dataFormat;
-
-}
\ No newline at end of file
diff --git a/yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/dal/dataobject/product/ProductDO.java b/yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/dal/dataobject/product/IotProductDO.java
similarity index 94%
rename from yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/dal/dataobject/product/ProductDO.java
rename to yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/dal/dataobject/product/IotProductDO.java
index 37c1eb513..1fa22c7d1 100644
--- a/yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/dal/dataobject/product/ProductDO.java
+++ b/yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/dal/dataobject/product/IotProductDO.java
@@ -19,7 +19,7 @@ import lombok.*;
@Builder
@NoArgsConstructor
@AllArgsConstructor
-public class ProductDO extends BaseDO {
+public class IotProductDO extends BaseDO {
/**
* 产品ID
@@ -37,7 +37,7 @@ public class ProductDO extends BaseDO {
private String productKey;
/**
* 产品所属品类编号
- *
+ *
* TODO 外键:后续加
*/
private Long categoryId;
@@ -48,44 +48,44 @@ public class ProductDO extends BaseDO {
/**
* 产品状态
- *
+ *
* 枚举 {@link cn.iocoder.yudao.module.iot.enums.product.IotProductStatusEnum}
*/
private Integer status;
/**
* 设备类型
- *
+ *
* 枚举 {@link cn.iocoder.yudao.module.iot.enums.product.IotProductDeviceTypeEnum}
*/
private Integer deviceType;
/**
* 联网方式
- *
+ *
* 枚举 {@link cn.iocoder.yudao.module.iot.enums.product.IotNetTypeEnum}
*/
private Integer netType;
/**
* 接入网关协议
- *
+ *
* 枚举 {@link cn.iocoder.yudao.module.iot.enums.product.IotProtocolTypeEnum}
*/
private Integer protocolType;
/**
* 协议编号
- *
+ *
* TODO 外键:后续加
*/
private Long protocolId;
/**
* 数据格式
- *
+ *
* 枚举 {@link cn.iocoder.yudao.module.iot.enums.product.IotDataFormatEnum}
*/
private Integer dataFormat;
/**
* 数据校验级别
- *
+ *
* 枚举 {@link cn.iocoder.yudao.module.iot.enums.product.IotValidateTypeEnum}
*/
private Integer validateType;
diff --git a/yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/dal/mysql/product/IotProductMapper.java b/yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/dal/mysql/product/IotProductMapper.java
new file mode 100644
index 000000000..111ed4969
--- /dev/null
+++ b/yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/dal/mysql/product/IotProductMapper.java
@@ -0,0 +1,28 @@
+package cn.iocoder.yudao.module.iot.dal.mysql.product;
+
+import cn.iocoder.yudao.framework.common.pojo.PageResult;
+import cn.iocoder.yudao.framework.mybatis.core.mapper.BaseMapperX;
+import cn.iocoder.yudao.framework.mybatis.core.query.LambdaQueryWrapperX;
+import cn.iocoder.yudao.module.iot.controller.admin.product.vo.IotProductPageReqVO;
+import cn.iocoder.yudao.module.iot.dal.dataobject.product.IotProductDO;
+import org.apache.ibatis.annotations.Mapper;
+
+/**
+ * iot 产品 Mapper
+ *
+ * @author ahh
+ */
+@Mapper
+public interface IotProductMapper extends BaseMapperX {
+
+ default PageResult selectPage(IotProductPageReqVO reqVO) {
+ return selectPage(reqVO, new LambdaQueryWrapperX()
+ .likeIfPresent(IotProductDO::getName, reqVO.getName())
+ .likeIfPresent(IotProductDO::getProductKey, reqVO.getProductKey())
+ .orderByDesc(IotProductDO::getId));
+ }
+
+ default IotProductDO selectByProductKey(String productKey) {
+ return selectOne(new LambdaQueryWrapperX().eq(IotProductDO::getProductKey, productKey));
+ }
+}
\ No newline at end of file
diff --git a/yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/dal/mysql/product/ProductMapper.java b/yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/dal/mysql/product/ProductMapper.java
deleted file mode 100644
index d9af9b4b9..000000000
--- a/yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/dal/mysql/product/ProductMapper.java
+++ /dev/null
@@ -1,35 +0,0 @@
-package cn.iocoder.yudao.module.iot.dal.mysql.product;
-
-import cn.iocoder.yudao.framework.common.pojo.PageResult;
-import cn.iocoder.yudao.framework.mybatis.core.mapper.BaseMapperX;
-import cn.iocoder.yudao.framework.mybatis.core.query.LambdaQueryWrapperX;
-import cn.iocoder.yudao.module.iot.controller.admin.product.vo.ProductPageReqVO;
-import cn.iocoder.yudao.module.iot.dal.dataobject.product.ProductDO;
-import org.apache.ibatis.annotations.Mapper;
-
-/**
- * iot 产品 Mapper
- *
- * @author ahh
- */
-@Mapper
-public interface ProductMapper extends BaseMapperX {
-
- default PageResult selectPage(ProductPageReqVO reqVO) {
- return selectPage(reqVO, new LambdaQueryWrapperX()
- .likeIfPresent(ProductDO::getName, reqVO.getName())
- .betweenIfPresent(ProductDO::getCreateTime, reqVO.getCreateTime())
- .likeIfPresent(ProductDO::getProductKey, reqVO.getProductKey())
- .eqIfPresent(ProductDO::getProtocolId, reqVO.getProtocolId())
- .eqIfPresent(ProductDO::getCategoryId, reqVO.getCategoryId())
- .eqIfPresent(ProductDO::getDescription, reqVO.getDescription())
- .eqIfPresent(ProductDO::getValidateType, reqVO.getValidateType())
- .eqIfPresent(ProductDO::getStatus, reqVO.getStatus())
- .eqIfPresent(ProductDO::getDeviceType, reqVO.getDeviceType())
- .eqIfPresent(ProductDO::getNetType, reqVO.getNetType())
- .eqIfPresent(ProductDO::getProtocolType, reqVO.getProtocolType())
- .eqIfPresent(ProductDO::getDataFormat, reqVO.getDataFormat())
- .orderByDesc(ProductDO::getId));
- }
-
-}
\ No newline at end of file
diff --git a/yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/service/product/ProductService.java b/yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/service/product/IotProductService.java
similarity index 62%
rename from yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/service/product/ProductService.java
rename to yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/service/product/IotProductService.java
index 8d4fdf801..14f408030 100644
--- a/yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/service/product/ProductService.java
+++ b/yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/service/product/IotProductService.java
@@ -1,9 +1,9 @@
package cn.iocoder.yudao.module.iot.service.product;
import cn.iocoder.yudao.framework.common.pojo.PageResult;
-import cn.iocoder.yudao.module.iot.controller.admin.product.vo.ProductPageReqVO;
-import cn.iocoder.yudao.module.iot.controller.admin.product.vo.ProductSaveReqVO;
-import cn.iocoder.yudao.module.iot.dal.dataobject.product.ProductDO;
+import cn.iocoder.yudao.module.iot.controller.admin.product.vo.IotProductPageReqVO;
+import cn.iocoder.yudao.module.iot.controller.admin.product.vo.IotProductSaveReqVO;
+import cn.iocoder.yudao.module.iot.dal.dataobject.product.IotProductDO;
import jakarta.validation.Valid;
/**
@@ -11,7 +11,7 @@ import jakarta.validation.Valid;
*
* @author ahh
*/
-public interface ProductService {
+public interface IotProductService {
/**
* 创建产品
@@ -19,14 +19,14 @@ public interface ProductService {
* @param createReqVO 创建信息
* @return 编号
*/
- Long createProduct(@Valid ProductSaveReqVO createReqVO);
+ Long createProduct(@Valid IotProductSaveReqVO createReqVO);
/**
* 更新产品
*
* @param updateReqVO 更新信息
*/
- void updateProduct(@Valid ProductSaveReqVO updateReqVO);
+ void updateProduct(@Valid IotProductSaveReqVO updateReqVO);
/**
* 删除产品
@@ -41,7 +41,7 @@ public interface ProductService {
* @param id 编号
* @return 产品
*/
- ProductDO getProduct(Long id);
+ IotProductDO getProduct(Long id);
/**
* 获得产品分页
@@ -49,7 +49,7 @@ public interface ProductService {
* @param pageReqVO 分页查询
* @return 产品分页
*/
- PageResult getProductPage(ProductPageReqVO pageReqVO);
+ PageResult getProductPage(IotProductPageReqVO pageReqVO);
/**
* 更新产品状态
diff --git a/yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/service/product/IotProductServiceImpl.java b/yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/service/product/IotProductServiceImpl.java
new file mode 100644
index 000000000..65686f533
--- /dev/null
+++ b/yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/service/product/IotProductServiceImpl.java
@@ -0,0 +1,117 @@
+package cn.iocoder.yudao.module.iot.service.product;
+
+import cn.hutool.core.util.StrUtil;
+import cn.iocoder.yudao.framework.common.pojo.PageResult;
+import cn.iocoder.yudao.framework.common.util.object.BeanUtils;
+import cn.iocoder.yudao.module.iot.controller.admin.product.vo.IotProductPageReqVO;
+import cn.iocoder.yudao.module.iot.controller.admin.product.vo.IotProductSaveReqVO;
+import cn.iocoder.yudao.module.iot.dal.dataobject.product.IotProductDO;
+import cn.iocoder.yudao.module.iot.dal.mysql.product.IotProductMapper;
+import cn.iocoder.yudao.module.iot.enums.product.IotProductStatusEnum;
+import jakarta.annotation.Resource;
+import org.springframework.stereotype.Service;
+import org.springframework.validation.annotation.Validated;
+
+import java.util.Objects;
+import java.util.UUID;
+
+import static cn.iocoder.yudao.framework.common.exception.util.ServiceExceptionUtil.exception;
+import static cn.iocoder.yudao.module.iot.enums.ErrorCodeConstants.PRODUCT_NOT_EXISTS;
+import static cn.iocoder.yudao.module.iot.enums.ErrorCodeConstants.PRODUCT_STATUS_NOT_DELETE;
+
+/**
+ * IOT 产品 Service 实现类
+ *
+ * @author ahh
+ */
+@Service
+@Validated
+public class IotProductServiceImpl implements IotProductService {
+
+ @Resource
+ private IotProductMapper productMapper;
+
+ @Override
+ public Long createProduct(IotProductSaveReqVO createReqVO) {
+ // 1. 生成 ProductKey
+ createProductKey(createReqVO);
+ // 2. 插入
+ IotProductDO product = BeanUtils.toBean(createReqVO, IotProductDO.class);
+ productMapper.insert(product);
+ return product.getId();
+ }
+
+ /**
+ * 创建 ProductKey
+ *
+ * @param createReqVO 创建信息
+ */
+ private void createProductKey(IotProductSaveReqVO createReqVO) {
+ String productKey = createReqVO.getProductKey();
+ // 1. productKey为空,生成随机的 11 位字符串
+ if (StrUtil.isEmpty(productKey)) {
+ productKey = UUID.randomUUID().toString().replace("-", "").substring(0, 11);
+ }
+ // 2. 校验唯一性
+ if (productMapper.selectByProductKey(productKey) != null) {
+ throw exception(PRODUCT_NOT_EXISTS);
+ }
+ createReqVO.setProductKey(productKey);
+ }
+
+ @Override
+ public void updateProduct(IotProductSaveReqVO updateReqVO) {
+ updateReqVO.setProductKey(null); // 不更新产品标识
+ // 1.1 校验存在
+ IotProductDO iotProductDO = validateProductExists(updateReqVO.getId());
+ // 1.2 发布状态不可更新
+ validateProductStatus(iotProductDO);
+ // 2. 更新
+ IotProductDO updateObj = BeanUtils.toBean(updateReqVO, IotProductDO.class);
+ productMapper.updateById(updateObj);
+ }
+
+ @Override
+ public void deleteProduct(Long id) {
+ // 1.1 校验存在
+ IotProductDO iotProductDO = validateProductExists(id);
+ // 1.2 发布状态不可删除
+ validateProductStatus(iotProductDO);
+ // 2. 删除
+ productMapper.deleteById(id);
+ }
+
+ private IotProductDO validateProductExists(Long id) {
+ IotProductDO iotProductDO = productMapper.selectById(id);
+ if (iotProductDO == null) {
+ throw exception(PRODUCT_NOT_EXISTS);
+ }
+ return iotProductDO;
+ }
+
+ private void validateProductStatus(IotProductDO iotProductDO) {
+ if (Objects.equals(iotProductDO.getStatus(), IotProductStatusEnum.PUBLISHED.getType())) {
+ throw exception(PRODUCT_STATUS_NOT_DELETE);
+ }
+ }
+
+ @Override
+ public IotProductDO getProduct(Long id) {
+ return productMapper.selectById(id);
+ }
+
+ @Override
+ public PageResult getProductPage(IotProductPageReqVO pageReqVO) {
+ return productMapper.selectPage(pageReqVO);
+ }
+
+ @Override
+ public void updateProductStatus(Long id, Integer status) {
+ // 1. 校验存在
+ validateProductExists(id);
+ // 2. 更新
+ IotProductDO updateObj = IotProductDO.builder().id(id).status(status).build();
+ productMapper.updateById(updateObj);
+ }
+
+}
\ No newline at end of file
diff --git a/yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/service/product/ProductServiceImpl.java b/yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/service/product/ProductServiceImpl.java
deleted file mode 100644
index e5e3bc421..000000000
--- a/yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/service/product/ProductServiceImpl.java
+++ /dev/null
@@ -1,109 +0,0 @@
-package cn.iocoder.yudao.module.iot.service.product;
-
-import cn.iocoder.yudao.framework.common.pojo.PageResult;
-import cn.iocoder.yudao.framework.common.util.object.BeanUtils;
-import cn.iocoder.yudao.module.iot.controller.admin.product.vo.ProductPageReqVO;
-import cn.iocoder.yudao.module.iot.controller.admin.product.vo.ProductSaveReqVO;
-import cn.iocoder.yudao.module.iot.dal.dataobject.product.ProductDO;
-import cn.iocoder.yudao.module.iot.dal.mysql.product.ProductMapper;
-import cn.iocoder.yudao.module.iot.enums.product.IotProductStatusEnum;
-import jakarta.annotation.Resource;
-import org.springframework.stereotype.Service;
-import org.springframework.validation.annotation.Validated;
-
-import java.util.Objects;
-import java.util.UUID;
-
-import static cn.iocoder.yudao.framework.common.exception.util.ServiceExceptionUtil.exception;
-import static cn.iocoder.yudao.module.iot.enums.ErrorCodeConstants.PRODUCT_NOT_EXISTS;
-import static cn.iocoder.yudao.module.iot.enums.ErrorCodeConstants.PRODUCT_STATUS_NOT_DELETE;
-
-/**
- * IOT 产品 Service 实现类
- *
- * @author ahh
- */
-@Service
-@Validated
-public class ProductServiceImpl implements ProductService {
-
- @Resource
- private ProductMapper productMapper;
-
- @Override
- public Long createProduct(ProductSaveReqVO createReqVO) {
- // 生成 ProductKey
- createProductKey(createReqVO);
- // 插入
- ProductDO product = BeanUtils.toBean(createReqVO, ProductDO.class);
- productMapper.insert(product);
- return product.getId();
- }
-
- /**
- * 创建 ProductKey
- *
- * @param createReqVO 创建信息
- */
- private void createProductKey(ProductSaveReqVO createReqVO) {
- // TODO @haohao:应该前端没传递的时候,才生成哇?ps:需要校验下唯一性,万一有重复;
- // 生成随机的 11 位字符串
- String productKey = UUID.randomUUID().toString().replace("-", "").substring(0, 11);
- createReqVO.setProductKey(productKey);
- }
-
- @Override
- public void updateProduct(ProductSaveReqVO updateReqVO) {
- updateReqVO.setProductKey(null); // 不更新产品标识
- // 校验存在
- validateProductExists(updateReqVO.getId());
- // TODO @haohao:如果已经发布,允许编辑么?
- // 更新
- ProductDO updateObj = BeanUtils.toBean(updateReqVO, ProductDO.class);
- productMapper.updateById(updateObj);
- }
-
- @Override
- public void deleteProduct(Long id) {
- // TODO @haohao:这里最好只查询一次哈
- // 1.1 校验存在
- validateProductExists(id);
- // 1.2 发布状态不可删除
- validateProductStatus(id);
- // 2. 删除
- productMapper.deleteById(id);
- }
-
- private void validateProductExists(Long id) {
- if (productMapper.selectById(id) == null) {
- throw exception(PRODUCT_NOT_EXISTS);
- }
- }
-
- private void validateProductStatus(Long id) {
- ProductDO product = productMapper.selectById(id);
- if (Objects.equals(product.getStatus(), IotProductStatusEnum.PUBLISHED.getType())) {
- throw exception(PRODUCT_STATUS_NOT_DELETE);
- }
- }
-
- @Override
- public ProductDO getProduct(Long id) {
- return productMapper.selectById(id);
- }
-
- @Override
- public PageResult getProductPage(ProductPageReqVO pageReqVO) {
- return productMapper.selectPage(pageReqVO);
- }
-
- @Override
- public void updateProductStatus(Long id, Integer status) {
- // 校验存在
- validateProductExists(id);
- // 更新
- ProductDO updateObj = ProductDO.builder().id(id).status(status).build();
- productMapper.updateById(updateObj);
- }
-
-}
\ No newline at end of file
From d9856ff79bdb5251faeda5cb8029f708d7513b9f Mon Sep 17 00:00:00 2001
From: puhui999
Date: Tue, 10 Sep 2024 11:46:21 +0800
Subject: [PATCH 017/156] =?UTF-8?q?=E3=80=90=E4=BB=A3=E7=A0=81=E4=BC=98?=
=?UTF-8?q?=E5=8C=96=E3=80=91=E5=95=86=E5=9F=8E:=20=E6=BB=A1=E5=87=8F?=
=?UTF-8?q?=E9=80=81=E6=B4=BB=E5=8A=A8?=
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
---
.../api/reward/RewardActivityApi.java | 10 +--
.../promotion/enums/ErrorCodeConstants.java | 1 +
.../api/reward/RewardActivityApiImpl.java | 11 ++-
.../mysql/reward/RewardActivityMapper.java | 28 ------
.../service/reward/RewardActivityService.java | 12 +--
.../reward/RewardActivityServiceImpl.java | 27 +++---
.../reward/RewardActivityServiceImplTest.java | 87 ++++++++++++++-----
.../TradeRewardActivityPriceCalculator.java | 23 ++---
...radeRewardActivityPriceCalculatorTest.java | 48 +++++-----
9 files changed, 123 insertions(+), 124 deletions(-)
diff --git a/yudao-module-mall/yudao-module-promotion-api/src/main/java/cn/iocoder/yudao/module/promotion/api/reward/RewardActivityApi.java b/yudao-module-mall/yudao-module-promotion-api/src/main/java/cn/iocoder/yudao/module/promotion/api/reward/RewardActivityApi.java
index efeddf3d5..2a941e051 100644
--- a/yudao-module-mall/yudao-module-promotion-api/src/main/java/cn/iocoder/yudao/module/promotion/api/reward/RewardActivityApi.java
+++ b/yudao-module-mall/yudao-module-promotion-api/src/main/java/cn/iocoder/yudao/module/promotion/api/reward/RewardActivityApi.java
@@ -2,7 +2,7 @@ package cn.iocoder.yudao.module.promotion.api.reward;
import cn.iocoder.yudao.module.promotion.api.reward.dto.RewardActivityMatchRespDTO;
-import java.util.Collection;
+import java.time.LocalDateTime;
import java.util.List;
/**
@@ -12,13 +12,13 @@ import java.util.List;
*/
public interface RewardActivityApi {
-
/**
- * 基于指定的 SPU 编号数组,获得它们匹配的满减送活动
+ * 获得当前时间内开启的满减送活动
*
- * @param spuIds SPU 编号数组
+ * @param status 状态
+ * @param dateTime 时间
* @return 满减送活动列表
*/
- List getMatchRewardActivityList(Collection spuIds);
+ List getRewardActivityListByStatusAndNow(Integer status, LocalDateTime dateTime);
}
diff --git a/yudao-module-mall/yudao-module-promotion-api/src/main/java/cn/iocoder/yudao/module/promotion/enums/ErrorCodeConstants.java b/yudao-module-mall/yudao-module-promotion-api/src/main/java/cn/iocoder/yudao/module/promotion/enums/ErrorCodeConstants.java
index e1efb9c91..116e2fe42 100644
--- a/yudao-module-mall/yudao-module-promotion-api/src/main/java/cn/iocoder/yudao/module/promotion/enums/ErrorCodeConstants.java
+++ b/yudao-module-mall/yudao-module-promotion-api/src/main/java/cn/iocoder/yudao/module/promotion/enums/ErrorCodeConstants.java
@@ -46,6 +46,7 @@ public interface ErrorCodeConstants {
ErrorCode REWARD_ACTIVITY_CLOSE_FAIL_STATUS_CLOSED = new ErrorCode(1_013_006_004, "满减送活动已关闭,不能重复关闭");
ErrorCode REWARD_ACTIVITY_SCOPE_ALL_EXISTS = new ErrorCode(1_013_006_005, "已存在商品范围为全场的满减送活动");
ErrorCode REWARD_ACTIVITY_SCOPE_CATEGORY_EXISTS = new ErrorCode(1_013_006_006, "存在商品类型参加了其它满减送活动");
+ ErrorCode REWARD_ACTIVITY_TIME_CONFLICTS = new ErrorCode(1_013_006_007, "满减送活动时段冲突");
// ========== TODO 空着 1-013-007-000 ============
diff --git a/yudao-module-mall/yudao-module-promotion-biz/src/main/java/cn/iocoder/yudao/module/promotion/api/reward/RewardActivityApiImpl.java b/yudao-module-mall/yudao-module-promotion-biz/src/main/java/cn/iocoder/yudao/module/promotion/api/reward/RewardActivityApiImpl.java
index 936c791a3..ce3d1c802 100644
--- a/yudao-module-mall/yudao-module-promotion-biz/src/main/java/cn/iocoder/yudao/module/promotion/api/reward/RewardActivityApiImpl.java
+++ b/yudao-module-mall/yudao-module-promotion-biz/src/main/java/cn/iocoder/yudao/module/promotion/api/reward/RewardActivityApiImpl.java
@@ -1,12 +1,14 @@
package cn.iocoder.yudao.module.promotion.api.reward;
+import cn.iocoder.yudao.framework.common.util.object.BeanUtils;
import cn.iocoder.yudao.module.promotion.api.reward.dto.RewardActivityMatchRespDTO;
+import cn.iocoder.yudao.module.promotion.dal.dataobject.reward.RewardActivityDO;
import cn.iocoder.yudao.module.promotion.service.reward.RewardActivityService;
+import jakarta.annotation.Resource;
import org.springframework.stereotype.Service;
import org.springframework.validation.annotation.Validated;
-import jakarta.annotation.Resource;
-import java.util.Collection;
+import java.time.LocalDateTime;
import java.util.List;
/**
@@ -22,8 +24,9 @@ public class RewardActivityApiImpl implements RewardActivityApi {
private RewardActivityService rewardActivityService;
@Override
- public List getMatchRewardActivityList(Collection spuIds) {
- return rewardActivityService.getMatchRewardActivityList(spuIds);
+ public List getRewardActivityListByStatusAndNow(Integer status, LocalDateTime dateTime) {
+ List list = rewardActivityService.getRewardActivityListByStatusAndDateTimeLt(status, dateTime);
+ return BeanUtils.toBean(list, RewardActivityMatchRespDTO.class);
}
}
diff --git a/yudao-module-mall/yudao-module-promotion-biz/src/main/java/cn/iocoder/yudao/module/promotion/dal/mysql/reward/RewardActivityMapper.java b/yudao-module-mall/yudao-module-promotion-biz/src/main/java/cn/iocoder/yudao/module/promotion/dal/mysql/reward/RewardActivityMapper.java
index 915696967..f8b8d5ccb 100755
--- a/yudao-module-mall/yudao-module-promotion-biz/src/main/java/cn/iocoder/yudao/module/promotion/dal/mysql/reward/RewardActivityMapper.java
+++ b/yudao-module-mall/yudao-module-promotion-biz/src/main/java/cn/iocoder/yudao/module/promotion/dal/mysql/reward/RewardActivityMapper.java
@@ -1,19 +1,14 @@
package cn.iocoder.yudao.module.promotion.dal.mysql.reward;
-import cn.hutool.core.util.StrUtil;
import cn.iocoder.yudao.framework.common.pojo.PageResult;
import cn.iocoder.yudao.framework.mybatis.core.mapper.BaseMapperX;
import cn.iocoder.yudao.framework.mybatis.core.query.LambdaQueryWrapperX;
import cn.iocoder.yudao.module.promotion.controller.admin.reward.vo.RewardActivityPageReqVO;
import cn.iocoder.yudao.module.promotion.dal.dataobject.reward.RewardActivityDO;
-import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import org.apache.ibatis.annotations.Mapper;
import java.time.LocalDateTime;
-import java.util.Collection;
import java.util.List;
-import java.util.function.Function;
-import java.util.stream.Collectors;
/**
* 满减送活动 Mapper
@@ -30,29 +25,6 @@ public interface RewardActivityMapper extends BaseMapperX {
.orderByDesc(RewardActivityDO::getId));
}
- default List selectListByProductScopeAndStatus(Integer productScope, Integer status) {
- return selectList(new LambdaQueryWrapperX()
- .eq(RewardActivityDO::getProductScope, productScope)
- .eq(RewardActivityDO::getStatus, status));
- }
-
- default List selectListBySpuIdsAndStatus(Collection spuIds, Integer status) {
- Function, String> productScopeValuesFindInSetFunc = ids -> ids.stream()
- .map(id -> StrUtil.format("FIND_IN_SET({}, product_spu_ids) ", id))
- .collect(Collectors.joining(" OR "));
- return selectList(new QueryWrapper()
- .eq("status", status)
- .apply(productScopeValuesFindInSetFunc.apply(spuIds)));
- }
-
- /**
- * 获取指定活动编号的活动列表且
- * 开始时间和结束时间小于给定时间 dateTime 的活动列表
- *
- * @param status 状态
- * @param dateTime 指定日期
- * @return 活动列表
- */
default List selectListByStatusAndDateTimeLt(Integer status, LocalDateTime dateTime) {
return selectList(new LambdaQueryWrapperX()
.eq(RewardActivityDO::getStatus, status)
diff --git a/yudao-module-mall/yudao-module-promotion-biz/src/main/java/cn/iocoder/yudao/module/promotion/service/reward/RewardActivityService.java b/yudao-module-mall/yudao-module-promotion-biz/src/main/java/cn/iocoder/yudao/module/promotion/service/reward/RewardActivityService.java
index 27cc86c33..d35e0874a 100755
--- a/yudao-module-mall/yudao-module-promotion-biz/src/main/java/cn/iocoder/yudao/module/promotion/service/reward/RewardActivityService.java
+++ b/yudao-module-mall/yudao-module-promotion-biz/src/main/java/cn/iocoder/yudao/module/promotion/service/reward/RewardActivityService.java
@@ -1,7 +1,6 @@
package cn.iocoder.yudao.module.promotion.service.reward;
import cn.iocoder.yudao.framework.common.pojo.PageResult;
-import cn.iocoder.yudao.module.promotion.api.reward.dto.RewardActivityMatchRespDTO;
import cn.iocoder.yudao.module.promotion.controller.admin.reward.vo.RewardActivityCreateReqVO;
import cn.iocoder.yudao.module.promotion.controller.admin.reward.vo.RewardActivityPageReqVO;
import cn.iocoder.yudao.module.promotion.controller.admin.reward.vo.RewardActivityUpdateReqVO;
@@ -9,7 +8,6 @@ import cn.iocoder.yudao.module.promotion.dal.dataobject.reward.RewardActivityDO;
import jakarta.validation.Valid;
import java.time.LocalDateTime;
-import java.util.Collection;
import java.util.List;
/**
@@ -65,15 +63,7 @@ public interface RewardActivityService {
PageResult getRewardActivityPage(RewardActivityPageReqVO pageReqVO);
/**
- * 基于指定的 SPU 编号数组,获得它们匹配的满减送活动
- *
- * @param spuIds SPU 编号数组
- * @return 满减送活动列表
- */
- List getMatchRewardActivityList(Collection spuIds);
-
- /**
- * 获取指定 spu 编号最近参加的活动,每个 spuId 只返回一条记录
+ * 开始时间 < 指定时间 < 结束时间,也就是说获取指定时间段的活动
*
* @param status 状态
* @param dateTime 当前日期时间
diff --git a/yudao-module-mall/yudao-module-promotion-biz/src/main/java/cn/iocoder/yudao/module/promotion/service/reward/RewardActivityServiceImpl.java b/yudao-module-mall/yudao-module-promotion-biz/src/main/java/cn/iocoder/yudao/module/promotion/service/reward/RewardActivityServiceImpl.java
index eefbc6dee..f12c0f284 100755
--- a/yudao-module-mall/yudao-module-promotion-biz/src/main/java/cn/iocoder/yudao/module/promotion/service/reward/RewardActivityServiceImpl.java
+++ b/yudao-module-mall/yudao-module-promotion-biz/src/main/java/cn/iocoder/yudao/module/promotion/service/reward/RewardActivityServiceImpl.java
@@ -1,11 +1,11 @@
package cn.iocoder.yudao.module.promotion.service.reward;
+import cn.hutool.core.date.LocalDateTimeUtil;
import cn.iocoder.yudao.framework.common.enums.CommonStatusEnum;
import cn.iocoder.yudao.framework.common.pojo.PageResult;
import cn.iocoder.yudao.framework.common.util.object.BeanUtils;
import cn.iocoder.yudao.module.product.api.category.ProductCategoryApi;
import cn.iocoder.yudao.module.product.api.spu.ProductSpuApi;
-import cn.iocoder.yudao.module.promotion.api.reward.dto.RewardActivityMatchRespDTO;
import cn.iocoder.yudao.module.promotion.controller.admin.reward.vo.RewardActivityBaseVO;
import cn.iocoder.yudao.module.promotion.controller.admin.reward.vo.RewardActivityCreateReqVO;
import cn.iocoder.yudao.module.promotion.controller.admin.reward.vo.RewardActivityPageReqVO;
@@ -19,7 +19,6 @@ import org.springframework.stereotype.Service;
import org.springframework.validation.annotation.Validated;
import java.time.LocalDateTime;
-import java.util.Collection;
import java.util.List;
import java.util.Objects;
@@ -87,8 +86,7 @@ public class RewardActivityServiceImpl implements RewardActivityService {
}
// 更新
- RewardActivityDO updateObj = new RewardActivityDO().setId(id).setStatus(CommonStatusEnum.DISABLE.getStatus());
- rewardActivityMapper.updateById(updateObj);
+ rewardActivityMapper.updateById(new RewardActivityDO().setId(id).setStatus(CommonStatusEnum.DISABLE.getStatus()));
}
@Override
@@ -118,14 +116,21 @@ public class RewardActivityServiceImpl implements RewardActivityService {
* @param rewardActivity 请求
*/
private void validateRewardActivitySpuConflicts(Long id, RewardActivityBaseVO rewardActivity) {
- List list = rewardActivityMapper.selectList(RewardActivityDO::getProductScope,
- rewardActivity.getProductScope(), RewardActivityDO::getStatus, CommonStatusEnum.ENABLE.getStatus());
+ // 0. 获得所有的活动包括关闭的
+ List list = rewardActivityMapper.selectList();
if (id != null) { // 排除自己这个活动
list.removeIf(activity -> id.equals(activity.getId()));
}
- // 情况一:全部商品参加
- if (PromotionProductScopeEnum.isAll(rewardActivity.getProductScope()) && !list.isEmpty()) {
+ // 1.1 校验满减送活动时间是否冲突
+ boolean hasConflict = list.stream().anyMatch(item -> LocalDateTimeUtil.isOverlap(item.getStartTime(), item.getEndTime(),
+ rewardActivity.getStartTime(), rewardActivity.getEndTime()));
+ if (hasConflict) {
+ throw exception(REWARD_ACTIVITY_TIME_CONFLICTS);
+ }
+ // 1.2 校验商品范围是否重叠
+ if (PromotionProductScopeEnum.isAll(rewardActivity.getProductScope()) && // 情况一:全部商品参加
+ anyMatch(list, item -> PromotionProductScopeEnum.isAll(item.getProductScope()))) {
throw exception(REWARD_ACTIVITY_SCOPE_ALL_EXISTS);
}
if (PromotionProductScopeEnum.isSpu(rewardActivity.getProductScope()) || // 情况二:指定商品参加
@@ -156,12 +161,6 @@ public class RewardActivityServiceImpl implements RewardActivityService {
return rewardActivityMapper.selectPage(pageReqVO);
}
- @Override
- public List getMatchRewardActivityList(Collection spuIds) {
- List list = rewardActivityMapper.selectListBySpuIdsAndStatus(spuIds, CommonStatusEnum.ENABLE.getStatus());
- return BeanUtils.toBean(list, RewardActivityMatchRespDTO.class);
- }
-
@Override
public List getRewardActivityListByStatusAndDateTimeLt(Integer status, LocalDateTime dateTime) {
return rewardActivityMapper.selectListByStatusAndDateTimeLt(status, dateTime);
diff --git a/yudao-module-mall/yudao-module-promotion-biz/src/test/java/cn/iocoder/yudao/module/promotion/service/reward/RewardActivityServiceImplTest.java b/yudao-module-mall/yudao-module-promotion-biz/src/test/java/cn/iocoder/yudao/module/promotion/service/reward/RewardActivityServiceImplTest.java
index 7e7cf14db..e8dfd07cc 100755
--- a/yudao-module-mall/yudao-module-promotion-biz/src/test/java/cn/iocoder/yudao/module/promotion/service/reward/RewardActivityServiceImplTest.java
+++ b/yudao-module-mall/yudao-module-promotion-biz/src/test/java/cn/iocoder/yudao/module/promotion/service/reward/RewardActivityServiceImplTest.java
@@ -2,8 +2,9 @@ package cn.iocoder.yudao.module.promotion.service.reward;
import cn.iocoder.yudao.framework.common.enums.CommonStatusEnum;
import cn.iocoder.yudao.framework.common.pojo.PageResult;
-import cn.iocoder.yudao.framework.test.core.ut.BaseDbUnitTest;
-import cn.iocoder.yudao.module.promotion.api.reward.dto.RewardActivityMatchRespDTO;
+import cn.iocoder.yudao.framework.test.core.ut.BaseMockitoUnitTest;
+import cn.iocoder.yudao.module.product.api.category.ProductCategoryApi;
+import cn.iocoder.yudao.module.product.api.spu.ProductSpuApi;
import cn.iocoder.yudao.module.promotion.controller.admin.reward.vo.RewardActivityCreateReqVO;
import cn.iocoder.yudao.module.promotion.controller.admin.reward.vo.RewardActivityPageReqVO;
import cn.iocoder.yudao.module.promotion.controller.admin.reward.vo.RewardActivityUpdateReqVO;
@@ -11,15 +12,19 @@ import cn.iocoder.yudao.module.promotion.dal.dataobject.reward.RewardActivityDO;
import cn.iocoder.yudao.module.promotion.dal.mysql.reward.RewardActivityMapper;
import cn.iocoder.yudao.module.promotion.enums.common.PromotionConditionTypeEnum;
import cn.iocoder.yudao.module.promotion.enums.common.PromotionProductScopeEnum;
-import jakarta.annotation.Resource;
import org.junit.jupiter.api.Disabled;
import org.junit.jupiter.api.Test;
-import org.springframework.context.annotation.Import;
+import org.mockito.InjectMocks;
+import org.mockito.Mock;
import java.time.Duration;
+import java.time.LocalDateTime;
+import java.util.ArrayList;
+import java.util.Collection;
import java.util.List;
import java.util.Set;
+import static cn.hutool.core.collection.CollUtil.intersectionDistinct;
import static cn.hutool.core.util.RandomUtil.randomEle;
import static cn.iocoder.yudao.framework.common.util.collection.SetUtils.asSet;
import static cn.iocoder.yudao.framework.common.util.date.LocalDateTimeUtils.addTime;
@@ -39,14 +44,17 @@ import static org.junit.jupiter.api.Assertions.*;
* @author 芋道源码
*/
@Disabled // TODO 芋艿:后续 fix 补充的单测
-@Import(RewardActivityServiceImpl.class)
-public class RewardActivityServiceImplTest extends BaseDbUnitTest {
+public class RewardActivityServiceImplTest extends BaseMockitoUnitTest {
- @Resource
- private RewardActivityServiceImpl rewardActivityService;
+ @InjectMocks
+ private RewardActivityServiceImpl rewardActivityServiceImpl;
- @Resource
+ @Mock
private RewardActivityMapper rewardActivityMapper;
+ @Mock
+ private ProductCategoryApi productCategoryApi;
+ @Mock
+ private ProductSpuApi productSpuApi;
@Test
public void testCreateRewardActivity_success() {
@@ -59,7 +67,7 @@ public class RewardActivityServiceImplTest extends BaseDbUnitTest {
});
// 调用
- Long rewardActivityId = rewardActivityService.createRewardActivity(reqVO);
+ Long rewardActivityId = rewardActivityServiceImpl.createRewardActivity(reqVO);
// 断言
assertNotNull(rewardActivityId);
// 校验记录的属性是否正确
@@ -86,7 +94,7 @@ public class RewardActivityServiceImplTest extends BaseDbUnitTest {
});
// 调用
- rewardActivityService.updateRewardActivity(reqVO);
+ rewardActivityServiceImpl.updateRewardActivity(reqVO);
// 校验是否更新正确
RewardActivityDO rewardActivity = rewardActivityMapper.selectById(reqVO.getId()); // 获取最新的
assertPojoEquals(reqVO, rewardActivity, "rules");
@@ -105,7 +113,7 @@ public class RewardActivityServiceImplTest extends BaseDbUnitTest {
Long id = dbRewardActivity.getId();
// 调用
- rewardActivityService.closeRewardActivity(id);
+ rewardActivityServiceImpl.closeRewardActivity(id);
// 校验状态
RewardActivityDO rewardActivity = rewardActivityMapper.selectById(id);
assertEquals(rewardActivity.getStatus(), CommonStatusEnum.DISABLE.getStatus());
@@ -117,7 +125,7 @@ public class RewardActivityServiceImplTest extends BaseDbUnitTest {
RewardActivityUpdateReqVO reqVO = randomPojo(RewardActivityUpdateReqVO.class);
// 调用, 并断言异常
- assertServiceException(() -> rewardActivityService.updateRewardActivity(reqVO), REWARD_ACTIVITY_NOT_EXISTS);
+ assertServiceException(() -> rewardActivityServiceImpl.updateRewardActivity(reqVO), REWARD_ACTIVITY_NOT_EXISTS);
}
@Test
@@ -129,7 +137,7 @@ public class RewardActivityServiceImplTest extends BaseDbUnitTest {
Long id = dbRewardActivity.getId();
// 调用
- rewardActivityService.deleteRewardActivity(id);
+ rewardActivityServiceImpl.deleteRewardActivity(id);
// 校验数据不存在了
assertNull(rewardActivityMapper.selectById(id));
}
@@ -140,7 +148,7 @@ public class RewardActivityServiceImplTest extends BaseDbUnitTest {
Long id = randomLongId();
// 调用, 并断言异常
- assertServiceException(() -> rewardActivityService.deleteRewardActivity(id), REWARD_ACTIVITY_NOT_EXISTS);
+ assertServiceException(() -> rewardActivityServiceImpl.deleteRewardActivity(id), REWARD_ACTIVITY_NOT_EXISTS);
}
@Test
@@ -161,7 +169,7 @@ public class RewardActivityServiceImplTest extends BaseDbUnitTest {
reqVO.setStatus(CommonStatusEnum.DISABLE.getStatus());
// 调用
- PageResult pageResult = rewardActivityService.getRewardActivityPage(reqVO);
+ PageResult pageResult = rewardActivityServiceImpl.getRewardActivityPage(reqVO);
// 断言
assertEquals(1, pageResult.getTotal());
assertEquals(1, pageResult.getList().size());
@@ -170,18 +178,22 @@ public class RewardActivityServiceImplTest extends BaseDbUnitTest {
@Test
public void testGetRewardActivities_all() {
+ LocalDateTime now = LocalDateTime.now();
// mock 数据
RewardActivityDO allActivity = randomPojo(RewardActivityDO.class, o -> o.setStatus(CommonStatusEnum.ENABLE.getStatus())
- .setProductScope(PromotionProductScopeEnum.ALL.getScope()));
+ .setProductScope(PromotionProductScopeEnum.ALL.getScope()).setStartTime(now.minusDays(1)).setEndTime(now.plusDays(1)));
rewardActivityMapper.insert(allActivity);
RewardActivityDO productActivity = randomPojo(RewardActivityDO.class, o -> o.setStatus(CommonStatusEnum.ENABLE.getStatus())
- .setProductScope(PromotionProductScopeEnum.SPU.getScope()).setProductScopeValues(asList(1L, 2L)));
+ .setProductScope(PromotionProductScopeEnum.SPU.getScope()).setProductScopeValues(asList(1L, 2L))
+ .setStartTime(now.minusDays(1)).setEndTime(now.plusDays(1)));
rewardActivityMapper.insert(productActivity);
// 准备参数
Set spuIds = asSet(1L, 2L);
- // 调用 TODO getMatchRewardActivities 没有这个方法,但是找到了 getMatchRewardActivityList
- List matchRewardActivityList = rewardActivityService.getMatchRewardActivityList(spuIds);
+ // 调用
+ List activityList = rewardActivityServiceImpl.getRewardActivityListByStatusAndDateTimeLt(
+ CommonStatusEnum.ENABLE.getStatus(), now);
+ List matchRewardActivityList = filterMatchActivity(spuIds, activityList);
// 断言
assertEquals(matchRewardActivityList.size(), 1);
matchRewardActivityList.forEach((activity) -> {
@@ -196,18 +208,22 @@ public class RewardActivityServiceImplTest extends BaseDbUnitTest {
@Test
public void testGetRewardActivities_product() {
+ LocalDateTime now = LocalDateTime.now();
// mock 数据
RewardActivityDO productActivity01 = randomPojo(RewardActivityDO.class, o -> o.setStatus(CommonStatusEnum.ENABLE.getStatus())
- .setProductScope(PromotionProductScopeEnum.SPU.getScope()).setProductScopeValues(asList(1L, 2L)));
+ .setProductScope(PromotionProductScopeEnum.SPU.getScope()).setProductScopeValues(asList(1L, 2L))
+ .setStartTime(now.minusDays(1)).setEndTime(now.plusDays(1)));
rewardActivityMapper.insert(productActivity01);
RewardActivityDO productActivity02 = randomPojo(RewardActivityDO.class, o -> o.setStatus(CommonStatusEnum.ENABLE.getStatus())
- .setProductScope(PromotionProductScopeEnum.SPU.getScope()).setProductScopeValues(singletonList(3L)));
+ .setProductScope(PromotionProductScopeEnum.SPU.getScope()).setProductScopeValues(singletonList(3L))
+ .setStartTime(now.minusDays(1)).setEndTime(now.plusDays(1)));
rewardActivityMapper.insert(productActivity02);
// 准备参数
Set spuIds = asSet(1L, 2L, 3L);
- // 调用 TODO getMatchRewardActivities 没有这个方法,但是找到了 getMatchRewardActivityList
- List matchRewardActivityList = rewardActivityService.getMatchRewardActivityList(spuIds);
+ List activityList = rewardActivityServiceImpl.getRewardActivityListByStatusAndDateTimeLt(
+ CommonStatusEnum.ENABLE.getStatus(), now);
+ List matchRewardActivityList = filterMatchActivity(spuIds, activityList);
// 断言
assertEquals(matchRewardActivityList.size(), 2);
matchRewardActivityList.forEach((activity) -> {
@@ -223,4 +239,27 @@ public class RewardActivityServiceImplTest extends BaseDbUnitTest {
});
}
+ /**
+ * 获得满减送的订单项(商品)列表
+ *
+ * @param spuIds 商品编号
+ * @param activityList 活动列表
+ * @return 订单项(商品)列表
+ */
+ private List filterMatchActivity(Collection spuIds, List activityList) {
+ List resultActivityList = new ArrayList<>();
+ for (RewardActivityDO activity : activityList) {
+ // 情况一:全部商品都可以参与
+ if (PromotionProductScopeEnum.isAll(activity.getProductScope())) {
+ resultActivityList.add(activity);
+ }
+ // 情况二:指定商品参与
+ if (PromotionProductScopeEnum.isSpu(activity.getProductScope()) &&
+ !intersectionDistinct(activity.getProductScopeValues(), spuIds).isEmpty()) {
+ resultActivityList.add(activity);
+ }
+ }
+ return resultActivityList;
+ }
+
}
diff --git a/yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/service/price/calculator/TradeRewardActivityPriceCalculator.java b/yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/service/price/calculator/TradeRewardActivityPriceCalculator.java
index 50d424c29..261eefd68 100644
--- a/yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/service/price/calculator/TradeRewardActivityPriceCalculator.java
+++ b/yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/service/price/calculator/TradeRewardActivityPriceCalculator.java
@@ -3,6 +3,7 @@ package cn.iocoder.yudao.module.trade.service.price.calculator;
import cn.hutool.core.collection.CollUtil;
import cn.hutool.core.util.ObjectUtil;
import cn.hutool.core.util.StrUtil;
+import cn.iocoder.yudao.framework.common.enums.CommonStatusEnum;
import cn.iocoder.yudao.framework.common.util.number.MoneyUtils;
import cn.iocoder.yudao.module.promotion.api.reward.RewardActivityApi;
import cn.iocoder.yudao.module.promotion.api.reward.dto.RewardActivityMatchRespDTO;
@@ -16,12 +17,12 @@ import jakarta.annotation.Resource;
import org.springframework.core.annotation.Order;
import org.springframework.stereotype.Component;
+import java.time.LocalDateTime;
import java.util.ArrayList;
import java.util.Comparator;
import java.util.List;
import java.util.Map;
-import static cn.iocoder.yudao.framework.common.util.collection.CollectionUtils.convertSet;
import static cn.iocoder.yudao.framework.common.util.collection.CollectionUtils.filterList;
import static cn.iocoder.yudao.module.trade.service.price.calculator.TradePriceCalculatorHelper.formatPrice;
@@ -46,8 +47,8 @@ public class TradeRewardActivityPriceCalculator implements TradePriceCalculator
return;
}
// 获得 SKU 对应的满减送活动
- List rewardActivities = rewardActivityApi.getMatchRewardActivityList(
- convertSet(result.getItems(), TradePriceCalculateRespBO.OrderItem::getSpuId));
+ List rewardActivities = rewardActivityApi.getRewardActivityListByStatusAndNow(
+ CommonStatusEnum.ENABLE.getStatus(), LocalDateTime.now());
if (CollUtil.isEmpty(rewardActivities)) {
return;
}
@@ -109,16 +110,8 @@ public class TradeRewardActivityPriceCalculator implements TradePriceCalculator
// 4.3 记录赠送的优惠券
if (CollUtil.isNotEmpty(rule.getGiveCouponTemplateCounts())) {
for (Map.Entry entry : rule.getGiveCouponTemplateCounts().entrySet()) {
- Map giveCouponTemplateCounts = result.getGiveCouponTemplateCounts();
- // TODO @puhui999:是不是有一种可能性,这个 key 没有,别的 key 有哈。
- // TODO 这里还有一种简化的写法。就是下面,大概两行就可以啦
-// result.getGiveCouponTemplateCounts().put(entry.getKey(),
-// result.getGiveCouponTemplateCounts().getOrDefault(entry.getKey(), 0) + entry.getValue());
- if (giveCouponTemplateCounts.get(entry.getKey()) == null) { // 情况一:还没有赠送的优惠券
- result.setGiveCouponTemplateCounts(rule.getGiveCouponTemplateCounts());
- } else { // 情况二:别的满减活动送过同类优惠券,则直接增加数量
- giveCouponTemplateCounts.put(entry.getKey(), giveCouponTemplateCounts.get(entry.getKey()) + entry.getValue());
- }
+ result.getGiveCouponTemplateCounts().put(entry.getKey(),
+ result.getGiveCouponTemplateCounts().getOrDefault(entry.getKey(), 0) + entry.getValue());
}
}
}
@@ -126,7 +119,7 @@ public class TradeRewardActivityPriceCalculator implements TradePriceCalculator
/**
* 获得满减送的订单项(商品)列表
*
- * @param result 计算结果
+ * @param result 计算结果
* @param rewardActivity 满减送活动
* @return 订单项(商品)列表
*/
@@ -153,7 +146,7 @@ public class TradeRewardActivityPriceCalculator implements TradePriceCalculator
* 获得最大匹配的满减送活动的规则
*
* @param rewardActivity 满减送活动
- * @param orderItems 商品项
+ * @param orderItems 商品项
* @return 匹配的活动规则
*/
private RewardActivityMatchRespDTO.Rule getMaxMatchRewardActivityRule(RewardActivityMatchRespDTO rewardActivity,
diff --git a/yudao-module-mall/yudao-module-trade-biz/src/test/java/cn/iocoder/yudao/module/trade/service/price/calculator/TradeRewardActivityPriceCalculatorTest.java b/yudao-module-mall/yudao-module-trade-biz/src/test/java/cn/iocoder/yudao/module/trade/service/price/calculator/TradeRewardActivityPriceCalculatorTest.java
index ba93fc10e..073e58d4e 100644
--- a/yudao-module-mall/yudao-module-trade-biz/src/test/java/cn/iocoder/yudao/module/trade/service/price/calculator/TradeRewardActivityPriceCalculatorTest.java
+++ b/yudao-module-mall/yudao-module-trade-biz/src/test/java/cn/iocoder/yudao/module/trade/service/price/calculator/TradeRewardActivityPriceCalculatorTest.java
@@ -1,5 +1,6 @@
package cn.iocoder.yudao.module.trade.service.price.calculator;
+import cn.iocoder.yudao.framework.common.enums.CommonStatusEnum;
import cn.iocoder.yudao.framework.test.core.ut.BaseMockitoUnitTest;
import cn.iocoder.yudao.module.promotion.api.reward.RewardActivityApi;
import cn.iocoder.yudao.module.promotion.api.reward.dto.RewardActivityMatchRespDTO;
@@ -13,15 +14,14 @@ import org.junit.jupiter.api.Test;
import org.mockito.InjectMocks;
import org.mockito.Mock;
+import java.time.LocalDateTime;
import java.util.ArrayList;
import java.util.LinkedHashMap;
-import static cn.iocoder.yudao.framework.common.util.collection.SetUtils.asSet;
import static cn.iocoder.yudao.framework.test.core.util.RandomUtils.randomPojo;
import static java.util.Arrays.asList;
import static java.util.Collections.singletonList;
import static org.junit.jupiter.api.Assertions.*;
-import static org.mockito.ArgumentMatchers.eq;
import static org.mockito.Mockito.when;
/**
@@ -63,22 +63,23 @@ public class TradeRewardActivityPriceCalculatorTest extends BaseMockitoUnitTest
TradePriceCalculatorHelper.recountAllPrice(result);
// mock 方法(满减送 RewardActivity 信息)
- when(rewardActivityApi.getMatchRewardActivityList(eq(asSet(1L, 2L, 3L)))).thenReturn(asList(
- randomPojo(RewardActivityMatchRespDTO.class, o -> o.setId(1000L).setName("活动 1000 号")
- .setConditionType(PromotionConditionTypeEnum.PRICE.getType())
- .setProductScope(PromotionProductScopeEnum.SPU.getScope()).setProductScopeValues(asList(1L, 2L))
- .setRules(singletonList(new RewardActivityMatchRespDTO.Rule().setLimit(20).setDiscountPrice(70)
- .setFreeDelivery(false)))),
- randomPojo(RewardActivityMatchRespDTO.class, o -> o.setId(2000L).setName("活动 2000 号")
- .setConditionType(PromotionConditionTypeEnum.COUNT.getType())
- .setProductScope(PromotionProductScopeEnum.SPU.getScope()).setProductScopeValues(singletonList(3L))
- .setRules(asList(new RewardActivityMatchRespDTO.Rule().setLimit(1).setDiscountPrice(10)
- .setPoint(50).setFreeDelivery(false),
- new RewardActivityMatchRespDTO.Rule().setLimit(2).setDiscountPrice(60)
- .setPoint(100).setFreeDelivery(false), // 最大可满足,因为是 4 个
- new RewardActivityMatchRespDTO.Rule().setLimit(10).setDiscountPrice(100)
- .setFreeDelivery(false))))
- ));
+ when(rewardActivityApi.getRewardActivityListByStatusAndNow(CommonStatusEnum.ENABLE.getStatus(), LocalDateTime.now()))
+ .thenReturn(asList(
+ randomPojo(RewardActivityMatchRespDTO.class, o -> o.setId(1000L).setName("活动 1000 号")
+ .setConditionType(PromotionConditionTypeEnum.PRICE.getType())
+ .setProductScope(PromotionProductScopeEnum.SPU.getScope()).setProductScopeValues(asList(1L, 2L))
+ .setRules(singletonList(new RewardActivityMatchRespDTO.Rule().setLimit(20).setDiscountPrice(70)
+ .setFreeDelivery(false)))),
+ randomPojo(RewardActivityMatchRespDTO.class, o -> o.setId(2000L).setName("活动 2000 号")
+ .setConditionType(PromotionConditionTypeEnum.COUNT.getType())
+ .setProductScope(PromotionProductScopeEnum.SPU.getScope()).setProductScopeValues(singletonList(3L))
+ .setRules(asList(new RewardActivityMatchRespDTO.Rule().setLimit(1).setDiscountPrice(10)
+ .setPoint(50).setFreeDelivery(false),
+ new RewardActivityMatchRespDTO.Rule().setLimit(2).setDiscountPrice(60)
+ .setPoint(100).setFreeDelivery(false), // 最大可满足,因为是 4 个
+ new RewardActivityMatchRespDTO.Rule().setLimit(10).setDiscountPrice(100)
+ .setFreeDelivery(false))))
+ ));
// 调用
tradeRewardActivityPriceCalculator.calculate(param, result);
@@ -184,11 +185,12 @@ public class TradeRewardActivityPriceCalculatorTest extends BaseMockitoUnitTest
TradePriceCalculatorHelper.recountAllPrice(result);
// mock 方法(限时折扣 DiscountActivity 信息)
- when(rewardActivityApi.getMatchRewardActivityList(eq(asSet(1L, 2L)))).thenReturn(singletonList(
- randomPojo(RewardActivityMatchRespDTO.class, o -> o.setId(1000L).setName("活动 1000 号")
- .setProductScopeValues(asList(1L, 2L)).setConditionType(PromotionConditionTypeEnum.PRICE.getType())
- .setRules(singletonList(new RewardActivityMatchRespDTO.Rule().setLimit(351).setDiscountPrice(70))))
- ));
+ when(rewardActivityApi.getRewardActivityListByStatusAndNow(CommonStatusEnum.ENABLE.getStatus(), LocalDateTime.now()))
+ .thenReturn(singletonList(
+ randomPojo(RewardActivityMatchRespDTO.class, o -> o.setId(1000L).setName("活动 1000 号")
+ .setProductScopeValues(asList(1L, 2L)).setConditionType(PromotionConditionTypeEnum.PRICE.getType())
+ .setRules(singletonList(new RewardActivityMatchRespDTO.Rule().setLimit(351).setDiscountPrice(70))))
+ ));
// 调用
tradeRewardActivityPriceCalculator.calculate(param, result);
From 258250e3c4a9c9378835493d13e84f9c2a1ab316 Mon Sep 17 00:00:00 2001
From: scholar <1145227973@qq.com>
Date: Tue, 10 Sep 2024 11:53:28 +0800
Subject: [PATCH 018/156] =?UTF-8?q?=E5=A2=9E=E5=8A=A0=E7=94=A8=E6=88=B7?=
=?UTF-8?q?=E6=B3=A8=E5=86=8C=E5=8A=9F=E8=83=BD?=
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
---
.../controller/admin/auth/AuthController.java | 5 +-
.../admin/auth/vo/AuthRegisterReqVO.java | 46 ++-----------
.../system/service/auth/AdminAuthService.java | 4 +-
.../service/auth/AdminAuthServiceImpl.java | 68 +++----------------
4 files changed, 18 insertions(+), 105 deletions(-)
diff --git a/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/controller/admin/auth/AuthController.java b/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/controller/admin/auth/AuthController.java
index 99d6a8899..764081121 100644
--- a/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/controller/admin/auth/AuthController.java
+++ b/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/controller/admin/auth/AuthController.java
@@ -164,8 +164,7 @@ public class AuthController {
@PostMapping("/register")
@PermitAll
@Operation(summary = "注册用户")
- @OperateLog(enable = false) // 避免 Post 请求被记录操作日志
- public CommonResult register(@RequestBody @Valid AuthRegisterReqVO reqVO) {
- return success(authService.register(reqVO));
+ public CommonResult register(@RequestBody @Valid AuthRegisterReqVO registerReqVO) {
+ return success(authService.register(registerReqVO));
}
}
diff --git a/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/controller/admin/auth/vo/AuthRegisterReqVO.java b/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/controller/admin/auth/vo/AuthRegisterReqVO.java
index 712f034f7..f98d353d1 100644
--- a/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/controller/admin/auth/vo/AuthRegisterReqVO.java
+++ b/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/controller/admin/auth/vo/AuthRegisterReqVO.java
@@ -1,22 +1,16 @@
package cn.iocoder.yudao.module.system.controller.admin.auth.vo;
-import cn.hutool.core.util.ObjectUtil;
-import cn.iocoder.yudao.framework.common.validation.Mobile;
-import com.fasterxml.jackson.annotation.JsonIgnore;
+
import io.swagger.v3.oas.annotations.media.Schema;
import lombok.Data;
import org.hibernate.validator.constraints.Length;
import jakarta.validation.constraints.*;
-import java.util.Set;
@Schema(description = "管理后台 - Register Request VO")
@Data
public class AuthRegisterReqVO {
- @Schema(description = "用户编号", example = "1024")
- private Long id;
-
@Schema(description = "用户账号", requiredMode = Schema.RequiredMode.REQUIRED, example = "yudao")
@NotBlank(message = "用户账号不能为空")
@Pattern(regexp = "^[a-zA-Z0-9]{4,30}$", message = "用户账号由 数字、字母 组成")
@@ -27,41 +21,13 @@ public class AuthRegisterReqVO {
@Size(max = 30, message = "用户昵称长度不能超过30个字符")
private String nickname;
- @Schema(description = "备注", example = "我是一个用户")
- private String remark;
-
- @Schema(description = "部门ID", example = "我是一个用户")
- private Long deptId;
-
- @Schema(description = "岗位编号数组", example = "1")
- private Set postIds;
-
- @Schema(description = "用户邮箱", example = "yudao@iocoder.cn")
- @Email(message = "邮箱格式不正确")
- @Size(max = 50, message = "邮箱长度不能超过 50 个字符")
- private String email;
-
- @Schema(description = "手机号码", example = "15601691300")
- @Mobile
- private String mobile;
-
- @Schema(description = "用户性别,参见 SexEnum 枚举类", example = "1")
- private Integer sex;
-
- @Schema(description = "用户头像", example = "https://www.iocoder.cn/xxx.png")
- private String avatar;
-
- // ========== 仅【创建】时,需要传递的字段 ==========
-
@Schema(description = "密码", requiredMode = Schema.RequiredMode.REQUIRED, example = "123456")
@Length(min = 4, max = 16, message = "密码长度为 4-16 位")
private String password;
- @AssertTrue(message = "密码不能为空")
- @JsonIgnore
- public boolean isPasswordValid() {
- return id != null // 修改时,不需要传递
- || (ObjectUtil.isAllNotEmpty(password)); // 新增时,必须都传递 password
- }
-
+ // ========== 图片验证码相关 ==========
+ @Schema(description = "验证码,验证码开启时,需要传递", requiredMode = Schema.RequiredMode.REQUIRED,
+ example = "PfcH6mgr8tpXuMWFjvW6YVaqrswIuwmWI5dsVZSg7sGpWtDCUbHuDEXl3cFB1+VvCC/rAkSwK8Fad52FSuncVg==")
+ @NotEmpty(message = "验证码不能为空", groups = AuthLoginReqVO.CodeEnableGroup.class)
+ private String captchaVerification;
}
\ No newline at end of file
diff --git a/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/service/auth/AdminAuthService.java b/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/service/auth/AdminAuthService.java
index 0ff0df56e..a960c8ff8 100644
--- a/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/service/auth/AdminAuthService.java
+++ b/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/service/auth/AdminAuthService.java
@@ -70,13 +70,11 @@ public interface AdminAuthService {
*/
AuthLoginRespVO refreshToken(String refreshToken);
-
/**
* 用户注册
*
* @param createReqVO 注册用户
* @return 注册结果
*/
- Long register(AuthRegisterReqVO createReqVO);
-
+ AuthLoginRespVO register(AuthRegisterReqVO createReqVO);
}
diff --git a/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/service/auth/AdminAuthServiceImpl.java b/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/service/auth/AdminAuthServiceImpl.java
index f739b8d0b..77471dd89 100644
--- a/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/service/auth/AdminAuthServiceImpl.java
+++ b/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/service/auth/AdminAuthServiceImpl.java
@@ -1,25 +1,20 @@
package cn.iocoder.yudao.module.system.service.auth;
-import cn.hutool.core.collection.CollectionUtil;
import cn.hutool.core.util.ObjectUtil;
-import cn.hutool.core.util.StrUtil;
import cn.iocoder.yudao.framework.common.enums.CommonStatusEnum;
import cn.iocoder.yudao.framework.common.enums.UserTypeEnum;
import cn.iocoder.yudao.framework.common.util.monitor.TracerUtils;
import cn.iocoder.yudao.framework.common.util.object.BeanUtils;
import cn.iocoder.yudao.framework.common.util.servlet.ServletUtils;
import cn.iocoder.yudao.framework.common.util.validation.ValidationUtils;
-import cn.iocoder.yudao.framework.datapermission.core.util.DataPermissionUtils;
import cn.iocoder.yudao.module.system.api.logger.dto.LoginLogCreateReqDTO;
import cn.iocoder.yudao.module.system.api.sms.SmsCodeApi;
import cn.iocoder.yudao.module.system.api.social.dto.SocialUserBindReqDTO;
import cn.iocoder.yudao.module.system.api.social.dto.SocialUserRespDTO;
import cn.iocoder.yudao.module.system.controller.admin.auth.vo.*;
import cn.iocoder.yudao.module.system.convert.auth.AuthConvert;
-import cn.iocoder.yudao.module.system.dal.dataobject.dept.UserPostDO;
import cn.iocoder.yudao.module.system.dal.dataobject.oauth2.OAuth2AccessTokenDO;
import cn.iocoder.yudao.module.system.dal.dataobject.user.AdminUserDO;
-import cn.iocoder.yudao.module.system.dal.mysql.dept.UserPostMapper;
import cn.iocoder.yudao.module.system.dal.mysql.user.AdminUserMapper;
import cn.iocoder.yudao.module.system.enums.logger.LoginLogTypeEnum;
import cn.iocoder.yudao.module.system.enums.logger.LoginResultEnum;
@@ -44,10 +39,8 @@ import org.springframework.stereotype.Service;
import jakarta.annotation.Resource;
import jakarta.validation.Validator;
import java.util.Objects;
-import java.util.Set;
import static cn.iocoder.yudao.framework.common.exception.util.ServiceExceptionUtil.exception;
-import static cn.iocoder.yudao.framework.common.util.collection.CollectionUtils.convertList;
import static cn.iocoder.yudao.framework.common.util.servlet.ServletUtils.getClientIP;
import static cn.iocoder.yudao.module.system.enums.ErrorCodeConstants.*;
@@ -88,9 +81,6 @@ public class AdminAuthServiceImpl implements AdminAuthService {
*/
@Value("${yudao.captcha.enable:true}")
private Boolean captchaEnable;
- @Resource
- private UserPostMapper userPostMapper;
-
@Override
public AdminUserDO authenticate(String username, String password) {
@@ -269,7 +259,10 @@ public class AdminAuthServiceImpl implements AdminAuthService {
}
- public Long register(AuthRegisterReqVO registerReqVO) {
+ public AuthLoginRespVO register(AuthRegisterReqVO registerReqVO) {
+ // 校验验证码
+ AuthLoginReqVO loginReqVO = BeanUtils.toBean(registerReqVO, AuthLoginReqVO.class);
+ validateCaptcha(loginReqVO);
// 校验账户配合
tenantService.handleTenantInfo(tenant -> {
long count = userMapper.selectCount();
@@ -277,60 +270,17 @@ public class AdminAuthServiceImpl implements AdminAuthService {
throw exception(USER_COUNT_MAX, tenant.getAccountCount());
}
});
- // 校验正确性
- validateUserForRegister(null, registerReqVO.getUsername(),
- registerReqVO.getMobile(), registerReqVO.getEmail(), registerReqVO.getDeptId(), registerReqVO.getPostIds());
+ // 校验用户名是否已存在
+ if (userMapper.selectByUsername(registerReqVO.getUsername()) != null) {
+ throw exception(USER_USERNAME_EXISTS);
+ }
// 插入用户
AdminUserDO user = BeanUtils.toBean(registerReqVO, AdminUserDO.class);
user.setStatus(CommonStatusEnum.ENABLE.getStatus()); // 默认开启
user.setPassword(encodePassword(registerReqVO.getPassword())); // 加密密码
userMapper.insert(user);
- // 插入关联岗位
- if (CollectionUtil.isNotEmpty(user.getPostIds())) {
- userPostMapper.insertBatch(convertList(user.getPostIds(),
- postId -> new UserPostDO().setUserId(user.getId()).setPostId(postId)));
- }
- return user.getId();
- }
- private void validateUserForRegister(Long id, String username, String mobile, String email,
- Long deptId, Set postIds) {
- // 关闭数据权限,避免因为没有数据权限,查询不到数据,进而导致唯一校验不正确
- DataPermissionUtils.executeIgnore(() -> {
- // 校验用户存在
- validateUserExists(id);
- // 校验用户名唯一
- validateUsernameUnique(id, username);
- });
- }
-
- @VisibleForTesting
- void validateUserExists(Long id) {
- if (id == null) {
- return;
- }
- AdminUserDO user = userMapper.selectById(id);
- if (user == null) {
- throw exception(USER_NOT_EXISTS);
- }
- }
-
- @VisibleForTesting
- void validateUsernameUnique(Long id, String username) {
- if (StrUtil.isBlank(username)) {
- return;
- }
- AdminUserDO user = userMapper.selectByUsername(username);
- if (user == null) {
- return;
- }
- // 如果 id 为空,说明不用比较是否为相同 id 的用户
- if (id == null) {
- throw exception(USER_USERNAME_EXISTS);
- }
- if (!user.getId().equals(id)) {
- throw exception(USER_USERNAME_EXISTS);
- }
+ return createTokenAfterLoginSuccess(user.getId(), registerReqVO.getUsername(), LoginLogTypeEnum.LOGIN_USERNAME);
}
/**
From 1352613ebe86f7a5971954735e01e7b7ec4e9eda Mon Sep 17 00:00:00 2001
From: puhui999
Date: Tue, 10 Sep 2024 12:24:53 +0800
Subject: [PATCH 019/156] =?UTF-8?q?=E3=80=90=E4=BB=A3=E7=A0=81=E4=BC=98?=
=?UTF-8?q?=E5=8C=96=E3=80=91=E5=95=86=E5=9F=8E:=20=E6=BB=A1=E5=87=8F?=
=?UTF-8?q?=E9=80=81=E6=B4=BB=E5=8A=A8?=
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
---
.../promotion/enums/ErrorCodeConstants.java | 7 ++--
.../reward/RewardActivityServiceImpl.java | 39 +++++++++----------
2 files changed, 22 insertions(+), 24 deletions(-)
diff --git a/yudao-module-mall/yudao-module-promotion-api/src/main/java/cn/iocoder/yudao/module/promotion/enums/ErrorCodeConstants.java b/yudao-module-mall/yudao-module-promotion-api/src/main/java/cn/iocoder/yudao/module/promotion/enums/ErrorCodeConstants.java
index 116e2fe42..841b4057e 100644
--- a/yudao-module-mall/yudao-module-promotion-api/src/main/java/cn/iocoder/yudao/module/promotion/enums/ErrorCodeConstants.java
+++ b/yudao-module-mall/yudao-module-promotion-api/src/main/java/cn/iocoder/yudao/module/promotion/enums/ErrorCodeConstants.java
@@ -40,13 +40,12 @@ public interface ErrorCodeConstants {
// ========== 满减送活动 1-013-006-000 ==========
ErrorCode REWARD_ACTIVITY_NOT_EXISTS = new ErrorCode(1_013_006_000, "满减送活动不存在");
- ErrorCode REWARD_ACTIVITY_SPU_CONFLICTS = new ErrorCode(1_013_006_001, "存在商品参加了其它满减送活动");
+ ErrorCode REWARD_ACTIVITY_SPU_CONFLICTS = new ErrorCode(1_013_006_001, "该时间段存在商品参加了其它满减送活动");
ErrorCode REWARD_ACTIVITY_UPDATE_FAIL_STATUS_CLOSED = new ErrorCode(1_013_006_002, "满减送活动已关闭,不能修改");
ErrorCode REWARD_ACTIVITY_DELETE_FAIL_STATUS_NOT_CLOSED = new ErrorCode(1_013_006_003, "满减送活动未关闭,不能删除");
ErrorCode REWARD_ACTIVITY_CLOSE_FAIL_STATUS_CLOSED = new ErrorCode(1_013_006_004, "满减送活动已关闭,不能重复关闭");
- ErrorCode REWARD_ACTIVITY_SCOPE_ALL_EXISTS = new ErrorCode(1_013_006_005, "已存在商品范围为全场的满减送活动");
- ErrorCode REWARD_ACTIVITY_SCOPE_CATEGORY_EXISTS = new ErrorCode(1_013_006_006, "存在商品类型参加了其它满减送活动");
- ErrorCode REWARD_ACTIVITY_TIME_CONFLICTS = new ErrorCode(1_013_006_007, "满减送活动时段冲突");
+ ErrorCode REWARD_ACTIVITY_SCOPE_ALL_EXISTS = new ErrorCode(1_013_006_005, "该时间段已存在商品范围为全场的满减送活动");
+ ErrorCode REWARD_ACTIVITY_SCOPE_CATEGORY_EXISTS = new ErrorCode(1_013_006_006, "该时间段存在商品类型参加了其它满减送活动");
// ========== TODO 空着 1-013-007-000 ============
diff --git a/yudao-module-mall/yudao-module-promotion-biz/src/main/java/cn/iocoder/yudao/module/promotion/service/reward/RewardActivityServiceImpl.java b/yudao-module-mall/yudao-module-promotion-biz/src/main/java/cn/iocoder/yudao/module/promotion/service/reward/RewardActivityServiceImpl.java
index f12c0f284..f8299edea 100755
--- a/yudao-module-mall/yudao-module-promotion-biz/src/main/java/cn/iocoder/yudao/module/promotion/service/reward/RewardActivityServiceImpl.java
+++ b/yudao-module-mall/yudao-module-promotion-biz/src/main/java/cn/iocoder/yudao/module/promotion/service/reward/RewardActivityServiceImpl.java
@@ -24,7 +24,6 @@ import java.util.Objects;
import static cn.hutool.core.collection.CollUtil.intersectionDistinct;
import static cn.iocoder.yudao.framework.common.exception.util.ServiceExceptionUtil.exception;
-import static cn.iocoder.yudao.framework.common.util.collection.CollectionUtils.anyMatch;
import static cn.iocoder.yudao.module.promotion.enums.ErrorCodeConstants.*;
/**
@@ -116,29 +115,29 @@ public class RewardActivityServiceImpl implements RewardActivityService {
* @param rewardActivity 请求
*/
private void validateRewardActivitySpuConflicts(Long id, RewardActivityBaseVO rewardActivity) {
- // 0. 获得所有的活动包括关闭的
- List list = rewardActivityMapper.selectList();
+ // 0. 获得开启的所有的活动
+ List list = rewardActivityMapper.selectList(RewardActivityDO::getStatus, CommonStatusEnum.ENABLE.getStatus());
if (id != null) { // 排除自己这个活动
list.removeIf(activity -> id.equals(activity.getId()));
}
- // 1.1 校验满减送活动时间是否冲突
- boolean hasConflict = list.stream().anyMatch(item -> LocalDateTimeUtil.isOverlap(item.getStartTime(), item.getEndTime(),
- rewardActivity.getStartTime(), rewardActivity.getEndTime()));
- if (hasConflict) {
- throw exception(REWARD_ACTIVITY_TIME_CONFLICTS);
- }
- // 1.2 校验商品范围是否重叠
- if (PromotionProductScopeEnum.isAll(rewardActivity.getProductScope()) && // 情况一:全部商品参加
- anyMatch(list, item -> PromotionProductScopeEnum.isAll(item.getProductScope()))) {
- throw exception(REWARD_ACTIVITY_SCOPE_ALL_EXISTS);
- }
- if (PromotionProductScopeEnum.isSpu(rewardActivity.getProductScope()) || // 情况二:指定商品参加
- PromotionProductScopeEnum.isCategory(rewardActivity.getProductScope())) { // 情况三:指定商品类型参加
- if (anyMatch(list, item -> !intersectionDistinct(item.getProductScopeValues(),
- rewardActivity.getProductScopeValues()).isEmpty())) {
- throw exception(PromotionProductScopeEnum.isSpu(rewardActivity.getProductScope()) ?
- REWARD_ACTIVITY_SPU_CONFLICTS : REWARD_ACTIVITY_SCOPE_CATEGORY_EXISTS);
+ for (RewardActivityDO item : list) {
+ // 1.1 校验满减送活动时间是否冲突,如果时段不冲突那么不同的时间段内则可以存在相同的商品范围
+ if (!LocalDateTimeUtil.isOverlap(item.getStartTime(), item.getEndTime(),
+ rewardActivity.getStartTime(), rewardActivity.getEndTime())) {
+ continue;
+ }
+ // 1.2 校验商品范围是否重叠
+ if (PromotionProductScopeEnum.isAll(rewardActivity.getProductScope()) &&
+ PromotionProductScopeEnum.isAll(item.getProductScope())) { // 情况一:全部商品参加
+ throw exception(REWARD_ACTIVITY_SCOPE_ALL_EXISTS);
+ }
+ if (PromotionProductScopeEnum.isSpu(rewardActivity.getProductScope()) || // 情况二:指定商品参加
+ PromotionProductScopeEnum.isCategory(rewardActivity.getProductScope())) { // 情况三:指定商品类型参加
+ if (!intersectionDistinct(item.getProductScopeValues(), rewardActivity.getProductScopeValues()).isEmpty()) {
+ throw exception(PromotionProductScopeEnum.isSpu(rewardActivity.getProductScope()) ?
+ REWARD_ACTIVITY_SPU_CONFLICTS : REWARD_ACTIVITY_SCOPE_CATEGORY_EXISTS);
+ }
}
}
}
From 9c5c40fe909036ebb54979705f92644d9c0d3adf Mon Sep 17 00:00:00 2001
From: YunaiV
Date: Tue, 10 Sep 2024 12:46:49 +0800
Subject: [PATCH 020/156] =?UTF-8?q?=E3=80=90=E4=BB=A3=E7=A0=81=E8=AF=84?=
=?UTF-8?q?=E5=AE=A1=E3=80=91=E5=95=86=E5=9F=8E=EF=BC=9A=E6=BB=A1=E5=87=8F?=
=?UTF-8?q?=E9=80=81=E7=9A=84=E6=A0=A1=E9=AA=8C=E9=80=BB=E8=BE=91?=
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
---
.../yudao/module/promotion/api/reward/RewardActivityApi.java | 2 +-
.../promotion/dal/mysql/reward/RewardActivityMapper.java | 4 ++--
.../promotion/service/reward/RewardActivityServiceImpl.java | 2 ++
3 files changed, 5 insertions(+), 3 deletions(-)
diff --git a/yudao-module-mall/yudao-module-promotion-api/src/main/java/cn/iocoder/yudao/module/promotion/api/reward/RewardActivityApi.java b/yudao-module-mall/yudao-module-promotion-api/src/main/java/cn/iocoder/yudao/module/promotion/api/reward/RewardActivityApi.java
index 2a941e051..68f76a1fa 100644
--- a/yudao-module-mall/yudao-module-promotion-api/src/main/java/cn/iocoder/yudao/module/promotion/api/reward/RewardActivityApi.java
+++ b/yudao-module-mall/yudao-module-promotion-api/src/main/java/cn/iocoder/yudao/module/promotion/api/reward/RewardActivityApi.java
@@ -16,7 +16,7 @@ public interface RewardActivityApi {
* 获得当前时间内开启的满减送活动
*
* @param status 状态
- * @param dateTime 时间
+ * @param dateTime 当前时间,即筛选 <= dateTime 的满减送活动
* @return 满减送活动列表
*/
List getRewardActivityListByStatusAndNow(Integer status, LocalDateTime dateTime);
diff --git a/yudao-module-mall/yudao-module-promotion-biz/src/main/java/cn/iocoder/yudao/module/promotion/dal/mysql/reward/RewardActivityMapper.java b/yudao-module-mall/yudao-module-promotion-biz/src/main/java/cn/iocoder/yudao/module/promotion/dal/mysql/reward/RewardActivityMapper.java
index f8b8d5ccb..6f377fb60 100755
--- a/yudao-module-mall/yudao-module-promotion-biz/src/main/java/cn/iocoder/yudao/module/promotion/dal/mysql/reward/RewardActivityMapper.java
+++ b/yudao-module-mall/yudao-module-promotion-biz/src/main/java/cn/iocoder/yudao/module/promotion/dal/mysql/reward/RewardActivityMapper.java
@@ -28,8 +28,8 @@ public interface RewardActivityMapper extends BaseMapperX {
default List selectListByStatusAndDateTimeLt(Integer status, LocalDateTime dateTime) {
return selectList(new LambdaQueryWrapperX()
.eq(RewardActivityDO::getStatus, status)
- .lt(RewardActivityDO::getStartTime, dateTime)
- .gt(RewardActivityDO::getEndTime, dateTime)// 开始时间 < 指定时间 < 结束时间,也就是说获取指定时间段的活动
+ // 开始时间 < 指定时间(dateTime) < 结束时间,也就是说获取指定时间段的活动
+ .lt(RewardActivityDO::getStartTime, dateTime).gt(RewardActivityDO::getEndTime, dateTime)
.orderByAsc(RewardActivityDO::getStartTime)
);
}
diff --git a/yudao-module-mall/yudao-module-promotion-biz/src/main/java/cn/iocoder/yudao/module/promotion/service/reward/RewardActivityServiceImpl.java b/yudao-module-mall/yudao-module-promotion-biz/src/main/java/cn/iocoder/yudao/module/promotion/service/reward/RewardActivityServiceImpl.java
index f8299edea..fcd650c28 100755
--- a/yudao-module-mall/yudao-module-promotion-biz/src/main/java/cn/iocoder/yudao/module/promotion/service/reward/RewardActivityServiceImpl.java
+++ b/yudao-module-mall/yudao-module-promotion-biz/src/main/java/cn/iocoder/yudao/module/promotion/service/reward/RewardActivityServiceImpl.java
@@ -121,6 +121,8 @@ public class RewardActivityServiceImpl implements RewardActivityService {
list.removeIf(activity -> id.equals(activity.getId()));
}
+ // TODO @puhui999:这个可能要完整对标有赞的校验。完全不允许重叠。
+ // 例如说,rewardActivity 是全部活动,结果有个 db 里的 activity 是某个分类,它也是冲突的。也就是说,当前时间段内,有且仅有只能有一个活动!
for (RewardActivityDO item : list) {
// 1.1 校验满减送活动时间是否冲突,如果时段不冲突那么不同的时间段内则可以存在相同的商品范围
if (!LocalDateTimeUtil.isOverlap(item.getStartTime(), item.getEndTime(),
From 51797e0dede7441af34a3e3acd6af79e1298cc92 Mon Sep 17 00:00:00 2001
From: puhui999
Date: Tue, 10 Sep 2024 15:13:38 +0800
Subject: [PATCH 021/156] =?UTF-8?q?=E3=80=90=E4=BB=A3=E7=A0=81=E4=BC=98?=
=?UTF-8?q?=E5=8C=96=E3=80=91=E5=95=86=E5=9F=8E:=20=E6=BB=A1=E5=87=8F?=
=?UTF-8?q?=E9=80=81=E6=B4=BB=E5=8A=A8=E6=A0=A1=E9=AA=8C=E8=A7=84=E5=88=99?=
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
---
.../promotion/enums/ErrorCodeConstants.java | 3 +-
.../reward/RewardActivityServiceImpl.java | 50 +++++++++++++++----
2 files changed, 41 insertions(+), 12 deletions(-)
diff --git a/yudao-module-mall/yudao-module-promotion-api/src/main/java/cn/iocoder/yudao/module/promotion/enums/ErrorCodeConstants.java b/yudao-module-mall/yudao-module-promotion-api/src/main/java/cn/iocoder/yudao/module/promotion/enums/ErrorCodeConstants.java
index 841b4057e..5187e2edd 100644
--- a/yudao-module-mall/yudao-module-promotion-api/src/main/java/cn/iocoder/yudao/module/promotion/enums/ErrorCodeConstants.java
+++ b/yudao-module-mall/yudao-module-promotion-api/src/main/java/cn/iocoder/yudao/module/promotion/enums/ErrorCodeConstants.java
@@ -44,8 +44,7 @@ public interface ErrorCodeConstants {
ErrorCode REWARD_ACTIVITY_UPDATE_FAIL_STATUS_CLOSED = new ErrorCode(1_013_006_002, "满减送活动已关闭,不能修改");
ErrorCode REWARD_ACTIVITY_DELETE_FAIL_STATUS_NOT_CLOSED = new ErrorCode(1_013_006_003, "满减送活动未关闭,不能删除");
ErrorCode REWARD_ACTIVITY_CLOSE_FAIL_STATUS_CLOSED = new ErrorCode(1_013_006_004, "满减送活动已关闭,不能重复关闭");
- ErrorCode REWARD_ACTIVITY_SCOPE_ALL_EXISTS = new ErrorCode(1_013_006_005, "该时间段已存在商品范围为全场的满减送活动");
- ErrorCode REWARD_ACTIVITY_SCOPE_CATEGORY_EXISTS = new ErrorCode(1_013_006_006, "该时间段存在商品类型参加了其它满减送活动");
+ ErrorCode REWARD_ACTIVITY_SCOPE_EXISTS = new ErrorCode(1_013_006_005, "与该时间段已存在的满减送活动商品范围冲突。注意商品范围 全部 > 分类 > 商品");
// ========== TODO 空着 1-013-007-000 ============
diff --git a/yudao-module-mall/yudao-module-promotion-biz/src/main/java/cn/iocoder/yudao/module/promotion/service/reward/RewardActivityServiceImpl.java b/yudao-module-mall/yudao-module-promotion-biz/src/main/java/cn/iocoder/yudao/module/promotion/service/reward/RewardActivityServiceImpl.java
index fcd650c28..fe2f0e621 100755
--- a/yudao-module-mall/yudao-module-promotion-biz/src/main/java/cn/iocoder/yudao/module/promotion/service/reward/RewardActivityServiceImpl.java
+++ b/yudao-module-mall/yudao-module-promotion-biz/src/main/java/cn/iocoder/yudao/module/promotion/service/reward/RewardActivityServiceImpl.java
@@ -6,6 +6,7 @@ import cn.iocoder.yudao.framework.common.pojo.PageResult;
import cn.iocoder.yudao.framework.common.util.object.BeanUtils;
import cn.iocoder.yudao.module.product.api.category.ProductCategoryApi;
import cn.iocoder.yudao.module.product.api.spu.ProductSpuApi;
+import cn.iocoder.yudao.module.product.api.spu.dto.ProductSpuRespDTO;
import cn.iocoder.yudao.module.promotion.controller.admin.reward.vo.RewardActivityBaseVO;
import cn.iocoder.yudao.module.promotion.controller.admin.reward.vo.RewardActivityCreateReqVO;
import cn.iocoder.yudao.module.promotion.controller.admin.reward.vo.RewardActivityPageReqVO;
@@ -24,6 +25,7 @@ import java.util.Objects;
import static cn.hutool.core.collection.CollUtil.intersectionDistinct;
import static cn.iocoder.yudao.framework.common.exception.util.ServiceExceptionUtil.exception;
+import static cn.iocoder.yudao.framework.common.util.collection.CollectionUtils.convertSet;
import static cn.iocoder.yudao.module.promotion.enums.ErrorCodeConstants.*;
/**
@@ -121,8 +123,7 @@ public class RewardActivityServiceImpl implements RewardActivityService {
list.removeIf(activity -> id.equals(activity.getId()));
}
- // TODO @puhui999:这个可能要完整对标有赞的校验。完全不允许重叠。
- // 例如说,rewardActivity 是全部活动,结果有个 db 里的 activity 是某个分类,它也是冲突的。也就是说,当前时间段内,有且仅有只能有一个活动!
+ // 完全不允许重叠。
for (RewardActivityDO item : list) {
// 1.1 校验满减送活动时间是否冲突,如果时段不冲突那么不同的时间段内则可以存在相同的商品范围
if (!LocalDateTimeUtil.isOverlap(item.getStartTime(), item.getEndTime(),
@@ -130,15 +131,44 @@ public class RewardActivityServiceImpl implements RewardActivityService {
continue;
}
// 1.2 校验商品范围是否重叠
- if (PromotionProductScopeEnum.isAll(rewardActivity.getProductScope()) &&
- PromotionProductScopeEnum.isAll(item.getProductScope())) { // 情况一:全部商品参加
- throw exception(REWARD_ACTIVITY_SCOPE_ALL_EXISTS);
+ // 情况一:如果与该时间段内商品范围为全部的活动冲突,或 rewardActivity 商品范围为全部,那么则直接校验不通过
+ // 例如说,rewardActivity 是全部活动,结果有个 db 里的 activity 是某个分类,它也是冲突的。也就是说,当前时间段内,有且仅有只能有一个活动!
+ if (PromotionProductScopeEnum.isAll(item.getProductScope()) ||
+ PromotionProductScopeEnum.isAll(rewardActivity.getProductScope())) {
+ throw exception(REWARD_ACTIVITY_SCOPE_EXISTS);
}
- if (PromotionProductScopeEnum.isSpu(rewardActivity.getProductScope()) || // 情况二:指定商品参加
- PromotionProductScopeEnum.isCategory(rewardActivity.getProductScope())) { // 情况三:指定商品类型参加
- if (!intersectionDistinct(item.getProductScopeValues(), rewardActivity.getProductScopeValues()).isEmpty()) {
- throw exception(PromotionProductScopeEnum.isSpu(rewardActivity.getProductScope()) ?
- REWARD_ACTIVITY_SPU_CONFLICTS : REWARD_ACTIVITY_SCOPE_CATEGORY_EXISTS);
+ // 情况二:如果与该时间段内商品范围为类别的活动冲突
+ if (PromotionProductScopeEnum.isCategory(item.getProductScope())) {
+ // 校验分类是否冲突
+ if (PromotionProductScopeEnum.isCategory(rewardActivity.getProductScope())) {
+ if (!intersectionDistinct(item.getProductScopeValues(), rewardActivity.getProductScopeValues()).isEmpty()) {
+ throw exception(REWARD_ACTIVITY_SCOPE_EXISTS);
+ }
+ }
+ // 校验商品分类是否冲突
+ if (PromotionProductScopeEnum.isSpu(rewardActivity.getProductScope())) {
+ List spuList = productSpuApi.getSpuList(rewardActivity.getProductScopeValues());
+ if (!intersectionDistinct(item.getProductScopeValues(),
+ convertSet(spuList, ProductSpuRespDTO::getCategoryId)).isEmpty()) {
+ throw exception(REWARD_ACTIVITY_SCOPE_EXISTS);
+ }
+ }
+ }
+ // 情况三:如果与该时间段内商品范围为商品的活动冲突
+ if (PromotionProductScopeEnum.isSpu(item.getProductScope())) {
+ // 校验商品是否冲突
+ if (PromotionProductScopeEnum.isSpu(rewardActivity.getProductScope())) {
+ if (!intersectionDistinct(item.getProductScopeValues(), rewardActivity.getProductScopeValues()).isEmpty()) {
+ throw exception(REWARD_ACTIVITY_SCOPE_EXISTS);
+ }
+ }
+ // 校验商品分类是否冲突
+ if (PromotionProductScopeEnum.isCategory(rewardActivity.getProductScope())) {
+ List spuList = productSpuApi.getSpuList(item.getProductScopeValues());
+ if (!intersectionDistinct(rewardActivity.getProductScopeValues(),
+ convertSet(spuList, ProductSpuRespDTO::getCategoryId)).isEmpty()) {
+ throw exception(REWARD_ACTIVITY_SCOPE_EXISTS);
+ }
}
}
}
From 28b10b35d5ddcd4f597d347b47a6f752bc8bf345 Mon Sep 17 00:00:00 2001
From: YunaiV
Date: Tue, 10 Sep 2024 21:05:11 +0800
Subject: [PATCH 022/156] =?UTF-8?q?=E3=80=90=E4=BB=A3=E7=A0=81=E4=BC=98?=
=?UTF-8?q?=E5=8C=96=E3=80=91=E6=B3=A8=E5=86=8C=E7=9A=84=E9=80=BB=E8=BE=91?=
=?UTF-8?q?=E5=AE=9E=E7=8E=B0?=
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
---
.../system/enums/ErrorCodeConstants.java | 1 +
.../controller/admin/auth/AuthController.java | 13 ++--
.../admin/auth/vo/AuthRegisterReqVO.java | 6 +-
.../system/service/auth/AdminAuthService.java | 1 +
.../service/auth/AdminAuthServiceImpl.java | 76 ++++++++-----------
.../system/service/user/AdminUserService.java | 23 +++++-
.../service/user/AdminUserServiceImpl.java | 21 +++++
7 files changed, 84 insertions(+), 57 deletions(-)
diff --git a/yudao-module-system/yudao-module-system-api/src/main/java/cn/iocoder/yudao/module/system/enums/ErrorCodeConstants.java b/yudao-module-system/yudao-module-system-api/src/main/java/cn/iocoder/yudao/module/system/enums/ErrorCodeConstants.java
index 5a44a9869..96052dc72 100644
--- a/yudao-module-system/yudao-module-system-api/src/main/java/cn/iocoder/yudao/module/system/enums/ErrorCodeConstants.java
+++ b/yudao-module-system/yudao-module-system-api/src/main/java/cn/iocoder/yudao/module/system/enums/ErrorCodeConstants.java
@@ -15,6 +15,7 @@ public interface ErrorCodeConstants {
ErrorCode AUTH_LOGIN_CAPTCHA_CODE_ERROR = new ErrorCode(1_002_000_004, "验证码不正确,原因:{}");
ErrorCode AUTH_THIRD_LOGIN_NOT_BIND = new ErrorCode(1_002_000_005, "未绑定账号,需要进行绑定");
ErrorCode AUTH_MOBILE_NOT_EXISTS = new ErrorCode(1_002_000_007, "手机号不存在");
+ ErrorCode AUTH_REGISTER_CAPTCHA_CODE_ERROR = new ErrorCode(1_002_000_008, "验证码不正确,原因:{}");
// ========== 菜单模块 1-002-001-000 ==========
ErrorCode MENU_NAME_DUPLICATE = new ErrorCode(1_002_001_000, "已经存在该名字的菜单");
diff --git a/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/controller/admin/auth/AuthController.java b/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/controller/admin/auth/AuthController.java
index 2b53c2667..281b766c0 100644
--- a/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/controller/admin/auth/AuthController.java
+++ b/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/controller/admin/auth/AuthController.java
@@ -115,6 +115,13 @@ public class AuthController {
return success(AuthConvert.INSTANCE.convert(user, roles, menuList));
}
+ @PostMapping("/register")
+ @PermitAll
+ @Operation(summary = "注册用户")
+ public CommonResult register(@RequestBody @Valid AuthRegisterReqVO registerReqVO) {
+ return success(authService.register(registerReqVO));
+ }
+
// ========== 短信登录相关 ==========
@PostMapping("/sms-login")
@@ -154,10 +161,4 @@ public class AuthController {
return success(authService.socialLogin(reqVO));
}
- @PostMapping("/register")
- @PermitAll
- @Operation(summary = "注册用户")
- public CommonResult register(@RequestBody @Valid AuthRegisterReqVO registerReqVO) {
- return success(authService.register(registerReqVO));
- }
}
diff --git a/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/controller/admin/auth/vo/AuthRegisterReqVO.java b/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/controller/admin/auth/vo/AuthRegisterReqVO.java
index f98d353d1..e15d46f11 100644
--- a/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/controller/admin/auth/vo/AuthRegisterReqVO.java
+++ b/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/controller/admin/auth/vo/AuthRegisterReqVO.java
@@ -18,16 +18,20 @@ public class AuthRegisterReqVO {
private String username;
@Schema(description = "用户昵称", requiredMode = Schema.RequiredMode.REQUIRED, example = "芋艿")
- @Size(max = 30, message = "用户昵称长度不能超过30个字符")
+ @NotBlank(message = "用户昵称不能为空")
+ @Size(max = 30, message = "用户昵称长度不能超过 30 个字符")
private String nickname;
@Schema(description = "密码", requiredMode = Schema.RequiredMode.REQUIRED, example = "123456")
+ @NotEmpty(message = "密码不能为空")
@Length(min = 4, max = 16, message = "密码长度为 4-16 位")
private String password;
// ========== 图片验证码相关 ==========
+
@Schema(description = "验证码,验证码开启时,需要传递", requiredMode = Schema.RequiredMode.REQUIRED,
example = "PfcH6mgr8tpXuMWFjvW6YVaqrswIuwmWI5dsVZSg7sGpWtDCUbHuDEXl3cFB1+VvCC/rAkSwK8Fad52FSuncVg==")
@NotEmpty(message = "验证码不能为空", groups = AuthLoginReqVO.CodeEnableGroup.class)
private String captchaVerification;
+
}
\ No newline at end of file
diff --git a/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/service/auth/AdminAuthService.java b/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/service/auth/AdminAuthService.java
index a960c8ff8..ee3ce101f 100644
--- a/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/service/auth/AdminAuthService.java
+++ b/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/service/auth/AdminAuthService.java
@@ -77,4 +77,5 @@ public interface AdminAuthService {
* @return 注册结果
*/
AuthLoginRespVO register(AuthRegisterReqVO createReqVO);
+
}
diff --git a/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/service/auth/AdminAuthServiceImpl.java b/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/service/auth/AdminAuthServiceImpl.java
index 77471dd89..013c4ea72 100644
--- a/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/service/auth/AdminAuthServiceImpl.java
+++ b/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/service/auth/AdminAuthServiceImpl.java
@@ -4,7 +4,6 @@ import cn.hutool.core.util.ObjectUtil;
import cn.iocoder.yudao.framework.common.enums.CommonStatusEnum;
import cn.iocoder.yudao.framework.common.enums.UserTypeEnum;
import cn.iocoder.yudao.framework.common.util.monitor.TracerUtils;
-import cn.iocoder.yudao.framework.common.util.object.BeanUtils;
import cn.iocoder.yudao.framework.common.util.servlet.ServletUtils;
import cn.iocoder.yudao.framework.common.util.validation.ValidationUtils;
import cn.iocoder.yudao.module.system.api.logger.dto.LoginLogCreateReqDTO;
@@ -15,7 +14,6 @@ import cn.iocoder.yudao.module.system.controller.admin.auth.vo.*;
import cn.iocoder.yudao.module.system.convert.auth.AuthConvert;
import cn.iocoder.yudao.module.system.dal.dataobject.oauth2.OAuth2AccessTokenDO;
import cn.iocoder.yudao.module.system.dal.dataobject.user.AdminUserDO;
-import cn.iocoder.yudao.module.system.dal.mysql.user.AdminUserMapper;
import cn.iocoder.yudao.module.system.enums.logger.LoginLogTypeEnum;
import cn.iocoder.yudao.module.system.enums.logger.LoginResultEnum;
import cn.iocoder.yudao.module.system.enums.oauth2.OAuth2ClientConstants;
@@ -24,20 +22,17 @@ import cn.iocoder.yudao.module.system.service.logger.LoginLogService;
import cn.iocoder.yudao.module.system.service.member.MemberService;
import cn.iocoder.yudao.module.system.service.oauth2.OAuth2TokenService;
import cn.iocoder.yudao.module.system.service.social.SocialUserService;
-import cn.iocoder.yudao.module.system.service.tenant.TenantService;
import cn.iocoder.yudao.module.system.service.user.AdminUserService;
import com.google.common.annotations.VisibleForTesting;
import com.xingyuv.captcha.model.common.ResponseModel;
import com.xingyuv.captcha.model.vo.CaptchaVO;
import com.xingyuv.captcha.service.CaptchaService;
-import lombok.extern.slf4j.Slf4j;
-import org.springframework.beans.factory.annotation.Value;
-import org.springframework.context.annotation.Lazy;
-import org.springframework.security.crypto.password.PasswordEncoder;
-import org.springframework.stereotype.Service;
-
import jakarta.annotation.Resource;
import jakarta.validation.Validator;
+import lombok.extern.slf4j.Slf4j;
+import org.springframework.beans.factory.annotation.Value;
+import org.springframework.stereotype.Service;
+
import java.util.Objects;
import static cn.iocoder.yudao.framework.common.exception.util.ServiceExceptionUtil.exception;
@@ -69,13 +64,7 @@ public class AdminAuthServiceImpl implements AdminAuthService {
private CaptchaService captchaService;
@Resource
private SmsCodeApi smsCodeApi;
- @Resource
- @Lazy // 延迟,避免循环依赖报错
- private TenantService tenantService;
- @Resource
- private AdminUserMapper userMapper;
- @Resource
- private PasswordEncoder passwordEncoder;
+
/**
* 验证码的开关,默认为 true
*/
@@ -258,38 +247,33 @@ public class AdminAuthServiceImpl implements AdminAuthService {
return UserTypeEnum.ADMIN;
}
-
+ @Override
public AuthLoginRespVO register(AuthRegisterReqVO registerReqVO) {
- // 校验验证码
- AuthLoginReqVO loginReqVO = BeanUtils.toBean(registerReqVO, AuthLoginReqVO.class);
- validateCaptcha(loginReqVO);
- // 校验账户配合
- tenantService.handleTenantInfo(tenant -> {
- long count = userMapper.selectCount();
- if (count >= tenant.getAccountCount()) {
- throw exception(USER_COUNT_MAX, tenant.getAccountCount());
- }
- });
- // 校验用户名是否已存在
- if (userMapper.selectByUsername(registerReqVO.getUsername()) != null) {
- throw exception(USER_USERNAME_EXISTS);
+ // 1. 校验验证码
+ validateCaptcha(registerReqVO);
+
+ // 2. 校验用户名是否已存在
+ Long userId = userService.registerUser(registerReqVO);
+
+ // 3. 创建 Token 令牌,记录登录日志
+ return createTokenAfterLoginSuccess(userId, registerReqVO.getUsername(), LoginLogTypeEnum.LOGIN_USERNAME);
+ }
+
+ @VisibleForTesting
+ void validateCaptcha(AuthRegisterReqVO reqVO) {
+ // 如果验证码关闭,则不进行校验
+ if (!captchaEnable) {
+ return;
+ }
+ // 校验验证码
+ ValidationUtils.validate(validator, reqVO, AuthLoginReqVO.CodeEnableGroup.class);
+ CaptchaVO captchaVO = new CaptchaVO();
+ captchaVO.setCaptchaVerification(reqVO.getCaptchaVerification());
+ ResponseModel response = captchaService.verification(captchaVO);
+ // 验证不通过
+ if (!response.isSuccess()) {
+ throw exception(AUTH_REGISTER_CAPTCHA_CODE_ERROR, response.getRepMsg());
}
- // 插入用户
- AdminUserDO user = BeanUtils.toBean(registerReqVO, AdminUserDO.class);
- user.setStatus(CommonStatusEnum.ENABLE.getStatus()); // 默认开启
- user.setPassword(encodePassword(registerReqVO.getPassword())); // 加密密码
- userMapper.insert(user);
-
- return createTokenAfterLoginSuccess(user.getId(), registerReqVO.getUsername(), LoginLogTypeEnum.LOGIN_USERNAME);
}
- /**
- * 对密码进行加密
- *
- * @param password 密码
- * @return 加密后的密码
- */
- private String encodePassword(String password) {
- return passwordEncoder.encode(password);
- }
}
diff --git a/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/service/user/AdminUserService.java b/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/service/user/AdminUserService.java
index 6345e2299..15564408d 100644
--- a/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/service/user/AdminUserService.java
+++ b/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/service/user/AdminUserService.java
@@ -1,16 +1,23 @@
package cn.iocoder.yudao.module.system.service.user;
import cn.hutool.core.collection.CollUtil;
+import cn.iocoder.yudao.framework.common.pojo.PageResult;
import cn.iocoder.yudao.framework.common.util.collection.CollectionUtils;
+import cn.iocoder.yudao.module.system.controller.admin.auth.vo.AuthRegisterReqVO;
import cn.iocoder.yudao.module.system.controller.admin.user.vo.profile.UserProfileUpdatePasswordReqVO;
import cn.iocoder.yudao.module.system.controller.admin.user.vo.profile.UserProfileUpdateReqVO;
-import cn.iocoder.yudao.module.system.controller.admin.user.vo.user.*;
-import cn.iocoder.yudao.framework.common.pojo.PageResult;
+import cn.iocoder.yudao.module.system.controller.admin.user.vo.user.UserImportExcelVO;
+import cn.iocoder.yudao.module.system.controller.admin.user.vo.user.UserImportRespVO;
+import cn.iocoder.yudao.module.system.controller.admin.user.vo.user.UserPageReqVO;
+import cn.iocoder.yudao.module.system.controller.admin.user.vo.user.UserSaveReqVO;
import cn.iocoder.yudao.module.system.dal.dataobject.user.AdminUserDO;
-
import jakarta.validation.Valid;
+
import java.io.InputStream;
-import java.util.*;
+import java.util.Collection;
+import java.util.HashMap;
+import java.util.List;
+import java.util.Map;
/**
* 后台用户 Service 接口
@@ -27,6 +34,14 @@ public interface AdminUserService {
*/
Long createUser(@Valid UserSaveReqVO createReqVO);
+ /**
+ * 注册用户
+ *
+ * @param registerReqVO 用户信息
+ * @return 用户编号
+ */
+ Long registerUser(@Valid AuthRegisterReqVO registerReqVO);
+
/**
* 修改用户
*
diff --git a/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/service/user/AdminUserServiceImpl.java b/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/service/user/AdminUserServiceImpl.java
index 7ef007386..cb9a73ff7 100644
--- a/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/service/user/AdminUserServiceImpl.java
+++ b/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/service/user/AdminUserServiceImpl.java
@@ -13,6 +13,7 @@ import cn.iocoder.yudao.framework.common.util.validation.ValidationUtils;
import cn.iocoder.yudao.framework.datapermission.core.util.DataPermissionUtils;
import cn.iocoder.yudao.module.infra.api.config.ConfigApi;
import cn.iocoder.yudao.module.infra.api.file.FileApi;
+import cn.iocoder.yudao.module.system.controller.admin.auth.vo.AuthRegisterReqVO;
import cn.iocoder.yudao.module.system.controller.admin.user.vo.profile.UserProfileUpdatePasswordReqVO;
import cn.iocoder.yudao.module.system.controller.admin.user.vo.profile.UserProfileUpdateReqVO;
import cn.iocoder.yudao.module.system.controller.admin.user.vo.user.UserImportExcelVO;
@@ -115,6 +116,26 @@ public class AdminUserServiceImpl implements AdminUserService {
return user.getId();
}
+ @Override
+ public Long registerUser(AuthRegisterReqVO registerReqVO) {
+ // 1.1 校验账户配合
+ tenantService.handleTenantInfo(tenant -> {
+ long count = userMapper.selectCount();
+ if (count >= tenant.getAccountCount()) {
+ throw exception(USER_COUNT_MAX, tenant.getAccountCount());
+ }
+ });
+ // 1.2 校验正确性
+ validateUserForCreateOrUpdate(null, registerReqVO.getUsername(), null, null, null, null);
+
+ // 2. 插入用户
+ AdminUserDO user = BeanUtils.toBean(registerReqVO, AdminUserDO.class);
+ user.setStatus(CommonStatusEnum.ENABLE.getStatus()); // 默认开启
+ user.setPassword(encodePassword(registerReqVO.getPassword())); // 加密密码
+ userMapper.insert(user);
+ return user.getId();
+ }
+
@Override
@Transactional(rollbackFor = Exception.class)
@LogRecord(type = SYSTEM_USER_TYPE, subType = SYSTEM_USER_UPDATE_SUB_TYPE, bizNo = "{{#updateReqVO.id}}",
From 5f7505d4acd68a6f2442f2ce4155256f48537269 Mon Sep 17 00:00:00 2001
From: YunaiV
Date: Tue, 10 Sep 2024 21:24:51 +0800
Subject: [PATCH 023/156] =?UTF-8?q?=E3=80=90=E4=BB=A3=E7=A0=81=E8=AF=84?=
=?UTF-8?q?=E5=AE=A1=E3=80=91=E5=95=86=E5=9F=8E=EF=BC=9A=E6=BB=A1=E5=87=8F?=
=?UTF-8?q?=E9=80=81=E7=9A=84=E6=A0=A1=E9=AA=8C=E9=80=BB=E8=BE=91?=
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
---
.../module/promotion/enums/ErrorCodeConstants.java | 2 +-
.../service/reward/RewardActivityServiceImpl.java | 10 ++++++----
2 files changed, 7 insertions(+), 5 deletions(-)
diff --git a/yudao-module-mall/yudao-module-promotion-api/src/main/java/cn/iocoder/yudao/module/promotion/enums/ErrorCodeConstants.java b/yudao-module-mall/yudao-module-promotion-api/src/main/java/cn/iocoder/yudao/module/promotion/enums/ErrorCodeConstants.java
index 5187e2edd..319625387 100644
--- a/yudao-module-mall/yudao-module-promotion-api/src/main/java/cn/iocoder/yudao/module/promotion/enums/ErrorCodeConstants.java
+++ b/yudao-module-mall/yudao-module-promotion-api/src/main/java/cn/iocoder/yudao/module/promotion/enums/ErrorCodeConstants.java
@@ -44,7 +44,7 @@ public interface ErrorCodeConstants {
ErrorCode REWARD_ACTIVITY_UPDATE_FAIL_STATUS_CLOSED = new ErrorCode(1_013_006_002, "满减送活动已关闭,不能修改");
ErrorCode REWARD_ACTIVITY_DELETE_FAIL_STATUS_NOT_CLOSED = new ErrorCode(1_013_006_003, "满减送活动未关闭,不能删除");
ErrorCode REWARD_ACTIVITY_CLOSE_FAIL_STATUS_CLOSED = new ErrorCode(1_013_006_004, "满减送活动已关闭,不能重复关闭");
- ErrorCode REWARD_ACTIVITY_SCOPE_EXISTS = new ErrorCode(1_013_006_005, "与该时间段已存在的满减送活动商品范围冲突。注意商品范围 全部 > 分类 > 商品");
+ ErrorCode REWARD_ACTIVITY_SCOPE_EXISTS = new ErrorCode(1_013_006_005, "与该时间段已存在的满减送活动商品范围冲突");
// ========== TODO 空着 1-013-007-000 ============
diff --git a/yudao-module-mall/yudao-module-promotion-biz/src/main/java/cn/iocoder/yudao/module/promotion/service/reward/RewardActivityServiceImpl.java b/yudao-module-mall/yudao-module-promotion-biz/src/main/java/cn/iocoder/yudao/module/promotion/service/reward/RewardActivityServiceImpl.java
index fe2f0e621..b475abce8 100755
--- a/yudao-module-mall/yudao-module-promotion-biz/src/main/java/cn/iocoder/yudao/module/promotion/service/reward/RewardActivityServiceImpl.java
+++ b/yudao-module-mall/yudao-module-promotion-biz/src/main/java/cn/iocoder/yudao/module/promotion/service/reward/RewardActivityServiceImpl.java
@@ -117,28 +117,30 @@ public class RewardActivityServiceImpl implements RewardActivityService {
* @param rewardActivity 请求
*/
private void validateRewardActivitySpuConflicts(Long id, RewardActivityBaseVO rewardActivity) {
- // 0. 获得开启的所有的活动
+ // 1. 获得开启的所有的活动
List list = rewardActivityMapper.selectList(RewardActivityDO::getStatus, CommonStatusEnum.ENABLE.getStatus());
if (id != null) { // 排除自己这个活动
list.removeIf(activity -> id.equals(activity.getId()));
}
- // 完全不允许重叠。
+ // 2. 完全不允许重叠
for (RewardActivityDO item : list) {
- // 1.1 校验满减送活动时间是否冲突,如果时段不冲突那么不同的时间段内则可以存在相同的商品范围
+ // 2.1 校验满减送活动时间是否冲突,如果时段不冲突那么不同的时间段内则可以存在相同的商品范围
if (!LocalDateTimeUtil.isOverlap(item.getStartTime(), item.getEndTime(),
rewardActivity.getStartTime(), rewardActivity.getEndTime())) {
continue;
}
- // 1.2 校验商品范围是否重叠
+ // 2.2 校验商品范围是否重叠
// 情况一:如果与该时间段内商品范围为全部的活动冲突,或 rewardActivity 商品范围为全部,那么则直接校验不通过
// 例如说,rewardActivity 是全部活动,结果有个 db 里的 activity 是某个分类,它也是冲突的。也就是说,当前时间段内,有且仅有只能有一个活动!
if (PromotionProductScopeEnum.isAll(item.getProductScope()) ||
PromotionProductScopeEnum.isAll(rewardActivity.getProductScope())) {
+ // TODO puhui999:需要提示出来与满减送活动“xxx 活动”存在商品范围冲突;这里可能要分情况,下面需要把 activityName 传入
throw exception(REWARD_ACTIVITY_SCOPE_EXISTS);
}
// 情况二:如果与该时间段内商品范围为类别的活动冲突
if (PromotionProductScopeEnum.isCategory(item.getProductScope())) {
+ // TODO puhui999:前端我们有限制,只允许子分类么?可能要限制下,不然基于分类查询不到对应的商品。因为商品目前必须在子分类下
// 校验分类是否冲突
if (PromotionProductScopeEnum.isCategory(rewardActivity.getProductScope())) {
if (!intersectionDistinct(item.getProductScopeValues(), rewardActivity.getProductScopeValues()).isEmpty()) {
From 1aef8515e2ce87e539518752a11e8a13e98b09dc Mon Sep 17 00:00:00 2001
From: YunaiV
Date: Tue, 10 Sep 2024 21:35:31 +0800
Subject: [PATCH 024/156] =?UTF-8?q?=E3=80=90=E4=BB=A3=E7=A0=81=E8=AF=84?=
=?UTF-8?q?=E5=AE=A1=E3=80=91IOT=EF=BC=9A=E4=BA=A7=E5=93=81=E7=9A=84?=
=?UTF-8?q?=E7=AE=A1=E7=90=86?=
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
---
.../controller/admin/product/IotProductController.java | 10 +---------
.../admin/product/vo/IotProductPageReqVO.java | 3 +--
.../controller/admin/product/vo/IotProductRespVO.java | 6 +++---
.../admin/product/vo/IotProductSaveReqVO.java | 2 +-
.../iot/dal/dataobject/product/IotProductDO.java | 2 +-
.../module/iot/dal/mysql/product/IotProductMapper.java | 2 +-
.../module/iot/service/product/IotProductService.java | 2 +-
.../iot/service/product/IotProductServiceImpl.java | 2 +-
8 files changed, 10 insertions(+), 19 deletions(-)
diff --git a/yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/controller/admin/product/IotProductController.java b/yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/controller/admin/product/IotProductController.java
index fe2f1de17..2a298e6a3 100644
--- a/yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/controller/admin/product/IotProductController.java
+++ b/yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/controller/admin/product/IotProductController.java
@@ -1,11 +1,8 @@
package cn.iocoder.yudao.module.iot.controller.admin.product;
-import cn.iocoder.yudao.framework.apilog.core.annotation.ApiAccessLog;
import cn.iocoder.yudao.framework.common.pojo.CommonResult;
-import cn.iocoder.yudao.framework.common.pojo.PageParam;
import cn.iocoder.yudao.framework.common.pojo.PageResult;
import cn.iocoder.yudao.framework.common.util.object.BeanUtils;
-import cn.iocoder.yudao.framework.excel.core.util.ExcelUtils;
import cn.iocoder.yudao.module.iot.controller.admin.product.vo.IotProductPageReqVO;
import cn.iocoder.yudao.module.iot.controller.admin.product.vo.IotProductRespVO;
import cn.iocoder.yudao.module.iot.controller.admin.product.vo.IotProductSaveReqVO;
@@ -15,19 +12,14 @@ import io.swagger.v3.oas.annotations.Operation;
import io.swagger.v3.oas.annotations.Parameter;
import io.swagger.v3.oas.annotations.tags.Tag;
import jakarta.annotation.Resource;
-import jakarta.servlet.http.HttpServletResponse;
import jakarta.validation.Valid;
import org.springframework.security.access.prepost.PreAuthorize;
import org.springframework.validation.annotation.Validated;
import org.springframework.web.bind.annotation.*;
-import java.io.IOException;
-import java.util.List;
-
-import static cn.iocoder.yudao.framework.apilog.core.enums.OperateTypeEnum.EXPORT;
import static cn.iocoder.yudao.framework.common.pojo.CommonResult.success;
-@Tag(name = "管理后台 - IOT 产品")
+@Tag(name = "管理后台 - IoT 产品")
@RestController
@RequestMapping("/iot/product")
@Validated
diff --git a/yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/controller/admin/product/vo/IotProductPageReqVO.java b/yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/controller/admin/product/vo/IotProductPageReqVO.java
index afc3aafa0..3437f563f 100644
--- a/yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/controller/admin/product/vo/IotProductPageReqVO.java
+++ b/yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/controller/admin/product/vo/IotProductPageReqVO.java
@@ -6,8 +6,7 @@ import lombok.Data;
import lombok.EqualsAndHashCode;
import lombok.ToString;
-// TODO @haohao:涉及到 iot 的拼写,要不都用 IoT,貌似更规范
-@Schema(description = "管理后台 - iot 产品分页 Request VO")
+@Schema(description = "管理后台 - IoT 产品分页 Request VO")
@Data
@EqualsAndHashCode(callSuper = true)
@ToString(callSuper = true)
diff --git a/yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/controller/admin/product/vo/IotProductRespVO.java b/yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/controller/admin/product/vo/IotProductRespVO.java
index 066efca93..0958b3e84 100644
--- a/yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/controller/admin/product/vo/IotProductRespVO.java
+++ b/yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/controller/admin/product/vo/IotProductRespVO.java
@@ -7,13 +7,13 @@ import lombok.Data;
import java.time.LocalDateTime;
-@Schema(description = "管理后台 - iot 产品 Response VO")
+@Schema(description = "管理后台 - IoT 产品 Response VO")
@Data
@ExcelIgnoreUnannotated
public class IotProductRespVO {
- @Schema(description = "产品ID", requiredMode = Schema.RequiredMode.REQUIRED, example = "26087")
- @ExcelProperty("产品ID")
+ @Schema(description = "产品编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "26087")
+ @ExcelProperty("产品编号")
private Long id;
@Schema(description = "产品名称", requiredMode = Schema.RequiredMode.REQUIRED, example = "李四")
diff --git a/yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/controller/admin/product/vo/IotProductSaveReqVO.java b/yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/controller/admin/product/vo/IotProductSaveReqVO.java
index ad01bcd03..254b6b9da 100644
--- a/yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/controller/admin/product/vo/IotProductSaveReqVO.java
+++ b/yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/controller/admin/product/vo/IotProductSaveReqVO.java
@@ -7,7 +7,7 @@ import jakarta.validation.constraints.NotEmpty;
import jakarta.validation.constraints.NotNull;
import lombok.Data;
-@Schema(description = "管理后台 - iot 产品新增/修改 Request VO")
+@Schema(description = "管理后台 - IoT 产品新增/修改 Request VO")
@Data
public class IotProductSaveReqVO {
diff --git a/yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/dal/dataobject/product/IotProductDO.java b/yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/dal/dataobject/product/IotProductDO.java
index 1fa22c7d1..eef466eda 100644
--- a/yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/dal/dataobject/product/IotProductDO.java
+++ b/yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/dal/dataobject/product/IotProductDO.java
@@ -7,7 +7,7 @@ import com.baomidou.mybatisplus.annotation.TableName;
import lombok.*;
/**
- * iot 产品 DO
+ * IoT 产品 DO
*
* @author ahh
*/
diff --git a/yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/dal/mysql/product/IotProductMapper.java b/yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/dal/mysql/product/IotProductMapper.java
index 111ed4969..694d7c007 100644
--- a/yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/dal/mysql/product/IotProductMapper.java
+++ b/yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/dal/mysql/product/IotProductMapper.java
@@ -8,7 +8,7 @@ import cn.iocoder.yudao.module.iot.dal.dataobject.product.IotProductDO;
import org.apache.ibatis.annotations.Mapper;
/**
- * iot 产品 Mapper
+ * IoT 产品 Mapper
*
* @author ahh
*/
diff --git a/yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/service/product/IotProductService.java b/yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/service/product/IotProductService.java
index 14f408030..9677701f1 100644
--- a/yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/service/product/IotProductService.java
+++ b/yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/service/product/IotProductService.java
@@ -7,7 +7,7 @@ import cn.iocoder.yudao.module.iot.dal.dataobject.product.IotProductDO;
import jakarta.validation.Valid;
/**
- * IOT 产品 Service 接口
+ * IoT 产品 Service 接口
*
* @author ahh
*/
diff --git a/yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/service/product/IotProductServiceImpl.java b/yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/service/product/IotProductServiceImpl.java
index 65686f533..844e074d9 100644
--- a/yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/service/product/IotProductServiceImpl.java
+++ b/yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/service/product/IotProductServiceImpl.java
@@ -20,7 +20,7 @@ import static cn.iocoder.yudao.module.iot.enums.ErrorCodeConstants.PRODUCT_NOT_E
import static cn.iocoder.yudao.module.iot.enums.ErrorCodeConstants.PRODUCT_STATUS_NOT_DELETE;
/**
- * IOT 产品 Service 实现类
+ * IoT 产品 Service 实现类
*
* @author ahh
*/
From 9805f9f512705fd514b2971a1ae96b0985be639c Mon Sep 17 00:00:00 2001
From: YunaiV
Date: Wed, 11 Sep 2024 20:55:28 +0800
Subject: [PATCH 025/156] =?UTF-8?q?=E3=80=90=E5=8A=9F=E8=83=BD=E4=BF=AE?=
=?UTF-8?q?=E5=A4=8D=E3=80=91=E5=95=86=E5=9F=8E=EF=BC=9A=E6=8C=87=E5=AE=9A?=
=?UTF-8?q?=E5=8F=91=E5=8D=B7=E3=80=81=E6=96=B0=E4=BA=BA=E5=8D=B7=EF=BC=8C?=
=?UTF-8?q?=E6=94=AF=E6=8C=81=E6=97=A0=E9=99=90=E5=8F=91=E6=94=BE=E7=9A=84?=
=?UTF-8?q?=E5=85=9C=E5=BA=95?=
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
---
.../promotion/enums/coupon/CouponTakeTypeEnum.java | 10 ++++++++--
.../app/coupon/AppCouponTemplateController.java | 4 ++--
.../promotion/service/coupon/CouponServiceImpl.java | 7 ++++---
.../service/coupon/CouponTemplateServiceImpl.java | 8 +++++---
4 files changed, 19 insertions(+), 10 deletions(-)
diff --git a/yudao-module-mall/yudao-module-promotion-api/src/main/java/cn/iocoder/yudao/module/promotion/enums/coupon/CouponTakeTypeEnum.java b/yudao-module-mall/yudao-module-promotion-api/src/main/java/cn/iocoder/yudao/module/promotion/enums/coupon/CouponTakeTypeEnum.java
index 1513e62ea..eff4137ac 100644
--- a/yudao-module-mall/yudao-module-promotion-api/src/main/java/cn/iocoder/yudao/module/promotion/enums/coupon/CouponTakeTypeEnum.java
+++ b/yudao-module-mall/yudao-module-promotion-api/src/main/java/cn/iocoder/yudao/module/promotion/enums/coupon/CouponTakeTypeEnum.java
@@ -5,6 +5,7 @@ import lombok.AllArgsConstructor;
import lombok.Getter;
import java.util.Arrays;
+import java.util.Objects;
/**
* 优惠劵领取方式
@@ -20,12 +21,12 @@ public enum CouponTakeTypeEnum implements IntArrayValuable {
REGISTER(3, "新人券"), // 注册时自动领取
;
- public static final int[] ARRAYS = Arrays.stream(values()).mapToInt(CouponTakeTypeEnum::getValue).toArray();
+ public static final int[] ARRAYS = Arrays.stream(values()).mapToInt(CouponTakeTypeEnum::getType).toArray();
/**
* 值
*/
- private final Integer value;
+ private final Integer type;
/**
* 名字
*/
@@ -35,4 +36,9 @@ public enum CouponTakeTypeEnum implements IntArrayValuable {
public int[] array() {
return ARRAYS;
}
+
+ public static boolean isUser(Integer type) {
+ return Objects.equals(USER.getType(), type);
+ }
+
}
diff --git a/yudao-module-mall/yudao-module-promotion-biz/src/main/java/cn/iocoder/yudao/module/promotion/controller/app/coupon/AppCouponTemplateController.java b/yudao-module-mall/yudao-module-promotion-biz/src/main/java/cn/iocoder/yudao/module/promotion/controller/app/coupon/AppCouponTemplateController.java
index 586618e92..a03a68adb 100755
--- a/yudao-module-mall/yudao-module-promotion-biz/src/main/java/cn/iocoder/yudao/module/promotion/controller/app/coupon/AppCouponTemplateController.java
+++ b/yudao-module-mall/yudao-module-promotion-biz/src/main/java/cn/iocoder/yudao/module/promotion/controller/app/coupon/AppCouponTemplateController.java
@@ -73,7 +73,7 @@ public class AppCouponTemplateController {
// 1.1 处理查询条件:商品范围编号
Long productScopeValue = getProductScopeValue(productScope, spuId);
// 1.2 处理查询条件:领取方式 = 直接领取
- List canTakeTypes = singletonList(CouponTakeTypeEnum.USER.getValue());
+ List canTakeTypes = singletonList(CouponTakeTypeEnum.USER.getType());
// 2. 查询
List list = couponTemplateService.getCouponTemplateList(canTakeTypes, productScope,
@@ -105,7 +105,7 @@ public class AppCouponTemplateController {
// 1.1 处理查询条件:商品范围编号
Long productScopeValue = getProductScopeValue(pageReqVO.getProductScope(), pageReqVO.getSpuId());
// 1.2 处理查询条件:领取方式 = 直接领取
- List canTakeTypes = singletonList(CouponTakeTypeEnum.USER.getValue());
+ List canTakeTypes = singletonList(CouponTakeTypeEnum.USER.getType());
// 2. 分页查询
PageResult pageResult = couponTemplateService.getCouponTemplatePage(
diff --git a/yudao-module-mall/yudao-module-promotion-biz/src/main/java/cn/iocoder/yudao/module/promotion/service/coupon/CouponServiceImpl.java b/yudao-module-mall/yudao-module-promotion-biz/src/main/java/cn/iocoder/yudao/module/promotion/service/coupon/CouponServiceImpl.java
index e6cd4ba0e..3945aa06b 100644
--- a/yudao-module-mall/yudao-module-promotion-biz/src/main/java/cn/iocoder/yudao/module/promotion/service/coupon/CouponServiceImpl.java
+++ b/yudao-module-mall/yudao-module-promotion-biz/src/main/java/cn/iocoder/yudao/module/promotion/service/coupon/CouponServiceImpl.java
@@ -284,8 +284,9 @@ public class CouponServiceImpl implements CouponService {
if (couponTemplate == null) {
throw exception(COUPON_TEMPLATE_NOT_EXISTS);
}
- // 校验剩余数量
- if (couponTemplate.getTakeCount() + userIds.size() > couponTemplate.getTotalCount()) {
+ // 校验剩余数量(仅在 CouponTakeTypeEnum.USER 用户领取时)
+ if (CouponTakeTypeEnum.isUser(couponTemplate.getTakeCount())
+ && couponTemplate.getTakeCount() + userIds.size() > couponTemplate.getTotalCount()) {
throw exception(COUPON_TEMPLATE_NOT_ENOUGH);
}
// 校验"固定日期"的有效期类型是否过期
@@ -295,7 +296,7 @@ public class CouponServiceImpl implements CouponService {
}
}
// 校验领取方式
- if (ObjectUtil.notEqual(couponTemplate.getTakeType(), takeType.getValue())) {
+ if (ObjectUtil.notEqual(couponTemplate.getTakeType(), takeType.getType())) {
throw exception(COUPON_TEMPLATE_CANNOT_TAKE);
}
}
diff --git a/yudao-module-mall/yudao-module-promotion-biz/src/main/java/cn/iocoder/yudao/module/promotion/service/coupon/CouponTemplateServiceImpl.java b/yudao-module-mall/yudao-module-promotion-biz/src/main/java/cn/iocoder/yudao/module/promotion/service/coupon/CouponTemplateServiceImpl.java
index 923ee5904..019c45dae 100755
--- a/yudao-module-mall/yudao-module-promotion-biz/src/main/java/cn/iocoder/yudao/module/promotion/service/coupon/CouponTemplateServiceImpl.java
+++ b/yudao-module-mall/yudao-module-promotion-biz/src/main/java/cn/iocoder/yudao/module/promotion/service/coupon/CouponTemplateServiceImpl.java
@@ -57,8 +57,10 @@ public class CouponTemplateServiceImpl implements CouponTemplateService {
public void updateCouponTemplate(CouponTemplateUpdateReqVO updateReqVO) {
// 校验存在
CouponTemplateDO couponTemplate = validateCouponTemplateExists(updateReqVO.getId());
- // 校验发放数量不能过小
- if (updateReqVO.getTotalCount() < couponTemplate.getTakeCount()) {
+ // 校验发放数量不能过小(仅在 CouponTakeTypeEnum.USER 用户领取时)
+ if (CouponTakeTypeEnum.isUser(couponTemplate.getTakeType())
+ && updateReqVO.getTotalCount() > 0 // 大于 0 的原因,是因为 -1 不限制
+ && updateReqVO.getTotalCount() < couponTemplate.getTakeCount()) {
throw exception(COUPON_TEMPLATE_TOTAL_COUNT_TOO_SMALL, couponTemplate.getTakeCount());
}
// 校验商品范围
@@ -118,7 +120,7 @@ public class CouponTemplateServiceImpl implements CouponTemplateService {
@Override
public List getCouponTemplateListByTakeType(CouponTakeTypeEnum takeType) {
- return couponTemplateMapper.selectListByTakeType(takeType.getValue());
+ return couponTemplateMapper.selectListByTakeType(takeType.getType());
}
@Override
From 18e789d4fb988dd4014a65fb4bda5ea90aa8307e Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?=E5=AE=89=E6=B5=A9=E6=B5=A9?= <1036606149@qq.com>
Date: Wed, 11 Sep 2024 23:00:33 +0800
Subject: [PATCH 026/156] =?UTF-8?q?=E6=96=B0=E5=A2=9E=EF=BC=9A=E5=A2=9E?=
=?UTF-8?q?=E5=8A=A0=20IOT=20=E7=89=A9=E6=A8=A1=E5=9E=8B?=
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
---
.../module/iot/enums/ErrorCodeConstants.java | 5 +-
.../IotThinkModelFunctionController.http | 96 +++++++++++++++++++
.../IotThinkModelFunctionController.java | 63 ++++++++++++
.../vo/IotThingModelProperty.java | 90 +++++++++++++++++
.../vo/IotThinkModelFunctionRespVO.java | 38 ++++++++
.../vo/IotThinkModelFunctionSaveReqVO.java | 26 +++++
.../IotThinkModelFunctionDO.java | 44 +++++++++
.../IotThinkModelFunctionMapper.java | 25 +++++
.../product/IotProductServiceImpl.java | 5 +-
.../IotThinkModelFunctionService.java | 43 +++++++++
.../IotThinkModelFunctionServiceImpl.java | 74 ++++++++++++++
.../IotThinkModelFunctionMapper.xml | 12 +++
.../IotThinkModelFunctionServiceImplTest.java | 71 ++++++++++++++
13 files changed, 588 insertions(+), 4 deletions(-)
create mode 100644 yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/controller/admin/thinkmodelfunction/IotThinkModelFunctionController.http
create mode 100644 yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/controller/admin/thinkmodelfunction/IotThinkModelFunctionController.java
create mode 100644 yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/controller/admin/thinkmodelfunction/vo/IotThingModelProperty.java
create mode 100644 yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/controller/admin/thinkmodelfunction/vo/IotThinkModelFunctionRespVO.java
create mode 100644 yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/controller/admin/thinkmodelfunction/vo/IotThinkModelFunctionSaveReqVO.java
create mode 100644 yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/dal/dataobject/thinkmodelfunction/IotThinkModelFunctionDO.java
create mode 100644 yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/dal/mysql/thinkmodelfunction/IotThinkModelFunctionMapper.java
create mode 100644 yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/service/thinkmodelfunction/IotThinkModelFunctionService.java
create mode 100644 yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/service/thinkmodelfunction/IotThinkModelFunctionServiceImpl.java
create mode 100644 yudao-module-iot/yudao-module-iot-biz/src/main/resources/mapper/thinkmodelfunction/IotThinkModelFunctionMapper.xml
create mode 100644 yudao-module-iot/yudao-module-iot-biz/src/test/java/cn/iocoder/yudao/module/iot/service/thinkmodelfunction/IotThinkModelFunctionServiceImplTest.java
diff --git a/yudao-module-iot/yudao-module-iot-api/src/main/java/cn/iocoder/yudao/module/iot/enums/ErrorCodeConstants.java b/yudao-module-iot/yudao-module-iot-api/src/main/java/cn/iocoder/yudao/module/iot/enums/ErrorCodeConstants.java
index 3fd09ce8e..19ee8972d 100644
--- a/yudao-module-iot/yudao-module-iot-api/src/main/java/cn/iocoder/yudao/module/iot/enums/ErrorCodeConstants.java
+++ b/yudao-module-iot/yudao-module-iot-api/src/main/java/cn/iocoder/yudao/module/iot/enums/ErrorCodeConstants.java
@@ -9,8 +9,11 @@ import cn.iocoder.yudao.framework.common.exception.ErrorCode;
*/
public interface ErrorCodeConstants {
- // ========== 产品相关 1-050-001-000 ============
+ // ========== IoT 产品相关 1-050-001-000 ============
ErrorCode PRODUCT_NOT_EXISTS = new ErrorCode(1_050_001_000, "产品不存在");
ErrorCode PRODUCT_IDENTIFICATION_EXISTS = new ErrorCode(1_050_001_001, "产品标识已经存在");
ErrorCode PRODUCT_STATUS_NOT_DELETE = new ErrorCode(1_050_001_002, "产品状是发布状态,不允许删除");
+
+ // ========== IoT 产品物模型 1-050-002-000 ============
+ ErrorCode THINK_MODEL_FUNCTION_NOT_EXISTS = new ErrorCode(1_050_002_000, "产品物模型不存在");
}
diff --git a/yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/controller/admin/thinkmodelfunction/IotThinkModelFunctionController.http b/yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/controller/admin/thinkmodelfunction/IotThinkModelFunctionController.http
new file mode 100644
index 000000000..bc0229bfb
--- /dev/null
+++ b/yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/controller/admin/thinkmodelfunction/IotThinkModelFunctionController.http
@@ -0,0 +1,96 @@
+### 请求 /iot/think-model-function/create 接口 => 成功
+POST {{baseUrl}}/iot/think-model-function/create
+Content-Type: application/json
+tenant-id: {{adminTenentId}}
+Authorization: Bearer {{token}}
+
+{
+ "productKey": "123456",
+ "properties": [
+ {
+ "identifier": "CurrentTemperature",
+ "name": "当前温度",
+ "accessMode": "r",
+ "required": true,
+ "dataType": {
+ "type": "float",
+ "specs": {
+ "min": "-40",
+ "max": "120",
+ "unit": "°C",
+ "unitName": "摄氏度",
+ "step": "0.1"
+ }
+ }
+ },
+ {
+ "identifier": "CurrentHumidity",
+ "name": "当前湿度",
+ "accessMode": "r",
+ "required": true,
+ "dataType": {
+ "type": "float",
+ "specs": {
+ "min": "0",
+ "max": "100",
+ "unit": "%",
+ "unitName": "百分比",
+ "step": "0.1"
+ }
+ }
+ }
+ ],
+ "services": "{}",
+ "events": "{}"
+}
+
+### 请求 /iot/think-model-function/update 接口 => 成功
+PUT {{baseUrl}}/iot/think-model-function/update
+Content-Type: application/json
+tenant-id: {{adminTenentId}}
+Authorization: Bearer {{token}}
+
+{
+ "productKey": "123456",
+ "properties": [
+ {
+ "identifier": "CurrentTemperature",
+ "name": "当前温度",
+ "accessMode": "r",
+ "required": true,
+ "dataType": {
+ "type": "float",
+ "specs": {
+ "min": "-40",
+ "max": "130",
+ "unit": "°C",
+ "unitName": "摄氏度",
+ "step": "0.1"
+ }
+ }
+ },
+ {
+ "identifier": "CurrentHumidity",
+ "name": "当前湿度",
+ "accessMode": "r",
+ "required": true,
+ "dataType": {
+ "type": "float",
+ "specs": {
+ "min": "0",
+ "max": "100",
+ "unit": "%",
+ "unitName": "百分比",
+ "step": "0.1"
+ }
+ }
+ }
+ ],
+ "services": "{}",
+ "events": "{}"
+}
+
+### 请求 /iot/think-model-function/get 接口 => 成功
+GET {{baseUrl}}/iot/think-model-function/get?productKey=123456
+tenant-id: {{adminTenentId}}
+Authorization: Bearer {{token}}
\ No newline at end of file
diff --git a/yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/controller/admin/thinkmodelfunction/IotThinkModelFunctionController.java b/yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/controller/admin/thinkmodelfunction/IotThinkModelFunctionController.java
new file mode 100644
index 000000000..cebaca4f5
--- /dev/null
+++ b/yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/controller/admin/thinkmodelfunction/IotThinkModelFunctionController.java
@@ -0,0 +1,63 @@
+package cn.iocoder.yudao.module.iot.controller.admin.thinkmodelfunction;
+
+import org.springframework.web.bind.annotation.*;
+import jakarta.annotation.Resource;
+import org.springframework.validation.annotation.Validated;
+import org.springframework.security.access.prepost.PreAuthorize;
+import io.swagger.v3.oas.annotations.tags.Tag;
+import io.swagger.v3.oas.annotations.Parameter;
+import io.swagger.v3.oas.annotations.Operation;
+
+import jakarta.validation.*;
+
+import cn.iocoder.yudao.framework.common.pojo.CommonResult;
+import cn.iocoder.yudao.framework.common.util.object.BeanUtils;
+import static cn.iocoder.yudao.framework.common.pojo.CommonResult.success;
+
+import cn.iocoder.yudao.module.iot.controller.admin.thinkmodelfunction.vo.*;
+import cn.iocoder.yudao.module.iot.dal.dataobject.thinkmodelfunction.IotThinkModelFunctionDO;
+import cn.iocoder.yudao.module.iot.service.thinkmodelfunction.IotThinkModelFunctionService;
+
+@Tag(name = "管理后台 - IoT 产品物模型")
+@RestController
+@RequestMapping("/iot/think-model-function")
+@Validated
+public class IotThinkModelFunctionController {
+
+ @Resource
+ private IotThinkModelFunctionService thinkModelFunctionService;
+
+ @PostMapping("/create")
+ @Operation(summary = "创建IoT 产品物模型")
+ @PreAuthorize("@ss.hasPermission('iot:think-model-function:create')")
+ public CommonResult createThinkModelFunction(@Valid @RequestBody IotThinkModelFunctionSaveReqVO createReqVO) {
+ return success(thinkModelFunctionService.createThinkModelFunction(createReqVO));
+ }
+
+ @PutMapping("/update")
+ @Operation(summary = "更新IoT 产品物模型")
+ @PreAuthorize("@ss.hasPermission('iot:think-model-function:update')")
+ public CommonResult updateThinkModelFunction(@Valid @RequestBody IotThinkModelFunctionSaveReqVO updateReqVO) {
+ thinkModelFunctionService.updateThinkModelFunctionByProductKey(updateReqVO);
+ return success(true);
+ }
+
+ @DeleteMapping("/delete")
+ @Operation(summary = "删除IoT 产品物模型")
+ @Parameter(name = "id", description = "编号", required = true)
+ @PreAuthorize("@ss.hasPermission('iot:think-model-function:delete')")
+ public CommonResult deleteThinkModelFunction(@RequestParam("id") Long id) {
+ thinkModelFunctionService.deleteThinkModelFunction(id);
+ return success(true);
+ }
+
+ @GetMapping("/get")
+ @Operation(summary = "获得IoT 产品物模型")
+ @Parameter(name = "productKey", description = "产品Key", required = true, example = "1024")
+ @PreAuthorize("@ss.hasPermission('iot:think-model-function:query')")
+ public CommonResult getThinkModelFunctionByProductKey(@RequestParam("productKey") String productKey) {
+ IotThinkModelFunctionDO thinkModelFunction = thinkModelFunctionService.getThinkModelFunctionByProductKey(productKey);
+ return success(BeanUtils.toBean(thinkModelFunction, IotThinkModelFunctionRespVO.class));
+ }
+
+}
\ No newline at end of file
diff --git a/yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/controller/admin/thinkmodelfunction/vo/IotThingModelProperty.java b/yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/controller/admin/thinkmodelfunction/vo/IotThingModelProperty.java
new file mode 100644
index 000000000..0187ae514
--- /dev/null
+++ b/yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/controller/admin/thinkmodelfunction/vo/IotThingModelProperty.java
@@ -0,0 +1,90 @@
+package cn.iocoder.yudao.module.iot.controller.admin.thinkmodelfunction.vo;
+
+import io.swagger.v3.oas.annotations.media.Schema;
+import lombok.Data;
+
+import java.util.List;
+
+@Schema(description = "管理后台 - IoT 产品物模型属性")
+@Data
+public class IotThingModelProperty {
+
+ @Schema(description = "属性标识符")
+ private String identifier;
+
+ @Schema(description = "属性名称")
+ private String name;
+
+ @Schema(description = "访问模式 (r/rw)")
+ private String accessMode;
+
+ @Schema(description = "是否必需")
+ private boolean required;
+
+ @Schema(description = "数据类型")
+ private DataType dataType;
+
+ @Schema(description = "数据类型")
+ @Data
+ public static class DataType {
+
+ @Schema(description = "数据类型(float, double, struct, enum等)")
+ private String type;
+
+ @Schema(description = "单一类型的规格(适用于float, double等)")
+ private Specs specs;
+
+ @Schema(description = "结构体字段(适用于struct类型)")
+ private List structSpecs;
+
+ @Schema(description = "规格")
+ @Data
+ public static class Specs {
+
+ @Schema(description = "最小值")
+ private String min;
+
+ @Schema(description = "最大值")
+ private String max;
+
+ @Schema(description = "单位符号")
+ private String unit;
+
+ @Schema(description = "单位名称")
+ private String unitName;
+
+ @Schema(description = "步进值")
+ private String step;
+ }
+
+ @Schema(description = "结构体字段")
+ @Data
+ public static class StructField {
+
+ @Schema(description = "字段标识符")
+ private String identifier;
+
+ @Schema(description = "字段名称")
+ private String name;
+
+ @Schema(description = "字段的数据类型")
+ private DataType dataType;
+ }
+ }
+
+ @Schema(description = "枚举规格")
+ @Data
+ public static class EnumSpecs {
+
+ @Schema(description = "枚举值")
+ private int value;
+
+ @Schema(description = "枚举名称")
+ private String name;
+
+ public EnumSpecs(int value, String name) {
+ this.value = value;
+ this.name = name;
+ }
+ }
+}
diff --git a/yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/controller/admin/thinkmodelfunction/vo/IotThinkModelFunctionRespVO.java b/yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/controller/admin/thinkmodelfunction/vo/IotThinkModelFunctionRespVO.java
new file mode 100644
index 000000000..74f7bfb6f
--- /dev/null
+++ b/yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/controller/admin/thinkmodelfunction/vo/IotThinkModelFunctionRespVO.java
@@ -0,0 +1,38 @@
+package cn.iocoder.yudao.module.iot.controller.admin.thinkmodelfunction.vo;
+
+import io.swagger.v3.oas.annotations.media.Schema;
+import lombok.*;
+
+import java.time.LocalDateTime;
+import com.alibaba.excel.annotation.*;
+
+@Schema(description = "管理后台 - IoT 产品物模型 Response VO")
+@Data
+@ExcelIgnoreUnannotated
+public class IotThinkModelFunctionRespVO {
+
+ @Schema(description = "产品ID", requiredMode = Schema.RequiredMode.REQUIRED, example = "21816")
+ @ExcelProperty("产品ID")
+ private Long id;
+
+ @Schema(description = "产品标识", requiredMode = Schema.RequiredMode.REQUIRED)
+ @ExcelProperty("产品标识")
+ private String productKey;
+
+ @Schema(description = "属性列表", requiredMode = Schema.RequiredMode.REQUIRED)
+ @ExcelProperty("属性列表")
+ private String properties;
+
+ @Schema(description = "服务列表")
+ @ExcelProperty("服务列表")
+ private String services;
+
+ @Schema(description = "事件列表")
+ @ExcelProperty("事件列表")
+ private String events;
+
+ @Schema(description = "创建时间", requiredMode = Schema.RequiredMode.REQUIRED)
+ @ExcelProperty("创建时间")
+ private LocalDateTime createTime;
+
+}
\ No newline at end of file
diff --git a/yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/controller/admin/thinkmodelfunction/vo/IotThinkModelFunctionSaveReqVO.java b/yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/controller/admin/thinkmodelfunction/vo/IotThinkModelFunctionSaveReqVO.java
new file mode 100644
index 000000000..200e7682c
--- /dev/null
+++ b/yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/controller/admin/thinkmodelfunction/vo/IotThinkModelFunctionSaveReqVO.java
@@ -0,0 +1,26 @@
+package cn.iocoder.yudao.module.iot.controller.admin.thinkmodelfunction.vo;
+
+import io.swagger.v3.oas.annotations.media.Schema;
+import lombok.*;
+import java.util.*;
+import jakarta.validation.constraints.*;
+
+@Schema(description = "管理后台 - IoT 产品物模型新增/修改 Request VO")
+@Data
+public class IotThinkModelFunctionSaveReqVO {
+
+ @Schema(description = "产品标识", requiredMode = Schema.RequiredMode.REQUIRED)
+ @NotEmpty(message = "产品标识不能为空")
+ private String productKey;
+
+ @Schema(description = "属性列表", requiredMode = Schema.RequiredMode.REQUIRED)
+ @NotEmpty(message = "属性列表不能为空")
+ private List properties;
+
+ @Schema(description = "服务列表")
+ private String services;
+
+ @Schema(description = "事件列表")
+ private String events;
+
+}
\ No newline at end of file
diff --git a/yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/dal/dataobject/thinkmodelfunction/IotThinkModelFunctionDO.java b/yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/dal/dataobject/thinkmodelfunction/IotThinkModelFunctionDO.java
new file mode 100644
index 000000000..7d9ea4589
--- /dev/null
+++ b/yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/dal/dataobject/thinkmodelfunction/IotThinkModelFunctionDO.java
@@ -0,0 +1,44 @@
+package cn.iocoder.yudao.module.iot.dal.dataobject.thinkmodelfunction;
+
+import lombok.*;
+import com.baomidou.mybatisplus.annotation.*;
+import cn.iocoder.yudao.framework.mybatis.core.dataobject.BaseDO;
+
+/**
+ * IoT 产品物模型 DO
+ *
+ * @author 芋道源码
+ */
+@TableName("iot_think_model_function")
+@KeySequence("iot_think_model_function_seq") // 用于 Oracle、PostgreSQL、Kingbase、DB2、H2 数据库的主键自增。如果是 MySQL 等数据库,可不写。
+@Data
+@EqualsAndHashCode(callSuper = true)
+@ToString(callSuper = true)
+@Builder
+@NoArgsConstructor
+@AllArgsConstructor
+public class IotThinkModelFunctionDO extends BaseDO {
+
+ /**
+ * 产品ID
+ */
+ @TableId
+ private Long id;
+ /**
+ * 产品标识
+ */
+ private String productKey;
+ /**
+ * 属性列表
+ */
+ private String properties;
+ /**
+ * 服务列表
+ */
+ private String services;
+ /**
+ * 事件列表
+ */
+ private String events;
+
+}
\ No newline at end of file
diff --git a/yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/dal/mysql/thinkmodelfunction/IotThinkModelFunctionMapper.java b/yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/dal/mysql/thinkmodelfunction/IotThinkModelFunctionMapper.java
new file mode 100644
index 000000000..5475a723b
--- /dev/null
+++ b/yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/dal/mysql/thinkmodelfunction/IotThinkModelFunctionMapper.java
@@ -0,0 +1,25 @@
+package cn.iocoder.yudao.module.iot.dal.mysql.thinkmodelfunction;
+
+import cn.iocoder.yudao.framework.mybatis.core.mapper.BaseMapperX;
+import cn.iocoder.yudao.framework.mybatis.core.query.LambdaQueryWrapperX;
+import cn.iocoder.yudao.module.iot.dal.dataobject.thinkmodelfunction.IotThinkModelFunctionDO;
+import org.apache.ibatis.annotations.Mapper;
+
+/**
+ * IoT 产品物模型 Mapper
+ *
+ * @author 芋道源码
+ */
+@Mapper
+public interface IotThinkModelFunctionMapper extends BaseMapperX {
+
+ default IotThinkModelFunctionDO selectByProductKey(String productKey) {
+ return selectOne(new LambdaQueryWrapperX().eq(IotThinkModelFunctionDO::getProductKey, productKey));
+ }
+
+ default int updateByProductKey(IotThinkModelFunctionDO thinkModelFunction) {
+ return update(thinkModelFunction, new LambdaQueryWrapperX()
+ .eq(IotThinkModelFunctionDO::getProductKey, thinkModelFunction.getProductKey())
+ );
+ }
+}
\ No newline at end of file
diff --git a/yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/service/product/IotProductServiceImpl.java b/yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/service/product/IotProductServiceImpl.java
index 844e074d9..96975c27f 100644
--- a/yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/service/product/IotProductServiceImpl.java
+++ b/yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/service/product/IotProductServiceImpl.java
@@ -16,8 +16,7 @@ import java.util.Objects;
import java.util.UUID;
import static cn.iocoder.yudao.framework.common.exception.util.ServiceExceptionUtil.exception;
-import static cn.iocoder.yudao.module.iot.enums.ErrorCodeConstants.PRODUCT_NOT_EXISTS;
-import static cn.iocoder.yudao.module.iot.enums.ErrorCodeConstants.PRODUCT_STATUS_NOT_DELETE;
+import static cn.iocoder.yudao.module.iot.enums.ErrorCodeConstants.*;
/**
* IoT 产品 Service 实现类
@@ -54,7 +53,7 @@ public class IotProductServiceImpl implements IotProductService {
}
// 2. 校验唯一性
if (productMapper.selectByProductKey(productKey) != null) {
- throw exception(PRODUCT_NOT_EXISTS);
+ throw exception(PRODUCT_IDENTIFICATION_EXISTS);
}
createReqVO.setProductKey(productKey);
}
diff --git a/yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/service/thinkmodelfunction/IotThinkModelFunctionService.java b/yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/service/thinkmodelfunction/IotThinkModelFunctionService.java
new file mode 100644
index 000000000..a52142810
--- /dev/null
+++ b/yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/service/thinkmodelfunction/IotThinkModelFunctionService.java
@@ -0,0 +1,43 @@
+package cn.iocoder.yudao.module.iot.service.thinkmodelfunction;
+
+import cn.iocoder.yudao.module.iot.controller.admin.thinkmodelfunction.vo.IotThinkModelFunctionSaveReqVO;
+import cn.iocoder.yudao.module.iot.dal.dataobject.thinkmodelfunction.IotThinkModelFunctionDO;
+import jakarta.validation.Valid;
+
+/**
+ * IoT 产品物模型 Service 接口
+ *
+ * @author 芋道源码
+ */
+public interface IotThinkModelFunctionService {
+
+ /**
+ * 创建IoT 产品物模型
+ *
+ * @param createReqVO 创建信息
+ * @return 编号
+ */
+ Long createThinkModelFunction(@Valid IotThinkModelFunctionSaveReqVO createReqVO);
+
+ /**
+ * 删除IoT 产品物模型
+ *
+ * @param id 编号
+ */
+ void deleteThinkModelFunction(Long id);
+
+ /**
+ * 获得IoT 产品物模型
+ *
+ * @param productKey 产品Key
+ * @return IoT 产品物模型
+ */
+ IotThinkModelFunctionDO getThinkModelFunctionByProductKey(String productKey);
+
+ /**
+ * 更新IoT 产品物模型
+ *
+ * @param updateReqVO 更新信息
+ */
+ void updateThinkModelFunctionByProductKey(@Valid IotThinkModelFunctionSaveReqVO updateReqVO);
+}
\ No newline at end of file
diff --git a/yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/service/thinkmodelfunction/IotThinkModelFunctionServiceImpl.java b/yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/service/thinkmodelfunction/IotThinkModelFunctionServiceImpl.java
new file mode 100644
index 000000000..1f1355dd3
--- /dev/null
+++ b/yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/service/thinkmodelfunction/IotThinkModelFunctionServiceImpl.java
@@ -0,0 +1,74 @@
+package cn.iocoder.yudao.module.iot.service.thinkmodelfunction;
+
+import cn.hutool.json.JSONUtil;
+import cn.iocoder.yudao.framework.common.util.object.BeanUtils;
+import cn.iocoder.yudao.module.iot.controller.admin.thinkmodelfunction.vo.IotThinkModelFunctionSaveReqVO;
+import cn.iocoder.yudao.module.iot.dal.dataobject.thinkmodelfunction.IotThinkModelFunctionDO;
+import cn.iocoder.yudao.module.iot.dal.mysql.thinkmodelfunction.IotThinkModelFunctionMapper;
+import jakarta.annotation.Resource;
+import org.springframework.stereotype.Service;
+import org.springframework.validation.annotation.Validated;
+
+import static cn.iocoder.yudao.framework.common.exception.util.ServiceExceptionUtil.exception;
+import static cn.iocoder.yudao.module.iot.enums.ErrorCodeConstants.THINK_MODEL_FUNCTION_NOT_EXISTS;
+
+/**
+ * IoT 产品物模型 Service 实现类
+ *
+ * @author 芋道源码
+ */
+@Service
+@Validated
+public class IotThinkModelFunctionServiceImpl implements IotThinkModelFunctionService {
+
+ @Resource
+ private IotThinkModelFunctionMapper thinkModelFunctionMapper;
+
+ @Override
+ public Long createThinkModelFunction(IotThinkModelFunctionSaveReqVO createReqVO) {
+ // 插入
+ IotThinkModelFunctionDO thinkModelFunction = BeanUtils.toBean(createReqVO, IotThinkModelFunctionDO.class);
+ // properties 字段,需要转换成 JSON
+ thinkModelFunction.setProperties(JSONUtil.toJsonStr(createReqVO.getProperties()));
+ thinkModelFunctionMapper.insert(thinkModelFunction);
+ // 返回
+ return thinkModelFunction.getId();
+ }
+
+ @Override
+ public void deleteThinkModelFunction(Long id) {
+ // 校验存在
+ validateThinkModelFunctionExists(id);
+ // 删除
+ thinkModelFunctionMapper.deleteById(id);
+ }
+
+ private void validateThinkModelFunctionExists(Long id) {
+ if (thinkModelFunctionMapper.selectById(id) == null) {
+ throw exception(THINK_MODEL_FUNCTION_NOT_EXISTS);
+ }
+ }
+
+ private void validateThinkModelFunctionExistsByProductKey(String productKey) {
+ if (thinkModelFunctionMapper.selectByProductKey(productKey) == null) {
+ throw exception(THINK_MODEL_FUNCTION_NOT_EXISTS);
+ }
+ }
+
+ @Override
+ public IotThinkModelFunctionDO getThinkModelFunctionByProductKey(String productKey) {
+ return thinkModelFunctionMapper.selectByProductKey(productKey);
+ }
+
+ @Override
+ public void updateThinkModelFunctionByProductKey(IotThinkModelFunctionSaveReqVO updateReqVO) {
+ // 校验存在
+ validateThinkModelFunctionExistsByProductKey(updateReqVO.getProductKey());
+ // 更新
+ IotThinkModelFunctionDO thinkModelFunction = BeanUtils.toBean(updateReqVO, IotThinkModelFunctionDO.class);
+ // properties 字段,需要转换成 JSON
+ thinkModelFunction.setProperties(JSONUtil.toJsonStr(updateReqVO.getProperties()));
+ thinkModelFunctionMapper.updateByProductKey(thinkModelFunction);
+ }
+
+}
\ No newline at end of file
diff --git a/yudao-module-iot/yudao-module-iot-biz/src/main/resources/mapper/thinkmodelfunction/IotThinkModelFunctionMapper.xml b/yudao-module-iot/yudao-module-iot-biz/src/main/resources/mapper/thinkmodelfunction/IotThinkModelFunctionMapper.xml
new file mode 100644
index 000000000..525a32bd6
--- /dev/null
+++ b/yudao-module-iot/yudao-module-iot-biz/src/main/resources/mapper/thinkmodelfunction/IotThinkModelFunctionMapper.xml
@@ -0,0 +1,12 @@
+
+
+
+
+
+
+
\ No newline at end of file
diff --git a/yudao-module-iot/yudao-module-iot-biz/src/test/java/cn/iocoder/yudao/module/iot/service/thinkmodelfunction/IotThinkModelFunctionServiceImplTest.java b/yudao-module-iot/yudao-module-iot-biz/src/test/java/cn/iocoder/yudao/module/iot/service/thinkmodelfunction/IotThinkModelFunctionServiceImplTest.java
new file mode 100644
index 000000000..762f6021b
--- /dev/null
+++ b/yudao-module-iot/yudao-module-iot-biz/src/test/java/cn/iocoder/yudao/module/iot/service/thinkmodelfunction/IotThinkModelFunctionServiceImplTest.java
@@ -0,0 +1,71 @@
+package cn.iocoder.yudao.module.iot.service.thinkmodelfunction;
+
+import org.junit.jupiter.api.Test;
+
+import jakarta.annotation.Resource;
+
+import cn.iocoder.yudao.framework.test.core.ut.BaseDbUnitTest;
+
+import cn.iocoder.yudao.module.iot.controller.admin.thinkmodelfunction.vo.*;
+import cn.iocoder.yudao.module.iot.dal.dataobject.thinkmodelfunction.IotThinkModelFunctionDO;
+import cn.iocoder.yudao.module.iot.dal.mysql.thinkmodelfunction.IotThinkModelFunctionMapper;
+
+import org.springframework.context.annotation.Import;
+
+import static cn.iocoder.yudao.module.iot.enums.ErrorCodeConstants.*;
+import static cn.iocoder.yudao.framework.test.core.util.AssertUtils.*;
+import static cn.iocoder.yudao.framework.test.core.util.RandomUtils.*;
+import static org.junit.jupiter.api.Assertions.*;
+
+/**
+ * {@link IotThinkModelFunctionServiceImpl} 的单元测试类
+ *
+ * @author 芋道源码
+ */
+@Import(IotThinkModelFunctionServiceImpl.class)
+public class IotThinkModelFunctionServiceImplTest extends BaseDbUnitTest {
+
+ @Resource
+ private IotThinkModelFunctionServiceImpl thinkModelFunctionService;
+
+ @Resource
+ private IotThinkModelFunctionMapper thinkModelFunctionMapper;
+
+ @Test
+ public void testCreateThinkModelFunction_success() {
+ // 准备参数
+ IotThinkModelFunctionSaveReqVO createReqVO = randomPojo(IotThinkModelFunctionSaveReqVO.class);
+
+ // 调用
+ Long thinkModelFunctionId = thinkModelFunctionService.createThinkModelFunction(createReqVO);
+ // 断言
+ assertNotNull(thinkModelFunctionId);
+ // 校验记录的属性是否正确
+ IotThinkModelFunctionDO thinkModelFunction = thinkModelFunctionMapper.selectById(thinkModelFunctionId);
+ assertPojoEquals(createReqVO, thinkModelFunction, "id");
+ }
+
+ @Test
+ public void testDeleteThinkModelFunction_success() {
+ // mock 数据
+ IotThinkModelFunctionDO dbThinkModelFunction = randomPojo(IotThinkModelFunctionDO.class);
+ thinkModelFunctionMapper.insert(dbThinkModelFunction);// @Sql: 先插入出一条存在的数据
+ // 准备参数
+ Long id = dbThinkModelFunction.getId();
+
+ // 调用
+ thinkModelFunctionService.deleteThinkModelFunction(id);
+ // 校验数据不存在了
+ assertNull(thinkModelFunctionMapper.selectById(id));
+ }
+
+ @Test
+ public void testDeleteThinkModelFunction_notExists() {
+ // 准备参数
+ Long id = randomLongId();
+
+ // 调用, 并断言异常
+ assertServiceException(() -> thinkModelFunctionService.deleteThinkModelFunction(id), THINK_MODEL_FUNCTION_NOT_EXISTS);
+ }
+
+}
\ No newline at end of file
From 9e77692414dc805be24c8ee12d5ccc3c05d1bb23 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?=E5=AE=89=E6=B5=A9=E6=B5=A9?= <1036606149@qq.com>
Date: Fri, 13 Sep 2024 22:30:19 +0800
Subject: [PATCH 027/156] =?UTF-8?q?=E4=BF=AE=E6=94=B9=EF=BC=9A=E4=BC=98?=
=?UTF-8?q?=E5=8C=96=20IOT=20=E7=89=A9=E6=A8=A1=E5=9E=8B=20=E4=BF=AE?=
=?UTF-8?q?=E6=94=B9=E5=92=8C=E6=9F=A5=E8=AF=A2=E6=8E=A5=E5=8F=A3?=
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
---
.../module/iot/enums/ErrorCodeConstants.java | 1 +
.../IotThinkModelFunctionController.http | 7 ++-
.../IotThinkModelFunctionController.java | 47 +++++++++------
.../vo/IotThinkModelFunctionRespVO.java | 8 ++-
.../vo/IotThinkModelFunctionSaveReqVO.java | 7 +++
.../IotThinkModelFunctionConvert.java | 51 ++++++++++++++++
.../IotThinkModelFunctionDO.java | 15 ++++-
.../IotThinkModelFunctionMapper.java | 7 +--
.../IotThinkModelFunctionService.java | 12 +++-
.../IotThinkModelFunctionServiceImpl.java | 60 +++++++++++--------
10 files changed, 159 insertions(+), 56 deletions(-)
create mode 100644 yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/convert/thinkmodelfunction/IotThinkModelFunctionConvert.java
diff --git a/yudao-module-iot/yudao-module-iot-api/src/main/java/cn/iocoder/yudao/module/iot/enums/ErrorCodeConstants.java b/yudao-module-iot/yudao-module-iot-api/src/main/java/cn/iocoder/yudao/module/iot/enums/ErrorCodeConstants.java
index 19ee8972d..d26e5f2ec 100644
--- a/yudao-module-iot/yudao-module-iot-api/src/main/java/cn/iocoder/yudao/module/iot/enums/ErrorCodeConstants.java
+++ b/yudao-module-iot/yudao-module-iot-api/src/main/java/cn/iocoder/yudao/module/iot/enums/ErrorCodeConstants.java
@@ -16,4 +16,5 @@ public interface ErrorCodeConstants {
// ========== IoT 产品物模型 1-050-002-000 ============
ErrorCode THINK_MODEL_FUNCTION_NOT_EXISTS = new ErrorCode(1_050_002_000, "产品物模型不存在");
+ ErrorCode THINK_MODEL_FUNCTION_EXISTS_BY_PRODUCT_KEY = new ErrorCode(1_050_002_001, "ProductKey 对应的产品物模型已存在");
}
diff --git a/yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/controller/admin/thinkmodelfunction/IotThinkModelFunctionController.http b/yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/controller/admin/thinkmodelfunction/IotThinkModelFunctionController.http
index bc0229bfb..b29ae8ddf 100644
--- a/yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/controller/admin/thinkmodelfunction/IotThinkModelFunctionController.http
+++ b/yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/controller/admin/thinkmodelfunction/IotThinkModelFunctionController.http
@@ -5,6 +5,7 @@ tenant-id: {{adminTenentId}}
Authorization: Bearer {{token}}
{
+ "productId": 1,
"productKey": "123456",
"properties": [
{
@@ -51,6 +52,8 @@ tenant-id: {{adminTenentId}}
Authorization: Bearer {{token}}
{
+ "id": 1,
+ "productId": 1,
"productKey": "123456",
"properties": [
{
@@ -90,7 +93,7 @@ Authorization: Bearer {{token}}
"events": "{}"
}
-### 请求 /iot/think-model-function/get 接口 => 成功
-GET {{baseUrl}}/iot/think-model-function/get?productKey=123456
+### 请求 /iot/think-model-function/get-by-product-key 接口 => 成功
+GET {{baseUrl}}/iot/think-model-function/get-by-product-key?productKey=123456
tenant-id: {{adminTenentId}}
Authorization: Bearer {{token}}
\ No newline at end of file
diff --git a/yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/controller/admin/thinkmodelfunction/IotThinkModelFunctionController.java b/yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/controller/admin/thinkmodelfunction/IotThinkModelFunctionController.java
index cebaca4f5..a0051d9eb 100644
--- a/yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/controller/admin/thinkmodelfunction/IotThinkModelFunctionController.java
+++ b/yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/controller/admin/thinkmodelfunction/IotThinkModelFunctionController.java
@@ -1,22 +1,21 @@
package cn.iocoder.yudao.module.iot.controller.admin.thinkmodelfunction;
-import org.springframework.web.bind.annotation.*;
-import jakarta.annotation.Resource;
-import org.springframework.validation.annotation.Validated;
-import org.springframework.security.access.prepost.PreAuthorize;
-import io.swagger.v3.oas.annotations.tags.Tag;
-import io.swagger.v3.oas.annotations.Parameter;
-import io.swagger.v3.oas.annotations.Operation;
-
-import jakarta.validation.*;
-
import cn.iocoder.yudao.framework.common.pojo.CommonResult;
-import cn.iocoder.yudao.framework.common.util.object.BeanUtils;
-import static cn.iocoder.yudao.framework.common.pojo.CommonResult.success;
-
-import cn.iocoder.yudao.module.iot.controller.admin.thinkmodelfunction.vo.*;
+import cn.iocoder.yudao.module.iot.controller.admin.thinkmodelfunction.vo.IotThinkModelFunctionRespVO;
+import cn.iocoder.yudao.module.iot.controller.admin.thinkmodelfunction.vo.IotThinkModelFunctionSaveReqVO;
+import cn.iocoder.yudao.module.iot.convert.thinkmodelfunction.IotThinkModelFunctionConvert;
import cn.iocoder.yudao.module.iot.dal.dataobject.thinkmodelfunction.IotThinkModelFunctionDO;
import cn.iocoder.yudao.module.iot.service.thinkmodelfunction.IotThinkModelFunctionService;
+import io.swagger.v3.oas.annotations.Operation;
+import io.swagger.v3.oas.annotations.Parameter;
+import io.swagger.v3.oas.annotations.tags.Tag;
+import jakarta.annotation.Resource;
+import jakarta.validation.Valid;
+import org.springframework.security.access.prepost.PreAuthorize;
+import org.springframework.validation.annotation.Validated;
+import org.springframework.web.bind.annotation.*;
+
+import static cn.iocoder.yudao.framework.common.pojo.CommonResult.success;
@Tag(name = "管理后台 - IoT 产品物模型")
@RestController
@@ -38,7 +37,7 @@ public class IotThinkModelFunctionController {
@Operation(summary = "更新IoT 产品物模型")
@PreAuthorize("@ss.hasPermission('iot:think-model-function:update')")
public CommonResult updateThinkModelFunction(@Valid @RequestBody IotThinkModelFunctionSaveReqVO updateReqVO) {
- thinkModelFunctionService.updateThinkModelFunctionByProductKey(updateReqVO);
+ thinkModelFunctionService.updateThinkModelFunction(updateReqVO);
return success(true);
}
@@ -51,13 +50,23 @@ public class IotThinkModelFunctionController {
return success(true);
}
- @GetMapping("/get")
+ @GetMapping("/get-by-product-key")
@Operation(summary = "获得IoT 产品物模型")
@Parameter(name = "productKey", description = "产品Key", required = true, example = "1024")
@PreAuthorize("@ss.hasPermission('iot:think-model-function:query')")
- public CommonResult getThinkModelFunctionByProductKey(@RequestParam("productKey") String productKey) {
+ public CommonResult getThinkModelFunctionByProductKey(@RequestParam("productKey") String productKey) {
IotThinkModelFunctionDO thinkModelFunction = thinkModelFunctionService.getThinkModelFunctionByProductKey(productKey);
- return success(BeanUtils.toBean(thinkModelFunction, IotThinkModelFunctionRespVO.class));
+ IotThinkModelFunctionRespVO respVO = IotThinkModelFunctionConvert.INSTANCE.convert(thinkModelFunction);
+ return success(respVO);
}
-}
\ No newline at end of file
+ @GetMapping("/get-by-product-id")
+ @Operation(summary = "获得IoT 产品物模型")
+ @Parameter(name = "productId", description = "产品ID", required = true, example = "1024")
+ @PreAuthorize("@ss.hasPermission('iot:think-model-function:query')")
+ public CommonResult getThinkModelFunctionByProductId(@RequestParam("productId") Long productId) {
+ IotThinkModelFunctionDO thinkModelFunction = thinkModelFunctionService.getThinkModelFunctionByProductId(productId);
+ IotThinkModelFunctionRespVO respVO = IotThinkModelFunctionConvert.INSTANCE.convert(thinkModelFunction);
+ return success(respVO);
+ }
+}
diff --git a/yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/controller/admin/thinkmodelfunction/vo/IotThinkModelFunctionRespVO.java b/yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/controller/admin/thinkmodelfunction/vo/IotThinkModelFunctionRespVO.java
index 74f7bfb6f..5d525e5b5 100644
--- a/yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/controller/admin/thinkmodelfunction/vo/IotThinkModelFunctionRespVO.java
+++ b/yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/controller/admin/thinkmodelfunction/vo/IotThinkModelFunctionRespVO.java
@@ -1,10 +1,12 @@
package cn.iocoder.yudao.module.iot.controller.admin.thinkmodelfunction.vo;
+import com.alibaba.excel.annotation.ExcelIgnoreUnannotated;
+import com.alibaba.excel.annotation.ExcelProperty;
import io.swagger.v3.oas.annotations.media.Schema;
-import lombok.*;
+import lombok.Data;
import java.time.LocalDateTime;
-import com.alibaba.excel.annotation.*;
+import java.util.List;
@Schema(description = "管理后台 - IoT 产品物模型 Response VO")
@Data
@@ -21,7 +23,7 @@ public class IotThinkModelFunctionRespVO {
@Schema(description = "属性列表", requiredMode = Schema.RequiredMode.REQUIRED)
@ExcelProperty("属性列表")
- private String properties;
+ private List properties;
@Schema(description = "服务列表")
@ExcelProperty("服务列表")
diff --git a/yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/controller/admin/thinkmodelfunction/vo/IotThinkModelFunctionSaveReqVO.java b/yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/controller/admin/thinkmodelfunction/vo/IotThinkModelFunctionSaveReqVO.java
index 200e7682c..705846210 100644
--- a/yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/controller/admin/thinkmodelfunction/vo/IotThinkModelFunctionSaveReqVO.java
+++ b/yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/controller/admin/thinkmodelfunction/vo/IotThinkModelFunctionSaveReqVO.java
@@ -9,6 +9,13 @@ import jakarta.validation.constraints.*;
@Data
public class IotThinkModelFunctionSaveReqVO {
+ @Schema(description = "编号", example = "1")
+ private Long id;
+
+ @Schema(description = "产品ID", requiredMode = Schema.RequiredMode.REQUIRED)
+ @NotNull(message = "产品ID不能为空")
+ private Long productId;
+
@Schema(description = "产品标识", requiredMode = Schema.RequiredMode.REQUIRED)
@NotEmpty(message = "产品标识不能为空")
private String productKey;
diff --git a/yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/convert/thinkmodelfunction/IotThinkModelFunctionConvert.java b/yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/convert/thinkmodelfunction/IotThinkModelFunctionConvert.java
new file mode 100644
index 000000000..783ef658a
--- /dev/null
+++ b/yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/convert/thinkmodelfunction/IotThinkModelFunctionConvert.java
@@ -0,0 +1,51 @@
+package cn.iocoder.yudao.module.iot.convert.thinkmodelfunction;
+
+import cn.hutool.json.JSONUtil;
+import cn.iocoder.yudao.module.iot.controller.admin.thinkmodelfunction.vo.IotThingModelProperty;
+import cn.iocoder.yudao.module.iot.controller.admin.thinkmodelfunction.vo.IotThinkModelFunctionRespVO;
+import cn.iocoder.yudao.module.iot.controller.admin.thinkmodelfunction.vo.IotThinkModelFunctionSaveReqVO;
+import cn.iocoder.yudao.module.iot.dal.dataobject.thinkmodelfunction.IotThinkModelFunctionDO;
+import org.mapstruct.AfterMapping;
+import org.mapstruct.Mapper;
+import org.mapstruct.Mapping;
+import org.mapstruct.MappingTarget;
+import org.mapstruct.factory.Mappers;
+
+import java.util.List;
+
+@Mapper
+public interface IotThinkModelFunctionConvert {
+
+ IotThinkModelFunctionConvert INSTANCE = Mappers.getMapper(IotThinkModelFunctionConvert.class);
+
+ // 将 SaveReqVO 转换为 DO
+ @Mapping(target = "properties", ignore = true)
+ IotThinkModelFunctionDO convert(IotThinkModelFunctionSaveReqVO bean);
+
+ // 将 DO 转换为 RespVO
+ @Mapping(target = "properties", ignore = true)
+ IotThinkModelFunctionRespVO convert(IotThinkModelFunctionDO bean);
+
+ // 处理 properties 字段的转换,从 VO 到 DO
+ @AfterMapping
+ default void convertPropertiesToDO(IotThinkModelFunctionSaveReqVO source, @MappingTarget IotThinkModelFunctionDO target) {
+ target.setProperties(JSONUtil.toJsonStr(source.getProperties()));
+ }
+
+ // 处理 properties 字段的转换,从 DO 到 VO
+ @AfterMapping
+ default void convertPropertiesToVO(IotThinkModelFunctionDO source, @MappingTarget IotThinkModelFunctionRespVO target) {
+ target.setProperties(JSONUtil.toList(source.getProperties(), IotThingModelProperty.class));
+ }
+
+ // 批量转换 DO 列表到 RespVO 列表
+ List convertList(List list);
+
+ // 批量转换处理 properties 字段
+ @AfterMapping
+ default void convertPropertiesListToVO(List sourceList, @MappingTarget List targetList) {
+ for (int i = 0; i < sourceList.size(); i++) {
+ convertPropertiesToVO(sourceList.get(i), targetList.get(i));
+ }
+ }
+}
diff --git a/yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/dal/dataobject/thinkmodelfunction/IotThinkModelFunctionDO.java b/yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/dal/dataobject/thinkmodelfunction/IotThinkModelFunctionDO.java
index 7d9ea4589..564eefb2b 100644
--- a/yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/dal/dataobject/thinkmodelfunction/IotThinkModelFunctionDO.java
+++ b/yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/dal/dataobject/thinkmodelfunction/IotThinkModelFunctionDO.java
@@ -1,8 +1,10 @@
package cn.iocoder.yudao.module.iot.dal.dataobject.thinkmodelfunction;
-import lombok.*;
-import com.baomidou.mybatisplus.annotation.*;
import cn.iocoder.yudao.framework.mybatis.core.dataobject.BaseDO;
+import com.baomidou.mybatisplus.annotation.KeySequence;
+import com.baomidou.mybatisplus.annotation.TableId;
+import com.baomidou.mybatisplus.annotation.TableName;
+import lombok.*;
/**
* IoT 产品物模型 DO
@@ -24,18 +26,27 @@ public class IotThinkModelFunctionDO extends BaseDO {
*/
@TableId
private Long id;
+
+ /**
+ * 产品标识
+ */
+ private Long productId;
+
/**
* 产品标识
*/
private String productKey;
+
/**
* 属性列表
*/
private String properties;
+
/**
* 服务列表
*/
private String services;
+
/**
* 事件列表
*/
diff --git a/yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/dal/mysql/thinkmodelfunction/IotThinkModelFunctionMapper.java b/yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/dal/mysql/thinkmodelfunction/IotThinkModelFunctionMapper.java
index 5475a723b..21ae1967a 100644
--- a/yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/dal/mysql/thinkmodelfunction/IotThinkModelFunctionMapper.java
+++ b/yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/dal/mysql/thinkmodelfunction/IotThinkModelFunctionMapper.java
@@ -17,9 +17,8 @@ public interface IotThinkModelFunctionMapper extends BaseMapperX().eq(IotThinkModelFunctionDO::getProductKey, productKey));
}
- default int updateByProductKey(IotThinkModelFunctionDO thinkModelFunction) {
- return update(thinkModelFunction, new LambdaQueryWrapperX()
- .eq(IotThinkModelFunctionDO::getProductKey, thinkModelFunction.getProductKey())
- );
+ default IotThinkModelFunctionDO selectByProductId(Long productId){
+ return selectOne(new LambdaQueryWrapperX().eq(IotThinkModelFunctionDO::getProductId, productId));
}
+
}
\ No newline at end of file
diff --git a/yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/service/thinkmodelfunction/IotThinkModelFunctionService.java b/yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/service/thinkmodelfunction/IotThinkModelFunctionService.java
index a52142810..d24ce0031 100644
--- a/yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/service/thinkmodelfunction/IotThinkModelFunctionService.java
+++ b/yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/service/thinkmodelfunction/IotThinkModelFunctionService.java
@@ -27,17 +27,25 @@ public interface IotThinkModelFunctionService {
void deleteThinkModelFunction(Long id);
/**
- * 获得IoT 产品物模型
+ * 获得IoT 产品物模型,通过产品Key
*
* @param productKey 产品Key
* @return IoT 产品物模型
*/
IotThinkModelFunctionDO getThinkModelFunctionByProductKey(String productKey);
+ /**
+ * 获得IoT 产品物模型,通过产品ID
+ *
+ * @param productId 产品ID
+ * @return IoT 产品物模型
+ */
+ IotThinkModelFunctionDO getThinkModelFunctionByProductId(Long productId);
+
/**
* 更新IoT 产品物模型
*
* @param updateReqVO 更新信息
*/
- void updateThinkModelFunctionByProductKey(@Valid IotThinkModelFunctionSaveReqVO updateReqVO);
+ void updateThinkModelFunction(@Valid IotThinkModelFunctionSaveReqVO updateReqVO);
}
\ No newline at end of file
diff --git a/yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/service/thinkmodelfunction/IotThinkModelFunctionServiceImpl.java b/yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/service/thinkmodelfunction/IotThinkModelFunctionServiceImpl.java
index 1f1355dd3..89c5f6b98 100644
--- a/yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/service/thinkmodelfunction/IotThinkModelFunctionServiceImpl.java
+++ b/yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/service/thinkmodelfunction/IotThinkModelFunctionServiceImpl.java
@@ -1,22 +1,20 @@
package cn.iocoder.yudao.module.iot.service.thinkmodelfunction;
-import cn.hutool.json.JSONUtil;
-import cn.iocoder.yudao.framework.common.util.object.BeanUtils;
+import cn.iocoder.yudao.framework.common.exception.ServiceException;
import cn.iocoder.yudao.module.iot.controller.admin.thinkmodelfunction.vo.IotThinkModelFunctionSaveReqVO;
+import cn.iocoder.yudao.module.iot.convert.thinkmodelfunction.IotThinkModelFunctionConvert;
import cn.iocoder.yudao.module.iot.dal.dataobject.thinkmodelfunction.IotThinkModelFunctionDO;
import cn.iocoder.yudao.module.iot.dal.mysql.thinkmodelfunction.IotThinkModelFunctionMapper;
import jakarta.annotation.Resource;
+import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Service;
import org.springframework.validation.annotation.Validated;
import static cn.iocoder.yudao.framework.common.exception.util.ServiceExceptionUtil.exception;
+import static cn.iocoder.yudao.module.iot.enums.ErrorCodeConstants.THINK_MODEL_FUNCTION_EXISTS_BY_PRODUCT_KEY;
import static cn.iocoder.yudao.module.iot.enums.ErrorCodeConstants.THINK_MODEL_FUNCTION_NOT_EXISTS;
-/**
- * IoT 产品物模型 Service 实现类
- *
- * @author 芋道源码
- */
+@Slf4j
@Service
@Validated
public class IotThinkModelFunctionServiceImpl implements IotThinkModelFunctionService {
@@ -26,17 +24,25 @@ public class IotThinkModelFunctionServiceImpl implements IotThinkModelFunctionSe
@Override
public Long createThinkModelFunction(IotThinkModelFunctionSaveReqVO createReqVO) {
+ log.info("创建物模型,参数:{}", createReqVO);
+ // 验证 ProductKey 对应的产品物模型是否已存在
+ validateThinkModelFunctionNotExistsByProductKey(createReqVO.getProductKey());
// 插入
- IotThinkModelFunctionDO thinkModelFunction = BeanUtils.toBean(createReqVO, IotThinkModelFunctionDO.class);
- // properties 字段,需要转换成 JSON
- thinkModelFunction.setProperties(JSONUtil.toJsonStr(createReqVO.getProperties()));
+ IotThinkModelFunctionDO thinkModelFunction = IotThinkModelFunctionConvert.INSTANCE.convert(createReqVO);
thinkModelFunctionMapper.insert(thinkModelFunction);
// 返回
return thinkModelFunction.getId();
}
+ private void validateThinkModelFunctionNotExistsByProductKey(String productKey) {
+ if (thinkModelFunctionMapper.selectByProductKey(productKey) != null) {
+ throw exception(THINK_MODEL_FUNCTION_EXISTS_BY_PRODUCT_KEY);
+ }
+ }
+
@Override
public void deleteThinkModelFunction(Long id) {
+ log.info("删除物模型,id:{}", id);
// 校验存在
validateThinkModelFunctionExists(id);
// 删除
@@ -49,26 +55,32 @@ public class IotThinkModelFunctionServiceImpl implements IotThinkModelFunctionSe
}
}
- private void validateThinkModelFunctionExistsByProductKey(String productKey) {
- if (thinkModelFunctionMapper.selectByProductKey(productKey) == null) {
- throw exception(THINK_MODEL_FUNCTION_NOT_EXISTS);
- }
- }
-
@Override
public IotThinkModelFunctionDO getThinkModelFunctionByProductKey(String productKey) {
return thinkModelFunctionMapper.selectByProductKey(productKey);
}
@Override
- public void updateThinkModelFunctionByProductKey(IotThinkModelFunctionSaveReqVO updateReqVO) {
- // 校验存在
- validateThinkModelFunctionExistsByProductKey(updateReqVO.getProductKey());
- // 更新
- IotThinkModelFunctionDO thinkModelFunction = BeanUtils.toBean(updateReqVO, IotThinkModelFunctionDO.class);
- // properties 字段,需要转换成 JSON
- thinkModelFunction.setProperties(JSONUtil.toJsonStr(updateReqVO.getProperties()));
- thinkModelFunctionMapper.updateByProductKey(thinkModelFunction);
+ public IotThinkModelFunctionDO getThinkModelFunctionByProductId(Long productId) {
+ return thinkModelFunctionMapper.selectByProductId(productId);
}
+ @Override
+ public void updateThinkModelFunction(IotThinkModelFunctionSaveReqVO updateReqVO) {
+ log.info("更新物模型,参数:{}", updateReqVO);
+ // 校验存在
+ validateThinkModelFunctionExists(updateReqVO.getId());
+ // 校验 productKey 是否重复
+ validateProductKeyUnique(updateReqVO.getId(), updateReqVO.getProductKey());
+ // 更新
+ IotThinkModelFunctionDO thinkModelFunction = IotThinkModelFunctionConvert.INSTANCE.convert(updateReqVO);
+ thinkModelFunctionMapper.updateById(thinkModelFunction);
+ }
+
+ private void validateProductKeyUnique(Long id, String productKey) {
+ IotThinkModelFunctionDO existingFunction = thinkModelFunctionMapper.selectByProductKey(productKey);
+ if (existingFunction != null && !existingFunction.getId().equals(id)) {
+ throw exception(THINK_MODEL_FUNCTION_EXISTS_BY_PRODUCT_KEY);
+ }
+ }
}
\ No newline at end of file
From 1f8576f6432fe5201497d2c3704de809d7185307 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?=E5=AE=89=E6=B5=A9=E6=B5=A9?= <1036606149@qq.com>
Date: Sat, 14 Sep 2024 00:35:43 +0800
Subject: [PATCH 028/156] =?UTF-8?q?=E4=BF=AE=E6=94=B9=EF=BC=9AIOT=20?=
=?UTF-8?q?=E6=A0=B9=E6=8D=AE=E5=B1=9E=E6=80=A7=E5=88=97=E8=A1=A8=EF=BC=8C?=
=?UTF-8?q?=E8=87=AA=E5=8A=A8=E7=94=9F=E6=88=90=E5=B1=9E=E6=80=A7=E4=B8=8A?=
=?UTF-8?q?=E6=8A=A5=E4=BA=8B=E4=BB=B6=E5=92=8C=E5=B1=9E=E6=80=A7=E8=AE=BE?=
=?UTF-8?q?=E7=BD=AE=E3=80=81=E8=8E=B7=E5=8F=96=E6=9C=8D=E5=8A=A1?=
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
---
.../IotThinkModelFunctionController.http | 265 +++++++++++++++---
.../thingModel/ThingModelArgument.java | 12 +
.../thingModel/ThingModelArraySpecs.java | 9 +
.../thingModel/ThingModelArrayType.java | 11 +
.../thingModel/ThingModelBoolType.java | 10 +
.../thingModel/ThingModelDataType.java | 22 ++
.../thingModel/ThingModelDateType.java | 10 +
.../thingModel/ThingModelDoubleType.java | 18 ++
.../thingModel/ThingModelEnumType.java | 11 +
.../thingModel/ThingModelEvent.java | 14 +
.../thingModel/ThingModelFloatType.java | 18 ++
.../thingModel/ThingModelIntType.java | 18 ++
.../thingModel/ThingModelProperty.java | 13 +
.../thingModel/ThingModelService.java | 15 +
.../thingModel/ThingModelStructField.java | 11 +
.../thingModel/ThingModelStructType.java | 13 +
.../thingModel/ThingModelTextType.java | 15 +
.../vo/IotThingModelProperty.java | 90 ------
.../vo/IotThinkModelFunctionRespVO.java | 9 +-
.../vo/IotThinkModelFunctionSaveReqVO.java | 17 +-
.../IotThinkModelFunctionConvert.java | 60 ++--
.../IotThinkModelFunctionServiceImpl.java | 176 +++++++++++-
22 files changed, 664 insertions(+), 173 deletions(-)
create mode 100644 yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/controller/admin/thinkmodelfunction/thingModel/ThingModelArgument.java
create mode 100644 yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/controller/admin/thinkmodelfunction/thingModel/ThingModelArraySpecs.java
create mode 100644 yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/controller/admin/thinkmodelfunction/thingModel/ThingModelArrayType.java
create mode 100644 yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/controller/admin/thinkmodelfunction/thingModel/ThingModelBoolType.java
create mode 100644 yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/controller/admin/thinkmodelfunction/thingModel/ThingModelDataType.java
create mode 100644 yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/controller/admin/thinkmodelfunction/thingModel/ThingModelDateType.java
create mode 100644 yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/controller/admin/thinkmodelfunction/thingModel/ThingModelDoubleType.java
create mode 100644 yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/controller/admin/thinkmodelfunction/thingModel/ThingModelEnumType.java
create mode 100644 yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/controller/admin/thinkmodelfunction/thingModel/ThingModelEvent.java
create mode 100644 yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/controller/admin/thinkmodelfunction/thingModel/ThingModelFloatType.java
create mode 100644 yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/controller/admin/thinkmodelfunction/thingModel/ThingModelIntType.java
create mode 100644 yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/controller/admin/thinkmodelfunction/thingModel/ThingModelProperty.java
create mode 100644 yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/controller/admin/thinkmodelfunction/thingModel/ThingModelService.java
create mode 100644 yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/controller/admin/thinkmodelfunction/thingModel/ThingModelStructField.java
create mode 100644 yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/controller/admin/thinkmodelfunction/thingModel/ThingModelStructType.java
create mode 100644 yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/controller/admin/thinkmodelfunction/thingModel/ThingModelTextType.java
delete mode 100644 yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/controller/admin/thinkmodelfunction/vo/IotThingModelProperty.java
diff --git a/yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/controller/admin/thinkmodelfunction/IotThinkModelFunctionController.http b/yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/controller/admin/thinkmodelfunction/IotThinkModelFunctionController.http
index b29ae8ddf..e31540710 100644
--- a/yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/controller/admin/thinkmodelfunction/IotThinkModelFunctionController.http
+++ b/yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/controller/admin/thinkmodelfunction/IotThinkModelFunctionController.http
@@ -5,46 +5,140 @@ tenant-id: {{adminTenentId}}
Authorization: Bearer {{token}}
{
- "productId": 1,
- "productKey": "123456",
+ "productId": 1002,
+ "productKey": "smart-sensor-002",
"properties": [
{
- "identifier": "CurrentTemperature",
- "name": "当前温度",
+ "identifier": "Temperature",
+ "name": "温度",
"accessMode": "r",
"required": true,
"dataType": {
"type": "float",
"specs": {
- "min": "-40",
- "max": "120",
- "unit": "°C",
- "unitName": "摄氏度",
- "step": "0.1"
+ "min": -40.0,
+ "max": 125.0,
+ "step": 0.1,
+ "unit": "℃"
}
- }
+ },
+ "description": "当前温度值"
},
{
- "identifier": "CurrentHumidity",
- "name": "当前湿度",
+ "identifier": "Humidity",
+ "name": "湿度",
"accessMode": "r",
"required": true,
"dataType": {
"type": "float",
"specs": {
- "min": "0",
- "max": "100",
- "unit": "%",
- "unitName": "百分比",
- "step": "0.1"
+ "min": 0.0,
+ "max": 100.0,
+ "step": 0.1,
+ "unit": "%"
}
- }
+ },
+ "description": "当前湿度值"
+ },
+ {
+ "identifier": "GeoLocation",
+ "name": "地理位置",
+ "accessMode": "r",
+ "required": false,
+ "dataType": {
+ "type": "struct",
+ "specs": [
+ {
+ "identifier": "Longitude",
+ "name": "经度",
+ "dataType": {
+ "type": "double",
+ "specs": {
+ "min": -180.0,
+ "max": 180.0,
+ "step": 0.000001,
+ "unit": "°"
+ }
+ },
+ "description": "设备所在位置的经度"
+ },
+ {
+ "identifier": "Latitude",
+ "name": "纬度",
+ "dataType": {
+ "type": "double",
+ "specs": {
+ "min": -90.0,
+ "max": 90.0,
+ "step": 0.000001,
+ "unit": "°"
+ }
+ },
+ "description": "设备所在位置的纬度"
+ }
+ ]
+ },
+ "description": "设备的地理位置信息"
}
],
- "services": "{}",
- "events": "{}"
+ "services": [
+ {
+ "identifier": "Reboot",
+ "name": "重启设备",
+ "callType": "async",
+ "inputData": [],
+ "description": "远程重启设备",
+ "method": "thing.service.reboot"
+ },
+ {
+ "identifier": "SetThreshold",
+ "name": "设置温度阈值",
+ "callType": "sync",
+ "inputData": [
+ {
+ "identifier": "Threshold",
+ "name": "阈值",
+ "dataType": {
+ "type": "float",
+ "specs": {
+ "min": -40.0,
+ "max": 125.0,
+ "step": 0.1,
+ "unit": "℃"
+ }
+ },
+ "description": "报警温度阈值"
+ }
+ ],
+ "description": "设置设备的温度报警阈值",
+ "method": "thing.service.setThreshold"
+ }
+ ],
+ "events": [
+ {
+ "identifier": "HighTemperatureAlert",
+ "name": "高温报警",
+ "type": "alert",
+ "outputData": [
+ {
+ "identifier": "CurrentTemperature",
+ "name": "当前温度",
+ "dataType": {
+ "type": "float",
+ "specs": {
+ "unit": "℃"
+ }
+ },
+ "description": "触发报警时的温度值"
+ }
+ ],
+ "description": "当温度超过阈值时触发高温报警事件",
+ "method": "thing.event.highTemperatureAlert"
+ }
+ ]
}
+
### 请求 /iot/think-model-function/update 接口 => 成功
PUT {{baseUrl}}/iot/think-model-function/update
Content-Type: application/json
@@ -53,46 +147,137 @@ Authorization: Bearer {{token}}
{
"id": 1,
- "productId": 1,
- "productKey": "123456",
+ "productId": 1001,
+ "productKey": "smart-sensor-001",
"properties": [
{
- "identifier": "CurrentTemperature",
- "name": "当前温度",
+ "identifier": "Temperature",
+ "name": "温度",
"accessMode": "r",
"required": true,
"dataType": {
"type": "float",
"specs": {
- "min": "-40",
- "max": "130",
- "unit": "°C",
- "unitName": "摄氏度",
- "step": "0.1"
+ "min": -40.0,
+ "max": 125.0,
+ "step": 0.1,
+ "unit": "℃"
}
- }
+ },
+ "description": "当前温度值"
},
{
- "identifier": "CurrentHumidity",
- "name": "当前湿度",
+ "identifier": "Humidity",
+ "name": "湿度",
"accessMode": "r",
"required": true,
"dataType": {
"type": "float",
"specs": {
- "min": "0",
- "max": "100",
- "unit": "%",
- "unitName": "百分比",
- "step": "0.1"
+ "min": 0.0,
+ "max": 100.0,
+ "step": 0.1,
+ "unit": "%"
}
- }
+ },
+ "description": "当前湿度值"
+ },
+ {
+ "identifier": "GeoLocation",
+ "name": "地理位置",
+ "accessMode": "r",
+ "required": false,
+ "dataType": {
+ "type": "struct",
+ "specs": [
+ {
+ "identifier": "Longitude",
+ "name": "经度",
+ "dataType": {
+ "type": "double",
+ "specs": {
+ "min": -180.0,
+ "max": 180.0,
+ "step": 0.000001,
+ "unit": "°"
+ }
+ },
+ "description": "设备所在位置的经度"
+ },
+ {
+ "identifier": "Latitude",
+ "name": "纬度",
+ "dataType": {
+ "type": "double",
+ "specs": {
+ "min": -90.0,
+ "max": 90.0,
+ "step": 0.000001,
+ "unit": "°"
+ }
+ },
+ "description": "设备所在位置的纬度"
+ }
+ ]
+ },
+ "description": "设备的地理位置信息"
}
],
- "services": "{}",
- "events": "{}"
+ "services": [
+ {
+ "identifier": "Reboot",
+ "name": "重启设备",
+ "callType": "async",
+ "inputData": [],
+ "description": "远程重启设备"
+ },
+ {
+ "identifier": "SetThreshold",
+ "name": "设置温度阈值",
+ "callType": "sync",
+ "inputData": [
+ {
+ "identifier": "Threshold",
+ "name": "阈值",
+ "dataType": {
+ "type": "float",
+ "specs": {
+ "min": -40.0,
+ "max": 125.0,
+ "step": 0.1,
+ "unit": "℃"
+ }
+ },
+ "description": "报警温度阈值"
+ }
+ ],
+ "description": "设置设备的温度报警阈值"
+ }
+ ],
+ "events": [
+ {
+ "identifier": "HighTemperatureAlert",
+ "name": "高温报警",
+ "type": "alert",
+ "outputData": [
+ {
+ "identifier": "CurrentTemperature",
+ "name": "当前温度",
+ "dataType": {
+ "type": "float",
+ "specs": {
+ "unit": "℃"
+ }
+ },
+ "description": "触发报警时的温度值"
+ }
+ ],
+ "description": "当温度超过阈值时触发高温报警事件"
+ }
+ ]
}
+
### 请求 /iot/think-model-function/get-by-product-key 接口 => 成功
GET {{baseUrl}}/iot/think-model-function/get-by-product-key?productKey=123456
tenant-id: {{adminTenentId}}
diff --git a/yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/controller/admin/thinkmodelfunction/thingModel/ThingModelArgument.java b/yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/controller/admin/thinkmodelfunction/thingModel/ThingModelArgument.java
new file mode 100644
index 000000000..909d63459
--- /dev/null
+++ b/yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/controller/admin/thinkmodelfunction/thingModel/ThingModelArgument.java
@@ -0,0 +1,12 @@
+package cn.iocoder.yudao.module.iot.controller.admin.thinkmodelfunction.thingModel;
+
+import lombok.Data;
+
+@Data
+public class ThingModelArgument {
+ private String identifier;
+ private String name;
+ private ThingModelDataType dataType;
+ private String direction; // 用于区分输入或输出参数,"input" 或 "output"
+ private String description;
+}
diff --git a/yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/controller/admin/thinkmodelfunction/thingModel/ThingModelArraySpecs.java b/yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/controller/admin/thinkmodelfunction/thingModel/ThingModelArraySpecs.java
new file mode 100644
index 000000000..3ea23e8db
--- /dev/null
+++ b/yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/controller/admin/thinkmodelfunction/thingModel/ThingModelArraySpecs.java
@@ -0,0 +1,9 @@
+package cn.iocoder.yudao.module.iot.controller.admin.thinkmodelfunction.thingModel;
+
+import lombok.Data;
+
+@Data
+public class ThingModelArraySpecs {
+ private int size; // 数组长度
+ private ThingModelDataType item; // 数组元素的类型
+}
diff --git a/yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/controller/admin/thinkmodelfunction/thingModel/ThingModelArrayType.java b/yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/controller/admin/thinkmodelfunction/thingModel/ThingModelArrayType.java
new file mode 100644
index 000000000..114add210
--- /dev/null
+++ b/yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/controller/admin/thinkmodelfunction/thingModel/ThingModelArrayType.java
@@ -0,0 +1,11 @@
+package cn.iocoder.yudao.module.iot.controller.admin.thinkmodelfunction.thingModel;
+
+import lombok.Data;
+import lombok.EqualsAndHashCode;
+
+@Data
+@EqualsAndHashCode(callSuper = true)
+public class ThingModelArrayType extends ThingModelDataType {
+ private ThingModelArraySpecs specs;
+}
+
diff --git a/yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/controller/admin/thinkmodelfunction/thingModel/ThingModelBoolType.java b/yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/controller/admin/thinkmodelfunction/thingModel/ThingModelBoolType.java
new file mode 100644
index 000000000..f7e7e456b
--- /dev/null
+++ b/yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/controller/admin/thinkmodelfunction/thingModel/ThingModelBoolType.java
@@ -0,0 +1,10 @@
+package cn.iocoder.yudao.module.iot.controller.admin.thinkmodelfunction.thingModel;
+
+import lombok.Data;
+import lombok.EqualsAndHashCode;
+
+@Data
+@EqualsAndHashCode(callSuper = true)
+public class ThingModelBoolType extends ThingModelDataType {
+ // Bool 类型一般不需要额外的 specs
+}
diff --git a/yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/controller/admin/thinkmodelfunction/thingModel/ThingModelDataType.java b/yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/controller/admin/thinkmodelfunction/thingModel/ThingModelDataType.java
new file mode 100644
index 000000000..613cbd766
--- /dev/null
+++ b/yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/controller/admin/thinkmodelfunction/thingModel/ThingModelDataType.java
@@ -0,0 +1,22 @@
+package cn.iocoder.yudao.module.iot.controller.admin.thinkmodelfunction.thingModel;
+
+import com.fasterxml.jackson.annotation.JsonSubTypes;
+import com.fasterxml.jackson.annotation.JsonTypeInfo;
+import lombok.Data;
+
+@Data
+@JsonTypeInfo(use = JsonTypeInfo.Id.NAME, property = "type", visible = true)
+@JsonSubTypes({
+ @JsonSubTypes.Type(value = ThingModelIntType.class, name = "int"),
+ @JsonSubTypes.Type(value = ThingModelFloatType.class, name = "float"),
+ @JsonSubTypes.Type(value = ThingModelDoubleType.class, name = "double"),
+ @JsonSubTypes.Type(value = ThingModelTextType.class, name = "text"),
+ @JsonSubTypes.Type(value = ThingModelDateType.class, name = "date"),
+ @JsonSubTypes.Type(value = ThingModelBoolType.class, name = "bool"),
+ @JsonSubTypes.Type(value = ThingModelEnumType.class, name = "enum"),
+ @JsonSubTypes.Type(value = ThingModelStructType.class, name = "struct"),
+ @JsonSubTypes.Type(value = ThingModelArrayType.class, name = "array")
+})
+public abstract class ThingModelDataType {
+ private String type;
+}
diff --git a/yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/controller/admin/thinkmodelfunction/thingModel/ThingModelDateType.java b/yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/controller/admin/thinkmodelfunction/thingModel/ThingModelDateType.java
new file mode 100644
index 000000000..11cb3a729
--- /dev/null
+++ b/yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/controller/admin/thinkmodelfunction/thingModel/ThingModelDateType.java
@@ -0,0 +1,10 @@
+package cn.iocoder.yudao.module.iot.controller.admin.thinkmodelfunction.thingModel;
+
+import lombok.Data;
+import lombok.EqualsAndHashCode;
+
+@Data
+@EqualsAndHashCode(callSuper = true)
+public class ThingModelDateType extends ThingModelDataType {
+ // Date 类型一般不需要额外的 specs
+}
diff --git a/yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/controller/admin/thinkmodelfunction/thingModel/ThingModelDoubleType.java b/yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/controller/admin/thinkmodelfunction/thingModel/ThingModelDoubleType.java
new file mode 100644
index 000000000..d60302179
--- /dev/null
+++ b/yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/controller/admin/thinkmodelfunction/thingModel/ThingModelDoubleType.java
@@ -0,0 +1,18 @@
+package cn.iocoder.yudao.module.iot.controller.admin.thinkmodelfunction.thingModel;
+
+import lombok.Data;
+import lombok.EqualsAndHashCode;
+
+@Data
+@EqualsAndHashCode(callSuper = true)
+public class ThingModelDoubleType extends ThingModelDataType {
+ private ThingModelDoubleSpecs specs;
+}
+
+@Data
+class ThingModelDoubleSpecs {
+ private Double min;
+ private Double max;
+ private Double step;
+ private String unit;
+}
diff --git a/yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/controller/admin/thinkmodelfunction/thingModel/ThingModelEnumType.java b/yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/controller/admin/thinkmodelfunction/thingModel/ThingModelEnumType.java
new file mode 100644
index 000000000..f76962661
--- /dev/null
+++ b/yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/controller/admin/thinkmodelfunction/thingModel/ThingModelEnumType.java
@@ -0,0 +1,11 @@
+package cn.iocoder.yudao.module.iot.controller.admin.thinkmodelfunction.thingModel;
+
+import lombok.Data;
+import lombok.EqualsAndHashCode;
+import java.util.Map;
+
+@Data
+@EqualsAndHashCode(callSuper = true)
+public class ThingModelEnumType extends ThingModelDataType {
+ private Map specs; // 枚举值和描述的键值对
+}
diff --git a/yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/controller/admin/thinkmodelfunction/thingModel/ThingModelEvent.java b/yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/controller/admin/thinkmodelfunction/thingModel/ThingModelEvent.java
new file mode 100644
index 000000000..857f688e9
--- /dev/null
+++ b/yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/controller/admin/thinkmodelfunction/thingModel/ThingModelEvent.java
@@ -0,0 +1,14 @@
+package cn.iocoder.yudao.module.iot.controller.admin.thinkmodelfunction.thingModel;
+
+import lombok.Data;
+import java.util.List;
+
+@Data
+public class ThingModelEvent {
+ private String identifier;
+ private String name;
+ private String type; // "info"、"alert"、"error"
+ private List outputData;
+ private String description;
+ private String method;
+}
diff --git a/yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/controller/admin/thinkmodelfunction/thingModel/ThingModelFloatType.java b/yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/controller/admin/thinkmodelfunction/thingModel/ThingModelFloatType.java
new file mode 100644
index 000000000..c9d5516ad
--- /dev/null
+++ b/yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/controller/admin/thinkmodelfunction/thingModel/ThingModelFloatType.java
@@ -0,0 +1,18 @@
+package cn.iocoder.yudao.module.iot.controller.admin.thinkmodelfunction.thingModel;
+
+import lombok.Data;
+import lombok.EqualsAndHashCode;
+
+@Data
+@EqualsAndHashCode(callSuper = true)
+public class ThingModelFloatType extends ThingModelDataType {
+ private ThingModelFloatSpecs specs;
+}
+
+@Data
+class ThingModelFloatSpecs {
+ private Float min;
+ private Float max;
+ private Float step;
+ private String unit;
+}
diff --git a/yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/controller/admin/thinkmodelfunction/thingModel/ThingModelIntType.java b/yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/controller/admin/thinkmodelfunction/thingModel/ThingModelIntType.java
new file mode 100644
index 000000000..d48f50e47
--- /dev/null
+++ b/yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/controller/admin/thinkmodelfunction/thingModel/ThingModelIntType.java
@@ -0,0 +1,18 @@
+package cn.iocoder.yudao.module.iot.controller.admin.thinkmodelfunction.thingModel;
+
+import lombok.Data;
+import lombok.EqualsAndHashCode;
+
+@Data
+@EqualsAndHashCode(callSuper = true)
+public class ThingModelIntType extends ThingModelDataType {
+ private ThingModelIntSpecs specs;
+}
+
+@Data
+class ThingModelIntSpecs {
+ private Integer min;
+ private Integer max;
+ private Integer step;
+ private String unit;
+}
diff --git a/yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/controller/admin/thinkmodelfunction/thingModel/ThingModelProperty.java b/yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/controller/admin/thinkmodelfunction/thingModel/ThingModelProperty.java
new file mode 100644
index 000000000..f82198152
--- /dev/null
+++ b/yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/controller/admin/thinkmodelfunction/thingModel/ThingModelProperty.java
@@ -0,0 +1,13 @@
+package cn.iocoder.yudao.module.iot.controller.admin.thinkmodelfunction.thingModel;
+
+import lombok.Data;
+
+@Data
+public class ThingModelProperty {
+ private String identifier;
+ private String name;
+ private String accessMode; // "rw"、"r"、"w"
+ private boolean required;
+ private ThingModelDataType dataType;
+ private String description;
+}
diff --git a/yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/controller/admin/thinkmodelfunction/thingModel/ThingModelService.java b/yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/controller/admin/thinkmodelfunction/thingModel/ThingModelService.java
new file mode 100644
index 000000000..521e9ab08
--- /dev/null
+++ b/yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/controller/admin/thinkmodelfunction/thingModel/ThingModelService.java
@@ -0,0 +1,15 @@
+package cn.iocoder.yudao.module.iot.controller.admin.thinkmodelfunction.thingModel;
+
+import lombok.Data;
+import java.util.List;
+
+@Data
+public class ThingModelService {
+ private String identifier;
+ private String name;
+ private String callType; // "sync"、"async"
+ private List inputData;
+ private List outputData;
+ private String description;
+ private String method;
+}
diff --git a/yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/controller/admin/thinkmodelfunction/thingModel/ThingModelStructField.java b/yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/controller/admin/thinkmodelfunction/thingModel/ThingModelStructField.java
new file mode 100644
index 000000000..449db55c2
--- /dev/null
+++ b/yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/controller/admin/thinkmodelfunction/thingModel/ThingModelStructField.java
@@ -0,0 +1,11 @@
+package cn.iocoder.yudao.module.iot.controller.admin.thinkmodelfunction.thingModel;
+
+import lombok.Data;
+
+@Data
+public class ThingModelStructField {
+ private String identifier;
+ private String name;
+ private ThingModelDataType dataType;
+ private String description;
+}
\ No newline at end of file
diff --git a/yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/controller/admin/thinkmodelfunction/thingModel/ThingModelStructType.java b/yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/controller/admin/thinkmodelfunction/thingModel/ThingModelStructType.java
new file mode 100644
index 000000000..d3d35f16c
--- /dev/null
+++ b/yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/controller/admin/thinkmodelfunction/thingModel/ThingModelStructType.java
@@ -0,0 +1,13 @@
+package cn.iocoder.yudao.module.iot.controller.admin.thinkmodelfunction.thingModel;
+
+import lombok.Data;
+import lombok.EqualsAndHashCode;
+import java.util.List;
+
+@Data
+@EqualsAndHashCode(callSuper = true)
+public class ThingModelStructType extends ThingModelDataType {
+ private List specs;
+}
+
+
diff --git a/yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/controller/admin/thinkmodelfunction/thingModel/ThingModelTextType.java b/yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/controller/admin/thinkmodelfunction/thingModel/ThingModelTextType.java
new file mode 100644
index 000000000..0f6ea2bcb
--- /dev/null
+++ b/yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/controller/admin/thinkmodelfunction/thingModel/ThingModelTextType.java
@@ -0,0 +1,15 @@
+package cn.iocoder.yudao.module.iot.controller.admin.thinkmodelfunction.thingModel;
+
+import lombok.Data;
+import lombok.EqualsAndHashCode;
+
+@Data
+@EqualsAndHashCode(callSuper = true)
+public class ThingModelTextType extends ThingModelDataType {
+ private ThingModelTextSpecs specs;
+}
+
+@Data
+class ThingModelTextSpecs {
+ private Integer length; // 最大长度
+}
diff --git a/yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/controller/admin/thinkmodelfunction/vo/IotThingModelProperty.java b/yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/controller/admin/thinkmodelfunction/vo/IotThingModelProperty.java
deleted file mode 100644
index 0187ae514..000000000
--- a/yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/controller/admin/thinkmodelfunction/vo/IotThingModelProperty.java
+++ /dev/null
@@ -1,90 +0,0 @@
-package cn.iocoder.yudao.module.iot.controller.admin.thinkmodelfunction.vo;
-
-import io.swagger.v3.oas.annotations.media.Schema;
-import lombok.Data;
-
-import java.util.List;
-
-@Schema(description = "管理后台 - IoT 产品物模型属性")
-@Data
-public class IotThingModelProperty {
-
- @Schema(description = "属性标识符")
- private String identifier;
-
- @Schema(description = "属性名称")
- private String name;
-
- @Schema(description = "访问模式 (r/rw)")
- private String accessMode;
-
- @Schema(description = "是否必需")
- private boolean required;
-
- @Schema(description = "数据类型")
- private DataType dataType;
-
- @Schema(description = "数据类型")
- @Data
- public static class DataType {
-
- @Schema(description = "数据类型(float, double, struct, enum等)")
- private String type;
-
- @Schema(description = "单一类型的规格(适用于float, double等)")
- private Specs specs;
-
- @Schema(description = "结构体字段(适用于struct类型)")
- private List structSpecs;
-
- @Schema(description = "规格")
- @Data
- public static class Specs {
-
- @Schema(description = "最小值")
- private String min;
-
- @Schema(description = "最大值")
- private String max;
-
- @Schema(description = "单位符号")
- private String unit;
-
- @Schema(description = "单位名称")
- private String unitName;
-
- @Schema(description = "步进值")
- private String step;
- }
-
- @Schema(description = "结构体字段")
- @Data
- public static class StructField {
-
- @Schema(description = "字段标识符")
- private String identifier;
-
- @Schema(description = "字段名称")
- private String name;
-
- @Schema(description = "字段的数据类型")
- private DataType dataType;
- }
- }
-
- @Schema(description = "枚举规格")
- @Data
- public static class EnumSpecs {
-
- @Schema(description = "枚举值")
- private int value;
-
- @Schema(description = "枚举名称")
- private String name;
-
- public EnumSpecs(int value, String name) {
- this.value = value;
- this.name = name;
- }
- }
-}
diff --git a/yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/controller/admin/thinkmodelfunction/vo/IotThinkModelFunctionRespVO.java b/yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/controller/admin/thinkmodelfunction/vo/IotThinkModelFunctionRespVO.java
index 5d525e5b5..42ac727a4 100644
--- a/yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/controller/admin/thinkmodelfunction/vo/IotThinkModelFunctionRespVO.java
+++ b/yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/controller/admin/thinkmodelfunction/vo/IotThinkModelFunctionRespVO.java
@@ -1,5 +1,8 @@
package cn.iocoder.yudao.module.iot.controller.admin.thinkmodelfunction.vo;
+import cn.iocoder.yudao.module.iot.controller.admin.thinkmodelfunction.thingModel.ThingModelEvent;
+import cn.iocoder.yudao.module.iot.controller.admin.thinkmodelfunction.thingModel.ThingModelProperty;
+import cn.iocoder.yudao.module.iot.controller.admin.thinkmodelfunction.thingModel.ThingModelService;
import com.alibaba.excel.annotation.ExcelIgnoreUnannotated;
import com.alibaba.excel.annotation.ExcelProperty;
import io.swagger.v3.oas.annotations.media.Schema;
@@ -23,15 +26,15 @@ public class IotThinkModelFunctionRespVO {
@Schema(description = "属性列表", requiredMode = Schema.RequiredMode.REQUIRED)
@ExcelProperty("属性列表")
- private List properties;
+ private List properties;
@Schema(description = "服务列表")
@ExcelProperty("服务列表")
- private String services;
+ private List services;
@Schema(description = "事件列表")
@ExcelProperty("事件列表")
- private String events;
+ private List events;
@Schema(description = "创建时间", requiredMode = Schema.RequiredMode.REQUIRED)
@ExcelProperty("创建时间")
diff --git a/yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/controller/admin/thinkmodelfunction/vo/IotThinkModelFunctionSaveReqVO.java b/yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/controller/admin/thinkmodelfunction/vo/IotThinkModelFunctionSaveReqVO.java
index 705846210..00132fa8b 100644
--- a/yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/controller/admin/thinkmodelfunction/vo/IotThinkModelFunctionSaveReqVO.java
+++ b/yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/controller/admin/thinkmodelfunction/vo/IotThinkModelFunctionSaveReqVO.java
@@ -1,9 +1,14 @@
package cn.iocoder.yudao.module.iot.controller.admin.thinkmodelfunction.vo;
+import cn.iocoder.yudao.module.iot.controller.admin.thinkmodelfunction.thingModel.ThingModelEvent;
+import cn.iocoder.yudao.module.iot.controller.admin.thinkmodelfunction.thingModel.ThingModelProperty;
+import cn.iocoder.yudao.module.iot.controller.admin.thinkmodelfunction.thingModel.ThingModelService;
import io.swagger.v3.oas.annotations.media.Schema;
-import lombok.*;
-import java.util.*;
-import jakarta.validation.constraints.*;
+import jakarta.validation.constraints.NotEmpty;
+import jakarta.validation.constraints.NotNull;
+import lombok.Data;
+
+import java.util.List;
@Schema(description = "管理后台 - IoT 产品物模型新增/修改 Request VO")
@Data
@@ -22,12 +27,12 @@ public class IotThinkModelFunctionSaveReqVO {
@Schema(description = "属性列表", requiredMode = Schema.RequiredMode.REQUIRED)
@NotEmpty(message = "属性列表不能为空")
- private List properties;
+ private List properties;
@Schema(description = "服务列表")
- private String services;
+ private List services;
@Schema(description = "事件列表")
- private String events;
+ private List events;
}
\ No newline at end of file
diff --git a/yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/convert/thinkmodelfunction/IotThinkModelFunctionConvert.java b/yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/convert/thinkmodelfunction/IotThinkModelFunctionConvert.java
index 783ef658a..41e0c583b 100644
--- a/yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/convert/thinkmodelfunction/IotThinkModelFunctionConvert.java
+++ b/yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/convert/thinkmodelfunction/IotThinkModelFunctionConvert.java
@@ -1,16 +1,17 @@
package cn.iocoder.yudao.module.iot.convert.thinkmodelfunction;
import cn.hutool.json.JSONUtil;
-import cn.iocoder.yudao.module.iot.controller.admin.thinkmodelfunction.vo.IotThingModelProperty;
+import cn.iocoder.yudao.module.iot.controller.admin.thinkmodelfunction.thingModel.ThingModelEvent;
+import cn.iocoder.yudao.module.iot.controller.admin.thinkmodelfunction.thingModel.ThingModelProperty;
+import cn.iocoder.yudao.module.iot.controller.admin.thinkmodelfunction.thingModel.ThingModelService;
import cn.iocoder.yudao.module.iot.controller.admin.thinkmodelfunction.vo.IotThinkModelFunctionRespVO;
import cn.iocoder.yudao.module.iot.controller.admin.thinkmodelfunction.vo.IotThinkModelFunctionSaveReqVO;
import cn.iocoder.yudao.module.iot.dal.dataobject.thinkmodelfunction.IotThinkModelFunctionDO;
-import org.mapstruct.AfterMapping;
import org.mapstruct.Mapper;
import org.mapstruct.Mapping;
-import org.mapstruct.MappingTarget;
import org.mapstruct.factory.Mappers;
+import java.util.ArrayList;
import java.util.List;
@Mapper
@@ -18,34 +19,43 @@ public interface IotThinkModelFunctionConvert {
IotThinkModelFunctionConvert INSTANCE = Mappers.getMapper(IotThinkModelFunctionConvert.class);
- // 将 SaveReqVO 转换为 DO
- @Mapping(target = "properties", ignore = true)
+ // 将 SaveReqVO 转换为 DO 对象,处理 properties, services, events 字段
+ @Mapping(target = "properties", expression = "java(convertPropertiesToJson(bean.getProperties()))")
+ @Mapping(target = "services", expression = "java(convertServicesToJson(bean.getServices()))")
+ @Mapping(target = "events", expression = "java(convertEventsToJson(bean.getEvents()))")
IotThinkModelFunctionDO convert(IotThinkModelFunctionSaveReqVO bean);
- // 将 DO 转换为 RespVO
- @Mapping(target = "properties", ignore = true)
- IotThinkModelFunctionRespVO convert(IotThinkModelFunctionDO bean);
-
- // 处理 properties 字段的转换,从 VO 到 DO
- @AfterMapping
- default void convertPropertiesToDO(IotThinkModelFunctionSaveReqVO source, @MappingTarget IotThinkModelFunctionDO target) {
- target.setProperties(JSONUtil.toJsonStr(source.getProperties()));
+ default String convertPropertiesToJson(List properties) {
+ return properties != null ? JSONUtil.toJsonStr(properties) : "[]";
}
- // 处理 properties 字段的转换,从 DO 到 VO
- @AfterMapping
- default void convertPropertiesToVO(IotThinkModelFunctionDO source, @MappingTarget IotThinkModelFunctionRespVO target) {
- target.setProperties(JSONUtil.toList(source.getProperties(), IotThingModelProperty.class));
+ default String convertServicesToJson(List services) {
+ return services != null ? JSONUtil.toJsonStr(services) : "[]";
+ }
+
+ default String convertEventsToJson(List events) {
+ return events != null ? JSONUtil.toJsonStr(events) : "[]";
+ }
+
+ // 将 DO 转换为 RespVO 对象,处理 properties, services, events 字段
+ @Mapping(target = "properties", expression = "java(convertJsonToProperties(bean.getProperties()))")
+ @Mapping(target = "services", expression = "java(convertJsonToServices(bean.getServices()))")
+ @Mapping(target = "events", expression = "java(convertJsonToEvents(bean.getEvents()))")
+ IotThinkModelFunctionRespVO convert(IotThinkModelFunctionDO bean);
+
+ default List convertJsonToProperties(String propertiesJson) {
+ return propertiesJson != null ? JSONUtil.toList(propertiesJson, ThingModelProperty.class) : new ArrayList<>();
+ }
+
+ default List convertJsonToServices(String servicesJson) {
+ return servicesJson != null ? JSONUtil.toList(servicesJson, ThingModelService.class) : new ArrayList<>();
+ }
+
+ default List convertJsonToEvents(String eventsJson) {
+ return eventsJson != null ? JSONUtil.toList(eventsJson, ThingModelEvent.class) : new ArrayList<>();
}
// 批量转换 DO 列表到 RespVO 列表
List convertList(List list);
-
- // 批量转换处理 properties 字段
- @AfterMapping
- default void convertPropertiesListToVO(List sourceList, @MappingTarget List targetList) {
- for (int i = 0; i < sourceList.size(); i++) {
- convertPropertiesToVO(sourceList.get(i), targetList.get(i));
- }
- }
}
+
diff --git a/yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/service/thinkmodelfunction/IotThinkModelFunctionServiceImpl.java b/yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/service/thinkmodelfunction/IotThinkModelFunctionServiceImpl.java
index 89c5f6b98..66fc01779 100644
--- a/yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/service/thinkmodelfunction/IotThinkModelFunctionServiceImpl.java
+++ b/yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/service/thinkmodelfunction/IotThinkModelFunctionServiceImpl.java
@@ -1,6 +1,7 @@
package cn.iocoder.yudao.module.iot.service.thinkmodelfunction;
-import cn.iocoder.yudao.framework.common.exception.ServiceException;
+import cn.hutool.json.JSONUtil;
+import cn.iocoder.yudao.module.iot.controller.admin.thinkmodelfunction.thingModel.*;
import cn.iocoder.yudao.module.iot.controller.admin.thinkmodelfunction.vo.IotThinkModelFunctionSaveReqVO;
import cn.iocoder.yudao.module.iot.convert.thinkmodelfunction.IotThinkModelFunctionConvert;
import cn.iocoder.yudao.module.iot.dal.dataobject.thinkmodelfunction.IotThinkModelFunctionDO;
@@ -10,6 +11,10 @@ import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Service;
import org.springframework.validation.annotation.Validated;
+import java.util.ArrayList;
+import java.util.Collections;
+import java.util.List;
+
import static cn.iocoder.yudao.framework.common.exception.util.ServiceExceptionUtil.exception;
import static cn.iocoder.yudao.module.iot.enums.ErrorCodeConstants.THINK_MODEL_FUNCTION_EXISTS_BY_PRODUCT_KEY;
import static cn.iocoder.yudao.module.iot.enums.ErrorCodeConstants.THINK_MODEL_FUNCTION_NOT_EXISTS;
@@ -27,10 +32,13 @@ public class IotThinkModelFunctionServiceImpl implements IotThinkModelFunctionSe
log.info("创建物模型,参数:{}", createReqVO);
// 验证 ProductKey 对应的产品物模型是否已存在
validateThinkModelFunctionNotExistsByProductKey(createReqVO.getProductKey());
- // 插入
+ // 转换请求对象为数据对象
IotThinkModelFunctionDO thinkModelFunction = IotThinkModelFunctionConvert.INSTANCE.convert(createReqVO);
+ // 自动生成属性上报事件和属性设置、获取服务
+ generateDefaultEventsAndServices(createReqVO, thinkModelFunction);
+ // 插入数据库
thinkModelFunctionMapper.insert(thinkModelFunction);
- // 返回
+ // 返回生成的 ID
return thinkModelFunction.getId();
}
@@ -43,9 +51,9 @@ public class IotThinkModelFunctionServiceImpl implements IotThinkModelFunctionSe
@Override
public void deleteThinkModelFunction(Long id) {
log.info("删除物模型,id:{}", id);
- // 校验存在
+ // 校验物模型是否存在
validateThinkModelFunctionExists(id);
- // 删除
+ // 删除物模型
thinkModelFunctionMapper.deleteById(id);
}
@@ -68,12 +76,15 @@ public class IotThinkModelFunctionServiceImpl implements IotThinkModelFunctionSe
@Override
public void updateThinkModelFunction(IotThinkModelFunctionSaveReqVO updateReqVO) {
log.info("更新物模型,参数:{}", updateReqVO);
- // 校验存在
+ // 校验物模型是否存在
validateThinkModelFunctionExists(updateReqVO.getId());
- // 校验 productKey 是否重复
+ // 校验 ProductKey 是否唯一
validateProductKeyUnique(updateReqVO.getId(), updateReqVO.getProductKey());
- // 更新
+ // 转换请求对象为数据对象
IotThinkModelFunctionDO thinkModelFunction = IotThinkModelFunctionConvert.INSTANCE.convert(updateReqVO);
+ // 自动生成或更新属性上报事件和属性设置、获取服务
+ generateDefaultEventsAndServices(updateReqVO, thinkModelFunction);
+ // 更新数据库
thinkModelFunctionMapper.updateById(thinkModelFunction);
}
@@ -83,4 +94,151 @@ public class IotThinkModelFunctionServiceImpl implements IotThinkModelFunctionSe
throw exception(THINK_MODEL_FUNCTION_EXISTS_BY_PRODUCT_KEY);
}
}
-}
\ No newline at end of file
+
+ /**
+ * @ TODO 还要再优化
+ * 根据属性列表,自动生成属性上报事件和属性设置、获取服务
+ */
+ private void generateDefaultEventsAndServices(IotThinkModelFunctionSaveReqVO reqVO, IotThinkModelFunctionDO thinkModelFunction) {
+ // 获取属性列表
+ List properties = reqVO.getProperties();
+ if (properties == null) {
+ properties = new ArrayList<>();
+ }
+
+ // 生成属性上报事件
+ List events = reqVO.getEvents() != null ? new ArrayList<>(reqVO.getEvents()) : new ArrayList<>();
+ ThingModelEvent propertyPostEvent = generatePropertyPostEvent(properties);
+ events.add(propertyPostEvent);
+
+ // 生成属性设置和获取服务
+ List services = reqVO.getServices() != null ? new ArrayList<>(reqVO.getServices()) : new ArrayList<>();
+ ThingModelService propertySetService = generatePropertySetService(properties);
+ if (propertySetService != null) {
+ services.add(propertySetService);
+ }
+ ThingModelService propertyGetService = generatePropertyGetService(properties);
+ if (propertyGetService != null) {
+ services.add(propertyGetService);
+ }
+
+ // 更新 thinkModelFunction 对象的 events 和 services 字段
+ thinkModelFunction.setEvents(JSONUtil.toJsonStr(events));
+ thinkModelFunction.setServices(JSONUtil.toJsonStr(services));
+ }
+
+ /**
+ * 生成属性上报事件
+ */
+ private ThingModelEvent generatePropertyPostEvent(List properties) {
+ ThingModelEvent event = new ThingModelEvent();
+ event.setIdentifier("post");
+ event.setName("属性上报");
+ event.setType("info");
+ event.setDescription("属性上报事件");
+ event.setMethod("thing.event.property.post");
+
+ // 将属性列表转换为事件的输出参数
+ List outputData = new ArrayList<>();
+ for (ThingModelProperty property : properties) {
+ ThingModelArgument arg = new ThingModelArgument();
+ arg.setIdentifier(property.getIdentifier());
+ arg.setName(property.getName());
+ arg.setDataType(property.getDataType());
+ arg.setDescription(property.getDescription());
+ arg.setDirection("output"); // 设置为输出参数
+ outputData.add(arg);
+ }
+ event.setOutputData(outputData);
+
+ return event;
+ }
+
+ /**
+ * 生成属性设置服务
+ */
+ private ThingModelService generatePropertySetService(List properties) {
+ List inputData = new ArrayList<>();
+ for (ThingModelProperty property : properties) {
+ if ("w".equals(property.getAccessMode()) || "rw".equals(property.getAccessMode())) {
+ ThingModelArgument arg = new ThingModelArgument();
+ arg.setIdentifier(property.getIdentifier());
+ arg.setName(property.getName());
+ arg.setDataType(property.getDataType());
+ arg.setDescription(property.getDescription());
+ arg.setDirection("input"); // 设置为输入参数
+ inputData.add(arg);
+ }
+ }
+ if (inputData.isEmpty()) {
+ // 如果没有可写属性,不生成属性设置服务
+ return null;
+ }
+
+ ThingModelService service = new ThingModelService();
+ service.setIdentifier("set");
+ service.setName("属性设置");
+ service.setCallType("async");
+ service.setDescription("属性设置服务");
+ service.setMethod("thing.service.property.set");
+ service.setInputData(inputData);
+ // 属性设置服务一般不需要输出参数
+ service.setOutputData(new ArrayList<>());
+
+ return service;
+ }
+
+ /**
+ * 生成属性获取服务
+ */
+ private ThingModelService generatePropertyGetService(List properties) {
+ List outputData = new ArrayList<>();
+ for (ThingModelProperty property : properties) {
+ if ("r".equals(property.getAccessMode()) || "rw".equals(property.getAccessMode())) {
+ ThingModelArgument arg = new ThingModelArgument();
+ arg.setIdentifier(property.getIdentifier());
+ arg.setName(property.getName());
+ arg.setDataType(property.getDataType());
+ arg.setDescription(property.getDescription());
+ arg.setDirection("output"); // 设置为输出参数
+ outputData.add(arg);
+ }
+ }
+ if (outputData.isEmpty()) {
+ // 如果没有可读属性,不生成属性获取服务
+ return null;
+ }
+
+ ThingModelService service = new ThingModelService();
+ service.setIdentifier("get");
+ service.setName("属性获取");
+ service.setCallType("async");
+ service.setDescription("属性获取服务");
+ service.setMethod("thing.service.property.get");
+
+ // 定义输入参数:属性标识符列表
+ ThingModelArgument inputArg = new ThingModelArgument();
+ inputArg.setIdentifier("properties");
+ inputArg.setName("属性标识符列表");
+ inputArg.setDescription("需要获取的属性标识符列表");
+ inputArg.setDirection("input"); // 设置为输入参数
+
+ // 创建数组类型,元素类型为文本类型(字符串)
+ ThingModelArrayType arrayType = new ThingModelArrayType();
+ arrayType.setType("array");
+ ThingModelArraySpecs arraySpecs = new ThingModelArraySpecs();
+ // 不指定数组长度,size 可以为 0 或者省略
+ ThingModelTextType textType = new ThingModelTextType();
+ textType.setType("text");
+ // 如果有需要,可以设置 TextType 的 specs,如长度限制
+ arraySpecs.setItem(textType);
+ arrayType.setSpecs(arraySpecs);
+
+ inputArg.setDataType(arrayType);
+
+ service.setInputData(Collections.singletonList(inputArg));
+ service.setOutputData(outputData);
+
+ return service;
+ }
+}
From 061819f25b16275b2ef97915f821dbf66cd673dd Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?=E5=AE=89=E6=B5=A9=E6=B5=A9?= <1036606149@qq.com>
Date: Sat, 14 Sep 2024 08:32:04 +0800
Subject: [PATCH 029/156] =?UTF-8?q?=E4=BF=AE=E6=94=B9=EF=BC=9AIOT=20?=
=?UTF-8?q?=E4=BC=98=E5=8C=96=E6=A0=B9=E6=8D=AE=E5=B1=9E=E6=80=A7=E5=88=97?=
=?UTF-8?q?=E8=A1=A8=EF=BC=8C=E8=87=AA=E5=8A=A8=E7=94=9F=E6=88=90=E5=B1=9E?=
=?UTF-8?q?=E6=80=A7=E4=B8=8A=E6=8A=A5=E4=BA=8B=E4=BB=B6=E5=92=8C=E5=B1=9E?=
=?UTF-8?q?=E6=80=A7=E8=AE=BE=E7=BD=AE=E3=80=81=E8=8E=B7=E5=8F=96=E6=9C=8D?=
=?UTF-8?q?=E5=8A=A1?=
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
---
.../IotThinkModelFunctionServiceImpl.java | 67 ++++++++++++++-----
1 file changed, 52 insertions(+), 15 deletions(-)
diff --git a/yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/service/thinkmodelfunction/IotThinkModelFunctionServiceImpl.java b/yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/service/thinkmodelfunction/IotThinkModelFunctionServiceImpl.java
index 66fc01779..a2943a77b 100644
--- a/yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/service/thinkmodelfunction/IotThinkModelFunctionServiceImpl.java
+++ b/yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/service/thinkmodelfunction/IotThinkModelFunctionServiceImpl.java
@@ -96,7 +96,6 @@ public class IotThinkModelFunctionServiceImpl implements IotThinkModelFunctionSe
}
/**
- * @ TODO 还要再优化
* 根据属性列表,自动生成属性上报事件和属性设置、获取服务
*/
private void generateDefaultEventsAndServices(IotThinkModelFunctionSaveReqVO reqVO, IotThinkModelFunctionDO thinkModelFunction) {
@@ -106,27 +105,65 @@ public class IotThinkModelFunctionServiceImpl implements IotThinkModelFunctionSe
properties = new ArrayList<>();
}
- // 生成属性上报事件
- List events = reqVO.getEvents() != null ? new ArrayList<>(reqVO.getEvents()) : new ArrayList<>();
- ThingModelEvent propertyPostEvent = generatePropertyPostEvent(properties);
- events.add(propertyPostEvent);
+ // 获取现有的事件和服务
+ List existingEvents = reqVO.getEvents() != null ? new ArrayList<>(reqVO.getEvents()) : new ArrayList<>();
+ List existingServices = reqVO.getServices() != null ? new ArrayList<>(reqVO.getServices()) : new ArrayList<>();
- // 生成属性设置和获取服务
- List services = reqVO.getServices() != null ? new ArrayList<>(reqVO.getServices()) : new ArrayList<>();
+ // 生成或更新属性上报事件
+ ThingModelEvent propertyPostEvent = generatePropertyPostEvent(properties);
+ updateEventInList(existingEvents, propertyPostEvent);
+
+ // 生成或更新属性设置和获取服务
ThingModelService propertySetService = generatePropertySetService(properties);
- if (propertySetService != null) {
- services.add(propertySetService);
- }
+ updateServiceInList(existingServices, propertySetService);
+
ThingModelService propertyGetService = generatePropertyGetService(properties);
- if (propertyGetService != null) {
- services.add(propertyGetService);
- }
+ updateServiceInList(existingServices, propertyGetService);
// 更新 thinkModelFunction 对象的 events 和 services 字段
- thinkModelFunction.setEvents(JSONUtil.toJsonStr(events));
- thinkModelFunction.setServices(JSONUtil.toJsonStr(services));
+ thinkModelFunction.setEvents(JSONUtil.toJsonStr(existingEvents));
+ thinkModelFunction.setServices(JSONUtil.toJsonStr(existingServices));
}
+ /**
+ * 在事件列表中更新或添加事件
+ */
+ private void updateEventInList(List events, ThingModelEvent newEvent) {
+ if (newEvent == null) {
+ return;
+ }
+ for (int i = 0; i < events.size(); i++) {
+ ThingModelEvent event = events.get(i);
+ if (event.getIdentifier().equals(newEvent.getIdentifier())) {
+ // 更新已有的事件
+ events.set(i, newEvent);
+ return;
+ }
+ }
+ // 如果不存在,则添加新的事件
+ events.add(newEvent);
+ }
+
+ /**
+ * 在服务列表中更新或添加服务
+ */
+ private void updateServiceInList(List services, ThingModelService newService) {
+ if (newService == null) {
+ return;
+ }
+ for (int i = 0; i < services.size(); i++) {
+ ThingModelService service = services.get(i);
+ if (service.getIdentifier().equals(newService.getIdentifier())) {
+ // 更新已有的服务
+ services.set(i, newService);
+ return;
+ }
+ }
+ // 如果不存在,则添加新的服务
+ services.add(newService);
+ }
+
+
/**
* 生成属性上报事件
*/
From 64fefaa6305027762e4836ae06dae3ebac961429 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?=E5=AE=89=E6=B5=A9=E6=B5=A9?= <1036606149@qq.com>
Date: Sat, 14 Sep 2024 08:59:55 +0800
Subject: [PATCH 030/156] =?UTF-8?q?=E4=BF=AE=E6=94=B9=EF=BC=9AIOT=20?=
=?UTF-8?q?=E5=BA=8F=E5=88=97=E5=8C=96=E6=8A=A5=E9=94=99=E9=97=AE=E9=A2=98?=
=?UTF-8?q?=E5=A4=84=E7=90=86=E3=80=81=E8=AF=B7=E6=B1=82=E7=A4=BA=E4=BE=8B?=
=?UTF-8?q?=E4=BF=AE=E6=94=B9?=
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
---
.../IotThinkModelFunctionController.http | 21 +++++----
.../IotThinkModelFunctionConvert.java | 44 +++++++++++++++----
.../IotThinkModelFunctionServiceImpl.java | 12 ++++-
3 files changed, 57 insertions(+), 20 deletions(-)
diff --git a/yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/controller/admin/thinkmodelfunction/IotThinkModelFunctionController.http b/yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/controller/admin/thinkmodelfunction/IotThinkModelFunctionController.http
index e31540710..34a4054f6 100644
--- a/yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/controller/admin/thinkmodelfunction/IotThinkModelFunctionController.http
+++ b/yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/controller/admin/thinkmodelfunction/IotThinkModelFunctionController.http
@@ -146,9 +146,9 @@ tenant-id: {{adminTenentId}}
Authorization: Bearer {{token}}
{
- "id": 1,
- "productId": 1001,
- "productKey": "smart-sensor-001",
+ "id": 3,
+ "productId": 1002,
+ "productKey": "smart-sensor-002",
"properties": [
{
"identifier": "Temperature",
@@ -158,8 +158,8 @@ Authorization: Bearer {{token}}
"dataType": {
"type": "float",
"specs": {
- "min": -40.0,
- "max": 125.0,
+ "min": -100.0,
+ "max": 200.0,
"step": 0.1,
"unit": "℃"
}
@@ -229,7 +229,8 @@ Authorization: Bearer {{token}}
"name": "重启设备",
"callType": "async",
"inputData": [],
- "description": "远程重启设备"
+ "description": "远程重启设备",
+ "method": "thing.service.reboot"
},
{
"identifier": "SetThreshold",
@@ -251,7 +252,8 @@ Authorization: Bearer {{token}}
"description": "报警温度阈值"
}
],
- "description": "设置设备的温度报警阈值"
+ "description": "设置设备的温度报警阈值",
+ "method": "thing.service.setThreshold"
}
],
"events": [
@@ -272,13 +274,14 @@ Authorization: Bearer {{token}}
"description": "触发报警时的温度值"
}
],
- "description": "当温度超过阈值时触发高温报警事件"
+ "description": "当温度超过阈值时触发高温报警事件",
+ "method": "thing.event.highTemperatureAlert"
}
]
}
### 请求 /iot/think-model-function/get-by-product-key 接口 => 成功
-GET {{baseUrl}}/iot/think-model-function/get-by-product-key?productKey=123456
+GET {{baseUrl}}/iot/think-model-function/get-by-product-key?productKey=smart-sensor-002
tenant-id: {{adminTenentId}}
Authorization: Bearer {{token}}
\ No newline at end of file
diff --git a/yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/convert/thinkmodelfunction/IotThinkModelFunctionConvert.java b/yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/convert/thinkmodelfunction/IotThinkModelFunctionConvert.java
index 41e0c583b..aa7322eb3 100644
--- a/yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/convert/thinkmodelfunction/IotThinkModelFunctionConvert.java
+++ b/yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/convert/thinkmodelfunction/IotThinkModelFunctionConvert.java
@@ -1,12 +1,13 @@
package cn.iocoder.yudao.module.iot.convert.thinkmodelfunction;
-import cn.hutool.json.JSONUtil;
import cn.iocoder.yudao.module.iot.controller.admin.thinkmodelfunction.thingModel.ThingModelEvent;
import cn.iocoder.yudao.module.iot.controller.admin.thinkmodelfunction.thingModel.ThingModelProperty;
import cn.iocoder.yudao.module.iot.controller.admin.thinkmodelfunction.thingModel.ThingModelService;
import cn.iocoder.yudao.module.iot.controller.admin.thinkmodelfunction.vo.IotThinkModelFunctionRespVO;
import cn.iocoder.yudao.module.iot.controller.admin.thinkmodelfunction.vo.IotThinkModelFunctionSaveReqVO;
import cn.iocoder.yudao.module.iot.dal.dataobject.thinkmodelfunction.IotThinkModelFunctionDO;
+import com.fasterxml.jackson.core.JsonProcessingException;
+import com.fasterxml.jackson.databind.ObjectMapper;
import org.mapstruct.Mapper;
import org.mapstruct.Mapping;
import org.mapstruct.factory.Mappers;
@@ -19,6 +20,8 @@ public interface IotThinkModelFunctionConvert {
IotThinkModelFunctionConvert INSTANCE = Mappers.getMapper(IotThinkModelFunctionConvert.class);
+ ObjectMapper objectMapper = new ObjectMapper();
+
// 将 SaveReqVO 转换为 DO 对象,处理 properties, services, events 字段
@Mapping(target = "properties", expression = "java(convertPropertiesToJson(bean.getProperties()))")
@Mapping(target = "services", expression = "java(convertServicesToJson(bean.getServices()))")
@@ -26,15 +29,27 @@ public interface IotThinkModelFunctionConvert {
IotThinkModelFunctionDO convert(IotThinkModelFunctionSaveReqVO bean);
default String convertPropertiesToJson(List properties) {
- return properties != null ? JSONUtil.toJsonStr(properties) : "[]";
+ try {
+ return properties != null ? objectMapper.writeValueAsString(properties) : "[]";
+ } catch (JsonProcessingException e) {
+ throw new RuntimeException("序列化 properties 时发生错误", e);
+ }
}
default String convertServicesToJson(List services) {
- return services != null ? JSONUtil.toJsonStr(services) : "[]";
+ try {
+ return services != null ? objectMapper.writeValueAsString(services) : "[]";
+ } catch (JsonProcessingException e) {
+ throw new RuntimeException("序列化 services 时发生错误", e);
+ }
}
default String convertEventsToJson(List events) {
- return events != null ? JSONUtil.toJsonStr(events) : "[]";
+ try {
+ return events != null ? objectMapper.writeValueAsString(events) : "[]";
+ } catch (JsonProcessingException e) {
+ throw new RuntimeException("序列化 events 时发生错误", e);
+ }
}
// 将 DO 转换为 RespVO 对象,处理 properties, services, events 字段
@@ -44,18 +59,29 @@ public interface IotThinkModelFunctionConvert {
IotThinkModelFunctionRespVO convert(IotThinkModelFunctionDO bean);
default List convertJsonToProperties(String propertiesJson) {
- return propertiesJson != null ? JSONUtil.toList(propertiesJson, ThingModelProperty.class) : new ArrayList<>();
+ try {
+ return propertiesJson != null ? objectMapper.readValue(propertiesJson, objectMapper.getTypeFactory().constructCollectionType(List.class, ThingModelProperty.class)) : new ArrayList<>();
+ } catch (JsonProcessingException e) {
+ throw new RuntimeException("反序列化 properties 时发生错误", e);
+ }
}
default List convertJsonToServices(String servicesJson) {
- return servicesJson != null ? JSONUtil.toList(servicesJson, ThingModelService.class) : new ArrayList<>();
+ try {
+ return servicesJson != null ? objectMapper.readValue(servicesJson, objectMapper.getTypeFactory().constructCollectionType(List.class, ThingModelService.class)) : new ArrayList<>();
+ } catch (JsonProcessingException e) {
+ throw new RuntimeException("反序列化 services 时发生错误", e);
+ }
}
default List convertJsonToEvents(String eventsJson) {
- return eventsJson != null ? JSONUtil.toList(eventsJson, ThingModelEvent.class) : new ArrayList<>();
+ try {
+ return eventsJson != null ? objectMapper.readValue(eventsJson, objectMapper.getTypeFactory().constructCollectionType(List.class, ThingModelEvent.class)) : new ArrayList<>();
+ } catch (JsonProcessingException e) {
+ throw new RuntimeException("反序列化 events 时发生错误", e);
+ }
}
// 批量转换 DO 列表到 RespVO 列表
List convertList(List list);
-}
-
+}
\ No newline at end of file
diff --git a/yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/service/thinkmodelfunction/IotThinkModelFunctionServiceImpl.java b/yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/service/thinkmodelfunction/IotThinkModelFunctionServiceImpl.java
index a2943a77b..559e0bed7 100644
--- a/yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/service/thinkmodelfunction/IotThinkModelFunctionServiceImpl.java
+++ b/yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/service/thinkmodelfunction/IotThinkModelFunctionServiceImpl.java
@@ -6,6 +6,8 @@ import cn.iocoder.yudao.module.iot.controller.admin.thinkmodelfunction.vo.IotThi
import cn.iocoder.yudao.module.iot.convert.thinkmodelfunction.IotThinkModelFunctionConvert;
import cn.iocoder.yudao.module.iot.dal.dataobject.thinkmodelfunction.IotThinkModelFunctionDO;
import cn.iocoder.yudao.module.iot.dal.mysql.thinkmodelfunction.IotThinkModelFunctionMapper;
+import com.fasterxml.jackson.core.JsonProcessingException;
+import com.fasterxml.jackson.databind.ObjectMapper;
import jakarta.annotation.Resource;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Service;
@@ -27,6 +29,8 @@ public class IotThinkModelFunctionServiceImpl implements IotThinkModelFunctionSe
@Resource
private IotThinkModelFunctionMapper thinkModelFunctionMapper;
+ private ObjectMapper objectMapper = new ObjectMapper();
+
@Override
public Long createThinkModelFunction(IotThinkModelFunctionSaveReqVO createReqVO) {
log.info("创建物模型,参数:{}", createReqVO);
@@ -121,8 +125,12 @@ public class IotThinkModelFunctionServiceImpl implements IotThinkModelFunctionSe
updateServiceInList(existingServices, propertyGetService);
// 更新 thinkModelFunction 对象的 events 和 services 字段
- thinkModelFunction.setEvents(JSONUtil.toJsonStr(existingEvents));
- thinkModelFunction.setServices(JSONUtil.toJsonStr(existingServices));
+ try {
+ thinkModelFunction.setEvents(objectMapper.writeValueAsString(existingEvents));
+ thinkModelFunction.setServices(objectMapper.writeValueAsString(existingServices));
+ } catch (JsonProcessingException e) {
+ throw new RuntimeException("序列化事件和服务时发生错误", e);
+ }
}
/**
From 07b3ac20f613e4b1e7fd7442f802fbba72bf3d30 Mon Sep 17 00:00:00 2001
From: YunaiV
Date: Sat, 14 Sep 2024 09:44:09 +0800
Subject: [PATCH 031/156] =?UTF-8?q?=E3=80=90=E4=BB=A3=E7=A0=81=E8=AF=84?=
=?UTF-8?q?=E5=AE=A1=E3=80=91IOT=EF=BC=9A=E7=89=A9=E6=A8=A1=E5=9E=8B?=
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
---
.../thingModel/ThingModelArraySpecs.java | 9 ---------
.../thingModel/ThingModelEvent.java | 10 +++++++++-
.../thingModel/ThingModelProperty.java | 5 ++++-
.../thingModel/ThingModelService.java | 10 +++++++++-
.../{ => dataType}/ThingModelArgument.java | 9 +++++++--
.../dataType/ThingModelArraySpecs.java | 17 +++++++++++++++++
.../{ => dataType}/ThingModelArrayType.java | 7 ++++---
.../{ => dataType}/ThingModelBoolType.java | 4 +++-
.../{ => dataType}/ThingModelDataType.java | 4 +++-
.../{ => dataType}/ThingModelDateType.java | 6 +++---
.../{ => dataType}/ThingModelDoubleType.java | 6 +++---
.../{ => dataType}/ThingModelEnumType.java | 12 ++++++++----
.../{ => dataType}/ThingModelFloatType.java | 4 +++-
.../{ => dataType}/ThingModelIntType.java | 6 +++---
.../{ => dataType}/ThingModelStructField.java | 4 +++-
.../{ => dataType}/ThingModelStructType.java | 7 ++++---
.../{ => dataType}/ThingModelTextType.java | 13 +++++++++----
.../IotThinkModelFunctionDO.java | 18 ++++++++++++------
.../IotThinkModelFunctionServiceImpl.java | 5 ++++-
19 files changed, 108 insertions(+), 48 deletions(-)
delete mode 100644 yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/controller/admin/thinkmodelfunction/thingModel/ThingModelArraySpecs.java
rename yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/controller/admin/thinkmodelfunction/thingModel/{ => dataType}/ThingModelArgument.java (64%)
create mode 100644 yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/controller/admin/thinkmodelfunction/thingModel/dataType/ThingModelArraySpecs.java
rename yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/controller/admin/thinkmodelfunction/thingModel/{ => dataType}/ThingModelArrayType.java (67%)
rename yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/controller/admin/thinkmodelfunction/thingModel/{ => dataType}/ThingModelBoolType.java (89%)
rename yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/controller/admin/thinkmodelfunction/thingModel/{ => dataType}/ThingModelDataType.java (97%)
rename yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/controller/admin/thinkmodelfunction/thingModel/{ => dataType}/ThingModelDateType.java (69%)
rename yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/controller/admin/thinkmodelfunction/thingModel/{ => dataType}/ThingModelDoubleType.java (78%)
rename yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/controller/admin/thinkmodelfunction/thingModel/{ => dataType}/ThingModelEnumType.java (52%)
rename yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/controller/admin/thinkmodelfunction/thingModel/{ => dataType}/ThingModelFloatType.java (92%)
rename yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/controller/admin/thinkmodelfunction/thingModel/{ => dataType}/ThingModelIntType.java (78%)
rename yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/controller/admin/thinkmodelfunction/thingModel/{ => dataType}/ThingModelStructField.java (89%)
rename yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/controller/admin/thinkmodelfunction/thingModel/{ => dataType}/ThingModelStructType.java (71%)
rename yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/controller/admin/thinkmodelfunction/thingModel/{ => dataType}/ThingModelTextType.java (63%)
diff --git a/yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/controller/admin/thinkmodelfunction/thingModel/ThingModelArraySpecs.java b/yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/controller/admin/thinkmodelfunction/thingModel/ThingModelArraySpecs.java
deleted file mode 100644
index 3ea23e8db..000000000
--- a/yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/controller/admin/thinkmodelfunction/thingModel/ThingModelArraySpecs.java
+++ /dev/null
@@ -1,9 +0,0 @@
-package cn.iocoder.yudao.module.iot.controller.admin.thinkmodelfunction.thingModel;
-
-import lombok.Data;
-
-@Data
-public class ThingModelArraySpecs {
- private int size; // 数组长度
- private ThingModelDataType item; // 数组元素的类型
-}
diff --git a/yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/controller/admin/thinkmodelfunction/thingModel/ThingModelEvent.java b/yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/controller/admin/thinkmodelfunction/thingModel/ThingModelEvent.java
index 857f688e9..96dff1adf 100644
--- a/yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/controller/admin/thinkmodelfunction/thingModel/ThingModelEvent.java
+++ b/yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/controller/admin/thinkmodelfunction/thingModel/ThingModelEvent.java
@@ -1,14 +1,22 @@
package cn.iocoder.yudao.module.iot.controller.admin.thinkmodelfunction.thingModel;
+import cn.iocoder.yudao.module.iot.controller.admin.thinkmodelfunction.thingModel.dataType.ThingModelArgument;
import lombok.Data;
import java.util.List;
@Data
public class ThingModelEvent {
+
private String identifier;
private String name;
- private String type; // "info"、"alert"、"error"
+ /**
+ * 事件类型
+ *
+ * "info"、"alert"、"error"
+ */
+ private String type;
private List outputData;
private String description;
private String method;
+
}
diff --git a/yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/controller/admin/thinkmodelfunction/thingModel/ThingModelProperty.java b/yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/controller/admin/thinkmodelfunction/thingModel/ThingModelProperty.java
index f82198152..4f9e32c59 100644
--- a/yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/controller/admin/thinkmodelfunction/thingModel/ThingModelProperty.java
+++ b/yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/controller/admin/thinkmodelfunction/thingModel/ThingModelProperty.java
@@ -1,13 +1,16 @@
package cn.iocoder.yudao.module.iot.controller.admin.thinkmodelfunction.thingModel;
+import cn.iocoder.yudao.module.iot.controller.admin.thinkmodelfunction.thingModel.dataType.ThingModelDataType;
import lombok.Data;
@Data
public class ThingModelProperty {
+
private String identifier;
private String name;
private String accessMode; // "rw"、"r"、"w"
- private boolean required;
+ private Boolean required;
private ThingModelDataType dataType;
private String description;
+
}
diff --git a/yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/controller/admin/thinkmodelfunction/thingModel/ThingModelService.java b/yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/controller/admin/thinkmodelfunction/thingModel/ThingModelService.java
index 521e9ab08..839ceff47 100644
--- a/yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/controller/admin/thinkmodelfunction/thingModel/ThingModelService.java
+++ b/yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/controller/admin/thinkmodelfunction/thingModel/ThingModelService.java
@@ -1,15 +1,23 @@
package cn.iocoder.yudao.module.iot.controller.admin.thinkmodelfunction.thingModel;
+import cn.iocoder.yudao.module.iot.controller.admin.thinkmodelfunction.thingModel.dataType.ThingModelArgument;
import lombok.Data;
import java.util.List;
@Data
public class ThingModelService {
+
private String identifier;
private String name;
- private String callType; // "sync"、"async"
+ /**
+ * 调用类型
+ *
+ * "sync"、"async"
+ */
+ private String callType;
private List inputData;
private List outputData;
private String description;
private String method;
+
}
diff --git a/yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/controller/admin/thinkmodelfunction/thingModel/ThingModelArgument.java b/yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/controller/admin/thinkmodelfunction/thingModel/dataType/ThingModelArgument.java
similarity index 64%
rename from yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/controller/admin/thinkmodelfunction/thingModel/ThingModelArgument.java
rename to yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/controller/admin/thinkmodelfunction/thingModel/dataType/ThingModelArgument.java
index 909d63459..2be24004e 100644
--- a/yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/controller/admin/thinkmodelfunction/thingModel/ThingModelArgument.java
+++ b/yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/controller/admin/thinkmodelfunction/thingModel/dataType/ThingModelArgument.java
@@ -1,12 +1,17 @@
-package cn.iocoder.yudao.module.iot.controller.admin.thinkmodelfunction.thingModel;
+package cn.iocoder.yudao.module.iot.controller.admin.thinkmodelfunction.thingModel.dataType;
import lombok.Data;
@Data
public class ThingModelArgument {
+
private String identifier;
private String name;
private ThingModelDataType dataType;
- private String direction; // 用于区分输入或输出参数,"input" 或 "output"
+ /**
+ * 用于区分输入或输出参数,"input" 或 "output"
+ */
+ private String direction;
private String description;
+
}
diff --git a/yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/controller/admin/thinkmodelfunction/thingModel/dataType/ThingModelArraySpecs.java b/yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/controller/admin/thinkmodelfunction/thingModel/dataType/ThingModelArraySpecs.java
new file mode 100644
index 000000000..c3faf6161
--- /dev/null
+++ b/yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/controller/admin/thinkmodelfunction/thingModel/dataType/ThingModelArraySpecs.java
@@ -0,0 +1,17 @@
+package cn.iocoder.yudao.module.iot.controller.admin.thinkmodelfunction.thingModel.dataType;
+
+import lombok.Data;
+
+@Data
+public class ThingModelArraySpecs {
+
+ /**
+ * 数组长度
+ */
+ private int size;
+ /**
+ * 数组元素的类型
+ */
+ private ThingModelDataType item;
+
+}
diff --git a/yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/controller/admin/thinkmodelfunction/thingModel/ThingModelArrayType.java b/yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/controller/admin/thinkmodelfunction/thingModel/dataType/ThingModelArrayType.java
similarity index 67%
rename from yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/controller/admin/thinkmodelfunction/thingModel/ThingModelArrayType.java
rename to yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/controller/admin/thinkmodelfunction/thingModel/dataType/ThingModelArrayType.java
index 114add210..bab87be0a 100644
--- a/yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/controller/admin/thinkmodelfunction/thingModel/ThingModelArrayType.java
+++ b/yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/controller/admin/thinkmodelfunction/thingModel/dataType/ThingModelArrayType.java
@@ -1,11 +1,12 @@
-package cn.iocoder.yudao.module.iot.controller.admin.thinkmodelfunction.thingModel;
+package cn.iocoder.yudao.module.iot.controller.admin.thinkmodelfunction.thingModel.dataType;
import lombok.Data;
-import lombok.EqualsAndHashCode;
+// TODO @haohao:这个是不是和别的类,不太统一哈
@Data
-@EqualsAndHashCode(callSuper = true)
public class ThingModelArrayType extends ThingModelDataType {
+
private ThingModelArraySpecs specs;
+
}
diff --git a/yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/controller/admin/thinkmodelfunction/thingModel/ThingModelBoolType.java b/yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/controller/admin/thinkmodelfunction/thingModel/dataType/ThingModelBoolType.java
similarity index 89%
rename from yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/controller/admin/thinkmodelfunction/thingModel/ThingModelBoolType.java
rename to yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/controller/admin/thinkmodelfunction/thingModel/dataType/ThingModelBoolType.java
index f7e7e456b..b8ca64195 100644
--- a/yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/controller/admin/thinkmodelfunction/thingModel/ThingModelBoolType.java
+++ b/yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/controller/admin/thinkmodelfunction/thingModel/dataType/ThingModelBoolType.java
@@ -1,4 +1,4 @@
-package cn.iocoder.yudao.module.iot.controller.admin.thinkmodelfunction.thingModel;
+package cn.iocoder.yudao.module.iot.controller.admin.thinkmodelfunction.thingModel.dataType;
import lombok.Data;
import lombok.EqualsAndHashCode;
@@ -6,5 +6,7 @@ import lombok.EqualsAndHashCode;
@Data
@EqualsAndHashCode(callSuper = true)
public class ThingModelBoolType extends ThingModelDataType {
+
// Bool 类型一般不需要额外的 specs
+
}
diff --git a/yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/controller/admin/thinkmodelfunction/thingModel/ThingModelDataType.java b/yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/controller/admin/thinkmodelfunction/thingModel/dataType/ThingModelDataType.java
similarity index 97%
rename from yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/controller/admin/thinkmodelfunction/thingModel/ThingModelDataType.java
rename to yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/controller/admin/thinkmodelfunction/thingModel/dataType/ThingModelDataType.java
index 613cbd766..ec5f04bbb 100644
--- a/yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/controller/admin/thinkmodelfunction/thingModel/ThingModelDataType.java
+++ b/yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/controller/admin/thinkmodelfunction/thingModel/dataType/ThingModelDataType.java
@@ -1,4 +1,4 @@
-package cn.iocoder.yudao.module.iot.controller.admin.thinkmodelfunction.thingModel;
+package cn.iocoder.yudao.module.iot.controller.admin.thinkmodelfunction.thingModel.dataType;
import com.fasterxml.jackson.annotation.JsonSubTypes;
import com.fasterxml.jackson.annotation.JsonTypeInfo;
@@ -18,5 +18,7 @@ import lombok.Data;
@JsonSubTypes.Type(value = ThingModelArrayType.class, name = "array")
})
public abstract class ThingModelDataType {
+
private String type;
+
}
diff --git a/yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/controller/admin/thinkmodelfunction/thingModel/ThingModelDateType.java b/yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/controller/admin/thinkmodelfunction/thingModel/dataType/ThingModelDateType.java
similarity index 69%
rename from yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/controller/admin/thinkmodelfunction/thingModel/ThingModelDateType.java
rename to yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/controller/admin/thinkmodelfunction/thingModel/dataType/ThingModelDateType.java
index 11cb3a729..854229339 100644
--- a/yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/controller/admin/thinkmodelfunction/thingModel/ThingModelDateType.java
+++ b/yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/controller/admin/thinkmodelfunction/thingModel/dataType/ThingModelDateType.java
@@ -1,10 +1,10 @@
-package cn.iocoder.yudao.module.iot.controller.admin.thinkmodelfunction.thingModel;
+package cn.iocoder.yudao.module.iot.controller.admin.thinkmodelfunction.thingModel.dataType;
import lombok.Data;
-import lombok.EqualsAndHashCode;
@Data
-@EqualsAndHashCode(callSuper = true)
public class ThingModelDateType extends ThingModelDataType {
+
// Date 类型一般不需要额外的 specs
+
}
diff --git a/yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/controller/admin/thinkmodelfunction/thingModel/ThingModelDoubleType.java b/yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/controller/admin/thinkmodelfunction/thingModel/dataType/ThingModelDoubleType.java
similarity index 78%
rename from yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/controller/admin/thinkmodelfunction/thingModel/ThingModelDoubleType.java
rename to yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/controller/admin/thinkmodelfunction/thingModel/dataType/ThingModelDoubleType.java
index d60302179..e5f3ad268 100644
--- a/yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/controller/admin/thinkmodelfunction/thingModel/ThingModelDoubleType.java
+++ b/yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/controller/admin/thinkmodelfunction/thingModel/dataType/ThingModelDoubleType.java
@@ -1,18 +1,18 @@
-package cn.iocoder.yudao.module.iot.controller.admin.thinkmodelfunction.thingModel;
+package cn.iocoder.yudao.module.iot.controller.admin.thinkmodelfunction.thingModel.dataType;
import lombok.Data;
-import lombok.EqualsAndHashCode;
@Data
-@EqualsAndHashCode(callSuper = true)
public class ThingModelDoubleType extends ThingModelDataType {
private ThingModelDoubleSpecs specs;
}
@Data
class ThingModelDoubleSpecs {
+
private Double min;
private Double max;
private Double step;
private String unit;
+
}
diff --git a/yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/controller/admin/thinkmodelfunction/thingModel/ThingModelEnumType.java b/yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/controller/admin/thinkmodelfunction/thingModel/dataType/ThingModelEnumType.java
similarity index 52%
rename from yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/controller/admin/thinkmodelfunction/thingModel/ThingModelEnumType.java
rename to yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/controller/admin/thinkmodelfunction/thingModel/dataType/ThingModelEnumType.java
index f76962661..3dcb068e9 100644
--- a/yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/controller/admin/thinkmodelfunction/thingModel/ThingModelEnumType.java
+++ b/yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/controller/admin/thinkmodelfunction/thingModel/dataType/ThingModelEnumType.java
@@ -1,11 +1,15 @@
-package cn.iocoder.yudao.module.iot.controller.admin.thinkmodelfunction.thingModel;
+package cn.iocoder.yudao.module.iot.controller.admin.thinkmodelfunction.thingModel.dataType;
import lombok.Data;
-import lombok.EqualsAndHashCode;
+
import java.util.Map;
@Data
-@EqualsAndHashCode(callSuper = true)
public class ThingModelEnumType extends ThingModelDataType {
- private Map specs; // 枚举值和描述的键值对
+
+ /**
+ * 枚举值和描述的键值对
+ */
+ private Map specs;
+
}
diff --git a/yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/controller/admin/thinkmodelfunction/thingModel/ThingModelFloatType.java b/yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/controller/admin/thinkmodelfunction/thingModel/dataType/ThingModelFloatType.java
similarity index 92%
rename from yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/controller/admin/thinkmodelfunction/thingModel/ThingModelFloatType.java
rename to yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/controller/admin/thinkmodelfunction/thingModel/dataType/ThingModelFloatType.java
index c9d5516ad..27926fa49 100644
--- a/yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/controller/admin/thinkmodelfunction/thingModel/ThingModelFloatType.java
+++ b/yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/controller/admin/thinkmodelfunction/thingModel/dataType/ThingModelFloatType.java
@@ -1,4 +1,4 @@
-package cn.iocoder.yudao.module.iot.controller.admin.thinkmodelfunction.thingModel;
+package cn.iocoder.yudao.module.iot.controller.admin.thinkmodelfunction.thingModel.dataType;
import lombok.Data;
import lombok.EqualsAndHashCode;
@@ -11,8 +11,10 @@ public class ThingModelFloatType extends ThingModelDataType {
@Data
class ThingModelFloatSpecs {
+
private Float min;
private Float max;
private Float step;
private String unit;
+
}
diff --git a/yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/controller/admin/thinkmodelfunction/thingModel/ThingModelIntType.java b/yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/controller/admin/thinkmodelfunction/thingModel/dataType/ThingModelIntType.java
similarity index 78%
rename from yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/controller/admin/thinkmodelfunction/thingModel/ThingModelIntType.java
rename to yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/controller/admin/thinkmodelfunction/thingModel/dataType/ThingModelIntType.java
index d48f50e47..a126eb749 100644
--- a/yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/controller/admin/thinkmodelfunction/thingModel/ThingModelIntType.java
+++ b/yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/controller/admin/thinkmodelfunction/thingModel/dataType/ThingModelIntType.java
@@ -1,18 +1,18 @@
-package cn.iocoder.yudao.module.iot.controller.admin.thinkmodelfunction.thingModel;
+package cn.iocoder.yudao.module.iot.controller.admin.thinkmodelfunction.thingModel.dataType;
import lombok.Data;
-import lombok.EqualsAndHashCode;
@Data
-@EqualsAndHashCode(callSuper = true)
public class ThingModelIntType extends ThingModelDataType {
private ThingModelIntSpecs specs;
}
@Data
class ThingModelIntSpecs {
+
private Integer min;
private Integer max;
private Integer step;
private String unit;
+
}
diff --git a/yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/controller/admin/thinkmodelfunction/thingModel/ThingModelStructField.java b/yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/controller/admin/thinkmodelfunction/thingModel/dataType/ThingModelStructField.java
similarity index 89%
rename from yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/controller/admin/thinkmodelfunction/thingModel/ThingModelStructField.java
rename to yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/controller/admin/thinkmodelfunction/thingModel/dataType/ThingModelStructField.java
index 449db55c2..5e079f22b 100644
--- a/yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/controller/admin/thinkmodelfunction/thingModel/ThingModelStructField.java
+++ b/yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/controller/admin/thinkmodelfunction/thingModel/dataType/ThingModelStructField.java
@@ -1,11 +1,13 @@
-package cn.iocoder.yudao.module.iot.controller.admin.thinkmodelfunction.thingModel;
+package cn.iocoder.yudao.module.iot.controller.admin.thinkmodelfunction.thingModel.dataType;
import lombok.Data;
@Data
public class ThingModelStructField {
+
private String identifier;
private String name;
private ThingModelDataType dataType;
private String description;
+
}
\ No newline at end of file
diff --git a/yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/controller/admin/thinkmodelfunction/thingModel/ThingModelStructType.java b/yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/controller/admin/thinkmodelfunction/thingModel/dataType/ThingModelStructType.java
similarity index 71%
rename from yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/controller/admin/thinkmodelfunction/thingModel/ThingModelStructType.java
rename to yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/controller/admin/thinkmodelfunction/thingModel/dataType/ThingModelStructType.java
index d3d35f16c..f0996513c 100644
--- a/yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/controller/admin/thinkmodelfunction/thingModel/ThingModelStructType.java
+++ b/yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/controller/admin/thinkmodelfunction/thingModel/dataType/ThingModelStructType.java
@@ -1,13 +1,14 @@
-package cn.iocoder.yudao.module.iot.controller.admin.thinkmodelfunction.thingModel;
+package cn.iocoder.yudao.module.iot.controller.admin.thinkmodelfunction.thingModel.dataType;
import lombok.Data;
-import lombok.EqualsAndHashCode;
+
import java.util.List;
@Data
-@EqualsAndHashCode(callSuper = true)
public class ThingModelStructType extends ThingModelDataType {
+
private List specs;
+
}
diff --git a/yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/controller/admin/thinkmodelfunction/thingModel/ThingModelTextType.java b/yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/controller/admin/thinkmodelfunction/thingModel/dataType/ThingModelTextType.java
similarity index 63%
rename from yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/controller/admin/thinkmodelfunction/thingModel/ThingModelTextType.java
rename to yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/controller/admin/thinkmodelfunction/thingModel/dataType/ThingModelTextType.java
index 0f6ea2bcb..16d1e402e 100644
--- a/yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/controller/admin/thinkmodelfunction/thingModel/ThingModelTextType.java
+++ b/yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/controller/admin/thinkmodelfunction/thingModel/dataType/ThingModelTextType.java
@@ -1,15 +1,20 @@
-package cn.iocoder.yudao.module.iot.controller.admin.thinkmodelfunction.thingModel;
+package cn.iocoder.yudao.module.iot.controller.admin.thinkmodelfunction.thingModel.dataType;
import lombok.Data;
-import lombok.EqualsAndHashCode;
@Data
-@EqualsAndHashCode(callSuper = true)
public class ThingModelTextType extends ThingModelDataType {
+
private ThingModelTextSpecs specs;
+
}
@Data
class ThingModelTextSpecs {
- private Integer length; // 最大长度
+
+ /**
+ * 最大长度
+ */
+ private Integer length;
+
}
diff --git a/yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/dal/dataobject/thinkmodelfunction/IotThinkModelFunctionDO.java b/yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/dal/dataobject/thinkmodelfunction/IotThinkModelFunctionDO.java
index 564eefb2b..80fe0a65b 100644
--- a/yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/dal/dataobject/thinkmodelfunction/IotThinkModelFunctionDO.java
+++ b/yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/dal/dataobject/thinkmodelfunction/IotThinkModelFunctionDO.java
@@ -1,42 +1,48 @@
package cn.iocoder.yudao.module.iot.dal.dataobject.thinkmodelfunction;
import cn.iocoder.yudao.framework.mybatis.core.dataobject.BaseDO;
+import cn.iocoder.yudao.module.iot.dal.dataobject.product.IotProductDO;
import com.baomidou.mybatisplus.annotation.KeySequence;
import com.baomidou.mybatisplus.annotation.TableId;
import com.baomidou.mybatisplus.annotation.TableName;
import lombok.*;
/**
- * IoT 产品物模型 DO
+ * IoT 产品物模型功能 DO
+ *
+ * 每个 {@link IotProductDO} 和 {@link IotThinkModelFunctionDO} 是“一对多”的关系,它的每个属性、事件、服务都对应一条记录
*
* @author 芋道源码
*/
@TableName("iot_think_model_function")
@KeySequence("iot_think_model_function_seq") // 用于 Oracle、PostgreSQL、Kingbase、DB2、H2 数据库的主键自增。如果是 MySQL 等数据库,可不写。
@Data
-@EqualsAndHashCode(callSuper = true)
-@ToString(callSuper = true)
@Builder
@NoArgsConstructor
@AllArgsConstructor
public class IotThinkModelFunctionDO extends BaseDO {
/**
- * 产品ID
+ * 物模型功能编号
*/
@TableId
private Long id;
-
+ // TODO @haohao:是不是有一个 identifier,需要要有哈
+ // TODO @haohao:name、description 属性,还有个类型
/**
* 产品标识
+ *
+ * 关联 {@link IotProductDO#getId()}
*/
private Long productId;
-
/**
* 产品标识
+ *
+ * 关联 {@link IotProductDO#getProductKey()}
*/
private String productKey;
+ // TODO @haohao:是不是可以搞成 ThingModelProperty、ThingModelEvent、ThingModelService 进行存储
/**
* 属性列表
*/
diff --git a/yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/service/thinkmodelfunction/IotThinkModelFunctionServiceImpl.java b/yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/service/thinkmodelfunction/IotThinkModelFunctionServiceImpl.java
index 559e0bed7..6c8afe15f 100644
--- a/yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/service/thinkmodelfunction/IotThinkModelFunctionServiceImpl.java
+++ b/yudao-module-iot/yudao-module-iot-biz/src/main/java/cn/iocoder/yudao/module/iot/service/thinkmodelfunction/IotThinkModelFunctionServiceImpl.java
@@ -1,7 +1,10 @@
package cn.iocoder.yudao.module.iot.service.thinkmodelfunction;
-import cn.hutool.json.JSONUtil;
import cn.iocoder.yudao.module.iot.controller.admin.thinkmodelfunction.thingModel.*;
+import cn.iocoder.yudao.module.iot.controller.admin.thinkmodelfunction.thingModel.dataType.ThingModelArgument;
+import cn.iocoder.yudao.module.iot.controller.admin.thinkmodelfunction.thingModel.dataType.ThingModelArraySpecs;
+import cn.iocoder.yudao.module.iot.controller.admin.thinkmodelfunction.thingModel.dataType.ThingModelArrayType;
+import cn.iocoder.yudao.module.iot.controller.admin.thinkmodelfunction.thingModel.dataType.ThingModelTextType;
import cn.iocoder.yudao.module.iot.controller.admin.thinkmodelfunction.vo.IotThinkModelFunctionSaveReqVO;
import cn.iocoder.yudao.module.iot.convert.thinkmodelfunction.IotThinkModelFunctionConvert;
import cn.iocoder.yudao.module.iot.dal.dataobject.thinkmodelfunction.IotThinkModelFunctionDO;
From e47b3f0aabd2a18f60a7326109ea33e34b091673 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?=E7=97=B4=E8=B4=A7?= <252048765@qq.com>
Date: Sat, 14 Sep 2024 15:59:27 +0800
Subject: [PATCH 032/156] =?UTF-8?q?=E3=80=90=E5=8A=9F=E8=83=BD=E3=80=91?=
=?UTF-8?q?=E5=AE=8C=E6=88=90=E6=BB=A1=E5=87=8F=E9=80=81=E5=85=B3=E9=97=AD?=
=?UTF-8?q?=E7=9A=84=E5=8A=9F=E8=83=BD?=
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
---
.../convert/reward/RewardActivityConvert.java | 33 +++++++++++++++++++
.../reward/RewardActivityServiceImpl.java | 12 +++++--
2 files changed, 42 insertions(+), 3 deletions(-)
create mode 100644 yudao-module-mall/yudao-module-promotion-biz/src/main/java/cn/iocoder/yudao/module/promotion/convert/reward/RewardActivityConvert.java
diff --git a/yudao-module-mall/yudao-module-promotion-biz/src/main/java/cn/iocoder/yudao/module/promotion/convert/reward/RewardActivityConvert.java b/yudao-module-mall/yudao-module-promotion-biz/src/main/java/cn/iocoder/yudao/module/promotion/convert/reward/RewardActivityConvert.java
new file mode 100644
index 000000000..2f03f2aae
--- /dev/null
+++ b/yudao-module-mall/yudao-module-promotion-biz/src/main/java/cn/iocoder/yudao/module/promotion/convert/reward/RewardActivityConvert.java
@@ -0,0 +1,33 @@
+package cn.iocoder.yudao.module.promotion.convert.reward;
+
+import cn.iocoder.yudao.framework.common.pojo.PageResult;
+import cn.iocoder.yudao.module.promotion.api.reward.dto.RewardActivityMatchRespDTO;
+import cn.iocoder.yudao.module.promotion.controller.admin.reward.vo.RewardActivityCreateReqVO;
+import cn.iocoder.yudao.module.promotion.controller.admin.reward.vo.RewardActivityRespVO;
+import cn.iocoder.yudao.module.promotion.controller.admin.reward.vo.RewardActivityUpdateReqVO;
+import cn.iocoder.yudao.module.promotion.dal.dataobject.reward.RewardActivityDO;
+import org.mapstruct.Mapper;
+import org.mapstruct.factory.Mappers;
+
+import java.util.List;
+
+/**
+ * 满减送活动 Convert
+ *
+ * @author 芋道源码
+ */
+@Mapper
+public interface RewardActivityConvert {
+
+ RewardActivityConvert INSTANCE = Mappers.getMapper(RewardActivityConvert.class);
+
+ RewardActivityDO convert(RewardActivityCreateReqVO bean);
+
+ RewardActivityDO convert(RewardActivityUpdateReqVO bean);
+
+ RewardActivityRespVO convert(RewardActivityDO bean);
+
+ PageResult convertPage(PageResult page);
+
+ List convertList(List rewardActivityBySpuIdsAndStatusAndDateTimeLt);
+}
diff --git a/yudao-module-mall/yudao-module-promotion-biz/src/main/java/cn/iocoder/yudao/module/promotion/service/reward/RewardActivityServiceImpl.java b/yudao-module-mall/yudao-module-promotion-biz/src/main/java/cn/iocoder/yudao/module/promotion/service/reward/RewardActivityServiceImpl.java
index b475abce8..b5fd98e56 100755
--- a/yudao-module-mall/yudao-module-promotion-biz/src/main/java/cn/iocoder/yudao/module/promotion/service/reward/RewardActivityServiceImpl.java
+++ b/yudao-module-mall/yudao-module-promotion-biz/src/main/java/cn/iocoder/yudao/module/promotion/service/reward/RewardActivityServiceImpl.java
@@ -11,8 +11,10 @@ import cn.iocoder.yudao.module.promotion.controller.admin.reward.vo.RewardActivi
import cn.iocoder.yudao.module.promotion.controller.admin.reward.vo.RewardActivityCreateReqVO;
import cn.iocoder.yudao.module.promotion.controller.admin.reward.vo.RewardActivityPageReqVO;
import cn.iocoder.yudao.module.promotion.controller.admin.reward.vo.RewardActivityUpdateReqVO;
+import cn.iocoder.yudao.module.promotion.convert.reward.RewardActivityConvert;
import cn.iocoder.yudao.module.promotion.dal.dataobject.reward.RewardActivityDO;
import cn.iocoder.yudao.module.promotion.dal.mysql.reward.RewardActivityMapper;
+import cn.iocoder.yudao.module.promotion.enums.common.PromotionActivityStatusEnum;
import cn.iocoder.yudao.module.promotion.enums.common.PromotionProductScopeEnum;
import cn.iocoder.yudao.module.promotion.util.PromotionUtils;
import jakarta.annotation.Resource;
@@ -52,9 +54,13 @@ public class RewardActivityServiceImpl implements RewardActivityService {
// 1.2 校验商品是否冲突
validateRewardActivitySpuConflicts(null, createReqVO);
- // 2. 插入
- RewardActivityDO rewardActivity = BeanUtils.toBean(createReqVO, RewardActivityDO.class)
- .setStatus(PromotionUtils.calculateActivityStatus(createReqVO.getEndTime()));
+ // 插入
+ RewardActivityDO rewardActivity = RewardActivityConvert.INSTANCE.convert(createReqVO)
+ .setStatus(
+ PromotionUtils.calculateActivityStatus(createReqVO.getEndTime()).equals(CommonStatusEnum.DISABLE.getStatus())?
+ PromotionActivityStatusEnum.WAIT.getStatus():
+ PromotionActivityStatusEnum.RUN.getStatus()
+ );
rewardActivityMapper.insert(rewardActivity);
// 返回
return rewardActivity.getId();
From e44c0e668e45e9a7439ea2fe96b02160f79e3ce5 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?=E7=97=B4=E8=B4=A7?= <252048765@qq.com>
Date: Sat, 14 Sep 2024 19:01:57 +0800
Subject: [PATCH 033/156] =?UTF-8?q?=E3=80=90=E5=8A=9F=E8=83=BD=E3=80=91?=
=?UTF-8?q?=E5=AE=8C=E6=88=90=E5=95=86=E5=93=81=E5=88=97=E8=A1=A8=E4=BB=B7?=
=?UTF-8?q?=E6=A0=BC=E8=AE=A1=E7=AE=97=E6=97=B6=EF=BC=8C=E9=9C=80=E8=A6=81?=
=?UTF-8?q?=E6=94=AF=E6=8C=81=E5=87=8F=E5=85=8D=E9=87=91=E9=A2=9D=E7=9A=84?=
=?UTF-8?q?=E5=8A=9F=E8=83=BD?=
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
---
.../app/spu/AppProductSpuController.java | 10 +-
.../app/spu/vo/AppProductSpuRespVO.java | 4 +-
.../discount/dto/DiscountProductRespDTO.java | 9 ++
.../api/reward/RewardActivityApi.java | 10 ++
.../promotion/enums/ErrorCodeConstants.java | 1 +
.../api/reward/RewardActivityApiImpl.java | 8 +
.../app/activity/AppActivityController.java | 47 +++---
.../mysql/reward/RewardActivityMapper.java | 43 ++++-
.../service/reward/RewardActivityService.java | 11 ++
.../reward/RewardActivityServiceImpl.java | 19 +++
.../mapper/discount/DiscountProductMapper.xml | 2 +-
.../app/order/AppTradeOrderController.java | 150 +++++++++++++++++-
.../vo/AppTradeProductSettlementRespVO.java | 59 +++++++
.../TradeRewardActivityPriceCalculator.java | 5 +-
.../src/main/resources/application-local.yaml | 22 +--
15 files changed, 350 insertions(+), 50 deletions(-)
create mode 100644 yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/controller/app/order/vo/AppTradeProductSettlementRespVO.java
diff --git a/yudao-module-mall/yudao-module-product-biz/src/main/java/cn/iocoder/yudao/module/product/controller/app/spu/AppProductSpuController.java b/yudao-module-mall/yudao-module-product-biz/src/main/java/cn/iocoder/yudao/module/product/controller/app/spu/AppProductSpuController.java
index e4e497dba..61808fc66 100644
--- a/yudao-module-mall/yudao-module-product-biz/src/main/java/cn/iocoder/yudao/module/product/controller/app/spu/AppProductSpuController.java
+++ b/yudao-module-mall/yudao-module-product-biz/src/main/java/cn/iocoder/yudao/module/product/controller/app/spu/AppProductSpuController.java
@@ -69,8 +69,8 @@ public class AppProductSpuController {
list.forEach(spu -> spu.setSalesCount(spu.getSalesCount() + spu.getVirtualSalesCount()));
List voList = BeanUtils.toBean(list, AppProductSpuRespVO.class);
// 处理 vip 价格
- MemberLevelRespDTO memberLevel = getMemberLevel();
- voList.forEach(vo -> vo.setVipPrice(calculateVipPrice(vo.getPrice(), memberLevel)));
+// MemberLevelRespDTO memberLevel = getMemberLevel();
+// voList.forEach(vo -> vo.setVipPrice(calculateVipPrice(vo.getPrice(), memberLevel)));
return success(voList);
}
@@ -86,8 +86,8 @@ public class AppProductSpuController {
pageResult.getList().forEach(spu -> spu.setSalesCount(spu.getSalesCount() + spu.getVirtualSalesCount()));
PageResult voPageResult = BeanUtils.toBean(pageResult, AppProductSpuRespVO.class);
// 处理 vip 价格
- MemberLevelRespDTO memberLevel = getMemberLevel();
- voPageResult.getList().forEach(vo -> vo.setVipPrice(calculateVipPrice(vo.getPrice(), memberLevel)));
+// MemberLevelRespDTO memberLevel = getMemberLevel();
+// voPageResult.getList().forEach(vo -> vo.setVipPrice(calculateVipPrice(vo.getPrice(), memberLevel)));
return success(voPageResult);
}
@@ -142,7 +142,7 @@ public class AppProductSpuController {
*/
public Integer calculateVipPrice(Integer price, MemberLevelRespDTO memberLevel) {
if (memberLevel == null || memberLevel.getDiscountPercent() == null) {
- return 0;
+ return null;
}
Integer newPrice = price * memberLevel.getDiscountPercent() / 100;
return price - newPrice;
diff --git a/yudao-module-mall/yudao-module-product-biz/src/main/java/cn/iocoder/yudao/module/product/controller/app/spu/vo/AppProductSpuRespVO.java b/yudao-module-mall/yudao-module-product-biz/src/main/java/cn/iocoder/yudao/module/product/controller/app/spu/vo/AppProductSpuRespVO.java
index df61090bb..b08d4125a 100644
--- a/yudao-module-mall/yudao-module-product-biz/src/main/java/cn/iocoder/yudao/module/product/controller/app/spu/vo/AppProductSpuRespVO.java
+++ b/yudao-module-mall/yudao-module-product-biz/src/main/java/cn/iocoder/yudao/module/product/controller/app/spu/vo/AppProductSpuRespVO.java
@@ -38,8 +38,8 @@ public class AppProductSpuRespVO {
@Schema(description = "市场价,单位使用:分", requiredMode = Schema.RequiredMode.REQUIRED, example = "1024")
private Integer marketPrice;
- @Schema(description = "VIP 价格,单位使用:分", requiredMode = Schema.RequiredMode.REQUIRED, example = "968") // 通过会员等级,计算出折扣后价格
- private Integer vipPrice;
+// @Schema(description = "VIP 价格,单位使用:分", requiredMode = Schema.RequiredMode.REQUIRED, example = "968") // 通过会员等级,计算出折扣后价格
+// private Integer vipPrice;
@Schema(description = "库存", requiredMode = Schema.RequiredMode.REQUIRED, example = "666")
private Integer stock;
diff --git a/yudao-module-mall/yudao-module-promotion-api/src/main/java/cn/iocoder/yudao/module/promotion/api/discount/dto/DiscountProductRespDTO.java b/yudao-module-mall/yudao-module-promotion-api/src/main/java/cn/iocoder/yudao/module/promotion/api/discount/dto/DiscountProductRespDTO.java
index 52dfdbe27..7f143ec83 100644
--- a/yudao-module-mall/yudao-module-promotion-api/src/main/java/cn/iocoder/yudao/module/promotion/api/discount/dto/DiscountProductRespDTO.java
+++ b/yudao-module-mall/yudao-module-promotion-api/src/main/java/cn/iocoder/yudao/module/promotion/api/discount/dto/DiscountProductRespDTO.java
@@ -2,6 +2,8 @@ package cn.iocoder.yudao.module.promotion.api.discount.dto;
import lombok.Data;
+import java.time.LocalDateTime;
+
/**
* 限时折扣活动商品 Response DTO
*
@@ -44,5 +46,12 @@ public class DiscountProductRespDTO {
* 活动标题
*/
private String activityName;
+ /**
+ * 活动结束时间点
+ *
+ * 冗余 {@link DiscountActivityDO#getEndTime()}
+ */
+ private LocalDateTime activityEndTime;
+
}
diff --git a/yudao-module-mall/yudao-module-promotion-api/src/main/java/cn/iocoder/yudao/module/promotion/api/reward/RewardActivityApi.java b/yudao-module-mall/yudao-module-promotion-api/src/main/java/cn/iocoder/yudao/module/promotion/api/reward/RewardActivityApi.java
index 68f76a1fa..c703cdca0 100644
--- a/yudao-module-mall/yudao-module-promotion-api/src/main/java/cn/iocoder/yudao/module/promotion/api/reward/RewardActivityApi.java
+++ b/yudao-module-mall/yudao-module-promotion-api/src/main/java/cn/iocoder/yudao/module/promotion/api/reward/RewardActivityApi.java
@@ -3,6 +3,7 @@ package cn.iocoder.yudao.module.promotion.api.reward;
import cn.iocoder.yudao.module.promotion.api.reward.dto.RewardActivityMatchRespDTO;
import java.time.LocalDateTime;
+import java.util.Collection;
import java.util.List;
/**
@@ -21,4 +22,13 @@ public interface RewardActivityApi {
*/
List getRewardActivityListByStatusAndNow(Integer status, LocalDateTime dateTime);
+ /**
+ * 获取指定 spu 编号最近参加的活动,每个 spuId 只返回一条记录
+ *
+ * @param spuIds spu 编号
+ * @param status 状态
+ * @param dateTime 当前日期时间
+ * @return 满减送活动列表
+ */
+ List getRewardActivityBySpuIdsAndStatusAndDateTimeLt(Collection spuIds, Integer status, LocalDateTime dateTime);
}
diff --git a/yudao-module-mall/yudao-module-promotion-api/src/main/java/cn/iocoder/yudao/module/promotion/enums/ErrorCodeConstants.java b/yudao-module-mall/yudao-module-promotion-api/src/main/java/cn/iocoder/yudao/module/promotion/enums/ErrorCodeConstants.java
index 319625387..14bb6e732 100644
--- a/yudao-module-mall/yudao-module-promotion-api/src/main/java/cn/iocoder/yudao/module/promotion/enums/ErrorCodeConstants.java
+++ b/yudao-module-mall/yudao-module-promotion-api/src/main/java/cn/iocoder/yudao/module/promotion/enums/ErrorCodeConstants.java
@@ -15,6 +15,7 @@ public interface ErrorCodeConstants {
ErrorCode DISCOUNT_ACTIVITY_UPDATE_FAIL_STATUS_CLOSED = new ErrorCode(1_013_001_002, "限时折扣活动已关闭,不能修改");
ErrorCode DISCOUNT_ACTIVITY_DELETE_FAIL_STATUS_NOT_CLOSED = new ErrorCode(1_013_001_003, "限时折扣活动未关闭,不能删除");
ErrorCode DISCOUNT_ACTIVITY_CLOSE_FAIL_STATUS_CLOSED = new ErrorCode(1_013_001_004, "限时折扣活动已关闭,不能重复关闭");
+ ErrorCode DISCOUNT_ACTIVITY_TYPE_NOT_EXISTS = new ErrorCode(1_013_001_005, "限时折扣活动类型不存在");
// ========== Banner 相关 1-013-002-000 ============
ErrorCode BANNER_NOT_EXISTS = new ErrorCode(1_013_002_000, "Banner 不存在");
diff --git a/yudao-module-mall/yudao-module-promotion-biz/src/main/java/cn/iocoder/yudao/module/promotion/api/reward/RewardActivityApiImpl.java b/yudao-module-mall/yudao-module-promotion-biz/src/main/java/cn/iocoder/yudao/module/promotion/api/reward/RewardActivityApiImpl.java
index ce3d1c802..6b33fdb7c 100644
--- a/yudao-module-mall/yudao-module-promotion-biz/src/main/java/cn/iocoder/yudao/module/promotion/api/reward/RewardActivityApiImpl.java
+++ b/yudao-module-mall/yudao-module-promotion-biz/src/main/java/cn/iocoder/yudao/module/promotion/api/reward/RewardActivityApiImpl.java
@@ -2,6 +2,7 @@ package cn.iocoder.yudao.module.promotion.api.reward;
import cn.iocoder.yudao.framework.common.util.object.BeanUtils;
import cn.iocoder.yudao.module.promotion.api.reward.dto.RewardActivityMatchRespDTO;
+import cn.iocoder.yudao.module.promotion.convert.reward.RewardActivityConvert;
import cn.iocoder.yudao.module.promotion.dal.dataobject.reward.RewardActivityDO;
import cn.iocoder.yudao.module.promotion.service.reward.RewardActivityService;
import jakarta.annotation.Resource;
@@ -9,6 +10,7 @@ import org.springframework.stereotype.Service;
import org.springframework.validation.annotation.Validated;
import java.time.LocalDateTime;
+import java.util.Collection;
import java.util.List;
/**
@@ -29,4 +31,10 @@ public class RewardActivityApiImpl implements RewardActivityApi {
return BeanUtils.toBean(list, RewardActivityMatchRespDTO.class);
}
+ @Override
+ public List getRewardActivityBySpuIdsAndStatusAndDateTimeLt(Collection spuIds, Integer status, LocalDateTime dateTime) {
+ List rewardActivityBySpuIdsAndStatusAndDateTimeLt = rewardActivityService.getRewardActivityBySpuIdsAndStatusAndDateTimeLt(spuIds, status, dateTime);
+ return RewardActivityConvert.INSTANCE.convertList(rewardActivityBySpuIdsAndStatusAndDateTimeLt);
+ }
+
}
diff --git a/yudao-module-mall/yudao-module-promotion-biz/src/main/java/cn/iocoder/yudao/module/promotion/controller/app/activity/AppActivityController.java b/yudao-module-mall/yudao-module-promotion-biz/src/main/java/cn/iocoder/yudao/module/promotion/controller/app/activity/AppActivityController.java
index fae7fa54d..c2c028267 100644
--- a/yudao-module-mall/yudao-module-promotion-biz/src/main/java/cn/iocoder/yudao/module/promotion/controller/app/activity/AppActivityController.java
+++ b/yudao-module-mall/yudao-module-promotion-biz/src/main/java/cn/iocoder/yudao/module/promotion/controller/app/activity/AppActivityController.java
@@ -33,6 +33,7 @@ import org.springframework.web.bind.annotation.RestController;
import java.time.LocalDateTime;
import java.util.*;
+import java.util.stream.Collectors;
import static cn.iocoder.yudao.framework.common.pojo.CommonResult.success;
import static cn.iocoder.yudao.framework.common.util.collection.CollectionUtils.*;
@@ -150,36 +151,32 @@ public class AppActivityController {
}
private void getRewardActivityList(Collection spuIds, LocalDateTime now, List activityList) {
- // 1.1 获得所有的活动
- List rewardActivityList = rewardActivityService.getRewardActivityListByStatusAndDateTimeLt(
- CommonStatusEnum.ENABLE.getStatus(), now);
+ // TODO @puhui999:有 3 范围,不只 spuId,还有 categoryId,全部,下次 fix
+ List rewardActivityList = rewardActivityService.getRewardActivityBySpuIdsAndStatusAndDateTimeLt(
+ spuIds, CommonStatusEnum.ENABLE.getStatus(), now);
if (CollUtil.isEmpty(rewardActivityList)) {
return;
}
- // 1.2 获得所有的商品信息
- List spuList = productSpuApi.getSpuList(spuIds);
- if (CollUtil.isEmpty(spuList)) {
- return;
- }
- // 2. 构建活动
- for (RewardActivityDO rewardActivity : rewardActivityList) {
- // 情况一:所有商品都能参加
- if (PromotionProductScopeEnum.isAll(rewardActivity.getProductScope())) {
- buildAppActivityRespVO(rewardActivity, spuIds, activityList);
- }
- // 情况二:指定商品参加
- if (PromotionProductScopeEnum.isSpu(rewardActivity.getProductScope())) {
- List fSpuIds = spuList.stream().map(ProductSpuRespDTO::getId).filter(id ->
- rewardActivity.getProductScopeValues().contains(id)).toList();
- buildAppActivityRespVO(rewardActivity, fSpuIds, activityList);
- }
- // 情况三:指定商品类型参加
- if (PromotionProductScopeEnum.isCategory(rewardActivity.getProductScope())) {
- List fSpuIds = spuList.stream().filter(spuItem -> rewardActivity.getProductScopeValues()
- .contains(spuItem.getCategoryId())).map(ProductSpuRespDTO::getId).toList();
- buildAppActivityRespVO(rewardActivity, fSpuIds, activityList);
+ Map> spuIdAndActivityMap = spuIds.stream()
+ .collect(Collectors.toMap(
+ spuId -> spuId,
+ spuId -> rewardActivityList.stream()
+ .filter(activity ->
+ ( activity.getProductScopeValues()!=null &&
+ (activity.getProductScopeValues().contains(spuId) ||
+ activity.getProductScopeValues().contains(productSpuApi.getSpu(spuId).getCategoryId()))) ||
+ activity.getProductScope()==1
+ )
+ .max(Comparator.comparing(RewardActivityDO::getCreateTime))));
+ for (Long supId : spuIdAndActivityMap.keySet()) {
+ if (spuIdAndActivityMap.get(supId).isEmpty()) {
+ continue;
}
+
+ RewardActivityDO rewardActivityDO = spuIdAndActivityMap.get(supId).get();
+ activityList.add(new AppActivityRespVO(rewardActivityDO.getId(), PromotionTypeEnum.REWARD_ACTIVITY.getType(),
+ rewardActivityDO.getName(), supId, rewardActivityDO.getStartTime(), rewardActivityDO.getEndTime()));
}
}
diff --git a/yudao-module-mall/yudao-module-promotion-biz/src/main/java/cn/iocoder/yudao/module/promotion/dal/mysql/reward/RewardActivityMapper.java b/yudao-module-mall/yudao-module-promotion-biz/src/main/java/cn/iocoder/yudao/module/promotion/dal/mysql/reward/RewardActivityMapper.java
index 6f377fb60..51c076a25 100755
--- a/yudao-module-mall/yudao-module-promotion-biz/src/main/java/cn/iocoder/yudao/module/promotion/dal/mysql/reward/RewardActivityMapper.java
+++ b/yudao-module-mall/yudao-module-promotion-biz/src/main/java/cn/iocoder/yudao/module/promotion/dal/mysql/reward/RewardActivityMapper.java
@@ -1,14 +1,19 @@
package cn.iocoder.yudao.module.promotion.dal.mysql.reward;
+import cn.hutool.core.util.StrUtil;
import cn.iocoder.yudao.framework.common.pojo.PageResult;
import cn.iocoder.yudao.framework.mybatis.core.mapper.BaseMapperX;
import cn.iocoder.yudao.framework.mybatis.core.query.LambdaQueryWrapperX;
import cn.iocoder.yudao.module.promotion.controller.admin.reward.vo.RewardActivityPageReqVO;
import cn.iocoder.yudao.module.promotion.dal.dataobject.reward.RewardActivityDO;
+import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import org.apache.ibatis.annotations.Mapper;
import java.time.LocalDateTime;
+import java.util.Collection;
import java.util.List;
+import java.util.function.Function;
+import java.util.stream.Collectors;
/**
* 满减送活动 Mapper
@@ -25,13 +30,47 @@ public interface RewardActivityMapper extends BaseMapperX {
.orderByDesc(RewardActivityDO::getId));
}
+ default List selectListBySpuIdsAndStatus(Collection spuIds, Integer status) {
+ Function, String> productScopeValuesFindInSetFunc = ids -> ids.stream()
+ .map(id -> StrUtil.format("FIND_IN_SET({}, product_scope_values) ", id))
+ .collect(Collectors.joining(" OR "));
+ return selectList(new QueryWrapper()
+ .eq("status", status)
+ .apply(productScopeValuesFindInSetFunc.apply(spuIds)));
+ }
+
+ /**
+ * 获取指定活动编号的活动列表且
+ * 开始时间和结束时间小于给定时间 dateTime 的活动列表
+ *
+ * @param status 状态
+ * @param dateTime 指定日期
+ * @return 活动列表
+ */
default List selectListByStatusAndDateTimeLt(Integer status, LocalDateTime dateTime) {
return selectList(new LambdaQueryWrapperX()
.eq(RewardActivityDO::getStatus, status)
- // 开始时间 < 指定时间(dateTime) < 结束时间,也就是说获取指定时间段的活动
- .lt(RewardActivityDO::getStartTime, dateTime).gt(RewardActivityDO::getEndTime, dateTime)
+ .lt(RewardActivityDO::getStartTime, dateTime)
+ .gt(RewardActivityDO::getEndTime, dateTime)// 开始时间 < 指定时间 < 结束时间,也就是说获取指定时间段的活动
.orderByAsc(RewardActivityDO::getStartTime)
);
}
+ default List getRewardActivityByStatusAndDateTimeLt(Collection spuIds,Collection categoryIds, Integer status, LocalDateTime dateTime) {
+ //拼接通用券查询语句
+ Function, String> productScopeValuesFindInSetFunc = ids -> ids.stream()
+ .map(id -> StrUtil.format("FIND_IN_SET({}, product_scope_values) ", id))
+ .collect(Collectors.joining(" OR "));
+ return selectList(new LambdaQueryWrapperX()
+ .eq(RewardActivityDO::getStatus,status)
+ .lt(RewardActivityDO::getStartTime, dateTime)
+ .gt(RewardActivityDO::getEndTime, dateTime)
+ .and(i -> i. eq(RewardActivityDO::getProductScope, 2).and(i1 -> i1.apply(productScopeValuesFindInSetFunc.apply(spuIds))))
+ .or(i -> i.eq(RewardActivityDO::getProductScope, 1))
+ .or(i -> i. eq(RewardActivityDO::getProductScope, 3).and(i1 -> i1.apply(productScopeValuesFindInSetFunc.apply(categoryIds))))
+ .orderByDesc(RewardActivityDO::getId)
+ .last("limit 1")
+ );
+ }
+
}
diff --git a/yudao-module-mall/yudao-module-promotion-biz/src/main/java/cn/iocoder/yudao/module/promotion/service/reward/RewardActivityService.java b/yudao-module-mall/yudao-module-promotion-biz/src/main/java/cn/iocoder/yudao/module/promotion/service/reward/RewardActivityService.java
index d35e0874a..ab6b2e79b 100755
--- a/yudao-module-mall/yudao-module-promotion-biz/src/main/java/cn/iocoder/yudao/module/promotion/service/reward/RewardActivityService.java
+++ b/yudao-module-mall/yudao-module-promotion-biz/src/main/java/cn/iocoder/yudao/module/promotion/service/reward/RewardActivityService.java
@@ -8,6 +8,7 @@ import cn.iocoder.yudao.module.promotion.dal.dataobject.reward.RewardActivityDO;
import jakarta.validation.Valid;
import java.time.LocalDateTime;
+import java.util.Collection;
import java.util.List;
/**
@@ -71,4 +72,14 @@ public interface RewardActivityService {
*/
List getRewardActivityListByStatusAndDateTimeLt(Integer status, LocalDateTime dateTime);
+ /**
+ * 获取指定 spu 编号最近参加的活动,每个 spuId 只返回一条记录
+ *
+ * @param spuIds spu 编号
+ * @param status 状态
+ * @param dateTime 当前日期时间
+ * @return 满减送活动列表
+ */
+ List getRewardActivityBySpuIdsAndStatusAndDateTimeLt(Collection spuIds, Integer status, LocalDateTime dateTime);
+
}
diff --git a/yudao-module-mall/yudao-module-promotion-biz/src/main/java/cn/iocoder/yudao/module/promotion/service/reward/RewardActivityServiceImpl.java b/yudao-module-mall/yudao-module-promotion-biz/src/main/java/cn/iocoder/yudao/module/promotion/service/reward/RewardActivityServiceImpl.java
index b5fd98e56..96ad87b2f 100755
--- a/yudao-module-mall/yudao-module-promotion-biz/src/main/java/cn/iocoder/yudao/module/promotion/service/reward/RewardActivityServiceImpl.java
+++ b/yudao-module-mall/yudao-module-promotion-biz/src/main/java/cn/iocoder/yudao/module/promotion/service/reward/RewardActivityServiceImpl.java
@@ -1,5 +1,6 @@
package cn.iocoder.yudao.module.promotion.service.reward;
+import cn.hutool.core.collection.CollUtil;
import cn.hutool.core.date.LocalDateTimeUtil;
import cn.iocoder.yudao.framework.common.enums.CommonStatusEnum;
import cn.iocoder.yudao.framework.common.pojo.PageResult;
@@ -22,8 +23,11 @@ import org.springframework.stereotype.Service;
import org.springframework.validation.annotation.Validated;
import java.time.LocalDateTime;
+import java.util.Collection;
+import java.util.Collections;
import java.util.List;
import java.util.Objects;
+import java.util.stream.Collectors;
import static cn.hutool.core.collection.CollUtil.intersectionDistinct;
import static cn.iocoder.yudao.framework.common.exception.util.ServiceExceptionUtil.exception;
@@ -205,4 +209,19 @@ public class RewardActivityServiceImpl implements RewardActivityService {
return rewardActivityMapper.selectListByStatusAndDateTimeLt(status, dateTime);
}
+ @Override
+ public List getRewardActivityBySpuIdsAndStatusAndDateTimeLt(Collection spuIds, Integer status, LocalDateTime dateTime) {
+ List spuList = productSpuApi.validateSpuList(spuIds);
+ //查询出商品的分类ids
+ List categoryIds = spuList.stream().map(ProductSpuRespDTO::getCategoryId).collect(Collectors.toList());
+ // 1. 查询出指定 spuId 的 spu 参加的活动
+ List rewardActivityList = rewardActivityMapper.getRewardActivityByStatusAndDateTimeLt(spuIds, categoryIds,status,dateTime);
+ if (CollUtil.isEmpty(rewardActivityList)) {
+ return Collections.emptyList();
+ }
+
+ // 2. 查询活动详情
+ return rewardActivityList;
+ }
+
}
diff --git a/yudao-module-mall/yudao-module-promotion-biz/src/main/resources/mapper/discount/DiscountProductMapper.xml b/yudao-module-mall/yudao-module-promotion-biz/src/main/resources/mapper/discount/DiscountProductMapper.xml
index 76af37db2..51e1d8f71 100644
--- a/yudao-module-mall/yudao-module-promotion-biz/src/main/resources/mapper/discount/DiscountProductMapper.xml
+++ b/yudao-module-mall/yudao-module-promotion-biz/src/main/resources/mapper/discount/DiscountProductMapper.xml
@@ -16,7 +16,7 @@
AND pda.start_time <= CURRENT_TIME AND pda.end_time >= CURRENT_TIME
- AND pda.`status` = 20
+ AND pda.`status` = 0
AND pda.deleted != 1
diff --git a/yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/controller/app/order/AppTradeOrderController.java b/yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/controller/app/order/AppTradeOrderController.java
index b1280d8c1..e4ae2f57d 100644
--- a/yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/controller/app/order/AppTradeOrderController.java
+++ b/yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/controller/app/order/AppTradeOrderController.java
@@ -1,9 +1,23 @@
package cn.iocoder.yudao.module.trade.controller.app.order;
+import cn.iocoder.yudao.framework.common.enums.CommonStatusEnum;
import cn.iocoder.yudao.framework.common.pojo.CommonResult;
import cn.iocoder.yudao.framework.common.pojo.PageResult;
import cn.iocoder.yudao.framework.security.core.annotations.PreAuthenticated;
+import cn.iocoder.yudao.module.member.api.level.MemberLevelApi;
+import cn.iocoder.yudao.module.member.api.level.dto.MemberLevelRespDTO;
+import cn.iocoder.yudao.module.member.api.user.MemberUserApi;
+import cn.iocoder.yudao.module.member.api.user.dto.MemberUserRespDTO;
import cn.iocoder.yudao.module.pay.api.notify.dto.PayOrderNotifyReqDTO;
+import cn.iocoder.yudao.module.product.api.sku.ProductSkuApi;
+import cn.iocoder.yudao.module.product.api.sku.dto.ProductSkuRespDTO;
+import cn.iocoder.yudao.module.promotion.api.discount.DiscountActivityApi;
+import cn.iocoder.yudao.module.promotion.api.discount.dto.DiscountProductRespDTO;
+import cn.iocoder.yudao.module.promotion.api.reward.RewardActivityApi;
+import cn.iocoder.yudao.module.promotion.api.reward.dto.RewardActivityMatchRespDTO;
+import cn.iocoder.yudao.module.promotion.enums.common.PromotionConditionTypeEnum;
+import cn.iocoder.yudao.module.promotion.enums.common.PromotionDiscountTypeEnum;
+import cn.iocoder.yudao.module.promotion.enums.common.PromotionTypeEnum;
import cn.iocoder.yudao.module.trade.controller.app.order.vo.*;
import cn.iocoder.yudao.module.trade.controller.app.order.vo.item.AppTradeOrderItemCommentCreateReqVO;
import cn.iocoder.yudao.module.trade.controller.app.order.vo.item.AppTradeOrderItemRespVO;
@@ -27,12 +41,14 @@ import lombok.extern.slf4j.Slf4j;
import org.springframework.validation.annotation.Validated;
import org.springframework.web.bind.annotation.*;
-import java.util.List;
-import java.util.Map;
+import java.time.LocalDateTime;
+import java.util.*;
+import static cn.iocoder.yudao.framework.common.exception.util.ServiceExceptionUtil.exception;
import static cn.iocoder.yudao.framework.common.pojo.CommonResult.success;
import static cn.iocoder.yudao.framework.common.util.collection.CollectionUtils.convertSet;
import static cn.iocoder.yudao.framework.security.core.util.SecurityFrameworkUtils.getLoginUserId;
+import static cn.iocoder.yudao.module.promotion.enums.ErrorCodeConstants.DISCOUNT_ACTIVITY_TYPE_NOT_EXISTS;
@Tag(name = "用户 App - 交易订单")
@RestController
@@ -54,6 +70,17 @@ public class AppTradeOrderController {
@Resource
private TradeOrderProperties tradeOrderProperties;
+ @Resource
+ private MemberLevelApi memberLevelApi;
+ @Resource
+ private MemberUserApi memberUserApi;
+ @Resource
+ private DiscountActivityApi discountActivityApi;
+ @Resource
+ private RewardActivityApi rewardActivityApi;
+ @Resource
+ private ProductSkuApi productKpuApi;
+
@GetMapping("/settlement")
@Operation(summary = "获得订单结算信息")
@PreAuthenticated
@@ -61,6 +88,51 @@ public class AppTradeOrderController {
return success(tradeOrderUpdateService.settlementOrder(getLoginUserId(), settlementReqVO));
}
+ @GetMapping("/settlementProduct")
+ @Operation(summary = "获得商品结算信息")
+ public CommonResult> settlementProduct(@RequestParam("ids") Set ids) {
+ List appTradeProductSettlementRespVOS = new ArrayList<>();
+ MemberLevelRespDTO memberLevel = getMemberLevel();
+ ids.forEach(spuId -> {
+ List skus = new ArrayList<>();
+ List skuList = productKpuApi.getSkuListBySpuId(Collections.singletonList(spuId));
+ //查询sku的会员和限时优惠
+ skuList.forEach(sku -> {
+ //查询限时优惠价格
+ AppTradeProductSettlementRespVO.Sku skuDiscount = calculateDiscountPrice(sku.getId(), sku.getPrice());
+ if(skuDiscount != null){
+ skus.add(skuDiscount);
+ }
+
+ //查询会员价
+ AppTradeProductSettlementRespVO.Sku skuVip = calculateVipPrice(sku.getId(), sku.getPrice(), memberLevel);
+ if(skuVip != null){
+ skus.add(skuVip);
+ }
+ });
+ AppTradeProductSettlementRespVO.Reward reward = calculateReward(spuId);
+ AppTradeProductSettlementRespVO respVO = AppTradeProductSettlementRespVO.builder().id(spuId).skus(skus).build();
+ if(reward != null){
+ //创建满减活动对象
+ respVO.setReward(reward);
+ }
+ appTradeProductSettlementRespVOS.add(respVO);
+ });
+ return success(appTradeProductSettlementRespVOS);
+ }
+
+ private MemberLevelRespDTO getMemberLevel() {
+ Long userId = getLoginUserId();
+ if (userId == null) {
+ return null;
+ }
+ MemberUserRespDTO user = memberUserApi.getUser(userId);
+ if (user.getLevelId() == null || user.getLevelId() <= 0) {
+ return null;
+ }
+ return memberLevelApi.getMemberLevel(user.getLevelId());
+ }
+
@PostMapping("/create")
@Operation(summary = "创建订单")
@PreAuthenticated
@@ -188,4 +260,78 @@ public class AppTradeOrderController {
return success(tradeOrderUpdateService.createOrderItemCommentByMember(getLoginUserId(), createReqVO));
}
+ /**
+ * 计算会员 VIP 优惠价格
+ *
+ * @param price 原价
+ * @param memberLevel 会员等级
+ * @return 优惠价格
+ */
+ public AppTradeProductSettlementRespVO.Sku calculateVipPrice(Long skuId, Integer price, MemberLevelRespDTO memberLevel) {
+ if (memberLevel == null || memberLevel.getDiscountPercent() == null) {
+ return null;
+ }
+ Integer newPrice = price * memberLevel.getDiscountPercent() / 100;
+ return AppTradeProductSettlementRespVO.Sku.builder().
+ skuId(skuId).
+ type(PromotionTypeEnum.MEMBER_LEVEL.getType()).
+ price(price - newPrice).build();
+ }
+
+ /**
+ * 计算限时优惠信息
+ *
+ * @param price 原价
+ * @param skuId 商品规格id
+ * @return 优惠价格
+ */
+ private AppTradeProductSettlementRespVO.Sku calculateDiscountPrice(Long skuId, Integer price) {
+ if (skuId == null) {
+ return null;
+ }
+
+ //根据商品id查询限时优惠
+ List matchDiscountProductList = discountActivityApi.getMatchDiscountProductList(Collections.singletonList(skuId));
+ if (matchDiscountProductList != null && !matchDiscountProductList.isEmpty()) {
+ DiscountProductRespDTO discountProductRespDTO = matchDiscountProductList.get(matchDiscountProductList.size() - 1);
+ AppTradeProductSettlementRespVO.Sku sku = AppTradeProductSettlementRespVO.Sku.builder().
+ skuId(skuId).
+ discountId(discountProductRespDTO.getId()).
+ type(PromotionTypeEnum.DISCOUNT_ACTIVITY.getType()).
+ endTime(discountProductRespDTO.getActivityEndTime()).
+ build();
+ Integer discountType = discountProductRespDTO.getDiscountType();
+ if(Objects.equals(PromotionDiscountTypeEnum.PRICE.getType(), discountType)){
+ sku.setPrice(price - discountProductRespDTO.getDiscountPrice() * 100);
+ }else if(Objects.equals(PromotionDiscountTypeEnum.PERCENT.getType(), discountType)){
+ Integer newPrice = price * discountProductRespDTO.getDiscountPercent() / 100;
+ sku.setPrice(price - newPrice);
+ }else{
+ throw exception(DISCOUNT_ACTIVITY_TYPE_NOT_EXISTS);
+ }
+ return sku;
+ }
+ return null;
+ }
+
+ /**
+ * 获取第一层满减活动
+ *
+ * @param spuId 商品规格id
+ * @return 优惠价格
+ */
+ private AppTradeProductSettlementRespVO.Reward calculateReward(Long spuId) {
+ List matchRewardActivityList = rewardActivityApi.getRewardActivityBySpuIdsAndStatusAndDateTimeLt(Collections.singletonList(spuId), CommonStatusEnum.ENABLE.getStatus(), LocalDateTime.now());
+ if(matchRewardActivityList != null && !matchRewardActivityList.isEmpty()){
+ RewardActivityMatchRespDTO rewardActivityMatchRespDTO = matchRewardActivityList.get(matchRewardActivityList.size() - 1);
+ if(rewardActivityMatchRespDTO != null){
+ RewardActivityMatchRespDTO.Rule rule = rewardActivityMatchRespDTO.getRules().get(0);
+ return AppTradeProductSettlementRespVO.Reward.builder().
+ rewardActivity("满" + rule.getLimit() / 100 + (Objects.equals(rewardActivityMatchRespDTO.getConditionType(), PromotionConditionTypeEnum.PRICE.getType())?"元":"件"+"减") +rule.getDiscountPrice() / 100)
+ .rewardId(rewardActivityMatchRespDTO.getId()).build();
+ }
+ }
+ return null;
+ }
+
}
diff --git a/yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/controller/app/order/vo/AppTradeProductSettlementRespVO.java b/yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/controller/app/order/vo/AppTradeProductSettlementRespVO.java
new file mode 100644
index 000000000..67c407924
--- /dev/null
+++ b/yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/controller/app/order/vo/AppTradeProductSettlementRespVO.java
@@ -0,0 +1,59 @@
+package cn.iocoder.yudao.module.trade.controller.app.order.vo;
+
+import io.swagger.v3.oas.annotations.media.Schema;
+import lombok.Builder;
+import lombok.Data;
+
+import java.io.Serializable;
+import java.time.LocalDateTime;
+import java.util.List;
+
+@Schema(description = "用户 App - 商品结算信息 Response VO")
+@Data
+@Builder
+public class AppTradeProductSettlementRespVO {
+
+ @Schema(description = "商品编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "1")
+ private Long id;
+
+ @Schema(description = "满减活动对象", requiredMode = Schema.RequiredMode.REQUIRED, example = "1")
+ private Reward reward;
+
+ @Schema(description = "sku活动信息", requiredMode = Schema.RequiredMode.REQUIRED, example = "1")
+ private List skus;
+
+ /**
+ * 满减活动
+ */
+ @Data
+ @Builder
+ public static class Reward implements Serializable {
+ @Schema(description = "满减活动编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "1")
+ private Long rewardId;
+
+ @Schema(description = "满减活动信息", requiredMode = Schema.RequiredMode.REQUIRED, example = "1")
+ private String rewardActivity;
+ }
+
+ /**
+ * SKU 数组
+ */
+ @Data
+ @Builder
+ public static class Sku implements Serializable {
+ @Schema(description = "商品 SKU 编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "1")
+ private Long skuId;
+
+ @Schema(description = "价格", requiredMode = Schema.RequiredMode.REQUIRED, example = "1")
+ private Integer price;
+
+ @Schema(description = "营销类型", requiredMode = Schema.RequiredMode.REQUIRED, example = "1") //PromotionTypeEnum
+ private Integer type;
+
+ @Schema(description = "限时优惠id", requiredMode = Schema.RequiredMode.REQUIRED)
+ private Long discountId;
+
+ @Schema(description = "活动结束时间", requiredMode = Schema.RequiredMode.REQUIRED)
+ private LocalDateTime endTime;
+ }
+}
diff --git a/yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/service/price/calculator/TradeRewardActivityPriceCalculator.java b/yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/service/price/calculator/TradeRewardActivityPriceCalculator.java
index 261eefd68..c2d64a6f2 100644
--- a/yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/service/price/calculator/TradeRewardActivityPriceCalculator.java
+++ b/yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/service/price/calculator/TradeRewardActivityPriceCalculator.java
@@ -23,6 +23,7 @@ import java.util.Comparator;
import java.util.List;
import java.util.Map;
+import static cn.iocoder.yudao.framework.common.util.collection.CollectionUtils.convertSet;
import static cn.iocoder.yudao.framework.common.util.collection.CollectionUtils.filterList;
import static cn.iocoder.yudao.module.trade.service.price.calculator.TradePriceCalculatorHelper.formatPrice;
@@ -47,8 +48,8 @@ public class TradeRewardActivityPriceCalculator implements TradePriceCalculator
return;
}
// 获得 SKU 对应的满减送活动
- List rewardActivities = rewardActivityApi.getRewardActivityListByStatusAndNow(
- CommonStatusEnum.ENABLE.getStatus(), LocalDateTime.now());
+ List rewardActivities = rewardActivityApi.getRewardActivityBySpuIdsAndStatusAndDateTimeLt(
+ convertSet(result.getItems(), TradePriceCalculateRespBO.OrderItem::getSpuId), CommonStatusEnum.ENABLE.getStatus(), LocalDateTime.now());
if (CollUtil.isEmpty(rewardActivities)) {
return;
}
diff --git a/yudao-server/src/main/resources/application-local.yaml b/yudao-server/src/main/resources/application-local.yaml
index 40c0919b7..86cfbda91 100644
--- a/yudao-server/src/main/resources/application-local.yaml
+++ b/yudao-server/src/main/resources/application-local.yaml
@@ -6,7 +6,7 @@ spring:
# 数据源配置项
autoconfigure:
exclude:
- - org.springframework.boot.autoconfigure.quartz.QuartzAutoConfiguration # 默认 local 环境,不开启 Quartz 的自动配置
+ #- org.springframework.boot.autoconfigure.quartz.QuartzAutoConfiguration # 默认 local 环境,不开启 Quartz 的自动配置
- de.codecentric.boot.admin.server.config.AdminServerAutoConfiguration # 禁用 Spring Boot Admin 的 Server 的自动配置
- de.codecentric.boot.admin.server.ui.config.AdminServerUiAutoConfiguration # 禁用 Spring Boot Admin 的 Server UI 的自动配置
- de.codecentric.boot.admin.client.config.SpringBootAdminClientAutoConfiguration # 禁用 Spring Boot Admin 的 Client 的自动配置
@@ -45,7 +45,7 @@ spring:
primary: master
datasource:
master:
- url: jdbc:mysql://127.0.0.1:3306/ruoyi-vue-pro?useSSL=false&serverTimezone=Asia/Shanghai&allowPublicKeyRetrieval=true&nullCatalogMeansCurrent=true&rewriteBatchedStatements=true # MySQL Connector/J 8.X 连接的示例
+ url: jdbc:mysql://192.168.10.207:3306/specialty?useSSL=false&serverTimezone=Asia/Shanghai&allowPublicKeyRetrieval=true&nullCatalogMeansCurrent=true&rewriteBatchedStatements=true # MySQL Connector/J 8.X 连接的示例
# url: jdbc:mysql://127.0.0.1:3306/ruoyi-vue-pro?useSSL=true&allowPublicKeyRetrieval=true&useUnicode=true&characterEncoding=UTF-8&serverTimezone=Asia/Shanghai&rewriteBatchedStatements=true # MySQL Connector/J 5.X 连接的示例
# url: jdbc:postgresql://127.0.0.1:5432/ruoyi-vue-pro # PostgreSQL 连接的示例
# url: jdbc:oracle:thin:@127.0.0.1:1521:xe # Oracle 连接的示例
@@ -61,19 +61,19 @@ spring:
# password: SYSDBA001 # DM 连接的示例
# username: root # OpenGauss 连接的示例
# password: Yudao@2024 # OpenGauss 连接的示例
- slave: # 模拟从库,可根据自己需要修改
- lazy: true # 开启懒加载,保证启动速度
- url: jdbc:mysql://127.0.0.1:3306/ruoyi-vue-pro?useSSL=false&serverTimezone=Asia/Shanghai&allowPublicKeyRetrieval=true&rewriteBatchedStatements=true&nullCatalogMeansCurrent=true
- username: root
- password: 123456
+# slave: # 模拟从库,可根据自己需要修改
+# lazy: true # 开启懒加载,保证启动速度
+# url: jdbc:mysql://192.168.10.207:3306/ruoyi-vue-pro?useSSL=false&serverTimezone=Asia/Shanghai&allowPublicKeyRetrieval=true&rewriteBatchedStatements=true&nullCatalogMeansCurrent=true
+# username: root
+# password: 123456
# Redis 配置。Redisson 默认的配置足够使用,一般不需要进行调优
data:
redis:
- host: 127.0.0.1 # 地址
+ host: 192.168.10.207 # 地址
port: 6379 # 端口
database: 0 # 数据库索引
-# password: dev # 密码,建议生产环境开启
+ password: 123456 # 密码,建议生产环境开启
--- #################### 定时任务相关配置 ####################
@@ -200,8 +200,8 @@ wx:
# secret: 6f270509224a7ae1296bbf1c8cb97aed
# appid: wxc4598c446f8a9cb3 # 测试号(Kongdy 提供的)
# secret: 4a1a04e07f6a4a0751b39c3064a92c8b
- appid: wx66186af0759f47c9 # 测试号(puhui 提供的)
- secret: 3218bcbd112cbc614c7264ceb20144ac
+ appid: wx9a0a5b259d852380 # 测试号(puhui 提供的)
+ secret: 70e65fa9d1a4f2c4e1b2aa8751d3b75e
config-storage:
type: RedisTemplate # 采用 RedisTemplate 操作 Redis,会自动从 Spring 中获取
key-prefix: wa # Redis Key 的前缀
From 86b02b698a99e186366b36b62aa1c07d80802c05 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?=E7=97=B4=E8=B4=A7?= <252048765@qq.com>
Date: Sat, 14 Sep 2024 19:10:21 +0800
Subject: [PATCH 034/156] =?UTF-8?q?=E3=80=90=E5=8A=9F=E8=83=BD=E3=80=91?=
=?UTF-8?q?=E5=AE=8C=E6=88=90=E4=B8=8B=E5=8D=95=E7=A1=AE=E8=AE=A4=E9=A1=B5?=
=?UTF-8?q?=E4=BB=B7=E6=A0=BC=E8=AE=A1=E7=AE=97=E5=8A=9F=E8=83=BD=EF=BC=88?=
=?UTF-8?q?=E5=8F=AA=E5=81=9A=E4=BA=86=E6=BB=A1=E5=87=8F=EF=BC=8C=E8=BF=98?=
=?UTF-8?q?=E6=B2=A1=E5=81=9A=E6=BB=A1=E9=80=81=EF=BC=89?=
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
---
.../promotion/enums/ErrorCodeConstants.java | 1 +
.../mysql/discount/DiscountProductMapper.java | 3 +-
.../discount/DiscountActivityService.java | 3 +-
.../discount/DiscountActivityServiceImpl.java | 5 +-
.../mapper/discount/DiscountProductMapper.xml | 8 +-
.../vo/AppTradeOrderSettlementRespVO.java | 8 ++
.../TradeDiscountActivityPriceCalculator.java | 87 ++++++++++++++++---
.../TradeMemberLevelPriceCalculator.java | 77 ++++++++--------
.../TradeRewardActivityPriceCalculator.java | 26 +++---
9 files changed, 149 insertions(+), 69 deletions(-)
diff --git a/yudao-module-mall/yudao-module-promotion-api/src/main/java/cn/iocoder/yudao/module/promotion/enums/ErrorCodeConstants.java b/yudao-module-mall/yudao-module-promotion-api/src/main/java/cn/iocoder/yudao/module/promotion/enums/ErrorCodeConstants.java
index 14bb6e732..5f785dccf 100644
--- a/yudao-module-mall/yudao-module-promotion-api/src/main/java/cn/iocoder/yudao/module/promotion/enums/ErrorCodeConstants.java
+++ b/yudao-module-mall/yudao-module-promotion-api/src/main/java/cn/iocoder/yudao/module/promotion/enums/ErrorCodeConstants.java
@@ -46,6 +46,7 @@ public interface ErrorCodeConstants {
ErrorCode REWARD_ACTIVITY_DELETE_FAIL_STATUS_NOT_CLOSED = new ErrorCode(1_013_006_003, "满减送活动未关闭,不能删除");
ErrorCode REWARD_ACTIVITY_CLOSE_FAIL_STATUS_CLOSED = new ErrorCode(1_013_006_004, "满减送活动已关闭,不能重复关闭");
ErrorCode REWARD_ACTIVITY_SCOPE_EXISTS = new ErrorCode(1_013_006_005, "与该时间段已存在的满减送活动商品范围冲突");
+ ErrorCode REWARD_ACTIVITY_TYPE_NOT_EXISTS = new ErrorCode(1_013_006_006, "满减送活动类型不存在");
// ========== TODO 空着 1-013-007-000 ============
diff --git a/yudao-module-mall/yudao-module-promotion-biz/src/main/java/cn/iocoder/yudao/module/promotion/dal/mysql/discount/DiscountProductMapper.java b/yudao-module-mall/yudao-module-promotion-biz/src/main/java/cn/iocoder/yudao/module/promotion/dal/mysql/discount/DiscountProductMapper.java
index 5257b836d..263afe5e4 100755
--- a/yudao-module-mall/yudao-module-promotion-biz/src/main/java/cn/iocoder/yudao/module/promotion/dal/mysql/discount/DiscountProductMapper.java
+++ b/yudao-module-mall/yudao-module-promotion-biz/src/main/java/cn/iocoder/yudao/module/promotion/dal/mysql/discount/DiscountProductMapper.java
@@ -1,6 +1,7 @@
package cn.iocoder.yudao.module.promotion.dal.mysql.discount;
import cn.iocoder.yudao.framework.mybatis.core.mapper.BaseMapperX;
+import cn.iocoder.yudao.module.promotion.api.discount.dto.DiscountProductRespDTO;
import cn.iocoder.yudao.module.promotion.dal.dataobject.discount.DiscountProductDO;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import org.apache.ibatis.annotations.Mapper;
@@ -31,7 +32,7 @@ public interface DiscountProductMapper extends BaseMapperX {
}
// TODO @zhangshuai:逻辑里,尽量避免写 join 语句哈,你可以看看这个查询,有什么办法优化?目前的一个思路,是分 2 次查询,性能也是 ok 的
- List getMatchDiscountProductList(@Param("skuIds") Collection skuIds);
+ List getMatchDiscountProductList(@Param("skuIds") Collection skuIds);
/**
* 查询出指定 spuId 的 spu 参加的活动最接近现在的一条记录。多个的话,一个 spuId 对应一个最近的活动编号
diff --git a/yudao-module-mall/yudao-module-promotion-biz/src/main/java/cn/iocoder/yudao/module/promotion/service/discount/DiscountActivityService.java b/yudao-module-mall/yudao-module-promotion-biz/src/main/java/cn/iocoder/yudao/module/promotion/service/discount/DiscountActivityService.java
index e08c7e2b5..42f27f6de 100644
--- a/yudao-module-mall/yudao-module-promotion-biz/src/main/java/cn/iocoder/yudao/module/promotion/service/discount/DiscountActivityService.java
+++ b/yudao-module-mall/yudao-module-promotion-biz/src/main/java/cn/iocoder/yudao/module/promotion/service/discount/DiscountActivityService.java
@@ -1,6 +1,7 @@
package cn.iocoder.yudao.module.promotion.service.discount;
import cn.iocoder.yudao.framework.common.pojo.PageResult;
+import cn.iocoder.yudao.module.promotion.api.discount.dto.DiscountProductRespDTO;
import cn.iocoder.yudao.module.promotion.controller.admin.discount.vo.DiscountActivityCreateReqVO;
import cn.iocoder.yudao.module.promotion.controller.admin.discount.vo.DiscountActivityPageReqVO;
import cn.iocoder.yudao.module.promotion.controller.admin.discount.vo.DiscountActivityUpdateReqVO;
@@ -27,7 +28,7 @@ public interface DiscountActivityService {
* @param skuIds SKU 编号数组
* @return 匹配的限时折扣商品
*/
- List getMatchDiscountProductList(Collection skuIds);
+ List getMatchDiscountProductList(Collection skuIds);
/**
* 创建限时折扣活动
diff --git a/yudao-module-mall/yudao-module-promotion-biz/src/main/java/cn/iocoder/yudao/module/promotion/service/discount/DiscountActivityServiceImpl.java b/yudao-module-mall/yudao-module-promotion-biz/src/main/java/cn/iocoder/yudao/module/promotion/service/discount/DiscountActivityServiceImpl.java
index 0c995267b..95694d52f 100644
--- a/yudao-module-mall/yudao-module-promotion-biz/src/main/java/cn/iocoder/yudao/module/promotion/service/discount/DiscountActivityServiceImpl.java
+++ b/yudao-module-mall/yudao-module-promotion-biz/src/main/java/cn/iocoder/yudao/module/promotion/service/discount/DiscountActivityServiceImpl.java
@@ -6,6 +6,7 @@ import cn.hutool.core.map.MapUtil;
import cn.iocoder.yudao.framework.common.enums.CommonStatusEnum;
import cn.iocoder.yudao.framework.common.pojo.PageResult;
import cn.iocoder.yudao.framework.common.util.object.BeanUtils;
+import cn.iocoder.yudao.module.promotion.api.discount.dto.DiscountProductRespDTO;
import cn.iocoder.yudao.module.promotion.controller.admin.discount.vo.DiscountActivityBaseVO;
import cn.iocoder.yudao.module.promotion.controller.admin.discount.vo.DiscountActivityCreateReqVO;
import cn.iocoder.yudao.module.promotion.controller.admin.discount.vo.DiscountActivityPageReqVO;
@@ -49,7 +50,7 @@ public class DiscountActivityServiceImpl implements DiscountActivityService {
private DiscountProductMapper discountProductMapper;
@Override
- public List getMatchDiscountProductList(Collection skuIds) {
+ public List getMatchDiscountProductList(Collection skuIds) {
return discountProductMapper.getMatchDiscountProductList(skuIds);
}
@@ -130,7 +131,7 @@ public class DiscountActivityServiceImpl implements DiscountActivityService {
List list = discountProductMapper.selectListByActivityId(id);
// TODO @zhangshuai:一般简单的 stream 方法,建议是使用 CollectionUtils,例如说这里是 convertList 对把。
List skuIds = list.stream().map(item -> item.getSkuId()).collect(Collectors.toList());
- List matchDiscountProductList = getMatchDiscountProductList(skuIds);
+ List matchDiscountProductList = getMatchDiscountProductList(skuIds);
if (id != null) { // 排除自己这个活动
matchDiscountProductList.removeIf(product -> id.equals(product.getActivityId()));
}
diff --git a/yudao-module-mall/yudao-module-promotion-biz/src/main/resources/mapper/discount/DiscountProductMapper.xml b/yudao-module-mall/yudao-module-promotion-biz/src/main/resources/mapper/discount/DiscountProductMapper.xml
index 51e1d8f71..762ae1358 100644
--- a/yudao-module-mall/yudao-module-promotion-biz/src/main/resources/mapper/discount/DiscountProductMapper.xml
+++ b/yudao-module-mall/yudao-module-promotion-biz/src/main/resources/mapper/discount/DiscountProductMapper.xml
@@ -3,8 +3,8 @@
-
diff --git a/yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/controller/app/order/vo/AppTradeOrderSettlementRespVO.java b/yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/controller/app/order/vo/AppTradeOrderSettlementRespVO.java
index 9aab1b68b..576703794 100644
--- a/yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/controller/app/order/vo/AppTradeOrderSettlementRespVO.java
+++ b/yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/controller/app/order/vo/AppTradeOrderSettlementRespVO.java
@@ -1,6 +1,7 @@
package cn.iocoder.yudao.module.trade.controller.app.order.vo;
import cn.iocoder.yudao.module.trade.controller.app.base.property.AppProductPropertyValueDetailRespVO;
+import cn.iocoder.yudao.module.trade.service.price.bo.TradePriceCalculateRespBO;
import io.swagger.v3.oas.annotations.media.Schema;
import jakarta.validation.constraints.NotNull;
import lombok.AllArgsConstructor;
@@ -31,6 +32,13 @@ public class AppTradeOrderSettlementRespVO {
@Schema(description = "总积分", requiredMode = Schema.RequiredMode.REQUIRED, example = "10")
private Integer totalPoint;
+ /**
+ * 营销活动数组
+ *
+ * 只对应 {@link TradePriceCalculateRespBO.Price#items} 商品匹配的活动
+ */
+ private List promotions;
+
@Schema(description = "购物项")
@Data
public static class Item {
diff --git a/yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/service/price/calculator/TradeDiscountActivityPriceCalculator.java b/yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/service/price/calculator/TradeDiscountActivityPriceCalculator.java
index 844d5266e..34cb68b06 100644
--- a/yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/service/price/calculator/TradeDiscountActivityPriceCalculator.java
+++ b/yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/service/price/calculator/TradeDiscountActivityPriceCalculator.java
@@ -3,6 +3,10 @@ package cn.iocoder.yudao.module.trade.service.price.calculator;
import cn.hutool.core.collection.CollUtil;
import cn.hutool.core.util.ObjectUtil;
import cn.hutool.core.util.StrUtil;
+import cn.iocoder.yudao.module.member.api.level.MemberLevelApi;
+import cn.iocoder.yudao.module.member.api.level.dto.MemberLevelRespDTO;
+import cn.iocoder.yudao.module.member.api.user.MemberUserApi;
+import cn.iocoder.yudao.module.member.api.user.dto.MemberUserRespDTO;
import cn.iocoder.yudao.module.promotion.api.discount.DiscountActivityApi;
import cn.iocoder.yudao.module.promotion.api.discount.dto.DiscountProductRespDTO;
import cn.iocoder.yudao.module.promotion.enums.common.PromotionDiscountTypeEnum;
@@ -32,6 +36,10 @@ public class TradeDiscountActivityPriceCalculator implements TradePriceCalculato
@Resource
private DiscountActivityApi discountActivityApi;
+ @Resource
+ private MemberLevelApi memberLevelApi;
+ @Resource
+ private MemberUserApi memberUserApi;
@Override
public void calculate(TradePriceCalculateReqBO param, TradePriceCalculateRespBO result) {
@@ -39,6 +47,7 @@ public class TradeDiscountActivityPriceCalculator implements TradePriceCalculato
if (ObjectUtil.notEqual(result.getType(), TradeOrderTypeEnum.NORMAL.getType())) {
return;
}
+ //----------------------------------限时折扣计算-----------------------------------------
// 获得 SKU 对应的限时折扣活动
List discountProducts = discountActivityApi.getMatchDiscountProductList(
convertSet(result.getItems(), TradePriceCalculateRespBO.OrderItem::getSkuId));
@@ -47,27 +56,64 @@ public class TradeDiscountActivityPriceCalculator implements TradePriceCalculato
}
Map discountProductMap = convertMap(discountProducts, DiscountProductRespDTO::getSkuId);
- // 处理每个 SKU 的限时折扣
+
+
+ //----------------------------------会员计算-----------------------------------------
+
+ // 获得用户的会员等级
+ MemberUserRespDTO user = memberUserApi.getUser(param.getUserId());
+ if (user.getLevelId() == null || user.getLevelId() <= 0) {
+ return;
+ }
+ MemberLevelRespDTO level = memberLevelApi.getMemberLevel(user.getLevelId());
+ if (level == null || level.getDiscountPercent() == null) {
+ return;
+ }
+
+ // 2. 计算每个 SKU 的优惠金额
result.getItems().forEach(orderItem -> {
- // 1. 获取该 SKU 的优惠信息
+
+ //----------------------------------限时折扣计算-----------------------------------------
+
+ // 2.1 计算限时折扣优惠信息
DiscountProductRespDTO discountProduct = discountProductMap.get(orderItem.getSkuId());
if (discountProduct == null) {
return;
}
- // 2. 计算优惠金额
+ // 2.2 计算优惠金额
Integer newPayPrice = calculatePayPrice(discountProduct, orderItem);
Integer newDiscountPrice = orderItem.getPayPrice() - newPayPrice;
- // 3.1 记录优惠明细
- if (orderItem.getSelected()) {
- // 注意,只有在选中的情况下,才会记录到优惠明细。否则仅仅是更新 SKU 优惠金额,用于展示
- TradePriceCalculatorHelper.addPromotion(result, orderItem,
- discountProduct.getActivityId(), discountProduct.getActivityName(), PromotionTypeEnum.DISCOUNT_ACTIVITY.getType(),
- StrUtil.format("限时折扣:省 {} 元", formatPrice(newDiscountPrice)),
- newDiscountPrice);
+
+ //----------------------------------会员计算-----------------------------------------
+
+ // 2.3 计算会员优惠金额
+ Integer vipPrice = calculateVipPrice(orderItem.getPayPrice(), level.getDiscountPercent());
+ if (vipPrice <= 0) {
+ return;
}
- // 3.2 更新 SKU 优惠金额
- orderItem.setDiscountPrice(orderItem.getDiscountPrice() + newDiscountPrice);
+
+ // 2.4 记录优惠明细
+ if (orderItem.getSelected()) {
+ if(newDiscountPrice > vipPrice){
+ // 注意,只有在选中的情况下,才会记录到优惠明细。否则仅仅是更新 SKU 优惠金额,用于展示
+ TradePriceCalculatorHelper.addPromotion(result, orderItem,
+ discountProduct.getActivityId(), discountProduct.getActivityName(), PromotionTypeEnum.DISCOUNT_ACTIVITY.getType(),
+ StrUtil.format("限时折扣:省 {} 元", formatPrice(newDiscountPrice)),
+ newDiscountPrice);
+ // 2.5 更新 SKU 优惠金额
+ orderItem.setDiscountPrice(orderItem.getDiscountPrice() + newDiscountPrice);
+ }else{
+ // 注意,只有在选中的情况下,才会记录到优惠明细。否则仅仅是更新 SKU 优惠金额,用于展示
+ TradePriceCalculatorHelper.addPromotion(result, orderItem,
+ level.getId(), level.getName(), PromotionTypeEnum.MEMBER_LEVEL.getType(),
+ String.format("会员等级折扣:省 %s 元", formatPrice(vipPrice)),
+ vipPrice);
+ // 2.5 更新 SKU 的优惠金额
+ orderItem.setVipPrice(vipPrice);
+ }
+ }
+
TradePriceCalculatorHelper.recountPayPrice(orderItem);
});
TradePriceCalculatorHelper.recountAllPrice(result);
@@ -77,7 +123,7 @@ public class TradeDiscountActivityPriceCalculator implements TradePriceCalculato
TradePriceCalculateRespBO.OrderItem orderItem) {
Integer price = orderItem.getPayPrice();
if (PromotionDiscountTypeEnum.PRICE.getType().equals(discountProduct.getDiscountType())) { // 减价
- price -= discountProduct.getDiscountPrice() * orderItem.getCount();
+ price -= discountProduct.getDiscountPrice() * 100 * orderItem.getCount();
} else if (PromotionDiscountTypeEnum.PERCENT.getType().equals(discountProduct.getDiscountType())) { // 打折
price = price * discountProduct.getDiscountPercent() / 100;
} else {
@@ -86,4 +132,19 @@ public class TradeDiscountActivityPriceCalculator implements TradePriceCalculato
return price;
}
+ /**
+ * 计算会员 VIP 优惠价格
+ *
+ * @param price 原价
+ * @param discountPercent 折扣
+ * @return 优惠价格
+ */
+ public Integer calculateVipPrice(Integer price, Integer discountPercent) {
+ if (discountPercent == null) {
+ return 0;
+ }
+ Integer newPrice = price * discountPercent / 100;
+ return price - newPrice;
+ }
+
}
diff --git a/yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/service/price/calculator/TradeMemberLevelPriceCalculator.java b/yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/service/price/calculator/TradeMemberLevelPriceCalculator.java
index f4a535065..26fb6721a 100644
--- a/yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/service/price/calculator/TradeMemberLevelPriceCalculator.java
+++ b/yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/service/price/calculator/TradeMemberLevelPriceCalculator.java
@@ -30,44 +30,49 @@ public class TradeMemberLevelPriceCalculator implements TradePriceCalculator {
@Resource
private MemberUserApi memberUserApi;
+ /**
+ * 会员计算迁移到限时优惠计算里
+ * @param param
+ * @param result
+ */
@Override
public void calculate(TradePriceCalculateReqBO param, TradePriceCalculateRespBO result) {
- // 0. 只有【普通】订单,才计算该优惠
- if (ObjectUtil.notEqual(result.getType(), TradeOrderTypeEnum.NORMAL.getType())) {
- return;
- }
- // 1. 获得用户的会员等级
- MemberUserRespDTO user = memberUserApi.getUser(param.getUserId());
- if (user.getLevelId() == null || user.getLevelId() <= 0) {
- return;
- }
- MemberLevelRespDTO level = memberLevelApi.getMemberLevel(user.getLevelId());
- if (level == null || level.getDiscountPercent() == null) {
- return;
- }
-
- // 2. 计算每个 SKU 的优惠金额
- result.getItems().forEach(orderItem -> {
- // 2.1 计算优惠金额
- Integer vipPrice = calculateVipPrice(orderItem.getPayPrice(), level.getDiscountPercent());
- if (vipPrice <= 0) {
- return;
- }
-
- // 2.2 记录优惠明细
- if (orderItem.getSelected()) {
- // 注意,只有在选中的情况下,才会记录到优惠明细。否则仅仅是更新 SKU 优惠金额,用于展示
- TradePriceCalculatorHelper.addPromotion(result, orderItem,
- level.getId(), level.getName(), PromotionTypeEnum.MEMBER_LEVEL.getType(),
- String.format("会员等级折扣:省 %s 元", formatPrice(vipPrice)),
- vipPrice);
- }
-
- // 2.3 更新 SKU 的优惠金额
- orderItem.setVipPrice(vipPrice);
- TradePriceCalculatorHelper.recountPayPrice(orderItem);
- });
- TradePriceCalculatorHelper.recountAllPrice(result);
+// // 0. 只有【普通】订单,才计算该优惠
+// if (ObjectUtil.notEqual(result.getType(), TradeOrderTypeEnum.NORMAL.getType())) {
+// return;
+// }
+// // 1. 获得用户的会员等级
+// MemberUserRespDTO user = memberUserApi.getUser(param.getUserId());
+// if (user.getLevelId() == null || user.getLevelId() <= 0) {
+// return;
+// }
+// MemberLevelRespDTO level = memberLevelApi.getMemberLevel(user.getLevelId());
+// if (level == null || level.getDiscountPercent() == null) {
+// return;
+// }
+//
+// // 2. 计算每个 SKU 的优惠金额
+// result.getItems().forEach(orderItem -> {
+// // 2.1 计算优惠金额
+// Integer vipPrice = calculateVipPrice(orderItem.getPayPrice(), level.getDiscountPercent());
+// if (vipPrice <= 0) {
+// return;
+// }
+//
+// // 2.2 记录优惠明细
+// if (orderItem.getSelected()) {
+// // 注意,只有在选中的情况下,才会记录到优惠明细。否则仅仅是更新 SKU 优惠金额,用于展示
+// TradePriceCalculatorHelper.addPromotion(result, orderItem,
+// level.getId(), level.getName(), PromotionTypeEnum.MEMBER_LEVEL.getType(),
+// String.format("会员等级折扣:省 %s 元", formatPrice(vipPrice)),
+// vipPrice);
+// }
+//
+// // 2.3 更新 SKU 的优惠金额
+// orderItem.setVipPrice(vipPrice);
+// TradePriceCalculatorHelper.recountPayPrice(orderItem);
+// });
+// TradePriceCalculatorHelper.recountAllPrice(result);
}
/**
diff --git a/yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/service/price/calculator/TradeRewardActivityPriceCalculator.java b/yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/service/price/calculator/TradeRewardActivityPriceCalculator.java
index c2d64a6f2..3b8ebab00 100644
--- a/yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/service/price/calculator/TradeRewardActivityPriceCalculator.java
+++ b/yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/service/price/calculator/TradeRewardActivityPriceCalculator.java
@@ -23,8 +23,10 @@ import java.util.Comparator;
import java.util.List;
import java.util.Map;
+import static cn.iocoder.yudao.framework.common.exception.util.ServiceExceptionUtil.exception;
import static cn.iocoder.yudao.framework.common.util.collection.CollectionUtils.convertSet;
import static cn.iocoder.yudao.framework.common.util.collection.CollectionUtils.filterList;
+import static cn.iocoder.yudao.module.promotion.enums.ErrorCodeConstants.REWARD_ACTIVITY_TYPE_NOT_EXISTS;
import static cn.iocoder.yudao.module.trade.service.price.calculator.TradePriceCalculatorHelper.formatPrice;
// TODO @puhui999:相关的单测,建议改一改
@@ -53,9 +55,10 @@ public class TradeRewardActivityPriceCalculator implements TradePriceCalculator
if (CollUtil.isEmpty(rewardActivities)) {
return;
}
-
- // 处理每个满减送活动
- rewardActivities.forEach(rewardActivity -> calculate(param, result, rewardActivity));
+ // 处理最新的满减送活动
+ if(!rewardActivities.isEmpty()){
+ calculate(param, result, rewardActivities.get(0));
+ }
}
private void calculate(TradePriceCalculateReqBO param, TradePriceCalculateRespBO result,
@@ -120,27 +123,24 @@ public class TradeRewardActivityPriceCalculator implements TradePriceCalculator
/**
* 获得满减送的订单项(商品)列表
*
- * @param result 计算结果
+ * @param result 计算结果
* @param rewardActivity 满减送活动
* @return 订单项(商品)列表
*/
private List filterMatchActivityOrderItems(TradePriceCalculateRespBO result,
RewardActivityMatchRespDTO rewardActivity) {
- // 情况一:全部商品都可以参与
- if (PromotionProductScopeEnum.isAll(rewardActivity.getProductScope())) {
+ Integer productScope = rewardActivity.getProductScope();
+ if(PromotionProductScopeEnum.isAll(productScope)){
return result.getItems();
- }
- // 情况二:指定商品参与
- if (PromotionProductScopeEnum.isSpu(rewardActivity.getProductScope())) {
+ }else if (PromotionProductScopeEnum.isSpu(productScope)) {
return filterList(result.getItems(),
orderItem -> CollUtil.contains(rewardActivity.getProductScopeValues(), orderItem.getSpuId()));
- }
- // 情况三:指定商品类型参与
- if (PromotionProductScopeEnum.isCategory(rewardActivity.getProductScope())) {
+ }else if (PromotionProductScopeEnum.isCategory(productScope)) {
return filterList(result.getItems(),
orderItem -> CollUtil.contains(rewardActivity.getProductScopeValues(), orderItem.getCategoryId()));
+ }else{
+ throw exception(REWARD_ACTIVITY_TYPE_NOT_EXISTS);
}
- return List.of();
}
/**
From cb7634ecb4f14c64bcdf0419a28837c0d5530ee1 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?=E7=97=B4=E8=B4=A7?= <252048765@qq.com>
Date: Sat, 14 Sep 2024 19:11:44 +0800
Subject: [PATCH 035/156] =?UTF-8?q?=E3=80=90=E5=8A=9F=E8=83=BD=E4=BC=98?=
=?UTF-8?q?=E5=8C=96=E3=80=91=E4=BC=98=E5=8C=96=E9=99=90=E6=97=B6=E6=BB=A1?=
=?UTF-8?q?=E5=87=8F=E7=9A=84=E9=87=91=E9=A2=9D=E6=95=B0=E6=8D=AE=E5=BA=93?=
=?UTF-8?q?=E4=BF=9D=E5=AD=98=E4=B8=BA=E5=88=86?=
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
---
.../price/calculator/TradeDiscountActivityPriceCalculator.java | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/service/price/calculator/TradeDiscountActivityPriceCalculator.java b/yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/service/price/calculator/TradeDiscountActivityPriceCalculator.java
index 34cb68b06..b3297a985 100644
--- a/yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/service/price/calculator/TradeDiscountActivityPriceCalculator.java
+++ b/yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/service/price/calculator/TradeDiscountActivityPriceCalculator.java
@@ -123,7 +123,7 @@ public class TradeDiscountActivityPriceCalculator implements TradePriceCalculato
TradePriceCalculateRespBO.OrderItem orderItem) {
Integer price = orderItem.getPayPrice();
if (PromotionDiscountTypeEnum.PRICE.getType().equals(discountProduct.getDiscountType())) { // 减价
- price -= discountProduct.getDiscountPrice() * 100 * orderItem.getCount();
+ price -= discountProduct.getDiscountPrice() * orderItem.getCount();
} else if (PromotionDiscountTypeEnum.PERCENT.getType().equals(discountProduct.getDiscountType())) { // 打折
price = price * discountProduct.getDiscountPercent() / 100;
} else {
From a9241cfbf41e613fe5b033ad76c44a97cb09946a Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?=E7=97=B4=E8=B4=A7?= <252048765@qq.com>
Date: Sat, 14 Sep 2024 19:12:35 +0800
Subject: [PATCH 036/156] =?UTF-8?q?=E3=80=90=E5=8A=9F=E8=83=BD=E4=BC=98?=
=?UTF-8?q?=E5=8C=96=E3=80=91=E4=BC=98=E5=8C=96=E5=95=86=E5=93=81=E5=88=97?=
=?UTF-8?q?=E8=A1=A8=E9=A1=B5=E6=88=96=E8=80=85=E8=AF=A6=E6=83=85=E9=A1=B5?=
=?UTF-8?q?=E4=BC=9A=E5=91=98=E4=BB=B7=E5=92=8C=E9=99=90=E6=97=B6=E4=BC=98?=
=?UTF-8?q?=E6=83=A0=E4=BB=B7=EF=BC=8C=E9=82=A3=E4=B8=AA=E4=BE=BF=E5=AE=9C?=
=?UTF-8?q?=E5=B1=95=E7=A4=BA=E9=82=A3=E4=B8=AA?=
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
---
.../app/order/AppTradeOrderController.java | 15 +++++++++++----
1 file changed, 11 insertions(+), 4 deletions(-)
diff --git a/yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/controller/app/order/AppTradeOrderController.java b/yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/controller/app/order/AppTradeOrderController.java
index e4ae2f57d..b325c99ec 100644
--- a/yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/controller/app/order/AppTradeOrderController.java
+++ b/yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/controller/app/order/AppTradeOrderController.java
@@ -100,15 +100,22 @@ public class AppTradeOrderController {
skuList.forEach(sku -> {
//查询限时优惠价格
AppTradeProductSettlementRespVO.Sku skuDiscount = calculateDiscountPrice(sku.getId(), sku.getPrice());
- if(skuDiscount != null){
- skus.add(skuDiscount);
- }
//查询会员价
AppTradeProductSettlementRespVO.Sku skuVip = calculateVipPrice(sku.getId(), sku.getPrice(), memberLevel);
- if(skuVip != null){
+
+ if(skuDiscount != null && skuVip != null){
+ if(skuDiscount.getPrice() > skuVip.getPrice()){
+ skus.add(skuDiscount);
+ }else{
+ skus.add(skuVip);
+ }
+ }else if(skuDiscount != null){
+ skus.add(skuDiscount);
+ }else if(skuVip != null){
skus.add(skuVip);
}
+
});
AppTradeProductSettlementRespVO.Reward reward = calculateReward(spuId);
AppTradeProductSettlementRespVO respVO = AppTradeProductSettlementRespVO.builder().id(spuId).skus(skus).build();
From c77a66967bd123eaafb6fb7893b08b278e549240 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?=E7=97=B4=E8=B4=A7?= <252048765@qq.com>
Date: Sat, 14 Sep 2024 19:14:12 +0800
Subject: [PATCH 037/156] =?UTF-8?q?=E3=80=90=E4=BC=98=E5=8C=96=E3=80=91?=
=?UTF-8?q?=E6=B7=BB=E5=8A=A0=E6=BB=A1=E5=87=8F=E6=B4=BB=E5=8A=A8=E5=BC=80?=
=?UTF-8?q?=E5=A7=8B=E6=97=B6=E9=97=B4=E5=92=8C=E7=BB=93=E6=9D=9F=E6=97=B6?=
=?UTF-8?q?=E9=97=B4?=
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
---
.../controller/app/reward/vo/AppRewardActivityRespVO.java | 7 +++++++
1 file changed, 7 insertions(+)
diff --git a/yudao-module-mall/yudao-module-promotion-biz/src/main/java/cn/iocoder/yudao/module/promotion/controller/app/reward/vo/AppRewardActivityRespVO.java b/yudao-module-mall/yudao-module-promotion-biz/src/main/java/cn/iocoder/yudao/module/promotion/controller/app/reward/vo/AppRewardActivityRespVO.java
index acaa5225d..cb4d79def 100755
--- a/yudao-module-mall/yudao-module-promotion-biz/src/main/java/cn/iocoder/yudao/module/promotion/controller/app/reward/vo/AppRewardActivityRespVO.java
+++ b/yudao-module-mall/yudao-module-promotion-biz/src/main/java/cn/iocoder/yudao/module/promotion/controller/app/reward/vo/AppRewardActivityRespVO.java
@@ -4,6 +4,7 @@ import cn.iocoder.yudao.module.promotion.controller.admin.reward.vo.RewardActivi
import io.swagger.v3.oas.annotations.media.Schema;
import lombok.Data;
+import java.time.LocalDateTime;
import java.util.List;
@Schema(description = "用户 App - 满减送活动 Response VO")
@@ -31,4 +32,10 @@ public class AppRewardActivityRespVO {
@Schema(description = "优惠规则的数组")
private List rules;
+ @Schema(description = "开始时间")
+ private LocalDateTime startTime;
+
+ @Schema(description = "结束时间")
+ private LocalDateTime endTime;
+
}
From 0496ac237c1c2f84d2530883e85cfe80aaeb9634 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?=E7=97=B4=E8=B4=A7?= <252048765@qq.com>
Date: Sat, 14 Sep 2024 19:15:42 +0800
Subject: [PATCH 038/156] =?UTF-8?q?=E3=80=90=E4=BC=98=E5=8C=96=E3=80=91?=
=?UTF-8?q?=E4=BC=98=E5=8C=96=E4=BB=A3=E7=A0=81?=
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
---
.../service/reward/RewardActivityService.java | 2 +-
.../order/vo/AppTradeProductSettlementRespVO.java | 14 +++++++++-----
2 files changed, 10 insertions(+), 6 deletions(-)
diff --git a/yudao-module-mall/yudao-module-promotion-biz/src/main/java/cn/iocoder/yudao/module/promotion/service/reward/RewardActivityService.java b/yudao-module-mall/yudao-module-promotion-biz/src/main/java/cn/iocoder/yudao/module/promotion/service/reward/RewardActivityService.java
index ab6b2e79b..ebfce39c3 100755
--- a/yudao-module-mall/yudao-module-promotion-biz/src/main/java/cn/iocoder/yudao/module/promotion/service/reward/RewardActivityService.java
+++ b/yudao-module-mall/yudao-module-promotion-biz/src/main/java/cn/iocoder/yudao/module/promotion/service/reward/RewardActivityService.java
@@ -75,7 +75,7 @@ public interface RewardActivityService {
/**
* 获取指定 spu 编号最近参加的活动,每个 spuId 只返回一条记录
*
- * @param spuIds spu 编号
+ * @param spuIds SPU 编号数组
* @param status 状态
* @param dateTime 当前日期时间
* @return 满减送活动列表
diff --git a/yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/controller/app/order/vo/AppTradeProductSettlementRespVO.java b/yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/controller/app/order/vo/AppTradeProductSettlementRespVO.java
index 67c407924..773b49617 100644
--- a/yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/controller/app/order/vo/AppTradeProductSettlementRespVO.java
+++ b/yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/controller/app/order/vo/AppTradeProductSettlementRespVO.java
@@ -13,13 +13,13 @@ import java.util.List;
@Builder
public class AppTradeProductSettlementRespVO {
- @Schema(description = "商品编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "1")
+ @Schema(description = "spu 商品编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "1")
private Long id;
@Schema(description = "满减活动对象", requiredMode = Schema.RequiredMode.REQUIRED, example = "1")
private Reward reward;
- @Schema(description = "sku活动信息", requiredMode = Schema.RequiredMode.REQUIRED, example = "1")
+ @Schema(description = "sku 活动信息", requiredMode = Schema.RequiredMode.REQUIRED, example = "1")
private List skus;
/**
@@ -28,11 +28,13 @@ public class AppTradeProductSettlementRespVO {
@Data
@Builder
public static class Reward implements Serializable {
+
@Schema(description = "满减活动编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "1")
- private Long rewardId;
+ private Long id;
@Schema(description = "满减活动信息", requiredMode = Schema.RequiredMode.REQUIRED, example = "1")
private String rewardActivity;
+
}
/**
@@ -41,19 +43,21 @@ public class AppTradeProductSettlementRespVO {
@Data
@Builder
public static class Sku implements Serializable {
+
@Schema(description = "商品 SKU 编号", requiredMode = Schema.RequiredMode.REQUIRED, example = "1")
private Long skuId;
@Schema(description = "价格", requiredMode = Schema.RequiredMode.REQUIRED, example = "1")
private Integer price;
- @Schema(description = "营销类型", requiredMode = Schema.RequiredMode.REQUIRED, example = "1") //PromotionTypeEnum
- private Integer type;
+ @Schema(description = "营销类型", requiredMode = Schema.RequiredMode.REQUIRED, example = "1")
+ private Integer type; // 对应 PromotionTypeEnum 枚举
@Schema(description = "限时优惠id", requiredMode = Schema.RequiredMode.REQUIRED)
private Long discountId;
@Schema(description = "活动结束时间", requiredMode = Schema.RequiredMode.REQUIRED)
private LocalDateTime endTime;
+
}
}
From 51b8fe2ecab72cd5342c481051474d22d6136f45 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?=E7=97=B4=E8=B4=A7?= <252048765@qq.com>
Date: Sat, 14 Sep 2024 19:16:48 +0800
Subject: [PATCH 039/156] =?UTF-8?q?=E3=80=90BUG=E3=80=91=E4=BF=AE=E6=94=B9?=
=?UTF-8?q?=E9=99=90=E6=97=B6=E4=BC=98=E6=83=A0=E5=92=8C=E4=BC=9A=E5=91=98?=
=?UTF-8?q?=E4=BC=98=E6=83=A0=E6=98=BE=E7=A4=BA=E6=9C=80=E4=BE=BF=E5=AE=9C?=
=?UTF-8?q?=E7=9B=B8=E5=8F=8D=E7=9A=84=E9=97=AE=E9=A2=98?=
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
---
.../trade/controller/app/order/AppTradeOrderController.java | 6 +++---
1 file changed, 3 insertions(+), 3 deletions(-)
diff --git a/yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/controller/app/order/AppTradeOrderController.java b/yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/controller/app/order/AppTradeOrderController.java
index b325c99ec..24bbfb6e7 100644
--- a/yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/controller/app/order/AppTradeOrderController.java
+++ b/yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/controller/app/order/AppTradeOrderController.java
@@ -106,9 +106,9 @@ public class AppTradeOrderController {
if(skuDiscount != null && skuVip != null){
if(skuDiscount.getPrice() > skuVip.getPrice()){
- skus.add(skuDiscount);
- }else{
skus.add(skuVip);
+ }else{
+ skus.add(skuDiscount);
}
}else if(skuDiscount != null){
skus.add(skuDiscount);
@@ -335,7 +335,7 @@ public class AppTradeOrderController {
RewardActivityMatchRespDTO.Rule rule = rewardActivityMatchRespDTO.getRules().get(0);
return AppTradeProductSettlementRespVO.Reward.builder().
rewardActivity("满" + rule.getLimit() / 100 + (Objects.equals(rewardActivityMatchRespDTO.getConditionType(), PromotionConditionTypeEnum.PRICE.getType())?"元":"件"+"减") +rule.getDiscountPrice() / 100)
- .rewardId(rewardActivityMatchRespDTO.getId()).build();
+ .id(rewardActivityMatchRespDTO.getId()).build();
}
}
return null;
From 60ab3389f52302b26043d45e166d524393fcdfad Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?=E7=97=B4=E8=B4=A7?= <252048765@qq.com>
Date: Sat, 14 Sep 2024 19:17:20 +0800
Subject: [PATCH 040/156] =?UTF-8?q?=E3=80=90BUG=E3=80=91=E4=BF=AE=E6=94=B9?=
=?UTF-8?q?=E9=99=90=E6=97=B6=E4=BC=98=E6=83=A0=E4=BF=AE=E6=94=B9=E6=B4=BB?=
=?UTF-8?q?=E5=8A=A8=E8=A1=A8=E6=97=B6=E9=97=B4=E6=97=B6=EF=BC=8C=E5=95=86?=
=?UTF-8?q?=E5=93=81=E8=A1=A8=E6=97=B6=E9=97=B4=E6=B2=A1=E6=9C=89=E5=8F=98?=
=?UTF-8?q?=E5=8C=96=E7=9A=84=E9=97=AE=E9=A2=98?=
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
---
.../promotion/convert/discount/DiscountActivityConvert.java | 5 ++++-
1 file changed, 4 insertions(+), 1 deletion(-)
diff --git a/yudao-module-mall/yudao-module-promotion-biz/src/main/java/cn/iocoder/yudao/module/promotion/convert/discount/DiscountActivityConvert.java b/yudao-module-mall/yudao-module-promotion-biz/src/main/java/cn/iocoder/yudao/module/promotion/convert/discount/DiscountActivityConvert.java
index 0ecbd92ef..05063b918 100755
--- a/yudao-module-mall/yudao-module-promotion-biz/src/main/java/cn/iocoder/yudao/module/promotion/convert/discount/DiscountActivityConvert.java
+++ b/yudao-module-mall/yudao-module-promotion-biz/src/main/java/cn/iocoder/yudao/module/promotion/convert/discount/DiscountActivityConvert.java
@@ -121,7 +121,10 @@ public interface DiscountActivityConvert {
default boolean isEquals(DiscountProductDO productDO, DiscountProductDO productVO) {
if (ObjectUtil.notEqual(productDO.getSpuId(), productVO.getSpuId())
|| ObjectUtil.notEqual(productDO.getSkuId(), productVO.getSkuId())
- || ObjectUtil.notEqual(productDO.getDiscountType(), productVO.getDiscountType())) {
+ || ObjectUtil.notEqual(productDO.getDiscountType(), productVO.getDiscountType())
+ || ObjectUtil.notEqual(productDO.getActivityEndTime(), productVO.getActivityEndTime())
+ || ObjectUtil.notEqual(productDO.getActivityStartTime(), productVO.getActivityStartTime())
+ || ObjectUtil.notEqual(productDO.getActivityStatus(), productVO.getActivityStatus())) {
return false;
}
if (productDO.getDiscountType().equals(PromotionDiscountTypeEnum.PRICE.getType())) {
From d0b60bf9b40b45ddf7026e0108e04109b2036cc8 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?=E7=97=B4=E8=B4=A7?= <252048765@qq.com>
Date: Sat, 14 Sep 2024 19:17:57 +0800
Subject: [PATCH 041/156] =?UTF-8?q?=E3=80=90BUG=E3=80=91=E6=B7=BB=E5=8A=A0?=
=?UTF-8?q?=E7=A7=9F=E6=88=B7=E6=97=B6=EF=BC=8C=E7=A7=9F=E6=88=B7id?=
=?UTF-8?q?=E6=B2=A1=E6=9C=89=E4=BF=9D=E5=AD=98=E7=9A=84=E9=97=AE=E9=A2=98?=
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
---
.../yudao/module/system/service/user/AdminUserServiceImpl.java | 2 ++
1 file changed, 2 insertions(+)
diff --git a/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/service/user/AdminUserServiceImpl.java b/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/service/user/AdminUserServiceImpl.java
index cb9a73ff7..0dc6fa8d1 100644
--- a/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/service/user/AdminUserServiceImpl.java
+++ b/yudao-module-system/yudao-module-system-biz/src/main/java/cn/iocoder/yudao/module/system/service/user/AdminUserServiceImpl.java
@@ -11,6 +11,7 @@ import cn.iocoder.yudao.framework.common.util.collection.CollectionUtils;
import cn.iocoder.yudao.framework.common.util.object.BeanUtils;
import cn.iocoder.yudao.framework.common.util.validation.ValidationUtils;
import cn.iocoder.yudao.framework.datapermission.core.util.DataPermissionUtils;
+import cn.iocoder.yudao.framework.tenant.core.context.TenantContextHolder;
import cn.iocoder.yudao.module.infra.api.config.ConfigApi;
import cn.iocoder.yudao.module.infra.api.file.FileApi;
import cn.iocoder.yudao.module.system.controller.admin.auth.vo.AuthRegisterReqVO;
@@ -104,6 +105,7 @@ public class AdminUserServiceImpl implements AdminUserService {
AdminUserDO user = BeanUtils.toBean(createReqVO, AdminUserDO.class);
user.setStatus(CommonStatusEnum.ENABLE.getStatus()); // 默认开启
user.setPassword(encodePassword(createReqVO.getPassword())); // 加密密码
+ user.setTenantId(TenantContextHolder.getRequiredTenantId());
userMapper.insert(user);
// 2.2 插入关联岗位
if (CollectionUtil.isNotEmpty(user.getPostIds())) {
From b48d0edef090a1dcddb88c1458854e3777154b98 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?=E7=97=B4=E8=B4=A7?= <252048765@qq.com>
Date: Sat, 14 Sep 2024 19:19:13 +0800
Subject: [PATCH 042/156] =?UTF-8?q?=E3=80=90BUG=E3=80=91=E8=A7=A3=E5=86=B3?=
=?UTF-8?q?=E9=80=80=E6=AC=BE=E6=97=B6=E6=89=BE=E4=B8=8D=E5=88=B0appkey?=
=?UTF-8?q?=E7=9A=84=E9=97=AE=E9=A2=98?=
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
---
.../yudao/module/trade/convert/aftersale/AfterSaleConvert.java | 2 +-
.../module/trade/service/aftersale/AfterSaleServiceImpl.java | 3 ++-
2 files changed, 3 insertions(+), 2 deletions(-)
diff --git a/yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/convert/aftersale/AfterSaleConvert.java b/yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/convert/aftersale/AfterSaleConvert.java
index 086cb6370..bf699a0cc 100644
--- a/yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/convert/aftersale/AfterSaleConvert.java
+++ b/yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/convert/aftersale/AfterSaleConvert.java
@@ -37,7 +37,7 @@ public interface AfterSaleConvert {
@Mapping(target = "creator", ignore = true),
@Mapping(target = "updater", ignore = true),
})
- AfterSaleDO convert(AppAfterSaleCreateReqVO createReqVO, TradeOrderItemDO tradeOrderItem);
+ PayRefundCreateReqDTO convert(String userIp, AfterSaleDO afterSale);
@Mappings({
@Mapping(source = "afterSale.orderId", target = "merchantOrderId"),
diff --git a/yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/service/aftersale/AfterSaleServiceImpl.java b/yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/service/aftersale/AfterSaleServiceImpl.java
index df3d2db60..2a332aad2 100644
--- a/yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/service/aftersale/AfterSaleServiceImpl.java
+++ b/yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/service/aftersale/AfterSaleServiceImpl.java
@@ -371,8 +371,9 @@ public class AfterSaleServiceImpl implements AfterSaleService {
@Override
public void afterCommit() {
// 创建退款单
- PayRefundCreateReqDTO createReqDTO = AfterSaleConvert.INSTANCE.convert(userIp, afterSale, tradeOrderProperties)
+ PayRefundCreateReqDTO createReqDTO = AfterSaleConvert.INSTANCE.convert(userIp, afterSale)
.setReason(StrUtil.format("退款【{}】", afterSale.getSpuName()));
+ createReqDTO.setAppKey(tradeOrderProperties.getPayAppKey());
Long payRefundId = payRefundApi.createRefund(createReqDTO);
// 更新售后单的退款单号
tradeAfterSaleMapper.updateById(new AfterSaleDO().setId(afterSale.getId()).setPayRefundId(payRefundId));
From 0a23b57c15a4f8fb4a9383bd3f92aba4f148c2d2 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?=E7=97=B4=E8=B4=A7?= <252048765@qq.com>
Date: Sat, 14 Sep 2024 19:20:58 +0800
Subject: [PATCH 043/156] =?UTF-8?q?=E3=80=90BUG=E3=80=91=E8=A7=A3=E5=86=B3?=
=?UTF-8?q?=E9=80=80=E6=AC=BE=E6=97=B6=E6=89=BE=E4=B8=8D=E5=88=B0appkey?=
=?UTF-8?q?=E7=9A=84=E9=97=AE=E9=A2=98?=
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
---
.../module/trade/convert/aftersale/AfterSaleConvert.java | 5 ++---
1 file changed, 2 insertions(+), 3 deletions(-)
diff --git a/yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/convert/aftersale/AfterSaleConvert.java b/yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/convert/aftersale/AfterSaleConvert.java
index bf699a0cc..01676a6b8 100644
--- a/yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/convert/aftersale/AfterSaleConvert.java
+++ b/yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/convert/aftersale/AfterSaleConvert.java
@@ -37,7 +37,7 @@ public interface AfterSaleConvert {
@Mapping(target = "creator", ignore = true),
@Mapping(target = "updater", ignore = true),
})
- PayRefundCreateReqDTO convert(String userIp, AfterSaleDO afterSale);
+ AfterSaleDO convert(AppAfterSaleCreateReqVO createReqVO, TradeOrderItemDO tradeOrderItem);
@Mappings({
@Mapping(source = "afterSale.orderId", target = "merchantOrderId"),
@@ -46,8 +46,7 @@ public interface AfterSaleConvert {
@Mapping(source = "afterSale.refundPrice", target = "price"),
@Mapping(source = "orderProperties.payAppKey", target = "appKey")
})
- PayRefundCreateReqDTO convert(String userIp, AfterSaleDO afterSale,
- TradeOrderProperties orderProperties);
+ PayRefundCreateReqDTO convert(String userIp, AfterSaleDO afterSale);
MemberUserRespVO convert(MemberUserRespDTO bean);
From 1301eb1c83e02666b88cb4d1433deed3a268b695 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?=E7=97=B4=E8=B4=A7?= <252048765@qq.com>
Date: Sat, 14 Sep 2024 19:21:33 +0800
Subject: [PATCH 044/156] =?UTF-8?q?=E3=80=90BUG=E3=80=91=E8=A7=A3=E5=86=B3?=
=?UTF-8?q?=E4=BC=9A=E5=91=98=E4=BB=B7=E8=AE=A1=E7=AE=97=E9=94=99=E8=AF=AF?=
=?UTF-8?q?=E7=9A=84=E9=97=AE=E9=A2=98?=
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
---
.../trade/controller/app/order/AppTradeOrderController.java | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/controller/app/order/AppTradeOrderController.java b/yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/controller/app/order/AppTradeOrderController.java
index 24bbfb6e7..dcf380981 100644
--- a/yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/controller/app/order/AppTradeOrderController.java
+++ b/yudao-module-mall/yudao-module-trade-biz/src/main/java/cn/iocoder/yudao/module/trade/controller/app/order/AppTradeOrderController.java
@@ -282,7 +282,7 @@ public class AppTradeOrderController {
return AppTradeProductSettlementRespVO.Sku.builder().
skuId(skuId).
type(PromotionTypeEnum.MEMBER_LEVEL.getType()).
- price(price - newPrice).build();
+ price(newPrice).build();
}
/**
From 085b94f0d0067dc46a1d8d70a3dfee3d809b5691 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?=E7=97=B4=E8=B4=A7?= <252048765@qq.com>
Date: Sat, 14 Sep 2024 19:42:04 +0800
Subject: [PATCH 045/156] =?UTF-8?q?=E3=80=90BUG=E3=80=91=E4=BF=AE=E6=94=B9?=
=?UTF-8?q?=E7=BB=93=E7=AE=97=E9=A1=B5=E9=9D=A2=E9=80=89=E6=8B=A9=E7=94=B5?=
=?UTF-8?q?=E5=AD=90=E5=88=B8=E5=85=A8=E9=83=A8=E9=83=BD=E6=98=AF=E4=B8=8D?=
=?UTF-8?q?=E5=8F=AF=E7=94=A8=E7=9A=84=E9=97=AE=E9=A2=98?=
MIME-Version: 1.0
Content-Type: text/plain; charset=UTF-8
Content-Transfer-Encoding: 8bit
---
.../api/discount/DiscountActivityApiImpl.java | 2 +-
.../app/coupon/AppCouponController.java | 4 +-
.../convert/coupon/CouponConvert.java | 2 +
.../dal/mysql/coupon/CouponMapper.java | 15 ++----
.../service/coupon/CouponService.java | 3 +-
.../service/coupon/CouponServiceImpl.java | 46 ++++++++++++++++---
.../convert/aftersale/AfterSaleConvert.java | 3 +-
7 files changed, 52 insertions(+), 23 deletions(-)
diff --git a/yudao-module-mall/yudao-module-promotion-biz/src/main/java/cn/iocoder/yudao/module/promotion/api/discount/DiscountActivityApiImpl.java b/yudao-module-mall/yudao-module-promotion-biz/src/main/java/cn/iocoder/yudao/module/promotion/api/discount/DiscountActivityApiImpl.java
index 82b8516f9..9c9d760d0 100644
--- a/yudao-module-mall/yudao-module-promotion-biz/src/main/java/cn/iocoder/yudao/module/promotion/api/discount/DiscountActivityApiImpl.java
+++ b/yudao-module-mall/yudao-module-promotion-biz/src/main/java/cn/iocoder/yudao/module/promotion/api/discount/DiscountActivityApiImpl.java
@@ -24,7 +24,7 @@ public class DiscountActivityApiImpl implements DiscountActivityApi {
@Override
public List getMatchDiscountProductList(Collection skuIds) {
- return DiscountActivityConvert.INSTANCE.convertList02(discountActivityService.getMatchDiscountProductList(skuIds));
+ return discountActivityService.getMatchDiscountProductList(skuIds);
}
}
diff --git a/yudao-module-mall/yudao-module-promotion-biz/src/main/java/cn/iocoder/yudao/module/promotion/controller/app/coupon/AppCouponController.java b/yudao-module-mall/yudao-module-promotion-biz/src/main/java/cn/iocoder/yudao/module/promotion/controller/app/coupon/AppCouponController.java
index ed19d9141..f4235d9d6 100755
--- a/yudao-module-mall/yudao-module-promotion-biz/src/main/java/cn/iocoder/yudao/module/promotion/controller/app/coupon/AppCouponController.java
+++ b/yudao-module-mall/yudao-module-promotion-biz/src/main/java/cn/iocoder/yudao/module/promotion/controller/app/coupon/AppCouponController.java
@@ -60,8 +60,8 @@ public class AppCouponController {
@Operation(summary = "获得匹配指定商品的优惠劵列表", description = "用于下单页,展示优惠劵列表")
public CommonResult> getMatchCouponList(AppCouponMatchReqVO matchReqVO) {
// todo: 优化:优惠金额倒序
- List list = couponService.getMatchCouponList(getLoginUserId(), matchReqVO);
- return success(BeanUtils.toBean(list, AppCouponMatchRespVO.class));
+ List