|
@@ -1,11 +1,14 @@
|
|
|
package zs.payment.service.yunmall.goods.impl;
|
|
package zs.payment.service.yunmall.goods.impl;
|
|
|
|
|
|
|
|
|
|
+import com.alibaba.fastjson.JSON;
|
|
|
import org.apache.commons.lang3.StringUtils;
|
|
import org.apache.commons.lang3.StringUtils;
|
|
|
|
|
+import org.bson.Document;
|
|
|
import org.springframework.beans.factory.annotation.Autowired;
|
|
import org.springframework.beans.factory.annotation.Autowired;
|
|
|
import org.springframework.data.mongodb.core.query.Criteria;
|
|
import org.springframework.data.mongodb.core.query.Criteria;
|
|
|
import org.springframework.data.mongodb.core.query.Query;
|
|
import org.springframework.data.mongodb.core.query.Query;
|
|
|
import org.springframework.stereotype.Service;
|
|
import org.springframework.stereotype.Service;
|
|
|
import zs.payment.dao.yunmall.GoodsDao;
|
|
import zs.payment.dao.yunmall.GoodsDao;
|
|
|
|
|
+import zs.payment.mapper.flymall.B2cGoodsSpuInOnlineMapper;
|
|
|
import zs.payment.entity.mongodb.yunmall.Goods;
|
|
import zs.payment.entity.mongodb.yunmall.Goods;
|
|
|
import zs.payment.entity.mongodb.yunmall.Shop;
|
|
import zs.payment.entity.mongodb.yunmall.Shop;
|
|
|
import zs.payment.entity.mongodb.yunmall.Sku;
|
|
import zs.payment.entity.mongodb.yunmall.Sku;
|
|
@@ -22,7 +25,10 @@ import zs.payment.service.yunmall.goods.GoodsService;
|
|
|
import zs.payment.utils.TimeUtils;
|
|
import zs.payment.utils.TimeUtils;
|
|
|
|
|
|
|
|
import java.math.BigDecimal;
|
|
import java.math.BigDecimal;
|
|
|
|
|
+import java.util.ArrayList;
|
|
|
|
|
+import java.util.LinkedHashMap;
|
|
|
import java.util.List;
|
|
import java.util.List;
|
|
|
|
|
+import java.util.Map;
|
|
|
import java.util.Optional;
|
|
import java.util.Optional;
|
|
|
import java.util.stream.Collectors;
|
|
import java.util.stream.Collectors;
|
|
|
|
|
|
|
@@ -44,6 +50,9 @@ public class GoodsServiceImpl implements GoodsService {
|
|
|
@Autowired
|
|
@Autowired
|
|
|
private GoodsDao goodsDao;
|
|
private GoodsDao goodsDao;
|
|
|
|
|
|
|
|
|
|
+ @Autowired
|
|
|
|
|
+ private B2cGoodsSpuInOnlineMapper b2cGoodsSpuInOnlineMapper;
|
|
|
|
|
+
|
|
|
|
|
|
|
|
@Override
|
|
@Override
|
|
|
public Boolean saveGoods(String gdId, Integer op) {
|
|
public Boolean saveGoods(String gdId, Integer op) {
|
|
@@ -110,4 +119,212 @@ public class GoodsServiceImpl implements GoodsService {
|
|
|
}
|
|
}
|
|
|
return false;
|
|
return false;
|
|
|
}
|
|
}
|
|
|
|
|
+
|
|
|
|
|
+ @Override
|
|
|
|
|
+ public Map<String, Object> searchGoods(Long shopId, String keyWord, String categorys, String pts,
|
|
|
|
|
+ Integer psize, Integer pno, Integer orderBy) {
|
|
|
|
|
+ // 1. 三个查询条件全空 → 参数缺失(对齐 qiyuesearchgoods)
|
|
|
|
|
+ if (StringUtils.isBlank(keyWord) && StringUtils.isBlank(categorys) && StringUtils.isBlank(pts)) {
|
|
|
|
|
+ return errorResult("参数缺失");
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ List<Long> ptIds = new ArrayList<>();
|
|
|
|
|
+
|
|
|
|
|
+ // 2. 一级/二级分类 → 向下钻取至 level>=3 叶子分类 → 品类 pt_id
|
|
|
|
|
+ if (StringUtils.isNotBlank(categorys)) {
|
|
|
|
|
+ List<Long> categoryIds = parseLongArray(categorys);
|
|
|
|
|
+ if (!categoryIds.isEmpty()) {
|
|
|
|
|
+ List<Map<String, Object>> categoryList =
|
|
|
|
|
+ b2cGoodsSpuInOnlineMapper.findCategoriesByCateIds(joinIds(categoryIds));
|
|
|
|
|
+ while (categoryList != null && !categoryList.isEmpty()
|
|
|
|
|
+ && toInteger(categoryList.get(0).get("level")) < 3) {
|
|
|
|
|
+ categoryIds = collectCateIds(categoryList);
|
|
|
|
|
+ categoryList = b2cGoodsSpuInOnlineMapper.findCategoriesByParentIds(joinIds(categoryIds));
|
|
|
|
|
+ if (categoryList != null && !categoryList.isEmpty()) {
|
|
|
|
|
+ categoryIds = collectCateIds(categoryList);
|
|
|
|
|
+ }
|
|
|
|
|
+ }
|
|
|
|
|
+ if (!categoryIds.isEmpty()) {
|
|
|
|
|
+ List<Long> resolved = b2cGoodsSpuInOnlineMapper.findPtIdsByCateIds(joinIds(categoryIds));
|
|
|
|
|
+ if (resolved != null) {
|
|
|
|
|
+ ptIds = resolved;
|
|
|
|
|
+ }
|
|
|
|
|
+ }
|
|
|
|
|
+ }
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ // 3. 传了 pts 时直接覆盖分类解析结果
|
|
|
|
|
+ if (StringUtils.isNotBlank(pts)) {
|
|
|
|
|
+ ptIds = parseLongArray(pts);
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ // 4. keyWord 为空且未解析出品类 → 查询参数缺失
|
|
|
|
|
+ if (StringUtils.isBlank(keyWord) && ptIds.isEmpty()) {
|
|
|
|
|
+ return errorResult("查询参数缺失");
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ // 5. 查询 + 逐条补全字段
|
|
|
|
|
+ long totalcount = goodsDao.searchCount(keyWord, ptIds, shopId);
|
|
|
|
|
+ List<Document> goodsList = goodsDao.searchRaw(keyWord, ptIds, shopId, psize, pno, orderBy);
|
|
|
|
|
+ for (Document doc : goodsList) {
|
|
|
|
|
+ enrichGoods(doc);
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ Map<String, Object> bodyItem = new LinkedHashMap<>();
|
|
|
|
|
+ bodyItem.put("totalcount", totalcount);
|
|
|
|
|
+ bodyItem.put("goodsList", goodsList);
|
|
|
|
|
+ List<Map<String, Object>> body = new ArrayList<>();
|
|
|
|
|
+ body.add(bodyItem);
|
|
|
|
|
+
|
|
|
|
|
+ Map<String, Object> head = new LinkedHashMap<>();
|
|
|
|
|
+ head.put("status", 200);
|
|
|
|
|
+ Map<String, Object> result = new LinkedHashMap<>();
|
|
|
|
|
+ result.put("head", head);
|
|
|
|
|
+ result.put("body", body);
|
|
|
|
|
+ return result;
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ /**
|
|
|
|
|
+ * 逐条商品字段补全(对齐 qiyueGoodsSearch):
|
|
|
|
|
+ * 去 _id、补 sku.gd_stock/attrs、算 totalstock/min_price,缺失时补 cost_price/statement_rate。
|
|
|
|
|
+ */
|
|
|
|
|
+ private void enrichGoods(Document doc) {
|
|
|
|
|
+ doc.remove("_id");
|
|
|
|
|
+ long totalstock = 0;
|
|
|
|
|
+ BigDecimal minPrice = BigDecimal.valueOf(-1);
|
|
|
|
|
+ boolean minPriceSet = false;
|
|
|
|
|
+ List<BigDecimal> costPrices = new ArrayList<>();
|
|
|
|
|
+
|
|
|
|
|
+ Object skusObj = doc.get("skus");
|
|
|
|
|
+ if (skusObj instanceof List) {
|
|
|
|
|
+ for (Object o : (List<?>) skusObj) {
|
|
|
|
|
+ if (!(o instanceof Document)) {
|
|
|
|
|
+ continue;
|
|
|
|
|
+ }
|
|
|
|
|
+ Document sku = (Document) o;
|
|
|
|
|
+ int gdStock = 0;
|
|
|
|
|
+ Object skuIdObj = sku.get("sku_id");
|
|
|
|
|
+ if (skuIdObj != null) {
|
|
|
|
|
+ B2cGoodsSkuInOnline dbSku = b2cGoodsSkuInOnlineService.getById(toInteger(skuIdObj));
|
|
|
|
|
+ if (dbSku != null) {
|
|
|
|
|
+ gdStock = dbSku.getGdStock() == null ? 0 : dbSku.getGdStock();
|
|
|
|
|
+ if (dbSku.getGdPrice() != null && (!minPriceSet || dbSku.getGdPrice().compareTo(minPrice) < 0)) {
|
|
|
|
|
+ minPrice = dbSku.getGdPrice();
|
|
|
|
|
+ minPriceSet = true;
|
|
|
|
|
+ }
|
|
|
|
|
+ if (dbSku.getCostPrice() != null && !costPrices.contains(dbSku.getCostPrice())) {
|
|
|
|
|
+ costPrices.add(dbSku.getCostPrice());
|
|
|
|
|
+ }
|
|
|
|
|
+ }
|
|
|
|
|
+ }
|
|
|
|
|
+ sku.put("gd_stock", gdStock);
|
|
|
|
|
+ if (!(sku.get("attrs") instanceof List)) {
|
|
|
|
|
+ sku.put("attrs", new ArrayList<>());
|
|
|
|
|
+ }
|
|
|
|
|
+ totalstock += gdStock;
|
|
|
|
|
+ }
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ doc.put("totalstock", totalstock);
|
|
|
|
|
+ doc.put("min_price", minPriceSet ? minPrice : BigDecimal.valueOf(-1));
|
|
|
|
|
+ if (!(doc.get("cost_price") instanceof List)) {
|
|
|
|
|
+ doc.put("cost_price", costPrices);
|
|
|
|
|
+ }
|
|
|
|
|
+ if (doc.get("statement_rate") == null || doc.get("tg_statement_rate") == null) {
|
|
|
|
|
+ Object ptObj = doc.get("pt_id");
|
|
|
|
|
+ if (ptObj != null) {
|
|
|
|
|
+ Map<String, Object> commission = b2cGoodsSpuInOnlineMapper.findCommissionByPtId(toInteger(ptObj));
|
|
|
|
|
+ if (commission != null) {
|
|
|
|
|
+ if (doc.get("statement_rate") == null) {
|
|
|
|
|
+ doc.put("statement_rate", commission.get("ledger_ratio"));
|
|
|
|
|
+ }
|
|
|
|
|
+ if (doc.get("tg_statement_rate") == null) {
|
|
|
|
|
+ doc.put("tg_statement_rate", commission.get("tg_ledger_ratio"));
|
|
|
|
|
+ }
|
|
|
|
|
+ }
|
|
|
|
|
+ }
|
|
|
|
|
+ }
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ /**
|
|
|
|
|
+ * 解析 ID 列表参数,兼容三种形式:
|
|
|
|
|
+ * 1) JSON 数组:[1200000] 或 [1200000,1200001](对齐 groovy jsonSlurper.parseText)
|
|
|
|
|
+ * 2) 逗号分隔:1200000,1200001
|
|
|
|
|
+ * 3) 单个数值:1200000
|
|
|
|
|
+ * 解析失败返回空列表。
|
|
|
|
|
+ */
|
|
|
|
|
+ private List<Long> parseLongArray(String value) {
|
|
|
|
|
+ if (StringUtils.isBlank(value)) {
|
|
|
|
|
+ return new ArrayList<>();
|
|
|
|
|
+ }
|
|
|
|
|
+ String trimmed = value.trim();
|
|
|
|
|
+ // JSON 数组形式
|
|
|
|
|
+ if (trimmed.startsWith("[")) {
|
|
|
|
|
+ try {
|
|
|
|
|
+ List<Long> list = JSON.parseArray(trimmed, Long.class);
|
|
|
|
|
+ return list == null ? new ArrayList<>() : list;
|
|
|
|
|
+ } catch (Exception e) {
|
|
|
|
|
+ return new ArrayList<>();
|
|
|
|
|
+ }
|
|
|
|
|
+ }
|
|
|
|
|
+ // 逗号分隔 / 单个数值形式
|
|
|
|
|
+ List<Long> list = new ArrayList<>();
|
|
|
|
|
+ for (String part : trimmed.split(",")) {
|
|
|
|
|
+ String p = part.trim();
|
|
|
|
|
+ if (p.isEmpty()) {
|
|
|
|
|
+ continue;
|
|
|
|
|
+ }
|
|
|
|
|
+ try {
|
|
|
|
|
+ list.add(Long.parseLong(p));
|
|
|
|
|
+ } catch (NumberFormatException ignore) {
|
|
|
|
|
+ // 跳过非法项
|
|
|
|
|
+ }
|
|
|
|
|
+ }
|
|
|
|
|
+ return list;
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ /** 从分类查询结果中收集 cate_id 列表 */
|
|
|
|
|
+ private List<Long> collectCateIds(List<Map<String, Object>> categoryList) {
|
|
|
|
|
+ List<Long> ids = new ArrayList<>();
|
|
|
|
|
+ for (Map<String, Object> row : categoryList) {
|
|
|
|
|
+ Object cateId = row.get("cate_id");
|
|
|
|
|
+ if (cateId != null) {
|
|
|
|
|
+ ids.add(((Number) cateId).longValue());
|
|
|
|
|
+ }
|
|
|
|
|
+ }
|
|
|
|
|
+ return ids;
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ /** 数值ID列表拼接为逗号串,用于 IN (${...}) */
|
|
|
|
|
+ private String joinIds(List<Long> ids) {
|
|
|
|
|
+ StringBuilder sb = new StringBuilder();
|
|
|
|
|
+ for (int i = 0; i < ids.size(); i++) {
|
|
|
|
|
+ if (i > 0) {
|
|
|
|
|
+ sb.append(",");
|
|
|
|
|
+ }
|
|
|
|
|
+ sb.append(ids.get(i));
|
|
|
|
|
+ }
|
|
|
|
|
+ return sb.toString();
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ /** 宽松转 Integer */
|
|
|
|
|
+ private Integer toInteger(Object value) {
|
|
|
|
|
+ if (value == null) {
|
|
|
|
|
+ return 0;
|
|
|
|
|
+ }
|
|
|
|
|
+ if (value instanceof Number) {
|
|
|
|
|
+ return ((Number) value).intValue();
|
|
|
|
|
+ }
|
|
|
|
|
+ return Integer.parseInt(value.toString().trim());
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ /** 错误响应:{head:{status:500,msg}} */
|
|
|
|
|
+ private Map<String, Object> errorResult(String msg) {
|
|
|
|
|
+ Map<String, Object> head = new LinkedHashMap<>();
|
|
|
|
|
+ head.put("status", 500);
|
|
|
|
|
+ head.put("msg", msg);
|
|
|
|
|
+ Map<String, Object> result = new LinkedHashMap<>();
|
|
|
|
|
+ result.put("head", head);
|
|
|
|
|
+ return result;
|
|
|
|
|
+ }
|
|
|
}
|
|
}
|