|
@@ -1,5 +1,6 @@
|
|
|
package com.haha.service.impl;
|
|
package com.haha.service.impl;
|
|
|
|
|
|
|
|
|
|
+import com.alibaba.fastjson2.JSON;
|
|
|
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
|
|
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
|
|
|
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
|
|
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
|
|
|
import com.haha.common.exception.BusinessException;
|
|
import com.haha.common.exception.BusinessException;
|
|
@@ -12,21 +13,19 @@ import com.qdb.sdk.QdbClient;
|
|
|
import com.qdb.sdk.QdbException;
|
|
import com.qdb.sdk.QdbException;
|
|
|
import com.qdb.sdk.model.request.SysGoodsQueryRequest;
|
|
import com.qdb.sdk.model.request.SysGoodsQueryRequest;
|
|
|
import com.qdb.sdk.model.response.QdbResponse;
|
|
import com.qdb.sdk.model.response.QdbResponse;
|
|
|
-import com.qdb.sdk.model.response.SysGoodsPageResult;
|
|
|
|
|
import com.qdb.sdk.model.response.SysGoodsVO;
|
|
import com.qdb.sdk.model.response.SysGoodsVO;
|
|
|
import lombok.RequiredArgsConstructor;
|
|
import lombok.RequiredArgsConstructor;
|
|
|
import lombok.extern.slf4j.Slf4j;
|
|
import lombok.extern.slf4j.Slf4j;
|
|
|
import org.springframework.beans.factory.annotation.Autowired;
|
|
import org.springframework.beans.factory.annotation.Autowired;
|
|
|
|
|
+import org.springframework.scheduling.annotation.Async;
|
|
|
import org.springframework.stereotype.Service;
|
|
import org.springframework.stereotype.Service;
|
|
|
import org.springframework.transaction.annotation.Transactional;
|
|
import org.springframework.transaction.annotation.Transactional;
|
|
|
import org.springframework.util.StringUtils;
|
|
import org.springframework.util.StringUtils;
|
|
|
|
|
|
|
|
import java.time.LocalDateTime;
|
|
import java.time.LocalDateTime;
|
|
|
|
|
+import java.time.ZoneId;
|
|
|
import java.util.List;
|
|
import java.util.List;
|
|
|
|
|
|
|
|
-/**
|
|
|
|
|
- * ERP 商品信息服务实现
|
|
|
|
|
- */
|
|
|
|
|
@Slf4j
|
|
@Slf4j
|
|
|
@Service
|
|
@Service
|
|
|
@RequiredArgsConstructor
|
|
@RequiredArgsConstructor
|
|
@@ -37,55 +36,75 @@ public class ErpGoodsServiceImpl extends ServiceImpl<ErpGoodsMapper, ErpGoods> i
|
|
|
@Autowired(required = false)
|
|
@Autowired(required = false)
|
|
|
private QdbClient qdbClient;
|
|
private QdbClient qdbClient;
|
|
|
|
|
|
|
|
|
|
+ @Async("taskExecutor")
|
|
|
@Override
|
|
@Override
|
|
|
- @Transactional(rollbackFor = Exception.class)
|
|
|
|
|
public void syncFromErp() {
|
|
public void syncFromErp() {
|
|
|
if (qdbClient == null) {
|
|
if (qdbClient == null) {
|
|
|
throw new BusinessException(500, "QdbClient 未配置,无法同步ERP商品数据");
|
|
throw new BusinessException(500, "QdbClient 未配置,无法同步ERP商品数据");
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
- int pageNo = 1;
|
|
|
|
|
- int pageSize = 50;
|
|
|
|
|
- boolean hasMore = true;
|
|
|
|
|
- int syncedCount = 0;
|
|
|
|
|
-
|
|
|
|
|
- while (hasMore) {
|
|
|
|
|
- SysGoodsQueryRequest request = SysGoodsQueryRequest.builder()
|
|
|
|
|
- .pageIndex(pageNo)
|
|
|
|
|
- .pageSize(pageSize)
|
|
|
|
|
- .status(1)
|
|
|
|
|
- .build();
|
|
|
|
|
|
|
+ List<Product> products = productMapper.selectList(new LambdaQueryWrapper<Product>()
|
|
|
|
|
+ .eq(Product::getIsDeleted, 0)
|
|
|
|
|
+ .isNotNull(Product::getName)
|
|
|
|
|
+ .ne(Product::getName, ""));
|
|
|
|
|
|
|
|
- try {
|
|
|
|
|
- QdbResponse<SysGoodsPageResult> response = qdbClient.getGoodsApi().listSysGoodsPaged(request);
|
|
|
|
|
- SysGoodsPageResult pageResult = response.getData();
|
|
|
|
|
|
|
+ if (products.isEmpty()) {
|
|
|
|
|
+ log.info("无本地商品需要同步");
|
|
|
|
|
+ return;
|
|
|
|
|
+ }
|
|
|
|
|
|
|
|
- if (pageResult == null || pageResult.getData() == null || pageResult.getData().isEmpty()) {
|
|
|
|
|
- hasMore = false;
|
|
|
|
|
- break;
|
|
|
|
|
- }
|
|
|
|
|
|
|
+ log.info("开始逐条同步ERP商品: 共 {} 个本地商品", products.size());
|
|
|
|
|
+ int syncedCount = 0;
|
|
|
|
|
+ int missCount = 0;
|
|
|
|
|
+ int total = products.size();
|
|
|
|
|
|
|
|
- for (SysGoodsVO goods : pageResult.getData()) {
|
|
|
|
|
- upsertErpGoods(goods);
|
|
|
|
|
- syncedCount++;
|
|
|
|
|
- }
|
|
|
|
|
|
|
+ for (int i = 0; i < total; i++) {
|
|
|
|
|
+ Product product = products.get(i);
|
|
|
|
|
+ String goodsCode = product.getName();
|
|
|
|
|
|
|
|
- Integer total = pageResult.getTotal();
|
|
|
|
|
- if (total != null && pageNo * pageSize >= total) {
|
|
|
|
|
- hasMore = false;
|
|
|
|
|
- } else if (pageResult.getData().size() < pageSize) {
|
|
|
|
|
- hasMore = false;
|
|
|
|
|
|
|
+ try {
|
|
|
|
|
+ SysGoodsQueryRequest request = SysGoodsQueryRequest.builder()
|
|
|
|
|
+ .pageIndex(1)
|
|
|
|
|
+ .pageSize(1)
|
|
|
|
|
+ .goodsCode(goodsCode)
|
|
|
|
|
+ .status(1)
|
|
|
|
|
+ .combination(0)
|
|
|
|
|
+ .build();
|
|
|
|
|
+
|
|
|
|
|
+ QdbResponse<List<SysGoodsVO>> response = qdbClient.getGoodsApi()
|
|
|
|
|
+ .listSysGoods(request);
|
|
|
|
|
+ List<SysGoodsVO> goodsList = response.getData();
|
|
|
|
|
+
|
|
|
|
|
+ if (goodsList != null && !goodsList.isEmpty()) {
|
|
|
|
|
+ for (SysGoodsVO goods : goodsList) {
|
|
|
|
|
+ if (goods.getGoodsId() == null) {
|
|
|
|
|
+ log.warn("ERP返回的商品缺少goodsId, 跳过: goodsCode={}", goodsCode);
|
|
|
|
|
+ continue;
|
|
|
|
|
+ }
|
|
|
|
|
+ upsertErpGoods(goods);
|
|
|
|
|
+ syncedCount++;
|
|
|
|
|
+ }
|
|
|
} else {
|
|
} else {
|
|
|
- pageNo++;
|
|
|
|
|
|
|
+ log.debug("ERP中未找到商品: goodsCode={}, productId={}", goodsCode, product.getId());
|
|
|
|
|
+ missCount++;
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
} catch (QdbException e) {
|
|
} catch (QdbException e) {
|
|
|
- log.error("同步ERP商品失败: pageNo={}, error={}", pageNo, e.getMessage());
|
|
|
|
|
- throw new BusinessException(500, "ERP商品同步失败: " + e.getMessage());
|
|
|
|
|
|
|
+ log.error("查询ERP商品失败: goodsCode={}, productId={}, error={}",
|
|
|
|
|
+ goodsCode, product.getId(), e.getMessage());
|
|
|
|
|
+ }
|
|
|
|
|
+
|
|
|
|
|
+ if ((i + 1) % 10 == 0 && i + 1 < total) {
|
|
|
|
|
+ try {
|
|
|
|
|
+ Thread.sleep(200);
|
|
|
|
|
+ } catch (InterruptedException e) {
|
|
|
|
|
+ Thread.currentThread().interrupt();
|
|
|
|
|
+ break;
|
|
|
|
|
+ }
|
|
|
}
|
|
}
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
- log.info("ERP商品同步完成: 共同步 {} 条", syncedCount);
|
|
|
|
|
|
|
+ log.info("ERP商品同步完成: 处理 {} 条, 命中 {} 条, 未找到 {} 条", total, syncedCount, missCount);
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
@Override
|
|
@Override
|
|
@@ -109,14 +128,12 @@ public class ErpGoodsServiceImpl extends ServiceImpl<ErpGoodsMapper, ErpGoods> i
|
|
|
throw new BusinessException(404, "商品不存在");
|
|
throw new BusinessException(404, "商品不存在");
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
- // 检查 ERP 商品是否存在
|
|
|
|
|
ErpGoods erpGoods = getOne(new LambdaQueryWrapper<ErpGoods>()
|
|
ErpGoods erpGoods = getOne(new LambdaQueryWrapper<ErpGoods>()
|
|
|
.eq(ErpGoods::getErpGoodsId, erpGoodsId));
|
|
.eq(ErpGoods::getErpGoodsId, erpGoodsId));
|
|
|
if (erpGoods == null) {
|
|
if (erpGoods == null) {
|
|
|
throw new BusinessException(404, "ERP商品不存在,请先同步ERP商品数据");
|
|
throw new BusinessException(404, "ERP商品不存在,请先同步ERP商品数据");
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
- // 检查是否已被其他本地商品绑定
|
|
|
|
|
List<Product> boundProducts = productMapper.selectList(new LambdaQueryWrapper<Product>()
|
|
List<Product> boundProducts = productMapper.selectList(new LambdaQueryWrapper<Product>()
|
|
|
.eq(Product::getErpGoodsId, erpGoodsId)
|
|
.eq(Product::getErpGoodsId, erpGoodsId)
|
|
|
.eq(Product::getIsDeleted, 0));
|
|
.eq(Product::getIsDeleted, 0));
|
|
@@ -147,10 +164,9 @@ public class ErpGoodsServiceImpl extends ServiceImpl<ErpGoodsMapper, ErpGoods> i
|
|
|
log.info("商品解除ERP商品关联: productId={}, productName={}", productId, product.getName());
|
|
log.info("商品解除ERP商品关联: productId={}, productName={}", productId, product.getName());
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
- /**
|
|
|
|
|
- * 插入或更新 ERP 商品记录(按 erp_goods_id 判断)
|
|
|
|
|
- */
|
|
|
|
|
private void upsertErpGoods(SysGoodsVO goods) {
|
|
private void upsertErpGoods(SysGoodsVO goods) {
|
|
|
|
|
+ log.info("同步ERP商品: goodsId={}, goodsCode={}, goodsName={}",
|
|
|
|
|
+ goods.getGoodsId(), goods.getGoodsCode(), goods.getGoodsName());
|
|
|
ErpGoods existing = getOne(new LambdaQueryWrapper<ErpGoods>()
|
|
ErpGoods existing = getOne(new LambdaQueryWrapper<ErpGoods>()
|
|
|
.eq(ErpGoods::getErpGoodsId, goods.getGoodsId()));
|
|
.eq(ErpGoods::getErpGoodsId, goods.getGoodsId()));
|
|
|
|
|
|
|
@@ -171,6 +187,12 @@ public class ErpGoodsServiceImpl extends ServiceImpl<ErpGoodsMapper, ErpGoods> i
|
|
|
existing.setArticleNo(goods.getArticleNo());
|
|
existing.setArticleNo(goods.getArticleNo());
|
|
|
existing.setPicPath(goods.getPicPath());
|
|
existing.setPicPath(goods.getPicPath());
|
|
|
existing.setWeight(goods.getWeight());
|
|
existing.setWeight(goods.getWeight());
|
|
|
|
|
+ existing.setBarCode(goods.getBarCodeList() != null && !goods.getBarCodeList().isEmpty()
|
|
|
|
|
+ ? JSON.toJSONString(goods.getBarCodeList()) : null);
|
|
|
|
|
+ if (goods.getModifyDate() != null) {
|
|
|
|
|
+ existing.setModifyDate(goods.getModifyDate().toInstant()
|
|
|
|
|
+ .atZone(ZoneId.systemDefault()).toLocalDateTime());
|
|
|
|
|
+ }
|
|
|
existing.setUpdateTime(LocalDateTime.now());
|
|
existing.setUpdateTime(LocalDateTime.now());
|
|
|
updateById(existing);
|
|
updateById(existing);
|
|
|
} else {
|
|
} else {
|
|
@@ -192,6 +214,12 @@ public class ErpGoodsServiceImpl extends ServiceImpl<ErpGoodsMapper, ErpGoods> i
|
|
|
erpGoods.setArticleNo(goods.getArticleNo());
|
|
erpGoods.setArticleNo(goods.getArticleNo());
|
|
|
erpGoods.setPicPath(goods.getPicPath());
|
|
erpGoods.setPicPath(goods.getPicPath());
|
|
|
erpGoods.setWeight(goods.getWeight());
|
|
erpGoods.setWeight(goods.getWeight());
|
|
|
|
|
+ erpGoods.setBarCode(goods.getBarCodeList() != null && !goods.getBarCodeList().isEmpty()
|
|
|
|
|
+ ? JSON.toJSONString(goods.getBarCodeList()) : null);
|
|
|
|
|
+ if (goods.getModifyDate() != null) {
|
|
|
|
|
+ erpGoods.setModifyDate(goods.getModifyDate().toInstant()
|
|
|
|
|
+ .atZone(ZoneId.systemDefault()).toLocalDateTime());
|
|
|
|
|
+ }
|
|
|
erpGoods.setStatus(1);
|
|
erpGoods.setStatus(1);
|
|
|
erpGoods.setCreateTime(LocalDateTime.now());
|
|
erpGoods.setCreateTime(LocalDateTime.now());
|
|
|
erpGoods.setUpdateTime(LocalDateTime.now());
|
|
erpGoods.setUpdateTime(LocalDateTime.now());
|