记得上下班打卡 | git大法好,push需谨慎

Commit e8922fa6 authored by 姜秀龙's avatar 姜秀龙

sqb 定时全部退完善

parent cf058708
......@@ -39,8 +39,9 @@ public interface IGoblinSqbService {
/**
* 演出结束自动退款(定时任务调用)
* TODO
* @param performancesId 演出ID
* SQL 已联表过滤:收钱吧扩展单、主单已支付(2)、演出已结束、扩展未核销;循环内仅调 refund。
*
* @param performancesId 演出ID,传 null 或空则不按演出缩小(全库符合条件候选,慎用)
* @return 处理结果摘要(成功/失败笔数)
*/
ResponseDto<String> autoRefundByPerformance(String performancesId);
......
......@@ -58,8 +58,8 @@ info:
artifactId: '@project.artifactId@'
version: '@project.version@'
# -----------------------------------------------------------
#mybatis-plus:
# mapper-locations: classpath*:com.liquidnet.service.*.mapper/*Mapper.xml
mybatis-plus:
mapper-locations: classpath*:com.liquidnet.service.*.mapper/*Mapper.xml
# -----------------------------------------------------------
spring:
application:
......
......@@ -2,6 +2,9 @@ package com.liquidnet.service.goblin.mapper;
import com.liquidnet.service.goblin.entity.GoblinSqbOrder;
import com.baomidou.mybatisplus.core.mapper.BaseMapper;
import org.apache.ibatis.annotations.Param;
import java.util.List;
/**
* <p>
......@@ -13,4 +16,8 @@ import com.baomidou.mybatisplus.core.mapper.BaseMapper;
*/
public interface GoblinSqbOrderMapper extends BaseMapper<GoblinSqbOrder> {
/**
* 联表过滤:主单已支付(2)、演出已结束、扩展未核销;可选按演出 id 缩小范围
*/
List<GoblinSqbOrder> selectAutoRefundCandidates(@Param("performancesId") String performancesId);
}
<?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.liquidnet.service.goblin.mapper.GoblinSqbOrderMapper">
<!-- 收钱吧扩展单 + 主单已支付 + 演出已结束 + 未核销(定时自动退候选) -->
<select id="selectAutoRefundCandidates" resultType="com.liquidnet.service.goblin.entity.GoblinSqbOrder">
SELECT so.*
FROM goblin_sqb_order so
INNER JOIN goblin_store_order o ON o.order_id = so.order_id
INNER JOIN kylin_performances kp ON kp.performances_id = so.performances_id
WHERE (so.coupon_used_status = 0 OR so.coupon_used_status IS NULL)
AND o.status = 2
AND kp.time_end &lt; NOW()
AND so.performances_id IS NOT NULL
AND so.performances_id != ''
<if test="performancesId != null and performancesId != ''">
AND so.performances_id = #{performancesId}
</if>
</select>
</mapper>
......@@ -31,6 +31,6 @@ public interface FeignGoblinTaskClient {
ResponseDto<Boolean> refundRes();
@PostMapping("/goblin/job/sqb/autoRefund")
ResponseDto<String> sqbAutoRefund(@RequestParam("performancesId") String performancesId);
ResponseDto<String> sqbAutoRefund(@RequestParam(value = "performancesId", required = false) String performancesId);
}
......@@ -71,11 +71,11 @@ public class GoblinTaskHandler {
/**
* 演出结束自动退款
* xxl-job 配置:JobHandler = sev-goblin:sqbAutoRefund,任务参数传入 performancesId
* xxl-job 配置:JobHandler = sev-goblin:sqbAutoRefund;参数为演出ID、或 performancesId=xxx;空则走 goblin 全库候选(慎用)
*/
@XxlJob(value = "sev-goblin:sqbAutoRefund")
public void sqbAutoRefund() {
String performancesId = XxlJobHelper.getJobParam();
String performancesId = parseSqbAutoRefundPerformancesId(XxlJobHelper.getJobParam());
try {
XxlJobHelper.handleSuccess("结果:" + feignGoblinTaskClient.sqbAutoRefund(performancesId).getData());
} catch (Exception e) {
......@@ -83,4 +83,27 @@ public class GoblinTaskHandler {
XxlJobHelper.handleFail();
}
}
/** 支持裸演出ID、或 performancesId=xxx(可与其他 & 参数混排) */
private static String parseSqbAutoRefundPerformancesId(String raw) {
if (raw == null) {
return null;
}
raw = raw.trim();
if (raw.isEmpty()) {
return null;
}
for (String part : raw.split("&")) {
part = part.trim();
int eq = part.indexOf('=');
if (eq > 0 && "performancesid".equalsIgnoreCase(part.substring(0, eq).trim())) {
String v = part.substring(eq + 1).trim();
return v.isEmpty() ? null : v;
}
}
if (!raw.contains("=")) {
return raw;
}
return null;
}
}
......@@ -19,7 +19,7 @@ import org.springframework.web.bind.annotation.RestController;
* - JobHandler:sev-goblin:sqbAutoRefund
* - CRON:按演出结束时间触发(如演出结束后 5 分钟:0 5 * * * ?,具体由运维根据演出时间动态配置)
* - 执行器:liquidnet-service-executor
* - 任务参数:performancesId=xxx(演出ID
* - 任务参数:演出ID 或 performancesId=xxx;留空则处理全库「演出已结束 + 主单已支付 + 扩展未核销」候选(慎用
* - 路由策略:第一个
*/
@Slf4j
......@@ -33,7 +33,7 @@ public class GoblinSqbJobController {
@PostMapping("/autoRefund")
@ApiOperation("演出结束自动退款")
public ResponseDto<String> autoRefund(@RequestParam("performancesId") String performancesId) {
public ResponseDto<String> autoRefund(@RequestParam(value = "performancesId", required = false) String performancesId) {
log.info("[收钱吧自动退款] 收到任务,performancesId={}", performancesId);
return goblinSqbService.autoRefundByPerformance(performancesId);
}
......
......@@ -261,34 +261,52 @@ public class GoblinSqbServiceImpl implements IGoblinSqbService {
@Override
public ResponseDto<String> autoRefundByPerformance(String performancesId) {
log.info("[收钱吧自动退款] 开始处理演出 performancesId={}", performancesId);
String pid = performancesId == null ? null : performancesId.trim();
if (pid != null && pid.isEmpty()) {
pid = null;
}
if (pid == null) {
log.warn("[收钱吧自动退款] performancesId 为空,将处理库内所有「演出已结束 + 主单已支付 + 扩展未核销」候选单");
} else {
log.info("[收钱吧自动退款] 开始 performancesId={}", pid);
}
// 查询该演出下 status=1(已支付)的订单(MySQL)
// TODO: 通过 GoblinSqbOrderMapper 查询(需注入后解注释)
// LambdaQueryWrapper<GoblinSqbOrder> query = new LambdaQueryWrapper<>();
// query.eq(GoblinSqbOrder::getPerformancesId, performancesId).eq(GoblinSqbOrder::getCouponUsedStatus, 0);
// List<GoblinSqbOrder> orders = goblinSqbOrderMapper.selectList(query);
List<GoblinSqbOrder> orders = goblinSqbOrderMapper.selectAutoRefundCandidates(pid);
if (CollectionUtils.isEmpty(orders)) {
String scope = pid != null ? ("演出 " + pid) : "全库(演出已结束)";
String summary = scope + " 无待自动退款的收钱吧扩展单";
log.info("[收钱吧自动退款] {}", summary);
return ResponseDto.success(summary);
}
int successCount = 0;
int failCount = 0;
// TODO: 取消注释并接入 GoblinSqbOrderMapper 后启用
// for (GoblinSqbOrder order : orders) {
// try {
// ResponseDto<Boolean> result = refund(order.getUserId(), order.getOrderId());
// if (result != null && result.isSuccess()) {
// successCount++;
// } else {
// log.warn("[收钱吧自动退款] 订单退款失败 orderId={}", order.getOrderId());
// failCount++;
// }
// } catch (Exception e) {
// log.error("[收钱吧自动退款] 订单退款异常 orderId={}", order.getOrderId(), e);
// failCount++;
// }
// }
String summary = String.format("演出 %s 自动退款完成:成功 %d 笔,失败 %d 笔", performancesId, successCount, failCount);
for (GoblinSqbOrder order : orders) {
String orderId = order.getOrderId();
String userId = order.getUserId();
if (orderId == null || orderId.trim().isEmpty() || userId == null || userId.trim().isEmpty()) {
log.warn("[收钱吧自动退款] 扩展单缺少 orderId/userId,跳过 mid={}", order.getMid());
failCount++;
continue;
}
try {
ResponseDto<Boolean> result = refund(userId, orderId, "演出结束自动退款");
if (result != null && result.isSuccess() && Boolean.TRUE.equals(result.getData())) {
successCount++;
} else {
log.warn("[收钱吧自动退款] 退款失败 orderId={}, msg={}", orderId,
result != null ? result.getMessage() : "null");
failCount++;
}
} catch (Exception e) {
log.error("[收钱吧自动退款] 订单退款异常 orderId={}", orderId, e);
failCount++;
}
}
String scopeLabel = pid != null ? ("演出 " + pid) : "全库(演出已结束)";
String summary = String.format("%s 自动退款完成:成功 %d 笔,失败 %d 笔", scopeLabel, successCount, failCount);
log.info("[收钱吧自动退款] {}", summary);
return ResponseDto.success(summary);
}
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment