调度补齐卖家姓名和电话

This commit is contained in:
2026-05-18 13:31:29 +08:00
parent fb1a86f0e0
commit 457de72b27
12 changed files with 383 additions and 45 deletions

View File

@@ -17,11 +17,28 @@ public class HxrAdminProperties {
private boolean enabled = true;
/**
* 完整请求 URL含查询串与浏览器地址栏一致即可
* 订单列表基础 URL含分页等通用查询串各业务在代码中覆盖查询参数或使用独立 URL 配置
*/
private String orderSelectUrl =
"https://hxrdhoutai.hxrdsm.cn/app/admin/order/select?page=1&limit=90";
/**
* 未支付订单拉取 URL含 {@code status=0} 等业务筛选),供 {@link LBAdminPullScheduler#pullOrdersForUnPay} 使用。
*/
private String orderSelectUnPayUrl =
"https://hxrdhoutai.hxrdsm.cn/app/admin/order/select?page=1&limit=90&status=0";
/**
* 已支付订单拉取 URL含 {@code status=1}),供 {@link LBAdminPullScheduler#pullOrdersForUnPay} 使用。
*/
private String orderSelectPaidUrl =
"https://hxrdhoutai.hxrdsm.cn/app/admin/order/select?page=1&limit=90&status=1";
/**
* 定时将 hxrd 订单同步到 {@code lb_order_row} 时使用的租户 id未配置时跳过订单状态同步。
*/
private String syncTenantId = "TENANT_ID_CST_2026";
/**
* 请求头 Cookie 完整取值,例如 {@code PHPSID=xxxx}。非空时优先于 {@link #phpsid}。
*/

View File

@@ -7,6 +7,8 @@ public record HxrOrderRow(
long id,
Long oldId,
long sellerId,
String sellerName,
String sellerPhone,
long buyerId,
String orderSn,
String totalMoney,

View File

@@ -40,6 +40,14 @@ public class LbOrderRow implements Serializable {
@Schema(description = "卖家 id")
private Long sellerId;
@TableField("seller_name")
@Schema(description = "卖家姓名")
private String sellerName;
@TableField("seller_phone")
@Schema(description = "卖家电话")
private String sellerPhone;
@TableField("buyer_id")
@Schema(description = "买家 id")
private Long buyerId;

View File

@@ -1,9 +1,19 @@
package com.rj.mapper;
import com.baomidou.mybatisplus.annotation.InterceptorIgnore;
import com.baomidou.mybatisplus.core.mapper.BaseMapper;
import com.rj.entity.LbOrderRow;
import org.apache.ibatis.annotations.Mapper;
import org.apache.ibatis.annotations.Param;
import java.util.List;
@Mapper
public interface LbOrderRowMapper extends BaseMapper<LbOrderRow> {
/**
* 按订单 id主键插入或更新跳过租户行拦截避免 listByIds 因 tenant_id 过滤漏判导致重复插入。
*/
@InterceptorIgnore(tenantLine = "true")
int upsertBatch(@Param("list") List<LbOrderRow> list);
}

View File

@@ -3,16 +3,21 @@ package com.rj.scheduler;
import com.rj.config.AppConfig;
import com.rj.config.HxrAdminProperties;
import com.rj.service.HxrAdminOrderSelectService;
import com.rj.service.ILbOrderRowService;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.scheduling.annotation.Scheduled;
import org.springframework.stereotype.Component;
import java.util.Map;
import java.time.Clock;
import java.time.DayOfWeek;
import java.time.LocalDate;
import java.time.LocalTime;
import java.time.ZoneId;
import java.time.ZonedDateTime;
import java.time.format.DateTimeFormatter;
/**
* hxrd 后台订单列表定时拉取:每 50 分钟触发一次,仅工作日(周一至周五)且在每天 18:1023:59:59应用时区内真正执行。
@@ -22,11 +27,15 @@ import java.time.ZonedDateTime;
@RequiredArgsConstructor
public class LBAdminPullScheduler {
private static final long FIFTY_MINUTES_MS = 50L * 60L * 1000L;
private static final long FIFTY_MINUTES_MS = 30L * 60L * 1000L;
private static final long UnPay_MINUTES_MS = 20L * 60L * 1000L;
private static final DateTimeFormatter BUY_TIME_FMT = DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss");
private final AppConfig appConfig;
private final HxrAdminProperties hxrAdminProperties;
private final HxrAdminOrderSelectService hxrAdminOrderSelectService;
private final ILbOrderRowService lbOrderRowService;
private final Clock clock;
@Scheduled(
@@ -63,4 +72,80 @@ public class LBAdminPullScheduler {
log.error("未寄卖 admin 订单拉取失败", e);
}
}
private static final int HXR_ORDER_STATUS_UNPAID = 0;
private static final int HXR_ORDER_STATUS_PAID = 1;
/**
* 未支付/已支付订单同步:工作日每天 11:0015:00应用时区仅在窗口内真正执行。
*/
@Scheduled(
fixedRate = UnPay_MINUTES_MS,
initialDelayString = "${hxr.admin.pull-initial-delay-ms:0}")
public void pullOrdersForUnPay() {
try {
if (!appConfig.getScheduler().isStart()) {
log.debug("全局调度未启用,跳过 未支付 订单拉取");
return;
}
if (!hxrAdminProperties.isEnabled()) {
log.debug("hxr.admin.enabled=false跳过订单拉取");
return;
}
ZoneId zone = ZoneId.of(appConfig.getTimezone());
ZonedDateTime nowZdt = ZonedDateTime.now(clock.withZone(zone));
DayOfWeek dow = nowZdt.getDayOfWeek();
if (dow == DayOfWeek.SATURDAY || dow == DayOfWeek.SUNDAY) {
log.debug("当前为周末 {},跳过 未支付 订单拉取", dow);
return;
}
LocalTime now = nowZdt.toLocalTime();
LocalTime windowStart = LocalTime.of(11, 0);
LocalTime windowEnd = LocalTime.of(15, 0);
if (now.isBefore(windowStart) || now.isAfter(windowEnd)) {
log.debug("当前时刻 {} 不在窗口 {}{},跳过 未支付 订单拉取", now, windowStart, windowEnd);
return;
}
String tenantId = hxrAdminProperties.getSyncTenantId();
if (tenantId == null || tenantId.isBlank()) {
log.warn("hxr.admin.sync-tenant-id 未配置,跳过订单状态同步");
return;
}
LocalDate today = nowZdt.toLocalDate();
String buyTimeStart = today.atStartOfDay().format(BUY_TIME_FMT);
String buyTimeEnd = today.atTime(23, 59, 59).format(BUY_TIME_FMT);
String tid = tenantId.trim();
syncOrdersByHxrStatus(tid, buyTimeStart, buyTimeEnd, HXR_ORDER_STATUS_UNPAID, "未支付");
syncOrdersByHxrStatus(tid, buyTimeStart, buyTimeEnd, HXR_ORDER_STATUS_PAID, "已支付");
} catch (Exception e) {
log.error("订单状态同步失败", e);
}
}
private void syncOrdersByHxrStatus(
String tenantId, String buyTimeStart, String buyTimeEnd, int hxrOrderStatus, String label) {
log.info(
"开始执行 {} 订单同步 status={} tenantId={} buyTime={}{}",
label,
hxrOrderStatus,
tenantId,
buyTimeStart,
buyTimeEnd);
Map<String, Object> syncResult =
lbOrderRowService.syncFromHxrAdmin(buyTimeStart, buyTimeEnd, tenantId, null, hxrOrderStatus);
if (Boolean.TRUE.equals(syncResult.get("success"))) {
log.info(
"{}订单同步完成 synced={} remoteCount={}",
label,
syncResult.get("synced"),
syncResult.get("remoteCount"));
} else {
log.warn("{}订单同步失败: {}", label, syncResult.get("message"));
}
}
}

View File

@@ -40,6 +40,13 @@ public class HxrAdminOrderSelectService {
return fetchOrderSelectInternal(properties.getOrderSelectUrl());
}
/**
* 拉取未支付订单,使用 {@link HxrAdminProperties#getOrderSelectUnPayUrl()}。
*/
public Optional<HxrOrderSelectResponse> fetchUnpaidOrderSelect() throws Exception {
return fetchOrderSelectInternal(properties.getOrderSelectUnPayUrl());
}
/**
* 按购买时间区间、转卖状态等条件拉取订单列表(在配置的 {@code orderSelectUrl} 上覆盖查询参数)。
*
@@ -62,6 +69,24 @@ public class HxrAdminOrderSelectService {
return fetchOrderSelectInternal(buildOrderSelectUrl(buyTimeStart, buyTimeEnd, isResell, page));
}
/**
* 按购买时间区间及页码拉取未支付订单({@code status=0},基于 {@link HxrAdminProperties#getOrderSelectUnPayUrl()})。
*/
public Optional<HxrOrderSelectResponse> fetchUnpaidOrderSelect(
String buyTimeStart, String buyTimeEnd, int page) throws Exception {
return fetchOrderSelectInternal(
buildStatusOrderSelectUrl(properties.getOrderSelectUnPayUrl(), buyTimeStart, buyTimeEnd, page));
}
/**
* 按购买时间区间及页码拉取已支付订单({@code status=1},基于 {@link HxrAdminProperties#getOrderSelectPaidUrl()})。
*/
public Optional<HxrOrderSelectResponse> fetchPaidOrderSelect(
String buyTimeStart, String buyTimeEnd, int page) throws Exception {
return fetchOrderSelectInternal(
buildStatusOrderSelectUrl(properties.getOrderSelectPaidUrl(), buyTimeStart, buyTimeEnd, page));
}
private Optional<HxrOrderSelectResponse> fetchOrderSelectInternal(String requestUri) throws Exception {
String cookieHeader = properties.resolveCookieHeader();
if (cookieHeader == null || cookieHeader.isBlank()) {
@@ -115,16 +140,35 @@ public class HxrAdminOrderSelectService {
return b.build().encode().toUriString();
}
private String buildStatusOrderSelectUrl(String baseUrl, String buyTimeStart, String buyTimeEnd, int page) {
UriComponentsBuilder b = UriComponentsBuilder.fromUriString(baseUrl);
b.replaceQueryParam("buy_time[0]", buyTimeStart == null ? "" : buyTimeStart);
b.replaceQueryParam("buy_time[1]", buyTimeEnd == null ? "" : buyTimeEnd);
b.replaceQueryParam("page", Math.max(1, page));
return b.build().encode().toUriString();
}
/**
* 拉取并逐条打日志(一行一条 JSON
*/
public void fetchAndLogEachOrder() throws Exception {
Optional<HxrOrderSelectResponse> opt = fetchOrderSelect();
fetchAndLogEachOrder(fetchOrderSelect(), "未寄卖");
}
/**
* 拉取未支付订单({@code status=0})并逐条打日志。
*/
public void fetchAndLogUnpaidOrders() throws Exception {
fetchAndLogEachOrder(fetchUnpaidOrderSelect(), "未支付");
}
private void fetchAndLogEachOrder(
Optional<HxrOrderSelectResponse> opt, String label) throws Exception {
if (opt.isEmpty()) {
return;
}
HxrOrderSelectResponse body = opt.get();
log.info("未寄卖 order/select ok count={} allMoney={}", body.count(), body.allMoney());
log.info("{} order/select ok count={} allMoney={}", label, body.count(), body.allMoney());
for (HxrOrderRow row : body.data()) {
log.info("hxr order row {}", JSON.writeValueAsString(row));
}

View File

@@ -34,6 +34,17 @@ public interface ILbOrderRowService extends IService<LbOrderRow> {
String tenantId,
Integer isResell);
/**
* 同 {@link #syncFromHxrAdmin(String, String, String, Integer)}{@code hxrOrderStatus} 非空时按后台
* {@code status} 筛选拉取(如 {@code 0} 未支付、{@code 1} 已支付),为 null 时使用通用订单列表 URL。
*/
Map<String, Object> syncFromHxrAdmin(
String buyTimeStart,
String buyTimeEnd,
String tenantId,
Integer isResell,
Integer hxrOrderStatus);
/**
* 按购买时间区间与租户查询明细,按天汇总为 {@code sum_data} 写入 {@code lb_order_row}。
*/

View File

@@ -5,10 +5,14 @@ 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.LbDepartmentUser;
import com.rj.entity.LbOrderRow;
import com.rj.mapper.LbOrderRowMapper;
import com.rj.service.HxrAdminOrderSelectService;
import com.rj.service.ILbDepartmentUserService;
import com.rj.service.ILbOrderRowService;
import com.rj.tenant.TenantContextHolder;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
@@ -20,11 +24,14 @@ import java.time.format.DateTimeFormatter;
import java.time.format.DateTimeParseException;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.HashSet;
import java.util.LinkedHashMap;
import java.util.List;
import java.util.Map;
import java.util.Optional;
import java.util.Set;
@Slf4j
@Service
public class LbOrderRowServiceImpl extends ServiceImpl<LbOrderRowMapper, LbOrderRow> implements ILbOrderRowService {
@@ -47,6 +54,9 @@ public class LbOrderRowServiceImpl extends ServiceImpl<LbOrderRowMapper, LbOrder
@Autowired
private HxrAdminOrderSelectService hxrAdminOrderSelectService;
@Autowired
private ILbDepartmentUserService lbDepartmentUserService;
@Override
public Map<String, Object> add(LbOrderRow entity) {
Map<String, Object> result = new HashMap<>();
@@ -224,6 +234,13 @@ public class LbOrderRowServiceImpl extends ServiceImpl<LbOrderRowMapper, LbOrder
@Transactional(rollbackFor = Exception.class)
public Map<String, Object> syncFromHxrAdmin(
String buyTimeStart, String buyTimeEnd, String tenantId, Integer isResell) {
return syncFromHxrAdmin(buyTimeStart, buyTimeEnd, tenantId, isResell, null);
}
@Override
@Transactional(rollbackFor = Exception.class)
public Map<String, Object> syncFromHxrAdmin(
String buyTimeStart, String buyTimeEnd, String tenantId, Integer isResell, Integer hxrOrderStatus) {
Map<String, Object> result = new HashMap<>();
try {
if (tenantId == null || tenantId.trim().isEmpty()) {
@@ -234,13 +251,15 @@ public class LbOrderRowServiceImpl extends ServiceImpl<LbOrderRowMapper, LbOrder
String tid = tenantId.trim();
String previousTenantId = TenantContextHolder.getTenantId();
TenantContextHolder.setTenantId(tid);
try {
HxrOrderSelectResponse firstBody = null;
int page = 1;
int totalSynced = 0;
while (true) {
Optional<HxrOrderSelectResponse> opt =
hxrAdminOrderSelectService.fetchOrderSelect(
buyTimeStart, buyTimeEnd, isResell, page);
fetchHxrOrderPage(buyTimeStart, buyTimeEnd, isResell, hxrOrderStatus, page);
if (opt.isEmpty()) {
if (page == 1) {
result.put("success", false);
@@ -273,9 +292,9 @@ public class LbOrderRowServiceImpl extends ServiceImpl<LbOrderRowMapper, LbOrder
for (HxrOrderRow row : rows) {
entities.add(toLbOrderRow(row, tid));
}
boolean ok = this.saveOrUpdateBatch(entities);
if (!ok) {
fillSellerInfoFromDepartmentUsers(entities, tid);
int upserted = upsertBatch(entities);
if (upserted < 0) {
result.put("success", false);
result.put("message", "" + page + " 页保存失败,已成功同步前 "
+ (page - 1) + " 页共 " + totalSynced + "");
@@ -285,7 +304,7 @@ public class LbOrderRowServiceImpl extends ServiceImpl<LbOrderRowMapper, LbOrder
result.put("pages", page - 1);
return result;
}
totalSynced += entities.size();
totalSynced += upserted;
if (rows.size() < HXR_ORDER_PAGE_SIZE ) {
break;
@@ -309,14 +328,40 @@ public class LbOrderRowServiceImpl extends ServiceImpl<LbOrderRowMapper, LbOrder
result.put("allMoney", firstBody.allMoney());
result.put("pages", page);
return result;
} finally {
if (previousTenantId != null) {
TenantContextHolder.setTenantId(previousTenantId);
} else {
TenantContextHolder.clear();
}
}
} catch (Exception e) {
result.put("success", false);
result.put("message", "同步异常:" + e.getMessage());
result.put("synced", 0);
log.error("syncFromHxrAdmin failed", e);
return result;
}
}
private Optional<HxrOrderSelectResponse> fetchHxrOrderPage(
String buyTimeStart,
String buyTimeEnd,
Integer isResell,
Integer hxrOrderStatus,
int page)
throws Exception {
if (hxrOrderStatus != null) {
if (hxrOrderStatus == 0) {
return hxrAdminOrderSelectService.fetchUnpaidOrderSelect(buyTimeStart, buyTimeEnd, page);
}
if (hxrOrderStatus == 1) {
return hxrAdminOrderSelectService.fetchPaidOrderSelect(buyTimeStart, buyTimeEnd, page);
}
}
return hxrAdminOrderSelectService.fetchOrderSelect(buyTimeStart, buyTimeEnd, isResell, page);
}
@Override
@Transactional(rollbackFor = Exception.class)
public Map<String, Object> generateDailySumData(
@@ -373,10 +418,11 @@ public class LbOrderRowServiceImpl extends ServiceImpl<LbOrderRowMapper, LbOrder
sumRows.add(buildDailySumRow(tid, entry.getKey(), entry.getValue(), nowStr));
}
boolean ok = this.saveOrUpdateBatch(sumRows);
int upserted = upsertBatch(sumRows);
boolean ok = upserted >= 0;
result.put("success", ok);
result.put("message", ok ? "按日汇总完成" : "保存失败");
result.put("generated", ok ? sumRows.size() : 0);
result.put("generated", ok ? upserted : 0);
result.put("sourceCount", details.size());
result.put("skippedNoBuyTime", skippedNoBuyTime);
if (ok) {
@@ -481,6 +527,78 @@ public class LbOrderRowServiceImpl extends ServiceImpl<LbOrderRowMapper, LbOrder
}
}
/**
* 按外部订单 id主键插入或更新同批重复 id 保留最后一条。
*
* @return 实际 upsert 条数;无有效 id 时返回 0失败返回 -1
*/
private int upsertBatch(List<LbOrderRow> entities) {
if (entities == null || entities.isEmpty()) {
return 0;
}
Map<Long, LbOrderRow> deduped = new LinkedHashMap<>();
for (LbOrderRow entity : entities) {
if (entity.getId() != null) {
deduped.put(entity.getId(), entity);
}
}
if (deduped.isEmpty()) {
return 0;
}
List<LbOrderRow> rows = new ArrayList<>(deduped.values());
try {
baseMapper.upsertBatch(rows);
return rows.size();
} catch (Exception e) {
log.error("lb_order_row upsertBatch failed, size={}", rows.size(), e);
return -1;
}
}
/**
* 按 seller_id 关联 lb_department_user.user_id用部门用户的 name、phone 填充卖方姓名与电话。
*/
private void fillSellerInfoFromDepartmentUsers(List<LbOrderRow> entities, String tenantId) {
if (entities == null || entities.isEmpty()) {
return;
}
Set<Long> sellerIds = new HashSet<>();
for (LbOrderRow entity : entities) {
if (entity.getSellerId() != null) {
sellerIds.add(entity.getSellerId());
}
}
if (sellerIds.isEmpty()) {
return;
}
List<String> userIdStrs = new ArrayList<>(sellerIds.size());
for (Long sellerId : sellerIds) {
userIdStrs.add(String.valueOf(sellerId));
}
LambdaQueryWrapper<LbDepartmentUser> w = new LambdaQueryWrapper<>();
w.eq(LbDepartmentUser::getTenantId, tenantId)
.in(LbDepartmentUser::getUserId, userIdStrs)
.orderByDesc(LbDepartmentUser::getUpdateTime)
.orderByDesc(LbDepartmentUser::getCreateTime);
List<LbDepartmentUser> users = lbDepartmentUserService.list(w);
Map<String, LbDepartmentUser> byUserId = new LinkedHashMap<>();
for (LbDepartmentUser user : users) {
if (user.getUserId() != null && !byUserId.containsKey(user.getUserId())) {
byUserId.put(user.getUserId(), user);
}
}
for (LbOrderRow entity : entities) {
if (entity.getSellerId() == null) {
continue;
}
LbDepartmentUser user = byUserId.get(String.valueOf(entity.getSellerId()));
if (user != null) {
entity.setSellerName(user.getName());
entity.setSellerPhone(user.getPhone());
}
}
}
private static LbOrderRow toLbOrderRow(HxrOrderRow row, String tenantId) {
LbOrderRow e = new LbOrderRow();
e.setId(row.id());
@@ -491,6 +609,8 @@ public class LbOrderRowServiceImpl extends ServiceImpl<LbOrderRowMapper, LbOrder
e.setTodayOrderCount(0);
e.setTodayUnresellCount(0);
e.setSellerId(row.sellerId());
e.setSellerName(row.sellerName());
e.setSellerPhone(row.sellerPhone());
e.setBuyerId(row.buyerId());
e.setOrderSn(row.orderSn());
e.setTotalMoney(parseMoney(row.totalMoney()));

View File

@@ -600,7 +600,7 @@ public class LbPurchaseApplyServiceImpl
continue;
}
try {
LocalDateTime vipTime = HxrAdminUserService.computeVipExpireTime(row.getApplyDate(), 3);
LocalDateTime vipTime = HxrAdminUserService.computeVipExpireTime(row.getApplyDate(), 2);
String vipTimeStr = HxrAdminUserService.formatVipTime(vipTime);
one.put("viptime", vipTimeStr);
@@ -940,7 +940,6 @@ public class LbPurchaseApplyServiceImpl
.orderByAsc(LbPurchaseApply::getApplyDate)
.orderByAsc(LbPurchaseApply::getId);
List<LbPurchaseApply> rows = this.list(queryWrapper);
Map<String, Integer> maxOrderByColleaguePhone = loadColleagueMaxOrderCache(rows);
LinkedHashMap<LocalDate, List<LbPurchaseApply>> grouped = new LinkedHashMap<>();
for (LbPurchaseApply row : rows) {
@@ -983,7 +982,7 @@ public class LbPurchaseApplyServiceImpl
createExportCell(row, 2, nullToEmpty(item.getApplyUser()), dataStyle);
createExportCell(row, 3, nullToEmpty(item.getApplyPhone()), dataStyle);
createExportCell(row, 4, formatPrivilegeRange(item), dataStyle);
createExportCell(row, 5, formatRecommender(item, maxOrderByColleaguePhone), dataStyle);
createExportCell(row, 5, formatRecommender(item), dataStyle);
createExportCell(row, 6, nullToEmpty(item.getColleaguePhone()), dataStyle);
createExportCell(row, 7, nullToEmpty(item.getTeamLeader()), dataStyle);
createExportCell(row, 8, formatActivationDate(item.getApplyDate()), dataStyle);
@@ -1026,25 +1025,6 @@ public class LbPurchaseApplyServiceImpl
}
}
private Map<String, Integer> loadColleagueMaxOrderCache(List<LbPurchaseApply> rows) {
Map<String, Integer> cache = new HashMap<>();
Set<String> phones = new HashSet<>();
for (LbPurchaseApply row : rows) {
if (row.getColleaguePhone() != null && !row.getColleaguePhone().trim().isEmpty()) {
phones.add(row.getColleaguePhone().trim());
}
}
for (String phone : phones) {
try {
Optional<HxrUserRow> userOpt = hxrAdminUserService.fetchFirstUserByMobile(phone);
userOpt.map(HxrUserRow::maxOrder).ifPresent(maxOrder -> cache.put(phone, maxOrder));
} catch (Exception ex) {
log.debug("导出时查询推荐人 max_order 失败phone={}", phone, ex);
}
}
return cache;
}
private static String formatDatePeopleLabel(LocalDate applyDate, int count) {
if (applyDate == null || applyDate.equals(LocalDate.MIN)) {
return "未知日期招商" + count + "";
@@ -1062,20 +1042,12 @@ public class LbPurchaseApplyServiceImpl
return start.format(PRIVILEGE_RANGE_FMT) + "" + endDate.format(PRIVILEGE_RANGE_FMT);
}
private static String formatRecommender(LbPurchaseApply item, Map<String, Integer> maxOrderByPhone) {
private static String formatRecommender(LbPurchaseApply item) {
String name = item.getColleagueName();
if (name == null || name.trim().isEmpty()) {
return "";
}
String trimmedName = name.trim();
String phone = item.getColleaguePhone() == null ? "" : item.getColleaguePhone().trim();
if (!phone.isEmpty()) {
Integer maxOrder = maxOrderByPhone.get(phone);
if (maxOrder != null) {
return trimmedName + " " + maxOrder;
}
}
return trimmedName;
return name.trim();
}
private static String formatActivationDate(LocalDate applyDate) {

View File

@@ -15,7 +15,9 @@ app:
# hxrd 后台订单列表LBAdminPullScheduler每 50 分钟一次,仅工作日 18:1023:59:59 执行,周末不跑)。默认关闭。
hxr:
admin:
enabled: false
enabled: true
# 未支付订单定时同步写入 lb_order_row 的租户 idLBAdminPullScheduler#pullOrdersForUnPay
sync-tenant-id: "TENANT_ID_CST_2026"
# 首次拉单延迟毫秒0 表示启动后尽快执行;集成测试会设为较大值避免与用例并发
pull-initial-delay-ms: 0
cookie: PHPSID=f3710baf6381da418aa832660ccb9d08

View File

@@ -0,0 +1,58 @@
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
<mapper namespace="com.rj.mapper.LbOrderRowMapper">
<!-- 外部订单 id 为全局主键,按 id upsert不受多租户拦截器影响 -->
<insert id="upsertBatch">
INSERT INTO lb_order_row (
id, old_id, tenant_id, data_type,
seller_id, seller_name, seller_phone,
buyer_id, order_sn, total_money,
pay_time, pay_img, status, is_resell, is_show,
consignee, phone, province, city, area, address,
merchandise_id, confirm_time, buy_time, created_at, updated_at,
today_total_money_sum, today_unresell_count, today_order_count
) VALUES
<foreach collection="list" item="item" separator=",">
(
#{item.id}, #{item.oldId}, #{item.tenantId}, #{item.dataType},
#{item.sellerId}, #{item.sellerName}, #{item.sellerPhone},
#{item.buyerId}, #{item.orderSn}, #{item.totalMoney},
#{item.payTime}, #{item.payImg}, #{item.status}, #{item.isResell}, #{item.isShow},
#{item.consignee}, #{item.phone}, #{item.province}, #{item.city}, #{item.area}, #{item.address},
#{item.merchandiseId}, #{item.confirmTime}, #{item.buyTime}, #{item.createdAt}, #{item.updatedAt},
#{item.todayTotalMoneySum}, #{item.todayUnresellCount}, #{item.todayOrderCount}
)
</foreach>
ON DUPLICATE KEY UPDATE
old_id = VALUES(old_id),
tenant_id = VALUES(tenant_id),
data_type = VALUES(data_type),
seller_id = VALUES(seller_id),
seller_name = VALUES(seller_name),
seller_phone = VALUES(seller_phone),
buyer_id = VALUES(buyer_id),
order_sn = VALUES(order_sn),
total_money = VALUES(total_money),
pay_time = VALUES(pay_time),
pay_img = VALUES(pay_img),
status = VALUES(status),
is_resell = VALUES(is_resell),
is_show = VALUES(is_show),
consignee = VALUES(consignee),
phone = VALUES(phone),
province = VALUES(province),
city = VALUES(city),
area = VALUES(area),
address = VALUES(address),
merchandise_id = VALUES(merchandise_id),
confirm_time = VALUES(confirm_time),
buy_time = VALUES(buy_time),
created_at = VALUES(created_at),
updated_at = VALUES(updated_at),
today_total_money_sum = VALUES(today_total_money_sum),
today_unresell_count = VALUES(today_unresell_count),
today_order_count = VALUES(today_order_count)
</insert>
</mapper>

View File

@@ -0,0 +1,9 @@
-- =============================================================================
-- 升级脚本:为 lb_order_row 表增加 seller_name、seller_phone 列
-- =============================================================================
SET NAMES utf8mb4;
ALTER TABLE `lb_order_row`
ADD COLUMN `seller_name` varchar(100) CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_ai_ci NULL DEFAULT NULL COMMENT '卖家姓名' AFTER `seller_id`,
ADD COLUMN `seller_phone` varchar(32) CHARACTER SET utf8mb4 COLLATE utf8mb4_0900_ai_ci NULL DEFAULT NULL COMMENT '卖家电话' AFTER `seller_name`;