|
|
@@ -85,23 +85,66 @@ public class DataSyncServiceImpl extends ServiceImpl<SyncRecordMapper, SyncRecor
|
|
|
record.setTotalCount(deviceList.size());
|
|
|
log.info("从哈哈平台获取到 {} 台设备", deviceList.size());
|
|
|
|
|
|
- // 3. 遍历设备列表,同步到本地数据库
|
|
|
+ // 3. 批量同步设备到本地数据库
|
|
|
+ List<String> sns = deviceList.stream().map(DeviceInfo::getId).filter(Objects::nonNull).toList();
|
|
|
+
|
|
|
+ // 3.1 批量查询已有设备(1 次 SELECT IN)
|
|
|
+ Map<String, Device> existingBySn = new HashMap<>();
|
|
|
+ if (!sns.isEmpty()) {
|
|
|
+ List<Device> existingDevices = deviceService.lambdaQuery()
|
|
|
+ .in(Device::getDeviceId, sns).list();
|
|
|
+ for (Device d : existingDevices) {
|
|
|
+ existingBySn.put(d.getDeviceId(), d);
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ // 3.2 分类新建/更新,批量操作
|
|
|
+ List<Device> toInsert = new ArrayList<>();
|
|
|
+ List<Device> toUpdate = new ArrayList<>();
|
|
|
+ List<SyncLog> syncLogs = new ArrayList<>();
|
|
|
+
|
|
|
for (DeviceInfo deviceInfo : deviceList) {
|
|
|
try {
|
|
|
- syncSingleDevice(record.getId(), deviceInfo);
|
|
|
+ Device existDevice = existingBySn.get(deviceInfo.getId());
|
|
|
+ if (existDevice != null) {
|
|
|
+ existDevice.setName(deviceInfo.getName());
|
|
|
+ existDevice.setAddress(deviceInfo.getAddress());
|
|
|
+ existDevice.setStatus("1".equals(deviceInfo.getStatus()) ? DeviceConstants.STATUS_ONLINE : DeviceOnlineStatus.OFFLINE.getCode());
|
|
|
+ toUpdate.add(existDevice);
|
|
|
+ syncLogs.add(buildSyncLog(record.getId(), SYNC_TYPE_DEVICE, deviceInfo.getId(),
|
|
|
+ deviceInfo.getName(), 1, "设备信息更新成功", null));
|
|
|
+ } else {
|
|
|
+ Device newDevice = new Device();
|
|
|
+ newDevice.setDeviceId(deviceInfo.getId());
|
|
|
+ newDevice.setName(deviceInfo.getName());
|
|
|
+ newDevice.setAddress(deviceInfo.getAddress());
|
|
|
+ newDevice.setStatus("1".equals(deviceInfo.getStatus()) ? DeviceConstants.STATUS_ONLINE : DeviceOnlineStatus.OFFLINE.getCode());
|
|
|
+ toInsert.add(newDevice);
|
|
|
+ // 先加入列表,saveBatch 后 ID 会自动回填
|
|
|
+ syncLogs.add(buildSyncLog(record.getId(), SYNC_TYPE_DEVICE, deviceInfo.getId(),
|
|
|
+ deviceInfo.getName(), 1, "设备新增成功", null));
|
|
|
+ }
|
|
|
successCount++;
|
|
|
} catch (Exception e) {
|
|
|
failCount++;
|
|
|
String errMsg = String.format("设备 %s 同步失败: %s", deviceInfo.getId(), e.getMessage());
|
|
|
errorMsg.append(errMsg).append("; ");
|
|
|
log.error(errMsg, e);
|
|
|
-
|
|
|
- // 记录失败日志
|
|
|
- saveSyncLog(record.getId(), SYNC_TYPE_DEVICE, deviceInfo.getId(),
|
|
|
- deviceInfo.getName(), 0, errMsg, JSON.toJSONString(deviceInfo));
|
|
|
+ syncLogs.add(buildSyncLog(record.getId(), SYNC_TYPE_DEVICE, deviceInfo.getId(),
|
|
|
+ deviceInfo.getName(), 0, errMsg, JSON.toJSONString(deviceInfo)));
|
|
|
}
|
|
|
}
|
|
|
|
|
|
+ // 3.3 批量保存/更新(各 1 次批量操作)
|
|
|
+ if (!toInsert.isEmpty()) {
|
|
|
+ deviceService.saveBatch(toInsert);
|
|
|
+ }
|
|
|
+ if (!toUpdate.isEmpty()) {
|
|
|
+ deviceService.updateBatchById(toUpdate);
|
|
|
+ }
|
|
|
+ // 3.4 批量保存同步日志
|
|
|
+ saveSyncLogBatch(syncLogs);
|
|
|
+
|
|
|
// 4. 更新同步记录
|
|
|
record.setSuccessCount(successCount);
|
|
|
record.setFailCount(failCount);
|
|
|
@@ -132,45 +175,11 @@ public class DataSyncServiceImpl extends ServiceImpl<SyncRecordMapper, SyncRecor
|
|
|
}
|
|
|
}
|
|
|
|
|
|
- /**
|
|
|
- * 同步单个设备
|
|
|
- */
|
|
|
- private void syncSingleDevice(Long recordId, DeviceInfo deviceInfo) {
|
|
|
- log.debug("同步设备: {} - {}", deviceInfo.getId(), deviceInfo.getName());
|
|
|
-
|
|
|
- // 查询本地是否已存在该设备
|
|
|
- Device existDevice = deviceService.getDeviceBySn(deviceInfo.getId());
|
|
|
-
|
|
|
- if (existDevice != null) {
|
|
|
- // 更新设备信息
|
|
|
- existDevice.setName(deviceInfo.getName());
|
|
|
- existDevice.setAddress(deviceInfo.getAddress());
|
|
|
- existDevice.setStatus("1".equals(deviceInfo.getStatus()) ? DeviceConstants.STATUS_ONLINE : DeviceOnlineStatus.OFFLINE.getCode());
|
|
|
- deviceService.updateById(existDevice);
|
|
|
-
|
|
|
- // 记录成功日志
|
|
|
- saveSyncLog(recordId, SYNC_TYPE_DEVICE, deviceInfo.getId(),
|
|
|
- deviceInfo.getName(), 1, "设备信息更新成功", null);
|
|
|
- } else {
|
|
|
- // 新增设备
|
|
|
- Device newDevice = new Device();
|
|
|
- newDevice.setDeviceId(deviceInfo.getId());
|
|
|
- newDevice.setName(deviceInfo.getName());
|
|
|
- newDevice.setAddress(deviceInfo.getAddress());
|
|
|
- newDevice.setStatus("1".equals(deviceInfo.getStatus()) ? DeviceConstants.STATUS_ONLINE : DeviceOnlineStatus.OFFLINE.getCode());
|
|
|
- deviceService.save(newDevice);
|
|
|
-
|
|
|
- // 记录成功日志
|
|
|
- saveSyncLog(recordId, SYNC_TYPE_DEVICE, deviceInfo.getId(),
|
|
|
- deviceInfo.getName(), 1, "设备新增成功", null);
|
|
|
- }
|
|
|
- }
|
|
|
-
|
|
|
/**
|
|
|
* 保存同步日志
|
|
|
*/
|
|
|
- private void saveSyncLog(Long recordId, String syncType, String dataId,
|
|
|
- String dataName, Integer status, String message, String detail) {
|
|
|
+ private SyncLog buildSyncLog(Long recordId, String syncType, String dataId,
|
|
|
+ String dataName, Integer status, String message, String detail) {
|
|
|
SyncLog syncLog = new SyncLog();
|
|
|
syncLog.setRecordId(recordId);
|
|
|
syncLog.setSyncType(syncType);
|
|
|
@@ -180,7 +189,15 @@ public class DataSyncServiceImpl extends ServiceImpl<SyncRecordMapper, SyncRecor
|
|
|
syncLog.setMessage(message);
|
|
|
syncLog.setDetail(detail);
|
|
|
syncLog.setCreateTime(LocalDateTime.now());
|
|
|
- syncLogMapper.insert(syncLog);
|
|
|
+ return syncLog;
|
|
|
+ }
|
|
|
+
|
|
|
+ private void saveSyncLogBatch(List<SyncLog> logs) {
|
|
|
+ if (logs != null && !logs.isEmpty()) {
|
|
|
+ for (SyncLog log : logs) {
|
|
|
+ syncLogMapper.insert(log);
|
|
|
+ }
|
|
|
+ }
|
|
|
}
|
|
|
|
|
|
@Override
|
|
|
@@ -297,28 +314,96 @@ public class DataSyncServiceImpl extends ServiceImpl<SyncRecordMapper, SyncRecor
|
|
|
break;
|
|
|
}
|
|
|
|
|
|
- // 3. 遍历商品列表,同步到本地数据库
|
|
|
+ // 3. 批量同步本页商品到本地数据库
|
|
|
for (Map<String, Object> productData : listData) {
|
|
|
totalCount++;
|
|
|
String code = productData.get("code") != null ? productData.get("code").toString() : null;
|
|
|
if (code != null) {
|
|
|
hahaCodes.add(code);
|
|
|
}
|
|
|
+ }
|
|
|
+
|
|
|
+ // 3.1 收集本页所有商品编码,批量查询已有商品(1 次 SELECT IN)
|
|
|
+ List<String> pageCodes = listData.stream()
|
|
|
+ .map(p -> p.get("code") != null ? p.get("code").toString() : null)
|
|
|
+ .filter(Objects::nonNull).toList();
|
|
|
+ Map<String, Product> existingByCode = new HashMap<>();
|
|
|
+ if (!pageCodes.isEmpty()) {
|
|
|
+ List<Product> existingProducts = productService.listByCodes(pageCodes);
|
|
|
+ for (Product p : existingProducts) {
|
|
|
+ existingByCode.put(p.getCode(), p);
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+ // 3.2 分类新建/更新
|
|
|
+ List<Product> toInsert = new ArrayList<>();
|
|
|
+ List<Product> toUpdate = new ArrayList<>();
|
|
|
+ List<SyncLog> pageSyncLogs = new ArrayList<>();
|
|
|
+
|
|
|
+ for (Map<String, Object> productData : listData) {
|
|
|
+ String code = productData.get("code") != null ? productData.get("code").toString() : null;
|
|
|
+ String name = productData.get("name") != null ? productData.get("name").toString() : "";
|
|
|
try {
|
|
|
- syncSingleProduct(record.getId(), productData);
|
|
|
+ if (code == null || code.isEmpty()) {
|
|
|
+ throw new BusinessException(400, "商品编码为空");
|
|
|
+ }
|
|
|
+
|
|
|
+ Product existProduct = existingByCode.get(code);
|
|
|
+ if (existProduct != null) {
|
|
|
+ existProduct.setName(name);
|
|
|
+ existProduct.setBarcode(productData.get("bar_code") != null ? productData.get("bar_code").toString() : null);
|
|
|
+ existProduct.setType(productData.get("type") != null ? productData.get("type").toString() : null);
|
|
|
+ existProduct.setPic(productData.get("pic") != null ? productData.get("pic").toString() : null);
|
|
|
+ existProduct.setPlanogram(productData.get("planogram") != null ? productData.get("planogram").toString() : null);
|
|
|
+ existProduct.setApplyStatus(productData.get("apply_status") != null ? productData.get("apply_status").toString() : null);
|
|
|
+ existProduct.setCostPrice(parseDouble(productData.get("cost_price")));
|
|
|
+ existProduct.setRetailPrice(parseDouble(productData.get("cprice")));
|
|
|
+ existProduct.setCustomerId(productData.get("customer_id") != null ? productData.get("customer_id").toString() : null);
|
|
|
+ existProduct.setSyncStatus(SyncConstants.STATUS_SYNCED);
|
|
|
+ existProduct.setSyncTime(LocalDateTime.now());
|
|
|
+ existProduct.setUpdateTime(LocalDateTime.now());
|
|
|
+ toUpdate.add(existProduct);
|
|
|
+ pageSyncLogs.add(buildSyncLog(record.getId(), SYNC_TYPE_PRODUCT, code, name, 1, "商品信息更新成功", null));
|
|
|
+ } else {
|
|
|
+ Product newProduct = new Product();
|
|
|
+ newProduct.setProductId(productData.get("product_id") != null ? productData.get("product_id").toString() : null);
|
|
|
+ newProduct.setCode(code);
|
|
|
+ newProduct.setName(name);
|
|
|
+ newProduct.setBarcode(productData.get("bar_code") != null ? productData.get("bar_code").toString() : null);
|
|
|
+ newProduct.setType(productData.get("type") != null ? productData.get("type").toString() : null);
|
|
|
+ newProduct.setPic(productData.get("pic") != null ? productData.get("pic").toString() : null);
|
|
|
+ newProduct.setPlanogram(productData.get("planogram") != null ? productData.get("planogram").toString() : null);
|
|
|
+ newProduct.setApplyStatus(productData.get("apply_status") != null ? productData.get("apply_status").toString() : null);
|
|
|
+ newProduct.setCostPrice(parseDouble(productData.get("cost_price")));
|
|
|
+ newProduct.setRetailPrice(parseDouble(productData.get("cprice")));
|
|
|
+ newProduct.setCustomerId(productData.get("customer_id") != null ? productData.get("customer_id").toString() : null);
|
|
|
+ newProduct.setSyncStatus(SyncConstants.STATUS_SYNCED);
|
|
|
+ newProduct.setSyncTime(LocalDateTime.now());
|
|
|
+ newProduct.setIsDeleted(CommonConstants.NOT_DELETED);
|
|
|
+ newProduct.setCreateTime(LocalDateTime.now());
|
|
|
+ newProduct.setUpdateTime(LocalDateTime.now());
|
|
|
+ toInsert.add(newProduct);
|
|
|
+ pageSyncLogs.add(buildSyncLog(record.getId(), SYNC_TYPE_PRODUCT, code, name, 1, "商品新增成功", null));
|
|
|
+ }
|
|
|
successCount++;
|
|
|
} catch (Exception e) {
|
|
|
failCount++;
|
|
|
- String name = productData.get("name") != null ? productData.get("name").toString() : "unknown";
|
|
|
String errMsg = String.format("商品 %s(%s) 同步失败: %s", code != null ? code : "unknown", name, e.getMessage());
|
|
|
errorMsg.append(errMsg).append("; ");
|
|
|
log.error(errMsg, e);
|
|
|
-
|
|
|
- // 记录失败日志
|
|
|
- saveSyncLog(record.getId(), SYNC_TYPE_PRODUCT, code != null ? code : "unknown", name, 0, errMsg, JSON.toJSONString(productData));
|
|
|
+ pageSyncLogs.add(buildSyncLog(record.getId(), SYNC_TYPE_PRODUCT, code != null ? code : "unknown", name, 0, errMsg, JSON.toJSONString(productData)));
|
|
|
}
|
|
|
}
|
|
|
|
|
|
+ // 3.3 批量保存/更新本页商品(各 1 次批量操作)
|
|
|
+ if (!toInsert.isEmpty()) {
|
|
|
+ productService.saveBatch(toInsert);
|
|
|
+ }
|
|
|
+ if (!toUpdate.isEmpty()) {
|
|
|
+ productService.updateBatchById(toUpdate);
|
|
|
+ }
|
|
|
+ saveSyncLogBatch(pageSyncLogs);
|
|
|
+
|
|
|
// 检查是否还有更多数据
|
|
|
Object totals = result.get("totals");
|
|
|
int total = totals != null ? Integer.parseInt(totals.toString()) : 0;
|
|
|
@@ -383,66 +468,6 @@ public class DataSyncServiceImpl extends ServiceImpl<SyncRecordMapper, SyncRecor
|
|
|
}
|
|
|
}
|
|
|
|
|
|
- /**
|
|
|
- * 同步单个商品
|
|
|
- */
|
|
|
- private void syncSingleProduct(Long recordId, Map<String, Object> productData) {
|
|
|
- String code = productData.get("code") != null ? productData.get("code").toString() : null;
|
|
|
- String name = productData.get("name") != null ? productData.get("name").toString() : "";
|
|
|
-
|
|
|
- log.debug("同步商品: {} - {}", code, name);
|
|
|
-
|
|
|
- if (code == null || code.isEmpty()) {
|
|
|
- throw new BusinessException(400, "商品编码为空");
|
|
|
- }
|
|
|
-
|
|
|
- // 查询本地是否已存在该商品
|
|
|
- Product existProduct = productService.getProductByCode(code);
|
|
|
-
|
|
|
- if (existProduct != null) {
|
|
|
- // 更新商品信息
|
|
|
- existProduct.setName(name);
|
|
|
- existProduct.setBarcode(productData.get("bar_code") != null ? productData.get("bar_code").toString() : null);
|
|
|
- existProduct.setType(productData.get("type") != null ? productData.get("type").toString() : null);
|
|
|
- existProduct.setPic(productData.get("pic") != null ? productData.get("pic").toString() : null);
|
|
|
- existProduct.setPlanogram(productData.get("planogram") != null ? productData.get("planogram").toString() : null);
|
|
|
- existProduct.setApplyStatus(productData.get("apply_status") != null ? productData.get("apply_status").toString() : null);
|
|
|
- existProduct.setCostPrice(parseDouble(productData.get("cost_price")));
|
|
|
- existProduct.setRetailPrice(parseDouble(productData.get("cprice")));
|
|
|
- existProduct.setCustomerId(productData.get("customer_id") != null ? productData.get("customer_id").toString() : null);
|
|
|
- existProduct.setSyncStatus(SyncConstants.STATUS_SYNCED);
|
|
|
- existProduct.setSyncTime(LocalDateTime.now());
|
|
|
- existProduct.setUpdateTime(LocalDateTime.now());
|
|
|
- productService.updateById(existProduct);
|
|
|
-
|
|
|
- // 记录成功日志
|
|
|
- saveSyncLog(recordId, SYNC_TYPE_PRODUCT, code, name, 1, "商品信息更新成功", null);
|
|
|
- } else {
|
|
|
- // 新增商品
|
|
|
- Product newProduct = new Product();
|
|
|
- newProduct.setProductId(productData.get("product_id") != null ? productData.get("product_id").toString() : null);
|
|
|
- newProduct.setCode(code);
|
|
|
- newProduct.setName(name);
|
|
|
- newProduct.setBarcode(productData.get("bar_code") != null ? productData.get("bar_code").toString() : null);
|
|
|
- newProduct.setType(productData.get("type") != null ? productData.get("type").toString() : null);
|
|
|
- newProduct.setPic(productData.get("pic") != null ? productData.get("pic").toString() : null);
|
|
|
- newProduct.setPlanogram(productData.get("planogram") != null ? productData.get("planogram").toString() : null);
|
|
|
- newProduct.setApplyStatus(productData.get("apply_status") != null ? productData.get("apply_status").toString() : null);
|
|
|
- newProduct.setCostPrice(parseDouble(productData.get("cost_price")));
|
|
|
- newProduct.setRetailPrice(parseDouble(productData.get("cprice")));
|
|
|
- newProduct.setCustomerId(productData.get("customer_id") != null ? productData.get("customer_id").toString() : null);
|
|
|
- newProduct.setSyncStatus(SyncConstants.STATUS_SYNCED);
|
|
|
- newProduct.setSyncTime(LocalDateTime.now());
|
|
|
- newProduct.setIsDeleted(CommonConstants.NOT_DELETED);
|
|
|
- newProduct.setCreateTime(LocalDateTime.now());
|
|
|
- newProduct.setUpdateTime(LocalDateTime.now());
|
|
|
- productService.save(newProduct);
|
|
|
-
|
|
|
- // 记录成功日志
|
|
|
- saveSyncLog(recordId, SYNC_TYPE_PRODUCT, code, name, 1, "商品新增成功", null);
|
|
|
- }
|
|
|
- }
|
|
|
-
|
|
|
/**
|
|
|
* 解析Double值
|
|
|
*/
|