Merge remote-tracking branch 'origin/master'

# Conflicts:
#	ghy-payment/src/main/resources/mapper/financial/OrderFineRecordMapper.xml
This commit is contained in:
kuang.yife 2023-05-11 10:58:37 +08:00
commit ba8a37c77d
15 changed files with 434 additions and 78 deletions

View File

@ -5,6 +5,8 @@ import com.alibaba.fastjson.JSONObject;
import com.ghy.common.adapay.model.AdapayStatusEnum;
import com.ghy.common.enums.AdapayOrderType;
import com.ghy.common.utils.AdapayUtils;
import com.ghy.customer.domain.CustomerBank;
import com.ghy.customer.service.CustomerBankService;
import com.ghy.order.service.OrderDetailService;
import com.ghy.payment.domain.DrawCashRecord;
import com.ghy.payment.mapper.DrawCashRecordMapper;
@ -39,6 +41,8 @@ public class AdapaySyncTimer {
@Resource
private WorkerBankService workerBankService;
@Resource
private CustomerBankService customerBankService;
@Resource
private OrderDetailService orderDetailService;
@Resource
private DrawCashRecordMapper drawCashRecordMapper;
@ -75,6 +79,33 @@ public class AdapaySyncTimer {
log.error(e.getMessage(), e);
}
}
List<CustomerBank> customerBanks = customerBankService.getCustomerBankList(new CustomerBank());
for (CustomerBank customer : customerBanks) {
Long deptId = customer.getDeptId();
String memberId = customer.getAdapayMemberId();
String settleAccountId = customer.getSettleAccountId();
if (deptId == null || StringUtils.isBlank(memberId) || StringUtils.isBlank(settleAccountId)) {
continue;
}
try {
JSONObject accountBalance = adapayService.queryAccountBalance(deptId, memberId, settleAccountId, "01");
if (AdapayStatusEnum.succeeded.code.equals(accountBalance.getString("status"))) {
// 可提现金额
String avlBalance = accountBalance.getString("avl_balance");
if (BigDecimal.ZERO.compareTo(new BigDecimal(avlBalance)) > -1) {
continue;
}
// 提现
log.info("Customer[{},{}]开始提现: avlBalance={}", customer.getCustomerId(), customer.getName(), avlBalance);
String orderNo = AdapayUtils.createOrderNo(AdapayOrderType.DRAW_CASH);
JSONObject drawCash = adapayService.drawCash(deptId, orderNo, "T1", avlBalance, memberId, "提现", null);
log.info("Customer[{},{}]提现结果: {}", customer.getCustomerId(), customer.getName(), drawCash.toJSONString());
}
} catch (BaseAdaPayException e) {
log.error(e.getMessage(), e);
}
}
}
@Scheduled(fixedRate = 5 * 60 * 1000L)

View File

@ -22,20 +22,8 @@
</resultMap>
<sql id="selectCustomerBank">
SELECT customer_bank_id,
settle_account_id,
customer_id,
name,
cert_id,
bank_name,
bank_num,
phone,
dept_id,
adapay_member_id,
settle_account,
create_by,
create_time,
remark
SELECT customer_bank_id, settle_account_id, customer_id, name, cert_id, bank_name, bank_num, phone, dept_id,
adapay_member_id, settle_account, create_by, create_time, update_by, update_time, remark
FROM customer_bank
</sql>

View File

@ -113,4 +113,14 @@ public class OrderMaster extends BaseEntity {
private Boolean shelveStatus;
private List<Long> exceptOrderMasterIds;
/**
* 是否超时 1= 0=
*/
private Integer timeout;
/**
* 超时扣款次数
*/
private Integer timeoutFineTimes;
}

View File

@ -89,4 +89,22 @@ public interface OrderMasterMapper {
List<OrderMaster> selectByIds(@Param("orderMasterId") Collection<Long> orderMasterIds);
int updatePayStatus(@Param("orderMasterId") Long orderMasterId, @Param("payStatus") Integer payStatus);
/**
* 更新主订单超时状态
*
* @param id 主订单ID
* @param timeout 是否超时
* @param timeoutFineTimes 超时罚款次数
* @return 1
*/
int updateTimeout(@Param("id") Long id, @Param("timeout") int timeout, @Param("timeoutFineTimes") Integer timeoutFineTimes);
/**
* 移除主订单的师傅ID
*
* @param id 主订单ID
* @return 1
*/
int removeWorker(Long id);
}

View File

@ -135,4 +135,31 @@ public interface OrderMasterService {
* @return true/false
*/
boolean isAllAssign(Long orderMasterId);
/**
* 更新主订单超时状态
*
* @param id 主订单ID
* @param timeout 是否超时
* @return 1
*/
int updateTimeout(Long id, int timeout);
/**
* 更新子订单超时状态
*
* @param id 子订单ID
* @param timeout 是否超时
* @param timeoutFineTimes 超时罚款次数
* @return 1
*/
int updateTimeout(Long id, int timeout, int timeoutFineTimes);
/**
* 移除主订单的师傅ID
*
* @param id 主订单ID
* @return 1
*/
int removeWorker(Long id);
}

View File

@ -23,6 +23,8 @@ import com.ghy.order.service.OrderMasterService;
import com.ghy.payment.domain.FinancialChangeRecord;
import com.ghy.payment.domain.FinancialDetail;
import com.ghy.payment.domain.FinancialMaster;
import com.ghy.payment.domain.OrderTimeoutRecord;
import com.ghy.payment.mapper.OrderFineRecordMapper;
import com.ghy.payment.service.AdapayService;
import com.ghy.payment.service.FinancialChangeRecordService;
import com.ghy.payment.service.FinancialDetailService;
@ -79,6 +81,8 @@ public class OrderDetailServiceImpl implements OrderDetailService {
private FinancialChangeRecordService financialChangeRecordService;
@Resource
private OrderGoodsService orderGoodsService;
@Resource
private OrderFineRecordMapper orderFineRecordMapper;
// Adapay 手续费率 默认0.008
@Value("${adapay.fee_rate:0.008}")
@ -404,6 +408,7 @@ public class OrderDetailServiceImpl implements OrderDetailService {
if (orderDetail == null) {
throw new BaseException("找不到对应的子订单");
}
OrderMaster orderMaster = orderMasterService.selectById(orderDetail.getOrderMasterId());
String odCode = orderDetail.getCode();
Assert.isTrue(!orderDetail.getOrderStatus().equals(OrderStatus.FINISH.code()), "订单已经是完成状态");
FinancialMaster financialMaster = financialMasterService.selectByOrderMasterId(orderDetail.getOrderMasterId());
@ -457,11 +462,45 @@ public class OrderDetailServiceImpl implements OrderDetailService {
if (paid || payedAdd) {
ArrayList<DivMember> divMembers = new ArrayList<>();
addPrice = fcRecord.getChangeMoney();
// 待提现金额里加入改价单金额
dtx = dtx.add(fcRecord.getChangeMoney());
// 这里先自己承担手续费 后面再用平台抽成来补偿
DivMember divMember = new DivMember(memberId, AdapayUtils.bigDecimalToString(fcRecord.getChangeMoney()), true);
divMembers.add(divMember);
BigDecimal fineMoney = BigDecimal.ZERO;
// 查询师傅的超时扣款记录
List<OrderTimeoutRecord> fineRecords = orderFineRecordMapper.selectUnFine(orderDetail.getWorkerId(), orderMaster.getDeptId());
ArrayList<Long> fineIds = new ArrayList<>();
for (OrderTimeoutRecord fineRecord : fineRecords) {
// 抵扣超时罚金 这里的罚金是按创建时间升序排列的 优先抵扣最早的罚金
if (fineMoney.add(fineRecord.getPayMoney()).compareTo(fcRecord.getChangeMoney()) > 0) {
// 加价单金额不足以抵扣罚金
logger.info("子订单[{}]的加价单[{}]不足以抵扣罚金{}元", orderDetailId, fcRecord.getId(), fineRecord.getPayMoney());
break;
} else {
// 抵扣罚金
logger.info("子订单[{}]的加价单[{}]抵扣罚金{}元", orderDetailId, fcRecord.getId(), fineRecord.getPayMoney());
fineMoney = fineMoney.add(fineRecord.getPayMoney());
// 被抵扣的罚金记录ID先存下来分账成功后修改状态
fineIds.add(fineRecord.getId());
}
}
// 是否有罚金
boolean haveFine = BigDecimal.ZERO.compareTo(fineMoney) < 0;
if (haveFine) { // 有罚金
// 扣除罚金后的加价金额
BigDecimal workerAddMoney = fcRecord.getChangeMoney().subtract(fineMoney);
// 待提现金额里加入加价金额
dtx = dtx.add(workerAddMoney);
// 这里由平台承担手续费
DivMember divMember = new DivMember(memberId, AdapayUtils.bigDecimalToString(workerAddMoney), false);
DivMember planDivMember = new DivMember("0", AdapayUtils.bigDecimalToString(fineMoney), true);
divMembers.add(divMember);
divMembers.add(planDivMember);
} else { // 没有罚金
// 待提现金额里加入加价金额
dtx = dtx.add(fcRecord.getChangeMoney());
// 这里先自己承担手续费 后面再用平台抽成来补偿
DivMember divMember = new DivMember(memberId, AdapayUtils.bigDecimalToString(fcRecord.getChangeMoney()), true);
divMembers.add(divMember);
}
//调用分账
logger.info("子订单[code={}]的[改价单]发起分账", odCode);
JSONObject response = adapayService.paymentConfirm(financialDetail.getDeptId(), fcRecord.getRemark(),
@ -469,21 +508,25 @@ public class OrderDetailServiceImpl implements OrderDetailService {
AdapayUtils.bigDecimalToString(fcRecord.getChangeMoney()), divMembers, null, null);
if (AdapayStatusEnum.succeeded.code.equals(response.getString("status"))) { // 分账成功
logger.info("子订单[code={}]的[改价单]分账成功", odCode);
// 这是被扣掉的手续费 按理说这里肯定大于0
String fee_amt = response.getString("fee_amt");
feeAmt = new BigDecimal(fee_amt);
if (feeAmt.compareTo(platformFeeFD.getPayMoney()) < 0 && !"0.00".equals(fee_amt)) {
// 0.00<改价单的手续费<=平台抽成金额
// 用平台抽成来补偿改价单的手续费 修改平台抽成子财务单金额
fdUpdate.setPayMoney(fdUpdate.getPayMoney().subtract(feeAmt));
int i = financialDetailService.updateFinancialDetail(fdUpdate);
compensate = i > 0;
} else {
logger.warn("主订单[code={}]的平台抽成金额不足以承担子订单[code={}]的[改价单]的手续费",
orderDetail.getOrderMasterCode(), odCode);
// 平台抽成不足以承担改价单手续费了 那没办法了只能自己承担
// 待提现金额里减去改价单手续费
dtx = dtx.subtract(feeAmt);
// 分账成功 把罚金状态改为已扣除
fineIds.forEach(fineRecordId -> orderFineRecordMapper.updateFineStatus(fineRecordId, 1));
if (!haveFine) { // 没有罚金的情况才需要补偿手续费 有罚金的话直接在罚金里承担手续费
// 这是被扣掉的手续费 按理说这里应该大于0
String fee_amt = response.getString("fee_amt");
feeAmt = new BigDecimal(fee_amt);
if (feeAmt.compareTo(platformFeeFD.getPayMoney()) < 0 && !"0.00".equals(fee_amt)) {
// 0.00<改价单的手续费<=平台抽成金额
// 用平台抽成来补偿改价单的手续费 修改平台抽成子财务单金额
fdUpdate.setPayMoney(fdUpdate.getPayMoney().subtract(feeAmt));
int i = financialDetailService.updateFinancialDetail(fdUpdate);
compensate = i > 0;
} else {
logger.warn("主订单[code={}]的平台抽成金额不足以承担子订单[code={}]的[改价单]的手续费",
orderDetail.getOrderMasterCode(), odCode);
// 平台抽成不足以承担改价单手续费了 那没办法了只能自己承担
// 待提现金额里减去改价单手续费
dtx = dtx.subtract(feeAmt);
}
}
} else { // 分账失败
if (AdapayErrorCode.CONFIRM_AMT_OVER_LIMIT.equals(response.getString("error_code"))) {
@ -522,27 +565,57 @@ public class OrderDetailServiceImpl implements OrderDetailService {
payMoney = fdPayMoney;
}
if (BigDecimal.ZERO.compareTo(payMoney) > -1) {
logger.info("子财务单[code={}] 应支付金额={} 不需要分账", financialDetail.getCode(), payMoney);
logger.info("子财务单[{}] 应支付金额={} 不需要分账", financialDetail.getId(), payMoney);
} else {
// 查询师傅的超时扣款记录
List<OrderTimeoutRecord> fineRecords = orderFineRecordMapper.selectUnFine(orderDetail.getWorkerId(), orderMaster.getDeptId());
// 超时罚金
BigDecimal fineMoney = BigDecimal.ZERO;
ArrayList<Long> fineIds = new ArrayList<>();
for (OrderTimeoutRecord fineRecord : fineRecords) {
// 抵扣超时罚金 这里的罚金是按创建时间升序排列的 优先抵扣最早的罚金
if (fineMoney.add(fineRecord.getPayMoney()).compareTo(fdPayMoney) > 0) {
// 加价单金额不足以抵扣罚金
logger.info("子订单[{}]的派单金额[{}元]不足以抵扣罚金{}元", orderDetailId, fdPayMoney, fineRecord.getPayMoney());
break;
} else {
// 抵扣罚金
logger.info("子订单[{}]的加价单[{}]抵扣罚金{}元", orderDetailId, fdPayMoney, fineRecord.getPayMoney());
fineMoney = fineMoney.add(fineRecord.getPayMoney());
// 被抵扣的罚金记录ID先存下来分账成功后修改状态
fineIds.add(fineRecord.getId());
}
}
// 总分账金额
BigDecimal fee = BigDecimal.ZERO;
// 接单师傅的分账信息
String payMoneyS = AdapayUtils.bigDecimalToString(payMoney);
String payMoneyS = AdapayUtils.bigDecimalToString(payMoney.subtract(fineMoney));
DivMember divMember = new DivMember(memberId, payMoneyS, false);
divMembers.add(divMember);
// 计算本次分账的手续费 保留两位小数(向上取整)
BigDecimal fee = payMoney.multiply(new BigDecimal(feeRate)).setScale(2, RoundingMode.UP);
// 平台的分账信息 用来承担手续费
DivMember feeDivMember = new DivMember("0", fee.toString(), true);
divMembers.add(feeDivMember);
// 是否有罚金
boolean haveFine = BigDecimal.ZERO.compareTo(fineMoney) < 0;
if (haveFine) { // 有罚金 从罚金里扣除手续费
// 平台的分账信息 用来承担罚金
DivMember fineDivMember = new DivMember("0", AdapayUtils.bigDecimalToString(fineMoney), true);
divMembers.add(fineDivMember);
} else { // 没有罚金 需要扣除手续费
// 计算本次分账的手续费 保留两位小数(向上取整)
fee = payMoney.multiply(new BigDecimal(feeRate)).setScale(2, RoundingMode.UP);
// 平台的分账信息 用来承担手续费
DivMember feeDivMember = new DivMember("0", fee.toString(), true);
divMembers.add(feeDivMember);
}
logger.info("子订单[code={}]发起分账", odCode);
JSONObject response = adapayService.paymentConfirm(financialDetail.getDeptId(), payment.getId(), payment.getOrderNo() + "_" + System.currentTimeMillis(),
fee.add(payMoney).toString(), divMembers, null, null);
JSONObject response = adapayService.paymentConfirm(financialDetail.getDeptId(), payment.getId(),
payment.getOrderNo() + "_" + System.currentTimeMillis(),
AdapayUtils.bigDecimalToString(fee.add(payMoney)), divMembers, null, null);
boolean status = AdapayStatusEnum.succeeded.code.equals(response.getString("status"));
// 如果确认支付失败 这里抛出异常 回滚订单状态
Assert.isTrue(status, response.toString());
// 分账成功 把罚金状态改为已扣除
fineIds.forEach(fineRecordId -> orderFineRecordMapper.updateFineStatus(fineRecordId, 1));
// 待提现金额里加入子财务单金额
dtx = dtx.add(fdPayMoney);
dtx = dtx.add(fdPayMoney.subtract(fineMoney));
// 修改平台抽成子财务单金额 减去手续费
fdUpdate.setPayMoney(fdUpdate.getPayMoney().subtract(fee));

View File

@ -23,6 +23,8 @@ import com.ghy.order.service.OrderMasterService;
import com.ghy.payment.domain.FinancialChangeRecord;
import com.ghy.payment.domain.FinancialDetail;
import com.ghy.payment.domain.FinancialMaster;
import com.ghy.payment.domain.OrderTimeoutRecord;
import com.ghy.payment.mapper.OrderFineRecordMapper;
import com.ghy.payment.service.AdapayService;
import com.ghy.payment.service.FinancialChangeRecordService;
import com.ghy.payment.service.FinancialDetailService;
@ -69,6 +71,8 @@ public class OrderMasterServiceImpl implements OrderMasterService {
private FinancialDetailService financialDetailService;
@Resource
private FinancialChangeRecordService financialChangeRecordService;
@Resource
private OrderFineRecordMapper orderFineRecordMapper;
private static final AtomicLong INDEX = new AtomicLong(1L);
@ -170,7 +174,7 @@ public class OrderMasterServiceImpl implements OrderMasterService {
Assert.notNull(payment, String.format("主订单[id=%d]找不到支付记录", orderMasterId));
// 修改主订单状态
updateStatus(orderMasterId, OrderStatus.FINISH_CHECK.code());
updateStatus(orderMasterId, OrderStatus.FINISH.code());
if (BigDecimal.ZERO.compareTo(financialMaster.getPayMoney()) > -1) {
logger.info("订单[code={}]支付金额<=0不需要分账", orderMaster.getCode());
@ -230,7 +234,29 @@ public class OrderMasterServiceImpl implements OrderMasterService {
}
}
memberMap.put(AdapayUtils.getWorkerMemberId(orderMaster.getWorkerId(), orderMaster.getDeptId()), bigWorkerAmt);
// 超时罚金
BigDecimal fineMoney = BigDecimal.ZERO;
// 查询师傅的超时扣款记录
List<OrderTimeoutRecord> fineRecords = orderFineRecordMapper.selectUnFine(orderMaster.getWorkerId(), orderMaster.getDeptId());
ArrayList<Long> fineIds = new ArrayList<>();
for (OrderTimeoutRecord fineRecord : fineRecords) {
// 抵扣超时罚金 这里的罚金是按创建时间升序排列的 优先抵扣最早的罚金
if (fineMoney.add(fineRecord.getPayMoney()).compareTo(bigWorkerAmt) > 0) {
// 加价单金额不足以抵扣罚金
logger.info("主订单[{}]的服务金额[{}]不足以抵扣罚金{}元", orderMasterId, bigWorkerAmt, fineRecord.getPayMoney());
break;
} else {
// 抵扣罚金
logger.info("主订单[{}]的服务金额抵扣罚金{}元", orderMasterId, fineRecord.getPayMoney());
fineMoney = fineMoney.add(fineRecord.getPayMoney());
// 被抵扣的罚金记录ID先存下来分账成功后修改状态
fineIds.add(fineRecord.getId());
}
}
// 罚金分给平台账户
memberMap.merge("0", fineMoney, BigDecimal::add);
memberMap.put(AdapayUtils.getWorkerMemberId(orderMaster.getWorkerId(), orderMaster.getDeptId()), bigWorkerAmt.subtract(fineMoney));
confirmAmt = confirmAmt.add(bigWorkerAmt);
// 分账账户
@ -264,6 +290,8 @@ public class OrderMasterServiceImpl implements OrderMasterService {
throw new BaseAdaPayException(response.getString("code"), response.getString("message"));
}
}
// 分账成功 把罚金状态改为已扣除
fineIds.forEach(fineRecordId -> orderFineRecordMapper.updateFineStatus(fineRecordId, 1));
// 走到这里确认支付和分账都成功了 异步进入自动提现流程
logger.info("订单[code={}]开始自动提现", orderMaster.getCode());
@ -367,7 +395,9 @@ public class OrderMasterServiceImpl implements OrderMasterService {
@Override
public List<OrderMaster> selectByStatus(List<Integer> status) {
Assert.isTrue(!CollectionUtils.isEmpty(status), "订单状态为空");
if (CollectionUtils.isEmpty(status)) {
return Collections.emptyList();
}
return orderMasterMapper.selectByStatus(status);
}
@ -473,4 +503,19 @@ public class OrderMasterServiceImpl implements OrderMasterService {
}).sum();
return masterCount == detailCount;
}
@Override
public int updateTimeout(Long id, int timeout) {
return orderMasterMapper.updateTimeout(id, timeout, null);
}
@Override
public int updateTimeout(Long id, int timeout, int timeoutFineTimes) {
return orderMasterMapper.updateTimeout(id, timeout, timeoutFineTimes);
}
@Override
public int removeWorker(Long id) {
return orderMasterMapper.removeWorker(id);
}
}

View File

@ -9,7 +9,7 @@
<result property="deptId" column="dept_id"/>
<result property="code" column="code"/>
<result property="customerId" column="customer_id"/>
<result property="addressId" column="address_id"/>
<result property="addressId" column="address_id"/>
<result property="orderType" column="order_type"/>
<result property="orderStatus" column="order_status"/>
<result property="payType" column="pay_type"/>
@ -25,8 +25,10 @@
<result property="updateTime" column="update_time"/>
<result property="remark" column="remark"/>
<result property="goodsId" column="goods_id"/>
<result property="allSelfAssigned" column="all_self_assigned"/>
<result property="hasDispatchedAll" column="has_dispatched_all"/>
<result property="allSelfAssigned" column="all_self_assigned"/>
<result property="hasDispatchedAll" column="has_dispatched_all"/>
<result property="timeout" column="timeout_"/>
<result property="timeoutFineTimes" column="timeout_fine_times"/>
</resultMap>
<sql id="selectOrderMaster">
@ -46,9 +48,12 @@
expect_time_end,
create_by,
create_time,
update_time,
remark,
all_self_assigned,
goods_id
goods_id,
timeout_,
timeout_fine_times
FROM order_master
</sql>
<sql id="selectOrderMasterMoreInfo">
@ -68,9 +73,12 @@
om.expect_time_end,
om.create_by,
om.create_time,
om.update_time,
om.remark,
om.all_self_assigned,
om.goods_id
om.goods_id,
om.timeout_,
om.timeout_fine_times
FROM order_master om
LEFT JOIN customer_address ca ON ca.customer_address_id = om.address_id
LEFT JOIN goods g ON g.goods_id = om.goods_id
@ -350,4 +358,17 @@
</where>
</select>
<update id="updateTimeout">
UPDATE order_master
SET timeout_ = #{timeout}
<if test="timeoutFineTimes != null">,timeout_fine_times = #{timeoutFineTimes}</if>
WHERE id = #{id}
</update>
<update id="removeWorker">
UPDATE order_master
SET worker_id = NULL
WHERE id = #{id}
</update>
</mapper>

View File

@ -21,6 +21,7 @@ public class OrderTimeoutRecord {
*/
private Long orderDetailId;
private Long workerId;
private Long deptId;
private List<Long> orderDetailIds;
@ -48,9 +49,10 @@ public class OrderTimeoutRecord {
public OrderTimeoutRecord() {
}
public OrderTimeoutRecord(Long orderDetailId, Long workerId, Integer orderStatus) {
public OrderTimeoutRecord(Long orderDetailId, Long workerId, Long deptId, Integer orderStatus) {
this.orderDetailId = orderDetailId;
this.workerId = workerId;
this.deptId = deptId;
this.orderStatus = orderStatus;
}
}

View File

@ -10,11 +10,22 @@ import java.util.List;
*/
public interface OrderFineRecordMapper {
OrderTimeoutRecord selectByDetailIdAndStatus(@Param("orderDetailId")Long orderDetailId, @Param("orderStatus")Integer orderStatus);
List<OrderTimeoutRecord> selectByDetailIdAndStatus(@Param("orderDetailId") Long orderDetailId, @Param("orderStatus") Integer orderStatus);
List<OrderTimeoutRecord> selectList(OrderTimeoutRecord orderTimeoutRecord);
int insert(OrderTimeoutRecord orderTimeoutRecord);
int update(OrderTimeoutRecord orderTimeoutRecord);
// int update(OrderTimeoutRecord orderTimeoutRecord);
int updateFineStatus(@Param("id") Long id, @Param("fineStatus") int fineStatus);
/**
* 查询某师傅的未扣款的罚金
*
* @param workerId 师傅id
* @param deptId 公司id
*/
List<OrderTimeoutRecord> selectUnFine(@Param("workerId") Long workerId, @Param("deptId") Long deptId);
}

View File

@ -3,6 +3,7 @@ package com.ghy.payment.service.impl;
import com.ghy.payment.domain.OrderTimeoutRecord;
import com.ghy.payment.mapper.OrderFineRecordMapper;
import com.ghy.payment.service.OrderFineRecordService;
import org.apache.commons.collections4.CollectionUtils;
import org.springframework.stereotype.Service;
import javax.annotation.Resource;
@ -21,7 +22,12 @@ public class OrderFineRecordServiceImpl implements OrderFineRecordService {
@Override
public OrderTimeoutRecord selectByDetailIdAndStatus(Long orderDetailId, Integer orderStatus) {
return orderFineRecordMapper.selectByDetailIdAndStatus(orderDetailId, orderStatus);
OrderTimeoutRecord orderTimeoutRecord = null;
List<OrderTimeoutRecord> orderTimeoutRecords = orderFineRecordMapper.selectByDetailIdAndStatus(orderDetailId, orderStatus);
if (CollectionUtils.isNotEmpty(orderTimeoutRecords)) {
orderTimeoutRecord = orderTimeoutRecords.get(0);
}
return orderTimeoutRecord;
}
@Override

View File

@ -7,19 +7,22 @@
<resultMap id="OrderFineRecordResult" type="com.ghy.payment.domain.OrderTimeoutRecord">
<id property="id" column="id"/>
<result property="orderDetailId" column="order_detail_id"/>
<result property="fineStatus" column="fine_status"/>
<result property="workerId" column="worker_id"/>
<result property="deptId" column="dept_id"/>
<result property="fineStatus" column="fine_status"/>
<result property="orderStatus" column="order_status"/>
<result property="payMoney" column="pay_money"/>
<result property="createTime" column="create_time"/>
</resultMap>
<sql id="selectOrderFineRecord">
SELECT id, order_detail_id, fine_status, order_status, create_time
SELECT id, order_detail_id, worker_id, dept_id, fine_status, order_status, pay_money, create_time
FROM order_timeout_record
</sql>
<select id="selectByDetailIdAndStatus" resultMap="OrderFineRecordResult">
<include refid="selectOrderFineRecord"/>
WHERE order_detail_id = #{orderDetailId} AND order_status = #{orderStatus} limit 1;
WHERE order_detail_id = #{orderDetailId} AND order_status = #{orderStatus} order by create_time desc
</select>
<select id="selectList" parameterType="com.ghy.payment.domain.OrderTimeoutRecord"
@ -29,6 +32,9 @@
<if test="orderDetailId != null">
AND order_detail_id = #{orderDetailId}
</if>
<if test="workerId != null">
AND worker_id = #{workerId}
</if>
<if test="orderDetailIds != null and orderDetailIds != ''">
AND order_detail_id IN
<foreach collection="orderDetailIds" item="orderDetailId" open="(" separator="," close=")">
@ -41,13 +47,25 @@
</where>
</select>
<insert id="insert" parameterType="com.ghy.payment.domain.OrderTimeoutRecord" useGeneratedKeys="true"
keyProperty="id">
INSERT INTO order_timeout_record (order_detail_id, fine_status, order_status)
VALUES (#{orderDetailId}, #{fineStatus}, #{orderStatus})
<select id="selectUnFine" resultMap="OrderFineRecordResult">
<include refid="selectOrderFineRecord"/>
WHERE worker_id = #{workerId}
AND dept_id = #{deptId}
AND fine_status = 0
ORDER BY create_time
</select>
<insert id="insert" parameterType="com.ghy.payment.domain.OrderTimeoutRecord" useGeneratedKeys="true" keyProperty="id">
INSERT INTO order_timeout_record (order_detail_id, worker_id, dept_id, order_status, pay_money)
VALUES (#{orderDetailId}, #{workerId}, #{deptId}, #{orderStatus}, #{payMoney})
</insert>
<update id="update">
<!-- <update id="update">-->
<!-- UPDATE order_timeout_record SET fine_status = #{fineStatus}-->
<!-- WHERE id = #{id}-->
<!-- </update>-->
<update id="updateFineStatus">
UPDATE order_timeout_record SET fine_status = #{fineStatus}
WHERE id = #{id}
</update>

View File

@ -6,9 +6,11 @@ import com.ghy.order.domain.OrderMaster;
import com.ghy.order.service.OrderDetailService;
import com.ghy.order.service.OrderMasterService;
import com.ghy.payment.domain.FinancialDetail;
import com.ghy.payment.domain.FinancialMaster;
import com.ghy.payment.domain.OrderTimeoutRecord;
import com.ghy.payment.mapper.OrderFineRecordMapper;
import com.ghy.payment.service.FinancialDetailService;
import com.ghy.payment.service.FinancialMasterService;
import com.ghy.quartz.service.OrderService;
import com.ghy.system.domain.SysDeptConfig;
import com.ghy.system.service.ISysDeptConfigService;
@ -31,13 +33,18 @@ import java.util.stream.Collectors;
@Service
public class OrderServiceImpl implements OrderService {
private static final Integer ZERO = 0;
private static final Integer ONE = 1;
private static final Integer TWO = 2;
/**
* 需要超时扣款的订单状态
*
* @see OrderStatus
*/
@Value("${order.timeout.status:-4,-3,-2,1,2,3}")
private List<Integer> timeoutOrderStatus;
private static final List<Integer> orderMasterTimeoutStatus = Arrays.asList(0, 1);
@Resource
private ThreadPoolTaskExecutor executor;
@ -50,6 +57,8 @@ public class OrderServiceImpl implements OrderService {
@Resource
private FinancialDetailService financialDetailService;
@Resource
private FinancialMasterService financialMasterService;
@Resource
private ISysDeptConfigService sysDeptConfigService;
@Override
@ -59,14 +68,93 @@ public class OrderServiceImpl implements OrderService {
if (nowT.getHour() < 8 || nowT.getHour() > 18) {
return;
}
// 查询符合超时的单
// 查询待接单状态的主单
List<OrderMaster> orderMasters = orderMasterService.selectByStatus(orderMasterTimeoutStatus);
log.info("扫描到{}条未完成的主订单", orderMasters.size());
for (OrderMaster orderMaster : orderMasters) {
executor.execute(() -> checkTimeout(orderMaster));
}
// 查询符合超时的子单
List<OrderDetail> orders = orderDetailService.selectByStatus(timeoutOrderStatus);
log.info("扫描到{}条未完成的订单", orders.size());
log.info("扫描到{}条未完成的订单", orders.size());
for (OrderDetail order : orders) {
executor.execute(() -> checkTimeout(order));
}
}
@Transactional(rollbackFor = Exception.class)
void checkTimeout(OrderMaster order) {
Date now = new Date();
// 待接单状态的超时逻辑
if (ZERO.equals(order.getOrderStatus())) {
Date createTime = order.getCreateTime();
Date overTime30min = getOverTime(createTime, 30 * 60 * 1000);
Date overTime1h = getOverTime(createTime, 60 * 60 * 1000);
// 是否已经超时
boolean timeout = ONE.equals(order.getTimeout());
if (!timeout) {
if (overTime30min.before(now) && overTime1h.after(now)) {
// 30min未接单为超时
log.info("主订单[{}]超时30分钟", order.getId());
orderMasterService.updateTimeout(order.getId(), 1);
timeout = true;
}
}
if (timeout) {
if (overTime1h.before(now) && order.getWorkerId() != null) {
log.info("主订单[{}]超时60分钟", order.getId());
// 已超时 60min后取消超时状态 清空workerId
orderMasterService.updateTimeout(order.getId(), 0);
orderMasterService.removeWorker(order.getId());
}
}
return;
}
// 未派单状态的超时逻辑
if (ONE.equals(order.getOrderStatus())) {
Date updateTime = order.getUpdateTime();
Date overTime30min = getOverTime(updateTime, 30 * 60 * 1000);
Date overTime4h = getOverTime(updateTime, 4 * 60 * 60 * 1000);
Date overTime6h = getOverTime(updateTime, 6 * 60 * 60 * 1000);
// 是否已经超时
boolean timeout = ONE.equals(order.getTimeout());
Integer fineTimes = order.getTimeoutFineTimes();
if (!timeout) {
if (overTime30min.before(now)) {
// 30min未接单为超时
log.info("主订单[{}]超时30分钟", order.getId());
orderMasterService.updateTimeout(order.getId(), 1);
timeout = true;
}
}
if (timeout) {
if (overTime4h.before(now) && ZERO.equals(fineTimes)) {
log.info("主订单[{}]超时4小时", order.getId());
orderMasterService.updateTimeout(order.getId(), 1, 1);
// insert 罚金记录
OrderTimeoutRecord record = new OrderTimeoutRecord(order.getId(), order.getWorkerId(), order.getDeptId(), order.getOrderStatus());
record.setPayMoney(getFineMoney(order));
record.setFineStatus(0);
orderFineRecordMapper.insert(record);
fineTimes = ONE;
}
if (overTime6h.before(now) && ONE.equals(fineTimes)) {
log.info("主订单[{}]超时6小时", order.getId());
orderMasterService.updateTimeout(order.getId(), 1, 2);
// insert 罚金记录
OrderTimeoutRecord record = new OrderTimeoutRecord(order.getId(), order.getWorkerId(), order.getDeptId(), order.getOrderStatus());
record.setPayMoney(getFineMoney(order));
record.setFineStatus(0);
orderFineRecordMapper.insert(record);
}
}
}
}
/**
* 判断是否超时
*
@ -86,7 +174,7 @@ public class OrderServiceImpl implements OrderService {
Date overTime = getOverTime(order.getExpectTimeStart(), 4 * 60 * 60 * 1000);
if (overTime.before(now)) {
log.info("订单[{}]服务中状态超时4小时 扣款", order.getId());
OrderTimeoutRecord record = new OrderTimeoutRecord(order.getId(), order.getWorkerId(), order.getOrderStatus());
OrderTimeoutRecord record = new OrderTimeoutRecord(order.getId(), order.getWorkerId(), order.getDeptId(), order.getOrderStatus());
record.setPayMoney(getFineMoney(order));
record.setFineStatus(0);
orderFineRecordMapper.insert(record);
@ -115,7 +203,7 @@ public class OrderServiceImpl implements OrderService {
Date overTime = getOverTime(order.getUpdateTime(), 4 * 60 * 60 * 1000);
if (overTime.before(now)) {
log.info("订单[{}]超时4h 扣款", order.getId());
OrderTimeoutRecord record = new OrderTimeoutRecord(order.getId(), order.getWorkerId(), order.getOrderStatus());
OrderTimeoutRecord record = new OrderTimeoutRecord(order.getId(), order.getWorkerId(), order.getDeptId(), order.getOrderStatus());
record.setPayMoney(getFineMoney(order));
record.setFineStatus(0);
orderFineRecordMapper.insert(record);
@ -128,7 +216,7 @@ public class OrderServiceImpl implements OrderService {
Date overTime = getOverTime(orderTime, 6 * 60 * 60 * 1000);
if (overTime.before(now)) {
log.info("订单[{}]超时6h 再次扣款", order.getId());
OrderTimeoutRecord record = new OrderTimeoutRecord(order.getId(), order.getWorkerId(), order.getOrderStatus());
OrderTimeoutRecord record = new OrderTimeoutRecord(order.getId(), order.getWorkerId(), order.getDeptId(), order.getOrderStatus());
record.setPayMoney(getFineMoney(order));
record.setFineStatus(0);
orderFineRecordMapper.insert(record);
@ -141,8 +229,9 @@ public class OrderServiceImpl implements OrderService {
* 计算订单罚金(固定罚金+比例罚金)
*/
private BigDecimal getFineMoney(OrderDetail order) {
OrderMaster orderMaster = orderMasterService.selectById(order.getOrderMasterId());
FinancialDetail orderFinancial = financialDetailService.selectByOrderDetailId(order.getId());
SysDeptConfig deptConfig = sysDeptConfigService.selectByDeptId(order.getDeptId());
SysDeptConfig deptConfig = sysDeptConfigService.selectByDeptId(orderMaster.getDeptId());
BigDecimal fineMoney = deptConfig.getGoingOutTime();
// 如果扣款额为null或<0
if (fineMoney == null || BigDecimal.ZERO.compareTo(fineMoney) > -1) {
@ -157,6 +246,26 @@ public class OrderServiceImpl implements OrderService {
return fineMoney.add(rateMoney);
}
/**
* 计算订单罚金(固定罚金+比例罚金)
*/
private BigDecimal getFineMoney(OrderMaster orderMaster) {
FinancialMaster financialMaster = financialMasterService.selectByOrderMasterId(orderMaster.getId());
SysDeptConfig deptConfig = sysDeptConfigService.selectByDeptId(orderMaster.getDeptId());
BigDecimal fineMoney = deptConfig.getGoingOutTime();
// 如果扣款额为null或<0
if (fineMoney == null || BigDecimal.ZERO.compareTo(fineMoney) > -1) {
fineMoney = BigDecimal.ZERO;
}
BigDecimal timeoutRate = deptConfig.getGoingOutTimeRate();
// 如果扣款比例 为null <0 >1.00
if (timeoutRate == null || BigDecimal.ZERO.compareTo(timeoutRate) > 0 || BigDecimal.ONE.compareTo(timeoutRate) < 0) {
return fineMoney;
}
BigDecimal rateMoney = financialMaster.getPayMoney().multiply(timeoutRate);
return fineMoney.add(rateMoney);
}
/**
* 计算超时时间
*

View File

@ -7,6 +7,7 @@ import com.ghy.system.mapper.SysDeptConfigMapper;
import com.ghy.system.mapper.SysDeptMapper;
import com.ghy.system.service.ISysDeptConfigService;
import org.springframework.stereotype.Service;
import org.springframework.util.Assert;
import javax.annotation.Resource;
import java.util.List;
@ -26,6 +27,7 @@ public class SysDeptConfigServiceImpl implements ISysDeptConfigService {
@Override
public SysDeptConfig selectByDeptId(Long deptId) {
Assert.notNull(deptId, "deptId is null!!!");
return sysDeptConfigMapper.selectByDeptId(deptId);
}

View File

@ -54,12 +54,7 @@
<select id="selectByDeptId" parameterType="long" resultMap="SysDeptConfigResult">
<include refid="selectSysDeptConfig"/>
<where>
<if test="deptId != null and deptId != 0">
AND dept_id = #{deptId}
</if>
</where>
WHERE dept_id = #{deptId}
</select>
<select id="selectAllMerchant" resultMap="SysDeptConfigResult">