package com.fs.task; import com.fs.common.annotation.QuartzRunnable; import com.fs.common.core.redis.RedisCache; import com.fs.erp.domain.ErpDeliverys; import com.fs.erp.domain.ErpOrderQuery; import com.fs.erp.dto.ErpOrderQueryRequert; import com.fs.erp.dto.ErpOrderQueryResponse; import com.fs.erp.service.FsJstAftersalePushService; import com.fs.erp.service.IErpOrderService; import com.fs.erp.utils.ErpContextHolder; import com.fs.express.FsStoreDeliversService; import com.fs.common.utils.StringUtils; import com.fs.huifuPay.domain.HuiFuQueryOrderResult; import com.fs.huifuPay.sdk.opps.core.request.V2TradePaymentScanpayQueryRequest; import com.fs.live.domain.LiveOrderPayment; import com.fs.live.mapper.LiveOrderPaymentMapper; import com.fs.live.vo.LiveOrderPaymentVo; import com.fs.pay.pay.domain.OrderResult; import com.fs.pay.pay.dto.OrderQueryDTO; import com.fs.pay.pay.service.PayService; import com.fs.huifuPay.service.HuiFuService; import com.fs.live.utils.redis.RedisBatchHandler; import com.fs.live.domain.LiveAfterSales; import com.fs.live.domain.LiveOrder; import com.fs.live.service.*; import com.fs.store.domain.FsExpress; import com.fs.store.enums.OrderLogEnum; import com.fs.store.mapper.*; import com.fs.store.param.LiveAfterSalesAudit1Param; import com.fs.store.service.*; import org.apache.commons.collections4.CollectionUtils; import org.apache.commons.lang.ObjectUtils; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.scheduling.annotation.Scheduled; import org.springframework.stereotype.Component; import java.text.ParseException; import java.text.SimpleDateFormat; import java.util.List; import java.util.concurrent.TimeUnit; import static com.fs.live.utils.redis.RedisBatchHandler.CONSUME_INTERVAL; /** * 定时任务调度 * @author fs */ @Component("liveTask") public class LiveTask { Logger logger = LoggerFactory.getLogger(LiveTask.class); @Autowired private ILiveOrderService liveOrderService; @Autowired private LiveOrderPaymentMapper liveOrderPaymentMapper; @Autowired private HuiFuService huiFuService; @Autowired private PayService ybPayService; @Autowired private ILiveAfterSalesService afterSalesService; @Autowired private IErpOrderService erpOrderService; @Autowired private IFsExpressService expressService; @Autowired private ILiveOrderLogsService orderLogsService; @Autowired private FsWarehousesMapper fsWarehousesMapper; @Autowired public FsJstAftersalePushService fsJstAftersalePushService; @Autowired public RedisBatchHandler redisBatchHandler; @Autowired private IFsUserService fsUserService; @Autowired private RedisCache redisCache; private static final String APP_USER_SYNC_TASK_LOCK_KEY = "task:live:app_user_sync:lock"; private static final long APP_USER_SYNC_TASK_LOCK_SECONDS = 600L; /** 两个 APP 用户同步任务错峰启动间隔(秒) */ private static final long APP_USER_SYNC_TASK_STAGGER_SECONDS = 15L; // 订单银行回调数据丢失补偿 public void recoveryBankOrder() { // 查询出来最近15分钟的订单 待支付 未退款 List list = liveOrderService.selectBankOrder(); if (CollectionUtils.isEmpty(list)) { return; } for (LiveOrder order : list) { try { LiveOrderPaymentVo payment = liveOrderPaymentMapper.selectLiveOrderPaymentByPaymentIdNew(order.getOrderId()); if (payment == null || payment.getStatus() == null || payment.getStatus() != 0) { continue; } if (StringUtils.isEmpty(payment.getTradeNo()) || StringUtils.isEmpty(payment.getPayMode())) { continue; } String payMode = payment.getPayMode(); if ("hf".equals(payMode)) { V2TradePaymentScanpayQueryRequest request = new V2TradePaymentScanpayQueryRequest(); request.setOrgReqDate(new SimpleDateFormat("yyyyMMdd").format(payment.getCreateTime())); request.setOrgHfSeqId(payment.getTradeNo()); HuiFuQueryOrderResult o = huiFuService.queryOrder(request); logger.info("直播订单补偿 汇付查询 orderId={} resp={}", order.getOrderId(), o); if (o != null && "00000000".equals(o.getResp_code()) && "S".equals(o.getTrans_stat())) { String[] parts = o.getOrg_req_seq_id().split("-"); if (parts.length >= 2 && "live".equals(parts[0])) { liveOrderService.payConfirm(1, null, parts[1], o.getOrg_hf_seq_id(), o.getOut_trans_id(), o.getParty_order_id()); } } } else if ("yb".equals(payMode)) { OrderQueryDTO q = new OrderQueryDTO(); q.setUpOrderId(payment.getTradeNo()); OrderResult orderResult = ybPayService.getOrder(q); if (orderResult == null) { continue; } if ("4".equals(orderResult.getState()) || "5".equals(orderResult.getState())) { continue; } if (!"0".equals(orderResult.getState()) || !"100".equals(orderResult.getStatus())) { continue; } String[] parts = orderResult.getLowOrderId().split("-"); if (parts.length >= 2 && "live".equals(parts[0])) { liveOrderService.payConfirm(1, null, parts[1], payment.getTradeNo(), orderResult.getBankTrxId(), orderResult.getBankOrderId()); } } else if ("tzbk".equals(payMode)) { logger.debug("直播订单补偿跳过台州银行支付 orderId={}", order.getOrderId()); } } catch (Exception e) { logger.error("直播订单银行补偿失败 orderId={}", order.getOrderId(), e); } } } /** * 超时订单自动取消 */ @QuartzRunnable(name = "超时订单自动取消") public void orderCancel(){ liveOrderService.orderCancel(); } /** * 发货任务 */ @QuartzRunnable(name = "发货任务") public void deliveryOp() { List list = liveOrderService.selectDeliverPenddingData(); for (LiveOrder order : list) { String orderCode = order.getOrderCode(); ErpOrderQueryRequert request = new ErpOrderQueryRequert(); request.setCode(order.getExtendOrderId()); try { // 根据仓库code找erp if (com.fs.common.utils.StringUtils.isNotBlank(order.getStoreHouseCode())) { String erp = fsWarehousesMapper.selectErpByCode(order.getStoreHouseCode()); ErpContextHolder.setErpType(erp); } ErpOrderQueryResponse response = erpOrderService.getOrderLive(request); if (CollectionUtils.isNotEmpty(response.getOrders())) { for (ErpOrderQuery orderQuery : response.getOrders()) { if (CollectionUtils.isNotEmpty(orderQuery.getDeliverys())) { // 部分发货或者全部发货 if (ObjectUtils.equals(orderQuery.getDelivery_state(), 1) || ObjectUtils.equals(orderQuery.getDelivery_state(), 2)) { orderLogsService.create(order.getOrderId(), OrderLogEnum.DELIVERY_GOODS.getValue(), OrderLogEnum.DELIVERY_GOODS.getDesc()); for (ErpDeliverys delivery : orderQuery.getDeliverys()) { FsExpress express = expressService.selectFsExpressByOmsCode(delivery.getExpress_code()); if (express == null) { logger.warn("当前express_code: {} 不存在!", delivery.getExpress_code()); continue; } if (delivery.getDelivery()) { liveOrderService.deliveryOrder(orderCode, delivery.getMail_no(), delivery.getExpress_code(), delivery.getExpress_name()); } } logger.info("订单 {} 发货信息同步成功", order.getOrderCode()); } } } } } catch (Exception e) { logger.error(String.format("[发货任务]调用erp查询接口失败!原因: %s", e)); } } } /** * 同步近三天直播订单关联的APP用户数据 */ @QuartzRunnable(name = "同步APP用户数据") public void syncAppUser() { if (!tryAcquireAppUserSyncLock()) { logger.debug("同步APP用户数据任务跳过,其他任务正在执行"); return; } try { fsUserService.syncAppUsersForRecentLiveOrders(3); } catch (Exception e) { logger.error("同步APP用户数据失败", e); } finally { releaseAppUserSyncLock(); } } /** * 从 Redis 拉取下单时缓存的待同步 APP 用户并同步 */ @QuartzRunnable(name = "同步APP用户数据(Redis)") public void syncAppUserFromRedis() { try { Thread.sleep(APP_USER_SYNC_TASK_STAGGER_SECONDS * 1000); } catch (InterruptedException e) { Thread.currentThread().interrupt(); return; } if (!tryAcquireAppUserSyncLock()) { logger.debug("Redis同步APP用户数据任务跳过,其他任务正在执行"); return; } try { fsUserService.syncPendingAppUsersFromRedis(); } catch (Exception e) { logger.error("Redis同步APP用户数据失败", e); } finally { releaseAppUserSyncLock(); } } private boolean tryAcquireAppUserSyncLock() { return redisCache.setIfAbsent(APP_USER_SYNC_TASK_LOCK_KEY, "1", APP_USER_SYNC_TASK_LOCK_SECONDS, TimeUnit.SECONDS); } private void releaseAppUserSyncLock() { redisCache.deleteObject(APP_USER_SYNC_TASK_LOCK_KEY); } /** * 退款自动处理 24小时未审核自动审核通过 每小时执行一次 */ @QuartzRunnable(name = "直播售后自动审核") public void refundOp() { //获取所有退款申请 List list = afterSalesService.selectLiveAfterSalesByDoAudit(); if (list != null) { for (LiveAfterSales afterSales : list) { //仅退款 // if (afterSales.getServiceType().equals(0)) { LiveAfterSalesAudit1Param audit1Param = new LiveAfterSalesAudit1Param(); audit1Param.setSalesId(afterSales.getId()); audit1Param.setOperator("平台"); afterSalesService.audit1(audit1Param); // } } } } /** * 批量推管易 * @throws ParseException 解析异常 */ @QuartzRunnable(name = "批量推管易") public void updateOrderItem() throws ParseException { List ids = liveOrderService.selectOrderIdByNoErp(); for (Long id : ids) { try{ liveOrderService.createOmsOrder(id); }catch (Exception e){ logger.error("推送管易失败 {}",id,e); } } } @Autowired FsStoreDeliversService fsStoreDeliverService; /** * 同步物流状态 */ @QuartzRunnable(name = "直播同步物流状态") public void syncExpress() { List ids = liveOrderService.selectSyncExpressIds(); for (Long id : ids) { liveOrderService.syncExpress(id); fsStoreDeliverService.finishOrder(id,1); } } /** * 更新发货状态 */ @QuartzRunnable(name = "直播发货任务") public void updateExpress() { List list = liveOrderService.selectUpdateExpress(); for (LiveOrder order : list) { try{ liveOrderService.syncDeliveryOrder(order); }catch (Exception e) { logger.error("获取订单是否发货失败!原因: ",e); } } } /** * 更新流量 */ @Scheduled(fixedRate = CONSUME_INTERVAL) public void insertLiveTrralog() { redisBatchHandler.consumeBatchData(); } }