Authored by sailing-PC\sailing

fix compute earnest money

add inbox msg facade
use optimized lock 2 update seller order status
Showing 26 changed files with 340 additions and 103 deletions
... ... @@ -81,4 +81,8 @@ public class BigDecimalHelper {
}
public static BigDecimal halfUp(BigDecimal fee){
return fee.setScale(2, BigDecimal.ROUND_HALF_UP);
}
}
... ...
... ... @@ -27,4 +27,7 @@ public interface SellerOrderGoodsMapper {
@Param("statusList") List<Integer> statusList,
@Param("offset")Integer offset,
@Param("limit")Integer limit);
int updateStatusBySkpu(SellerOrderGoods record);
}
\ No newline at end of file
... ...
... ... @@ -23,6 +23,10 @@ public class SellerOrder {
private Integer isDel;
private Integer status;
/**
* 期望的原值,用来做乐观锁
*/
private Integer exceptStatus;
private Integer createTime;
... ... @@ -124,4 +128,13 @@ public class SellerOrder {
public void setIsDel(Integer isDel) {
this.isDel = isDel;
}
public Integer getExceptStatus() {
return exceptStatus;
}
public void setExceptStatus(Integer exceptStatus) {
this.exceptStatus = exceptStatus;
}
}
\ No newline at end of file
... ...
... ... @@ -27,6 +27,7 @@ public class SellerOrderGoods {
private Integer status;
private Integer exceptStatus;
private String imageUrl;
... ... @@ -136,4 +137,12 @@ public class SellerOrderGoods {
public void setUid(Integer uid) {
this.uid = uid;
}
public Integer getExceptStatus() {
return exceptStatus;
}
public void setExceptStatus(Integer exceptStatus) {
this.exceptStatus = exceptStatus;
}
}
\ No newline at end of file
... ...
... ... @@ -169,6 +169,21 @@
</if>
</trim>
</insert>
<update id="updateStatusBySkpu" parameterType="com.yohoufo.dal.order.model.SellerOrderGoods">
update seller_order_goods
<set>
<if test="status != null">
status = #{status,jdbcType=TINYINT},
</if>
</set>
where id = #{id,jdbcType=INTEGER}
and status = #{exceptStatus,jdbcType=TINYINT}
</update>
<update id="updateByPrimaryKeySelective" parameterType="com.yohoufo.dal.order.model.SellerOrderGoods">
update seller_order_goods
<set>
... ...
... ... @@ -214,6 +214,8 @@
update_time = #{updateTime,jdbcType=INTEGER}
where uid = #{uid,jdbcType=INTEGER}
and order_code = #{orderCode,jdbcType=BIGINT}
and status = #{exceptStatus,jdbcType=INTEGER}
</update>
... ...
... ... @@ -54,5 +54,15 @@
<artifactId>javax.servlet-api</artifactId>
<scope>compile</scope>
</dependency>
<dependency>
<groupId>com.yohoufo.fore</groupId>
<artifactId>yohoufo-fore-inboxclient</artifactId>
</dependency>
<dependency>
<groupId>com.yoho.ufo.model</groupId>
<artifactId>user-ufo-model</artifactId>
</dependency>
</dependencies>
</project>
\ No newline at end of file
... ...
... ... @@ -11,7 +11,7 @@ import java.util.List;
public class ActionStatusHold {
public static List<Integer> getSellerCanCancelStatus(){
public static List<Integer> getSellerCanRefundStatus(){
List<Integer> sellerCanCancelStatus;
sellerCanCancelStatus = Arrays.asList(SellerOrderStatus.WAITING_PAY.getCode(),
SellerOrderStatus.HAS_PAYED.getCode());
... ... @@ -19,15 +19,15 @@ public class ActionStatusHold {
return sellerCanCancelStatus;
}
public static List<Integer> getSellerCanRefundEarnestMoneyStatus(){
List<Integer> sellerCanCancelStatus;
sellerCanCancelStatus = Arrays.asList(SellerOrderStatus.SELf_CANCEL_PAY.getCode(),
SellerOrderStatus.TIMEOUT_CANCEL.getCode(),
static List<Integer> sellerCanRefundStatus;
static {
sellerCanRefundStatus = Arrays.asList(
SellerOrderStatus.YOHO_CANCEL_SELL.getCode(),
SellerOrderStatus.FINISH.getCode());
}
return sellerCanCancelStatus;
public static List<Integer> getSellerCanRefundEarnestMoneyStatus(){
return sellerCanRefundStatus;
}
... ...
... ... @@ -4,6 +4,7 @@ import com.yohobuy.ufo.model.order.bo.PlatformFee;
import com.yohobuy.ufo.model.order.bo.SoldPrdComputeBo;
import com.yohoufo.common.utils.BigDecimalHelper;
import com.yohoufo.common.utils.PriceFormater;
import com.yohoufo.order.model.dto.EarnestMoney;
import com.yohoufo.order.model.dto.PlatformFeeDto;
import com.yohoufo.order.model.dto.SellerOrderComputeResult;
... ... @@ -16,9 +17,8 @@ public final class SellerOrderConvertor {
public static SoldPrdComputeBo computeResult2SoldPrdComputeBo(SellerOrderComputeResult computeResult){
//保证金(28-200(按照卖家发布商品的货款金额5%计算,最低28,封顶200))
BigDecimal earnestMoney = computeResult.getEarnestMoney();
//银行转账费(0.65%+¥1.00)
BigDecimal bankTransferfee = computeResult.getBankTransferfee();
EarnestMoney earnestMoneyDTO = computeResult.getEarnestMoney();
BigDecimal earnestMoney = earnestMoneyDTO.getEarnestMoney();
PlatformFeeDto platformFeeDto = computeResult.getPlatformFee();
BigDecimal income = computeResult.getIncome();
... ... @@ -27,15 +27,13 @@ public final class SellerOrderConvertor {
.amount(buildSubtractFee(formatFee(platformFeeDto.getTotal())))
.appraiseFee(formatFee(platformFeeDto.getAppraiseFee()))
.packageFee(formatFee(platformFeeDto.getPackageFee()))
.serviceFee(formatFee(platformFeeDto.getServiceFee())).build();
.build();
//
String incomeStr = formatFee(income);
String earnestMoneyStr = formatFee(earnestMoney);
String bankTransferFeeStr = buildSubtractFee(formatFee(bankTransferfee));
SoldPrdComputeBo computeBo = SoldPrdComputeBo.builder()
.earnestMoney(earnestMoney.doubleValue())
.earnestMoneyStr(earnestMoneyStr)
.bankTransferFee(bankTransferFeeStr)
.platformFee(platformFeeWrapper)
.income(incomeStr)
.build();
... ...
... ... @@ -27,6 +27,14 @@ public class OrderInfo {
private Integer payment;
private Integer status;
/**
* 原来(数据库持久化)的状态
*/
private Integer sourceStatus;
/**
* 目标状态
*/
private Integer targetStatus;
private OrderCodeType orderCodeType;
... ...
package com.yohoufo.order.model.dto;
import com.yohoufo.common.utils.BigDecimalHelper;
import lombok.Data;
import java.math.BigDecimal;
/**
* 保证金(28-200(按照卖家发布商品的货款金额5%计算,最低28,封顶200))
* Created by chenchao on 2018/10/8.
*/
@Data
public class EarnestMoney {
private BigDecimal prdSalePrice;
private BigDecimal min = new BigDecimal(28);
private BigDecimal max = new BigDecimal(200);
private BigDecimal rate = new BigDecimal(0.05D).setScale(2, BigDecimal.ROUND_HALF_UP);
private BigDecimal earnestMoney;
}
... ...
... ... @@ -11,7 +11,14 @@ import java.math.BigDecimal;
public class PlatformFeeDto {
BigDecimal total;
BigDecimal appraiseFee;
BigDecimal packageFee;
BigDecimal serviceFee;
/**
* 有货鉴定费(暂定5元)
*/
BigDecimal appraiseFee = new BigDecimal(5);
/**
* 有货包装费(暂定5元)
*/
BigDecimal packageFee = new BigDecimal(5);
}
... ...
... ... @@ -10,7 +10,7 @@ import java.math.BigDecimal;
@Data
public class SellerOrderComputeResult {
BigDecimal earnestMoney;
EarnestMoney earnestMoney;
//
PlatformFeeDto platformFee;
BigDecimal bankTransferfee;
... ...
package com.yohoufo.order.model.dto;
import com.yohoufo.common.utils.BigDecimalHelper;
import lombok.Data;
import java.math.BigDecimal;
/**
* Created by chenchao on 2018/9/28.
*/
@Data
public class ServiceFeeRate {
BigDecimal goodsPaymentRate = new BigDecimal(0.05D);
BigDecimal earnestMoneyRate = new BigDecimal(0.20D);
BigDecimal payChannelRate = new BigDecimal(0.0006D);
/**
* 货款抽成
* (
* 暂定5%,后期可调整,上线初期为0,
* 后期活动可根据活动进行减免,每个卖家可收费不一样
* )
*/
BigDecimal goodsPaymentRate = new BigDecimal(0.05D).setScale(2, BigDecimal.ROUND_HALF_UP);
/**
* 保证金抽成(暂定20%,后期可调整)
*/
BigDecimal earnestMoneyRate = new BigDecimal(0.20D).setScale(2, BigDecimal.ROUND_HALF_UP);
/**
* 支付渠道费,调用银联支付接口时实时扣款
* (支付宝0.55%、微信均为0.6%,统一对用户收取0.6%,前期优惠策略可暂定0)
*/
BigDecimal payChannelRate = new BigDecimal(0.0006D).setScale(4, BigDecimal.ROUND_HALF_UP);
public static ServiceFeeRate getServiceFeeRate(){
... ...
... ... @@ -76,6 +76,8 @@ public abstract class AbstractOrderPaymentService {
public abstract boolean isOrderPaid(OrderInfo orderInfo);
public abstract boolean canRefund(OrderInfo orderInfo);
/**
* 更新订单状态
* @param orderInfo
... ...
... ... @@ -88,6 +88,13 @@ public class BuyerOrderPaymentService extends AbstractOrderPaymentService {
return false;
}
@Override
public boolean canRefund(OrderInfo orderInfo) {
if (orderInfo.getStatus() != null && orderInfo.getStatus().intValue() == OrderStatus.HAS_PAYED.getCode()){
return true;
}
return false;
}
/**
... ... @@ -188,6 +195,7 @@ public class BuyerOrderPaymentService extends AbstractOrderPaymentService {
.amount(buyerOrder.getAmount())
.createTime(buyerOrder.getCreateTime())
.orderCodeType(OrderCodeType.BUYER_TYPE)
.sourceStatus(buyerOrder.getStatus())
.build();
... ... @@ -197,7 +205,7 @@ public class BuyerOrderPaymentService extends AbstractOrderPaymentService {
/**
* 获取订单情报
* @param request
* @param orderCode
* @return
*/
public OrderInfo getOrderInfo(long orderCode) {
... ...
... ... @@ -25,6 +25,8 @@ import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import java.util.Objects;
@Service
public class SellerOrderPaymentService extends AbstractOrderPaymentService {
... ... @@ -49,25 +51,29 @@ public class SellerOrderPaymentService extends AbstractOrderPaymentService {
* @param orderInfo
*/
public void updateOrderStatusPaid(OrderInfo orderInfo){
//TODO
//
logger.info("in update seller OrderStatus after Paid, orderInfo {}",orderInfo);
SellerOrder sellerOrder = new SellerOrder();
sellerOrder.setOrderCode(orderInfo.getOrderCode());
sellerOrder.setUid(orderInfo.getUid());
SellerOrderStatus sellerOrderStatus = SellerOrderStatus.HAS_PAYED;
sellerOrder.setStatus(sellerOrderStatus.getCode());
SellerOrderStatus soTargetStatus = SellerOrderStatus.HAS_PAYED;
sellerOrder.setStatus(soTargetStatus.getCode());
orderInfo.setStatus(sellerOrderStatus.getCode());
orderInfo.setStatus(soTargetStatus.getCode());
sellerOrder.setUpdateTime(DateUtil.getCurrentTimeSecond());
sellerOrderMapper.updateByOrderCode(sellerOrder);
//
SellerOrderGoods targetSog = new SellerOrderGoods();
targetSog.setId(orderInfo.getSkup());
targetSog.setStatus(sellerOrderStatus.getSkupStatus().getCode());
sellerOrderGoodsMapper.updateByPrimaryKeySelective(targetSog);
SellerOrderGoods tsog = new SellerOrderGoods();
tsog.setId(orderInfo.getSkup());
productProxyService.syncSkup(tsog,sellerOrderStatus.getSkupStatus());
sellerOrder.setExceptStatus(SellerOrderStatus.WAITING_PAY.getCode());
int updateCnt = sellerOrderMapper.updateByOrderCode(sellerOrder);
if (1 == updateCnt) {
//
SellerOrderGoods targetSog = new SellerOrderGoods();
targetSog.setId(orderInfo.getSkup());
targetSog.setStatus(soTargetStatus.getSkupStatus().getCode());
sellerOrderGoodsMapper.updateByPrimaryKeySelective(targetSog);
//sync 2 product biz model
SellerOrderGoods tsog = new SellerOrderGoods();
tsog.setId(orderInfo.getSkup());
productProxyService.syncSkup(tsog, soTargetStatus.getSkupStatus());
}
}
... ... @@ -94,7 +100,7 @@ public class SellerOrderPaymentService extends AbstractOrderPaymentService {
public boolean isOrderPaid(OrderInfo orderInfo){
if (orderInfo.getStatus() == null ||
!ActionStatusHold.getSellerCanRefundEarnestMoneyStatus().contains(orderInfo.getStatus().intValue())){
!Objects.equals(SellerOrderStatus.HAS_PAYED.getCode(), orderInfo.getStatus().intValue())){
return false;
}
... ... @@ -102,6 +108,17 @@ public class SellerOrderPaymentService extends AbstractOrderPaymentService {
}
public boolean canRefund(OrderInfo orderInfo){
Integer sourceStatus = orderInfo.getSourceStatus();
if (sourceStatus != null &&
ActionStatusHold.getSellerCanRefundEarnestMoneyStatus().contains(sourceStatus.intValue())){
return true;
}
return false;
}
/**
* 保存前回预支付结果
* @param orderInfo
... ... @@ -225,6 +242,7 @@ public class SellerOrderPaymentService extends AbstractOrderPaymentService {
.status(sellerOrder.getStatus())
.orderCodeType(OrderCodeType.BUYER_TYPE)
.amount(sellerOrder.getEarnestMoney())
.sourceStatus(sellerOrder.getStatus())
.build();
return orderInfo;
}
... ...
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;
... ... @@ -16,9 +18,9 @@ import java.math.BigDecimal;
public class SellerOrderComputeHandler {
@Value("${order.seller.earnestmoney.min:28}")
private double earnestmoney_min;
private double earnestmoney_min = 28;
@Value("${order.seller.earnestmoney.max:200}")
private double earnestmoney_max;
private double earnestmoney_max = 200;
private BigDecimal[] EARNESTMONEYRANGE = new BigDecimal[2];
... ... @@ -35,19 +37,19 @@ public class SellerOrderComputeHandler {
public SellerOrderComputeResult compute(BigDecimal prdPrice){
//保证金(28-200(按照卖家发布商品的货款金额5%计算,最低28,封顶200))
BigDecimal earnestMoney = calEarnestMoney(prdPrice);
//银行转账费(0.65%+¥1.00)
BigDecimal bankTransferfee = calBankTransferFee(prdPrice);
EarnestMoney earnestMoney = calEarnestMoney(prdPrice);
PlatformFeeDto platformFeeDto = calPlatformFee();
BigDecimal income = calIncome(prdPrice, platformFeeDto.getTotal(), bankTransferfee);
//
ServiceFeeRate serviceFeeRate = ServiceFeeRate.getServiceFeeRate();
BigDecimal income = calIncome(prdPrice, platformFeeDto.getTotal(), serviceFeeRate);
//set
SellerOrderComputeResult result = new SellerOrderComputeResult();
result.setEarnestMoney(earnestMoney);
result.setBankTransferfee(bankTransferfee);
result.setPlatformFee(platformFeeDto);
result.setIncome(income);
//TODO 根据配置文件
result.setServiceFeeRate(ServiceFeeRate.getServiceFeeRate());
result.setServiceFeeRate(serviceFeeRate);
return result;
}
... ... @@ -56,8 +58,23 @@ public class SellerOrderComputeHandler {
return halfUp(prdPrice.multiply(new BigDecimal(0.0065)).add(new BigDecimal(1)));
}
private BigDecimal calIncome(BigDecimal prdPrice,BigDecimal platformFee,BigDecimal bankTransferfee){
return halfUp(prdPrice.subtract(platformFee).subtract(bankTransferfee));
/**
* (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,ServiceFeeRate serviceFeeRate){
return halfUp(prdPrice.multiply(
new BigDecimal(1D).subtract(serviceFeeRate.getEarnestMoneyRate())
.subtract(serviceFeeRate.getGoodsPaymentRate())
).subtract(platformFee));
}
/**
... ... @@ -66,17 +83,11 @@ public class SellerOrderComputeHandler {
* @return
*/
private PlatformFeeDto calPlatformFee(){
BigDecimal appraiseFee = new BigDecimal(10);;
BigDecimal packageFee = new BigDecimal(10);
BigDecimal serviceFee = new BigDecimal(0);
BigDecimal total = appraiseFee.add(packageFee).add(serviceFee);
PlatformFeeDto platformFee = new PlatformFeeDto();
BigDecimal appraiseFee = platformFee.getAppraiseFee();
BigDecimal packageFee = platformFee.getPackageFee();
BigDecimal total = appraiseFee.add(packageFee);
platformFee.setTotal(total);
platformFee.setAppraiseFee(appraiseFee);
platformFee.setPackageFee(packageFee);
platformFee.setServiceFee(serviceFee);
return platformFee;
}
... ... @@ -85,20 +96,25 @@ public class SellerOrderComputeHandler {
* @param prdPrice
* @return
*/
private BigDecimal calEarnestMoney(BigDecimal prdPrice){
BigDecimal real = halfUp(prdPrice.multiply(new BigDecimal(0.05)));
final BigDecimal min = EARNESTMONEYRANGE[0];
final BigDecimal max = EARNESTMONEYRANGE[1];
private EarnestMoney calEarnestMoney(BigDecimal prdPrice){
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){
return min;
real = min;
}
if (real.subtract(max).doubleValue() > 0D){
return max;
real = max;
}
return real;
earnestMoney.setMin(min);
earnestMoney.setMax(max);
earnestMoney.setEarnestMoney(real);
return earnestMoney;
}
private BigDecimal halfUp(BigDecimal fee){
return fee.setScale(2, BigDecimal.ROUND_HALF_UP);
return BigDecimalHelper.halfUp(fee);
}
}
... ...
... ... @@ -90,6 +90,7 @@ public class AppraiseService {
tso.setOrderCode(sellerOrderCode);
tso.setStatus(targetSoStatus.getCode());
tso.setUpdateTime(DateUtil.getCurrentTimeSecond());
tso.setExceptStatus(expectSOStatus.getCode());
int soCnt = sellerOrderMapper.updateByOrderCode(tso);
if (soCnt == 1){
//refund earnestMoney
... ...
... ... @@ -281,7 +281,7 @@ public class PaymentServiceImpl implements IPaymentService {
AbstractOrderPaymentService orderPaymentService = getOrderPaymentService(codeMeta, request.getOrderCode());
OrderInfo orderInfo = orderPaymentService.getOrderInfo(request.getOrderCode());
if (!orderPaymentService.isOrderPaid(orderInfo)){
if (!orderPaymentService.canRefund(orderInfo)){
logger.warn("refund has not paid status, orderCode is {}", request.getOrderCode());
throw new ServiceException(ServiceError.ORDER_HAS_NOT_PAID);
}
... ...
... ... @@ -11,10 +11,7 @@ import com.yohoufo.dal.order.model.BuyerOrder;
import com.yohoufo.dal.order.model.BuyerOrderGoods;
import com.yohoufo.dal.order.model.SellerOrder;
import com.yohoufo.dal.order.model.SellerOrderGoods;
import com.yohoufo.order.common.ActionStatusHold;
import com.yohoufo.order.common.OrderCodeType;
import com.yohoufo.order.common.OrderStatus;
import com.yohoufo.order.common.SellerOrderStatus;
import com.yohoufo.order.common.*;
import com.yohoufo.order.event.ErpCancelSellerOrderEvent;
import com.yohoufo.order.event.OrderCancelEvent;
import com.yohoufo.order.model.request.PaymentRequest;
... ... @@ -27,16 +24,15 @@ import com.yohoufo.order.service.impl.visitor.UserCancelCase;
import com.yohoufo.order.service.proxy.ProductProxyService;
import com.yohoufo.order.service.support.codegenerator.OrderCodeGenerator;
import com.yohoufo.order.service.support.codegenerator.bean.CodeMeta;
import lombok.experimental.Builder;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import java.util.Arrays;
import java.util.List;
import java.util.Objects;
import java.util.Optional;
import java.util.stream.Collectors;
/**
* Created by chenchao on 2018/9/17.
... ... @@ -118,7 +114,7 @@ public class SellerOrderCancelService {
if (Objects.isNull(status)){
return result;
}
List<Integer> sellerCanCancelStatus = ActionStatusHold.getSellerCanCancelStatus();
List<Integer> sellerCanCancelStatus = ActionStatusHold.getSellerCanRefundStatus();
if (!sellerCanCancelStatus.contains(status)){
logger.warn("seller cancel can not execute in this status, uid {} orderCode {}, status {}", uid, orderCode, status);
throw new ServiceException(ServiceError.ORDER_REQUEST_PARM_IS_EMPTY);
... ... @@ -130,7 +126,10 @@ public class SellerOrderCancelService {
//case 1: 未支付时
if (SellerOrderStatus.WAITING_PAY.getCode() == status){
targetSOStatus = SellerOrderStatus.SELf_CANCEL_PAY;
result = cancelBeforePayAction(uid, orderCode, sellerOrder.getSkup(), targetSOStatus);
SellerOrderStatusNode statusNode = SellerOrderStatusNode.builder()
.exceptStatus(SellerOrderStatus.WAITING_PAY).targetStatus(targetSOStatus).build();
result = cancelBeforePayAction(uid, orderCode, sellerOrder.getSkup(), statusNode);
}
//case 2: 支付完成,没有买家下单
... ... @@ -160,30 +159,26 @@ public class SellerOrderCancelService {
//case 1: 未支付时
if (SellerOrderStatus.WAITING_PAY.getCode() == status){
targetSOStatus = SellerOrderStatus.TIMEOUT_CANCEL;
result = cancelBeforePayAction(uid, orderCode, sellerOrder.getSkup(), targetSOStatus);
SellerOrderStatusNode statusNode = SellerOrderStatusNode.builder()
.exceptStatus(SellerOrderStatus.WAITING_PAY)
.targetStatus(targetSOStatus).build();
result = cancelBeforePayAction(uid, orderCode, sellerOrder.getSkup(), statusNode);
}
return result;
}
private int cancelBeforePayAction(int uid, long orderCode,Integer skup, SellerOrderStatus targetSOStatus){
logger.info("in seller cancel before Buy Action, uid {}, orderCode {}, targetSOStatus {}",
uid, orderCode, targetSOStatus);
SellerOrder target = new SellerOrder();
target.setOrderCode(orderCode);
target.setUid(uid);
target.setStatus(targetSOStatus.getCode());
target.setSkup(skup);
return cancelBeforePayAction(target, targetSOStatus);
@Builder
static class SellerOrderStatusNode{
SellerOrderStatus targetStatus;
SellerOrderStatus exceptStatus;
}
/**
*
* @param target
* @param targetSOStatus
* @return
*/
private int cancelBeforePayAction(SellerOrder target, SellerOrderStatus targetSOStatus){
private int cancelBeforePayAction(int uid, long orderCode, Integer skup, SellerOrderStatusNode statusNode){
SellerOrderStatus targetSOStatus = statusNode.targetStatus;
SellerOrderStatus exceptStatus = statusNode.exceptStatus;
logger.info("in seller cancel before Buy Action, uid {}, orderCode {}, targetSOStatus {}, exceptStatus {}",
uid, orderCode, targetSOStatus, exceptStatus);
/**case 1: 未支付时
* actions as blow:
* 1. sellerOrder
... ... @@ -191,9 +186,15 @@ public class SellerOrderCancelService {
* 3. 同步product skup状态
*/
int result = 0;
//update seller order
if (Objects.nonNull(targetSOStatus)){
SellerOrder target = new SellerOrder();
target.setOrderCode(orderCode);
target.setUid(uid);
target.setStatus(targetSOStatus.getCode());
target.setSkup(skup);
target.setExceptStatus(exceptStatus.getCode());
target.setStatus(targetSOStatus.getCode());
target.setUpdateTime(DateUtil.getCurrentTimeSecond());
result += sellerOrderMapper.updateByOrderCode(target);
}
... ... @@ -202,17 +203,19 @@ public class SellerOrderCancelService {
//sync skup
if (result>0) {
SellerOrderGoods sogCondition = new SellerOrderGoods();
sogCondition.setId(target.getSkup());
sogCondition.setId(skup);
sogCondition.setStatus(targetSOStatus.getSkupStatus().getCode());
sellerOrderGoodsMapper.updateByPrimaryKeySelective(sogCondition);
//sync skup
SellerOrderGoods tsog = new SellerOrderGoods();
tsog.setId(target.getSkup());
tsog.setId(skup);
productProxyService.syncSkup(tsog, targetSOStatus.getSkupStatus());
}
return result;
}
private int cancelAfterPayButNotBuyAction(SellerOrder sellerOrder){
/**case 2: 支付完成,没有买家下单
* actions as blow:
... ... @@ -228,8 +231,11 @@ public class SellerOrderCancelService {
SellerOrderStatus targetSOStatus;
targetSOStatus = SellerOrderStatus.PLAY_SELF;
SellerOrderStatus expectStatus = SellerOrderStatus.HAS_PAYED;
int skup = sellerOrder.getSkup();
result = cancelBeforePayAction(sellerUid, orderCode, skup, targetSOStatus);
SellerOrderStatusNode statusNode = SellerOrderStatusNode.builder().targetStatus(targetSOStatus)
.exceptStatus(expectStatus).build();
result = cancelBeforePayAction(sellerUid, orderCode, skup, statusNode);
//refund earnestMoney
if (result>0){
double earnestMoney = sellerOrder.getEarnestMoney().doubleValue();
... ... @@ -280,6 +286,7 @@ public class SellerOrderCancelService {
target.setUid(sellerUid);
target.setStatus(targetSOStatus.getCode());
target.setUpdateTime(DateUtil.getCurrentTimeSecond());
target.setExceptStatus(SellerOrderStatus.HAS_PAYED.getCode());
result += sellerOrderMapper.updateByOrderCode(target);
//TODO 分赃(分账) 有待考虑使用2比对
... ... @@ -354,6 +361,7 @@ public class SellerOrderCancelService {
/**
* 目前来看 只有支付过保证金的skup才有下架处理
* TODO 如何控制好并发,必须控制不能重复转账 退款
* 使用乐观锁,带着查询到的状态且符合条件时再去更新
* @param offShelveCancelCase
... ... @@ -362,15 +370,32 @@ public class SellerOrderCancelService {
logger.info("in cancel offShelveCancelCase {}", offShelveCancelCase);
ErpCancelSellerOrderEvent event = (ErpCancelSellerOrderEvent)offShelveCancelCase.getEvent();
final int skup = event.getSkup();
if (skup <= 0){
logger.warn("in offShelveCancelCase ,skup is illegal, skup {}", skup);
return;
}
SellerOrderGoods psog = sellerOrderGoodsMapper.selectByPrimaryKey(skup);
Integer skupStatus;
if (psog == null || (skupStatus = psog.getStatus() )== null){
logger.warn("in offShelveCancelCase, SellerOrderGoods or it's status illegal, skup {}", skup);
return;
}
SkupStatus expectSkupStatus = SkupStatus.CAN_SELL;
boolean isPayEarnestMoney = expectSkupStatus.getCode() == skupStatus;
if (!isPayEarnestMoney){
logger.warn("in offShelveCancelCase, SellerOrderGoods status illegal, skup {}, status {}", skup, skupStatus);
return;
}
final SellerOrderStatus targetSellerOrderStatus = SellerOrderStatus.YOHO_CANCEL_SELL;
//TODO check skup is buy away
SellerOrderGoods targetGoods = new SellerOrderGoods();
targetGoods.setId(skup);
targetGoods.setStatus(targetSellerOrderStatus.getSkupStatus().getCode());
targetGoods.setExceptStatus(skupStatus);
//利用数据库做并发控制
int result = sellerOrderGoodsMapper.updateByPrimaryKeySelective(targetGoods);
int result = sellerOrderGoodsMapper.updateStatusBySkpu(targetGoods);
if (result == 0) {
return;
}
... ... @@ -380,10 +405,13 @@ public class SellerOrderCancelService {
Long orderCode = sellerOrder.getOrderCode();
SellerOrder tso = new SellerOrder();
tso.setOrderCode(sellerOrder.getOrderCode());
tso.setExceptStatus(sellerOrder.getStatus());
tso.setStatus(targetSellerOrderStatus.getCode());
tso.setUid(sellerUid);
tso.setUpdateTime(DateUtil.getCurrentTimeSecond());
result = sellerOrderMapper.updateByOrderCode(tso);
//refund earnestMoney
if (result > 0) {
//refund earnestMoney only has payed
if (isPayEarnestMoney && result > 0) {
double earnestMoney = sellerOrder.getEarnestMoney().doubleValue();
PaymentRequest refundReq = PaymentRequest.builder().uid(sellerOrder.getUid())
.orderCode(sellerOrder.getOrderCode())
... ...
... ... @@ -33,7 +33,7 @@ public class SellerOrderCreateService {
condition.setIsDel(DelStatus.NOT_DEL.getCode());
condition.setCreateTime(currentTiem);
condition.setStatus(SellerOrderStatus.WAITING_PAY.getCode());
condition.setEarnestMoney(context.getSellerOrderComputeResult().getEarnestMoney());
condition.setEarnestMoney(context.getSellerOrderComputeResult().getEarnestMoney().getEarnestMoney());
condition.setIncome(context.getSellerOrderComputeResult().getIncome());
return sellerOrderMapper.insertSelective(condition);
}
... ...
package com.yohoufo.order.service.proxy;
import com.yohobuy.ufo.model.enums.InboxBusinessTypeEnum;
import com.yohoufo.inboxclient.model.InBoxResponse;
import com.yohoufo.inboxclient.model.InboxReqVO;
import com.yohoufo.inboxclient.sdk.InBoxSDK;
import org.apache.commons.lang3.StringUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
/**
* Created by chenchao on 2018/10/8.
*/
@Service
public class InBoxFacade {
private final Logger logger = LoggerFactory.getLogger(getClass());
@Autowired
private InBoxSDK inBoxSDK;
/**
* 买家订单未付款
* @param buyerUid
*/
public void buyerOrderNotPayed(int buyerUid, long orderCode){
InboxReqVO req = new InboxReqVO();
req.setUid(buyerUid);
String params = buildParams(orderCode);
req.setParams(params);
InboxBusinessTypeEnum ibt = InboxBusinessTypeEnum.PURCHASE_UNPAID;
req.setType(ibt.getType());
req.setBusinessType(ibt.getBusinessType());
//
InBoxResponse resp = inBoxSDK.addInbox(req);
logger.info("record buyerOrderNotPayed inbox msg, buyerUid {}, orderCode {}, resp {}",
buyerUid, orderCode, resp);
}
public static String buildParams(Object... objects){
String params = StringUtils.join(objects, ",");
return params;
}
}
... ...
... ... @@ -2,6 +2,8 @@ package com.yohoufo.order.service;
import com.alibaba.fastjson.JSONObject;
import com.yohobuy.ufo.model.order.bo.SoldPrdComputeBo;
import com.yohoufo.order.model.dto.SellerOrderComputeResult;
import com.yohoufo.order.service.handler.SellerOrderComputeHandler;
import com.yohoufo.order.service.impl.SellerOrderService;
import org.junit.Test;
... ... @@ -14,9 +16,9 @@ public class SellerOrderServiceTest {
@Test
public void testBuildSoldPrdComputeBo(){
SellerOrderService sos = new SellerOrderService();
BigDecimal prdPrice = new BigDecimal(123.44);
SoldPrdComputeBo bo = sos.buildSoldPrdComputeBo(prdPrice);
SellerOrderComputeHandler sos = new SellerOrderComputeHandler();
BigDecimal prdPrice = new BigDecimal(123.44D);
SellerOrderComputeResult bo = sos.compute(prdPrice);
System.out.println("in testBuildSoldPrdComputeBo :"+ JSONObject.toJSONString(bo));
}
}
... ...
... ... @@ -90,6 +90,12 @@
<artifactId>commons-pool2</artifactId>
<version>2.2</version>
</dependency>
<dependency>
<groupId>com.yohoufo.fore</groupId>
<artifactId>yohoufo-fore-inboxclient</artifactId>
</dependency>
</dependencies>
... ...
... ... @@ -19,7 +19,6 @@
<context:component-scan base-package="com.yohoufo" />
<!-- 启动SpringMVC的注解功能,完成请求和注解POJO的映射 -->
<mvc:annotation-driven>
<mvc:message-converters register-defaults="false">
... ...