CmsGoodsDonSpecServiceImpl.java 23 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573
  1. package com.cyksj.service.mange.goods;
  2. import cn.hutool.core.bean.BeanUtil;
  3. import cn.hutool.core.collection.CollUtil;
  4. import cn.hutool.core.util.StrUtil;
  5. import com.baomidou.mybatisplus.core.toolkit.Wrappers;
  6. import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
  7. import com.cyksj.common.exception.BusinessRuntimeException;
  8. import com.cyksj.common.util.Jsons;
  9. import com.cyksj.mapper.DistributeGoodsSkuAlertMapper;
  10. import com.cyksj.mapper.GoodsDonMapper;
  11. import com.cyksj.mapper.GoodsDonSkuMapper;
  12. import com.cyksj.mapper.GoodsDonSpecMapper;
  13. import com.cyksj.model.entity.*;
  14. import com.cyksj.model.manage.request.ReqGoodsSkuInsert;
  15. import com.cyksj.model.manage.request.ReqGoodsSkuSpec;
  16. import com.cyksj.model.manage.request.ReqGoodsSpecSingle;
  17. import com.cyksj.model.request.CombinationSkuReq;
  18. import com.cyksj.service.mange.CmsGoodsDonSpecService;
  19. import com.cyksj.service.translations.BackInfoTranslationsService;
  20. import com.fasterxml.jackson.databind.JavaType;
  21. import lombok.RequiredArgsConstructor;
  22. import lombok.extern.slf4j.Slf4j;
  23. import org.apache.commons.lang3.StringUtils;
  24. import org.springframework.stereotype.Service;
  25. import org.springframework.transaction.annotation.Transactional;
  26. import javax.servlet.http.HttpServletRequest;
  27. import java.math.BigDecimal;
  28. import java.util.*;
  29. import java.util.concurrent.ConcurrentHashMap;
  30. import java.util.concurrent.atomic.AtomicBoolean;
  31. import java.util.stream.Collectors;
  32. /**
  33. * @author chan
  34. * @date 2022/9/27 5:19 PM
  35. */
  36. @Slf4j
  37. @Service
  38. @RequiredArgsConstructor
  39. public class CmsGoodsDonSpecServiceImpl extends ServiceImpl<GoodsDonSpecMapper, GoodsDonSpec> implements CmsGoodsDonSpecService {
  40. private final GoodsDonMapper goodsDonMapper;
  41. private final GoodsDonSkuMapper goodsDonSkuMapper;
  42. private final DistributeGoodsSkuAlertMapper distributeGoodsSkuAlertMapper;
  43. private final BackInfoTranslationsService backInfoTranslationsService;
  44. private final HttpServletRequest request;
  45. @Override
  46. @Transactional(rollbackFor = Throwable.class)
  47. public void insertOrUpdateSkuSpec(ReqGoodsSkuInsert insert, Boolean isUpdate) throws Exception {
  48. GoodsDon goods = goodsDonMapper.selectById(insert.getGoodsId());
  49. if (null == goods) {
  50. throw new RuntimeException("找不到商品spu.");
  51. }
  52. String lang = request.getHeader("lang");
  53. GoodsDonSpec loveSpec = this.getOne(Wrappers.lambdaQuery(GoodsDonSpec.class).eq(GoodsDonSpec::getGoodsId, insert.getGoodsId()));
  54. Map<String, List<ReqGoodsSkuSpec>> dbSpecMap = null;
  55. Map<Integer, ReqGoodsSkuSpec.Node> dbNodeMap = null;
  56. if (null != loveSpec) {
  57. insert.setId(loveSpec.getId());
  58. String specsJson = loveSpec.getSpecsJson();
  59. dbSpecMap = Jsons.parseList(specsJson, ReqGoodsSkuSpec.class).stream().collect(Collectors.groupingBy(ReqGoodsSkuSpec::getKey));
  60. }
  61. if (isUpdate && loveSpec == null) {
  62. throw BusinessRuntimeException.getInstance("所更新的平台id:{0}属性不存在", insert.getGoodsId());
  63. }
  64. List<ReqGoodsSkuSpec> specs = insert.getSpecs();
  65. if (null == specs || specs.isEmpty()) {
  66. throw new RuntimeException("缺少商品总规格.");
  67. }
  68. // 属性最大id
  69. Integer maxId = 0;
  70. if (loveSpec != null && loveSpec.getMaxId() != null) {
  71. maxId = loveSpec.getMaxId();
  72. }
  73. // 统计总属性数
  74. Integer total = 0;
  75. // 判断id是否有重复
  76. Map<Integer, ReqGoodsSpecSingle> map = null;
  77. // 规格数量
  78. int specNumber = specs.size();
  79. dbNodeMap = checkUpdateGoodsSpec(goods.getId(), dbSpecMap, dbNodeMap, specs);
  80. for (ReqGoodsSkuSpec spec : specs) {
  81. if (StringUtils.isBlank(spec.getKey())) {
  82. throw new RuntimeException("存在空白规格名.");
  83. }
  84. List<ReqGoodsSkuSpec.Node> values = spec.getValues();
  85. if (null == values || values.isEmpty()) {
  86. throw new RuntimeException("规格[" + spec.getKey() + "]中缺少属性.");
  87. }
  88. total += values.size();
  89. for (ReqGoodsSkuSpec.Node e : values) {
  90. if (null == e.getId() || e.getId() < 0) {
  91. e.setId(maxId + 1);
  92. }
  93. if (StringUtils.isBlank(e.getValue())) {
  94. throw new RuntimeException("规格[" + spec.getKey() + "]中存在空白属性.");
  95. }
  96. if (e.getId() > maxId) {
  97. maxId = e.getId();
  98. }
  99. //新增时 实物价格要填入
  100. if (goods.getType() == 2 && insert.getId() == null && (e.getPrice() == null || e.getPrice().compareTo(BigDecimal.ZERO) < 0)) {
  101. throw BusinessRuntimeException.getInstance("实物规格:{0}对应价格请输入", e.getValue());
  102. }
  103. if (null == map) {
  104. map = new HashMap<>(16);
  105. }
  106. String benefitsList = e.getBenefitsList();
  107. if (StrUtil.isNotBlank(benefitsList)) {
  108. Set<GoodsDonSku> benefitsSkuIds = Jsons.parseSet(benefitsList, GoodsDonSku.class);
  109. e.setBenefitsList(Jsons.toJson(benefitsSkuIds));
  110. }
  111. syncSpecNodeSku(goods.getId(), dbNodeMap, e, lang);
  112. ReqGoodsSpecSingle single = new ReqGoodsSpecSingle();
  113. single.setId(e.getId());
  114. single.setKey(spec.getKey());
  115. single.setName(e.getValue());
  116. map.put(e.getId(), single);
  117. }
  118. }
  119. if (map.size() != total) {
  120. throw new RuntimeException("规格中存在重复id.");
  121. }
  122. GoodsDonSpec spec = new GoodsDonSpec();
  123. spec.setId(insert.getId());
  124. spec.setGoodsId(insert.getGoodsId());
  125. spec.setMaxId(maxId);
  126. spec.setSpecsJson(Jsons.toJson(specs));
  127. spec.setSpecNumber(specNumber);
  128. spec.setSpecMapping(Jsons.toJson(map));
  129. if (!StrUtil.equals(UserPageLanguage.Language.zh_CN.name(), lang)) {
  130. //spec
  131. backInfoTranslationsService.saveOrUpdateBackInfoTranslations(BackInfoTranslations.Type.spec, spec.getId(), spec, lang);
  132. //sku
  133. List<GoodsDonSku> goodsDonSkus = goodsDonSkuMapper.selectList(Wrappers.lambdaQuery(GoodsDonSku.class)
  134. .eq(GoodsDonSku::getGoodsId, goods.getId()));
  135. List<GoodsDonSku> resetSkuSpec = resetSkuSpec(goodsDonSkus, spec);
  136. resetSkuSpec.stream().forEach(sku -> backInfoTranslationsService.saveOrUpdateBackInfoTranslations(BackInfoTranslations.Type.sku, sku.getId(), sku, lang));
  137. }else {
  138. if (insert.getId() != null) {
  139. this.updateById(spec);
  140. return;
  141. }
  142. this.save(spec);
  143. }
  144. }
  145. @Override
  146. public void skuAppend(ReqGoodsSkuInsert insert, GoodsDon goods) throws Exception {
  147. GoodsDonSpec loveSpec = this.getOne(Wrappers.lambdaQuery(GoodsDonSpec.class).eq(GoodsDonSpec::getGoodsId, insert.getGoodsId()));
  148. if (null == loveSpec) {
  149. throw new RuntimeException("该商品未设置总规格, 请设置总规格.");
  150. }
  151. List<ReqGoodsSkuInsert.Sku> skus = insert.getSkus();
  152. if (null == skus || skus.isEmpty()) {
  153. throw new RuntimeException("参数错误.");
  154. }
  155. int specNumber = loveSpec.getSpecNumber();
  156. JavaType type = Jsons.javaType().constructMapType(HashMap.class, Integer.class, ReqGoodsSpecSingle.class);
  157. Map<Integer, ReqGoodsSpecSingle> map = Jsons.parseObject(loveSpec.getSpecMapping(), type);
  158. StringBuilder builder = new StringBuilder();
  159. List<ReqGoodsSpecSingle> specList = null;
  160. GoodsDonSku goodsDonSku = null;
  161. // 判断属性是否属于同一个key
  162. Set<String> set = null;
  163. for (ReqGoodsSkuInsert.Sku sku : insert.getSkus()) {
  164. // 跳过空值的sku
  165. // 解析sku的规格属性
  166. final String specIds = sku.getSpecIds();
  167. if (StringUtils.isBlank(specIds)) {
  168. throw new RuntimeException("请选择商品的规格.");
  169. }
  170. int[] ids = Jsons.parseObject(specIds, int[].class);
  171. // if (ids.length != specNumber) {
  172. // throw new RuntimeException("sku规格数量 与 总规格数量 不一致.");
  173. // }
  174. // init
  175. builder.delete(0, builder.length());
  176. if (null == specList) {
  177. specList = new ArrayList<>(specNumber);
  178. } else {
  179. specList.clear();
  180. }
  181. if (null == set) {
  182. int capacity = (specNumber + 1) * 4 / 3 + 1;
  183. set = new HashSet<>(capacity);
  184. } else {
  185. set.clear();
  186. }
  187. for (int id : ids) {
  188. ReqGoodsSpecSingle single = map.get(id);
  189. if (null == single) {
  190. throw new RuntimeException("总规格属性id中 不存在 sku中的id.");
  191. }
  192. builder.append(single.getName()).append(';');
  193. specList.add(single);
  194. set.add(single.getKey());
  195. }
  196. // if (set.size() != specNumber) {
  197. // throw new RuntimeException("sku中存在多个属性属于同一个规格.");
  198. // }
  199. String specVal = builder.toString();
  200. String specJson = Jsons.toJson(specList);
  201. if (null == goodsDonSku) {
  202. goodsDonSku = new GoodsDonSku();
  203. goodsDonSku.setGoodsId(insert.getGoodsId());
  204. }
  205. BeanUtil.copyProperties(sku, goodsDonSku);
  206. String specIdsStr = Jsons.toJson(ids);
  207. //升序
  208. Arrays.sort(ids);
  209. String dupSpecIds = Jsons.toJson(ids);
  210. GoodsDonSku specIds_exists = goodsDonSkuMapper.selectOne(Wrappers.lambdaQuery(GoodsDonSku.class)
  211. .and(qr -> qr.eq(GoodsDonSku::getDupSpecIds, dupSpecIds).or().eq(GoodsDonSku::getSpecIds, specIdsStr))
  212. .eq(GoodsDonSku::getGoodsId, goods.getId())
  213. .last("limit 1"));
  214. if (specIds_exists != null) {
  215. log.info("库中存在相同二级分类的规格,spec_ids:{}", dupSpecIds);
  216. continue;
  217. }
  218. goodsDonSku.setSpecIds(specIdsStr);
  219. goodsDonSku.setDupSpecIds(dupSpecIds);
  220. goodsDonSku.setSpecVal(specVal);
  221. goodsDonSku.setSpecJson(specJson);
  222. String benefitsList = goodsDonSku.getBenefitsList();
  223. if (StrUtil.isNotBlank(benefitsList)) {
  224. Set<GoodsDonSku> benefitsSkuIds = Jsons.parseSet(benefitsList, GoodsDonSku.class);
  225. goodsDonSku.setIsBenefits(true);
  226. goodsDonSku.setBenefitsList(Jsons.toJson(benefitsSkuIds));
  227. }
  228. if (goods.getType() == 1) {
  229. if (sku.getMonths() != null && sku.getMonths() > 0 && sku.getDays() != null && sku.getDays() > 0)
  230. throw BusinessRuntimeException.getInstance("续费天数和续费月数不能同时存在");
  231. if (sku.getMonths() == null && sku.getDays() == null)
  232. throw BusinessRuntimeException.getInstance("请输入对应续费时间");
  233. }
  234. String specificGoodsIds = goodsDonSku.getSpecificGoodsIds();
  235. if (StrUtil.isNotBlank(specificGoodsIds)) {
  236. Set<Long> specificGids = Jsons.parseSet(specificGoodsIds, Long.class);
  237. if (specificGids.isEmpty()) {
  238. goodsDonSku.setSpecificPrice(BigDecimal.ZERO);
  239. } else {
  240. Integer count = goodsDonMapper.selectCount(Wrappers.lambdaQuery(GoodsDon.class)
  241. .in(GoodsDon::getId, specificGids)
  242. .eq(GoodsDon::getStatus, true)
  243. .eq(GoodsDon::getDeleted, true));
  244. if (count != specificGids.size()) {
  245. throw BusinessRuntimeException.getInstance("存在被删除或已下架的平台");
  246. }
  247. BigDecimal specificPrice = goodsDonSku.getSpecificPrice();
  248. if (specificPrice == null || specificPrice.compareTo(BigDecimal.ZERO) <= 0) {
  249. throw BusinessRuntimeException.getInstance("请输入正确的特定价格");
  250. }
  251. }
  252. }
  253. if (StrUtil.isNotEmpty(goodsDonSku.getUserOwns())) {
  254. List<Long> userOwnsList = Jsons.parseList(goodsDonSku.getUserOwns(), Long.class);
  255. if (CollUtil.isEmpty(userOwnsList)) {
  256. goodsDonSku.setUserOwns(null);
  257. } else {
  258. goodsDonSku.setUserOwns(userOwnsList.toString());
  259. }
  260. }
  261. goodsDonSkuMapper.insert(goodsDonSku);
  262. DistributeGoodsSkuAlert distributeGoodsSkuAlert = new DistributeGoodsSkuAlert();
  263. distributeGoodsSkuAlert.setGoodsId(goods.getId());
  264. distributeGoodsSkuAlert.setSkuId(goodsDonSku.getId());
  265. distributeGoodsSkuAlertMapper.insert(distributeGoodsSkuAlert);
  266. }
  267. }
  268. @Override
  269. public void combinationSku(Long goodsId, List<CombinationSkuReq> combinations) throws Exception {
  270. GoodsDon goodsDon = goodsDonMapper.selectById(goodsId);
  271. if (goodsDon == null) throw BusinessRuntimeException.getInstance("平台不存在");
  272. if (goodsDon.getType() != 2) {
  273. throw BusinessRuntimeException.getInstance("暂只支持实物规格");
  274. }
  275. GoodsDonSpec loveSpec = this.getOne(Wrappers.lambdaQuery(GoodsDonSpec.class).eq(GoodsDonSpec::getGoodsId, goodsId));
  276. if (null == loveSpec) {
  277. throw new RuntimeException("该商品未设置总规格, 请设置总规格.");
  278. }
  279. String specsJson = loveSpec.getSpecsJson();
  280. List<ReqGoodsSkuSpec> specsList = Jsons.parseList(specsJson, ReqGoodsSkuSpec.class);
  281. Map<String, List<ReqGoodsSkuSpec>> specValueMap = specsList.stream().collect(Collectors.groupingBy(ReqGoodsSkuSpec::getKey));
  282. if (combinations.isEmpty()) {
  283. throw BusinessRuntimeException.getInstance("请选择对应的规格组合");
  284. }
  285. List<ReqGoodsSkuInsert.Sku> skus = new LinkedList<>();
  286. ReqGoodsSkuInsert reqGoodsSkuInsert = new ReqGoodsSkuInsert();
  287. reqGoodsSkuInsert.setGoodsId(goodsId);
  288. List<List<Integer>> specIdLists = new LinkedList<>();
  289. CombinationSkuReq request = combinations.get(0);
  290. List<ReqGoodsSkuSpec> reqGoodsSkuSpecs = specValueMap.get(request.getKey());
  291. if (reqGoodsSkuSpecs == null) {
  292. throw BusinessRuntimeException.getInstance("传入的总规格属性:{0}不存在", request.getKey());
  293. }
  294. Map<Integer, List<ReqGoodsSkuSpec.Node>> nodeIdMap = reqGoodsSkuSpecs.get(0).getValues().stream().collect(Collectors.groupingBy(ReqGoodsSkuSpec.Node::getId));
  295. if (CollUtil.isNotEmpty(request.getValues())) {
  296. unifiedHandleCombinationSku(combinations, request.getValues(), specValueMap, nodeIdMap, specIdLists, skus);
  297. } else {
  298. ReqGoodsSkuSpec reqGoodsSkuSpec = reqGoodsSkuSpecs.get(0);
  299. unifiedHandleCombinationSku(combinations,reqGoodsSkuSpec.getValues(),specValueMap, nodeIdMap,specIdLists,skus);
  300. }
  301. reqGoodsSkuInsert.setSkus(skus);
  302. skuAppend(reqGoodsSkuInsert, goodsDon);
  303. }
  304. public void unifiedHandleCombinationSku(List<CombinationSkuReq> combinations, List<ReqGoodsSkuSpec.Node> values, Map<String, List<ReqGoodsSkuSpec>> specValueMap, Map<Integer, List<ReqGoodsSkuSpec.Node>> nodeIdMap, List<List<Integer>> specIdLists, List<ReqGoodsSkuInsert.Sku> skus) throws Exception {
  305. for (ReqGoodsSkuSpec.Node node_value : values) {
  306. ReqGoodsSkuInsert.Sku sku = new ReqGoodsSkuInsert.Sku();
  307. sku.setPrice(BigDecimal.ZERO);
  308. List<Integer> specIds = new LinkedList<>();
  309. unifiedHandleSecondCombinationSku(node_value, nodeIdMap, sku, specIds);
  310. recurCombinationSku(combinations, combinations.size(), 1, 1, specIds, specIdLists, sku, specValueMap, skus);
  311. }
  312. }
  313. public void unifiedHandleSecondCombinationSku(ReqGoodsSkuSpec.Node temp_node, Map<Integer, List<ReqGoodsSkuSpec.Node>> nodeIdMap, ReqGoodsSkuInsert.Sku sku, List<Integer> specIds) {
  314. List<ReqGoodsSkuSpec.Node> nodes = nodeIdMap.get(temp_node.getId());
  315. if (CollUtil.isEmpty(nodes)) {
  316. throw BusinessRuntimeException.getInstance("{0}规格不存在", temp_node.getValue());
  317. }
  318. ReqGoodsSkuSpec.Node node = nodes.get(0);
  319. BigDecimal price = node.getPrice();
  320. if (price == null && node.getValue().contains("无")) {
  321. price = BigDecimal.ZERO;
  322. }
  323. if (price == null) {
  324. throw BusinessRuntimeException.getInstance("该实物子规格:{0}未配置价格", node.getValue());
  325. }
  326. sku.setPrice(sku.getPrice().add(price));
  327. specIds.add(temp_node.getId());
  328. if (StrUtil.isNotEmpty(node.getBenefitsList())) {
  329. sku.setIsBenefits(true);
  330. sku.setBenefitsList(node.getBenefitsList());
  331. }
  332. }
  333. /**
  334. * @param combinations 传入的组合数据
  335. * @param total 总共需要组合的大小
  336. * @param has 已有组合数大小
  337. * @param start 下一个组合数组下表
  338. * @param specIds 组合规格ids
  339. * @param sku 待插入库中的sku
  340. * @param specValueMap 总规格库中对应values
  341. */
  342. private void recurCombinationSku(List<CombinationSkuReq> combinations, Integer total, Integer has, Integer start, List<Integer> specIds, List<List<Integer>> specIdLists, ReqGoodsSkuInsert.Sku sku, Map<String, List<ReqGoodsSkuSpec>> specValueMap, List<ReqGoodsSkuInsert.Sku> skus) throws Exception {
  343. if (has == total) {
  344. if (specIdLists.contains(specIds)) {
  345. return;
  346. }
  347. sku.setSpecIds(Jsons.toJson(specIds));
  348. skus.add(sku);
  349. return;
  350. }
  351. CombinationSkuReq request = combinations.get(start);
  352. List<ReqGoodsSkuSpec> reqGoodsSkuSpecs = specValueMap.get(request.getKey());
  353. if (reqGoodsSkuSpecs == null) {
  354. throw BusinessRuntimeException.getInstance("总规格属性{0}不存在", request.getKey());
  355. }
  356. ReqGoodsSkuSpec reqGoodsSkuSpec = reqGoodsSkuSpecs.get(0);
  357. Map<Integer, List<ReqGoodsSkuSpec.Node>> nodeIdMap = reqGoodsSkuSpec.getValues().stream().collect(Collectors.groupingBy(ReqGoodsSkuSpec.Node::getId));
  358. if (CollUtil.isNotEmpty(request.getValues())) {
  359. createNewSkuAndRecurCombination(combinations, request.getValues(), nodeIdMap, has, start, specIds, specIdLists, sku, specValueMap, skus);
  360. return;
  361. }
  362. createNewSkuAndRecurCombination(combinations, reqGoodsSkuSpec.getValues(), nodeIdMap, has, start, specIds, specIdLists, sku, specValueMap, skus);
  363. }
  364. /**
  365. * 新的规格 递归
  366. */
  367. public void createNewSkuAndRecurCombination(List<CombinationSkuReq> combinations, List<ReqGoodsSkuSpec.Node> values, Map<Integer, List<ReqGoodsSkuSpec.Node>> nodeIdMap, Integer has, Integer start, List<Integer> specIds, List<List<Integer>> specIdLists, ReqGoodsSkuInsert.Sku sku, Map<String, List<ReqGoodsSkuSpec>> specValueMap, List<ReqGoodsSkuInsert.Sku> skus) throws Exception {
  368. for (ReqGoodsSkuSpec.Node node_value : values) {
  369. BigDecimal last_price = sku.getPrice();
  370. unifiedHandleSecondCombinationSku(node_value, nodeIdMap, sku, specIds);
  371. recurCombinationSku(combinations, combinations.size(), has + 1, start + 1, specIds, specIdLists, sku, specValueMap, skus);
  372. specIds.remove(node_value.getId());
  373. sku = new ReqGoodsSkuInsert.Sku();
  374. sku.setPrice(last_price);
  375. }
  376. }
  377. /**
  378. * 更新删除总属性 一级分类 校验
  379. */
  380. public Map<Integer, ReqGoodsSkuSpec.Node> checkUpdateGoodsSpec(Long goodsId, Map<String, List<ReqGoodsSkuSpec>> dbSpecMap, Map<Integer, ReqGoodsSkuSpec.Node> dbNodeMap, List<ReqGoodsSkuSpec> specs) {
  381. if (CollUtil.isNotEmpty(dbSpecMap)) {
  382. Map<String, List<ReqGoodsSkuSpec>> updateSpecMap = specs.stream().collect(Collectors.groupingBy(ReqGoodsSkuSpec::getKey));
  383. dbNodeMap = new ConcurrentHashMap<>();
  384. for (String key : dbSpecMap.keySet()) {
  385. List<ReqGoodsSkuSpec> reqGoodsSkuSpecs = updateSpecMap.get(key);
  386. if (CollUtil.isNotEmpty(reqGoodsSkuSpecs)) {
  387. ReqGoodsSkuSpec reqGoodsSkuSpec = reqGoodsSkuSpecs.get(0);
  388. if (CollUtil.isEmpty(reqGoodsSkuSpec.getValues())) {
  389. //删除整个一级分类key
  390. String specFirstKey = reqGoodsSkuSpec.getKey();
  391. GoodsDonSku sku = goodsDonSkuMapper.selectOne(Wrappers.lambdaQuery(GoodsDonSku.class)
  392. .eq(GoodsDonSku::getGoodsId, goodsId)
  393. .like(GoodsDonSku::getSpecJson, specFirstKey).last("limit 1"));
  394. if (sku != null) {
  395. throw BusinessRuntimeException.getInstance("删除总规格分类,存在使用该总规格分类的规格");
  396. }
  397. } else {
  398. Map<Integer, List<ReqGoodsSkuSpec.Node>> updateSecondMap = reqGoodsSkuSpec.getValues().stream().filter(node -> node.getId() != null).collect(Collectors.groupingBy(ReqGoodsSkuSpec.Node::getId));
  399. ReqGoodsSkuSpec dbReqGoodsSkuSpec = dbSpecMap.get(key).get(0);
  400. for (ReqGoodsSkuSpec.Node dbSecondValue : dbReqGoodsSkuSpec.getValues()) {
  401. if (updateSecondMap.get(dbSecondValue.getId()) == null) {
  402. GoodsDonSku sku = goodsDonSkuMapper.selectOne(Wrappers.lambdaQuery(GoodsDonSku.class)
  403. .eq(GoodsDonSku::getGoodsId, goodsId)
  404. .apply("JSON_CONTAINS(spec_ids,'" + dbSecondValue.getId() + "')").last("limit 1"));
  405. if (sku != null) {
  406. throw BusinessRuntimeException.getInstance("删除总规格分类,存在使用该总规格分类的规格");
  407. }
  408. }
  409. dbNodeMap.put(dbSecondValue.getId(), dbSecondValue);
  410. }
  411. }
  412. }
  413. //去除总规格分类时
  414. //校验是否已引用该属性规格
  415. if (CollUtil.isEmpty(reqGoodsSkuSpecs)) {
  416. ReqGoodsSkuSpec dbReqGoodsSkuSpec = dbSpecMap.get(key).get(0);
  417. //删除整个一级分类key
  418. String specFirstKey = dbReqGoodsSkuSpec.getKey();
  419. GoodsDonSku sku = goodsDonSkuMapper.selectOne(Wrappers.lambdaQuery(GoodsDonSku.class)
  420. .eq(GoodsDonSku::getGoodsId, goodsId)
  421. .like(GoodsDonSku::getSpecJson, specFirstKey).last("limit 1"));
  422. if (sku != null) {
  423. throw BusinessRuntimeException.getInstance("删除总规格分类,存在使用该总规格分类的规格");
  424. }
  425. }
  426. }
  427. return dbNodeMap;
  428. }
  429. return null;
  430. }
  431. /**
  432. * 更新二级分类标题价格等 同步库中sku
  433. */
  434. public void syncSpecNodeSku(Long goodsId, Map<Integer, ReqGoodsSkuSpec.Node> dbNodeMap, ReqGoodsSkuSpec.Node e, String lang) {
  435. if (CollUtil.isNotEmpty(dbNodeMap)) {
  436. ReqGoodsSkuSpec.Node dbNode = dbNodeMap.get(e.getId());
  437. if (dbNode == null) {
  438. return;
  439. }
  440. AtomicBoolean isUpdateTitle = new AtomicBoolean(false);
  441. AtomicBoolean isUpdatePrice = new AtomicBoolean(false);
  442. AtomicBoolean isUpdateBenefits = new AtomicBoolean(false);
  443. if (!StrUtil.equals(dbNode.getValue(), e.getValue())) {
  444. isUpdateTitle.set(true);
  445. }
  446. if (e.getPrice() == null) {
  447. e.setPrice(BigDecimal.ZERO);
  448. }
  449. if (dbNode.getPrice() != null && e.getPrice().compareTo(dbNode.getPrice()) != 0) {
  450. isUpdatePrice.set(true);
  451. }
  452. if (!StrUtil.equals(dbNode.getBenefitsList(), e.getBenefitsList())) {
  453. isUpdateBenefits.set(true);
  454. }
  455. if (isUpdateTitle.get() || isUpdatePrice.get() || isUpdateBenefits.get()) {
  456. List<GoodsDonSku> goodsDonSkus = goodsDonSkuMapper.selectList(Wrappers.lambdaQuery(GoodsDonSku.class)
  457. .eq(GoodsDonSku::getGoodsId, goodsId));
  458. goodsDonSkus.forEach(sku -> {
  459. try {
  460. List<Integer> specIdsList = Jsons.parseList(sku.getSpecIds(), Integer.class);
  461. if (specIdsList.contains(dbNode.getId())) {
  462. if (isUpdateTitle.get()) {
  463. sku.setSpecJson(StrUtil.replace(sku.getSpecJson(), dbNode.getValue(), e.getValue()));
  464. sku.setSpecVal(StrUtil.replace(sku.getSpecVal(), dbNode.getValue(), e.getValue()));
  465. }
  466. if (isUpdatePrice.get()) {
  467. if (specIdsList.size() == 1) {
  468. sku.setPrice(e.getPrice());
  469. } else {
  470. sku.setPrice(sku.getPrice().subtract(dbNode.getPrice()).add(e.getPrice()));
  471. }
  472. }
  473. if (isUpdateBenefits.get()) {
  474. if (StrUtil.isEmpty(e.getBenefitsList())) {
  475. sku.setBenefitsList(StrUtil.EMPTY);
  476. } else {
  477. try {
  478. sku.setBenefitsList(e.getBenefitsList());
  479. } catch (Exception exception) {
  480. }
  481. }
  482. }
  483. if (StrUtil.equals(UserPageLanguage.Language.zh_CN.name(), lang)) {
  484. goodsDonSkuMapper.updateById(sku);
  485. }
  486. }
  487. } catch (Exception exception) {
  488. }
  489. });
  490. }
  491. }
  492. }
  493. //多语言设置sku
  494. public List<GoodsDonSku> resetSkuSpec(List<GoodsDonSku> skus, GoodsDonSpec loveSpec) throws Exception {
  495. StringBuilder builder = new StringBuilder();
  496. List<ReqGoodsSpecSingle> specList = null;
  497. JavaType type = Jsons.javaType().constructMapType(HashMap.class, Integer.class, ReqGoodsSpecSingle.class);
  498. Map<Integer, ReqGoodsSpecSingle> map = Jsons.parseObject(loveSpec.getSpecMapping(), type);
  499. int specNumber = loveSpec.getSpecNumber();
  500. List<GoodsDonSku> reSkuList = new ArrayList<>();
  501. GoodsDonSku reSku = null;
  502. for (GoodsDonSku sku : skus) {
  503. final String specIds = sku.getSpecIds();
  504. if (StringUtils.isBlank(specIds)) {
  505. throw new RuntimeException("请选择商品的规格.");
  506. }
  507. int[] ids = Jsons.parseObject(specIds, int[].class);
  508. // init
  509. builder.delete(0, builder.length());
  510. if (null == specList) {
  511. specList = new ArrayList<>(specNumber);
  512. } else {
  513. specList.clear();
  514. }
  515. for (int id : ids) {
  516. ReqGoodsSpecSingle single = map.get(id);
  517. if (null == single) {
  518. throw new RuntimeException("总规格属性id中 不存在 sku中的id.");
  519. }
  520. builder.append(single.getName()).append(';');
  521. specList.add(single);
  522. }
  523. reSku = new GoodsDonSku();
  524. String specVal = builder.toString();
  525. String specJson = Jsons.toJson(specList);
  526. reSku.setId(sku.getId());
  527. reSku.setSpecVal(specVal);
  528. reSku.setSpecJson(specJson);
  529. reSkuList.add(reSku);
  530. }
  531. return reSkuList;
  532. }
  533. }