Files
smartDriveEE/src/main/java/com/rj/service/impl/LbOrderRowServiceImpl.java

516 lines
20 KiB
Java
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

package com.rj.service.impl;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.rj.dto.hxr.HxrOrderRow;
import com.rj.dto.hxr.HxrOrderSelectResponse;
import com.rj.entity.LbOrderRow;
import com.rj.mapper.LbOrderRowMapper;
import com.rj.service.HxrAdminOrderSelectService;
import com.rj.service.ILbOrderRowService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import java.math.BigDecimal;
import java.time.LocalDate;
import java.time.LocalDateTime;
import java.time.format.DateTimeFormatter;
import java.time.format.DateTimeParseException;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.LinkedHashMap;
import java.util.List;
import java.util.Map;
import java.util.Optional;
@Service
public class LbOrderRowServiceImpl extends ServiceImpl<LbOrderRowMapper, LbOrderRow> implements ILbOrderRowService {
/** 与 hxr.admin.order-select-url 中 {@code limit} 一致,用于判断是否还有下一页 */
private static final int HXR_ORDER_PAGE_SIZE = 90;
/** 从第三方同步的订单明细默认 data_type */
private static final String SYNC_DATA_TYPE_DETAIL = "detail_data";
private static final String SUM_DATA_TYPE = "sum_data";
private static final long SUM_PLACEHOLDER_USER_ID = 10000L;
private static final String SUM_ORDER_SN = "order_sn_10000";
private static final DateTimeFormatter DAY_TIME_FMT = DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss");
private static final DateTimeFormatter DAY_FMT = DateTimeFormatter.ofPattern("yyyy-MM-dd");
@Autowired
private HxrAdminOrderSelectService hxrAdminOrderSelectService;
@Override
public Map<String, Object> add(LbOrderRow entity) {
Map<String, Object> result = new HashMap<>();
try {
if (entity.getId() == null) {
result.put("success", false);
result.put("message", "id订单 id不能为空");
return result;
}
if (entity.getTenantId() == null || entity.getTenantId().trim().isEmpty()) {
result.put("success", false);
result.put("message", "tenantId不能为空");
return result;
}
if (entity.getSellerId() == null) {
result.put("success", false);
result.put("message", "sellerId不能为空");
return result;
}
if (entity.getBuyerId() == null) {
result.put("success", false);
result.put("message", "buyerId不能为空");
return result;
}
if (entity.getOrderSn() == null || entity.getOrderSn().trim().isEmpty()) {
result.put("success", false);
result.put("message", "orderSn不能为空");
return result;
}
if (entity.getMerchandiseId() == null) {
result.put("success", false);
result.put("message", "merchandiseId不能为空");
return result;
}
if (this.getById(entity.getId()) != null) {
result.put("success", false);
result.put("message", "该订单 id 已存在");
return result;
}
entity.setTenantId(entity.getTenantId().trim());
entity.setOrderSn(entity.getOrderSn().trim());
if (entity.getStatus() == null) {
entity.setStatus(0);
}
if (entity.getIsResell() == null) {
entity.setIsResell(0);
}
if (entity.getIsShow() == null) {
entity.setIsShow(0);
}
boolean ok = this.save(entity);
result.put("success", ok);
result.put("message", ok ? "新增成功" : "新增失败");
if (ok) {
result.put("data", this.getById(entity.getId()));
}
return result;
} catch (Exception e) {
result.put("success", false);
result.put("message", "新增异常:" + e.getMessage());
return result;
}
}
@Override
public Map<String, Object> update(LbOrderRow entity) {
Map<String, Object> result = new HashMap<>();
try {
if (entity.getId() == null) {
result.put("success", false);
result.put("message", "id不能为空");
return result;
}
if (this.getById(entity.getId()) == null) {
result.put("success", false);
result.put("message", "记录不存在");
return result;
}
boolean ok = this.updateById(entity);
result.put("success", ok);
result.put("message", ok ? "编辑成功" : "编辑失败");
if (ok) {
result.put("data", this.getById(entity.getId()));
}
return result;
} catch (Exception e) {
result.put("success", false);
result.put("message", "编辑异常:" + e.getMessage());
return result;
}
}
@Override
public Map<String, Object> deleteById(Long id) {
Map<String, Object> result = new HashMap<>();
try {
boolean ok = this.removeById(id);
result.put("success", ok);
result.put("message", ok ? "删除成功" : "删除失败");
return result;
} catch (Exception e) {
result.put("success", false);
result.put("message", "删除异常:" + e.getMessage());
return result;
}
}
@Override
public Map<String, Object> pageQuery(
Integer current,
Integer size,
String isResell,
String dataType,
String orderSn,
String phone,
Long buyerId,
Long sellerId,
Integer status,
Long merchandiseId) {
Map<String, Object> result = new HashMap<>();
try {
if (current == null || current < 1) {
current = 1;
}
if (size == null || size < 1) {
size = 10;
}
LambdaQueryWrapper<LbOrderRow> w = new LambdaQueryWrapper<>();
if (isResell != null && !isResell.trim().isEmpty()) {
w.eq(LbOrderRow::getIsResell, isResell.trim());
}
if (dataType != null && !dataType.trim().isEmpty()) {
w.eq(LbOrderRow::getDataType, dataType.trim());
}
if (orderSn != null && !orderSn.trim().isEmpty()) {
w.like(LbOrderRow::getOrderSn, orderSn.trim());
}
if (phone != null && !phone.trim().isEmpty()) {
w.like(LbOrderRow::getPhone, phone.trim());
}
if (buyerId != null) {
w.eq(LbOrderRow::getBuyerId, buyerId);
}
if (sellerId != null) {
w.eq(LbOrderRow::getSellerId, sellerId);
}
if (status != null) {
w.eq(LbOrderRow::getStatus, status);
}
if (merchandiseId != null) {
w.eq(LbOrderRow::getMerchandiseId, merchandiseId);
}
w.orderByDesc(LbOrderRow::getId);
Page<LbOrderRow> page = this.page(new Page<>(current, size), w);
result.put("success", true);
result.put("message", "查询成功");
result.put("data", page.getRecords());
result.put("total", page.getTotal());
result.put("current", page.getCurrent());
result.put("size", page.getSize());
result.put("pages", page.getPages());
return result;
} catch (Exception e) {
result.put("success", false);
result.put("message", "查询异常:" + e.getMessage());
return result;
}
}
@Override
@Transactional(rollbackFor = Exception.class)
public Map<String, Object> syncFromHxrAdmin(
String buyTimeStart, String buyTimeEnd, String tenantId, Integer isResell) {
Map<String, Object> result = new HashMap<>();
try {
if (tenantId == null || tenantId.trim().isEmpty()) {
result.put("success", false);
result.put("message", "tenantId不能为空");
return result;
}
String tid = tenantId.trim();
HxrOrderSelectResponse firstBody = null;
int page = 1;
int totalSynced = 0;
while (true) {
Optional<HxrOrderSelectResponse> opt =
hxrAdminOrderSelectService.fetchOrderSelect(
buyTimeStart, buyTimeEnd, isResell, page);
if (opt.isEmpty()) {
if (page == 1) {
result.put("success", false);
result.put("message", "未拉取到订单(请检查 hxr.admin cookie/phpsid、网络或后台返回");
result.put("synced", 0);
return result;
}
result.put("success", false);
result.put("message", "" + page + " 页拉取失败,已成功同步前 "
+ (page - 1) + " 页共 " + totalSynced + "");
result.put("synced", totalSynced);
if (firstBody != null) {
result.put("remoteCount", firstBody.count());
result.put("allMoney", firstBody.allMoney());
}
result.put("pages", page - 1);
return result;
}
HxrOrderSelectResponse body = opt.get();
if (firstBody == null) {
firstBody = body;
}
List<HxrOrderRow> rows = body.data();
if (rows == null || rows.isEmpty()) {
break;
}
List<LbOrderRow> entities = new ArrayList<>(rows.size());
for (HxrOrderRow row : rows) {
entities.add(toLbOrderRow(row, tid));
}
boolean ok = this.saveOrUpdateBatch(entities);
if (!ok) {
result.put("success", false);
result.put("message", "" + page + " 页保存失败,已成功同步前 "
+ (page - 1) + " 页共 " + totalSynced + "");
result.put("synced", totalSynced);
result.put("remoteCount", firstBody.count());
result.put("allMoney", firstBody.allMoney());
result.put("pages", page - 1);
return result;
}
totalSynced += entities.size();
if (rows.size() < HXR_ORDER_PAGE_SIZE ) {
break;
}
page++;
}
if (totalSynced == 0) {
result.put("success", true);
result.put("message", "接口成功,时间范围内无订单数据");
result.put("synced", 0);
result.put("remoteCount", firstBody != null ? firstBody.count() : 0);
result.put("pages", page);
return result;
}
result.put("success", true);
result.put("message", "同步完成");
result.put("synced", totalSynced);
result.put("remoteCount", firstBody.count());
result.put("allMoney", firstBody.allMoney());
result.put("pages", page);
return result;
} catch (Exception e) {
result.put("success", false);
result.put("message", "同步异常:" + e.getMessage());
result.put("synced", 0);
return result;
}
}
@Override
@Transactional(rollbackFor = Exception.class)
public Map<String, Object> generateDailySumData(
String buyTimeStart, String buyTimeEnd, String tenantId) {
Map<String, Object> result = new HashMap<>();
try {
if (tenantId == null || tenantId.trim().isEmpty()) {
result.put("success", false);
result.put("message", "tenantId不能为空");
return result;
}
String tid = tenantId.trim();
LambdaQueryWrapper<LbOrderRow> w = new LambdaQueryWrapper<>();
w.eq(LbOrderRow::getTenantId, tid);
w.eq(LbOrderRow::getDataType, SYNC_DATA_TYPE_DETAIL);
if (buyTimeStart != null && !buyTimeStart.trim().isEmpty()) {
w.ge(LbOrderRow::getBuyTime, buyTimeStart.trim());
}
if (buyTimeEnd != null && !buyTimeEnd.trim().isEmpty()) {
w.le(LbOrderRow::getBuyTime, buyTimeEnd.trim());
}
List<LbOrderRow> details = this.list(w);
if (details.isEmpty()) {
result.put("success", true);
result.put("message", "时间范围内无明细数据");
result.put("generated", 0);
result.put("sourceCount", 0);
return result;
}
Map<LocalDate, List<LbOrderRow>> byDay = new LinkedHashMap<>();
int skippedNoBuyTime = 0;
for (LbOrderRow row : details) {
LocalDate day = parseBuyTimeToDate(row.getBuyTime());
if (day == null) {
skippedNoBuyTime++;
continue;
}
byDay.computeIfAbsent(day, k -> new ArrayList<>()).add(row);
}
if (byDay.isEmpty()) {
result.put("success", false);
result.put("message", "明细 buy_time 均无法解析为日期,无法汇总");
result.put("skippedNoBuyTime", skippedNoBuyTime);
return result;
}
String nowStr = LocalDateTime.now().format(DAY_TIME_FMT);
List<LbOrderRow> sumRows = new ArrayList<>(byDay.size());
for (Map.Entry<LocalDate, List<LbOrderRow>> entry : byDay.entrySet()) {
sumRows.add(buildDailySumRow(tid, entry.getKey(), entry.getValue(), nowStr));
}
boolean ok = this.saveOrUpdateBatch(sumRows);
result.put("success", ok);
result.put("message", ok ? "按日汇总完成" : "保存失败");
result.put("generated", ok ? sumRows.size() : 0);
result.put("sourceCount", details.size());
result.put("skippedNoBuyTime", skippedNoBuyTime);
if (ok) {
result.put("data", sumRows);
}
return result;
} catch (Exception e) {
result.put("success", false);
result.put("message", "汇总异常:" + e.getMessage());
result.put("generated", 0);
return result;
}
}
private LbOrderRow buildDailySumRow(
String tenantId, LocalDate day, List<LbOrderRow> dayRows, String nowStr) {
BigDecimal moneySum = BigDecimal.ZERO;
int unresellCount = 0;
for (LbOrderRow row : dayRows) {
if (row.getTotalMoney() != null) {
moneySum = moneySum.add(row.getTotalMoney());
}
if (row.getIsResell() == null || row.getIsResell() != 1) {
unresellCount++;
}
}
String payTime = day.atStartOfDay().format(DAY_TIME_FMT);
Long id = resolveSumRowId(tenantId, payTime);
LbOrderRow sum = new LbOrderRow();
sum.setId(id);
sum.setTenantId(tenantId);
sum.setDataType(SUM_DATA_TYPE);
sum.setTodayTotalMoneySum(moneySum);
sum.setTodayUnresellCount(unresellCount);
sum.setTodayOrderCount(dayRows.size());
sum.setSellerId(SUM_PLACEHOLDER_USER_ID);
sum.setBuyerId(SUM_PLACEHOLDER_USER_ID);
sum.setOrderSn(SUM_ORDER_SN);
sum.setPhone("18808852688");
sum.setConsignee("老板统计");
sum.setTotalMoney(moneySum);
sum.setIsResell(1);
sum.setStatus(1);
sum.setIsShow(1);
sum.setPayTime(payTime);
sum.setBuyTime(payTime);
sum.setMerchandiseId(0L);
sum.setCreatedAt(nowStr);
sum.setUpdatedAt(nowStr);
return sum;
}
/** 同一天、同一租户已存在 sum_data 则复用其 id否则生成占位 id */
private Long resolveSumRowId(String tenantId, String payTime) {
LambdaQueryWrapper<LbOrderRow> w = new LambdaQueryWrapper<>();
w.eq(LbOrderRow::getTenantId, tenantId)
.eq(LbOrderRow::getDataType, SUM_DATA_TYPE)
.eq(LbOrderRow::getPayTime, payTime)
.last("LIMIT 1");
LbOrderRow existing = this.getOne(w, false);
if (existing != null && existing.getId() != null) {
return existing.getId();
}
LocalDate day = LocalDate.parse(payTime.substring(0, 10), DAY_FMT);
long dayKey = day.getYear() * 10000L + day.getMonthValue() * 100L + day.getDayOfMonth();
int tenantSlot = Math.floorMod(tenantId.hashCode(), 10000);
return 10_000_000_000_000_000L + dayKey * 10_000L + tenantSlot;
}
private static LocalDate parseBuyTimeToDate(String buyTime) {
if (buyTime == null || buyTime.trim().isEmpty()) {
return null;
}
String text = buyTime.trim();
try {
return LocalDateTime.parse(text, DAY_TIME_FMT).toLocalDate();
} catch (DateTimeParseException ignored) {
// continue
}
try {
return LocalDate.parse(text.substring(0, Math.min(10, text.length())), DAY_FMT);
} catch (DateTimeParseException ignored) {
// continue
}
try {
return LocalDateTime.parse(text, DateTimeFormatter.ISO_LOCAL_DATE_TIME).toLocalDate();
} catch (DateTimeParseException e) {
return null;
}
}
private static BigDecimal parseMoney(String money) {
if (money == null || money.trim().isEmpty()) {
return null;
}
try {
return new BigDecimal(money.trim());
} catch (NumberFormatException e) {
return null;
}
}
private static LbOrderRow toLbOrderRow(HxrOrderRow row, String tenantId) {
LbOrderRow e = new LbOrderRow();
e.setId(row.id());
e.setOldId(row.oldId());
e.setTenantId(tenantId);
e.setDataType(SYNC_DATA_TYPE_DETAIL);
e.setTodayTotalMoneySum(BigDecimal.ZERO);
e.setTodayOrderCount(0);
e.setTodayUnresellCount(0);
e.setSellerId(row.sellerId());
e.setBuyerId(row.buyerId());
e.setOrderSn(row.orderSn());
e.setTotalMoney(parseMoney(row.totalMoney()));
e.setPayTime(row.payTime());
e.setPayImg(row.payImg());
e.setStatus(row.status());
e.setIsResell(row.isResell());
e.setIsShow(row.isShow());
e.setConsignee(row.consignee());
e.setPhone(row.phone());
e.setProvince(row.province());
e.setCity(row.city());
e.setArea(row.area());
e.setAddress(row.address());
e.setMerchandiseId(row.merchandiseId());
e.setConfirmTime(row.confirmTime());
e.setBuyTime(row.buyTime());
e.setCreatedAt(row.createdAt());
e.setUpdatedAt(row.updatedAt());
return e;
}
}