Authored by chenchao

optimized compute seller goods fee

... ... @@ -15,7 +15,7 @@ import com.yohoufo.dal.order.model.SellerOrder;
import com.yohoufo.order.model.request.OrderListRequest;
import com.yohoufo.order.model.request.OrderRequest;
import com.yohoufo.order.model.response.OrderSubmitResp;
import com.yohoufo.order.service.handler.SellerOrderComputeHandler;
import com.yohoufo.order.service.impl.OrderDynamicConfig;
import com.yohoufo.order.service.impl.SellerOrderService;
import com.yohoufo.order.service.impl.SellerService;
import com.yohoufo.order.service.impl.SkupListService;
... ... @@ -44,7 +44,7 @@ public class SellerOrderController {
private SellerOrderService sellerOrderService;
@Autowired
private SellerOrderComputeHandler sellerOrderComputeHandler;
protected OrderDynamicConfig orderDynamicConfig;
@Autowired
private SellerService sellerService;
... ... @@ -211,7 +211,7 @@ public class SellerOrderController {
@ResponseBody
public ApiResponse getEarnestMoneyRange(){
return new ApiResponse.ApiResponseBuilder()
.data(sellerOrderComputeHandler.getEarnestMoneyrange())
.data(orderDynamicConfig.getEMR())
.message("get EarnestMoneyrange success").build();
}
... ...
package com.yohoufo.order.service.handler;
import com.yohoufo.common.utils.BigDecimalHelper;
import com.yohoufo.order.model.dto.EarnestMoney;
import com.yohoufo.order.model.dto.PlatformFeeDto;
import com.yohoufo.order.model.dto.SellerOrderComputeResult;
import com.yohoufo.order.model.dto.ServiceFeeRate;
import com.yohoufo.order.utils.LoggerUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Value;
import com.yohoufo.order.service.seller.AbsSellerOrderComputeHandler;
import org.springframework.stereotype.Component;
import javax.annotation.PostConstruct;
import java.math.BigDecimal;
/**
* Created by chenchao on 2018/9/14.
*/
@Component
public class SellerOrderComputeHandler {
private Logger logger = LoggerUtils.getSellerOrderLogger();
@Value("${order.seller.earnestmoney.min:28}")
private double earnestmoney_min;
@Value("${order.seller.earnestmoney.max:200}")
private double earnestmoney_max;
private BigDecimal[] EARNESTMONEYRANGE = new BigDecimal[2];
@Value("${order.seller.appraiseFee:5}")
private Double appraiseFee;
/**
* 有货包装费(暂定5元)
*/
@Value("${order.seller.packageFee:5}")
private Double packageFee ;
@Value("${order.seller.goodsPaymentRate}")
private Double goodsPaymentRate = 0.05D;
@Value("${order.seller.earnestMoneyRate}")
private Double earnestMoneyRate = 0.20D;
@Value("${order.seller.payChannelRate}")
private Double payChannelRate = 0.006D;
@PostConstruct
public void init(){
EARNESTMONEYRANGE[0] = new BigDecimal(earnestmoney_min);
EARNESTMONEYRANGE[1] = new BigDecimal(earnestmoney_max);
}
public BigDecimal[] getEarnestMoneyrange(){
return EARNESTMONEYRANGE;
}
public SellerOrderComputeResult compute(BigDecimal prdPrice){
//保证金(28-200(按照卖家发布商品的货款金额5%计算,最低28,封顶200))
EarnestMoney earnestMoney = calEarnestMoney(prdPrice);
//init fee rate
ServiceFeeRate serviceFeeRate = new ServiceFeeRate();
serviceFeeRate.setGoodsPaymentRate(new BigDecimal(goodsPaymentRate).setScale(2, BigDecimal.ROUND_HALF_UP));
serviceFeeRate.setEarnestMoneyRate(new BigDecimal(earnestMoneyRate).setScale(2, BigDecimal.ROUND_HALF_UP));
serviceFeeRate.setPayChannelRate(new BigDecimal(payChannelRate).setScale(4, BigDecimal.ROUND_HALF_UP));
//
PlatformFeeDto platformFeeDto = calPlatformFee(prdPrice, serviceFeeRate.getGoodsPaymentRate());
BigDecimal bankTransferFee = calBankTransferFee(prdPrice, serviceFeeRate.getPayChannelRate());
logger.info("in SellerOrder Compute, prdPrice {}, platformFee {}, bankTransferFee {}",
prdPrice, platformFeeDto, bankTransferFee);
BigDecimal income = calIncome(prdPrice, platformFeeDto.getTotal(), bankTransferFee);
//set
SellerOrderComputeResult result = new SellerOrderComputeResult();
result.setEarnestMoney(earnestMoney);
result.setPlatformFee(platformFeeDto);
result.setIncome(halfUp(income));
//TODO 根据配置文件
result.setServiceFeeRate(serviceFeeRate);
result.setBankTransferfee(bankTransferFee);
return result;
}
private BigDecimal calBankTransferFee(BigDecimal prdPrice, BigDecimal payServiceFeeRate){
//支付渠道转账费率(0.6%)
return halfUp(prdPrice.multiply(payServiceFeeRate));
}
/**
* (1-X-Z)*B-D-E *
B:货款(卖家发布商品自行输入);
D:有货鉴定费(暂定5元);
E:有货包装费(暂定5元);
X:货款抽成(暂定5%,后期可调整,上线初期为0,后期活动可根据活动进行减免,每个卖家可收费不一样);
Z:支付渠道费,调用银联支付接口时实时扣款(支付宝0.55%、微信均为0.6%,统一对用户收取0.6%,前期优惠策略可暂定0)
* @param prdPrice
* @param platformFee
* @return
*/
private BigDecimal calIncome(BigDecimal prdPrice,BigDecimal platformFee,BigDecimal bankTransferFee){
return prdPrice.subtract(platformFee).subtract(bankTransferFee);
}
public Double getAppraiseFee() {
return appraiseFee;
}
public Double getPackageFee() {
return packageFee;
}
/**
* 通过相加得出的数据
* 服务费参与计算后需要考虑精度问题(四舍五入)
* @return
*/
private PlatformFeeDto calPlatformFee(BigDecimal price, BigDecimal goodsServiceRate){
PlatformFeeDto platformFee = new PlatformFeeDto();
BigDecimal appraiseFee = new BigDecimal(getAppraiseFee());
BigDecimal packageFee = new BigDecimal(getPackageFee());
BigDecimal serviceFee = price.multiply(goodsServiceRate);
platformFee.setAppraiseFee(halfUp(appraiseFee));
platformFee.setPackageFee(halfUp(packageFee));
BigDecimal total = appraiseFee.add(packageFee).add(serviceFee);
platformFee.setTotal(halfUp(total));
platformFee.setServiceFee(halfUp(serviceFee));
return platformFee;
}
public class SellerOrderComputeHandler extends AbsSellerOrderComputeHandler{
/**
* 相对独立 不涉及到计算其他费用
* @param prdPrice
* @return
*/
private EarnestMoney calEarnestMoney(BigDecimal prdPrice){
protected EarnestMoney calEarnestMoney(BigDecimal prdPrice){
BigDecimal[] EARNEST_MONEY_RANGE = orderDynamicConfig.getEMR();
EarnestMoney earnestMoney = new EarnestMoney();
BigDecimal real = halfUp(prdPrice.multiply(earnestMoney.getRate()));
final BigDecimal min = EARNESTMONEYRANGE[0] == null ? earnestMoney.getMin() : EARNESTMONEYRANGE[0];
final BigDecimal max = EARNESTMONEYRANGE[1] == null ? earnestMoney.getMax() : EARNESTMONEYRANGE[1];
if(real.subtract(min).doubleValue() < 0D){
final BigDecimal min = EARNEST_MONEY_RANGE[0] == null ? earnestMoney.getMin() : EARNEST_MONEY_RANGE[0];
final BigDecimal max = EARNEST_MONEY_RANGE[1] == null ? earnestMoney.getMax() : EARNEST_MONEY_RANGE[1];
if(real.compareTo(min) < 0){
real = min;
}
if (real.subtract(max).doubleValue() > 0D){
if (real.compareTo(max) > 0){
real = max;
}
earnestMoney.setMin(min);
... ... @@ -152,7 +36,11 @@ public class SellerOrderComputeHandler {
return earnestMoney;
}
private BigDecimal halfUp(BigDecimal fee){
return BigDecimalHelper.halfUp(fee);
@Override
protected ServiceFeeRate buildServiceFeeRate() {
ServiceFeeRate serviceFeeRate = orderDynamicConfig.getServiceFeeRate();
return serviceFeeRate;
}
}
... ...
package com.yohoufo.order.service.impl;
import com.yohoufo.common.utils.BigDecimalHelper;
import com.yohoufo.order.model.dto.ServiceFeeRate;
import lombok.Data;
import lombok.Getter;
import org.slf4j.Logger;
... ... @@ -14,12 +15,40 @@ import java.math.BigDecimal;
/**
* Created by chao.chen on 2018/11/15.
*/
@Component("orderDynamicConfig")
@Component
public class OrderDynamicConfig {
final private Logger logger = LoggerFactory.getLogger(getClass());
@Value("${order.seller.earnestmoney.min:28}")
protected double earnestmoney_min;
@Value("${order.seller.earnestmoney.max:200}")
protected double earnestmoney_max;
/**
* 货款抽成费率
*/
@Value("${order.seller.goodsPaymentRate}")
private Double goodsPaymentRate = 0.05D;
/**
* 保证金抽成费率
*/
@Value("${order.seller.earnestMoneyRate}")
private Double earnestMoneyRate = 0.20D;
/**
* (主要是第三方,支付宝 or 微信)支付渠道手续费率
*/
@Value("${order.seller.payChannelRate}")
private Double payChannelRate = 0.006D;
/**
* 保证金上下限阈值
*/
private BigDecimal[] EARNEST_MONEY_RANGE = new BigDecimal[2];
@Data
public static class BuyerCancelCompensateNode{
/**
... ... @@ -70,40 +99,30 @@ public class OrderDynamicConfig {
*/
private BuyerCancelCompensateNode beforeDepotReceiveBCCN;
@Getter
private ServiceFeeRate serviceFeeRate;
@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 (buyerCancelUnDeliveryMoney.compareTo(BigDecimal.ZERO) < 0) {
throw new Error("buyerCancelUnDeliveryMoney买家取消(货未寄出)罚款金额不能为负数");
}
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]");
}
EARNEST_MONEY_RANGE[0] = new BigDecimal(earnestmoney_min);
EARNEST_MONEY_RANGE[1] = new BigDecimal(earnestmoney_max);
//
//ServiceFeeRate buildServiceFeeRate() {
serviceFeeRate = new ServiceFeeRate();
serviceFeeRate.setGoodsPaymentRate(new BigDecimal(goodsPaymentRate).setScale(2, BigDecimal.ROUND_HALF_UP));
serviceFeeRate.setEarnestMoneyRate(new BigDecimal(earnestMoneyRate).setScale(2, BigDecimal.ROUND_HALF_UP));
serviceFeeRate.setPayChannelRate(new BigDecimal(payChannelRate).setScale(4, BigDecimal.ROUND_HALF_UP));
}
/**
*
* EMR : EarnestMoneyRange
* @return
*/
public BigDecimal[] getEMR(){
return EARNEST_MONEY_RANGE;
}
}
... ...
package com.yohoufo.order.service.seller;
import com.yohoufo.common.utils.BigDecimalHelper;
import com.yohoufo.order.model.dto.EarnestMoney;
import com.yohoufo.order.model.dto.PlatformFeeDto;
import com.yohoufo.order.model.dto.SellerOrderComputeResult;
import com.yohoufo.order.model.dto.ServiceFeeRate;
import com.yohoufo.order.service.impl.OrderDynamicConfig;
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 java.math.BigDecimal;
/**
* Created by chao.chen on 2019/2/1.
*/
public abstract class AbsSellerOrderComputeHandler {
protected Logger logger = LoggerUtils.getSellerOrderLogger();
@Autowired
protected OrderDynamicConfig orderDynamicConfig;
/**
* 鉴定费
*/
@Value("${order.seller.appraiseFee:5}")
private Double appraiseFee;
/**
* 有货包装费(暂定5元)
*/
@Value("${order.seller.packageFee:5}")
private Double packageFee ;
public SellerOrderComputeResult compute(BigDecimal prdPrice){
//保证金(28-200(按照卖家发布商品的货款金额5%计算,最低28,封顶200))
EarnestMoney earnestMoney = calEarnestMoney(prdPrice);
//init fee rate
ServiceFeeRate serviceFeeRate = buildServiceFeeRate();
PlatformFeeDto platformFeeDto = calPlatformFee(prdPrice, serviceFeeRate);
BigDecimal bankTransferFee = calBankTransferFee(prdPrice, serviceFeeRate.getPayChannelRate());
logger.info("in SellerOrder Compute, prdPrice {}, platformFee {}, bankTransferFee {}",
prdPrice, platformFeeDto, bankTransferFee);
BigDecimal income = calIncome(prdPrice, platformFeeDto.getTotal(), bankTransferFee);
//set
SellerOrderComputeResult result = new SellerOrderComputeResult();
result.setEarnestMoney(earnestMoney);
result.setPlatformFee(platformFeeDto);
result.setIncome(halfUp(income));
//TODO 根据配置文件
result.setServiceFeeRate(serviceFeeRate);
result.setBankTransferfee(bankTransferFee);
return result;
}
protected BigDecimal halfUp(BigDecimal fee){
return BigDecimalHelper.halfUp(fee);
}
protected abstract EarnestMoney calEarnestMoney(BigDecimal prdPrice);
/**
* (1-X-Z)*B-D-E *
B:货款(卖家发布商品自行输入);
D:有货鉴定费(暂定5元);
E:有货包装费(暂定5元);
X:货款抽成(暂定5%,后期可调整,上线初期为0,后期活动可根据活动进行减免,每个卖家可收费不一样);
Z:支付渠道费,调用银联支付接口时实时扣款(支付宝0.55%、微信均为0.6%,统一对用户收取0.6%,前期优惠策略可暂定0)
* @param prdPrice
* @param platformFee
* @return
*/
protected BigDecimal calIncome(BigDecimal prdPrice, BigDecimal platformFee, BigDecimal bankTransferFee){
return prdPrice.subtract(platformFee).subtract(bankTransferFee);
}
protected BigDecimal calBankTransferFee(BigDecimal prdPrice, BigDecimal payServiceFeeRate){
//支付渠道转账费率(0.6%)
return halfUp(prdPrice.multiply(payServiceFeeRate));
}
/**
* 通过相加得出的数据
* 服务费参与计算后需要考虑精度问题(四舍五入)
* @return
*/
protected PlatformFeeDto calPlatformFee(BigDecimal price, ServiceFeeRate serviceFeeRate){
BigDecimal goodsServiceRate = serviceFeeRate.getGoodsPaymentRate();
PlatformFeeDto platformFee = new PlatformFeeDto();
BigDecimal appraiseFee = new BigDecimal(getAppraiseFee());
BigDecimal packageFee = new BigDecimal(getPackageFee());
BigDecimal serviceFee = price.multiply(goodsServiceRate);
platformFee.setAppraiseFee(halfUp(appraiseFee));
platformFee.setPackageFee(halfUp(packageFee));
BigDecimal total = appraiseFee.add(packageFee).add(serviceFee);
platformFee.setTotal(halfUp(total));
platformFee.setServiceFee(halfUp(serviceFee));
return platformFee;
}
public Double getAppraiseFee() {
return appraiseFee;
}
public Double getPackageFee() {
return packageFee;
}
protected abstract ServiceFeeRate buildServiceFeeRate();
}
... ...
package com.yohoufo.order.service.seller;
import com.yohoufo.order.model.dto.EarnestMoney;
import com.yohoufo.order.model.dto.ServiceFeeRate;
import org.springframework.stereotype.Component;
import java.math.BigDecimal;
/**
* Created by chao.chen on 2019/2/1.
*/
@Component
public class SellerAdvanceOrderComputeHandler extends AbsSellerOrderComputeHandler {
@Override
protected EarnestMoney calEarnestMoney(BigDecimal prdPrice) {
return null;
}
@Override
protected ServiceFeeRate buildServiceFeeRate() {
return null;
}
}
... ...