Compare commits

...

24 Commits

Author SHA1 Message Date
97ecfa3c79 Merge branch 'main' into dev 2025-10-22 09:07:45 +08:00
6398635707 预约订单参数加入下单流程。 2025-10-22 00:14:43 +08:00
a65fb441cb 思迅同步,改为出库时才扣减库存 2025-10-21 18:02:23 +08:00
2b03dee62d order info 增加预约下单的相关三字段 2025-10-21 16:27:24 +08:00
aeb3c0d029 思迅同步库存问题修改,新增取消订单和商家同意退货时触发库存回退到思迅 2025-10-21 15:19:03 +08:00
69b195322e 优化自动取消订单批次,改为分页 2025-10-21 15:18:46 +08:00
8058773aac 是否能禁止退货,关联到用户订单详情和商家订单列表详情接口 2025-10-21 11:15:49 +08:00
3f75c6f191 是否能禁止退货,关联到用户订单详情和商家订单列表 2025-10-21 11:15:20 +08:00
b60f4d9210 是否能禁止退货,关联到用户订单详情和商家订单列表 2025-10-21 11:07:38 +08:00
12523f13da 优化禁止退货的方法 2025-10-21 10:35:52 +08:00
986e8acb00 思迅同步库存问题修改,类型问题扣减货架号取值从product_number 2025-10-21 09:16:09 +08:00
2471d2b4c2 优化禁止退货的方法 2025-10-20 22:15:35 +08:00
66498ff82d 思迅同步库存问题修改,类型问题扣减为空问题日志 记录 2025-10-20 22:10:25 +08:00
4959f8ae64 编写禁止退货的方法 2025-10-20 21:54:50 +08:00
10bc17df0e 编写禁止退货的方法 2025-10-20 21:30:56 +08:00
501d3761e6 思迅同步库存问题修改,类型问题扣减问题 2025-10-20 21:15:23 +08:00
8abac2a5b3 思迅同步库存问题修改,类型问题扣减问题 2025-10-20 20:48:14 +08:00
56a62f6673 顺丰完成订单时候,发出催促确认收货的通知-> 微信 2025-10-20 17:26:12 +08:00
6637180cbf 思迅同步库存问题修改,类型问题扣减问题 2025-10-20 15:36:57 +08:00
e252475a34 思迅同步库存问题修改,类型问题扣减问题 2025-10-20 15:20:38 +08:00
71a2b5acb8 思迅同步库存问题修改,类型问题 2025-10-20 11:21:35 +08:00
a334cfce29 顺丰创建店铺,地址改成 去掉省市区的详细地址。 提现通知日志修改 2025-10-19 01:14:27 +08:00
d061510a5e 顺丰创建店铺,地址改成 去掉省市区的详细地址。 提现通知日志修改 2025-10-18 16:36:34 +08:00
b7701a8685 同一商户分账合并,增加打票机打印日志 2025-10-18 10:12:16 +08:00
31 changed files with 895 additions and 271 deletions

View File

@ -121,4 +121,8 @@ public class CommonConstant {
public static final Integer Agent_Level_2nd = 2;
// 订单配送预约状态1-立即配送2-预约配送
public static final Integer Order_Booking_State_LJ = 1;
public static final Integer Order_Booking_State_YY = 2;
}

View File

@ -110,6 +110,9 @@ public class LklOrderDraw {
@ApiModelProperty(value = "商户订单号", example = "MER2023100100001")
private String mer_order_no;
@ApiModelProperty(value = "商城订单Id")
private String order_id;
/**
* 结算流水号
*/

View File

@ -75,7 +75,7 @@ public class ShopOrderInfo implements Serializable {
@ApiModelProperty(value = "下单时间:检索使用")
private Long order_time;
@ApiModelProperty(value = "当前状态的处理时间")
@ApiModelProperty(value = "当前状态的处理时间,一般是确认收货时间")
private Long order_deal_time;
@ApiModelProperty(value = "买家删除(BOOL): 1-是; 0-否")
@ -204,6 +204,15 @@ public class ShopOrderInfo implements Serializable {
@ApiModelProperty(value = "拣货完成时间戳")
private Long order_picked_time;
@ApiModelProperty(value = "订单配送预约状态1-立即配送2-预约配送")
private Integer booking_state;
@ApiModelProperty(value = "预约送达起始时间格式如yyyy-MM-dd HH:mm:ss")
private Date booking_begin_time;
@ApiModelProperty(value = "预约送达截止时间格式如yyyy-MM-dd HH:mm:ss")
private Date booking_end_time;
@ApiModelProperty(value = "新建时间")
private Date created_at;

View File

@ -91,6 +91,6 @@ public class MchOrderInfoDTO implements Serializable {
private BigDecimal order_income_amount;
@ApiModelProperty(value = "两点距离,单位米")
private Integer distance;
// 快递鸟物流信息
@ApiModelProperty(value = "是否禁止退款1-是2-否;")
private Integer is_deny_return;
}

View File

@ -61,4 +61,7 @@ public class MchOrderItemDTO implements Serializable {
@ApiModelProperty(value = "退款金额:同意额度")
private BigDecimal order_item_return_agree_amount;
@ApiModelProperty(value = "是否禁止退款1-是2-否;")
private Integer is_deny_return;
}

View File

@ -62,7 +62,7 @@ public class LklSeparateWithTotalAmountDTO {
// 测试用例1: 所有参与方都参与分账符合比例要求
System.out.println("=== 测试用例1: 所有参与方都参与分账 ===");
LklSeparateWithTotalAmountDTO dto1 = new LklSeparateWithTotalAmountDTO();
dto1.setTotalSeparateAmount(5500); // 总金额100元(10000分)
dto1.setTotalSeparateAmount(1696); // 总金额100元(10000分)
dto1.setShippingFee(500);
// dto1.setRefCanSeparateAmount(1496);
dto1.setLklRatio(new BigDecimal("0.0025")); // 拉卡拉分账比例0.25%

View File

@ -33,7 +33,7 @@ public class AddressParseResultTO implements java.io.Serializable {
private String joinArea;
/**
* 详细地址
* 去掉省市县的详细地址
*/
private String detailAddress;

View File

@ -112,7 +112,7 @@ public class AddressUtil {
* System.out.println("详细地址: " + parsedAddress.getDetailAddress()); // 西山镇新安街粤桂花城1102号
*/
public static void main(String[] args) {
String fullAddress = "广西壮族自治区贵港市桂平市西山镇新安街粤桂花城1102号";
String fullAddress = "广西壮族自治区贵港市桂平市桂平西山镇新安街粤桂花城1102号";
AddressParseResultTO parsedAddress = AddressUtil.parseAddress(fullAddress);
System.out.println("省: " + parsedAddress.getProvince());
System.out.println("市: " + parsedAddress.getCity());

View File

@ -8,6 +8,7 @@ import java.text.SimpleDateFormat;
import java.time.*;
import java.time.format.DateTimeFormatter;
import java.time.format.DateTimeFormatterBuilder;
import java.time.format.DateTimeParseException;
import java.time.temporal.ChronoField;
import java.util.Calendar;
import java.util.Date;
@ -62,6 +63,121 @@ public class DateTimeUtils {
}
}
/**
* 验证日期时间字符串是否符合支持的日期时间格式
* 支持的格式包括
* - yyyy-MM-dd HH:mm ( 2023-12-01 09:30)
* - yyyy-MM-dd HH:mm:ss ( 2023-12-01 09:30:45)
* - yyyy-MM-dd HH:mm:ss.SSS ( 2023-12-01 09:30:45.123)
* - yyyy-MM-dd HH:mm:ss.SSSSSS ( 2023-12-01 09:30:45.123456)
* - yyyy-MM-dd HH:mm:ss.SSSSSSSSS ( 2023-12-01 09:30:45.123456789)
* - yyyy/MM/dd HH:mm:ss ( 2023/12/01 09:30:45)
* - yyyy.MM.dd HH:mm:ss ( 2023.12.01 09:30:45)
*
* @param dateTimeStr 待验证的日期时间字符串
* @return true表示符合日期时间格式false表示不符合
*/
public static LocalDateTime tryParseDateTime(String dateTimeStr) {
// 空值检查
if (dateTimeStr == null || dateTimeStr.trim().isEmpty()) {
return null;
}
dateTimeStr = dateTimeStr.trim();
// 使用正则表达式验证日期时间格式
// 支持多种日期分隔符和从分钟到纳秒的各种时间格式
String dateTimePattern = "^\\d{4}[-/.]\\d{1,2}[-/.]\\d{1,2}\\s+([01]?[0-9]|2[0-3]):[0-5][0-9](:[0-5][0-9])?(\\.\\d{1,9})?$";
if (!dateTimeStr.matches(dateTimePattern)) {
return null;
}
try {
// 尝试解析日期时间确保日期时间值有效
// 支持三种常见分隔符-, /, .
if (dateTimeStr.contains("-")) {
return parseDateTime(dateTimeStr, "yyyy-MM-dd HH:mm", "yyyy-MM-dd HH:mm:ss",
"yyyy-MM-dd HH:mm:ss.SSS", "yyyy-MM-dd HH:mm:ss.SSSSSS",
"yyyy-MM-dd HH:mm:ss.SSSSSSSSS");
} else if (dateTimeStr.contains("/")) {
return parseDateTime(dateTimeStr, "yyyy/MM/dd HH:mm", "yyyy/MM/dd HH:mm:ss",
"yyyy/MM/dd HH:mm:ss.SSS", "yyyy/MM/dd HH:mm:ss.SSSSSS",
"yyyy/MM/dd HH:mm:ss.SSSSSSSSS");
} else if (dateTimeStr.contains(".")) {
return parseDateTime(dateTimeStr, "yyyy.MM.dd HH:mm", "yyyy.MM.dd HH:mm:ss",
"yyyy.MM.dd HH:mm:ss.SSS", "yyyy.MM.dd HH:mm:ss.SSSSSS",
"yyyy.MM.dd HH:mm:ss.SSSSSSSSS");
}
return null;
} catch (Exception e) {
// 解析失败说明日期时间值无效
return null;
}
}
/**
* 验证并解析日期时间字符串为Date对象
* 支持的格式包括
* - yyyy-MM-dd HH:mm ( 2023-12-01 09:30)
* - yyyy-MM-dd HH:mm:ss ( 2023-12-01 09:30:45)
* - yyyy-MM-dd HH:mm:ss.SSS ( 2023-12-01 09:30:45.123)
* - yyyy-MM-dd HH:mm:ss.SSSSSS ( 2023-12-01 09:30:45.123456)
* - yyyy-MM-dd HH:mm:ss.SSSSSSSSS ( 2023-12-01 09:30:45.123456789)
* - yyyy/MM/dd HH:mm:ss ( 2023/12/01 09:30:45)
* - yyyy.MM.dd HH:mm:ss ( 2023.12.01 09:30:45)
*
* @param dateTimeStr 待解析的日期时间字符串
* @return 解析后的Date对象解析失败返回null
*/
public static Date tryParseDateTimeToDate(String dateTimeStr) {
LocalDateTime localDateTime = tryParseDateTime(dateTimeStr);
if (localDateTime != null) {
return Date.from(localDateTime.atZone(ZoneId.systemDefault()).toInstant());
}
return null;
}
/**
* 解析日期时间字符串
*
* @param dateTimeStr 日期时间字符串
* @param patterns 可能的日期时间格式模式
* @return 解析后的 LocalDateTime 对象
*/
private static LocalDateTime parseDateTime(String dateTimeStr, String... patterns) {
for (String pattern : patterns) {
try {
// 检查模式和字符串长度是否匹配
if (isMatchingDateTimePattern(dateTimeStr, pattern)) {
return LocalDateTime.parse(dateTimeStr, DateTimeFormatter.ofPattern(pattern));
}
} catch (Exception ignored) {
// 继续尝试下一个格式
}
}
// 如果所有格式都失败则抛出异常
throw new DateTimeParseException("无法解析日期时间字符串: " + dateTimeStr, dateTimeStr, 0);
}
/**
* 判断日期时间字符串是否与格式模式匹配
*
* @param dateTimeStr 日期时间字符串
* @param pattern 格式模式字符串
* @return 是否匹配
*/
private static boolean isMatchingDateTimePattern(String dateTimeStr, String pattern) {
try {
DateTimeFormatter formatter = DateTimeFormatter.ofPattern(pattern);
LocalDateTime.parse(dateTimeStr, formatter);
return true;
} catch (Exception e) {
return false;
}
}
/**
* 将多种日期格式转换为 yyyy-MM-dd
@ -233,8 +349,8 @@ public class DateTimeUtils {
/**
* 判断指定时间是否在两个时间点之间包含边界
*
* @param startTimeStr 开始时间字符串格式为 HH:mm
* @param endTimeStr 结束时间字符串格式为 HH:mm
* @param startTimeStr 开始时间字符串支持格式如 HH:mm, HH:mm:ss, HH:mm:ss.SSS
* @param endTimeStr 结束时间字符串支持格式如 HH:mm, HH:mm:ss, HH:mm:ss.SSS
* @param currentTime 要判断的时间点
* @return 如果在时间段内返回true否则返回false出现异常时返回false不影响主流程
*/
@ -247,11 +363,11 @@ public class DateTimeUtils {
return false;
}
// 解析开始时间
LocalTime startTime = LocalTime.parse(startTimeStr, DateTimeFormatter.ofPattern("HH:mm"));
// 解析开始时间 - 支持多种时间格式
LocalTime startTime = parseTime(startTimeStr);
// 解析结束时间
LocalTime endTime = LocalTime.parse(endTimeStr, DateTimeFormatter.ofPattern("HH:mm"));
// 解析结束时间 - 支持多种时间格式
LocalTime endTime = parseTime(endTimeStr);
// 获取当前时间的时间部分
LocalTime nowTime = currentTime.toLocalTime();
@ -273,18 +389,114 @@ public class DateTimeUtils {
}
}
/**
* 判断指定时间是否在两个时间点之间包含边界
*
* @param startTimeStr 开始时间字符串支持格式如 HH:mm, HH:mm:ss, HH:mm:ss.SSS
* @param endTimeStr 结束时间字符串支持格式如 HH:mm, HH:mm:ss, HH:mm:ss.SSS
* @param currentTime 要判断的时间点
* @return 如果在时间段内返回true否则返回false出现异常时返回false不影响主流程
*/
public static boolean isTimeInRange(String startTimeStr, String endTimeStr, Date currentTime) {
if (currentTime == null) {
log.warn("时间参数不能为空startTimeStr: {}, endTimeStr: {}, currentTime: null",
startTimeStr, endTimeStr);
return false;
}
// 将Date转换为LocalDateTime并调用已有的方法
LocalDateTime localDateTime = currentTime.toInstant().atZone(ZoneId.systemDefault()).toLocalDateTime();
return isTimeInRange(startTimeStr, endTimeStr, localDateTime);
}
/**
* 判断当前时间是否在两个时间点之间包含边界
*
* @param startTimeStr 开始时间字符串格式为 HH:mm
* @param endTimeStr 结束时间字符串格式为 HH:mm
* @param startTimeStr 开始时间字符串支持格式如 HH:mm, HH:mm:ss, HH:mm:ss.SSS
* @param endTimeStr 结束时间字符串支持格式如 HH:mm, HH:mm:ss, HH:mm:ss.SSS
* @return 如果在时间段内返回true否则返回false
* @throws IllegalArgumentException 当时间字符串格式不正确时抛出异常
*/
public static boolean isCurrentTimeInRange(String startTimeStr, String endTimeStr) {
return isTimeInRange(startTimeStr, endTimeStr, LocalDateTime.now());
}
/**
* 解析时间字符串支持多种时间格式
*
* @param timeStr 时间字符串支持格式如 HH:mm, HH:mm:ss, HH:mm:ss.SSS
* @return 解析后的 LocalTime 对象
*/
private static LocalTime parseTime(String timeStr) {
if (timeStr == null || timeStr.isEmpty()) {
throw new IllegalArgumentException("时间字符串不能为空");
}
try {
// 尝试使用不同的格式解析时间字符串
// 按照精度从高到低排序避免精度损失
DateTimeFormatter[] formatters = {
DateTimeFormatter.ofPattern("HH:mm:ss.SSSSSSSSS"), // 纳秒(9位)
DateTimeFormatter.ofPattern("HH:mm:ss.SSSSSS"), // 微秒(6位)
DateTimeFormatter.ofPattern("HH:mm:ss.SSS"), // 毫秒(3位)
DateTimeFormatter.ofPattern("HH:mm:ss"), //
DateTimeFormatter.ofPattern("HH:mm") // 分钟
};
// 先尝试精确匹配长度的格式
for (DateTimeFormatter formatter : formatters) {
try {
// 根据格式长度进行预筛选
String pattern = formatter.toString();
if (isMatchingTimePattern(timeStr, pattern)) {
return LocalTime.parse(timeStr, formatter);
}
} catch (Exception ignored) {
// 继续尝试下一个格式
}
}
// 如果精确匹配失败按原有方式尝试所有格式
for (DateTimeFormatter formatter : formatters) {
try {
return LocalTime.parse(timeStr, formatter);
} catch (Exception ignored) {
// 继续尝试下一个格式
}
}
// 如果所有格式都失败则抛出异常
throw new DateTimeParseException("无法解析时间字符串: " + timeStr, timeStr, 0);
} catch (Exception e) {
log.warn("时间解析失败timeStr: {}", timeStr, e);
throw e;
}
}
/**
* 判断时间字符串是否与格式模式匹配
*
* @param timeStr 时间字符串
* @param pattern 格式模式字符串
* @return 是否匹配
*/
private static boolean isMatchingTimePattern(String timeStr, String pattern) {
// 简单的长度匹配检查
switch (pattern) {
case "HH:mm":
return timeStr.length() == 5 && timeStr.charAt(2) == ':';
case "HH:mm:ss":
return timeStr.length() == 8 && timeStr.charAt(2) == ':' && timeStr.charAt(5) == ':';
case "HH:mm:ss.SSS":
return timeStr.length() == 12 && timeStr.charAt(2) == ':' && timeStr.charAt(5) == ':' && timeStr.charAt(8) == '.';
case "HH:mm:ss.SSSSSS":
return timeStr.length() == 15 && timeStr.charAt(2) == ':' && timeStr.charAt(5) == ':' && timeStr.charAt(8) == '.';
case "HH:mm:ss.SSSSSSSSS":
return timeStr.length() == 18 && timeStr.charAt(2) == ':' && timeStr.charAt(5) == ':' && timeStr.charAt(8) == '.';
default:
return false;
}
}
public static void main(String[] args) {
// System.out.println(convertLklDate("2021-02-19")); // 2025-01-02
@ -310,8 +522,9 @@ public class DateTimeUtils {
boolean isWorkTime = isCurrentTimeInRange("09:00", "22:36");
// 判断特定时间是否在夜间时间22:00-06:00
LocalDateTime testTime = LocalDateTime.of(2025, 1, 1, 23, 30);
boolean isNight = isTimeInRange("22:00", "06:00", testTime);
// LocalDateTime testTime = LocalDateTime.of(2025, 1, 1, 23, 30);
Date testTime = Date.from(LocalDateTime.of(2025, 10, 23, 21, 30).atZone(ZoneId.systemDefault()).toInstant());
boolean isNight = isTimeInRange("08:30", "22:20", testTime);
System.out.println("当前时间是否在工作时间内:" + isWorkTime);
System.out.println("特定时间是否在夜间时间段内:" + isNight);

View File

@ -49,7 +49,7 @@ public class LakalaAdminController extends BaseControllerImpl {
}
// 执行业务逻辑
Boolean success = lakalaPayService.ewalletWithDrawD1(paramsJSON.getStr("mercId"), paramsJSON.getStr("merOrderNo"), paramsJSON.getStr("drawAmt"), paramsJSON.getStr("summary"));
Boolean success = lakalaPayService.ewalletWithDrawD1(paramsJSON.getStr("mercId"), paramsJSON.getStr("merOrderNo"), paramsJSON.getStr("drawAmt"), paramsJSON.getStr("orderId"), paramsJSON.getStr("summary"));
if (success) {
return CommonResult.success("账户D1提现提交成功");
}

View File

@ -208,9 +208,10 @@ public interface LakalaApiService {
* @param lklMerchantNo 拉卡拉商户号
* @param receiveTradeNo 收货交易号对应拉卡拉的trade_no
* @param receiveLogNo 收货流水号对应拉卡拉的log_no
* @param logDate posp日期yyyyMMdd查清结算用, 一般是值交易完成日期确认收货的日期
* @return Pair<Boolean, String> 处理结果对first为是否成功second为结果描述信息
*/
Pair<Boolean, String> innerDoOrderSeparateByMerchantAndLogNo(String lklMerchantNo, String receiveTradeNo, String receiveLogNo);
Pair<Boolean, String> innerDoOrderSeparateByMerchantAndLogNo(String lklMerchantNo, String receiveTradeNo, String receiveLogNo, String logDate);
/**
* 分账结果通知
@ -339,9 +340,10 @@ public interface LakalaApiService {
* @param mercId 822商户号或receiveNo
* @param merOrderNo 商户订单号
* @param drawAmt 提现金额
* @param orderId 商城订单Id
* @param summary
*/
Boolean ewalletWithDrawD1(String mercId, String merOrderNo, String drawAmt, String summary);
Boolean ewalletWithDrawD1(String mercId, String merOrderNo, String drawAmt, String orderId, String summary);
/**
* 拉卡拉账户D1提现结果通知

View File

@ -29,4 +29,12 @@ public interface LklOrderDrawService extends IBaseService<LklOrderDraw> {
* @return
*/
LklOrderDraw getByByMercIdAndMerOrderNo(String mercId, String merOrderNo);
/**
* 判断订单是否已经提现完成
*
* @param orderId
* @return
*/
Boolean isOrderDrawed(String orderId);
}

View File

@ -11,6 +11,7 @@ package com.suisung.mall.shop.lakala.service.impl;
import cn.hutool.core.collection.CollUtil;
import cn.hutool.core.collection.CollectionUtil;
import cn.hutool.core.convert.Convert;
import cn.hutool.core.date.DateUtil;
import cn.hutool.core.util.ObjectUtil;
import cn.hutool.core.util.StrUtil;
import cn.hutool.json.JSONArray;
@ -823,7 +824,14 @@ public class LakalaApiServiceImpl implements LakalaApiService {
// 分账用途
String logNo = paramsJSON.getStr("log_no");
String tradeNo = paramsJSON.getStr("trade_no");
log.debug("[确认收货通知] 获取基础交易信息: logNo={} tradeNo={}", logNo, tradeNo);
String tradeTime = paramsJSON.getStr("trade_time"); // 实际交易完成时间yyyyMMddHHmmss
// 直接截取前8位获取日期部分
String logDate = tradeTime != null && tradeTime.length() >= 8 ? tradeTime.substring(0, 8) : null;
if (logDate == null) {
logDate = DateUtil.format(new Date(), "yyyyMMdd"); // 当前时间
}
log.debug("[确认收货通知] 获取基础交易信息: logNo={} tradeNo={} logDate={}", logNo, tradeNo, logDate);
// 查询用途
String originTradeNo = paramsJSON.getStr("origin_trade_no");
@ -900,7 +908,7 @@ public class LakalaApiServiceImpl implements LakalaApiService {
// 重要准备发起分账指令
log.info("[确认收货通知] 开始发起分账指令: merchantNo={}, receiveTradeNo={}, logNo={}",
merchantNo, shopOrderLkl.getLkl_receive_trade_no(), logNo);
Pair<Boolean, String> separateResult = innerDoOrderSeparateByMerchantAndLogNo(merchantNo, shopOrderLkl.getLkl_receive_trade_no(), shopOrderLkl.getLkl_receive_log_no());
Pair<Boolean, String> separateResult = innerDoOrderSeparateByMerchantAndLogNo(merchantNo, shopOrderLkl.getLkl_receive_trade_no(), shopOrderLkl.getLkl_receive_log_no(), logDate);
if (!separateResult.getFirst()) {
shopOrderLkl.setSeparate_msg(separateResult.getSecond());
@ -2451,15 +2459,16 @@ public class LakalaApiServiceImpl implements LakalaApiService {
* @param lklMerchantNo 拉卡拉商户号
* @param receiveTradeNo 收货交易号对应拉卡拉的trade_no
* @param receiveLogNo 收货流水号对应拉卡拉的log_no
* @param logDate posp日期yyyyMMdd查清结算用, 一般是值交易完成日期确认收货的日期
* @return Pair<Boolean, String> 处理结果对first为是否成功second为结果描述信息
*/
@Transactional
@Override
public Pair<Boolean, String> innerDoOrderSeparateByMerchantAndLogNo(String lklMerchantNo, String receiveTradeNo, String receiveLogNo) {
public Pair<Boolean, String> innerDoOrderSeparateByMerchantAndLogNo(String lklMerchantNo, String receiveTradeNo, String receiveLogNo, String logDate) {
// 1. 输入参数校验
if (StrUtil.hasBlank(lklMerchantNo, receiveTradeNo, receiveLogNo)) {
log.warn("[分账操作] 参数校验失败:缺少必要参数, lklMerchantNo={}, receiveTradeNo={}, receiveLogNo={}",
lklMerchantNo, receiveTradeNo, receiveLogNo);
if (StrUtil.hasBlank(lklMerchantNo, receiveTradeNo, receiveLogNo, logDate)) {
log.warn("[分账操作] 参数校验失败:缺少必要参数, lklMerchantNo={}, receiveTradeNo={}, receiveLogNo={}, logDate={}",
lklMerchantNo, receiveTradeNo, receiveLogNo, logDate);
return Pair.of(false, "缺少必要参数");
}
@ -2639,7 +2648,7 @@ public class LakalaApiServiceImpl implements LakalaApiService {
receiver.setSeparateValue(Convert.toStr(merchantAmount));
recvDatas.add(receiver);
}
// 是否有二级代理商
boolean has2ndAgent = CheckUtil.isNotEmpty(agent2ndSplitRatio) && agent2ndReceiver != null &&
StrUtil.isNotBlank(agent2ndReceiver.getReceiver_no()) &&
@ -2695,7 +2704,7 @@ public class LakalaApiServiceImpl implements LakalaApiService {
separateRequest.setMerchantNo(merchantNo);
separateRequest.setOutSeparateNo(shopOrderLkl.getOut_separate_no());
separateRequest.setLogNo(shopOrderLkl.getLkl_receive_log_no()); // 使用确认收货流水号作为分账流水号
separateRequest.setLogDate(shopOrderLkl.getLkl_log_date());
separateRequest.setLogDate(logDate); // 重要确认收货后的交易时间
separateRequest.setTotalAmt(refCanSeparateAmt.toString());
separateRequest.setLklOrgNo(orgCode);
separateRequest.setCalType("0"); // 0- 按照指定金额1- 按照指定比例默认 0
@ -2799,11 +2808,12 @@ public class LakalaApiServiceImpl implements LakalaApiService {
public JSONObject sacsSeparateNotify(HttpServletRequest request, String merchantNoParam, String separateNoParam) {
String channel = "";
try {
JSONObject paramsJson = null;
JSONObject paramsJson;
if (!StrUtil.hasBlank(merchantNoParam, separateNoParam)) {
channel = "(补偿)";
log.info("[拉卡拉分账通知] 开始处理拉卡拉分账结果通知异步回调{}merchantNoParam={}separateNoParam={}",
channel, merchantNoParam, separateNoParam);
// 主动从拉卡拉获取分账结果
paramsJson = sacsQuery(merchantNoParam, separateNoParam);
} else {
log.info("[拉卡拉分账通知] 开始处理拉卡拉分账结果通知异步回调");
@ -2922,13 +2932,15 @@ public class LakalaApiServiceImpl implements LakalaApiService {
continue;
}
// 分账成功之后立即申请提现
String recvNo = Convert.toStr(detailData.get("recv_no"), "");
String amt = Convert.toStr(detailData.get("amt"), "");
if (StrUtil.isNotBlank(recvNo) && StrUtil.isNotBlank(amt)) {
String outSeparateNoTemp = String.format("%s_%d", outSeparateNo, idx);
Boolean drawSuccess = ewalletWithDrawD1(recvNo, outSeparateNoTemp, amt, JSONUtil.toJsonStr(detailDatas));
String merOrderNo = String.format("%s_%d", outSeparateNo, idx);
// 账户D1提现
Boolean drawSuccess = ewalletWithDrawD1(recvNo, merOrderNo, amt, outSeparateNo, JSONUtil.toJsonStr(detailDatas));
log.info("[拉卡拉分账通知] 账户D1提现{},商户号={},分账单号={},金额={}分",
Boolean.TRUE.equals(drawSuccess) ? "成功" : "失败", recvNo, outSeparateNoTemp, amt);
Boolean.TRUE.equals(drawSuccess) ? "成功" : "失败", recvNo, merOrderNo, amt);
idx++;
}
}
@ -3038,9 +3050,9 @@ public class LakalaApiServiceImpl implements LakalaApiService {
public Integer fixUnSuccessSeparateStatusJob() {
log.info("[分账状态修复任务] 开始执行未成功分账记录的状态修复任务");
// 获取2天前分账状态未成功的记录
Date now = new Date();
Date threeDaysAgo = DateUtils.addHours(now, -48);
// 获取3天前分账状态未成功的记录
Date endDate = new Date();
Date beginDate = DateUtils.addDays(endDate, -3); // 3天前
// 分页参数
int pageSize = 200;
@ -3050,100 +3062,104 @@ public class LakalaApiServiceImpl implements LakalaApiService {
// 记录处理开始时间
long startTime = System.currentTimeMillis();
String redisPrefKey = "lkl:separate:status:retry:";
List<LklOrderSeparate> lklOrderSeparates;
do {
// 分页获取未成功分账的记录
lklOrderSeparates = lklOrderSeparateService.getUnSuccessSeparateList(threeDaysAgo, now, currentPage, pageSize);
try {
List<LklOrderSeparate> lklOrderSeparates;
do {
// 分页获取未成功分账的记录
lklOrderSeparates = lklOrderSeparateService.getUnSuccessSeparateList(beginDate, endDate, currentPage, pageSize);
if (CollectionUtil.isEmpty(lklOrderSeparates)) {
break;
}
log.info("[分账状态修复任务] 获取到第{}页数据,共{}条记录", currentPage, lklOrderSeparates.size());
String redisPrefKey = "lkl:separate:status:retry:";
// 按处理次数排序从未处理过的记录优先处理处理次数越多优先级越低
lklOrderSeparates.sort((o1, o2) -> {
String redisKey1 = redisPrefKey + o1.getSeparate_no();
String redisKey2 = redisPrefKey + o2.getSeparate_no();
int retryCount1 = Convert.toInt(redisService.get(redisKey1), 0);
int retryCount2 = Convert.toInt(redisService.get(redisKey2), 0);
return Integer.compare(retryCount1, retryCount2);
});
// 处理当前页中的记录
for (LklOrderSeparate record : lklOrderSeparates) {
// 检查该记录的处理次数是否已达到上限5次
String redisKey = redisPrefKey + record.getSeparate_no();
int retryCount = Convert.toInt(redisService.get(redisKey), 0);
if (retryCount >= 5) {
log.warn("[分账状态修复任务] 记录已达到最大重试次数,跳过处理: merchantNo={}, separateNo={}",
record.getMerchant_no(), record.getSeparate_no());
continue;
if (CollectionUtil.isEmpty(lklOrderSeparates)) {
break;
}
totalProcessed++;
// 每处理10条记录才输出一次详细日志减少日志量
if (totalProcessed % 10 == 1) {
log.info("[分账状态修复任务] 正在处理第 {} 条记录: merchantNo={}, separateNo={}, 已重试{}次",
totalProcessed, record.getMerchant_no(), record.getSeparate_no(), retryCount);
}
log.info("[分账状态修复任务] 获取到第{}页数据,共{}条记录", currentPage, lklOrderSeparates.size());
try {
// 增加处理次数计数并设置3天过期时间
redisService.incr(redisKey, 1);
redisService.expire(redisKey, 3 * 24 * 60 * 60);
// 按处理次数排序从未处理过的记录优先处理处理次数越多优先级越低
lklOrderSeparates.sort((o1, o2) -> {
String redisKey1 = redisPrefKey + o1.getSeparate_no();
String redisKey2 = redisPrefKey + o2.getSeparate_no();
// 调用分账通知回调接口进行状态补偿
JSONObject notifyResp = sacsSeparateNotify(null, record.getMerchant_no(), record.getSeparate_no());
int retryCount1 = Convert.toInt(redisService.get(redisKey1), 0);
int retryCount2 = Convert.toInt(redisService.get(redisKey2), 0);
// 检查处理结果
if (notifyResp != null && "SUCCESS".equals(notifyResp.getStr("code"))) {
totalSuccessCount++;
log.debug("[分账状态修复任务] 记录处理成功: merchantNo={}, separateNo={}",
return Integer.compare(retryCount1, retryCount2);
});
// 处理当前页中的记录
for (LklOrderSeparate record : lklOrderSeparates) {
// 检查该记录的处理次数是否已达到上限5次
String redisKey = redisPrefKey + record.getSeparate_no();
int retryCount = Convert.toInt(redisService.get(redisKey), 0);
if (retryCount >= 5) {
log.warn("[分账状态修复任务] 记录已达到最大重试次数,跳过处理: merchantNo={}, separateNo={}",
record.getMerchant_no(), record.getSeparate_no());
} else {
String errorMsg = notifyResp != null ? notifyResp.getStr("message") : "未知错误";
log.warn("[分账状态修复任务] 记录处理失败: merchantNo={}, separateNo={}, errorMsg={}",
record.getMerchant_no(), record.getSeparate_no(), errorMsg);
continue;
}
totalProcessed++;
// 每处理10条记录才输出一次详细日志减少日志量
if (totalProcessed % 10 == 1) {
log.info("[分账状态修复任务] 正在处理第 {} 条记录: merchantNo={}, separateNo={}, 已重试{}次",
totalProcessed, record.getMerchant_no(), record.getSeparate_no(), retryCount);
}
try {
// 增加处理次数计数并设置3天过期时间
redisService.incr(redisKey, 1);
redisService.expire(redisKey, 3 * 24 * 60 * 60);
// 调用拉卡拉分账通知回调接口进行状态补偿
JSONObject notifyResp = sacsSeparateNotify(null, record.getMerchant_no(), record.getSeparate_no());
// 检查处理结果
if (notifyResp != null && "SUCCESS".equals(notifyResp.getStr("code"))) {
totalSuccessCount++;
log.debug("[分账状态修复任务] 记录处理成功: merchantNo={}, separateNo={}",
record.getMerchant_no(), record.getSeparate_no());
} else {
String errorMsg = notifyResp != null ? notifyResp.getStr("message") : "未知错误";
log.warn("[分账状态修复任务] 记录处理失败: merchantNo={}, separateNo={}, errorMsg={}",
record.getMerchant_no(), record.getSeparate_no(), errorMsg);
}
} catch (Exception e) {
log.error("[分账状态修复任务] 处理记录时发生异常: merchantNo={}, separateNo={}",
record.getMerchant_no(), record.getSeparate_no(), e);
}
} catch (Exception e) {
log.error("[分账状态修复任务] 处理记录时发生异常: merchantNo={}, separateNo={}",
record.getMerchant_no(), record.getSeparate_no(), e);
}
}
log.info("[分账状态修复任务] 第{}页处理完成,已处理 {} 条记录,总成功 {} 条",
currentPage, totalProcessed, totalSuccessCount);
log.info("[分账状态修复任务] 第{}页处理完成,已处理 {} 条记录,总成功 {} 条",
currentPage, totalProcessed, totalSuccessCount);
// 如果当前页数据少于页面大小说明已经是最后一页
if (lklOrderSeparates.size() < pageSize) {
break;
}
// 如果当前页数据少于页面大小说明已经是最后一页
if (lklOrderSeparates.size() < pageSize) {
break;
}
currentPage++;
currentPage++;
// 添加短暂延迟避免对系统造成过大压力
try {
// 添加短暂延迟避免对系统造成过大压力
Thread.sleep(100);
} catch (InterruptedException e) {
Thread.currentThread().interrupt();
break;
}
} while (!CollectionUtil.isEmpty(lklOrderSeparates));
} while (!CollectionUtil.isEmpty(lklOrderSeparates));
} catch (InterruptedException e) {
log.warn("[分账状态修复任务] 任务被中断");
Thread.currentThread().interrupt();
} catch (Exception e) {
log.error("[分账状态修复任务] 任务执行过程中发生异常", e);
}
long endTime = System.currentTimeMillis();
log.info("[分账状态修复任务] 任务执行完成,总共处理 {} 条记录,成功处理 {} 条记录,耗时 {} ms",
totalProcessed, totalSuccessCount, (endTime - startTime));
return totalSuccessCount;
}
/**
* 检测修复补全商户的商户分账业务信息及分账接收方绑定关系分账业务申请异步通知的补偿机制
*
@ -3499,11 +3515,12 @@ public class LakalaApiServiceImpl implements LakalaApiService {
* @param mercId 822商户号或receiveNo
* @param merOrderNo 商户订单号
* @param drawAmt 提现金额
* @param orderId 商城订单Id
* @param summary 摘要信息
* @return 操作结果成功返回true失败返回false
*/
@Override
public Boolean ewalletWithDrawD1(String mercId, String merOrderNo, String drawAmt, String summary) {
public Boolean ewalletWithDrawD1(String mercId, String merOrderNo, String drawAmt, String orderId, String summary) {
// 1. 参数校验
if (StrUtil.hasBlank(mercId, merOrderNo, drawAmt)) {
log.warn("[D1提现申请] D1提现参数校验失败关键参数为空: mercId={}, merOrderNo={}, drawAmt={}",
@ -3548,7 +3565,8 @@ public class LakalaApiServiceImpl implements LakalaApiService {
if (StrUtil.isNotBlank(summary)) {
request.setSummary(summary);
}
request.setNotifyUrl(projectDomain + "/api/mobile/shop/lakala/ewallet/ewallet/drawNotify");
request.setNotifyUrl(projectDomain + "/api/mobile/shop/lakala/ewallet/drawNotify");
// 4. 发送请求
String responseStr = LKLSDK.httpPost(request);
@ -3574,6 +3592,7 @@ public class LakalaApiServiceImpl implements LakalaApiService {
LklOrderDraw lklOrderDraw = new LklOrderDraw();
lklOrderDraw.setMerc_id(mercId);
lklOrderDraw.setMer_order_no(merOrderNo);
lklOrderDraw.setOrder_id(orderId);
lklOrderDraw.setDraw_jnl(Convert.toStr(drawJnl));
lklOrderDraw.setDraw_amt(drawAmtYuan);
lklOrderDraw.setBatch_auto_settle(payType);
@ -3618,13 +3637,13 @@ public class LakalaApiServiceImpl implements LakalaApiService {
*/
@Override
public JSONObject ewalletWithDrawNotify(HttpServletRequest request) {
log.debug("[拉卡拉提现结果通知] 开始处理拉卡拉提现结果通知");
log.debug("[拉卡拉D1提现结果通知] 开始处理拉卡拉提现结果通知");
try {
// 1. 验签处理 - 验证通知来源的合法性
Pair<Boolean, String> signCheckResult = LakalaUtil.chkLklApiNotifySign(request, lklNotifyCerPath, false);
if (!signCheckResult.getFirst()) {
log.warn("[LklOrderDraw] 验签失败: {}", signCheckResult.getSecond());
log.warn("[拉卡拉D1提现结果通知] 验签失败: {}", signCheckResult.getSecond());
return JSONUtil.createObj()
.set("code", "FAIL")
.set("message", signCheckResult.getSecond());
@ -3633,7 +3652,7 @@ public class LakalaApiServiceImpl implements LakalaApiService {
// 2. 解析回调参数
JSONObject paramsJSON = JSONUtil.parseObj(signCheckResult.getSecond());
if (paramsJSON == null) {
log.warn("[拉卡拉提现结果通知] 回调参数解析失败");
log.warn("[拉卡拉D1提现结果通知] 回调参数解析失败");
return JSONUtil.createObj()
.set("code", "FAIL")
.set("message", "回调参数解析失败");
@ -3643,9 +3662,9 @@ public class LakalaApiServiceImpl implements LakalaApiService {
String mercId = paramsJSON.getStr("mercId");
String merOrderNo = paramsJSON.getStr("merOrderNo");
log.info("[拉卡拉提现结果通知] 提现通知参数: drawState={}, mercId={}, merOrderNo={}", drawState, mercId, merOrderNo);
log.info("[拉卡拉D1提现结果通知] 提现通知参数: drawState={}, mercId={}, merOrderNo={}", drawState, mercId, merOrderNo);
if (StrUtil.isBlank(mercId) || StrUtil.isBlank(merOrderNo) || StrUtil.isBlank(drawState)) {
if (StrUtil.hasBlank(mercId, merOrderNo, drawState)) {
log.warn("[拉卡拉提现结果通知] 回调参数缺失: drawState={}, mercId={}, merOrderNo={}", drawState, mercId, merOrderNo);
return JSONUtil.createObj()
.set("code", "FAIL")
@ -3654,16 +3673,16 @@ public class LakalaApiServiceImpl implements LakalaApiService {
// 只处理成功的提现状态
if (!"DRAW.SUCCESS".equals(drawState)) {
log.debug("[拉卡拉提现结果通知] 提现状态未成功,忽略处理: drawState={}", drawState);
log.debug("[拉卡拉D1提现结果通知] 提现状态未成功,忽略处理: drawState={}", drawState);
return JSONUtil.createObj()
.set("code", "SUCCESS") // 返回成功避免重复通知
.set("code", "FAIL") // 返回成功避免重复通知
.set("message", "状态未成功,忽略处理");
}
// 3. 转换参数并更新数据
String snakeCaseJson = StringUtils.convertCamelToSnake(signCheckResult.getSecond());
if (StringUtils.isBlank(snakeCaseJson)) {
log.error("[拉卡拉提现结果通知] 回调参数转换失败mercId={} merOrderNo={}", mercId, merOrderNo);
log.error("[拉卡拉D1提现结果通知] 回调参数转换失败mercId={} merOrderNo={}", mercId, merOrderNo);
return JSONUtil.createObj()
.set("code", "FAIL")
.set("message", "回调参数转换失败");
@ -3671,7 +3690,7 @@ public class LakalaApiServiceImpl implements LakalaApiService {
LklOrderDraw lklOrderDraw = JSONUtil.toBean(snakeCaseJson, LklOrderDraw.class);
if (lklOrderDraw == null) {
log.error("[拉卡拉提现结果通知] 回调参数转换为对象失败mercId={} merOrderNo={}", mercId, merOrderNo);
log.error("[拉卡拉D1提现结果通知] 回调参数转换为对象失败mercId={} merOrderNo={}", mercId, merOrderNo);
return JSONUtil.createObj()
.set("code", "FAIL")
.set("message", "回调参数转换失败");
@ -3679,13 +3698,13 @@ public class LakalaApiServiceImpl implements LakalaApiService {
boolean isSuccess = lklOrderDrawService.addOrUpdateByMercIdAndMerOrderNo(lklOrderDraw);
if (!isSuccess) {
log.error("[拉卡拉提现结果通知] 数据更新失败mercId={} merOrderNo={}", mercId, merOrderNo);
log.error("[拉卡拉D1提现结果通知] 数据更新失败mercId={} merOrderNo={}", mercId, merOrderNo);
return JSONUtil.createObj()
.set("code", "FAIL")
.set("message", "数据更新失败");
}
log.info("[拉卡拉提现结果通知] 拉卡拉提现结果通知处理成功mercId={} merOrderNo={}", mercId, merOrderNo);
log.info("[拉卡拉D1提现结果通知] 拉卡拉提现结果通知处理成功mercId={} merOrderNo={}", mercId, merOrderNo);
// 4. 返回成功响应
return JSONUtil.createObj()
@ -3693,7 +3712,7 @@ public class LakalaApiServiceImpl implements LakalaApiService {
.set("message", "处理成功");
} catch (Exception e) {
log.error("[拉卡拉提现结果通知] 处理拉卡拉提现结果通知异常", e);
log.error("[拉卡拉D1提现结果通知] 处理拉卡拉提现结果通知异常", e);
return JSONUtil.createObj()
.set("code", "FAIL")
.set("message", "系统处理异常");

View File

@ -38,7 +38,7 @@ public class LklOrderDrawServiceImpl extends BaseServiceImpl<LklOrderDrawMapper,
queryWrapper.eq("draw_jnl", record.getDraw_jnl());
}
LklOrderDraw existsRecord = getOne(queryWrapper);
LklOrderDraw existsRecord = findOne(queryWrapper);
if (existsRecord != null && existsRecord.getId() != null && existsRecord.getId() > 0) {
// 更新记录
log.info("[LklOrderDraw] 记录已存在执行更新操作ID={}", existsRecord.getId());
@ -102,4 +102,39 @@ public class LklOrderDrawServiceImpl extends BaseServiceImpl<LklOrderDrawMapper,
return null;
}
}
/**
* 判断订单是否已经提现完成
*
* @param orderId 订单ID
* @return 如果订单已提现完成返回true否则返回false
*/
@Override
public Boolean isOrderDrawed(String orderId) {
// 参数校验
if (StrUtil.isBlank(orderId)) {
log.warn("订单ID为空无法判断提现状态");
return false;
}
try {
// 查询提现成功的记录
LklOrderDraw lklOrderDraw = findOne(new QueryWrapper<LklOrderDraw>()
.eq("order_id", orderId)
.eq("draw_state", "DRAW.SUCCESS")
.orderByDesc("id"));
// 根据查询结果判断是否已提现
if (lklOrderDraw != null) {
log.debug("订单[{}]提现已完成", orderId);
return true;
} else {
log.debug("订单[{}]提现未完成或不存在提现记录", orderId);
return false;
}
} catch (Exception e) {
log.error("查询订单[{}]提现状态异常", orderId, e);
return false;
}
}
}

View File

@ -103,7 +103,7 @@ public class ShopOrderBaseController extends BaseControllerImpl {
public CommonResult cancel(@RequestParam(name = "order_id") String order_id) {
return shopOrderBaseService.cancel(order_id);
}
@ApiOperation(value = "确认收货", notes = "确认收货")
@RequestMapping(value = "/receive", method = {RequestMethod.GET, RequestMethod.POST})
public CommonResult receive(@RequestParam(name = "order_id") String order_id) {
@ -326,9 +326,12 @@ public class ShopOrderBaseController extends BaseControllerImpl {
return CommonResult.failed(ResultCode.FORBIDDEN);
}
// 同城订单超时秒数
// 初定同城订单超时秒数
long mchOrderExpireSeconds = shopOrderBaseService.sameCityOrderExpireSeconds(2100L); // 35分钟超时60秒*35分钟 = 2100秒
//同城配送订单状态delivery=1时才生效无值 or 0-全部订单1-进行中订单2-异常超时订单3-退款订单9-已完成订单
Integer status = params.getInt("status");
// === 构建响应数据 ===
Map<String, Object> respMap = new HashMap<>();
// 订单列表数据缓存时间25分钟
@ -336,7 +339,7 @@ public class ShopOrderBaseController extends BaseControllerImpl {
storeId,
params.getStr("keyword"),
params.getInt("delivery"),
params.getInt("status"),
status,
params.getInt("logistics_status"),
mchOrderExpireSeconds,
params.getLong("begin_time"),
@ -388,6 +391,7 @@ public class ShopOrderBaseController extends BaseControllerImpl {
return CommonResult.failed(ResultCode.FORBIDDEN);
}
// 5. 返回结果
return CommonResult.success(mchOrderInfoDTO);
} catch (Exception e) {

View File

@ -113,7 +113,7 @@ public class UserOrderController extends BaseControllerImpl {
return CommonResult.success(shopOrderBaseService.detail(order_id));
}
@ApiOperation(value = "添加订单详细信息", notes = "添加订单详细信息")
@ApiOperation(value = "添加订单详细信息", notes = "添加订单详细信息(提交订单)")
@ApiImplicitParams({
@ApiImplicitParam(name = "ud_id", value = "收货地址编号", paramType = "query", required = true, dataType = "int"),
@ApiImplicitParam(name = "is_edu", value = "是教育", paramType = "query", required = false, dataType = "int"),

View File

@ -85,7 +85,8 @@ public class UserReturnController extends BaseControllerImpl {
return CommonResult.failed(ResultCode.NEED_LOGIN);
}
return shopOrderReturnService.addWholeItems(order_id, false, "");
// return shopOrderReturnService.addWholeItems(order_id, false, "");
return shopOrderReturnService.addRemainingItems(order_id, true, "");
}
@ApiOperation(value = "取消退款订单", notes = "取消退款订单")

View File

@ -9,6 +9,7 @@ import com.suisung.mall.common.constant.CommonConstant;
import com.suisung.mall.common.constant.MqConstant;
import com.suisung.mall.common.constant.RedisConstant;
import com.suisung.mall.common.modules.order.ShopOrderInfo;
import com.suisung.mall.common.utils.CheckUtil;
import com.suisung.mall.common.utils.DateTimeUtils;
import com.suisung.mall.core.web.service.RedisService;
import com.suisung.mall.shop.message.service.PushMessageService;
@ -138,10 +139,10 @@ public class OrderPayedListener {
}
}
logger.info("[订单支付监听] 支付异步通知回调处理结果: {}, 订单ID: {}", flag, orderId);
logger.info("[订单支付监听] 订单ID: {},支付异步通知回调处理是否成功: {} ", flag, orderId);
// 生成取单号和打印小票
if (flag) {
// TODO 以下仅处理下单打印的情况还需要处理退单打印分支
// 原始状态 2010-待付款;2011--待订单审核;2013-待财务审核 变成 2020-待配货2016-已经付款 的时候
// 生成取单号打票机打印订单向顺丰同城下单
@ -152,12 +153,14 @@ public class OrderPayedListener {
Long orderPickupNum = shopOrderInfoService.isPaidOrderGenPickNumAndPrint(orderInfoOld.getStore_id(), orderId);
// 如果配送方式是 顺丰同城下单
if (orderInfoOld.getDelivery_type_id() != null && orderInfoOld.getDelivery_type_id().equals(StateCode.DELIVERY_TYPE_SAME_CITY)
&& orderPickupNum > 0) {
// 发送顺丰同城快递
if (CheckUtil.isNotEmpty(orderInfoOld.getDelivery_type_id())
&& orderInfoOld.getDelivery_type_id().equals(StateCode.DELIVERY_TYPE_SAME_CITY)
&& CheckUtil.isNotEmpty(orderPickupNum)) {
// 顺丰同城下单
Pair<Boolean, String> pairCreateSfOrder = sfExpressApiService.innerCreateSfExpressOrder(orderId, orderPickupNum);
if (pairCreateSfOrder == null) {
logger.error("[订单支付监听] 顺丰同城下单失败pairCreateSfOrder 返回空值. 订单ID: {}", orderId);
logger.error("[订单支付监听] 顺丰同城下单失败,无返回值 订单ID: {}", orderId);
continue;
}

View File

@ -3,6 +3,7 @@ package com.suisung.mall.shop.order.service;
import com.suisung.mall.common.api.CommonResult;
import com.suisung.mall.common.modules.order.ShopOrderInfo;
import com.suisung.mall.core.web.service.IBaseService;
import org.springframework.data.util.Pair;
import java.util.List;
import java.util.Map;
@ -91,6 +92,7 @@ public interface ShopOrderInfoService extends IBaseService<ShopOrderInfo> {
/**
* 分页查询取消订单
*
* @param pageNum
* @param pageSize
* @return
@ -99,7 +101,19 @@ public interface ShopOrderInfoService extends IBaseService<ShopOrderInfo> {
/**
* 查询取消订单总数
*
* @return
*/
long countgetAutoCancelOrderId();
/**
* 检查订单预约参数是否合法
*
* @param storeId 店铺ID
* @param bookingState 预约配送状态
* @param bookingBeginTime 预约开始时间
* @param bookingEndTime 预约截止时间
* @return
*/
Pair<Boolean, String> checkBookingOrderArgs(Integer storeId, Integer bookingState, String bookingBeginTime, String bookingEndTime);
}

View File

@ -159,6 +159,28 @@ public interface ShopOrderReturnService extends IBaseService<ShopOrderReturn> {
*/
boolean ifDenyReturn(Long order_item_id);
/**
* 判断订单中某个商品是否禁止退货
* <p>
* 该方法用于检查指定订单中的特定商品是否允许退货主要检查以下几种情况
* 1. 商品是否设置了"禁止退货"的消费者保障标识
* 2. 订单是否已超过退货期限已收货或已完成状态且超过可提现时间
* 3. 拉卡拉分账订单是否已完成提现
*
* @param orderId 订单ID
* @param productId 商品ID
* @return boolean true表示禁止退货false表示允许退货
*/
boolean ifOrderItemDenyReturn(String orderId, Long productId);
/**
* 判断订单是否禁止退货
*
* @param orderId 订单ID
* @return 如果订单禁止退货返回true否则返回false
*/
boolean isOrderDenyReturn(String orderId);
/**
* 该方法用于处理整单退货申请具体功能如下
* 根据订单ID获取订单信息若为空则抛异常
@ -201,4 +223,6 @@ public interface ShopOrderReturnService extends IBaseService<ShopOrderReturn> {
* @return
*/
CommonResult doRefundForMch(JSONObject params);
}

View File

@ -99,6 +99,7 @@ import com.suisung.mall.shop.sfexpress.service.SFExpressApiService;
import com.suisung.mall.shop.store.service.*;
import com.suisung.mall.shop.sync.service.SyncThirdDataService;
import com.suisung.mall.shop.user.service.*;
import com.suisung.mall.shop.wechat.service.WxOrderShippingService;
import io.seata.common.util.StringUtils;
import io.seata.core.context.RootContext;
import io.seata.core.exception.TransactionException;
@ -376,6 +377,10 @@ public class ShopOrderBaseServiceImpl extends BaseServiceImpl<ShopOrderBaseMappe
@Autowired
private LakalaApiService lakalaApiService;
@Lazy
@Autowired
private WxOrderShippingService wxOrderShippingService;
@Lazy
@Autowired
private SyncThirdDataService syncThirdDataService;
@ -665,6 +670,7 @@ public class ShopOrderBaseServiceImpl extends BaseServiceImpl<ShopOrderBaseMappe
Integer user_id = user.getId();
log.debug("当前用户ID: {}", user_id);
QueryWrapper<ShopDistributionUserOrder> userOrderQueryWrapper = new QueryWrapper<>();
userOrderQueryWrapper.eq("user_id", user_id).in("order_id", order_ids);
ShopDistributionUserOrder distributionUserOrder = shopDistributionUserOrderService.findOne(userOrderQueryWrapper);
@ -756,11 +762,14 @@ public class ShopOrderBaseServiceImpl extends BaseServiceImpl<ShopOrderBaseMappe
throw new ApiException(I18nUtil._("无该订单访问权限!"));
}
// 是否禁止退款
int isOrderDenyReturn = shopOrderReturnService.isOrderDenyReturn(order_id) ? 1 : 2;
data.put("is_deny_return", isOrderDenyReturn);
log.info("订单详情获取完成订单ID: {}", order_id);
return data;
}
/**
* @param order_id
* @param base_row shopOrderBase
@ -1597,6 +1606,21 @@ public class ShopOrderBaseServiceImpl extends BaseServiceImpl<ShopOrderBaseMappe
}
}
// 预约订单检测
Integer bookingState = Convert.toInt(getParameter("booking_state"));
if (CheckUtil.isNotEmpty(bookingState) && CommonConstant.Order_Booking_State_YY.equals(bookingState)) {
String bookingBeginTime = getParameter("booking_begin_time");
String bookingEndTime = getParameter("booking_end_time");
Pair<Boolean, String> pair = shopOrderInfoService.checkBookingOrderArgs(checkedStore, bookingState, bookingBeginTime, bookingEndTime);
if (!pair.getFirst()) {
throw new ApiException(I18nUtil._(pair.getSecond()));
}
cartData.put("booking_state", bookingState);
cartData.put("booking_begin_time", bookingBeginTime);
cartData.put("booking_end_time", bookingEndTime);
}
// 添加保存订单关键方法
List<String> orderIdRow = addOrder(cartData, true, false, null);
@ -5037,6 +5061,9 @@ public class ShopOrderBaseServiceImpl extends BaseServiceImpl<ShopOrderBaseMappe
continue;
}
/// 服务号确认收货通知跳转链接设置
wxOrderShippingService.setMsgJumpPath(order_id);
BigDecimal order_points_add = order_data_row.getOrder_points_add();
BigDecimal order_double_points_add = order_data_row.getOrder_double_points_add();
BigDecimal order_points_add_all = order_points_add != null ? order_points_add : BigDecimal.ZERO;
@ -6605,13 +6632,21 @@ public class ShopOrderBaseServiceImpl extends BaseServiceImpl<ShopOrderBaseMappe
info_row.setCoupon_type_id(shopProductIndex.getCoupon_type_id());
}
// 预约订单关键字段保存处理
Integer bookingState = Convert.toInt(cart_data.get("booking_state"));
Date bookingBeginTime = DateTimeUtils.tryParseDateTimeToDate(Convert.toStr(cart_data.get("booking_begin_time")));
Date bookingEndTime = DateTimeUtils.tryParseDateTimeToDate(Convert.toStr(cart_data.get("booking_end_time")));
if (CommonConstant.Order_Booking_State_YY.equals(bookingState) && bookingBeginTime != null && bookingEndTime != null) {
info_row.setBooking_state(bookingState);
info_row.setBooking_begin_time(bookingBeginTime);
info_row.setBooking_end_time(bookingEndTime);
}
info_row.setActivity_json(JSONUtil.toJsonStr(store_item.get("discount_detail_rows")));
info_row.setPayment_form_id(payment_form_id);
UserDto user = getCurrentUser();
if (ObjectUtil.isNotEmpty(user) && user.isChain()) {
info_row.setChain_id(Convert.toInt(user.getChain_id()));
}
@ -8560,13 +8595,18 @@ public class ShopOrderBaseServiceImpl extends BaseServiceImpl<ShopOrderBaseMappe
}
}
/**
* 获取确认收货之后多久后可提现时间戳毫秒
*
* @return
*/
@Override
public Long getWithdrawTime() {
//订单可提现时间
Date now = new Date();
Long withdraw_time = now.getTime();
Long withdraw_time;
float withdraw_received_day = accountBaseConfigService.getConfig("withdraw_received_day", 7f);
float withdraw_received_day = accountBaseConfigService.getConfig("withdraw_received_day", 1f); // 确认收货之后多久可以提现默认1天
int second = NumberUtil.mul(withdraw_received_day, 60, 60, 24).intValue();
if (withdraw_received_day >= 0) {
@ -8907,17 +8947,16 @@ public class ShopOrderBaseServiceImpl extends BaseServiceImpl<ShopOrderBaseMappe
} catch (Exception e) {
logger.error("获取物流轨迹失败订单ID{}", order.getOrder_id(), e);
}
}
// 处理顺丰同城物流轨迹
else if (CommonService.isSFExpress(deliveryTypeId)
&& orderStateId >= StateCode.ORDER_STATE_SHIPPED
&& orderStateId <= StateCode.ORDER_STATE_FINISH
} else if (CommonService.isSFExpress(deliveryTypeId)
&& orderStateId.intValue() >= StateCode.ORDER_STATE_SHIPPED
&& orderStateId.intValue() <= StateCode.ORDER_STATE_FINISH
&& order.getSf_order_info() != null
&& order.getSf_order_info().getFeed() == null) {
&& StrUtil.isBlank(order.getSf_order_info().getFeed())) {
// 获取顺丰同城的物流轨迹
Map<String, Object> params = new HashMap<>();
params.put("order_id", order.getSf_order_info().getSf_order_id());
try {
ThirdApiRes feedRes = sfExpressApiService.listOrderFeed(params);
logger.info("获取配送员物流轨迹:{}", feedRes);
if (feedRes != null && feedRes.getError_code() != null && feedRes.getError_code().equals(0)) {
@ -8926,6 +8965,7 @@ public class ShopOrderBaseServiceImpl extends BaseServiceImpl<ShopOrderBaseMappe
order.getSf_order_info().setFeed(JSONUtil.toJsonStr(result.get("feed")));
}
}
} catch (Exception e) {
logger.error("获取顺丰同城物流轨迹失败订单ID{}", order.getOrder_id(), e);
}
@ -8934,6 +8974,16 @@ public class ShopOrderBaseServiceImpl extends BaseServiceImpl<ShopOrderBaseMappe
// 格式化取货号
order.setOrder_pickup_num_str(fmtPickNum(order.getOrder_pickup_num()));
// 订单是否禁止退款
int isOrderDenyReturn = shopOrderReturnService.isOrderDenyReturn(order.getOrder_id()) ? 1 : 2;
order.setIs_deny_return(isOrderDenyReturn);
// 订单商品列表是否禁止退款
order.getOrder_items().forEach(item -> {
item.setIs_deny_return(isOrderDenyReturn);
});
});
return pageList;
@ -9031,10 +9081,18 @@ public class ShopOrderBaseServiceImpl extends BaseServiceImpl<ShopOrderBaseMappe
// 格式化取货号
orderDetail.setOrder_pickup_num_str(fmtPickNum(orderDetail.getOrder_pickup_num()));
// 订单是否禁止退款
int isOrderDenyReturn = shopOrderReturnService.isOrderDenyReturn(orderId) ? 1 : 2;
orderDetail.setIs_deny_return(isOrderDenyReturn);
// 订单商品列表是否禁止退款
orderDetail.getOrder_items().forEach(item -> {
item.setIs_deny_return(isOrderDenyReturn);
});
return orderDetail;
}
/**
* 商家订单各个分类和状态的订单数量
*

View File

@ -25,9 +25,11 @@ import com.suisung.mall.common.modules.order.ShopOrderStateLog;
import com.suisung.mall.common.modules.pay.PayPlantformResource;
import com.suisung.mall.common.modules.plantform.ShopPlantformFeedback;
import com.suisung.mall.common.modules.product.ShopProductComment;
import com.suisung.mall.common.modules.store.ShopStoreInfo;
import com.suisung.mall.common.pojo.res.ThirdApiRes;
import com.suisung.mall.common.utils.CheckUtil;
import com.suisung.mall.common.utils.CommonUtil;
import com.suisung.mall.common.utils.DateTimeUtils;
import com.suisung.mall.core.web.service.impl.BaseServiceImpl;
import com.suisung.mall.shop.base.service.AccountBaseConfigService;
import com.suisung.mall.shop.base.service.ShopBaseStateCodeService;
@ -41,12 +43,14 @@ import com.suisung.mall.shop.product.service.ShopProductBaseService;
import com.suisung.mall.shop.product.service.ShopProductCommentService;
import com.suisung.mall.shop.sfexpress.service.SFExpressApiService;
import com.suisung.mall.shop.store.service.ShopStoreBaseService;
import com.suisung.mall.shop.store.service.ShopStoreInfoService;
import com.suisung.mall.shop.store.service.ShopStorePrinterService;
import com.suisung.mall.shop.store.service.ShopStoreSfOrderService;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.context.annotation.Lazy;
import org.springframework.data.util.Pair;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.web.context.request.RequestContextHolder;
@ -84,6 +88,8 @@ public class ShopOrderInfoServiceImpl extends BaseServiceImpl<ShopOrderInfoMappe
@Autowired
private ShopStoreBaseService shopStoreBaseService;
@Autowired
private ShopStoreInfoService shopStoreInfoService;
@Autowired
private ShopDistributionUserCommissionService shopDistributionUserCommissionService;
@Autowired
private AccountBaseConfigService accountBaseConfigService;
@ -182,8 +188,6 @@ public class ShopOrderInfoServiceImpl extends BaseServiceImpl<ShopOrderInfoMappe
}
/**
* 获取能自动确认收货的订单号
*
@ -437,7 +441,7 @@ public class ShopOrderInfoServiceImpl extends BaseServiceImpl<ShopOrderInfoMappe
Integer times = orderInfo.getOrder_picked_notice_count() == null ? 0 : orderInfo.getOrder_picked_notice_count();
if (times > 3) {
return CommonResult.success("提交,请勿重复提交");
return CommonResult.success("通知配送人员,请稍候");
}
// 更新订单拣货时间
@ -502,7 +506,7 @@ public class ShopOrderInfoServiceImpl extends BaseServiceImpl<ShopOrderInfoMappe
updateWrapper.eq("order_id", orderId)
.ne("order_is_received", CommonConstant.Enable);
updateWrapper.set("order_is_received", CommonConstant.Enable)
.set("order_deal_time", System.currentTimeMillis());
.set("order_deal_time", System.currentTimeMillis()); // 确认收货时间戳
boolean result = update(updateWrapper);
if (result) {
@ -789,7 +793,7 @@ public class ShopOrderInfoServiceImpl extends BaseServiceImpl<ShopOrderInfoMappe
@Override
public List<String> getAutoCancelOrderIdByPage(Integer pageNum, Integer pageSize) {
QueryWrapper<ShopOrderInfo> queryWrapper = new QueryWrapper<>();
queryWrapper.select("order_id","order_state_id");
queryWrapper.select("order_id", "order_state_id");
queryWrapper.eq("order_state_id", StateCode.ORDER_STATE_WAIT_PAY)
.eq("order_is_paid", StateCode.ORDER_PAID_STATE_NO)
.eq("payment_type_id", StateCode.PAYMENT_TYPE_ONLINE);
@ -798,7 +802,7 @@ public class ShopOrderInfoServiceImpl extends BaseServiceImpl<ShopOrderInfoMappe
int second = NumberUtil.mul(order_autocancel_time, 60, 60).intValue();
long time = DateUtil.offsetSecond(new Date(), -second).getTime();
queryWrapper.lt("order_time", time);
List<ShopOrderInfo> shopOrderInfos=this.lists(queryWrapper,pageNum,pageSize).getRecords();
List<ShopOrderInfo> shopOrderInfos = this.lists(queryWrapper, pageNum, pageSize).getRecords();
return shopOrderInfos.stream().map(ShopOrderInfo::getOrder_id).collect(Collectors.toList());
}
@ -816,5 +820,56 @@ public class ShopOrderInfoServiceImpl extends BaseServiceImpl<ShopOrderInfoMappe
return this.count(queryWrapper);
}
/**
* 检查订单预约参数是否合法
*
* @param storeId 店铺ID
* @param bookingState 预约配送状态
* @param bookingBeginTimeStr 预约开始时间
* @param bookingEndTimeStr 预约截止时间
* @return
*/
@Override
public Pair<Boolean, String> checkBookingOrderArgs(Integer storeId, Integer bookingState, String bookingBeginTimeStr, String bookingEndTimeStr) {
if (CheckUtil.isEmpty(storeId) || CheckUtil.isEmpty(bookingState)) {
return Pair.of(false, "[预约订单校验] 缺少必要参数");
}
if (!CommonConstant.Order_Booking_State_YY.equals(bookingState)) {
return Pair.of(true, "[预约订单校验] 非预订单,跳过验证");
}
if (StrUtil.hasBlank(bookingBeginTimeStr, bookingEndTimeStr)) {
return Pair.of(false, "[预约订单校验] 预约时间不能为空");
}
Date bookingBeginTime = DateTimeUtils.tryParseDateTimeToDate(bookingBeginTimeStr);
Date bookingEndTime = DateTimeUtils.tryParseDateTimeToDate(bookingEndTimeStr);
if (bookingBeginTime == null || bookingBeginTime == null) {
return Pair.of(false, "[预约订单校验] 预约时间格式有误");
}
// 验证开始时间是否早于结束时间
if (bookingBeginTime.after(bookingEndTime)) {
return Pair.of(false, "[预约订单校验] 开始时间不能晚于截止时间");
}
// 判断预约订单开始时间是否在店铺的营业时间段里
ShopStoreInfo shopStoreInfo = shopStoreInfoService.getShopStoreInfoByStoreId(storeId);
if (shopStoreInfo == null) {
return Pair.of(false, "[预约订单校验] 店铺信息有误");
}
if (StrUtil.isBlank(shopStoreInfo.getStore_opening_hours()) || StrUtil.isBlank(shopStoreInfo.getStore_close_hours())) {
return Pair.of(false, "[预约订单校验] 店铺营业时间未设置");
}
if (!DateTimeUtils.isTimeInRange(shopStoreInfo.getStore_opening_hours(), shopStoreInfo.getStore_close_hours(), bookingBeginTime)) {
return Pair.of(false, "[预约订单校验] 预约时间不在店铺营业时间内");
}
return Pair.of(true, "[预约订单校验] 成功");
}
}

View File

@ -519,11 +519,11 @@ public class ShopOrderLklServiceImpl extends BaseServiceImpl<ShopOrderLklMapper,
*
* @param lklReceiveLogNo 拉卡拉确认收货对账单流水号
* @param separateStatus 分账状态1-已分账2-未分账3-分账已失败
* @param separateRemark 分账问题备注
* @param separateMsg 分账问题备注
* @return 更新结果 true-成功 false-失败
*/
@Override
public Boolean updateSeparateStatusByReceiveLogNo(String lklReceiveLogNo, Integer separateStatus, String separateRemark) {
public Boolean updateSeparateStatusByReceiveLogNo(String lklReceiveLogNo, Integer separateStatus, String separateMsg) {
// 检查参数是否全部为空
if (StringUtils.isBlank(lklReceiveLogNo) || separateStatus == null) {
log.warn("[更新分账状态] 参数校验失败:缺少必要参数, lklReceiveLogNo={}, separateStatus={}", lklReceiveLogNo, separateStatus);
@ -536,8 +536,8 @@ public class ShopOrderLklServiceImpl extends BaseServiceImpl<ShopOrderLklMapper,
UpdateWrapper<ShopOrderLkl> updateWrapper = new UpdateWrapper<>();
updateWrapper.eq("lkl_receive_log_no", lklReceiveLogNo);
updateWrapper.set("separate_status", separateStatus);
if (StrUtil.isNotBlank(separateRemark)) {
updateWrapper.set("separate_remark", separateRemark);
if (StrUtil.isNotBlank(separateMsg)) {
updateWrapper.set("separate_msg", separateMsg);
}
boolean result = update(updateWrapper);

View File

@ -43,6 +43,7 @@ import com.suisung.mall.shop.base.service.ShopBaseStateCodeService;
import com.suisung.mall.shop.distribution.service.ShopDistributionUserCommissionService;
import com.suisung.mall.shop.distribution.service.ShopDistributionUserOrderItemService;
import com.suisung.mall.shop.distribution.service.ShopDistributionUserOrderService;
import com.suisung.mall.shop.lakala.service.LklOrderDrawService;
import com.suisung.mall.shop.lakala.service.LklOrderSeparateService;
import com.suisung.mall.shop.message.service.PushMessageService;
import com.suisung.mall.shop.number.service.ShopNumberSeqService;
@ -196,7 +197,7 @@ public class ShopOrderReturnServiceImpl extends BaseServiceImpl<ShopOrderReturnM
@Lazy
@Autowired
private ShopOrderLklService shopOrderLklService;
private LklOrderDrawService lklOrderDrawService;
@Lazy
@Autowired
@ -553,6 +554,9 @@ public class ShopOrderReturnServiceImpl extends BaseServiceImpl<ShopOrderReturnM
if (is_denyreturn) {
// 获取更详细的拒绝退货原因
String denyReason = getDenyReturnReason(shopOrderInfo, shopOrderItem, shopProductIndex);
if (StrUtil.isBlank(denyReason)) {
denyReason = "此商品不允许退货!";
}
throw new ApiException(denyReason);
}
@ -1513,10 +1517,10 @@ public class ShopOrderReturnServiceImpl extends BaseServiceImpl<ShopOrderReturnM
// RMK 第三方数据同步相关redis 新增返还思迅库存
Map<String, Integer> stockDeltaMap = new HashMap<>();
String item_src_id= productItem.getItem_src_id();
String item_src_id = productItem.getItem_src_id();
stockDeltaMap.put(item_src_id + "-" + shopOrderItem.getOrder_id(), returnNum);
syncThirdDataService.incrProductStockToRedis(stockDeltaMap);
logger.info("退货返回给思迅,存入redis成功,item_src_id:{},订单号:{},数量:{}",item_src_id,shopOrderReturn.getOrder_id(),returnNum);
logger.info("退货返回给思迅,存入redis成功,item_src_id:{},订单号:{},数量:{}", item_src_id, shopOrderReturn.getOrder_id(), returnNum);
} else {
logger.warn("退货数量为空无法增加库存订单项ID: {}", orderItemId);
}
@ -1602,12 +1606,8 @@ public class ShopOrderReturnServiceImpl extends BaseServiceImpl<ShopOrderReturnM
// 当前订单状态
Integer order_state_id = info_row.getOrder_state_id();
// 没有发货没有完成订单之前允许取消订单和退运费(这个存在争议)
List<Integer> forbiddenStates = Arrays.asList(
StateCode.ORDER_STATE_SHIPPED,
StateCode.ORDER_STATE_RECEIVED,
StateCode.ORDER_STATE_FINISH);
if (order_state_id != null && !forbiddenStates.contains(order_state_id)) {
// 订单不是禁止退货能退货的情况下
if (order_state_id != null && !isOrderDenyReturn(order_id)) {
logger.info("处理运费和打包费事宜:{}", order_id);
ShopOrderData order_data_row = shopOrderDataService.get(order_id);
@ -2098,56 +2098,203 @@ public class ShopOrderReturnServiceImpl extends BaseServiceImpl<ShopOrderReturnM
}
/**
* 该函数用于判断某个订单商品是否禁止退货
* 该函数用于判断订单某个商品是否禁止退货判断订单的商品
* 参数校验检查订单商品和商品信息是否为空若为空则抛出异常
* 商品是否禁止退货从商品信息中获取消费者保障类型如果包含"禁止退货"则标记为不可退货
* 订单状态是否超过退货期限
* 如果订单状态为"已收货""已完成"并且当前时间超过允许提现时间则标记为不可退货
*
* @param shopOrderInfo
* @param shopOrderItem
* @param shopProductIndex
* @return
* @param shopOrderInfo 订单信息
* @param shopOrderItem 订单商品项
* @param shopProductIndex 商品索引信息
* @return boolean true表示禁止退货false表示允许退货
*/
public boolean ifDenyReturn(ShopOrderInfo shopOrderInfo, ShopOrderItem shopOrderItem, ShopProductIndex shopProductIndex) {
// 默认允许退货
boolean is_denyreturn = false;
// 1. 参数校验
if (shopOrderItem == null) {
throw new ApiException(I18nUtil._("此订单商品订单数据有误!"));
log.debug("[是否禁止退货] 订单商品数据为空 true");
return true;
}
if (shopProductIndex == null) {
shopProductIndex = shopProductIndexService.get(shopOrderItem.getProduct_id());
if (shopOrderInfo == null) {
log.debug("[是否禁止退货] 订单信息为空 true");
return true;
}
if (shopProductIndex == null) {
throw new ApiException(I18nUtil._("此订单商品数据有误!"));
String orderId = shopOrderInfo.getOrder_id();
Integer orderStateId = shopOrderInfo.getOrder_state_id();
if (StrUtil.isBlank(orderId) || CheckUtil.isEmpty(orderStateId)) {
log.debug("[是否禁止退货] 订单ID或订单状态为空 true");
return true;
}
List<Integer> contractTypeIds = Convert.toList(Integer.class, shopProductIndex.getContract_type_ids());
//start判断是否可以申请退款
// 1商品是否允许
if (contractTypeIds.contains(new Integer(StateCode.CONTRACT_TYPE_DENY_RETURN))) {
is_denyreturn = true;
throw new ApiException(I18nUtil._("此商品不允许退货!"));
if (orderStateId.intValue() == StateCode.ORDER_STATE_CANCEL ||
orderStateId.intValue() == StateCode.ORDER_STATE_WAIT_PAY) {
log.debug("[是否禁止退货] 订单已取消或未支付true order_id: {}", orderId);
return true;
}
// 2是否已经可结算, 进入可结算不允许退货
if (shopOrderInfo.getOrder_state_id().intValue() == StateCode.ORDER_STATE_RECEIVED || shopOrderInfo.getOrder_state_id().intValue() == StateCode.ORDER_STATE_FINISH) {
Long withdrawTime = shopOrderBaseService.getWithdrawTime();
// 2. 先判断整个订单是否可以退货订单级别检查
// 2.1 检查订单状态是否为已收货或已完成
if (orderStateId.intValue() == StateCode.ORDER_STATE_RECEIVED ||
orderStateId.intValue() == StateCode.ORDER_STATE_FINISH) {
try {
// 获取可提现时间戳
Long withdrawTime = shopOrderBaseService.getWithdrawTime();
Long orderDealTime = shopOrderInfo.getOrder_deal_time();
//order_qs_time
if (withdrawTime.compareTo(shopOrderInfo.getOrder_deal_time()) > 0) {
is_denyreturn = true;
throw new ApiException(I18nUtil._("此商品已过退货期,不允许退货!"));
// 检查是否超过退货期限
if (orderDealTime != null && withdrawTime.compareTo(orderDealTime) > 0) {
log.debug("[是否禁止退货] 订单已超过退货期限 trueorder_id: {}", orderId);
return true;
}
} catch (Exception e) {
log.error("[是否禁止退货] 检查订单退货期限时发生异常 trueorder_id: {}", orderId, e);
}
}
return is_denyreturn;
// 2.2 检查拉卡拉分账订单是否已提现
try {
if (lklOrderSeparateService != null && lklOrderDrawService != null) {
boolean isSeparated = lklOrderSeparateService.isOrderSeparated(orderId);
boolean isDrawn = lklOrderDrawService.isOrderDrawed(orderId);
if (isSeparated && isDrawn) {
log.debug("[是否禁止退货] 拉卡拉分账订单已提现,不允许退货 trueorder_id: {}", orderId);
return true;
}
}
} catch (Exception e) {
log.error("[是否禁止退货] 检查拉卡拉分账状态时发生异常order_id: {}", orderId, e);
}
Long productId = shopOrderItem.getProduct_id();
if (CheckUtil.isEmpty(productId)) {
log.debug("[是否禁止退货] 商品ID为空 true");
return true;
}
// 3. 再判断具体商品是否可以退货商品级别检查
// 获取商品索引信息
ShopProductIndex productIndex = shopProductIndex;
if (productIndex == null) {
productIndex = shopProductIndexService.get(productId);
}
if (productIndex == null) {
log.debug("[是否禁止退货] 商品索引信息不存在 trueproduct_id: {}", productId);
return true;
}
// 3.1 检查商品是否设置了禁止退货标识
String contractTypeIdsStr = productIndex.getContract_type_ids();
if (StrUtil.isNotBlank(contractTypeIdsStr)) {
try {
List<Integer> contractTypeIds = Convert.toList(Integer.class, contractTypeIdsStr);
if (contractTypeIds != null && contractTypeIds.contains(StateCode.CONTRACT_TYPE_DENY_RETURN)) {
log.debug("[是否禁止退货] 商品设置了禁止退货标识 trueorder_id: {}, product_id: {}", orderId, productId);
return true;
}
} catch (Exception e) {
log.error("[是否禁止退货] 解析商品保障类型失败 trueorder_id: {}, product_id: {}", orderId, productId, e);
}
}
// 默认允许退货
log.debug("[是否禁止退货] false}");
return false;
}
/**
* 判断订单中某个商品是否禁止退货
* <p>
* 该方法用于检查指定订单中的特定商品是否允许退货主要检查以下几种情况
* 1. 商品是否设置了"禁止退货"的消费者保障标识
* 2. 订单是否已超过退货期限已收货或已完成状态且超过可提现时间
* 3. 拉卡拉分账订单是否已完成提现
*
* @param orderId 订单ID
* @param productId 商品ID
* @return boolean true表示禁止退货false表示允许退货
*/
public boolean ifOrderItemDenyReturn(String orderId, Long productId) {
// 复用已有的方法逻辑避免重复代码
return ifDenyReturn(
shopOrderInfoService.get(orderId),
null, // 不需要具体的订单商品项信息
shopProductIndexService.get(productId)
);
}
/**
* 判断订单是否禁止退货
*
* @param orderId 订单ID
* @return 如果订单禁止退货返回true否则返回false
*/
@Override
public boolean isOrderDenyReturn(String orderId) {
// 参数校验
if (StrUtil.isBlank(orderId)) {
log.warn("[订单是否禁止退货] 订单ID为空无法判断退货状态");
return true;
}
try {
// 获取订单信息
ShopOrderInfo shopOrderInfo = shopOrderInfoService.get(orderId);
if (shopOrderInfo == null) {
log.error("[订单是否禁止退货] 订单信息不存在订单ID: {}", orderId);
return true;
}
// 检查订单状态是否已收货或已完成
Integer orderStateId = shopOrderInfo.getOrder_state_id();
if (CheckUtil.isEmpty(orderStateId)) {
log.warn("[订单是否禁止退货] 订单状态为空");
return true;
}
if (orderStateId.intValue() == StateCode.ORDER_STATE_CANCEL ||
orderStateId.intValue() == StateCode.ORDER_STATE_WAIT_PAY) {
log.debug("[是否禁止退货] 订单已取消或未支付order_id: {}", orderId);
return true;
}
if (orderStateId.intValue() == StateCode.ORDER_STATE_RECEIVED ||
orderStateId.intValue() == StateCode.ORDER_STATE_FINISH) {
// 获取可提现时间戳
Long withdrawTime = shopOrderBaseService.getWithdrawTime();
Long orderDealTime = shopOrderInfo.getOrder_deal_time();
log.debug("[订单是否禁止退货] 订单:{} 可提现时间戳: {},确认收货时间:{}", orderId, withdrawTime, orderDealTime);
// 如果订单成交时间早于可提现时间说明已过退货期
if (orderDealTime != null && withdrawTime.compareTo(orderDealTime) > 0) {
log.debug("[订单是否禁止退货] 订单:{} 已过退货期,不允许退货", orderId);
return true;
}
}
// 检查拉卡拉分账和提现状态
if (lklOrderSeparateService.isOrderSeparated(orderId) &&
lklOrderDrawService.isOrderDrawed(orderId)) {
log.debug("[订单是否禁止退货] 订单[{}]已提现,不允许退货", orderId);
return true;
}
// 默认允许退货
return false;
} catch (Exception e) {
log.error("[订单是否禁止退货] 查询订单{}退货状态异常", orderId, e);
return true;
}
}
/**
* 该函数用于判断指定订单商品是否禁止退货
* 根据 order_item_id 获取订单商品信息
@ -2210,7 +2357,7 @@ public class ShopOrderReturnServiceImpl extends BaseServiceImpl<ShopOrderReturnM
}
if (StrUtil.isBlank(remark)) {
remark = "整单退";
remark = "整单退";
}
// 判断此订单商品是否已有退款单
@ -2291,7 +2438,7 @@ public class ShopOrderReturnServiceImpl extends BaseServiceImpl<ShopOrderReturnM
}
if (StrUtil.isBlank(remark)) {
remark = "剩余商品退款!";
remark = "整单退款!";
}
// 获取订单中所有商品
@ -2561,12 +2708,14 @@ public class ShopOrderReturnServiceImpl extends BaseServiceImpl<ShopOrderReturnM
}
if (lklOrderSeparateService.isOrderSeparated(orderId)) {
// TODO 后期如果已经分账的订单一定强硬退款可能需要拉卡拉撤销分账再退款
// TODO 后期如果已经分账的订单一定强硬退款可能需要拉卡拉撤销分账再退款已提现的真的没有办法退款了
return CommonResult.failed("订单已三方结清,无法退款");
}
List<ShopOrderItem> orderItems = shopOrderItemService.find(new QueryWrapper<ShopOrderItem>().eq("order_id", orderId));
if (CollectionUtil.isEmpty(orderItems)) return CommonResult.failed("无可退货商品");
if (CollectionUtil.isEmpty(orderItems)) {
return CommonResult.failed("无可退货商品");
}
// === 3. 检查退货单 ===
ShopOrderReturn refundOrder = findOne(new QueryWrapper<ShopOrderReturn>()
@ -2723,9 +2872,10 @@ public class ShopOrderReturnServiceImpl extends BaseServiceImpl<ShopOrderReturnM
// 2是否已经超过退货期
if (shopOrderInfo.getOrder_state_id().intValue() == StateCode.ORDER_STATE_RECEIVED || shopOrderInfo.getOrder_state_id().intValue() == StateCode.ORDER_STATE_FINISH) {
// 可提现时间
Long withdrawTime = shopOrderBaseService.getWithdrawTime();
//order_qs_time
//order_deal_time 当前状态的处理时间
if (withdrawTime.compareTo(shopOrderInfo.getOrder_deal_time()) > 0) {
return "订单已超过退货期限,无法退货";
}

View File

@ -26,10 +26,8 @@ import com.suisung.mall.common.modules.store.ShopStoreSameCityTransportBase;
import com.suisung.mall.common.modules.store.ShopStoreSfOrder;
import com.suisung.mall.common.pojo.req.*;
import com.suisung.mall.common.pojo.res.ThirdApiRes;
import com.suisung.mall.common.utils.CheckUtil;
import com.suisung.mall.common.utils.CommonUtil;
import com.suisung.mall.common.utils.I18nUtil;
import com.suisung.mall.common.utils.JsonUtil;
import com.suisung.mall.common.pojo.to.AddressParseResultTO;
import com.suisung.mall.common.utils.*;
import com.suisung.mall.shop.message.service.PushMessageService;
import com.suisung.mall.shop.order.service.ShopOrderBaseService;
import com.suisung.mall.shop.order.service.ShopOrderInfoService;
@ -172,15 +170,23 @@ public class SFExpressApiServiceImpl implements SFExpressApiService {
return Pair.of(false, "联系人手机号不能为空");
}
AddressParseResultTO addressParseResultTO = AddressUtil.parseAddress(shopMchEntry.getStore_address());
// 解析城市名称
String cityName = "桂平市"; // 默认城市
// 去掉省市区的详细地址
String storeAddress = addressParseResultTO.getDetailAddress();
if (StrUtil.isNotBlank(shopMchEntry.getStore_area())) {
String[] areaNames = shopMchEntry.getStore_area().split("/");
if (areaNames.length > 0) {
if (areaNames.length >= 3) {
cityName = areaNames[areaNames.length - 1];
} else {
cityName = shopMchEntry.getStore_area().replace("/", "");
}
} else {
cityName = addressParseResultTO.getCity();
}
// 如果解析后城市名为空使用默认值
@ -199,7 +205,7 @@ public class SFExpressApiServiceImpl implements SFExpressApiService {
Convert.toInt(shopMchEntry.getStore_id()),
shopStoreName,
cityName,
shopMchEntry.getStore_address(),
storeAddress,
shopMchEntry.getContact_name(),
contactMobile,
shopMchEntry.getStore_longitude(),
@ -1040,7 +1046,7 @@ public class SFExpressApiServiceImpl implements SFExpressApiService {
pushRemark = "已完成配送";
orderStatus = StateCode.ORDER_STATE_RECEIVED; //已签收
// 通知微信用户确认收货(同城配送不能调用微信的确认收货)
// 顺丰送达后发出催促微信用户确认收货通知 (同城配送不能调用微信的确认收货)
wxOrderShippingService.notifyConfirmReceive(shopStoreSfOrder.getShop_order_id());
// 不要提前 订单确认收货等微信拉卡拉确认通知
@ -1136,13 +1142,14 @@ public class SFExpressApiServiceImpl implements SFExpressApiService {
throw new ApiException(I18nUtil._("状态处理失败!"));
}
// 通知微信用户确认收货同城配送不能调用该微信接口
// wxOrderShippingService.notifyConfirmReceive(shopStoreSfOrder.getShop_order_id());
String orderId = shopStoreSfOrder.getShop_order_id();
// 顺丰送达后发出催促微信用户确认收货通知 (同城配送不能调用微信的确认收货)
wxOrderShippingService.notifyConfirmReceive(orderId);
// 订单确认收货
// shopOrderBaseService.receive(shopStoreSfOrder.getShop_order_id(), null);
String orderId = shopStoreSfOrder.getShop_order_id();
// 消息推送
// JSONObject payload = new JSONObject();
@ -1150,7 +1157,6 @@ public class SFExpressApiServiceImpl implements SFExpressApiService {
// payload.put("orderId", orderId);
// pushMessageService.noticeMerchantEmployeeOrderAction(null, orderId, "", "顺丰同城订单[" + orderId + "]已完成配送。", null);
return new ThirdApiRes().success("success");
}

View File

@ -20,6 +20,14 @@ public interface ShopStoreInfoService extends IBaseService<ShopStoreInfo> {
Map getStoreInfoById(Integer store_id);
/**
* 根据店铺id获取店铺信息
*
* @param storeId
* @return
*/
ShopStoreInfo getShopStoreInfoByStoreId(Integer storeId);
Map getInfoList(QueryWrapper<ShopStoreInfo> queryWrapper, Integer pageNum, Integer pageSize);
/**

View File

@ -80,7 +80,6 @@ import org.springframework.transaction.annotation.Transactional;
import org.springframework.web.context.request.RequestContextHolder;
import org.springframework.web.context.request.ServletRequestAttributes;
import javax.annotation.Resource;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;
import java.io.Serializable;
@ -176,9 +175,6 @@ public class ShopStoreBaseServiceImpl extends BaseServiceImpl<ShopStoreBaseMappe
@Autowired
private ShopPageModuleService shopPageModuleService;
@Lazy
@Resource
private ShopStoreSameCityTransportBaseService storeSameCityTransportBaseService;
@Lazy
@Autowired
private ShopMchEntryService shopMchEntryService;
@Autowired
@ -3277,54 +3273,58 @@ public class ShopStoreBaseServiceImpl extends BaseServiceImpl<ShopStoreBaseMappe
return Pair.of(0, "店铺ID获取失败");
}
// 创建店铺信息
ShopStoreInfo shopStoreInfo = new ShopStoreInfo();
shopStoreInfo.setStore_id(storeId);
shopStoreInfo.setStore_start_time(DateUtil.date());
shopStoreInfo.setStore_end_time(DateUtil.offsetDay(DateUtil.date(), 365 * 5));
shopStoreInfo.setStore_opening_hours("07:30");
shopStoreInfo.setStore_close_hours("23:00");
shopStoreInfo.setStore_discount(BigDecimal.valueOf(10));
shopStoreInfo.setStore_banner(storeFacadeImage);
// 处理联系人信息
String contact_mobile = StrUtil.isNotBlank(shopMchEntry.getLegal_person_mobile()) ?
shopMchEntry.getLegal_person_mobile() : shopMchEntry.getLogin_mobile();
shopStoreInfo.setStore_tel(contact_mobile);
shopStoreInfo.setContact_mobile(contact_mobile);
shopStoreInfo.setContact_name(shopMchEntry.getContact_name());
// 构建幻灯片
JSONArray list = new JSONArray();
if (StrUtil.isNotBlank(storeFacadeImage)) {
JSONObject slide = new JSONObject();
slide.put("img", storeFacadeImage);
slide.put("name", "店铺门面照片");
slide.put("check", true);
slide.put("url", "https://www.gpxscs.cn");
list.put(slide);
}
if (StrUtil.isNotBlank(shopMchEntry.getEnvironment_image())) {
JSONObject slide = new JSONObject();
slide.put("img", shopMchEntry.getEnvironment_image());
slide.put("name", "店铺环境照片");
slide.put("check", true);
slide.put("url", "https://www.gpxscs.cn");
list.put(slide);
}
shopStoreInfo.setStore_slide(list.toString());
// 创建店铺信息
ShopStoreInfo shopStoreInfo = shopStoreInfoService.getShopStoreInfoByStoreId(storeId); // new ShopStoreInfo();
if (shopStoreInfo == null) {
shopStoreInfo = new ShopStoreInfo();
shopStoreInfo.setStore_id(storeId);
shopStoreInfo.setStore_start_time(DateUtil.date());
shopStoreInfo.setStore_end_time(DateUtil.offsetDay(DateUtil.date(), 365 * 5));
shopStoreInfo.setStore_opening_hours("08:00");
shopStoreInfo.setStore_close_hours("21:30");
shopStoreInfo.setStore_discount(BigDecimal.valueOf(10));
shopStoreInfo.setStore_banner(storeFacadeImage);
shopStoreInfo.setStore_tel(contact_mobile);
shopStoreInfo.setContact_mobile(contact_mobile);
shopStoreInfo.setContact_name(shopMchEntry.getContact_name());
if (shopMchEntry.getStore_address() != null) {
shopStoreInfo.setStore_address(shopMchEntry.getStore_address());
}
shopStoreInfo.setStore_state_id(StateCode.STORE_STATE_YES);
if (!shopStoreInfoService.save(shopStoreInfo)) {
logger.error("生成店铺新增店铺info失败");
if (Boolean.TRUE.equals(allowThrown)) {
throw new ApiException("新增店铺信息失败");
// 构建幻灯片
JSONArray list = new JSONArray();
if (StrUtil.isNotBlank(storeFacadeImage)) {
JSONObject slide = new JSONObject();
slide.put("img", storeFacadeImage);
slide.put("name", "店铺门面照片");
slide.put("check", true);
slide.put("url", "https://www.gpxscs.cn");
list.put(slide);
}
if (StrUtil.isNotBlank(shopMchEntry.getEnvironment_image())) {
JSONObject slide = new JSONObject();
slide.put("img", shopMchEntry.getEnvironment_image());
slide.put("name", "店铺环境照片");
slide.put("check", true);
slide.put("url", "https://www.gpxscs.cn");
list.put(slide);
}
shopStoreInfo.setStore_slide(list.toString());
if (shopMchEntry.getStore_address() != null) {
shopStoreInfo.setStore_address(shopMchEntry.getStore_address());
}
shopStoreInfo.setStore_state_id(StateCode.STORE_STATE_YES);
if (!shopStoreInfoService.save(shopStoreInfo)) {
logger.error("生成店铺新增店铺info失败");
if (Boolean.TRUE.equals(allowThrown)) {
throw new ApiException("新增店铺信息失败");
}
return Pair.of(0, "新增店铺信息失败");
}
return Pair.of(0, "新增店铺信息失败");
}
// 创建店铺公司信息
@ -3887,14 +3887,14 @@ public class ShopStoreBaseServiceImpl extends BaseServiceImpl<ShopStoreBaseMappe
bizState = CommonConstant.Disable2;
}
String store_opening_hours=getParameter("store_opening_hours");
String store_close_hours=getParameter("store_close_hours");
String store_opening_hours = getParameter("store_opening_hours");
String store_close_hours = getParameter("store_close_hours");
try {
if(StringUtils.isNotEmpty(store_close_hours)){
UpdateWrapper<ShopStoreInfo> shopStoreInfoUpdateWrapper=new UpdateWrapper<>();
shopStoreInfoUpdateWrapper.eq("store_id",storeId);
shopStoreInfoUpdateWrapper.set("store_opening_hours",store_opening_hours);
shopStoreInfoUpdateWrapper.set("store_close_hours",store_close_hours);
if (StringUtils.isNotEmpty(store_close_hours)) {
UpdateWrapper<ShopStoreInfo> shopStoreInfoUpdateWrapper = new UpdateWrapper<>();
shopStoreInfoUpdateWrapper.eq("store_id", storeId);
shopStoreInfoUpdateWrapper.set("store_opening_hours", store_opening_hours);
shopStoreInfoUpdateWrapper.set("store_close_hours", store_close_hours);
shopStoreInfoService.update(shopStoreInfoUpdateWrapper);
}
// 使用 UpdateWrapper 更新店铺营业状态

View File

@ -53,6 +53,13 @@ public class ShopStoreInfoServiceImpl extends BaseServiceImpl<ShopStoreInfoMappe
return shopStoreInfoMapper.getStoreInfoById(store_id);
}
@Override
public ShopStoreInfo getShopStoreInfoByStoreId(Integer storeId) {
QueryWrapper<ShopStoreInfo> queryWrapper = new QueryWrapper<>();
queryWrapper.eq("store_id", storeId);
return findOne(queryWrapper);
}
@Override
public Map getInfoList(QueryWrapper<ShopStoreInfo> queryWrapper, Integer pageNum, Integer pageSize) {
Page<ShopStoreInfo> lists = lists(queryWrapper, pageNum, pageSize);

View File

@ -128,21 +128,17 @@ public class WxOrderShippingServiceImpl implements WxOrderShippingService {
// Step 4: Prepare request payload
JSONArray shippingList = new JSONArray().put(shippingItem);
// String mchId = orderBaseInfo.getMch_id();
JSONObject paramsJSON = new JSONObject()
.set("order_key", new JSONObject().set("order_number_type", 2).set("transaction_id", orderBaseInfo.getTransaction_id()))
// .set("order_key", new JSONObject().set("order_number_type", 1).set("out_trade_no", orderBaseInfo.getOut_trade_no()).set("mchid", mchId))
.set("delivery_mode", 1)
.set("logistics_type", logisticsType)
.set("shipping_list", shippingList)
.set("upload_time", DateTimeUtils.formatDateTimeRFC3339(new Date()))
.set("payer", new JSONObject().set("openid", orderBaseInfo.getOpen_id()));
// Step 5: Send request to WeChat API
String postUrl = "https://api.weixin.qq.com/wxa/sec/order/upload_shipping_info?access_token=" + accessToken;
log.debug("发货信息录入请求: {} \n {}", postUrl, paramsJSON);
log.debug("发货信息录入请求: {} \n 响应数据 {}", postUrl, paramsJSON);
JSONObject respObj = RestTemplateHttpUtil.sendPost(
postUrl,
@ -161,7 +157,7 @@ public class WxOrderShippingServiceImpl implements WxOrderShippingService {
return Pair.of(false, "发货信息录入失败: " + errorMsg);
}
// 跳转链接设置
// 服务号发货通知跳转链接设置
setMsgJumpPath(orderId);
log.info("发货信息录入成功, 订单ID: {}", orderId);
@ -235,9 +231,9 @@ public class WxOrderShippingServiceImpl implements WxOrderShippingService {
return Pair.of(false, "通知微信用户确认收货失败: " + errorMsg);
}
// 跳转链接设置
/// 服务号催促确认收货通知跳转链接设置
setMsgJumpPath(orderId);
log.info("通知微信用户确认收货成功, 订单ID: {}", orderId);
return Pair.of(true, "通知微信用户确认收货成功");

View File

@ -655,6 +655,7 @@
<!--refundstatus 退款状态:0-是无退款;1-是部分退款;2-是全部退款
orderstatus 订单状态2010-待付款;2011-待订单审核;2012-待发货;2013-待财务审核;2014-待配货/待出库审核;2020-待发货;
2030-待发货/待收货确认;2040-已发货/待收货确认;2050-已签收;2060-已完成/已签收;2070-已取消/已作废;2080-自提-->
<!-- status: 同城配送订单状态delivery=1时才生效无值 or 0-全部订单1-进行中订单2-异常超时订单3-退款订单9-已完成订单-->
<!-- 公共的where条件片段 -->
<sql id="mchOrderWhereCondition">
<where>
@ -684,12 +685,12 @@
<choose>
<!-- 1-进行中订单 -->
<when test="status != null and status == 1 and expireSeconds != null and expireSeconds > 0">
AND ob.order_state_id IN (2011,2012,2013, 2014, 2020, 2030, 2040)
AND ob.order_state_id IN (2011,2012,2013,2014,2020,2030,2040)
AND (oi.order_time + #{expireSeconds}*1000) <![CDATA[>=]]> UNIX_TIMESTAMP() * 1000
</when>
<!-- 2-异常(超时)订单 -->
<when test="status != null and status == 2 and expireSeconds != null and expireSeconds > 0">
AND ob.order_state_id IN (2011,2012,2013, 2014, 2020, 2030, 2040)
AND ob.order_state_id IN (2011,2012,2013,2014,2020,2030,2040)
AND (oi.order_time + #{expireSeconds}*1000) <![CDATA[<]]> UNIX_TIMESTAMP() * 1000
</when>
<!-- 3-退款订单 -->

View File

@ -11,7 +11,8 @@
order_is_received, chain_id, delivery_type_id, order_is_offline, cart_type_id, order_express_print, activity_id,
activity_type_id, salesperson_id, order_is_sync, store_is_selfsupport, store_type, order_erp_id,
distributor_user_id, order_is_cb, order_is_cb_sync, src_order_id, order_is_transfer, order_is_transfer_note,
order_fx_is_settlemented, order_fx_settlement_time, order_pickup_num,order_picked_notice_count,order_picked_time
order_fx_is_settlemented, order_fx_settlement_time, order_pickup_num,order_picked_notice_count,order_picked_time,
booking_state, booking_begin_time, booking_end_time,created_at, updated_at
</sql>
<!--// refundstatus 退款状态:0-是无退款;1-是部分退款;2-是全部退款