Authored by chenchao

add some point

... ... @@ -7,6 +7,7 @@ import com.yohobuy.ufo.model.order.vo.AddressInfo;
import com.yohoufo.order.model.request.OrderRequest;
import com.yohoufo.order.model.request.SaveQualityCheckInfoRequest;
import com.yohoufo.order.model.response.OrderSummaryResp;
import com.yohoufo.order.service.impl.BuyerOrderAssistant;
public interface IBuyerOrderService {
... ... @@ -67,6 +68,11 @@ public interface IBuyerOrderService {
OrderCntResp getOrderCnt(OrderRequest req, OrderListType listType);
/**
* 现货订单使用寄存商品发货
* @param preparedData
* @param dscNode
*/
void processOrderDeliverByDepositGoods(BuyerOrderAssistant.PreparedData preparedData,
BuyerOrderAssistant.DepositSkuCheckNode dscNode);
}
... ...
... ... @@ -11,8 +11,10 @@ import com.yohoufo.dal.order.model.BuyerOrderGoods;
import com.yohoufo.dal.order.model.SellerOrderGoods;
import com.yohoufo.dal.order.model.StorageDeposit;
import com.yohoufo.order.utils.BuyerOrderUtils;
import com.yohoufo.order.utils.LoggerUtils;
import lombok.Data;
import org.apache.commons.lang3.StringUtils;
import org.slf4j.Logger;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
... ... @@ -24,6 +26,7 @@ import java.util.Objects;
*/
@Component
public class BuyerOrderAssistant {
private final Logger logger = LoggerUtils.getBuyerOrderLogger();
@Autowired
private BuyerOrderMapper buyerOrderMapper;
... ... @@ -72,11 +75,22 @@ public class BuyerOrderAssistant {
boolean existDepositGoods = false;
boolean isInstockOrder = buyerOrder.getAttributes().equals(OrderAttributes.COMMON_IN_STOCK.getCode());
boolean isInstockDepositOrder = isInstockDepositOrder(buyerOrder, sellerOrderGoods);
if (StringUtils.isNotBlank(depositCode) && isInstockOrder && isInstockDepositOrder){
boolean depositCodeIsNotBlank = StringUtils.isNotBlank(depositCode);
if (depositCodeIsNotBlank && isInstockOrder && isInstockDepositOrder){
depositCode = depositCode.trim();
StorageDeposit psd = storageDepositMapper.queryByDepositCode(sellerUid, depositCode);
existDepositGoods = Objects.nonNull(psd);
dsNode.setPsd(psd);
}
if (!depositCodeIsNotBlank){
logger.warn("checkExistDepositSku depositCode Is Blank, orderCode {} depositCode {}",
buyerOrder.getOrderCode(), depositCode);
}
if (depositCodeIsNotBlank && !existDepositGoods){
logger.warn("checkExistDepositSku depositCode Is Not Blank but not exist DepositGoods, orderCode {} depositCode {}",
buyerOrder.getOrderCode(), depositCode);
}
dsNode.setExistDepositGoods(existDepositGoods);
dsNode.setDepositCode(depositCode);
return dsNode;
... ...
... ... @@ -29,10 +29,7 @@ import com.yohoufo.order.model.PayQueryBo;
import com.yohoufo.order.model.request.OrderRequest;
import com.yohoufo.order.model.request.SaveQualityCheckInfoRequest;
import com.yohoufo.order.model.response.OrderSummaryResp;
import com.yohoufo.order.service.IBuyerOrderMetaService;
import com.yohoufo.order.service.IBuyerOrderService;
import com.yohoufo.order.service.IExpressInfoService;
import com.yohoufo.order.service.IPaymentService;
import com.yohoufo.order.service.*;
import com.yohoufo.order.service.cache.CacheCleaner;
import com.yohoufo.order.service.cache.CacheKeyBuilder;
import com.yohoufo.order.service.cache.OrderCacheService;
... ... @@ -40,6 +37,7 @@ import com.yohoufo.order.service.listener.BuyerOrderChangeEvent;
import com.yohoufo.order.service.listener.OrderChangeListenerContainer;
import com.yohoufo.order.service.pay.AbstractPayService;
import com.yohoufo.order.service.proxy.*;
import com.yohoufo.order.service.seller.SkupService;
import com.yohoufo.order.service.seller.deposit.SellerDepositOrderService;
import com.yohoufo.order.utils.BuyerOrderUtils;
import com.yohoufo.order.utils.LoggerUtils;
... ... @@ -119,6 +117,13 @@ public class BuyerOrderServiceImpl implements IBuyerOrderService {
@Autowired
private SellerDepositOrderService sellerDepositOrderService;
@Autowired
private SkupService skupService;
@Autowired
private DepositService depositService;
/**
* 提交订单
* @param orderRequest
... ... @@ -1013,7 +1018,39 @@ public class BuyerOrderServiceImpl implements IBuyerOrderService {
return resp;
}
@Override
public void processOrderDeliverByDepositGoods(BuyerOrderAssistant.PreparedData preparedData,
BuyerOrderAssistant.DepositSkuCheckNode dscNode){
if (!dscNode.isExistDepositGoods()){
return;
}
BuyerOrder buyerOrder = preparedData.getBuyerOrder();
Integer buyerUid = buyerOrder.getUid();
Long orderCode = buyerOrder.getOrderCode();
String depositCode = dscNode.getDepositCode();
//bind deposit code 2 buyer order
buyerOrderMetaService.saveDepositCode(depositCode, buyerUid, orderCode);
//check
//需要满足以下条件
//订单状态为已发货
//互斥:申请一个分布锁,锁定订单,防止与发货后取消并发
StorageDeposit psd = dscNode.getPsd();
Integer ownerUid = psd.getOwnerUid();
//skup 下架
Integer skup;
Integer productId;
if (Objects.nonNull(skup = psd.getNewSkup())){
// 减库存
productProxyService.subtractStorage(productId=psd.getProductId(), skup);
//
skupService.saleOut(skup);
}
//寄存商品 出库准备
depositService.updateDepositWaitToPick(ownerUid, depositCode);
}
}
... ...
... ... @@ -37,10 +37,7 @@ import com.yohoufo.order.event.BuyerOrderSellerDeliveryCheckEvent;
import com.yohoufo.order.event.ErpBuyerOrderEvent;
import com.yohoufo.order.model.OperateTransferExpressInfo;
import com.yohoufo.order.model.response.AppraiseAddressResp;
import com.yohoufo.order.service.IBuyerOrderMetaService;
import com.yohoufo.order.service.IExpressCompanyService;
import com.yohoufo.order.service.IExpressInfoService;
import com.yohoufo.order.service.IGoodsService;
import com.yohoufo.order.service.*;
import com.yohoufo.order.service.cache.CacheCleaner;
import com.yohoufo.order.service.cache.CacheKeyBuilder;
import com.yohoufo.order.service.proxy.*;
... ... @@ -153,6 +150,9 @@ public class ExpressInfoServiceImpl implements IExpressInfoService {
@Autowired
private BuyerOrderAssistant buyerOrderAssistant;
@Autowired
private IBuyerOrderService buyerOrderService;
private static String EXPRESS_MQ_SEND = "third.logistics.logistics_data";
//物流文案设置
... ... @@ -171,8 +171,6 @@ public class ExpressInfoServiceImpl implements IExpressInfoService {
@Autowired
private SkupService skupService;
@Autowired
private ProductProxyService productProxyService;
/**
... ... @@ -285,7 +283,6 @@ public class ExpressInfoServiceImpl implements IExpressInfoService {
int updateOrderCnt = 0;
String sellerMobile;
String depositCode = req.getDepositCode();
Integer buyerUid;
switch (orderCodeType){
case BUYER_TYPE:
BuyerOrderAssistant.PreparedData preparedData = buyerOrderAssistant.prepare(orderCode);
... ... @@ -294,7 +291,6 @@ public class ExpressInfoServiceImpl implements IExpressInfoService {
LOGGER.warn("deliverToDepot getOrderInfo order not exist, orderCode is {}", orderCode);
throw new ServiceException(ServiceError.ORDER_NULL);
}
buyerUid = buyerOrder.getUid();
sellerMobile = Optional.of(preparedData.getBuyerOrderGoods())
.map(e -> sellerAddressService.getNoHiddenAddressInfo(sellerUid, e.getSkup()))
.map(AddressInfo::getMobile)
... ... @@ -302,11 +298,9 @@ public class ExpressInfoServiceImpl implements IExpressInfoService {
//目前校验现货订单 和 现货寄存订单
BuyerOrderAssistant.DepositSkuCheckNode dscNode = buyerOrderAssistant.checkExistDepositSku(buyerOrder, preparedData.getSellerOrderGoods(), depositCode);
boolean existDepositGoods = dscNode.isExistDepositGoods();
if(existDepositGoods){
//set depot num
depotNum = DepotType.NJ.getCode();
//生成内部使用的物流单号
wayBillCode = new StringBuilder()
.append(orderCode)
... ... @@ -318,10 +312,22 @@ public class ExpressInfoServiceImpl implements IExpressInfoService {
if (isHKLargeSettlementSuper(sellerUid)) {
depotNum = DepotType.HK.getCode();
}
//博弈 以下步骤若非原子操作,谁先谁后
//o1.更新订单状态->已发货 o2.更新寄存商品->待捡货
//竞争操作: a:买家取消订单 a1:更新寄存商品->重回货架 b:寄存商品被购买
//o1 pk a的结果, (1.1) a失败 o1成功; (1.2)a成功,o1失败
//o2 pk b的结果, (2.1) o2 success, b fail, (2.2) o2 fail , b success
//case 1: 先o1后o2: 1.1 正常流程走下去 1.2 回滚
//case 2: 先o2后o1: 2.1(需要考虑a1导致的并发,由服务提供方保证) & 2.2(需要回滚已操作的业务)
//采用分布式锁解决寄存商品的并发问题
//思路 用寄存码加锁
//采用case 2 当使用寄存商品发货时 o2操作前加锁;a操作发现是寄存商品发货的订单 检查锁;b操作 下单 计算 支付回调均要检查
//合理的方案将 加锁 释放锁抽成独立的工具类,使用者引用
//o1 & o2 捆绑在一个数据库的事务里 用于保证业务本地的原子操作
updateOrderCnt = processBuyerOrder(preparedData, expressCompanyId, expressType, wayBillCode, depotNum);
if (updateOrderCnt>0){
try {
processOrderDeliverByDepositGoods(preparedData, dscNode);
buyerOrderService.processOrderDeliverByDepositGoods(preparedData, dscNode);
}catch (Exception ex){
LOGGER.warn("deliverToDepot processOrderDeliverByDepositGoods fail ,req {} error {}",
req, Throwables.getStackTraceAsString(ex));
... ... @@ -372,29 +378,7 @@ public class ExpressInfoServiceImpl implements IExpressInfoService {
LOGGER.info("deliverToDepot update buyer order status, orderCode {} result {} ", orderCode, updateOrderCnt);
}
private void processOrderDeliverByDepositGoods(BuyerOrderAssistant.PreparedData preparedData,
BuyerOrderAssistant.DepositSkuCheckNode dscNode){
if (!dscNode.isExistDepositGoods()){
return;
}
BuyerOrder buyerOrder = preparedData.getBuyerOrder();
Integer buyerUid = buyerOrder.getUid();
Long orderCode = buyerOrder.getOrderCode();
String depositCode = dscNode.getDepositCode();
//bind deposit code 2 buyer order
buyerOrderMetaService.saveDepositCode(depositCode, buyerUid, orderCode);
//TODO skup 下架
StorageDeposit psd = dscNode.getPsd();
Integer skup;
Integer productId;
if (Objects.nonNull(skup = psd.getNewSkup())){
// 减库存
productProxyService.subtractStorage(productId=psd.getProductId(), skup);
//
skupService.saleOut(skup);
}
//TODO 寄存商品 出库准备
}
@Override
... ... @@ -469,7 +453,13 @@ public class ExpressInfoServiceImpl implements IExpressInfoService {
* @param wayBillCode
* @param expressType
*/
private void saveExpressRecordAndOperateTransferExpressInfo(Integer uid, Integer expressCompanyId, Long orderCode, String wayBillCode, Integer expressType, EnumExpressDataType expressDataType, EnumExpressDataOperateTransferCode operateTransferCode, Integer depotNum) {
private void saveExpressRecordAndOperateTransferExpressInfo(Integer uid, Integer expressCompanyId,
Long orderCode,
String wayBillCode,
Integer expressType,
EnumExpressDataType expressDataType,
EnumExpressDataOperateTransferCode operateTransferCode,
Integer depotNum) {
ExpressRecord record = new ExpressRecord();
record.setUid(uid);/// 存卖家的uid
record.setOrderCode(orderCode);
... ...
... ... @@ -89,9 +89,11 @@ public class ProductProxyService extends AbsProxyService{
private static final String PRODUCT_IN_POOL = "ufo.product.belongPool";
public boolean subtractStorage(Integer productId, Integer skup){
ApiResponse resp = ufoServiceCaller.call(SUBTRACT_STORAGE, productId, skup);
final String api = SUBTRACT_STORAGE;
logger.info("{}.subtractStorage call {} productId {} skup {}", getClass().getSimpleName(), api, productId, skup);
ApiResponse resp = ufoServiceCaller.call(api, productId, skup);
logger.info("{}.subtractStorage call {} productId {} skup {} resp {}",
getClass().getSimpleName(), api, productId, skup, resp);
return (resp == null || resp.getData()==null) ? false : (boolean)resp.getData();
}
... ...