Authored by chenchao

add config

package com.yohoufo.order.common;
import java.util.Map;
/**
* 1:鉴定通过(货款-->卖家 + 平台);
* 2:鉴定不通过(保证金 --> 买家 + 平台);
* 3:有买家时卖家不卖了(保证金 --> 买家+ 平台)
* 4:超时发货(保证金 --> 买家 + 平台)
* Created by chenchao on 2018/10/9.
* 5:买家付款后[卖家未发货],取消订单(货款部分-->卖家);
* 6:买家付款后[卖家已发货],取消订单(货款部分-->卖家);
*/
public enum TransferCase {
... ... @@ -13,7 +17,9 @@ public enum TransferCase {
APPRAISE_SUCCESS(1),
APPRAISE_FAIL(2),
SELLER_PLAY_BUYER(3),
DELIVER_TIME_OUT(4);
DELIVER_TIME_OUT(4),
BUYER_CANCEL_BEFORE_SELLER_DELIVER(5),
BUYER_CANCEL_BEFORE_DEPOT_RECEIVE(6);
private int code;
... ... @@ -24,4 +30,16 @@ public enum TransferCase {
public int getCode() {
return code;
}
private static Map<Integer, TransferCase> cache;
static {
for(TransferCase tc: values()){
cache.put(tc.code, tc);
}
}
public static TransferCase getTransferCase(Integer code){
return cache.get(code);
}
}
... ...
package com.yohoufo.order.event;
import com.yohobuy.ufo.model.order.common.OrderStatus;
import com.yohoufo.common.alarm.Event;
import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;
... ... @@ -13,9 +14,16 @@ import lombok.experimental.Builder;
@Builder
@NoArgsConstructor
@AllArgsConstructor
public class BeforeDepotReceiveEvent extends BuyerCancelEvent {
public class BeforeDepotReceiveEvent extends Event {
private int buyerUid;
private long orderCode;
private OrderStatus target;
private OrderStatus expected;
private int sellerUid;
private int skup;
}
... ...
package com.yohoufo.order.event;
import com.yohobuy.ufo.model.order.common.OrderStatus;
import lombok.Data;
import com.yohoufo.common.alarm.Event;
import lombok.*;
import lombok.experimental.Builder;
/**
* Created by chao.chen on 2018/11/14.
*/
@Data
@Builder
@NoArgsConstructor
@AllArgsConstructor
public class BeforeSellerDeliverEvent extends Event {
private int buyerUid;
private long orderCode;
public class BeforeSellerDeliverEvent extends BuyerCancelEvent {
private OrderStatus target;
private OrderStatus expected;
private int sellerUid;
private int skup;
}
... ...
package com.yohoufo.order.model.request;
import com.yohoufo.order.common.RefundCase;
import lombok.AllArgsConstructor;
import lombok.Data;
import lombok.NoArgsConstructor;
... ... @@ -25,4 +26,6 @@ public class PaymentRequest {
private double refundAmount;
private String openid;
private RefundCase refundCase;
}
... ...
package com.yohoufo.order.service.handler;
import com.yohoufo.order.service.impl.OrderDynamicConfig;
import org.springframework.stereotype.Component;
import javax.annotation.Resource;
import java.math.BigDecimal;
/**
* Created by chao.chen on 2018/11/16.
*/
@Component
public class BuyerCancelCompensateComputeHandler {
@Resource(name = "orderDynamicConfig")
OrderDynamicConfig orderDynamicConfig;
public BigDecimal calBeforeSellerDeliver(){
//todo 若后续改成动态配置时,需要实时计算
OrderDynamicConfig.BuyerCancelCompensateNode node = orderDynamicConfig.getBeforeSellerDeliverBCCN();
return node.getSellerGetMoney();
}
public BigDecimal calBeforeDepotReceive(){
//todo 若后续改成动态配置时,需要实时计算
OrderDynamicConfig.BuyerCancelCompensateNode node = orderDynamicConfig.getBeforeDepotReceiveBCCN();
return node.getSellerGetMoney();
}
}
... ...
package com.yohoufo.order.service.impl;
import com.yohobuy.ufo.model.order.common.OrderStatus;
import com.yohobuy.ufo.model.order.common.SkupStatus;
import com.yohoufo.common.utils.DateUtil;
import com.yohoufo.dal.order.BuyerOrderMapper;
import com.yohoufo.dal.order.SellerOrderGoodsMapper;
import com.yohoufo.dal.order.model.SellerOrderGoods;
import com.yohoufo.order.event.BeforeDepotReceiveEvent;
import com.yohoufo.order.event.BeforeSellerDeliverEvent;
import com.yohoufo.order.utils.LoggerUtils;
import org.slf4j.Logger;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Service;
import org.springframework.web.bind.annotation.RequestParam;
... ... @@ -20,19 +27,57 @@ public class BuyerOrderCancelService {
@Resource(name = "orderDynamicConfig")
private OrderDynamicConfig orderDynamicConfig;
@Autowired
private BuyerOrderMapper buyerOrderMapper;
@Autowired
private SellerOrderGoodsMapper sellerOrderGoodsMapper;
public void cancel(BeforeSellerDeliverEvent bsdEvent){
Double compensate = orderDynamicConfig.getCOMPENSATE_BEFORE_SELLER_DELIVER();
OrderDynamicConfig.BuyerCancelCompensateNode compensate = orderDynamicConfig.getBeforeSellerDeliverBCCN();
logger.info("in buyer cancel BeforeSellerDeliver, event {} compensate {}", bsdEvent, compensate);
int buyerUid = bsdEvent.getBuyerUid();
long orderCode = bsdEvent.getOrderCode();
OrderStatus target = bsdEvent.getTarget();
OrderStatus expected = bsdEvent.getExpected();
int currentTime = DateUtil.getCurrentTimeSecond();
int rows = buyerOrderMapper.updateStatusByOrderCode(orderCode, buyerUid, expected.getCode(), target.getCode(), currentTime);
if (rows>0) {
int skup = bsdEvent.getSkup();
SellerOrderGoods targetGoods = new SellerOrderGoods();
targetGoods.setId(skup);
targetGoods.setStatus(SkupStatus.BUYER_CANCEL_BEFORE_SELLER_DELIVER.getCode());
targetGoods.setExceptStatus(SkupStatus.SELL_OUT.getCode());
sellerOrderGoodsMapper.updateStatusBySkpu(targetGoods);
//TODO 整个过程异步去执行(考虑退费依赖订单状态)
//(退费)退保证金给卖家
//(转账)瓜分指定赔偿款给卖家和平台
//(退费)扣除赔偿款,计算剩余的货款,退给买家
}
}
public void cancel(BeforeDepotReceiveEvent bdrEvent){
Double compensate = orderDynamicConfig.getCOMPENSATE_BEFORE_DEPOT_RECEIVE();
OrderDynamicConfig.BuyerCancelCompensateNode compensate = orderDynamicConfig.getBeforeDepotReceiveBCCN();
logger.info("in buyer cancel BeforeDepotReceive, event {} compensate {}", bdrEvent, compensate);
OrderStatus target = bdrEvent.getTarget();
OrderStatus expected = bdrEvent.getExpected();
int buyerUid = bdrEvent.getBuyerUid();
long orderCode = bdrEvent.getOrderCode();
int currentTime = DateUtil.getCurrentTimeSecond();
int rows = buyerOrderMapper.updateStatusByOrderCode(orderCode, buyerUid, expected.getCode(), target.getCode(), currentTime);
if (rows>0) {
int skup = bdrEvent.getSkup();
SellerOrderGoods targetGoods = new SellerOrderGoods();
targetGoods.setId(skup);
targetGoods.setStatus(SkupStatus.BUYER_CANCEL_BEFORE_DEPOT_RECEIVE.getCode());
targetGoods.setExceptStatus(SkupStatus.SELL_OUT.getCode());
sellerOrderGoodsMapper.updateStatusBySkpu(targetGoods);
//TODO 整个过程异步去执行(考虑退费依赖订单状态)
//(退费)退保证金给卖家
//(转账)瓜分指定赔偿款给卖家和平台
... ... @@ -40,6 +85,9 @@ public class BuyerOrderCancelService {
}
}
}
... ...
... ... @@ -143,21 +143,25 @@ public class BuyerOrderServiceImpl implements IBuyerOrderService {
cancelBeforePaid(orderRequest, node, expectStatus, targetStatus);
break;
case HAS_PAYED:
BuyerOrderGoods bog = buyerOrderGoodsMapper.selectByOrderCode(orderRequest.getUid(),
orderRequest.getOrderCode());
int skup = bog.getSkup();
targetStatus = OrderStatus.BUYER_CANCEL_BEFORE_SELLER_DELIVER;
BeforeSellerDeliverEvent bsde = new BeforeSellerDeliverEvent();
bsde.setUid(orderRequest.getUid());
bsde.setOrderCode(orderRequest.getOrderCode());
bsde.setExpected(expectStatus);
bsde.setTarget(targetStatus);
BeforeSellerDeliverEvent bsde = BeforeSellerDeliverEvent.builder()
.buyerUid(orderRequest.getUid()).orderCode(orderRequest.getOrderCode())
.expected(expectStatus).target(targetStatus).skup(skup).sellerUid(buyerOrder.getSellerUid())
.build();
buyerOrderCancelService.cancel(bsde);
break;
case SELLER_SEND_OUT:
bog = buyerOrderGoodsMapper.selectByOrderCode(orderRequest.getUid(),
orderRequest.getOrderCode());
skup = bog.getSkup();
targetStatus = OrderStatus.BUYER_CANCEL_BEFORE_DEPOT_RECEIVE;
BeforeDepotReceiveEvent bdre = new BeforeDepotReceiveEvent();
bdre.setUid(orderRequest.getUid());
bdre.setOrderCode(orderRequest.getOrderCode());
bdre.setExpected(expectStatus);
bdre.setTarget(targetStatus);
BeforeDepotReceiveEvent bdre = BeforeDepotReceiveEvent.builder()
.buyerUid(orderRequest.getUid()).orderCode(orderRequest.getOrderCode())
.expected(expectStatus).target(targetStatus).skup(skup).sellerUid(buyerOrder.getSellerUid())
.build();
buyerOrderCancelService.cancel(bdre);
break;
}
... ...
package com.yohoufo.order.service.impl;
import com.yohoufo.common.utils.BigDecimalHelper;
import lombok.Data;
import lombok.Getter;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Component;
import javax.annotation.PostConstruct;
import java.math.BigDecimal;
/**
* Created by chao.chen on 2018/11/15.
*/
@Component("orderDynamicConfig")
@Data
public class OrderDynamicConfig {
@Value("${order.buyer.compensate.before_seller_deliver}")
private Double COMPENSATE_BEFORE_SELLER_DELIVER;
final private Logger logger = LoggerFactory.getLogger(getClass());
@Data
public static class BuyerCancelCompensateNode{
/**
* 卖家赔偿金额
*/
private BigDecimal buyerCompensateMoney;
/**
* 卖家获取的赔偿金额
*/
private BigDecimal sellerGetMoney;
/**
* 赔偿比例
*/
private BigDecimal compensateRate;
@Value("${order.buyer.compensate.before_depot_receive}")
private Double COMPENSATE_BEFORE_DEPOT_RECEIVE;
public BuyerCancelCompensateNode(BigDecimal buyerCompensateMoney, BigDecimal compensateRate) {
this.buyerCompensateMoney = buyerCompensateMoney;
this.compensateRate = compensateRate;
this.sellerGetMoney = BigDecimalHelper.halfUp(buyerCompensateMoney.multiply(compensateRate));
}
}
/**
* 卖家发货前
*/
@Value("${order.buyer.cancelWhenSellerUnDelivery.money}")
private String buyerCancelUnDelivery;
@Value("${order.buyer.cancelWhenSellerUnDelivery.sellerGetMoneyRate}")
private String sellerGetRateUnDelivery;
/**
* 卖家发货后 鉴定中心收货前
*/
@Value("${order.buyer.cancelWhenSellerDelivery.money}")
private String buyerCancelDelivery;
@Value("${order.buyer.cancelWhenSellerDelivery.sellerGetMoneyRate}")
private String sellerGetRateDelivery;
public void set(OrderDynamicConfig config){
if (config == null){
return;
/**
* 卖家发货,买家赔偿金额 比例 ,卖家获取金额
*/
@Getter
private BuyerCancelCompensateNode beforeSellerDeliverBCCN;
/**
* 卖家未发货,买家赔偿金额
*/
@Getter
private BuyerCancelCompensateNode beforeDepotReceiveBCCN;
@PostConstruct
private void init() {
BigDecimal buyerCancelUnDeliveryMoney , beforeSellerDeliverRate;
BigDecimal buyerCancelDeliveryMoney, beforeDepotReceiveRate;
try {
buyerCancelDeliveryMoney = new BigDecimal(buyerCancelUnDelivery);
beforeSellerDeliverRate = new BigDecimal( sellerGetRateUnDelivery);
//包装结构时做格式化,之前请保留有效位
beforeSellerDeliverBCCN = new BuyerCancelCompensateNode(BigDecimalHelper.halfUp(buyerCancelDeliveryMoney),
BigDecimalHelper.halfUp(beforeSellerDeliverRate) );
buyerCancelUnDeliveryMoney = new BigDecimal(buyerCancelDelivery);
beforeDepotReceiveRate = new BigDecimal(sellerGetRateDelivery);
beforeDepotReceiveBCCN = new BuyerCancelCompensateNode(buyerCancelUnDeliveryMoney, beforeDepotReceiveRate);
} catch (Exception e) {
logger.error("买家取消罚款金额相关参数配置错误!", e);
throw new Error("买家取消罚款金额相关参数配置错误!");
}
if (buyerCancelDeliveryMoney.compareTo(BigDecimal.ZERO) < 0) {
throw new Error("buyerCancelDeliveryMoney买家取消(货已寄出)罚款金额不能为负数");
}
if(config.COMPENSATE_BEFORE_SELLER_DELIVER>0D){
this.COMPENSATE_BEFORE_SELLER_DELIVER = config.COMPENSATE_BEFORE_SELLER_DELIVER;
if (buyerCancelUnDeliveryMoney.compareTo(BigDecimal.ZERO) < 0) {
throw new Error("buyerCancelUnDeliveryMoney买家取消(货未寄出)罚款金额不能为负数");
}
if(config.COMPENSATE_BEFORE_DEPOT_RECEIVE>0D){
this.COMPENSATE_BEFORE_DEPOT_RECEIVE = config.COMPENSATE_BEFORE_DEPOT_RECEIVE;
if (beforeDepotReceiveRate.compareTo(BigDecimal.ZERO) < 0
|| beforeDepotReceiveRate.compareTo(BigDecimal.ONE) > 0) {
throw new Error("sellerGetRateDeliveryMoney买家取消(货已寄出)卖家获得赔偿比率必须在[0,1]");
}
if (beforeSellerDeliverRate.compareTo(BigDecimal.ZERO) < 0
|| beforeSellerDeliverRate.compareTo(BigDecimal.ONE) > 0) {
throw new Error("sellerGetRateUnDeliveryMoney买家取消(货未寄出)卖家获得赔偿比率必须在[0,1]");
}
}
}
... ...
... ... @@ -17,6 +17,7 @@ import com.yohoufo.common.utils.TimeUtils;
import com.yohoufo.dal.order.*;
import com.yohoufo.dal.order.model.*;
import com.yohoufo.order.common.Payment;
import com.yohoufo.order.common.TransferCase;
import com.yohoufo.order.constants.RefundContant;
import com.yohoufo.order.model.PayQueryBo;
import com.yohoufo.order.model.PayRefundBo;
... ... @@ -29,6 +30,7 @@ import com.yohoufo.order.service.AbstractOrderPaymentService;
import com.yohoufo.order.service.BuyerOrderPaymentService;
import com.yohoufo.order.service.IPaymentService;
import com.yohoufo.order.service.SellerOrderPaymentService;
import com.yohoufo.order.service.handler.BuyerCancelCompensateComputeHandler;
import com.yohoufo.order.service.pay.AbstractPayService;
import com.yohoufo.order.service.pay.alipay.AlipayOuyinService;
import com.yohoufo.order.service.pay.weixin.WeixinMiniappPayService;
... ... @@ -52,7 +54,18 @@ import javax.annotation.PostConstruct;
@Service
public class PaymentServiceImpl implements IPaymentService {
public enum TargetUserType {
buyer(1),seller(2);
int code;
TargetUserType(int code) {
this.code = code;
}
public int getCode() {
return code;
}
}
private static final Logger logger = LoggerUtils.getPayConfirmLogger();
... ... @@ -104,19 +117,10 @@ public class PaymentServiceImpl implements IPaymentService {
@Autowired
TradeBillsMapper tradeBillsMapper;
@Value("${order.buyer.cancelWhenSellerDelivery.money}")
private String buyerCancelDelivery;
@Value("${order.buyer.cancelWhenSellerUnDelivery.money}")
private String buyerCancelUnDelivery;
@Value("${order.buyer.cancelWhenSellerDelivery.sellerGetMoneyRate}")
private String sellerGetRateDelivery;
@Value("${order.buyer.cancelWhenSellerUnDelivery.sellerGetMoneyRate}")
private String sellerGetRateUnDelivery;
@Autowired
private BuyerCancelCompensateComputeHandler buyerCancelCompensateComputeHandler;
private BigDecimal buyerCancelDeliveryMoney;
private BigDecimal buyerCancelUnDeliveryMoney;
private BigDecimal sellerGetRateDeliveryMoney;
private BigDecimal sellerGetRateUnDeliveryMoney;
/**
* 获取主场的订单service
... ... @@ -418,6 +422,7 @@ public class PaymentServiceImpl implements IPaymentService {
}
/**
* <pre>
* 1:鉴定通过(货款-->卖家);
... ... @@ -433,18 +438,17 @@ public class PaymentServiceImpl implements IPaymentService {
@Database(ForceMaster = true)
public void transferMon(TransferMoneyRequest request){
logger.info("transferMon转账开始,request = {}", request);
long buyerOrderCode = request.getBuyerOrderCode();
int transferType = request.getType();
logger.info("transferMon参数检查");
// 订单号check
if (buyerOrderCode < 1) {
if (buyerOrderCode < 1L) {
logger.warn("transferMonErr orderCode empty");
throw new ServiceException(ServiceError.ORDER_REQUEST_PARM_IS_EMPTY);
}
// 类型检查
if (transferType < 1 || transferType > 5) {
int transferType = request.getType();
TransferCase transferCase = TransferCase.getTransferCase(transferType);
if (transferCase == null) {
logger.warn("transferMonErr transferType invalid");
throw new ServiceException(ServiceError.ORDER_REQUEST_PARM_IS_EMPTY);
}
... ... @@ -470,8 +474,10 @@ public class PaymentServiceImpl implements IPaymentService {
}
long sellerOrderCode = sellerOrder.getOrderCode();
Integer targetUserType = (transferType == 2 || transferType == 3) ? 1 : 2;
Integer targetUid = targetUserType == 1 ? buyerOrder.getUid() : sellerOrder.getUid();
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;
Integer targetUid = targetUserType == TargetUserType.buyer ? buyerOrder.getUid() : sellerOrder.getUid();
if (targetUid == null || targetUid < 1) {
logger.warn("transferMonErr uid {} 不合法", targetUid);
... ... @@ -508,7 +514,7 @@ public class PaymentServiceImpl implements IPaymentService {
TradeBills record = new TradeBills();
record.setUid(targetUid);
record.setOrderCode(buyerOrderCode);
record.setUserType(targetUserType);
record.setUserType(targetUserType.getCode());
record.setPayType(1);
record.setTradeType(transferType == 1 ? 2 : 3);
record.setIncomeOutcome(1);
... ... @@ -520,7 +526,7 @@ public class PaymentServiceImpl implements IPaymentService {
logger.info("transferMon插入初始化转账信息成功,接下来计算费用");
// 算费
BigDecimal transferAmount = calcTransferAmount(sellerOrder.getUid(), sellerOrder.getSkup(), transferType);
BigDecimal transferAmount = calcTransferAmount(sellerOrder.getUid(), sellerOrder.getSkup(), transferCase);
logger.info("transferMon计算费用结果为 {}", transferAmount);
if (transferAmount == null) {
logger.warn("transferMonErr transferMon计算费用结果为 null, 不合法的金额");
... ... @@ -917,14 +923,21 @@ public class PaymentServiceImpl implements IPaymentService {
addTradeBills(record);
}
private BigDecimal getBuyerCancelBeforeSellerDeliver(){
//todo
return buyerCancelCompensateComputeHandler.calBeforeSellerDeliver();
}
private BigDecimal getBuyerCancelBeforeDepotReceive(){
//todo
return buyerCancelCompensateComputeHandler.calBeforeDepotReceive();
}
private BigDecimal calcTransferAmount(Integer sellerUid, Integer skup, int transferType) {
if (transferType == 4) {
return sellerGetRateUnDeliveryMoney;
private BigDecimal calcTransferAmount(Integer sellerUid, Integer skup, TransferCase transferCase) {
if (transferCase == TransferCase.BUYER_CANCEL_BEFORE_SELLER_DELIVER) {
return getBuyerCancelBeforeSellerDeliver();
}
if (transferType == 5) {
return sellerGetRateDeliveryMoney;
if (transferCase == TransferCase.BUYER_CANCEL_BEFORE_DEPOT_RECEIVE) {
return getBuyerCancelBeforeDepotReceive();
}
SellerOrderMeta meta = sellerOrderMetaMapper.selectByMetaKey(sellerUid, skup, "fee");
... ... @@ -940,7 +953,7 @@ public class PaymentServiceImpl implements IPaymentService {
try {
JSONObject metavalue = JSON.parseObject(meta.getMetaValue());
// 交易成功的情况
if (transferType == 1) {
if (transferCase == TransferCase.APPRAISE_SUCCESS) {
return metavalue.getBigDecimal("income");
}
// (1-Y)*A
... ... @@ -1048,33 +1061,6 @@ public class PaymentServiceImpl implements IPaymentService {
CommonAlarmEventPublisher.publish(name, type, content);
}
@PostConstruct
private void init() {
try {
buyerCancelDeliveryMoney = new BigDecimal(buyerCancelUnDelivery);
buyerCancelUnDeliveryMoney = new BigDecimal(buyerCancelUnDelivery);
sellerGetRateDeliveryMoney = buyerCancelDeliveryMoney.multiply(new BigDecimal(sellerGetRateDelivery))
.setScale(2, BigDecimal.ROUND_HALF_DOWN);
sellerGetRateUnDeliveryMoney = buyerCancelUnDeliveryMoney.multiply(new BigDecimal(sellerGetRateUnDelivery))
.setScale(2, BigDecimal.ROUND_HALF_DOWN);
} catch (Exception e) {
logger.error("买家取消罚款金额相关参数配置错误!", e);
throw new Error("买家取消罚款金额相关参数配置错误!");
}
if (buyerCancelDeliveryMoney.compareTo(BigDecimal.ZERO) < 0) {
throw new Error("buyerCancelDeliveryMoney买家取消(货已寄出)罚款金额不能为负数");
}
if (buyerCancelUnDeliveryMoney.compareTo(BigDecimal.ZERO) < 0) {
throw new Error("buyerCancelUnDeliveryMoney买家取消(货未寄出)罚款金额不能为负数");
}
if (sellerGetRateDeliveryMoney.compareTo(BigDecimal.ZERO) < 0
|| sellerGetRateDeliveryMoney.compareTo(BigDecimal.ONE) > 0) {
throw new Error("sellerGetRateDeliveryMoney买家取消(货已寄出)卖家获得赔偿比率必须在[0,1]");
}
if (sellerGetRateUnDeliveryMoney.compareTo(BigDecimal.ZERO) < 0
|| sellerGetRateUnDeliveryMoney.compareTo(BigDecimal.ONE) > 0) {
throw new Error("sellerGetRateUnDeliveryMoney买家取消(货未寄出)卖家获得赔偿比率必须在[0,1]");
}
}
}
... ...