zoujiajian преди 2 години
родител
ревизия
0c8c2a49cb
променени са 23 файла, в които са добавени 993 реда и са изтрити 0 реда
  1. 13 0
      netflix-dao/src/main/java/com/cyksj/mapper/rent/RentGoodsDonMapper.java
  2. 13 0
      netflix-dao/src/main/java/com/cyksj/mapper/rent/RentGoodsDonSkuMapper.java
  3. 13 0
      netflix-dao/src/main/java/com/cyksj/mapper/rent/RentGoodsDonSpecMapper.java
  4. 13 0
      netflix-dao/src/main/java/com/cyksj/mapper/rent/RentOrderDonMapper.java
  5. 35 0
      netflix-dao/src/main/java/com/cyksj/model/entity/RentGoodsDon.java
  6. 38 0
      netflix-dao/src/main/java/com/cyksj/model/entity/RentGoodsDonSku.java
  7. 24 0
      netflix-dao/src/main/java/com/cyksj/model/entity/RentGoodsDonSpec.java
  8. 107 0
      netflix-dao/src/main/java/com/cyksj/model/entity/RentOrderDon.java
  9. 9 0
      netflix-dao/src/main/java/com/cyksj/model/manage/request/ReqGoodsSkuSpec.java
  10. 28 0
      netflix-dao/src/main/java/com/cyksj/model/manage/request/rent/ReqRentGoodsSkuInert.java
  11. 48 0
      netflix-dao/src/main/java/com/cyksj/model/manage/request/rent/ReqRentGoodsSkuSpec.java
  12. 1 0
      netflix-service/src/main/java/com/cyksj/redis/RedisService.java
  13. 14 0
      netflix-service/src/main/java/com/cyksj/service/mange/RefreshCacheService.java
  14. 32 0
      netflix-service/src/main/java/com/cyksj/service/mange/impl/RefreshCacheServiceImpl.java
  15. 13 0
      netflix-service/src/main/java/com/cyksj/service/rent/CmsRentGoodsDonService.java
  16. 13 0
      netflix-service/src/main/java/com/cyksj/service/rent/CmsRentGoodsDonSkuService.java
  17. 22 0
      netflix-service/src/main/java/com/cyksj/service/rent/CmsRentGoodsDonSpecService.java
  18. 19 0
      netflix-service/src/main/java/com/cyksj/service/rent/impl/CmsRentGoodsDonServiceImpl.java
  19. 15 0
      netflix-service/src/main/java/com/cyksj/service/rent/impl/CmsRentGoodsDonSkuServiceImpl.java
  20. 228 0
      netflix-service/src/main/java/com/cyksj/service/rent/impl/CmsRentGoodsDonSpecServiceImpl.java
  21. 110 0
      netflix-web/src/main/java/com/cyksj/web/controller/manage/rent/RentGoodsDonController.java
  22. 165 0
      netflix-web/src/main/java/com/cyksj/web/controller/manage/rent/RentGoodsDonSkuMapper.java
  23. 20 0
      netflix-web/src/main/java/com/cyksj/web/controller/payment/RentOrderController.java

+ 13 - 0
netflix-dao/src/main/java/com/cyksj/mapper/rent/RentGoodsDonMapper.java

@@ -0,0 +1,13 @@
+package com.cyksj.mapper.rent;
+
+import com.baomidou.mybatisplus.core.mapper.BaseMapper;
+import com.cyksj.model.entity.RentGoodsDon;
+
+/**
+ * 项目名: yhlxj2
+ * 文件名: RentGoodsDonMapper
+ * 创建者: JavaZou
+ * 创建时间:2024/2/22 16:00
+ */
+public interface RentGoodsDonMapper extends BaseMapper<RentGoodsDon> {
+}

+ 13 - 0
netflix-dao/src/main/java/com/cyksj/mapper/rent/RentGoodsDonSkuMapper.java

@@ -0,0 +1,13 @@
+package com.cyksj.mapper.rent;
+
+import com.baomidou.mybatisplus.core.mapper.BaseMapper;
+import com.cyksj.model.entity.RentGoodsDonSku;
+
+/**
+ * 项目名: yhlxj2
+ * 文件名: RentGoodsDonSkuMapper
+ * 创建者: JavaZou
+ * 创建时间:2024/2/22 16:01
+ */
+public interface RentGoodsDonSkuMapper extends BaseMapper<RentGoodsDonSku> {
+}

+ 13 - 0
netflix-dao/src/main/java/com/cyksj/mapper/rent/RentGoodsDonSpecMapper.java

@@ -0,0 +1,13 @@
+package com.cyksj.mapper.rent;
+
+import com.baomidou.mybatisplus.core.mapper.BaseMapper;
+import com.cyksj.model.entity.RentGoodsDonSpec;
+
+/**
+ * 项目名: yhlxj2
+ * 文件名: RentGoodsDonSpecMapper
+ * 创建者: JavaZou
+ * 创建时间:2024/2/22 16:01
+ */
+public interface RentGoodsDonSpecMapper extends BaseMapper<RentGoodsDonSpec> {
+}

+ 13 - 0
netflix-dao/src/main/java/com/cyksj/mapper/rent/RentOrderDonMapper.java

@@ -0,0 +1,13 @@
+package com.cyksj.mapper.rent;
+
+import com.baomidou.mybatisplus.core.mapper.BaseMapper;
+import com.cyksj.model.entity.RentOrderDon;
+
+/**
+ * 项目名: yhlxj2
+ * 文件名: RentOrderDonMapper
+ * 创建者: JavaZou
+ * 创建时间:2024/2/22 16:01
+ */
+public interface RentOrderDonMapper extends BaseMapper<RentOrderDon> {
+}

+ 35 - 0
netflix-dao/src/main/java/com/cyksj/model/entity/RentGoodsDon.java

@@ -0,0 +1,35 @@
+package com.cyksj.model.entity;
+
+import lombok.Getter;
+import lombok.Setter;
+
+import javax.validation.constraints.NotEmpty;
+
+/**
+ * 项目名: yhlxj2
+ * 文件名: RentGoodsDon
+ * 创建者: JavaZou
+ * 创建时间:2024/2/22 15:47
+ */
+@Getter
+@Setter
+public class RentGoodsDon extends BaseEntity{
+	@NotEmpty(message = "平台名称不为空")
+	private String title;
+
+	private String banner;
+
+	/**
+	 * 背景图
+	 */
+	private String img;
+
+	/**
+	 * 租赁说明
+	 */
+	private String detail;
+
+	private Boolean status;
+
+	private Boolean deleted;
+}

+ 38 - 0
netflix-dao/src/main/java/com/cyksj/model/entity/RentGoodsDonSku.java

@@ -0,0 +1,38 @@
+package com.cyksj.model.entity;
+
+import lombok.Getter;
+import lombok.Setter;
+
+import java.math.BigDecimal;
+
+/**
+ * 项目名: yhlxj2
+ * 文件名: RentGoodsDonSku
+ * 创建者: JavaZou
+ * 创建时间:2024/2/22 15:50
+ */
+@Getter
+@Setter
+public class RentGoodsDonSku extends BaseEntity{
+	private String subTitle;
+
+	private Long goodsId;
+
+	private String specIds;
+
+	private String specVal;
+
+	private String specJson;
+
+	/**
+	 * 天数
+	 */
+	private Integer days;
+
+	/**
+	 * 价格
+	 */
+	private BigDecimal price;
+
+	private Boolean status;
+}

+ 24 - 0
netflix-dao/src/main/java/com/cyksj/model/entity/RentGoodsDonSpec.java

@@ -0,0 +1,24 @@
+package com.cyksj.model.entity;
+
+import lombok.Getter;
+import lombok.Setter;
+
+/**
+ * 项目名: yhlxj2
+ * 文件名: RentGoodsDonSpec
+ * 创建者: JavaZou
+ * 创建时间:2024/2/22 15:53
+ */
+@Getter
+@Setter
+public class RentGoodsDonSpec extends BaseEntity{
+	private Long goodsId;
+
+	private String specsJson;
+
+	private Integer maxId;
+
+	private Integer specNumber;
+
+	private String specMapping;
+}

+ 107 - 0
netflix-dao/src/main/java/com/cyksj/model/entity/RentOrderDon.java

@@ -0,0 +1,107 @@
+package com.cyksj.model.entity;
+
+import lombok.AllArgsConstructor;
+import lombok.Getter;
+import lombok.Setter;
+
+import java.math.BigDecimal;
+import java.util.Arrays;
+import java.util.Date;
+
+/**
+ * 项目名: yhlxj2
+ * 文件名: RentOrderDon
+ * 创建者: JavaZou
+ * 创建时间:2024/2/22 15:54
+ */
+@Getter
+@Setter
+public class RentOrderDon extends BaseEntity{
+	private String openId;
+
+	private Long goodsId;
+
+	private Long skuId;
+
+	private Long userId;
+
+	private String orderNo;
+
+	private String transactionId;
+
+	/**
+	 * 付款金额
+	 */
+	private BigDecimal money;
+
+	/**
+	 * 押金
+	 */
+	private BigDecimal deposit;
+
+	/**
+	 * 付款规格
+	 */
+	private String payTitle;
+
+	/**
+	 * 退款金额
+	 */
+	private BigDecimal refundMoney;
+
+	private String refundDesc;
+
+	private Status status;
+
+	private Type type;
+
+	/**
+	 * 租赁开始时间
+	 */
+	private Date startTime;
+
+	/**
+	 * 租赁结束时间
+	 */
+	private Date endTime;
+
+	public enum Status {
+		/**
+		 * 订单状态
+		 */
+		close("已关闭"),
+		noPayment("待付款"),
+		hasPayment("已付款"),
+		transport("已发货"),
+		received("已签收"),
+		complete("已完成"),
+		refund("已退款"),
+		;
+
+		private String desc;
+
+		Status(String desc) {
+			this.desc = desc;
+		}
+
+		public String getDesc() {
+			return desc;
+		}
+	}
+
+	@Getter
+	@AllArgsConstructor
+	public enum Type{
+		WeChat("wechat","微信"),
+		ALI_PAY("zfb","支付宝"),
+		PAYPAL("paypal","paypal支付"),
+		STRIPE("stripe","stripe支付")
+		;
+		String type;
+		String desc;
+
+		public static RentOrderDon.Type getType(String type) {
+			return Arrays.stream(RentOrderDon.Type.values()).filter(tp -> tp.getType().equals(type)).findFirst().orElse(ALI_PAY);
+		}
+	}
+}

+ 9 - 0
netflix-dao/src/main/java/com/cyksj/model/manage/request/ReqGoodsSkuSpec.java

@@ -24,6 +24,15 @@ public class ReqGoodsSkuSpec {
 
         private String value;
 
+        /**
+         * 租赁价格
+         */
+        private BigDecimal deposit;
+
+        private Boolean hide;
+
+        private String logo;
+
         private BigDecimal price;
 
         /**

+ 28 - 0
netflix-dao/src/main/java/com/cyksj/model/manage/request/rent/ReqRentGoodsSkuInert.java

@@ -0,0 +1,28 @@
+package com.cyksj.model.manage.request.rent;
+
+import com.cyksj.model.entity.RentGoodsDonSku;
+import com.cyksj.model.manage.request.ReqGoodsSkuSpec;
+import lombok.Getter;
+import lombok.Setter;
+
+import javax.validation.constraints.NotNull;
+import java.util.List;
+
+/**
+ * 项目名: yhlxj2
+ * 文件名: ReqRentGoodsSkuInert
+ * 创建者: JavaZou
+ * 创建时间:2024/2/22 16:17
+ */
+@Getter
+@Setter
+public class ReqRentGoodsSkuInert {
+	private Long id;
+
+	@NotNull(message = "请指定商品spu.")
+	private Long goodsId;
+
+	private List<ReqGoodsSkuSpec> specs;
+
+	private List<RentGoodsDonSku> skus;
+}

+ 48 - 0
netflix-dao/src/main/java/com/cyksj/model/manage/request/rent/ReqRentGoodsSkuSpec.java

@@ -0,0 +1,48 @@
+package com.cyksj.model.manage.request.rent;
+
+import lombok.Getter;
+import lombok.Setter;
+
+import java.math.BigDecimal;
+import java.util.List;
+
+/**
+ * 项目名: yhlxj2
+ * 文件名: ReqRentGoodsSkuSpec
+ * 创建者: JavaZou
+ * 创建时间:2024/2/22 16:18
+ */
+@Getter
+@Setter
+public class ReqRentGoodsSkuSpec {
+
+	private String key;
+
+	private List<ReqRentGoodsSkuSpec.Node> values;
+
+	@Getter
+	@Setter
+	public static class Node {
+		private Integer id;
+
+		private String value;
+
+		private Boolean hide;
+
+		private String logo;
+
+		private BigDecimal price;
+
+		/**
+		 * 预览图
+		 */
+		private String previewImgs;
+
+		private String benefitsList;
+
+		/**
+		 * 原价
+		 */
+		private BigDecimal benefitsPrice;
+	}
+}

+ 1 - 0
netflix-service/src/main/java/com/cyksj/redis/RedisService.java

@@ -669,6 +669,7 @@ public class RedisService {
         DOUBLE_VERIFY_CODE_VIEW_MINUTES_KEY("double_verify_code_view_minutes_key","双重验证码查看同时间段人数限制",60),
 
         WX_INDENT_BIND_KEY("wx_indent_bind:key:", "微信身份授权绑定key", 60 * 60 * 24),
+        RENT_GOODS_PAGHE_CACHE("rent_goods_paghe_cache:", "租赁商品缓存", 30 * 60),
         ;
 
         private String name;

+ 14 - 0
netflix-service/src/main/java/com/cyksj/service/mange/RefreshCacheService.java

@@ -0,0 +1,14 @@
+package com.cyksj.service.mange;
+
+/**
+ * 项目名: yhlxj2
+ * 文件名: RefreshCacheService
+ * 创建者: JavaZou
+ * 创建时间:2024/2/22 16:28
+ */
+public interface RefreshCacheService {
+
+	void refreshYhHomePageCache();
+
+	void refreshRentGoodsPageCache();
+}

+ 32 - 0
netflix-service/src/main/java/com/cyksj/service/mange/impl/RefreshCacheServiceImpl.java

@@ -0,0 +1,32 @@
+package com.cyksj.service.mange.impl;
+
+import com.cyksj.redis.RedisService;
+import com.cyksj.service.mange.RefreshCacheService;
+import lombok.RequiredArgsConstructor;
+import org.springframework.stereotype.Service;
+
+import java.util.Set;
+
+/**
+ * 项目名: yhlxj2
+ * 文件名: RefreshCacheServiceImpl
+ * 创建者: JavaZou
+ * 创建时间:2024/2/22 16:28
+ */
+@Service
+@RequiredArgsConstructor
+public class RefreshCacheServiceImpl implements RefreshCacheService {
+	private final RedisService redisService;
+
+	@Override
+	public void refreshYhHomePageCache() {
+		Set<String> keys = redisService.keys(RedisService.key.YH_HOME_PAGHE_CACHE.getEnvName() + "*");
+		redisService.del(keys.toArray(String[]::new));
+	}
+
+	@Override
+	public void refreshRentGoodsPageCache() {
+		Set<String> keys = redisService.keys(RedisService.key.RENT_GOODS_PAGHE_CACHE.getEnvName() + "*");
+		redisService.del(keys.toArray(String[]::new));
+	}
+}

+ 13 - 0
netflix-service/src/main/java/com/cyksj/service/rent/CmsRentGoodsDonService.java

@@ -0,0 +1,13 @@
+package com.cyksj.service.rent;
+
+import com.baomidou.mybatisplus.extension.service.IService;
+import com.cyksj.model.entity.RentGoodsDon;
+
+/**
+ * 项目名: yhlxj2
+ * 文件名: CmsRentGoodsDonService
+ * 创建者: JavaZou
+ * 创建时间:2024/2/22 16:11
+ */
+public interface CmsRentGoodsDonService extends IService<RentGoodsDon> {
+}

+ 13 - 0
netflix-service/src/main/java/com/cyksj/service/rent/CmsRentGoodsDonSkuService.java

@@ -0,0 +1,13 @@
+package com.cyksj.service.rent;
+
+import com.baomidou.mybatisplus.extension.service.IService;
+import com.cyksj.model.entity.RentGoodsDonSku;
+
+/**
+ * 项目名: yhlxj2
+ * 文件名: CmsRentGoodsDonSkuService
+ * 创建者: JavaZou
+ * 创建时间:2024/2/22 16:31
+ */
+public interface CmsRentGoodsDonSkuService extends IService<RentGoodsDonSku> {
+}

+ 22 - 0
netflix-service/src/main/java/com/cyksj/service/rent/CmsRentGoodsDonSpecService.java

@@ -0,0 +1,22 @@
+package com.cyksj.service.rent;
+
+import com.baomidou.mybatisplus.extension.service.IService;
+import com.cyksj.model.entity.RentGoodsDon;
+import com.cyksj.model.entity.RentGoodsDonSpec;
+import com.cyksj.model.manage.request.ReqGoodsSkuInsert;
+import com.cyksj.model.manage.request.rent.ReqRentGoodsSkuInert;
+
+/**
+ * 项目名: yhlxj2
+ * 文件名: CmsRentGoodsDonSpecService
+ * 创建者: JavaZou
+ * 创建时间:2024/2/22 16:24
+ */
+public interface CmsRentGoodsDonSpecService extends IService<RentGoodsDonSpec> {
+	/**
+	 * 新增或编辑规格spec
+	 */
+	void insertOrUpdateSkuSpec(ReqRentGoodsSkuInert insert, Boolean isUpdate) throws Exception;
+
+	void skuAppend(ReqGoodsSkuInsert insert, RentGoodsDon goods) throws Exception;
+}

+ 19 - 0
netflix-service/src/main/java/com/cyksj/service/rent/impl/CmsRentGoodsDonServiceImpl.java

@@ -0,0 +1,19 @@
+package com.cyksj.service.rent.impl;
+
+import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
+import com.cyksj.mapper.rent.RentGoodsDonMapper;
+import com.cyksj.model.entity.RentGoodsDon;
+import com.cyksj.service.rent.CmsRentGoodsDonService;
+import lombok.RequiredArgsConstructor;
+import org.springframework.stereotype.Service;
+
+/**
+ * 项目名: yhlxj2
+ * 文件名: CmsRentGoodsDonServiceImpl
+ * 创建者: JavaZou
+ * 创建时间:2024/2/22 16:11
+ */
+@Service
+@RequiredArgsConstructor
+public class CmsRentGoodsDonServiceImpl extends ServiceImpl<RentGoodsDonMapper, RentGoodsDon> implements CmsRentGoodsDonService {
+}

+ 15 - 0
netflix-service/src/main/java/com/cyksj/service/rent/impl/CmsRentGoodsDonSkuServiceImpl.java

@@ -0,0 +1,15 @@
+package com.cyksj.service.rent.impl;
+
+import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
+import com.cyksj.mapper.rent.RentGoodsDonSkuMapper;
+import com.cyksj.model.entity.RentGoodsDonSku;
+import com.cyksj.service.rent.CmsRentGoodsDonSkuService;
+
+/**
+ * 项目名: yhlxj2
+ * 文件名: CmsRentGoodsDonSkuServiceImpl
+ * 创建者: JavaZou
+ * 创建时间:2024/2/22 16:31
+ */
+public class CmsRentGoodsDonSkuServiceImpl extends ServiceImpl<RentGoodsDonSkuMapper, RentGoodsDonSku> implements CmsRentGoodsDonSkuService {
+}

+ 228 - 0
netflix-service/src/main/java/com/cyksj/service/rent/impl/CmsRentGoodsDonSpecServiceImpl.java

@@ -0,0 +1,228 @@
+package com.cyksj.service.rent.impl;
+
+import cn.hutool.core.bean.BeanUtil;
+import com.baomidou.mybatisplus.core.toolkit.Wrappers;
+import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
+import com.cyksj.common.exception.BusinessRuntimeException;
+import com.cyksj.common.util.Jsons;
+import com.cyksj.mapper.rent.RentGoodsDonMapper;
+import com.cyksj.mapper.rent.RentGoodsDonSkuMapper;
+import com.cyksj.mapper.rent.RentGoodsDonSpecMapper;
+import com.cyksj.model.entity.RentGoodsDon;
+import com.cyksj.model.entity.RentGoodsDonSku;
+import com.cyksj.model.entity.RentGoodsDonSpec;
+import com.cyksj.model.manage.request.ReqGoodsSkuInsert;
+import com.cyksj.model.manage.request.ReqGoodsSkuSpec;
+import com.cyksj.model.manage.request.ReqGoodsSpecSingle;
+import com.cyksj.model.manage.request.rent.ReqRentGoodsSkuInert;
+import com.cyksj.service.rent.CmsRentGoodsDonSpecService;
+import com.fasterxml.jackson.databind.JavaType;
+import lombok.RequiredArgsConstructor;
+import lombok.extern.slf4j.Slf4j;
+import org.apache.commons.lang3.StringUtils;
+import org.springframework.stereotype.Service;
+import org.springframework.transaction.annotation.Transactional;
+
+import java.math.BigDecimal;
+import java.util.*;
+import java.util.stream.Collectors;
+
+/**
+ * 项目名: yhlxj2
+ * 文件名: CmsRentGoodsDonSpecServiceImpl
+ * 创建者: JavaZou
+ * 创建时间:2024/2/22 16:24
+ */
+@Service
+@RequiredArgsConstructor
+@Slf4j
+public class CmsRentGoodsDonSpecServiceImpl extends ServiceImpl<RentGoodsDonSpecMapper, RentGoodsDonSpec> implements CmsRentGoodsDonSpecService {
+	private final RentGoodsDonMapper goodsDonMapper;
+
+	private final RentGoodsDonSkuMapper goodsDonSkuMapper;
+
+	@Override
+	@Transactional(rollbackFor = Throwable.class)
+	public void insertOrUpdateSkuSpec(ReqRentGoodsSkuInert insert, Boolean isUpdate) throws Exception {
+		RentGoodsDon goods = goodsDonMapper.selectById(insert.getGoodsId());
+		if (null == goods) {
+			throw new RuntimeException("找不到商品spu.");
+		}
+		RentGoodsDonSpec loveSpec = this.getOne(Wrappers.lambdaQuery(RentGoodsDonSpec.class).eq(RentGoodsDonSpec::getGoodsId, insert.getGoodsId()));
+		Map<String, List<ReqGoodsSkuSpec>> dbSpecMap = null;
+		if (null != loveSpec) {
+			insert.setId(loveSpec.getId());
+			String specsJson = loveSpec.getSpecsJson();
+			dbSpecMap = Jsons.parseList(specsJson, ReqGoodsSkuSpec.class).stream().collect(Collectors.groupingBy(ReqGoodsSkuSpec::getKey));
+		}
+		if (isUpdate && loveSpec == null) {
+			throw BusinessRuntimeException.getInstance("所更新的平台id:{0}属性不存在", insert.getGoodsId());
+		}
+
+		List<ReqGoodsSkuSpec> specs = insert.getSpecs();
+		if (null == specs || specs.isEmpty()) {
+			throw new RuntimeException("缺少商品总规格.");
+		}
+
+		// 属性最大id
+		Integer maxId = 0;
+		// 统计总属性数
+		Integer total = 0;
+		// 判断id是否有重复
+		Map<Integer, ReqGoodsSpecSingle> map = null;
+		// 规格数量
+		int specNumber = specs.size();
+		for (ReqGoodsSkuSpec spec : specs) {
+			if (StringUtils.isBlank(spec.getKey())) {
+				throw new RuntimeException("存在空白规格名.");
+			}
+
+			List<ReqGoodsSkuSpec.Node> values = spec.getValues();
+			if (null == values || values.isEmpty()) {
+				throw new RuntimeException("规格[" + spec.getKey() + "]中缺少属性.");
+			}
+			total += values.size();
+			for (ReqGoodsSkuSpec.Node e : values) {
+				if (null == e.getId() || e.getId() < 0) {
+					e.setId(maxId + 1);
+				}
+				if (StringUtils.isBlank(e.getValue())) {
+					throw new RuntimeException("规格[" + spec.getKey() + "]中存在空白属性.");
+				}
+				if (e.getId() > maxId) {
+					maxId = e.getId();
+				}
+				//新增时 实物价格要填入
+				if (insert.getId() == null && (e.getDeposit() == null || e.getDeposit().compareTo(BigDecimal.ZERO) < 0)) {
+					throw BusinessRuntimeException.getInstance("实物规格:{0}对应抵押价格请输入", e.getValue());
+				}
+
+				if (null == map) {
+					map = new HashMap<>(16);
+				}
+
+				ReqGoodsSpecSingle single = new ReqGoodsSpecSingle();
+				single.setId(e.getId());
+				single.setKey(spec.getKey());
+				single.setName(e.getValue());
+				map.put(e.getId(), single);
+			}
+		}
+
+		if (map.size() != total) {
+			throw new RuntimeException("规格中存在重复id.");
+		}
+
+		RentGoodsDonSpec spec = new RentGoodsDonSpec();
+		spec.setId(insert.getId());
+		spec.setGoodsId(insert.getGoodsId());
+		spec.setMaxId(maxId);
+		spec.setSpecsJson(Jsons.toJson(specs));
+		spec.setSpecNumber(specNumber);
+		spec.setSpecMapping(Jsons.toJson(map));
+		if (insert.getId() != null) {
+			this.updateById(spec);
+			return;
+		}
+		this.save(spec);
+	}
+
+	@Override
+	public void skuAppend(ReqGoodsSkuInsert insert, RentGoodsDon goods) throws Exception {
+
+		RentGoodsDonSpec loveSpec = this.getOne(Wrappers.lambdaQuery(RentGoodsDonSpec.class).eq(RentGoodsDonSpec::getGoodsId, insert.getGoodsId()));
+		if (null == loveSpec) {
+			throw new RuntimeException("该商品未设置总规格, 请设置总规格.");
+		}
+
+		List<ReqGoodsSkuInsert.Sku> skus = insert.getSkus();
+		if (null == skus || skus.isEmpty()) {
+			throw new RuntimeException("参数错误.");
+		}
+		int specNumber = loveSpec.getSpecNumber();
+
+		JavaType type = Jsons.javaType().constructMapType(HashMap.class, Integer.class, ReqGoodsSpecSingle.class);
+		Map<Integer, ReqGoodsSpecSingle> map = Jsons.parseObject(loveSpec.getSpecMapping(), type);
+
+		StringBuilder builder = new StringBuilder();
+		List<ReqGoodsSpecSingle> specList = null;
+		RentGoodsDonSku goodsDonSku = null;
+
+		// 判断属性是否属于同一个key
+		Set<String> set = null;
+
+		for (ReqGoodsSkuInsert.Sku sku : insert.getSkus()) {
+			// 跳过空值的sku
+			// 解析sku的规格属性
+			final String specIds = sku.getSpecIds();
+			if (StringUtils.isBlank(specIds)) {
+				throw new RuntimeException("请选择商品的规格.");
+			}
+			int[] ids = Jsons.parseObject(specIds, int[].class);
+//            if (ids.length != specNumber) {
+//                throw new RuntimeException("sku规格数量 与 总规格数量 不一致.");
+//            }
+
+			// init
+			builder.delete(0, builder.length());
+			if (null == specList) {
+				specList = new ArrayList<>(specNumber);
+			} else {
+				specList.clear();
+			}
+			if (null == set) {
+				int capacity = (specNumber + 1) * 4 / 3 + 1;
+				set = new HashSet<>(capacity);
+			} else {
+				set.clear();
+			}
+
+			for (int id : ids) {
+				ReqGoodsSpecSingle single = map.get(id);
+				if (null == single) {
+					throw new RuntimeException("总规格属性id中 不存在 sku中的id.");
+				}
+				builder.append(single.getName()).append(';');
+				specList.add(single);
+				set.add(single.getKey());
+			}
+//            if (set.size() != specNumber) {
+//                throw new RuntimeException("sku中存在多个属性属于同一个规格.");
+//            }
+
+			String specVal = builder.toString();
+			String specJson = Jsons.toJson(specList);
+
+			if (null == goodsDonSku) {
+				goodsDonSku = new RentGoodsDonSku();
+				goodsDonSku.setGoodsId(insert.getGoodsId());
+			}
+			BeanUtil.copyProperties(sku, goodsDonSku);
+			String specIdsStr = Jsons.toJson(ids);
+			//升序
+			Arrays.sort(ids);
+			String dupSpecIds = Jsons.toJson(ids);
+			//是否存在相同规格
+			RentGoodsDonSku specIds_exists = goodsDonSkuMapper.selectOne(Wrappers.lambdaQuery(RentGoodsDonSku.class)
+					.eq(RentGoodsDonSku::getSpecIds, specIdsStr)
+					.eq(RentGoodsDonSku::getGoodsId, goods.getId())
+					.last("limit 1"));
+			if (specIds_exists != null) {
+				log.info("库中存在相同二级分类的规格,spec_ids:{}", dupSpecIds);
+				continue;
+			}
+			goodsDonSku.setSpecIds(specIdsStr);
+			goodsDonSku.setSpecVal(specVal);
+			goodsDonSku.setSpecJson(specJson);
+
+			if (sku.getDays() == null || sku.getDays() < 0) {
+				throw BusinessRuntimeException.getInstance("请输入正确的租赁天数");
+			}
+			if (sku.getPrice() == null || sku.getPrice().compareTo(BigDecimal.ZERO) < 0) {
+				throw BusinessRuntimeException.getInstance("请输入正确的价格");
+			}
+			goodsDonSkuMapper.insert(goodsDonSku);
+
+		}
+	}
+}

+ 110 - 0
netflix-web/src/main/java/com/cyksj/web/controller/manage/rent/RentGoodsDonController.java

@@ -0,0 +1,110 @@
+package com.cyksj.web.controller.manage.rent;
+
+import com.cyksj.common.exception.BusinessRuntimeException;
+import com.cyksj.dto.Result;
+import com.cyksj.enums.GatewayResponse;
+import com.cyksj.model.entity.RentGoodsDon;
+import com.cyksj.model.entity.RentGoodsDonSku;
+import com.cyksj.model.views.GoodsDonCategoryDetailView;
+import com.cyksj.service.mange.RefreshCacheService;
+import com.cyksj.service.rent.CmsRentGoodsDonService;
+import com.ejlchina.searcher.BeanSearcher;
+import com.ejlchina.searcher.SearchResult;
+import com.ejlchina.searcher.util.MapUtils;
+import lombok.RequiredArgsConstructor;
+import lombok.extern.slf4j.Slf4j;
+import org.springframework.validation.annotation.Validated;
+import org.springframework.web.bind.annotation.*;
+
+import javax.servlet.http.HttpServletRequest;
+import java.util.List;
+
+/**
+ * 项目名: yhlxj2
+ * 文件名: RentGoodsDonController
+ * 创建者: JavaZou
+ * 创建时间:2024/2/22 16:02
+ */
+@Slf4j
+@RequiredArgsConstructor
+@RestController
+@RequestMapping("/manage/rent/goods")
+public class RentGoodsDonController {
+
+	private final HttpServletRequest request;
+
+	private final BeanSearcher beanSearcher;
+
+	private final CmsRentGoodsDonService goodsDonService;
+
+	private final RefreshCacheService refreshCacheService;
+
+	@GetMapping("/get")
+	public Result<SearchResult<RentGoodsDon>> get() {
+		SearchResult<RentGoodsDon> search = beanSearcher.search(RentGoodsDon.class, MapUtils.flatBuilder(request.getParameterMap()).field(GoodsDonCategoryDetailView::getDeleted, true).build());
+		return GatewayResponse.SUCCESS.newBuilder().toResult(search);
+	}
+
+	/**
+	 * 商品详情
+	 */
+	@GetMapping("/get/{id}")
+	public Result<RentGoodsDon> getById(@PathVariable Long id) {
+		RentGoodsDon goodsDonViewer = beanSearcher.searchFirst(RentGoodsDon.class, MapUtils.builder().field(RentGoodsDon::getId, id).build());
+		return GatewayResponse.SUCCESS.newBuilder().toResult(goodsDonViewer);
+	}
+
+	/**
+	 * 商品规格详情
+	 */
+	@GetMapping("/get/sku/{id}")
+	public Result<List<RentGoodsDonSku>> getSkuById(@PathVariable Long id, HttpServletRequest request) {
+		List<RentGoodsDonSku> goodsDonSkus = beanSearcher.searchAll(RentGoodsDonSku.class, MapUtils.flatBuilder(request.getParameterMap()).field(RentGoodsDonSku::getGoodsId, id).build());
+		return GatewayResponse.SUCCESS.newBuilder().toResult(goodsDonSkus);
+	}
+
+	/**
+	 * 新增 商品spu
+	 */
+	@PostMapping(value = "/post")
+	public Result<Long> spuInsert(@Validated @RequestBody RentGoodsDon goods) {
+		goodsDonService.save(goods);
+		refreshCacheService.refreshRentGoodsPageCache();
+		return GatewayResponse.SUCCESS.newBuilder().toResult(goods.getId());
+	}
+
+	/**
+	 * 修改 商品spu
+	 */
+	@PutMapping(value = "/update")
+	public Result<String> spuUpdate(@Validated @RequestBody RentGoodsDon goods) {
+		goodsDonService.updateById(goods);
+		refreshCacheService.refreshRentGoodsPageCache();
+		return GatewayResponse.SUCCESS.newBuilder().toResult();
+	}
+
+
+	@PutMapping("/put/status/{id}")
+	public Result<Boolean> updateStatus(@PathVariable Long id) {
+		RentGoodsDon goods = goodsDonService.getById(id);
+		if (goods == null) {
+			throw BusinessRuntimeException.getInstance("平台不存在");
+		}
+		goods.setStatus(!goods.getStatus());
+		goodsDonService.updateById(goods);
+		refreshCacheService.refreshRentGoodsPageCache();
+		return GatewayResponse.SUCCESS.newBuilder().toResult(goods.getStatus());
+	}
+
+	@DeleteMapping("/delete/{id}")
+	public Result<Long> deleteById(@PathVariable Long id) {
+		RentGoodsDon goods = goodsDonService.getById(id);
+		if (goods == null) {
+			throw BusinessRuntimeException.getInstance("平台不存在");
+		}
+		goods.setDeleted(false);
+		goodsDonService.updateById(goods);
+		refreshCacheService.refreshRentGoodsPageCache();
+		return GatewayResponse.SUCCESS.newBuilder().toResult(id);
+	}
+}

+ 165 - 0
netflix-web/src/main/java/com/cyksj/web/controller/manage/rent/RentGoodsDonSkuMapper.java

@@ -0,0 +1,165 @@
+package com.cyksj.web.controller.manage.rent;
+
+import cn.hutool.core.util.StrUtil;
+import com.baomidou.mybatisplus.core.toolkit.Wrappers;
+import com.cyksj.common.annotation.Log;
+import com.cyksj.common.exception.BusinessRuntimeException;
+import com.cyksj.common.util.Jsons;
+import com.cyksj.dto.Result;
+import com.cyksj.enums.BusinessType;
+import com.cyksj.enums.GatewayResponse;
+import com.cyksj.model.entity.GoodsDiscountPlusPurchaseRelation;
+import com.cyksj.model.entity.GoodsDonSku;
+import com.cyksj.model.entity.RentGoodsDon;
+import com.cyksj.model.entity.RentGoodsDonSku;
+import com.cyksj.model.manage.request.ReqGoodsSkuInsert;
+import com.cyksj.model.manage.request.rent.ReqRentGoodsSkuInert;
+import com.cyksj.model.views.DistributeSearchView;
+import com.cyksj.service.mange.RefreshCacheService;
+import com.cyksj.service.rent.CmsRentGoodsDonService;
+import com.cyksj.service.rent.CmsRentGoodsDonSkuService;
+import com.cyksj.service.rent.CmsRentGoodsDonSpecService;
+import com.ejlchina.searcher.BeanSearcher;
+import com.ejlchina.searcher.SearchResult;
+import com.ejlchina.searcher.param.Operator;
+import com.ejlchina.searcher.util.MapBuilder;
+import com.ejlchina.searcher.util.MapUtils;
+import lombok.RequiredArgsConstructor;
+import lombok.extern.slf4j.Slf4j;
+import org.springframework.transaction.annotation.Transactional;
+import org.springframework.validation.annotation.Validated;
+import org.springframework.web.bind.annotation.*;
+
+import javax.servlet.http.HttpServletRequest;
+import java.math.BigDecimal;
+import java.util.List;
+
+/**
+ * 项目名: yhlxj2
+ * 文件名: RentGoodsDonSkuMapper
+ * 创建者: JavaZou
+ * 创建时间:2024/2/22 16:15
+ */
+@Slf4j
+@RequiredArgsConstructor
+@RequestMapping("/manage/rent/goods/sku")
+@RestController
+public class RentGoodsDonSkuMapper {
+
+	private final CmsRentGoodsDonService goodsDonService;
+
+	private final CmsRentGoodsDonSpecService goodsDonSpecService;
+
+	private final CmsRentGoodsDonSkuService goodsDonSkuService;
+
+	private final BeanSearcher beanSearcher;
+
+	private final HttpServletRequest request;
+
+	private final RefreshCacheService refreshCacheService;
+
+	/**
+	 * 新增 商品spec & sku
+	 */
+	@PostMapping(value = "/post/spec-sku")
+	@Log(module = "平台管理/新增商品sku&spec", businessType = BusinessType.POST, isSaveRequestData = true)
+	public Result<String> skuInsert(@Validated @RequestBody ReqRentGoodsSkuInert insert) throws Exception {
+		goodsDonSpecService.insertOrUpdateSkuSpec(insert, false);
+		refreshCacheService.refreshRentGoodsPageCache();
+		return GatewayResponse.SUCCESS.newBuilder().toResult();
+	}
+
+	/**
+	 * 更新 spec
+	 */
+	@PutMapping("/update/spec")
+	public Result<String> updateGoodsSpec(@Validated @RequestBody ReqRentGoodsSkuInert insert) throws Exception {
+		goodsDonSpecService.insertOrUpdateSkuSpec(insert, true);
+		refreshCacheService.refreshRentGoodsPageCache();
+		return GatewayResponse.SUCCESS.newBuilder().toResult();
+	}
+
+	/**
+	 * 追加 商品sku
+	 */
+	@Transactional(rollbackFor = Throwable.class)
+	@PostMapping(value = "/post")
+	public Result<String> skuAppend(@Validated @RequestBody ReqGoodsSkuInsert insert) throws Exception {
+		RentGoodsDon goods = goodsDonService.getById(insert.getGoodsId());
+		if (null == goods) {
+			throw new RuntimeException("找不到商品spu.");
+		}
+		goodsDonSpecService.skuAppend(insert, goods);
+		refreshCacheService.refreshRentGoodsPageCache();
+		return GatewayResponse.SUCCESS.newBuilder().toResult();
+	}
+
+	/**
+	 * 修改 sku
+	 */
+	@Transactional(rollbackFor = Throwable.class)
+	@PutMapping(value = "/update")
+	public Result<String> skuUpdate(@RequestBody RentGoodsDonSku sku) throws Exception {
+		if (sku.getDays() == null || sku.getDays() < 0) {
+			throw BusinessRuntimeException.getInstance("请输入正确的租赁天数");
+		}
+		if (sku.getPrice() == null || sku.getPrice().compareTo(BigDecimal.ZERO) < 0) {
+			throw BusinessRuntimeException.getInstance("请输入正确的价格");
+		}
+		goodsDonSkuService.saveOrUpdate(sku);
+		refreshCacheService.refreshRentGoodsPageCache();
+		return GatewayResponse.SUCCESS.newBuilder().toResult();
+	}
+
+
+	/**
+	 * 删除 sku
+	 */
+	@Transactional(rollbackFor = Throwable.class)
+	@DeleteMapping("/delete/{skuId}")
+	@Log(module = "平台管理/删除规格", businessType = BusinessType.DELETE)
+	public Result<String> skuDelete(@PathVariable Long skuId) {
+		goodsDonSkuService.removeById(skuId);
+		refreshCacheService.refreshRentGoodsPageCache();
+		return GatewayResponse.SUCCESS.newBuilder().toResult();
+	}
+
+	/**
+	 * 获取平台规格列表
+	 */
+	@GetMapping("/get/list")
+	public Result<SearchResult<GoodsDonSku>> getGoodsSkuList(@RequestParam(defaultValue = "0") Boolean filterPack) {
+		MapBuilder builder = MapUtils.flatBuilder(request.getParameterMap());
+		if (filterPack) {
+			String condition = " spec_json not like '%套餐%'";
+			builder.put("condition", condition);
+		}
+		SearchResult<GoodsDonSku> skuViewList = beanSearcher.search(GoodsDonSku.class, builder.build());
+		skuViewList.getDataList().forEach(sku -> {
+			if (sku.getIsDp()) {
+				sku.setDpSku(beanSearcher.searchAll(GoodsDiscountPlusPurchaseRelation.class, MapUtils.builder().field(GoodsDiscountPlusPurchaseRelation::getSkuId, sku.getId()).build()));
+			}
+
+			if (StrUtil.isNotEmpty(sku.getUserOwns())) {
+				try {
+					sku.setUserOwnsList(beanSearcher.searchAll(DistributeSearchView.class, MapUtils.builder().field(DistributeSearchView::getUserId, Jsons.parseList(sku.getUserOwns(), Long.class)).op(Operator.InList).build()));
+				} catch (Exception e) {
+				}
+			}
+		});
+		return GatewayResponse.SUCCESS.newBuilder().toResult(skuViewList);
+	}
+
+	/**
+	 * 批量上架
+	 */
+	@PutMapping("/batch/update/status/{goodsId}")
+	public Result<String> batchUpdateStatus(@PathVariable Long goodsId, @RequestBody List<Long> skuIds) {
+		boolean update = goodsDonSkuService.update(null, Wrappers.lambdaUpdate(RentGoodsDonSku.class).set(RentGoodsDonSku::getStatus, true).eq(RentGoodsDonSku::getGoodsId, goodsId).in(RentGoodsDonSku::getId, skuIds).eq(RentGoodsDonSku::getStatus, false));
+		if (update) {
+			refreshCacheService.refreshRentGoodsPageCache();
+		}
+		return GatewayResponse.SUCCESS.newBuilder().toResult();
+	}
+
+}

+ 20 - 0
netflix-web/src/main/java/com/cyksj/web/controller/payment/RentOrderController.java

@@ -0,0 +1,20 @@
+package com.cyksj.web.controller.payment;
+
+import lombok.RequiredArgsConstructor;
+import lombok.extern.slf4j.Slf4j;
+import org.springframework.web.bind.annotation.RequestMapping;
+import org.springframework.web.bind.annotation.RestController;
+
+/**
+ * 项目名: yhlxj2
+ * 文件名: RentOrderController
+ * 创建者: JavaZou
+ * 创建时间:2024/2/22 16:51
+ */
+@Slf4j
+@RequestMapping("/applets/rent/order")
+@RestController
+@RequiredArgsConstructor
+public class RentOrderController {
+
+}