Authored by LUOXC

添加卖家取消订单

... ... @@ -47,6 +47,7 @@ public class SellerWalletDetail {
SELLER_CANCEL("卖家不卖了", 31),
SELLER_OVER_TIME("卖家发货超时", 32),
APPRAISE_FAIL("鉴定不通过", 33),
CS_CANCEL_BEFORE_DEPOT_RECEIVE("鉴定中心收货前客服取消", 34),
BUYER_CANCEL_NO_DELIVERY("买家取消(无物流)", 41),
BUYER_CANCEL_DELIVERY("买家取消(有物流)", 42),
APPRAISE_OK("鉴定通过", 51),
... ...
... ... @@ -2,6 +2,8 @@ package com.yohoufo.order.common;
import java.util.HashMap;
import java.util.Map;
import java.util.Optional;
import java.util.function.Supplier;
/**
* 1:鉴定通过(货款-->卖家 + 平台);
... ... @@ -20,7 +22,8 @@ public enum TransferCase {
SELLER_PLAY_BUYER(3,"有买家时卖家不卖[保证金->买家]"),
DELIVER_TIME_OUT(4,"卖家超时发货[保证金->买家]"),
BUYER_CANCEL_BEFORE_SELLER_DELIVER(5,"卖家未发货时买家取消[部分货款->卖家]"),
BUYER_CANCEL_BEFORE_DEPOT_RECEIVE(6,"卖家已发货时买家取消[部分货款->卖家]");
BUYER_CANCEL_BEFORE_DEPOT_RECEIVE(6,"卖家已发货时买家取消[部分货款->卖家]"),
CS_CANCEL_BEFORE_DEPOT_RECEIVE(7,"鉴定中心收货前客服取消[保证金->买家]");
private int code;
private String info;
... ... @@ -50,4 +53,9 @@ public enum TransferCase {
public static TransferCase getTransferCase(Integer code){
return cache.get(code);
}
public static TransferCase getTransferCaseOrElseThrow(Integer code, Supplier<RuntimeException> exceptionSupplier){
return Optional.ofNullable(getTransferCase(code)).orElseThrow(exceptionSupplier);
}
}
... ...
... ... @@ -9,7 +9,8 @@ public enum AlarmConfig {
APPRAISE_SUCCESS("buyerOrder.transferGoodsMoney","buyerOrder.refundEarnestMoney"),
APPRAISE_FAIL("buyerOrder.transferEarnestMoney","buyerOrder.refundGoodsMoney"),
SELLER_PLAY_BUYER("buyerOrder.transferEarnestMoney","buyerOrder.refundGoodsMoney"),
DELIVER_TIME_OUT("buyerOrder.transferEarnestMoney","buyerOrder.refundGoodsMoney");
DELIVER_TIME_OUT("buyerOrder.transferEarnestMoney","buyerOrder.refundGoodsMoney"),
CS_CANCEL_BEFORE_DEPOT_RECEIVE("buyerOrder.transferEarnestMoney","buyerOrder.refundGoodsMoney");
private String transferName;
private String refundName;
... ...
... ... @@ -15,7 +15,7 @@ import lombok.experimental.Builder;
@AllArgsConstructor
public class BuyerRefundCouponEvent extends Event {
public enum BizCase{
APPRAISE_FAIL, SELLER_DELIVER_TIMEOUT, SELLER_PLAY_BUYER, BUYER_CANCEL_BSD, BUYER_CANCEL_BDR
APPRAISE_FAIL, SELLER_DELIVER_TIMEOUT, SELLER_PLAY_BUYER, BUYER_CANCEL_BSD, BUYER_CANCEL_BDR,CS_CANCEL_BEFORE_DEPOT_RECEIVE
}
Integer uid;
... ...
... ... @@ -621,7 +621,8 @@ public class MerchantOrderPaymentService extends AbstractOrderPaymentService {
logger.info("{}修改钱包,uid={},增加保证金场合:", type.getName(), uid);
} else if (type == SellerWalletDetail.Type.SELLER_CANCEL
|| type == SellerWalletDetail.Type.SELLER_OVER_TIME
|| type == SellerWalletDetail.Type.APPRAISE_FAIL) {
|| type == SellerWalletDetail.Type.APPRAISE_FAIL
|| type == SellerWalletDetail.Type.CS_CANCEL_BEFORE_DEPOT_RECEIVE) {
// 处罚保证金
lockAmount = money.multiply(new BigDecimal("-1"));
tradeAmount = lockAmount;
... ...
... ... @@ -35,7 +35,7 @@ import java.util.function.BiConsumer;
* @date 2019/1/8 14:07
*/
@Slf4j
public class BuyerOrderCancelHandler {
class BuyerOrderCancelHandler {
private final int uid;
private final long orderCode;
... ... @@ -55,10 +55,8 @@ public class BuyerOrderCancelHandler {
private TransferCase transferCase;
private SellerWalletDetail.Type sellerWalletDetailType;
private BiConsumer<PaymentRequest, BillLogEvent.BillLogEventBuilder> payGoodsMoneyRefundConsumer;
private RefundCase refundCase;
private AlarmConfig refundPayFailAlarm;
private BiConsumer<PaymentRequest, BillLogEvent.BillLogEventBuilder> goodsMoneyRefundConsumer;
private RefundCase goodsMoneyRefundCase;
private SellerNoticeSender sellerNoticeSender;
private SellerOrderGoodsMapper sellerOrderGoodsMapper;
... ... @@ -66,6 +64,11 @@ public class BuyerOrderCancelHandler {
private BuyerRefundCouponEvent.BizCase refundCouponCase;
private AlarmConfig failAlarm;
BuyerOrderCancelHandler(int uid, long orderCode) {
this.uid = uid;
this.orderCode = orderCode;
... ... @@ -105,14 +108,9 @@ public class BuyerOrderCancelHandler {
return this;
}
public BuyerOrderCancelHandler withRefundPay(BiConsumer<PaymentRequest, BillLogEvent.BillLogEventBuilder> payRefundConsumer, RefundCase refundCase) {
this.payGoodsMoneyRefundConsumer = payRefundConsumer;
this.refundCase = refundCase;
return this;
}
public BuyerOrderCancelHandler withRefundPayFailAlarm(AlarmConfig refundPayFailAlarm) {
this.refundPayFailAlarm = refundPayFailAlarm;
public BuyerOrderCancelHandler withRefundGoodsMoney(BiConsumer<PaymentRequest, BillLogEvent.BillLogEventBuilder> refundConsumer, RefundCase refundCase) {
this.goodsMoneyRefundConsumer = refundConsumer;
this.goodsMoneyRefundCase = refundCase;
return this;
}
... ... @@ -128,6 +126,11 @@ public class BuyerOrderCancelHandler {
return this;
}
public BuyerOrderCancelHandler withFailAlarm(AlarmConfig failAlarm) {
this.failAlarm = failAlarm;
return this;
}
public void cancel() {
verify();
// 获取买家订单
... ... @@ -194,13 +197,13 @@ public class BuyerOrderCancelHandler {
}
private void refundPayGoodsMoney(BuyerOrder buyerOrder) {
if (Objects.isNull(payGoodsMoneyRefundConsumer)) {
if (Objects.isNull(goodsMoneyRefundConsumer)) {
return;
}
BigDecimal goodsMoney = buyerOrder.getAmount();
val paymentRequest = PaymentRequest.builder()
.uid(uid)
.refundCase(refundCase)
.refundCase(goodsMoneyRefundCase)
.orderCode(orderCode)
.refundAmount(goodsMoney.doubleValue())
.build();
... ... @@ -209,19 +212,19 @@ public class BuyerOrderCancelHandler {
.sellerUid(buyerOrder.getSellerUid())
.orderCode(orderCode)
.payType(buyerOrder.getPayment())
.refundCase(refundCase)
.refundCase(goodsMoneyRefundCase)
.amount(goodsMoney);
try {
payGoodsMoneyRefundConsumer.accept(paymentRequest, billLogEventBuilder.skup(getSkup()));
goodsMoneyRefundConsumer.accept(paymentRequest, billLogEventBuilder.skup(getSkup()));
} catch (Exception ex) {
log.warn("pay refund fail,req {}", paymentRequest, ex);
BillLogEvent billLogEvent = billLogEventBuilder.tradeStatus(BillTradeStatus.FAIL.getCode()).build();
EventBusPublisher.publishEvent(billLogEvent);
if (Objects.nonNull(refundPayFailAlarm)) {
if (Objects.nonNull(failAlarm)) {
SmsAlarmEvent smsAlarmEvent = new SmsAlarmEvent(
refundPayFailAlarm.getRefundName(),
refundPayFailAlarm.name(),
failAlarm.getRefundName(),
failAlarm.name(),
expectStatus.getDesc() + ",取消订单" + orderCode + "退货款失败"
);
EventBusPublisher.publishEvent(smsAlarmEvent);
... ...
... ... @@ -264,12 +264,13 @@ public class BuyerOrderCancelService {
.withSkup(skup)
.withSellerOrderGoods(sellerOrderGoods)
.withBuyerOrderSupplier(buyerOrderMapper, buyerOrderGoodsMapper)
// 已付款 -> 超时未发货取消
.withStateTransition(OrderStatus.HAS_PAYED, OrderStatus.SEND_OUT_TIMEOUT, orderStatusFlowService)
// 保证金分账给平台和买家
.withTransfer(transferService, TransferCase.SELLER_PLAY_BUYER.getCode(), TransferCase.DELIVER_TIME_OUT, SellerWalletDetail.Type.SELLER_OVER_TIME)
// 退买家货款
.withRefundPay(payRefundService::refund, RefundCase.BUYER_GOODS_MONEY)
.withRefundPayFailAlarm(AlarmConfig.DELIVER_TIME_OUT)
.withRefundGoodsMoney(payRefundService::refund, RefundCase.BUYER_GOODS_MONEY)
.withFailAlarm(AlarmConfig.DELIVER_TIME_OUT)
// 通知卖家商品发货超时
.withNoticeSeller(inBoxFacade::sellerDeliverNotice, 3, sellerOrderGoodsMapper)
// 退优惠券
... ... @@ -280,16 +281,17 @@ public class BuyerOrderCancelService {
public void cancelForCsBeforeDepotReceive(int uid, long orderCode){
new BuyerOrderCancelHandler(uid, orderCode)
.withBuyerOrderSupplier(buyerOrderMapper, buyerOrderGoodsMapper)
// 卖家发货 -> 鉴定中心收货前客服取消
.withStateTransition(OrderStatus.SELLER_SEND_OUT, OrderStatus.CS_CANCEL_BEFORE_DEPOT_RECEIVE, orderStatusFlowService)
// 保证金分账给平台和买家
.withTransfer(transferService, TransferCase.SELLER_PLAY_BUYER.getCode(), TransferCase.DELIVER_TIME_OUT, SellerWalletDetail.Type.SELLER_OVER_TIME)
.withTransfer(transferService, TransferCase.CS_CANCEL_BEFORE_DEPOT_RECEIVE.getCode(), TransferCase.CS_CANCEL_BEFORE_DEPOT_RECEIVE, SellerWalletDetail.Type.CS_CANCEL_BEFORE_DEPOT_RECEIVE)
// 退买家货款
.withRefundPay(payRefundService::refund, RefundCase.BUYER_GOODS_MONEY)
.withRefundPayFailAlarm(AlarmConfig.DELIVER_TIME_OUT)
.withRefundGoodsMoney(payRefundService::refund, RefundCase.BUYER_GOODS_MONEY)
// 通知卖家涉及虚假发货
.withNoticeSeller(inBoxFacade::sellerDeliverNotice, 3, sellerOrderGoodsMapper)
.withNoticeSeller(inBoxFacade::sellerDeliverNotice, 4, sellerOrderGoodsMapper)
// 退优惠券
.withRefundCoupon(BuyerRefundCouponEvent.BizCase.SELLER_DELIVER_TIMEOUT)
.withRefundCoupon(BuyerRefundCouponEvent.BizCase.CS_CANCEL_BEFORE_DEPOT_RECEIVE)
.withFailAlarm(AlarmConfig.CS_CANCEL_BEFORE_DEPOT_RECEIVE)
.cancel();
}
... ...
... ... @@ -499,8 +499,7 @@ public class PaymentServiceImpl implements IPaymentService {
throw new ServiceException(ServiceError.ORDER_REQUEST_PARM_IS_EMPTY);
}
// 类型检查
int transferType = request.getType();
TransferCase transferCase = TransferCase.getTransferCase(transferType);
TransferCase transferCase = TransferCase.getTransferCase(request.getType());
if (transferCase == null) {
logger.warn("transferMonErr transferType invalid");
throw new ServiceException(ServiceError.ORDER_REQUEST_PARM_IS_EMPTY);
... ... @@ -529,9 +528,10 @@ public class PaymentServiceImpl implements IPaymentService {
Integer sellerUid = sellerOrder.getUid();
long sellerOrderCode = sellerOrder.getOrderCode();
punishEarnest(request.getSwdType(), sellerOrder);
TargetUserType targetUserType = (transferType == TransferCase.APPRAISE_FAIL.getCode()
|| transferType == TransferCase.SELLER_PLAY_BUYER.getCode()) ? TargetUserType.buyer : TargetUserType.seller;
//Integer targetUserType = (transferType == 2 || transferType == 3) ? 1 : 2;
TargetUserType targetUserType = (transferCase == TransferCase.APPRAISE_FAIL
|| transferCase == TransferCase.SELLER_PLAY_BUYER
|| transferCase == TransferCase.DELIVER_TIME_OUT
|| transferCase == TransferCase.CS_CANCEL_BEFORE_DEPOT_RECEIVE) ? TargetUserType.buyer : TargetUserType.seller;
Integer targetUid = targetUserType == TargetUserType.buyer ? buyerOrder.getUid() : sellerUid;
if (targetUid == null || targetUid < 1) {
... ... @@ -551,7 +551,7 @@ public class PaymentServiceImpl implements IPaymentService {
transfer.setSellerOrderCode(sellerOrderCode);
transfer.setAlipayTradeId("");
transfer.setAlipayTradeResult("");
transfer.setTransferType(transferType);
transfer.setTransferType(transferCase.getCode());
transfer.setUid(targetUid);
transfer.setAmount(BigDecimal.ZERO);
transfer.setCreateTime(now);
... ... @@ -571,7 +571,8 @@ public class PaymentServiceImpl implements IPaymentService {
record.setOrderCode(buyerOrderCode);
record.setUserType(targetUserType.getCode());
record.setPayType(1);
record.setTradeType(transferType == 1 ? 2 : 3);
// 如果鉴定通过[货款->卖家],否则[补偿款->卖家或买家] 2:货款;3:补偿款
record.setTradeType(transferCase == TransferCase.APPRAISE_SUCCESS ? 2 : 3);
record.setIncomeOutcome(1);
record.setTradeStatus(0);
record.setCreateTime(now);
... ... @@ -582,7 +583,7 @@ public class PaymentServiceImpl implements IPaymentService {
logger.info("transferMon计算费用结果为 {}", transferAmount);
if (transferAmount == null) {
logger.warn("transferMonErr transferMon计算费用结果为 null, 不合法的金额");
alarm("转账金额不合法", "ufo.order.transferMon", "订单号:" + buyerOrderCode + "操作类型(" + transferType + ")计算金额结果为null");
alarm("转账金额不合法", "ufo.order.transferMon", "订单号:" + buyerOrderCode + "操作类型(" + transferCase.getCode() + ")计算金额结果为null");
record.setTradeStatus(202);
addTradeBills(record);
throw new ServiceException(400, "计算金额错误!:");
... ... @@ -593,7 +594,7 @@ public class PaymentServiceImpl implements IPaymentService {
record.setSystemAmount(transferAmount.multiply(new BigDecimal("-1")));
if (transferAmount.compareTo(new BigDecimal("0.1")) < 0) {
logger.warn("transferMonErr transferMon计算费用结果为 {}, 小于0.1", transferAmount);
alarm("转账金额小于0.1", "ufo.order.transferMon", "订单号:" + buyerOrderCode + "操作类型(" + transferType + ")计算金额结果为" + transferAmount);
alarm("转账金额小于0.1", "ufo.order.transferMon", "订单号:" + buyerOrderCode + "操作类型(" + transferCase.getCode() + ")计算金额结果为" + transferAmount);
record.setTradeStatus(202);
addTradeBills(record);
throw new ServiceException(400, "不合法的金额:" + transferAmount);
... ...
... ... @@ -74,6 +74,12 @@ public class TransferService {
alarmConfig = AlarmConfig.DELIVER_TIME_OUT;
break;
case CS_CANCEL_BEFORE_DEPOT_RECEIVE:
closeLogger.warn("in deliver timeout , transfer fail,req {}", req);
content = "鉴定中心收货前客服取消,订单"+ req.getBuyerOrderCode() + "保证金分账失败";
alarmConfig = AlarmConfig.CS_CANCEL_BEFORE_DEPOT_RECEIVE;
break;
default:
return null;
}
... ...
... ... @@ -15,7 +15,10 @@ import org.springframework.stereotype.Service;
import java.util.Arrays;
import java.util.List;
import java.util.concurrent.*;
import java.util.concurrent.ArrayBlockingQueue;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.ThreadPoolExecutor;
import java.util.concurrent.TimeUnit;
/**
* Created by chenchao on 2018/10/8.
... ... @@ -655,26 +658,30 @@ public class InBoxFacade {
Integer sellerUid = sog.getUid();
String prdName = sog.getProductName();
String sizeName = sog.getSizeName();
InboxBusinessTypeEnum ibt;
InboxBusinessTypeEnum smsInboxBusinessTypeEnum;
if (times == 2) {
ibt = InboxBusinessTypeEnum.NOTICE_SELLER_DELIVER_GOODS;
smsInboxBusinessTypeEnum = InboxBusinessTypeEnum.SMS_NOTIFIED_SEND_SECOND;
} else if (times == 3) {
ibt = InboxBusinessTypeEnum.NOTICE_SELLER_DELIVER_GOODS_FAIL;
smsInboxBusinessTypeEnum = InboxBusinessTypeEnum.SMS_NOTIFIED_SEND_FAILED;
} else if (times == 4) {
ibt = InboxBusinessTypeEnum.NOTICE_SELLER_CS_CANCEL_ORDER_TRADE_FAIL;
smsInboxBusinessTypeEnum = InboxBusinessTypeEnum.SMS_NOTICE_SELLER_CS_CANCEL_ORDER_TRADE_FAIL;
}else {
return;
}
try {
executorService.execute(() -> {
logger.info("record sellerDeliverNotice inbox sms msg,sellerUid {}, prdName {}, times {}",
sellerUid, prdName, times);
if(times == 2 || times == 3){
InboxBusinessTypeEnum ibt = null;
if (times == 2) {
ibt = InboxBusinessTypeEnum.NOTICE_SELLER_DELIVER_GOODS;
}
if(times == 3){
ibt = InboxBusinessTypeEnum.NOTICE_SELLER_DELIVER_GOODS_FAIL;
}
String params = buildParams(prdName, sizeName);
InboxReqVO req = buildInboxReqVO(sellerUid, params, ibt);
InBoxResponse resp = inBoxSDK.addInbox(req);
logger.info("record sellerDeliverNotice inbox msg,sellerUid {}, prdName {},sizeName {} times {},resp {}",
sellerUid, prdName, sizeName, times, resp);
}
String phone = userProxyService.getMobile(sellerUid);
if (StringUtils.isBlank(phone)){
... ... @@ -683,22 +690,10 @@ public class InBoxFacade {
return;
}
List<String> mobileList = Arrays.asList(phone);
if(times == 2 || times == 3){
String content = null;
if (times == 2) {
content = getReplacedContent(InboxBusinessTypeEnum.SMS_NOTIFIED_SEND_SECOND.getContent(),prdName,orderCode);
}
if (times == 3) {
content = getReplacedContent(InboxBusinessTypeEnum.SMS_NOTIFIED_SEND_FAILED.getContent(),prdName,orderCode);
}
String content = getReplacedContent(smsInboxBusinessTypeEnum.getContent(),prdName,orderCode);
sendSmsService.smsSendByMobile(content, mobileList);
logger.info("record sellerDeliverNotice inbox sms msg,sellerUid {}, prdName {}, times {},resp {}",
sellerUid, prdName, times);
}
});
} catch (Exception e) {
logger.warn("InBoxFacade sellerDeliverNotice error inbox msg, sellerUid {}, prdName {} ",
... ...