Ver código fonte

订单信息

唐tag 1 ano atrás
pai
commit
19b4683d3d
33 arquivos alterados com 1580 adições e 116 exclusões
  1. 6 0
      pom.xml
  2. 2 2
      src/main/java/com/zswl/dataservicestarter/components/DataRecord.java
  3. 1 0
      src/main/java/com/zswl/dataservicestarter/dao/AppInfoDao.java
  4. 17 0
      src/main/java/com/zswl/dataservicestarter/dao/DataServiceGoodsDao.java
  5. 6 7
      src/main/java/com/zswl/dataservicestarter/dao/DataServiceOrderInfoDao.java
  6. 2 3
      src/main/java/com/zswl/dataservicestarter/dao/DataServicePaymentInfoDao.java
  7. 0 12
      src/main/java/com/zswl/dataservicestarter/dao/MongoDao.java
  8. 1 0
      src/main/java/com/zswl/dataservicestarter/dao/UserDao.java
  9. 12 0
      src/main/java/com/zswl/dataservicestarter/dao/base/MongoDao.java
  10. 2 2
      src/main/java/com/zswl/dataservicestarter/domain/AppInfo.java
  11. 53 0
      src/main/java/com/zswl/dataservicestarter/domain/DataServiceGoods.java
  12. 111 6
      src/main/java/com/zswl/dataservicestarter/domain/DataServiceOrderInfo.java
  13. 33 6
      src/main/java/com/zswl/dataservicestarter/domain/DataServicePaymentInfo.java
  14. 45 0
      src/main/java/com/zswl/dataservicestarter/domain/RefundLog.java
  15. 2 2
      src/main/java/com/zswl/dataservicestarter/domain/User.java
  16. 1 1
      src/main/java/com/zswl/dataservicestarter/domain/base/DataServiceSuperEntity.java
  17. 18 0
      src/main/java/com/zswl/dataservicestarter/helper/ApplicationContextHolder.java
  18. 2 2
      src/main/java/com/zswl/dataservicestarter/helper/BatchQueryHelper.java
  19. 4 4
      src/main/java/com/zswl/dataservicestarter/helper/DBHelper.java
  20. 7 7
      src/main/java/com/zswl/dataservicestarter/helper/ReIndexHelper.java
  21. 53 0
      src/main/java/com/zswl/dataservicestarter/model/DataServiceGoodsModel.java
  22. 96 3
      src/main/java/com/zswl/dataservicestarter/model/DataServiceOrderInfoModel.java
  23. 51 0
      src/main/java/com/zswl/dataservicestarter/model/DataServicePaymentInfoModel.java
  24. 115 11
      src/main/java/com/zswl/dataservicestarter/service/DataServiceOrderInfoService.java
  25. 0 28
      src/main/java/com/zswl/dataservicestarter/service/DataServicePaymentInfoService.java
  26. 39 17
      src/main/java/com/zswl/dataservicestarter/service/UserService.java
  27. 5 0
      src/main/java/com/zswl/dataservicestarter/type/CommonEnum.java
  28. 18 0
      src/main/java/com/zswl/dataservicestarter/type/DataServiceOrderType.java
  29. 57 0
      src/main/java/com/zswl/dataservicestarter/type/DataServiceRefundLogType.java
  30. 63 0
      src/main/java/com/zswl/dataservicestarter/utils/AopTargetUtil.java
  31. 400 0
      src/main/java/com/zswl/dataservicestarter/utils/BeanUtils.java
  32. 355 0
      src/main/java/com/zswl/dataservicestarter/utils/CommonUtil.java
  33. 3 3
      src/main/java/com/zswl/dataservicestarter/utils/bean/EntityObjectUtil.java

+ 6 - 0
pom.xml

@@ -443,6 +443,12 @@
             <version>1.9.4</version>
         </dependency>
 
+        <dependency>
+            <groupId>cn.hutool</groupId>
+            <artifactId>hutool-all</artifactId>
+            <version>5.8.20</version>
+        </dependency>
+
     </dependencies>
 
 

+ 2 - 2
src/main/java/com/zswl/dataservicestarter/components/DataRecord.java

@@ -1,6 +1,6 @@
 package com.zswl.dataservicestarter.components;
 
-import com.zswl.dataservicestarter.domain.base.SuperEntity;
+import com.zswl.dataservicestarter.domain.base.DataServiceSuperEntity;
 import lombok.*;
 import lombok.experimental.Delegate;
 import org.springframework.beans.factory.annotation.Autowired;
@@ -45,7 +45,7 @@ public class DataRecord {
     @AllArgsConstructor
     @NoArgsConstructor
     public static class RevertData {
-        private Class<? extends SuperEntity> entityClass;
+        private Class<? extends DataServiceSuperEntity> entityClass;
         private Query query;
         private Update update;
     }

+ 1 - 0
src/main/java/com/zswl/dataservicestarter/dao/AppInfoDao.java

@@ -1,5 +1,6 @@
 package com.zswl.dataservicestarter.dao;
 
+import com.zswl.dataservicestarter.dao.base.MongoDao;
 import com.zswl.dataservicestarter.domain.AppInfo;
 
 /**

+ 17 - 0
src/main/java/com/zswl/dataservicestarter/dao/DataServiceGoodsDao.java

@@ -0,0 +1,17 @@
+package com.zswl.dataservicestarter.dao;
+
+import com.zswl.dataservicestarter.dao.base.MongoDao;
+import com.zswl.dataservicestarter.domain.DataServiceGoods;
+import com.zswl.dataservicestarter.domain.DataServiceOrderInfo;
+
+import java.util.List;
+
+/**
+ * 订单信息Dao
+ */
+public interface DataServiceGoodsDao extends MongoDao<DataServiceGoods> {
+
+    DataServiceOrderInfo findTopById(String id);
+
+    DataServiceOrderInfo findTopByOrderNo(String orderNo);
+}

+ 6 - 7
src/main/java/com/zswl/dataservicestarter/dao/DataServiceOrderInfoDao.java

@@ -1,17 +1,16 @@
 package com.zswl.dataservicestarter.dao;
 
+import com.zswl.dataservicestarter.dao.base.MongoDao;
 import com.zswl.dataservicestarter.domain.DataServiceOrderInfo;
-import com.zswl.dataservicestarter.domain.User;
-
-import java.util.List;
 
+/**
+ * 订单信息Dao
+ */
 public interface DataServiceOrderInfoDao extends MongoDao<DataServiceOrderInfo> {
 
     DataServiceOrderInfo findTopById(String id);
 
-    DataServiceOrderInfo findTopByDataId(String dataId);
-
-    DataServiceOrderInfo findTopByCode(String code);
-
     DataServiceOrderInfo findTopByHashCode(int hashCode);
+
+    DataServiceOrderInfo findTopByOrderNo(String orderNo);
 }

+ 2 - 3
src/main/java/com/zswl/dataservicestarter/dao/DataServicePaymentInfoDao.java

@@ -1,5 +1,6 @@
 package com.zswl.dataservicestarter.dao;
 
+import com.zswl.dataservicestarter.dao.base.MongoDao;
 import com.zswl.dataservicestarter.domain.DataServicePaymentInfo;
 
 /**
@@ -8,7 +9,5 @@ import com.zswl.dataservicestarter.domain.DataServicePaymentInfo;
 public interface DataServicePaymentInfoDao extends MongoDao<DataServicePaymentInfo> {
     DataServicePaymentInfo findTopById(String id);
 
-    DataServicePaymentInfo findTopByDataId(String dataId);
-
-    DataServicePaymentInfo findTopByHashCode(int hashCode);
+    DataServicePaymentInfo findTopByOrderNo(String orderNo);
 }

+ 0 - 12
src/main/java/com/zswl/dataservicestarter/dao/MongoDao.java

@@ -1,12 +0,0 @@
-package com.zswl.dataservicestarter.dao;
-
-import com.zswl.dataservicestarter.domain.base.SuperEntity;
-import org.springframework.data.mongodb.repository.MongoRepository;
-
-/**
- * Mongodb的一些通用方法
- */
-public interface MongoDao<T extends SuperEntity> extends MongoRepository<T, String> {
-
-
-}

+ 1 - 0
src/main/java/com/zswl/dataservicestarter/dao/UserDao.java

@@ -1,5 +1,6 @@
 package com.zswl.dataservicestarter.dao;
 
+import com.zswl.dataservicestarter.dao.base.MongoDao;
 import com.zswl.dataservicestarter.domain.User;
 
 import java.util.List;

+ 12 - 0
src/main/java/com/zswl/dataservicestarter/dao/base/MongoDao.java

@@ -0,0 +1,12 @@
+package com.zswl.dataservicestarter.dao.base;
+
+import com.zswl.dataservicestarter.domain.base.DataServiceSuperEntity;
+import org.springframework.data.mongodb.repository.MongoRepository;
+
+/**
+ * Mongodb的一些通用方法
+ */
+public interface MongoDao<T extends DataServiceSuperEntity> extends MongoRepository<T, String> {
+
+
+}

+ 2 - 2
src/main/java/com/zswl/dataservicestarter/domain/AppInfo.java

@@ -1,6 +1,6 @@
 package com.zswl.dataservicestarter.domain;
 
-import com.zswl.dataservicestarter.domain.base.SuperEntity;
+import com.zswl.dataservicestarter.domain.base.DataServiceSuperEntity;
 import com.zswl.dataservicestarter.type.AppState;
 import lombok.AllArgsConstructor;
 import lombok.Data;
@@ -18,7 +18,7 @@ import org.springframework.data.mongodb.core.mapping.Document;
 @Document
 @NoArgsConstructor
 @AllArgsConstructor
-public class AppInfo extends SuperEntity {
+public class AppInfo extends DataServiceSuperEntity {
     /**
      * 渠道ID
      */

+ 53 - 0
src/main/java/com/zswl/dataservicestarter/domain/DataServiceGoods.java

@@ -0,0 +1,53 @@
+package com.zswl.dataservicestarter.domain;
+
+import cn.hutool.json.JSONObject;
+import com.zswl.dataservicestarter.domain.base.DataServiceSuperEntity;
+import lombok.AllArgsConstructor;
+import lombok.Builder;
+import lombok.Data;
+import lombok.NoArgsConstructor;
+import org.springframework.data.mongodb.core.mapping.Document;
+
+import java.math.BigDecimal;
+
+/**
+ * 商品信息
+ */
+@Data
+@Builder
+@Document
+@AllArgsConstructor
+@NoArgsConstructor
+public class DataServiceGoods extends DataServiceSuperEntity {
+
+    /**
+     * 订单号
+     */
+    private String orderNo;
+
+    /**
+     * 商品id
+     */
+    private String goodsId;
+
+    /**
+     * 商品类型
+     */
+    private Integer goodsType;
+
+    /**
+     * 商品全部信息
+     */
+    private JSONObject goodsInfo;
+
+    /**
+     * 商品单价
+     */
+    private BigDecimal payAmount;
+
+    /**
+     * 扩展信息
+     */
+    private String extend;
+
+}

+ 111 - 6
src/main/java/com/zswl/dataservicestarter/domain/DataServiceOrderInfo.java

@@ -1,21 +1,126 @@
 package com.zswl.dataservicestarter.domain;
 
-import com.zswl.dataservicestarter.domain.base.SuperEntity;
+import com.zswl.dataservicestarter.domain.base.DataServiceSuperEntity;
+import com.zswl.dataservicestarter.type.DataServiceOrderType;
 import lombok.AllArgsConstructor;
 import lombok.Data;
 import lombok.NoArgsConstructor;
-import net.bytebuddy.implementation.bind.annotation.Super;
+import org.springframework.data.mongodb.core.index.Indexed;
+import org.springframework.data.mongodb.core.mapping.DBRef;
+
+import java.math.BigDecimal;
+import java.util.List;
+
+import cn.hutool.json.JSONObject;
 
 /**
+ * 订单信息
+ *
  * @author TRX
  * @date 2024/3/25
  */
 @Data
 @AllArgsConstructor
 @NoArgsConstructor
-public class DataServiceOrderInfo extends SuperEntity {
-    private String dataId;
-    private String code;
+public class DataServiceOrderInfo extends DataServiceSuperEntity {
+
+    /**
+     * 数据的hashCode
+     */
+    private Integer hashCode;
+
+    /**
+     * 订单类型 平台  商铺
+     */
+    private DataServiceOrderType orderType;
+
+    /**
+     * 是否同步到平台
+     */
+    private Boolean isSync2Platform;
+
+    /**
+     * 是否同步到商铺
+     */
+    private Boolean isSync2Shop;
+
+    /**
+     * 同步时间
+     */
+    private Long syncTime;
+
+    //----------------------------平台订单信息 start-------------------------
+
+    /**
+     * 用户ID
+     */
+    private String userId;
+
+    /**
+     * 店铺ID
+     */
+    private String epId;
+
+    /**
+     * 订单号
+     */
+    @Indexed(unique = true)
+    private String orderNo;
+
+    /**
+     * 店铺信息
+     */
+    private JSONObject shopInfo;
+
+    /**
+     * 商品总价格
+     */
+    private BigDecimal totalAmount;
+
+    /**
+     * 优惠价格
+     */
+    private BigDecimal discountAmount;
+
+
+    /**
+     * 实际支付价格
+     */
+    private BigDecimal payAmount;
+
+    /**
+     * 使用优惠券信息
+     */
+    private List<JSONObject> discountList;
+
+    /**
+     * 退款信息
+     */
+    @DBRef
+    private RefundLog refundLog;
+
+    /**
+     * 是否已退款
+     */
+    private Boolean isRefund;
+
+    /**
+     * 扩展参数
+     */
+    private String extend;
+
+    /**
+     * 商品和分账信息
+     */
+    @DBRef
+    private List<DataServiceGoods> goodsList;
+
+    /**
+     * 支付信息
+     */
+    @DBRef
+    private DataServicePaymentInfo payment;
+
+    //----------------------------平台订单信息 end---------------------------
 
-    private int hashCode;
 }

+ 33 - 6
src/main/java/com/zswl/dataservicestarter/domain/DataServicePaymentInfo.java

@@ -1,9 +1,10 @@
 package com.zswl.dataservicestarter.domain;
 
-import com.zswl.dataservicestarter.domain.base.SuperEntity;
+import com.zswl.dataservicestarter.domain.base.DataServiceSuperEntity;
 import lombok.AllArgsConstructor;
 import lombok.Data;
 import lombok.NoArgsConstructor;
+import org.springframework.data.mongodb.core.index.Indexed;
 
 /**
  * @author TRX
@@ -12,13 +13,39 @@ import lombok.NoArgsConstructor;
 @Data
 @AllArgsConstructor
 @NoArgsConstructor
-public class DataServicePaymentInfo extends SuperEntity {
+public class DataServicePaymentInfo extends DataServiceSuperEntity {
+
+    @Indexed(unique = true)
+    private String orderNo;
+
+    /**
+     * 支付订单号
+     */
+    private String paymentNo;
+
+    /**
+     * 支付时间
+     */
+    private String paymentTime;
+
     /**
-     * 支付信息三方数据ID
+     * 支付方式
      */
-    private String dataId;
+    private String paymentWay;
+
+    /**
+     * 支付订单状态
+     */
+    private String paymentStatus;
+
     /**
-     * 数据的HashCode信息
+     * 支付信息
      */
-    private int hashCode;
+    private String miniPayRequest;
+
+    /**
+     * 支付订单创建时间
+     */
+    private Long payCreateTime;
+
 }

+ 45 - 0
src/main/java/com/zswl/dataservicestarter/domain/RefundLog.java

@@ -0,0 +1,45 @@
+package com.zswl.dataservicestarter.domain;
+
+import com.zswl.dataservicestarter.domain.base.DataServiceSuperEntity;
+import com.zswl.dataservicestarter.type.DataServiceRefundLogType;
+import lombok.AllArgsConstructor;
+import lombok.Builder;
+import lombok.Data;
+import lombok.NoArgsConstructor;
+import org.springframework.data.mongodb.core.mapping.Document;
+
+/**
+ * 订单的退款状态信息
+ */
+@Data
+@Builder
+@Document
+@AllArgsConstructor
+@NoArgsConstructor
+public class RefundLog extends DataServiceSuperEntity {
+
+    /**
+     * 订单号
+     */
+    private String orderNo;
+
+    /**
+     * 退款时间
+     */
+    private Long refundTime;
+
+    /**
+     * 申请信息
+     */
+    private Long applicationRefundTime;
+
+    /**
+     * 退款状态
+     */
+    private DataServiceRefundLogType refund;
+
+    /**
+     * 退款审核结果
+     */
+    private String conclusion;
+}

+ 2 - 2
src/main/java/com/zswl/dataservicestarter/domain/User.java

@@ -1,6 +1,6 @@
 package com.zswl.dataservicestarter.domain;
 
-import com.zswl.dataservicestarter.domain.base.SuperEntity;
+import com.zswl.dataservicestarter.domain.base.DataServiceSuperEntity;
 import lombok.AllArgsConstructor;
 import lombok.Data;
 import lombok.NoArgsConstructor;
@@ -14,7 +14,7 @@ import org.springframework.data.mongodb.core.mapping.Document;
 @Document
 @NoArgsConstructor
 @AllArgsConstructor
-public class User extends SuperEntity {
+public class User extends DataServiceSuperEntity {
     private String name;
     private Integer age;
     private String address;

+ 1 - 1
src/main/java/com/zswl/dataservicestarter/domain/base/SuperEntity.java → src/main/java/com/zswl/dataservicestarter/domain/base/DataServiceSuperEntity.java

@@ -15,7 +15,7 @@ import java.io.Serializable;
 @Data
 @MappedSuperclass
 @EntityListeners(AuditingEntityListener.class)
-public abstract class SuperEntity extends AbstractPersistable<String> implements Serializable {
+public abstract class DataServiceSuperEntity extends AbstractPersistable<String> implements Serializable {
 
 
     @Id

+ 18 - 0
src/main/java/com/zswl/dataservicestarter/helper/ApplicationContextHolder.java

@@ -0,0 +1,18 @@
+package com.zswl.dataservicestarter.helper;
+
+import org.springframework.beans.BeansException;
+import org.springframework.context.ApplicationContext;
+import org.springframework.context.ApplicationContextAware;
+
+public class ApplicationContextHolder implements ApplicationContextAware {
+    private static ApplicationContext context;
+
+    @Override
+    public void setApplicationContext(ApplicationContext context) throws BeansException {
+        ApplicationContextHolder.context = context;
+    }
+
+    public static ApplicationContext getContext() {
+        return context;
+    }
+}

+ 2 - 2
src/main/java/com/zswl/dataservicestarter/helper/BatchQueryHelper.java

@@ -1,6 +1,6 @@
 package com.zswl.dataservicestarter.helper;
 
-import com.zswl.dataservicestarter.domain.base.SuperEntity;
+import com.zswl.dataservicestarter.domain.base.DataServiceSuperEntity;
 import com.zswl.dataservicestarter.utils.bean.EntityObjectUtil;
 import org.springframework.beans.factory.annotation.Autowired;
 import org.springframework.data.mongodb.core.MongoTemplate;
@@ -29,7 +29,7 @@ public class BatchQueryHelper {
      * @param <T>
      * @return
      */
-    public <T extends SuperEntity> List<T> batchQuery(Class<T> entityCls, Collection<Map<String, Object>> items) {
+    public <T extends DataServiceSuperEntity> List<T> batchQuery(Class<T> entityCls, Collection<Map<String, Object>> items) {
         return this.mongoTemplate.find(Query.query(EntityObjectUtil.createQueryBatch(items)), entityCls);
     }
 

+ 4 - 4
src/main/java/com/zswl/dataservicestarter/helper/DBHelper.java

@@ -1,6 +1,6 @@
 package com.zswl.dataservicestarter.helper;
 
-import com.zswl.dataservicestarter.domain.base.SuperEntity;
+import com.zswl.dataservicestarter.domain.base.DataServiceSuperEntity;
 import com.zswl.dataservicestarter.helper.jpa.TransactionHelper;
 import lombok.Getter;
 import lombok.Setter;
@@ -67,7 +67,7 @@ public class DBHelper {
      *
      * @param entity
      */
-    public void updateTime(SuperEntity entity) {
+    public void updateTime(DataServiceSuperEntity entity) {
         entity.setUpdateTime(getTime());
     }
 
@@ -76,7 +76,7 @@ public class DBHelper {
      *
      * @param entity
      */
-    public void saveTime(SuperEntity entity) {
+    public void saveTime(DataServiceSuperEntity entity) {
         entity.setCreateTime(getTime());
         updateTime(entity);
     }
@@ -160,7 +160,7 @@ public class DBHelper {
      * @param cls
      * @return
      */
-    public Page<Document> pages(Criteria criteria, Pageable pageable, Class<? extends SuperEntity> cls, AggregationOperation... aggregationOperations) {
+    public Page<Document> pages(Criteria criteria, Pageable pageable, Class<? extends DataServiceSuperEntity> cls, AggregationOperation... aggregationOperations) {
         //分页
         AggregationOperation skip = Aggregation.skip(pageable.getOffset());
         AggregationOperation limit = Aggregation.limit(pageable.getPageSize());

+ 7 - 7
src/main/java/com/zswl/dataservicestarter/helper/ReIndexHelper.java

@@ -1,6 +1,6 @@
 package com.zswl.dataservicestarter.helper;
 
-import com.zswl.dataservicestarter.domain.base.SuperEntity;
+import com.zswl.dataservicestarter.domain.base.DataServiceSuperEntity;
 import com.zswl.dataservicestarter.utils.bean.BeanUtil;
 import lombok.SneakyThrows;
 import lombok.extern.slf4j.Slf4j;
@@ -35,7 +35,7 @@ public class ReIndexHelper {
     /**
      * 重建索引
      */
-    public void reIndexFromField(Class<? extends SuperEntity> entityClass, String fieldName, Class<?> cls) {
+    public void reIndexFromField(Class<? extends DataServiceSuperEntity> entityClass, String fieldName, Class<?> cls) {
         //构建索引
         Set<Index> nowIndexNames = BeanUtil.readBeanType(cls).keySet()
                 .stream()
@@ -52,7 +52,7 @@ public class ReIndexHelper {
     /**
      * 重置索引
      */
-    public void reIndexFromMap(Class<? extends SuperEntity> entityClass, String fieldName) {
+    public void reIndexFromMap(Class<? extends DataServiceSuperEntity> entityClass, String fieldName) {
         //构建索引
         Set<Index> nowIndexNames = getIndexNamesFromMap(entityClass, fieldName)
                 .stream()
@@ -110,7 +110,7 @@ public class ReIndexHelper {
      * @param entityClass
      * @return
      */
-    public Set<String> getIndexNames(Class<? extends SuperEntity> entityClass) {
+    public Set<String> getIndexNames(Class<? extends DataServiceSuperEntity> entityClass) {
         return this.getIndexNames(this.mongoTemplate.getCollectionName(entityClass));
     }
 
@@ -161,7 +161,7 @@ public class ReIndexHelper {
      * @param indexs
      */
     @SneakyThrows
-    public void updateIndex(Class<? extends SuperEntity> entityClass, Index... indexs) {
+    public void updateIndex(Class<? extends DataServiceSuperEntity> entityClass, Index... indexs) {
         this.updateIndex(this.mongoTemplate.getCollectionName(entityClass), indexs);
     }
 
@@ -172,7 +172,7 @@ public class ReIndexHelper {
      * @param entityClass
      */
     @SneakyThrows
-    public void updateIndex(Class<? extends SuperEntity> entityClass, String indexName, Index... indexs) {
+    public void updateIndex(Class<? extends DataServiceSuperEntity> entityClass, String indexName, Index... indexs) {
         boolean isUpdate = false;
         List<IndexInfo> indexInfos = this.mongoTemplate.indexOps(entityClass)
                 .getIndexInfo()
@@ -268,7 +268,7 @@ public class ReIndexHelper {
      *
      * @return
      */
-    public Set<String> getIndexNamesFromMap(Class<? extends SuperEntity> entityClass, String fieldName) {
+    public Set<String> getIndexNamesFromMap(Class<? extends DataServiceSuperEntity> entityClass, String fieldName) {
         String collectionName = this.mongoTemplate.getCollectionName(entityClass);
         String map = "function(){if(this." + fieldName + "==null){return}for(var key in this." + fieldName + "){emit(key,1)}};";
         String reduce = "function(key,values){return values.length};";

+ 53 - 0
src/main/java/com/zswl/dataservicestarter/model/DataServiceGoodsModel.java

@@ -0,0 +1,53 @@
+package com.zswl.dataservicestarter.model;
+
+import cn.hutool.json.JSONObject;
+import com.zswl.dataservicestarter.domain.base.DataServiceSuperEntity;
+import lombok.AllArgsConstructor;
+import lombok.Builder;
+import lombok.Data;
+import lombok.NoArgsConstructor;
+import org.springframework.data.mongodb.core.mapping.Document;
+
+import java.math.BigDecimal;
+
+/**
+ * 商品信息
+ */
+@Data
+@Builder
+@Document
+@AllArgsConstructor
+@NoArgsConstructor
+public class DataServiceGoodsModel extends DataServiceSuperEntity {
+
+    /**
+     * 订单号
+     */
+    private String orderNo;
+
+    /**
+     * 商品id
+     */
+    private String goodsId;
+
+    /**
+     * 商品类型
+     */
+    private Integer goodsType;
+
+    /**
+     * 商品全部信息
+     */
+    private JSONObject goodsInfo;
+
+    /**
+     * 商品单价
+     */
+    private BigDecimal payAmount;
+
+    /**
+     * 扩展信息
+     */
+    private String extend;
+
+}

+ 96 - 3
src/main/java/com/zswl/dataservicestarter/model/DataServiceOrderInfoModel.java

@@ -1,10 +1,20 @@
 package com.zswl.dataservicestarter.model;
 
+import cn.hutool.json.JSONObject;
+import com.zswl.dataservicestarter.domain.DataServiceGoods;
+import com.zswl.dataservicestarter.domain.DataServicePaymentInfo;
+import com.zswl.dataservicestarter.domain.RefundLog;
+import com.zswl.dataservicestarter.type.DataServiceOrderType;
 import io.swagger.annotations.ApiModel;
 import io.swagger.annotations.ApiModelProperty;
 import lombok.AllArgsConstructor;
 import lombok.Data;
 import lombok.NoArgsConstructor;
+import org.springframework.data.mongodb.core.index.Indexed;
+import org.springframework.data.mongodb.core.mapping.DBRef;
+
+import java.math.BigDecimal;
+import java.util.List;
 
 /**
  * @author TRX
@@ -15,8 +25,91 @@ import lombok.NoArgsConstructor;
 @NoArgsConstructor
 @ApiModel("支付信息Model")
 public class DataServiceOrderInfoModel extends SuperModel {
-    @ApiModelProperty("数据ID")
-    private String dataId;
-    @ApiModelProperty("数据的hashCode")
+    /**
+     * 数据的hashCode
+     */
     private int hashCode;
+
+    /**
+     * 订单类型 平台  商铺
+     */
+    private DataServiceOrderType orderType;
+
+    /**
+     * 是否已同步
+     */
+    private Boolean isSync;
+
+    /**
+     * 同步时间
+     */
+    private Long syncTime;
+
+    //----------------------------平台订单信息 start-------------------------
+
+    /**
+     * 用户ID
+     */
+    private String userId;
+
+    /**
+     * 店铺ID
+     */
+    private String epId;
+
+    /**
+     * 订单号
+     */
+    private String orderNo;
+
+    /**
+     * 店铺信息
+     */
+    private JSONObject shopInfo;
+
+    /**
+     * 商品总价格
+     */
+    private BigDecimal totalAmount;
+
+    /**
+     * 优惠价格
+     */
+    private BigDecimal discountAmount;
+
+
+    /**
+     * 实际支付价格
+     */
+    private BigDecimal payAmount;
+
+    /**
+     * 使用优惠券信息
+     */
+    private List<JSONObject> discountList;
+
+    /**
+     * 退款信息
+     */
+    private RefundLog refundLog;
+
+    /**
+     * 是否已退款
+     */
+    private Boolean isRefund;
+
+    /**
+     * 扩展参数
+     */
+    private String extend;
+
+    /**
+     * 商品和分账信息
+     */
+    private List<DataServiceGoodsModel> goodsList;
+
+    /**
+     * 支付信息
+     */
+    private DataServicePaymentInfoModel payment;
 }

+ 51 - 0
src/main/java/com/zswl/dataservicestarter/model/DataServicePaymentInfoModel.java

@@ -0,0 +1,51 @@
+package com.zswl.dataservicestarter.model;
+
+import com.zswl.dataservicestarter.domain.base.DataServiceSuperEntity;
+import lombok.AllArgsConstructor;
+import lombok.Data;
+import lombok.NoArgsConstructor;
+import org.springframework.data.mongodb.core.index.Indexed;
+
+/**
+ * @author TRX
+ * @date 2024/3/25
+ */
+@Data
+@AllArgsConstructor
+@NoArgsConstructor
+public class DataServicePaymentInfoModel extends DataServiceSuperEntity {
+
+    @Indexed(unique = true)
+    private String orderNo;
+
+    /**
+     * 支付订单号
+     */
+    private String paymentNo;
+
+    /**
+     * 支付时间
+     */
+    private String paymentTime;
+
+    /**
+     * 支付方式
+     */
+    private String paymentWay;
+
+    /**
+     * 支付订单状态
+     */
+    private String paymentStatus;
+
+    /**
+     * 支付信息
+     */
+    private String miniPayRequest;
+
+    /**
+     * 支付订单创建时间
+     */
+    private Long payCreateTime;
+
+}

+ 115 - 11
src/main/java/com/zswl/dataservicestarter/service/DataServiceOrderInfoService.java

@@ -1,11 +1,26 @@
 package com.zswl.dataservicestarter.service;
 
+import com.zswl.dataservicestarter.dao.DataServiceGoodsDao;
 import com.zswl.dataservicestarter.dao.DataServiceOrderInfoDao;
+import com.zswl.dataservicestarter.dao.DataServicePaymentInfoDao;
+import com.zswl.dataservicestarter.domain.DataServiceGoods;
 import com.zswl.dataservicestarter.domain.DataServiceOrderInfo;
+import com.zswl.dataservicestarter.domain.DataServicePaymentInfo;
+import com.zswl.dataservicestarter.model.DataServiceGoodsModel;
+import com.zswl.dataservicestarter.model.DataServiceOrderInfoModel;
+import com.zswl.dataservicestarter.model.DataServicePaymentInfoModel;
+import com.zswl.dataservicestarter.type.DataServiceOrderType;
+import com.zswl.dataservicestarter.utils.CommonUtil;
 import com.zswl.dataservicestarter.utils.result.ResultContent;
 import org.apache.commons.lang3.ObjectUtils;
+import org.apache.commons.lang3.StringUtils;
+import org.springframework.beans.BeanUtils;
 import org.springframework.beans.factory.annotation.Autowired;
 import org.springframework.stereotype.Service;
+import org.springframework.transaction.annotation.Transactional;
+
+import java.util.ArrayList;
+import java.util.List;
 
 /**
  * 订单信息 管理
@@ -19,28 +34,117 @@ public class DataServiceOrderInfoService {
     @Autowired
     DataServiceOrderInfoDao orderInfoDao;
 
+    @Autowired
+    DataServiceGoodsDao dataServiceGoodsDao;
+
+    @Autowired
+    DataServicePaymentInfoDao paymentInfoDao;
+
     /**
-     * 更加HashCode验证支付信息是否存在
+     * 从平台同步订单信息到 数据服务
      *
-     * @param hashCode
+     * @param model
      * @return
      */
-    public ResultContent validateDataByHashCode(int hashCode) {
-        DataServiceOrderInfo orderInfo = orderInfoDao.findTopByHashCode(hashCode);
-        if (ObjectUtils.isEmpty(orderInfo)) {
-            return ResultContent.buildFail("对应数据未找到");
+    @Transactional
+    public ResultContent saveOrderInfoFromPlatform(DataServiceOrderInfoModel model) {
+        // 验证数据完整性
+        if (StringUtils.isEmpty(model.getEpId())) {
+            return ResultContent.buildFail("商铺ID不能为空");
         }
-        return ResultContent.buildSuccess();
+        if (StringUtils.isEmpty(model.getOrderNo())) {
+            return ResultContent.buildFail("订单号不能为空");
+        }
+        if (model.getShopInfo() == null) {
+            return ResultContent.buildFail("店铺信息为空");
+        }
+        if (CommonUtil.bigDecimalIsEmpty(model.getTotalAmount())) {
+            return ResultContent.buildFail("商品总价格不能为空");
+        }
+        String orderNo = model.getOrderNo();
+        DataServiceOrderInfo tempOrderInfo = orderInfoDao.findTopByOrderNo(orderNo);
+        if (ObjectUtils.isNotEmpty(tempOrderInfo)) {
+//            return ResultContent.buildFail(String.format("%s 订单号已存在", model.getOrderNo()));
+        }
+        if (CommonUtil.bigDecimalIsEmpty(model.getDiscountAmount())) {
+            return ResultContent.buildFail("优惠价格不能为空");
+        }
+        if (CommonUtil.bigDecimalIsEmpty(model.getPayAmount())) {
+            return ResultContent.buildFail("实际支付价格不能为空");
+        }
+
+        // 订单管理的商品信息
+        List<DataServiceGoodsModel> goodsList = model.getGoodsList();
+        if (ObjectUtils.isEmpty(goodsList)) {
+            return ResultContent.buildFail("商品不能为空");
+        }
+        List<DataServiceGoods> goodsList1 = new ArrayList<>();
+        for (DataServiceGoodsModel goodsModel : goodsList) {
+            DataServiceGoods goods = new DataServiceGoods();
+            if (StringUtils.isEmpty(goodsModel.getGoodsId())) {
+                return ResultContent.buildFail(String.format("商品id不能为空"));
+            }
+            if (goodsModel.getGoodsInfo() == null) {
+                return ResultContent.buildFail(String.format("商品信息不能为空"));
+            }
+
+            BeanUtils.copyProperties(goodsModel, goods);
+            goods.setOrderNo(orderNo);
+
+            goodsList1.add(goods);
+        }
+
+        // 支付信息
+        DataServicePaymentInfoModel paymentInfoModel = model.getPayment();
+        if (StringUtils.isEmpty(paymentInfoModel.getPaymentTime())) {
+            return ResultContent.buildFail("支付时间为空");
+        }
+        DataServicePaymentInfo paymentInfo = new DataServicePaymentInfo();
+        BeanUtils.copyProperties(paymentInfoModel, paymentInfo);
+        paymentInfo.setOrderNo(orderNo);
+
+        dataServiceGoodsDao.saveAll(goodsList1);
+        paymentInfoDao.save(paymentInfo);
+
+        // 保存响应数据
+        DataServiceOrderInfo orderInfo = new DataServiceOrderInfo();
+        BeanUtils.copyProperties(model, orderInfo);
+        orderInfo.setGoodsList(goodsList1);
+        orderInfo.setPayment(paymentInfo);
+        orderInfo.setOrderType(DataServiceOrderType.Platform);
+        orderInfo.setIsSync2Platform(Boolean.FALSE);
+        orderInfo.setIsSync2Shop(Boolean.FALSE);
+        int hasCode = CommonUtil.getEntityHashCode(orderInfo);
+        orderInfo.setHashCode(hasCode);
+
+        orderInfoDao.save(orderInfo);
+
+        return ResultContent.buildSuccess(hasCode);
     }
 
     /**
-     * 更加dataId验证支付信息是否存在
+     * 根据订单号查询订单信息
      *
-     * @param dataId
+     * @param orderNo
      * @return
      */
-    public ResultContent validateDataByDataId(String dataId) {
-        DataServiceOrderInfo orderInfo = orderInfoDao.findTopByDataId(dataId);
+    public ResultContent<DataServiceOrderInfo> getOrderInfoByOrderNo(String orderNo) {
+        if (StringUtils.isEmpty(orderNo)) {
+            return ResultContent.buildFail("订单号为空");
+        }
+        DataServiceOrderInfo orderInfo = orderInfoDao.findTopByOrderNo(orderNo);
+
+        return ResultContent.buildSuccess(orderInfo);
+    }
+
+    /**
+     * 更加HashCode验证支付信息是否存在
+     *
+     * @param hashCode
+     * @return
+     */
+    public ResultContent validateDataByHashCode(int hashCode) {
+        DataServiceOrderInfo orderInfo = orderInfoDao.findTopByHashCode(hashCode);
         if (ObjectUtils.isEmpty(orderInfo)) {
             return ResultContent.buildFail("对应数据未找到");
         }

+ 0 - 28
src/main/java/com/zswl/dataservicestarter/service/DataServicePaymentInfoService.java

@@ -19,32 +19,4 @@ public class DataServicePaymentInfoService {
     @Autowired
     DataServicePaymentInfoDao paymentInfoDao;
 
-    /**
-     * 更加HashCode验证订单信息是否存在
-     *
-     * @param hashCode
-     * @return
-     */
-    public ResultContent validateDataByHashCode(int hashCode) {
-        DataServicePaymentInfo paymentInfo = paymentInfoDao.findTopByHashCode(hashCode);
-        if (ObjectUtils.isEmpty(paymentInfo)) {
-            return ResultContent.buildFail("对应数据未找到");
-        }
-        return ResultContent.buildSuccess();
-    }
-
-    /**
-     * 更加dataId验证订单信息是否存在
-     *
-     * @param dataId
-     * @return
-     */
-    public ResultContent validateDataByDataId(String dataId) {
-        DataServicePaymentInfo paymentInfo = paymentInfoDao.findTopByDataId(dataId);
-        if (ObjectUtils.isEmpty(paymentInfo)) {
-            return ResultContent.buildFail("对应数据未找到");
-        }
-        return ResultContent.buildSuccess();
-    }
-
 }

+ 39 - 17
src/main/java/com/zswl/dataservicestarter/service/UserService.java

@@ -1,11 +1,16 @@
 package com.zswl.dataservicestarter.service;
 
+import cn.hutool.json.JSONObject;
 import com.zswl.dataservicestarter.dao.DataServiceOrderInfoDao;
 import com.zswl.dataservicestarter.dao.UserDao;
 import com.zswl.dataservicestarter.domain.DataServiceOrderInfo;
 import com.zswl.dataservicestarter.domain.User;
+import com.zswl.dataservicestarter.model.DataServiceGoodsModel;
+import com.zswl.dataservicestarter.model.DataServiceOrderInfoModel;
+import com.zswl.dataservicestarter.model.DataServicePaymentInfoModel;
 import com.zswl.dataservicestarter.service.baeService.RedisService;
 import com.zswl.dataservicestarter.utils.AppInfoUtil;
+import com.zswl.dataservicestarter.utils.CommonUtil;
 import com.zswl.dataservicestarter.utils.exception.BusinessException;
 import com.zswl.dataservicestarter.utils.result.ResultContent;
 import lombok.extern.slf4j.Slf4j;
@@ -15,6 +20,10 @@ import org.springframework.data.mongodb.gridfs.GridFsTemplate;
 import org.springframework.stereotype.Service;
 import org.springframework.transaction.annotation.Transactional;
 
+import java.math.BigDecimal;
+import java.util.ArrayList;
+import java.util.List;
+
 /**
  * @author TRX
  * @date 2024/3/20
@@ -35,24 +44,37 @@ public class UserService {
     @Autowired
     DataServiceOrderInfoDao orderInfoDao;
 
+    @Autowired
+    DataServiceOrderInfoService orderInfoService;
+
     @Transactional
     public ResultContent addUser(String name) {
-        User user = new User();
-        if (StringUtils.isEmpty(name)) {
-            name = "名称";
-        }
-        //        name = name + Math.random();
-        user.setName(name);
-        user.setAge(1);
-        user.setAddress("重庆市渝北区");
-        userDao.save(user);
-        int code = user.hashCode();
-
-        DataServiceOrderInfo orderInfo = new DataServiceOrderInfo();
-        orderInfo.setCode(code + "");
-        orderInfoDao.save(orderInfo);
-
-        log.info("名称: {} code {} redis: {}", name, code, AppInfoUtil.generateRandomString());
-        return ResultContent.buildSuccess(name + ": " + code);
+        DataServiceOrderInfoModel model = new DataServiceOrderInfoModel();
+        model.setEpId("1");
+        model.setOrderNo("1000");
+        JSONObject shopInfo = new JSONObject();
+        shopInfo.append("name", "美宜佳");
+        model.setShopInfo(shopInfo);
+        model.setTotalAmount(BigDecimal.valueOf(100));
+        model.setDiscountAmount(BigDecimal.valueOf(10));
+        model.setPayAmount(BigDecimal.valueOf(90));
+
+        List<DataServiceGoodsModel> goodsList = new ArrayList<>();
+        DataServiceGoodsModel goodsModel = new DataServiceGoodsModel();
+        goodsModel.setGoodsId("1");
+        goodsModel.setGoodsType(0);
+        JSONObject goodsInfo = new JSONObject();
+        goodsInfo.putOpt("name", "打火机");
+        goodsModel.setGoodsInfo(goodsInfo);
+        goodsModel.setPayAmount(BigDecimal.valueOf(90));
+        goodsList.add(goodsModel);
+        model.setGoodsList(goodsList);
+
+        // 支付信息
+        DataServicePaymentInfoModel paymentInfoMode = new DataServicePaymentInfoModel();
+        paymentInfoMode.setPaymentTime(String.valueOf(System.currentTimeMillis()));
+        model.setPayment(paymentInfoMode);
+
+        return orderInfoService.saveOrderInfoFromPlatform(model);
     }
 }

+ 5 - 0
src/main/java/com/zswl/dataservicestarter/type/CommonEnum.java

@@ -0,0 +1,5 @@
+package com.zswl.dataservicestarter.type;
+
+public interface CommonEnum {
+    public String getRemark();
+}

+ 18 - 0
src/main/java/com/zswl/dataservicestarter/type/DataServiceOrderType.java

@@ -0,0 +1,18 @@
+package com.zswl.dataservicestarter.type;
+
+import lombok.Getter;
+
+/**
+ * 订单类型
+ */
+public enum DataServiceOrderType {
+    Platform("平台"), Shop("商铺"),
+    ;
+
+    @Getter
+    private String remark;
+
+    DataServiceOrderType(String remark) {
+        this.remark = remark;
+    }
+}

+ 57 - 0
src/main/java/com/zswl/dataservicestarter/type/DataServiceRefundLogType.java

@@ -0,0 +1,57 @@
+package com.zswl.dataservicestarter.type;
+
+import lombok.Getter;
+
+/**
+ * 订单类型
+ */
+public enum DataServiceRefundLogType {
+    /**
+     * 待付款
+     */
+    WAIT_PAYMENT("待付款"),
+
+    /**
+     * 待使用
+     */
+    WAIT_USE("待使用"),
+
+    /**
+     * 已使用
+     */
+    USED("已使用"),
+    /**
+     * 申请退款
+     */
+    APPLY_REFUND("申请退款"),
+
+    /**
+     * 退款处理中
+     */
+    APPLY_REFUNDING("退款处理中"),
+
+    /**
+     * 拒绝退款
+     */
+    REFUSAL_REFUND("拒绝退款"),
+
+    UN_REFUND(""),
+
+    /**
+     * 已退款
+     */
+    REFUNDED("已退款"),
+
+    /**
+     * 关闭订单
+     */
+    CLOSE("闭订单"),
+    ;
+
+    @Getter
+    private String remark;
+
+    DataServiceRefundLogType(String remark) {
+        this.remark = remark;
+    }
+}

+ 63 - 0
src/main/java/com/zswl/dataservicestarter/utils/AopTargetUtil.java

@@ -0,0 +1,63 @@
+package com.zswl.dataservicestarter.utils;
+
+import org.springframework.aop.framework.AdvisedSupport;
+import org.springframework.aop.framework.AopProxy;
+import org.springframework.aop.support.AopUtils;
+import org.springframework.util.ClassUtils;
+
+import java.lang.reflect.Field;
+
+public class AopTargetUtil {
+
+    /**
+     * 获取 目标对象
+     * @param proxy 代理对象
+     * @return 原生对象
+     * @throws Exception 异常
+     */
+    public static Object getTarget(Object proxy) throws Exception {
+         if(proxy==null)
+         {
+             return null;
+         }
+        if(!AopUtils.isAopProxy(proxy) && !proxy.getClass().getName().contains(ClassUtils.CGLIB_CLASS_SEPARATOR)) {
+            return proxy;//不是代理对象
+        }
+
+        if(AopUtils.isJdkDynamicProxy(proxy)) {
+            return getJdkDynamicProxyTargetObject(proxy);
+        } else { //cglib
+            return getCglibProxyTargetObject(proxy);
+        }
+
+    }
+
+
+    private static Object getCglibProxyTargetObject(Object proxy) throws Exception {
+        Field h = proxy.getClass().getDeclaredField("CGLIB$CALLBACK_0");
+        h.setAccessible(true);
+        Object dynamicAdvisedInterceptor = h.get(proxy);
+
+        try {
+            Field result = dynamicAdvisedInterceptor.getClass().getDeclaredField("result");
+            result.setAccessible(true);
+            return  result.get(dynamicAdvisedInterceptor);
+        }catch (NoSuchFieldException nfe)
+        {
+            nfe.printStackTrace();
+        }
+        return  null;
+    }
+
+
+    private static Object getJdkDynamicProxyTargetObject(Object proxy) throws Exception {
+        Field h = proxy.getClass().getSuperclass().getDeclaredField("h");
+        h.setAccessible(true);
+        AopProxy aopProxy = (AopProxy) h.get(proxy);
+
+        Field advised = aopProxy.getClass().getDeclaredField("advised");
+        advised.setAccessible(true);
+
+        return ((AdvisedSupport)advised.get(aopProxy)).getTargetSource().getTarget();
+    }
+}

+ 400 - 0
src/main/java/com/zswl/dataservicestarter/utils/BeanUtils.java

@@ -0,0 +1,400 @@
+package com.zswl.dataservicestarter.utils;
+
+import com.fasterxml.jackson.core.JsonProcessingException;
+import com.fasterxml.jackson.core.type.TypeReference;
+import com.fasterxml.jackson.databind.DeserializationFeature;
+import com.fasterxml.jackson.databind.JavaType;
+import com.fasterxml.jackson.databind.ObjectMapper;
+import com.zswl.dataservicestarter.domain.base.DataServiceSuperEntity;
+import com.zswl.dataservicestarter.helper.ApplicationContextHolder;
+import com.zswl.dataservicestarter.type.CommonEnum;
+import io.swagger.annotations.ApiModelProperty;
+import org.apache.commons.lang3.ObjectUtils;
+import org.slf4j.Logger;
+import org.slf4j.LoggerFactory;
+import org.springframework.beans.FatalBeanException;
+import org.springframework.cglib.beans.BeanMap;
+import org.springframework.util.ClassUtils;
+
+import java.beans.Introspector;
+import java.beans.PropertyDescriptor;
+import java.lang.reflect.*;
+import java.util.*;
+
+public class BeanUtils extends org.springframework.beans.BeanUtils {
+
+    private static Logger log = LoggerFactory.getLogger(BeanUtils.class);
+
+
+    /**
+     * 将对象属性转化为map结合
+     */
+    public static <T> Map<String, Object> beanToMap(T bean) {
+        Map<String, Object> map = new HashMap<>();
+        if (bean != null) {
+            BeanMap beanMap = BeanMap.create(bean);
+            for (Object key : beanMap.keySet()) {
+                map.put(key + "", beanMap.get(key));
+            }
+        }
+        return map;
+    }
+
+    public static <T> Map<String, Object> beanToMapBlockRef(T bean) {
+        Map<String, Object> data = new HashMap<>();
+        if (ObjectUtils.isNotEmpty(bean)) {
+            Map<String, Object> map = BeanMap.create(bean);
+            for (Map.Entry<String, Object> entry : map.entrySet()) {
+                String key = entry.getKey();
+                Object value = entry.getValue();
+                List<String> _keys = new ArrayList<>();
+                data.put(key, loopValue(value, _keys));
+            }
+        }
+        return data;
+    }
+
+    protected static Object loopValue(Object value, List<String> _keys) {
+        if (value != null && isCustomObj(value)) {
+            if (isCglibObj(value)) {
+                return null;
+            }
+            Map<String, Object> _map = BeanMap.create(value);
+            HashMap<String, Object> map = new HashMap<>();
+            for (Map.Entry<String, Object> entry : _map.entrySet()) {
+                if (!_keys.contains(entry.getKey())) {
+                    // prevent custom entity endless loop
+                    if (entry.getValue() != null && isCustomObj(entry.getValue())) {
+                        _keys.add(entry.getKey());
+                    }
+                    map.put(entry.getKey(), loopValue(entry.getValue(), _keys));
+                }
+            }
+            return map;
+        }
+        return value;
+    }
+
+    private static boolean isCglibObj(Object value) {
+        String name = value.getClass().getName();
+        return name == null || name.contains(ClassUtils.CGLIB_CLASS_SEPARATOR);
+    }
+
+    /**
+     * 判断是否是自定义类型
+     *
+     * @param value
+     * @return
+     */
+    private static boolean isCustomObj(Object value) {
+        if (value == null) {
+            return true;
+        }
+        String _name = value.getClass().getName();
+        if (_name.startsWith("java.lang") || _name.startsWith("java.util") || _name.startsWith("java.math") || (value instanceof Enum)) {
+            return false;
+        }
+        return true;
+    }
+
+    public static void copyPropertiesWithoutNull(Object source, Object target) {
+        if (source == null || target == null) {
+            return;
+        }
+        Class<?> actualEditable = target.getClass();
+        PropertyDescriptor[] targetPds = getPropertyDescriptors(actualEditable);
+        for (PropertyDescriptor targetPd : targetPds) {
+            if (targetPd.getWriteMethod() == null) {
+                continue;
+            }
+
+            try {
+                Object value = getValueFromSource(source, targetPd);
+                if (value == null) {
+                    continue;
+                }
+                if (!isSimpleProperty(targetPd.getPropertyType()) && !targetPd.getPropertyType().isInterface()) {
+                    Object targetPdValue = targetPd.getReadMethod().invoke(target);
+                    targetPdValue = AopTargetUtil.getTarget(targetPdValue);
+                    if (targetPdValue == null) {
+                        targetPdValue = targetPd.getPropertyType().getDeclaredConstructor().newInstance();
+                    }
+                    copyPropertiesWithoutNull(value, targetPdValue);
+                    setValue(target, targetPd, targetPdValue);
+                } else if (targetPd.getPropertyType().isAssignableFrom(List.class)) {
+                    Class paramCls = getFieldActualType(actualEditable.getDeclaredField(targetPd.getName()));
+                    if (paramCls != null) {
+                        Object targetPdValue = convertListToList((List) value, paramCls);
+                        setValue(target, targetPd, targetPdValue);
+                    }
+                } else {
+                    setValue(target, targetPd, value);
+                }
+            } catch (Exception ex) {
+                throw new FatalBeanException("Could not copy properties from source to target", ex);
+            }
+        }
+    }
+
+    private static void setValue(Object target, PropertyDescriptor targetPd, Object value) throws IllegalAccessException, InvocationTargetException {
+        if (value.getClass().isEnum() && targetPd.getPropertyType() == String.class) {
+            if (CommonEnum.class.isAssignableFrom(value.getClass())) {
+                CommonEnum commonEnum = (CommonEnum) value;
+                value = commonEnum.getRemark();
+            }
+        }
+        // 这里判断以下value是否为空
+        if ("".equals(value)) {
+            value = null;
+        }
+        if (value != null) {
+            Method writeMethod = targetPd.getWriteMethod();
+            if (!Modifier.isPublic(writeMethod.getDeclaringClass().getModifiers())) {
+                writeMethod.setAccessible(true);
+            }
+            try {
+                writeMethod.invoke(target, value);
+            } catch (Exception e) {
+                log.error("复制属性出错,target object type:{},target property name:{},type:{},set value type:{}", target.getClass(), targetPd.getName(), targetPd.getPropertyType(), value.getClass());
+                throw e;
+            }
+        }
+    }
+
+    public static <T> T mapToBean(Map map, T bean) {
+        BeanMap beanMap = BeanMap.create(bean);
+
+        beanMap.putAll(map);
+        return bean;
+
+    }
+
+    public static <T> List<T> convertListToList(List bList, TypeReference<List<T>> typeRef) {
+        if (bList == null) return null;
+        ObjectMapper objectMapper = ApplicationContextHolder.getContext().getBean(ObjectMapper.class);
+        List<T> list = null;
+        try {
+            //objectMapper.configure(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES, false);
+            String json = objectMapper.writeValueAsString(bList);
+            list = objectMapper.readValue(json, typeRef);
+        } catch (Exception e) {
+            e.printStackTrace();
+        }
+        return list;
+
+    }
+
+    public static <T> List<T> convertListToList(List bList, Class targetClass) {
+        if (bList == null) {
+            return null;
+        }
+        List<T> list = null;
+        ObjectMapper objectMapper = ApplicationContextHolder.getContext().getBean(ObjectMapper.class);
+        if (targetClass == Map.class) {
+            targetClass = HashMap.class;
+        }
+        JavaType javaType = objectMapper.getTypeFactory().constructParametricType(List.class, targetClass);
+        objectMapper.configure(DeserializationFeature.FAIL_ON_UNKNOWN_PROPERTIES, false);
+        String json = null;
+        try {
+            json = objectMapper.writeValueAsString(bList);
+            list = objectMapper.readValue(json, javaType);
+        } catch (JsonProcessingException e) {
+            throw new RuntimeException(e);
+        }
+        return list;
+    }
+
+/*    public static <T> List<T> fastConvertListToList(List bList, Class targetClass) {
+        if (bList == null) {
+            return null;
+        }
+
+        String json = JSON.toJSONString(bList, JSONWriter.Feature.FieldBased,JSONWriter.Feature.ReferenceDetection,JSONWriter.Feature.LargeObject);
+        List<T> list = JSON.parseArray(json,targetClass);
+        return list;
+    }*/
+
+    public static <T> List<T> beanConvertListToList(List bList, Class<T> targetClass) throws NoSuchMethodException, InvocationTargetException, InstantiationException, IllegalAccessException {
+        if (bList == null) {
+            return null;
+        }
+        List<T> list = new ArrayList<>(bList.size());
+
+        for (Object source : bList) {
+            if (Map.class.equals(targetClass)) {
+                Map map = new HashMap();
+                copyPropertiesWithoutNull(source, map);
+                list.add((T) map);
+            } else if (targetClass.isEnum()) {
+                list.add((T) source);
+            } else {
+                Constructor<T> constructor = targetClass.getDeclaredConstructor();
+                if (constructor != null) {
+                    T target = constructor.newInstance();
+                    copyPropertiesWithoutNull(source, target);
+                    list.add(target);
+                } else {
+                    log.warn("复制对象没有默认构造参数,请检查,复制类:{}", targetClass.getName());
+                }
+            }
+        }
+        return list;
+    }
+
+    public static String getActualType(Object o, int index) {
+        Type clazz = o.getClass().getGenericSuperclass();
+        ParameterizedType pt = (ParameterizedType) clazz;
+        return pt.getActualTypeArguments()[index].toString();
+    }
+
+    public static Class getFieldActualType(Field field) {
+        Type genType = field.getGenericType();
+        if (genType == null) {
+            return null;
+        } else if (genType instanceof ParameterizedType) {
+            ParameterizedType pt = (ParameterizedType) genType;
+            if (pt.getActualTypeArguments()[0] instanceof ParameterizedType) {
+                return (Class) ((ParameterizedType) pt.getActualTypeArguments()[0]).getRawType();
+            } else {
+                return (Class) pt.getActualTypeArguments()[0];
+            }
+        } else {
+            return null;
+        }
+    }
+
+    public static Object getValueFromSource(Object source, PropertyDescriptor targetPd) throws InvocationTargetException, IllegalAccessException {
+        Class sourceClass = source.getClass();
+        PropertyDescriptor sourcePd = getPropertyDescriptor(sourceClass, targetPd.getName());
+        if (sourcePd == null || sourcePd.getReadMethod() == null) {
+            Method readMethod = targetPd.getReadMethod();
+            if (readMethod != null) {
+                String readMethodName = readMethod.getName();
+                Method sourceReadMethod = findMethod(sourceClass, readMethodName);
+                if (sourceReadMethod != null && Modifier.isPublic(sourceReadMethod.getDeclaringClass().getModifiers())) {
+                    if (targetPd.getPropertyType().equals(sourceReadMethod.getReturnType())) {
+                        Object value = readMethod.invoke(source);
+                        return value;
+                    }
+                }
+            }
+            return null;
+        }
+
+        boolean changeAccess = false;
+        Method readMethod = sourcePd.getReadMethod();
+        if (!Modifier.isPublic(readMethod.getDeclaringClass().getModifiers())) {
+            readMethod.setAccessible(true);
+            changeAccess = true;
+        }
+        Object value = readMethod.invoke(source);
+        if (changeAccess) {
+            readMethod.setAccessible(false);
+        }
+        return value;
+    }
+
+    /**
+     * 比较两个实体属性值,返回一个boolean,true则表时两个对象中的属性值无差异
+     *
+     * @param oldObject 进行属性比较的对象1
+     * @param newObject 进行属性比较的对象2
+     * @return 属性差异比较结果boolean
+     */
+    public static boolean compareObject(Object oldObject, Object newObject) {
+        Map<String, Map<String, Object>> resultMap = compareFields(oldObject, newObject);
+
+        if (resultMap.size() > 0) {
+            return false;
+        } else {
+            return true;
+        }
+    }
+
+    /**
+     * 比较两个实体属性值,返回一个map以有差异的属性名为key,value为一个Map分别存oldObject,newObject此属性名的值
+     *
+     * @param oldObject 进行属性比较的对象1
+     * @param newObject 进行属性比较的对象2
+     * @return 属性差异比较结果map
+     */
+    public static Map<String, Map<String, Object>> compareFields(Object oldObject, Object newObject) {
+        Map<String, Map<String, Object>> map = new HashMap<>();
+
+        try {
+            /**
+             * 只有两个对象都是同一类型的才有可比性
+             */
+            if (oldObject.getClass() == newObject.getClass()) {
+                Class clazz = oldObject.getClass();
+
+                //获取object的所有属性
+                PropertyDescriptor[] pds = Introspector.getBeanInfo(clazz, Object.class).getPropertyDescriptors();
+
+                for (PropertyDescriptor pd : pds) {
+                    //遍历获取属性名
+                    String name = pd.getName();
+                    String description = name;
+
+                    Field field = null;
+                    try {
+                        field = clazz.getDeclaredField(name);
+                    } catch (NoSuchFieldException nsee) {
+                        try {
+                            field = clazz.getSuperclass().getDeclaredField(name);
+                        } catch (NoSuchFieldException nse) {
+
+                        }
+                    }
+
+                    if (field != null) {
+                        if (field.isAnnotationPresent(ApiModelProperty.class)) {
+                            ApiModelProperty apiModelProperty = field.getAnnotation(ApiModelProperty.class);
+                            description = apiModelProperty.value();
+                        }
+                    }
+                    //获取属性的get方法
+                    Method readMethod = pd.getReadMethod();
+
+                    // 在oldObject上调用get方法等同于获得oldObject的属性值
+                    Object oldValue = readMethod.invoke(oldObject);
+                    // 在newObject上调用get方法等同于获得newObject的属性值
+                    Object newValue = readMethod.invoke(newObject);
+
+                    if (oldValue == null && newValue == null) {
+                        continue;
+                    }
+                    if (oldValue instanceof List || newValue instanceof List) {
+                        continue;
+                    }
+
+                    if (oldValue == null && newValue != null) {
+                        Map<String, Object> valueMap = new HashMap<>(2);
+                        valueMap.put("oldValue", oldValue);
+                        valueMap.put("newValue", newValue);
+                        map.put(description, valueMap);
+                    } else if (oldValue instanceof DataServiceSuperEntity && newValue instanceof DataServiceSuperEntity) {
+                        DataServiceSuperEntity oldSp = (DataServiceSuperEntity) oldValue;
+                        DataServiceSuperEntity newSp = (DataServiceSuperEntity) newValue;
+                        if (!Objects.equals(oldSp.getId(), newSp.getId())) {
+                            Map<String, Object> valueMap = new HashMap<>(2);
+                            valueMap.put("oldValue", oldValue);
+                            valueMap.put("newValue", newValue);
+                            map.put(description, valueMap);
+                        }
+                    } else if (!Objects.equals(oldValue, newValue)) {// 比较这两个值是否相等,不等就可以放入map了
+                        Map<String, Object> valueMap = new HashMap<>(2);
+                        valueMap.put("oldValue", oldValue);
+                        valueMap.put("newValue", newValue);
+                        map.put(description, valueMap);
+                    }
+                }
+            }
+        } catch (Exception e) {
+            e.printStackTrace();
+        }
+
+        return map;
+    }
+}

+ 355 - 0
src/main/java/com/zswl/dataservicestarter/utils/CommonUtil.java

@@ -1,10 +1,365 @@
 package com.zswl.dataservicestarter.utils;
 
+import com.google.common.collect.Lists;
+import com.zswl.dataservicestarter.domain.base.DataServiceSuperEntity;
+import com.zswl.dataservicestarter.utils.exception.BusinessException;
+import lombok.extern.slf4j.Slf4j;
+import org.apache.commons.lang3.ObjectUtils;
+import org.apache.commons.lang3.StringUtils;
+import org.bson.types.Decimal128;
+import org.springframework.data.domain.Page;
+import org.springframework.data.domain.PageImpl;
+import org.springframework.data.domain.Pageable;
+
+import java.lang.reflect.Field;
+import java.math.BigDecimal;
+import java.math.RoundingMode;
+import java.util.*;
+
 /**
  * 工具类方法
  *
  * @author TRX
  * @date 2024/3
  */
+@Slf4j
 public class CommonUtil {
+
+    private static final List<String> outKeys = List.of("id", "createTime", "updateTime", "remark",
+            "hashCode", "isSync2Platform", "syncTime", "isSync2Shop");
+
+    public static <T extends DataServiceSuperEntity> int getEntityHashCode(T entity) {
+        int code = 0;
+        if (ObjectUtils.isEmpty(entity)) {
+            return code;
+        }
+        Field[] fields = entity.getClass().getDeclaredFields();
+        for (Field field : fields) {
+            String name = field.getName();
+            Class type = field.getType();
+//            log.info("字段: {} -> {}", name, type);
+            if (outKeys.contains(name)) {
+                continue;
+            }
+            int _code = 0;
+            field.setAccessible(true);
+            try {
+                Object obj = field.get(entity);
+                if (obj != null) {
+                    boolean isSuper = false;
+                    if (obj instanceof DataServiceSuperEntity) {
+                        isSuper = true;
+                    }
+                    if (!isSuper && obj instanceof List) {
+                        List<Object> objects = (List<Object>) obj;
+                        isSuper = objects.stream().anyMatch(element -> element instanceof DataServiceSuperEntity);
+                    }
+                    if (!isSuper) {
+                        _code = obj.hashCode();
+                    }
+                }
+//                log.info("值: {} {} ", obj, _code);
+            } catch (Exception e) {
+                e.printStackTrace();
+                throw new BusinessException(String.format("HashCode出错: %s", e.getMessage()));
+            }
+            code += _code;
+        }
+        return code;
+    }
+
+    /**
+     * 生成指定长度的随机码(由数字构成)
+     *
+     * @param length
+     * @return
+     */
+    public static String randomCode(int length) {
+        StringBuilder str = new StringBuilder();
+        Random random = new Random();
+        for (int i = 0; i < length; i++) {
+            str.append(random.nextInt(10));
+        }
+        return str.toString();
+    }
+
+    /**
+     * 生产UUID
+     *
+     * @return
+     */
+    public static String UUID() {
+        return UUID.randomUUID().toString().replaceAll("-", "");
+    }
+
+    /**
+     * 创建空分页对象
+     *
+     * @param pageable
+     * @param cls
+     * @param <T>
+     * @return
+     */
+    public static <T> Page<T> buildEmptyPage(Pageable pageable, Class<T> cls) {
+        return new PageImpl<T>(Lists.newArrayList(), pageable, 0);
+    }
+
+    public static Long getLongZero(Long number) {
+        if (number == null) {
+            return Long.valueOf(0);
+        }
+        return number;
+    }
+
+    /**
+     * 判断long值是否为空:为 null 或 0 时都为空
+     *
+     * @param longValue
+     * @return
+     */
+    public static boolean longIsEmpty(Long longValue) {
+        if (longValue == null || longValue <= 0) {
+            return true;
+        }
+        return false;
+    }
+
+    /**
+     * 判断bigDecimal值是否为空:为 null 或 0 时都为空
+     *
+     * @param bigDecimal
+     * @return
+     */
+    public static boolean bigDecimalIsEmpty(BigDecimal bigDecimal) {
+        if (bigDecimal == null || bigDecimal.compareTo(BigDecimal.ZERO) <= 0) {
+            return true;
+        }
+        return false;
+    }
+
+    /**
+     * 2个Long是否相等
+     *
+     * @param val1
+     * @param val2
+     * @return
+     */
+    public static boolean longIsEqual(Long val1, Long val2) {
+        if (val1 == null || val2 == null) {
+            return false;
+        }
+        if (val1.longValue() == val2.longValue()) {
+            return true;
+        }
+        return false;
+    }
+
+    /**
+     * 判断2个时间 是否是同一天
+     *
+     * @param time1
+     * @param time2
+     * @return
+     */
+    public static boolean isSameDay(Long time1, Long time2) {
+        if (time1 == null || time2 == null) {
+            return false;
+        }
+        if (DateUtils.paresTime(time1, DateUtils.pattern).equals(DateUtils.paresTime(time2, DateUtils.pattern))) {
+            return true;
+        }
+        return false;
+    }
+
+    public static BigDecimal getBigDecimalByLong(Long number) {
+        if (number != null) {
+            return BigDecimal.valueOf(number);
+        }
+        return BigDecimal.ZERO;
+    }
+
+    public static String getCollectionName(Class domainClass) {
+        if (domainClass != null) {
+            String className = domainClass.getSimpleName();
+            String collectionName = className.replace(className.charAt(0), String.valueOf(className.charAt(0)).toLowerCase().toCharArray()[0]);
+            return collectionName;
+        } else {
+            return null;
+        }
+    }
+
+    public static String getCollectionName(String collectionName) {
+        if (StringUtils.isNotEmpty(collectionName)) {
+            String[] arr = collectionName.split(".");
+            if (arr.length > 1) {
+                collectionName = arr[(arr.length - 1)];
+            }
+            collectionName = collectionName.replace(collectionName.charAt(0), String.valueOf(collectionName.charAt(0)).toLowerCase().toCharArray()[0]);
+            return collectionName;
+        } else {
+            return null;
+        }
+    }
+
+    /**
+     * obj对象转 BigDecimal
+     *
+     * @param obj
+     * @return
+     */
+    public static BigDecimal getBigDecimalByObj(Object obj) {
+        BigDecimal count = BigDecimal.ZERO;
+        if (obj != null) {
+            if (obj instanceof Integer) {
+                count = new BigDecimal((Integer) obj);
+            } else if (obj instanceof Decimal128) {
+                Decimal128 countDecimal = (Decimal128) obj;
+                count = countDecimal.bigDecimalValue();
+            } else if (obj instanceof BigDecimal) {
+                count = (BigDecimal) obj;
+            } else if (obj instanceof Long) {
+                count = new BigDecimal((Long) obj);
+            }
+        }
+        return count;
+    }
+
+    /**
+     * BigDecimal 保留四位小数
+     *
+     * @param bigDecimal
+     * @return
+     */
+    public static BigDecimal getBigDecimalScale4(BigDecimal bigDecimal) {
+        if (bigDecimal != null) {
+            String ss = bigDecimal.setScale(4, RoundingMode.HALF_UP).stripTrailingZeros().toPlainString();
+            bigDecimal = new BigDecimal(ss);
+            return bigDecimal;
+        }
+        return BigDecimal.ZERO;
+    }
+
+    /**
+     * 向上取整,如:16.251、16.256 -> 16.25
+     *
+     * @param bigDecimal
+     * @return
+     */
+    public static BigDecimal getBigDecimalScale2(BigDecimal bigDecimal) {
+        if (bigDecimal != null) {
+            String ss = bigDecimal.setScale(2, RoundingMode.HALF_UP).stripTrailingZeros().toPlainString();
+            bigDecimal = new BigDecimal(ss);
+            return bigDecimal;
+        }
+        return BigDecimal.ZERO;
+    }
+
+    public static BigDecimal getBigDecimalScale2Floor(BigDecimal bigDecimal) {
+        if (bigDecimal != null) {
+            String ss = bigDecimal.setScale(2, RoundingMode.FLOOR).stripTrailingZeros().toPlainString();
+            bigDecimal = new BigDecimal(ss);
+            return bigDecimal;
+        }
+        return BigDecimal.ZERO;
+    }
+
+    /**
+     * 不保留小数,, 四舍五入
+     *
+     * @param bigDecimal
+     * @return
+     */
+    public static BigDecimal getBigDecimalScale0(BigDecimal bigDecimal) {
+        if (bigDecimal != null) {
+            String ss = bigDecimal.setScale(0, RoundingMode.HALF_UP).stripTrailingZeros().toPlainString();
+            bigDecimal = new BigDecimal(ss);
+            return bigDecimal;
+        }
+        return BigDecimal.ZERO;
+    }
+
+    /**
+     * 不要小数,,而且 向下取数 如:16.2455、16.874 -> 16
+     *
+     * @param bigDecimal
+     * @return
+     */
+    public static BigDecimal getBigDecimalScale0Floor(BigDecimal bigDecimal) {
+        if (bigDecimal != null) {
+            String ss = bigDecimal.setScale(0, RoundingMode.FLOOR).stripTrailingZeros().toPlainString();
+            bigDecimal = new BigDecimal(ss);
+            return bigDecimal;
+        }
+        return BigDecimal.ZERO;
+    }
+
+
+    public static Map<String, Object> filterData(Collection<Map<String, Object>> datas, List<String> props) {
+        Map<String, Object> useDataMap = new HashMap<>(props.size());
+        datas.forEach(actDataMap -> {
+            for (String prop : props) {
+                if (actDataMap.containsKey(prop)) {
+                    useDataMap.put(prop, actDataMap.get(prop));
+                }
+            }
+        });
+        return useDataMap;
+    }
+
+    /**
+     * BigDecimal 是否含有小数,如:12.202 true  12.0000 false
+     *
+     * @param number
+     * @return
+     */
+    public static boolean bigDecimalHasDec(BigDecimal number) {
+        boolean b = false;
+        if (number != null) {
+            BigDecimal number1 = BigDecimal.valueOf(number.intValue());
+            if (number1.compareTo(number) != 0) {
+                b = true;
+            }
+        }
+        return b;
+    }
+
+    /**
+     * 判断 BigDecimal 是否是最小值
+     *
+     * @param number
+     * @return
+     */
+    public static boolean bigDecimalIsSmall(BigDecimal number) {
+        if (number.compareTo(BigDecimal.valueOf(0.02)) <= 0) {
+            return true;
+        }
+        return false;
+    }
+
+    public static boolean treeIdIsTop(String id) {
+        if (StringUtils.isEmpty(id) || id.equals(ITree.ROOT_ID)) {
+            return true;
+        }
+        return false;
+    }
+
+    /**
+     * 小时转为分钟,,保留整数 (最小 1 分钟)
+     *
+     * @param hours 1.5
+     * @return 90
+     */
+    public static int trun2Mins(BigDecimal hours) {
+        int mins = 0;
+        if (hours != null) {
+            BigDecimal number = getBigDecimalScale0(hours.multiply(BigDecimal.valueOf(60)));
+            mins = number.intValue();
+            if (mins <= 0) {
+                mins = 1;
+            }
+        }
+        return mins;
+    }
+
+
 }

+ 3 - 3
src/main/java/com/zswl/dataservicestarter/utils/bean/EntityObjectUtil.java

@@ -1,7 +1,7 @@
 package com.zswl.dataservicestarter.utils.bean;
 
 
-import com.zswl.dataservicestarter.domain.base.SuperEntity;
+import com.zswl.dataservicestarter.domain.base.DataServiceSuperEntity;
 import org.springframework.data.mongodb.core.query.Criteria;
 import org.springframework.data.mongodb.core.query.Update;
 
@@ -17,7 +17,7 @@ public class EntityObjectUtil {
      *
      * @param superEntity
      */
-    public static void preInsert(SuperEntity superEntity) {
+    public static void preInsert(DataServiceSuperEntity superEntity) {
         superEntity.setId(null);
         superEntity.setCreateTime(getTime());
         superEntity.setUpdateTime(getTime());
@@ -29,7 +29,7 @@ public class EntityObjectUtil {
      * @param superEntity
      * @return
      */
-    public static void preUpdate(SuperEntity superEntity) {
+    public static void preUpdate(DataServiceSuperEntity superEntity) {
         superEntity.setUpdateTime(getTime());
     }