OpenApiOrderValuationServiceImpl.java 42 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753
  1. package com.ydd.app.service.impl;
  2. import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
  3. import com.ydd.api.DeliveryService;
  4. import com.ydd.app.OrderEntityUtils;
  5. import com.ydd.app.QueryAmountEntityUtils;
  6. import com.ydd.app.dto.*;
  7. import com.ydd.app.response.OrderValuationResponse;
  8. import com.ydd.app.service.OpenApiOrderValuationService;
  9. import com.ydd.app.vo.OrderValuationVo;
  10. import com.ydd.common.constant.BillingConstant;
  11. import com.ydd.common.constant.RedisKeyConstant;
  12. import com.ydd.common.core.domain.ResponseResult;
  13. import com.ydd.common.core.redis.RedisCache;
  14. import com.ydd.common.enums.DeliveryTypeEnums;
  15. import com.ydd.common.enums.ResponseResultCodeEnum;
  16. import com.ydd.common.utils.DateUtils;
  17. import com.ydd.common.utils.SnCodeUtils;
  18. import com.ydd.common.utils.StringUtils;
  19. import com.ydd.ecloud.core.enums.DeletedEnum;
  20. import com.ydd.ecloud.core.utils.BigDecimalUtils;
  21. import com.ydd.module.constants.AppConstant;
  22. import com.ydd.module.domain.*;
  23. import com.ydd.module.dto.*;
  24. import com.ydd.module.enums.*;
  25. import com.ydd.module.service.*;
  26. import com.ydd.module.utils.CommonUtils;
  27. import com.ydd.system.domain.SysConfig;
  28. import com.ydd.system.service.ISysConfigService;
  29. import com.ydd.third.common.config.DeliveryConfig;
  30. import com.ydd.third.common.vo.ResObject;
  31. import com.ydd.third.common.vo.shop.AmountResultVo;
  32. import com.ydd.third.common.vo.shop.QueryAmount;
  33. import com.ydd.third.common.vo.vo.order.OrderResultVo;
  34. import com.ydd.third.common.vo.vo.order.OrderVo;
  35. import lombok.RequiredArgsConstructor;
  36. import lombok.extern.slf4j.Slf4j;
  37. import org.apache.commons.collections4.CollectionUtils;
  38. import org.apache.commons.compress.utils.Lists;
  39. import org.springframework.beans.BeanUtils;
  40. import org.springframework.beans.factory.annotation.Autowired;
  41. import org.springframework.stereotype.Service;
  42. import java.math.BigDecimal;
  43. import java.util.*;
  44. import java.util.concurrent.TimeUnit;
  45. import java.util.stream.Collectors;
  46. /**
  47. * 开放接口-订单计价ServiceImpl
  48. * @author 叶君翔
  49. * @date 2022/04/08 15:51
  50. */
  51. @Slf4j
  52. @Service
  53. @RequiredArgsConstructor(onConstructor_ = @Autowired)
  54. public class OpenApiOrderValuationServiceImpl implements OpenApiOrderValuationService {
  55. private final IShopService iShopService;
  56. private final IMerchantService iMerchantService;
  57. private final IMemberService iMemberService;
  58. private final IProductService iProductService;
  59. private final IPackageCityConfigService iPackageCityConfigService;
  60. private final IPackageDeliveryService iPackageDeliveryService;
  61. private final IPackageDiscountService iPackageDiscountService;
  62. private final IPackageDiscountDetailService iPackageDiscountDetailService;
  63. private final IPackageCommissionService iPackageCommissionService;
  64. private final IPackageCommissionDetailService iPackageCommissionDetailService;
  65. private final IDspDeliveryService iDspDeliveryService;
  66. private final IShopDeliveryDisableService iShopDeliveryDisableService;
  67. private final IShopDeliveryService iShopDeliveryService;
  68. private final IMemberConfigService iMemberConfigService;
  69. private final DeliveryConfig deliveryConfig;
  70. private final ISysConfigService iSysConfigService;
  71. private final DeliveryService client;
  72. private final IShopDeliveryBindService iShopDeliveryBindService;
  73. private final RedisCache redisCache;
  74. private final IDspDeliveryUuService iDspDeliveryUuService;
  75. @Override
  76. public ResponseResult valuation(OrderValuationReq valuationReq, Long loginId) {
  77. // 开放平台大商户对应的用户
  78. Member member = iMemberService.getById(loginId);
  79. OrderValuationDto valuationDto = new OrderValuationDto();
  80. // 参数校验
  81. ResponseResult result = this.validParam(valuationReq, valuationDto, member);
  82. if (result.getCode() != ResponseResultCodeEnum.SUCCESS.getCode()) {
  83. return result;
  84. }
  85. Product product = iProductService.getById(valuationReq.getCategoryId());
  86. if (product == null) {
  87. return ResponseResult.error(ResponseResultCodeEnum.CATEGORY_NOT_EXIST);
  88. }
  89. valuationDto.setProduct(product);
  90. valuationDto.setOrderSn(SnCodeUtils.createSn());
  91. valuationDto.setTakeType(0);
  92. // 获取最匹配的运力包(门店 > 城市 > 全国)
  93. Long deliveryPackageId = iPackageCityConfigService.getPackageId(valuationDto.getShopId(), member, null, PackageCityConfigPackageTypeEnum.DELIVERY.type);
  94. List<Integer> types = Lists.newArrayList();
  95. PackageDeliveryDto packageDeliveryDto = null;
  96. if (deliveryPackageId != null) {
  97. packageDeliveryDto = iPackageDeliveryService.getDeliveryDtoByPackageIdAndDeliveryType(deliveryPackageId);
  98. List<PackageDeliveryDetailDto> deliveryDetailDtoList = packageDeliveryDto.getPackageDeliveryDetailDtoList();
  99. if (CollectionUtils.isNotEmpty(deliveryDetailDtoList)) {
  100. types = deliveryDetailDtoList.stream().map(PackageDeliveryDetailDto::getDeliveryType).collect(Collectors.toList());
  101. }
  102. }
  103. // 获取门店屏蔽运力(开放平台门店)
  104. List<Integer> disableDeliveryTypes = iShopDeliveryDisableService.list(new QueryWrapper<ShopDeliveryDisable>()
  105. .eq("shop_id", valuationDto.getShopId()).eq("deleted", 0))
  106. .stream().map(ShopDeliveryDisable::getDeliveryType).collect(Collectors.toList());
  107. if (CollectionUtils.isNotEmpty(disableDeliveryTypes)) {
  108. types.removeAll(disableDeliveryTypes);
  109. }
  110. // 获取可用发单运力
  111. List<DeliveryInfo> deliveryInfos = this.getDeliveryInfos(valuationDto, types);
  112. if (CollectionUtils.isEmpty(deliveryInfos)) {
  113. log.warn("无可用发单运力!");
  114. return ResponseResult.error(ResponseResultCodeEnum.NO_DELIVERY);
  115. }
  116. List<Integer> deliveryTypes = deliveryInfos.stream().map(DspDelivery::getType).collect(Collectors.toList());
  117. // 获取最匹配的优惠包(门店 > 代理商 > 全国)
  118. Long discountPackageId = iPackageCityConfigService.getPackageId(valuationDto.getShopId(), member, null, PackageCityConfigPackageTypeEnum.DISCOUNT.type);
  119. Map<Integer, List<PackageDiscountDetailDto>> packageDiscountMap = new HashMap<>();
  120. if (discountPackageId != null) {
  121. List<PackageDiscountDetailDto> discountDetailDtoList = iPackageDiscountDetailService.getDiscountListByPackageIdAndDeliveryType(discountPackageId, deliveryTypes);
  122. packageDiscountMap = discountDetailDtoList.stream().collect(Collectors.groupingBy(PackageDiscountDetailDto::getDeliveryType));
  123. }
  124. // 获取最匹配的佣金包(门店 > 代理商 > 全国)
  125. Long commissionPackageId = iPackageCityConfigService.getPackageId(valuationDto.getShopId(), member, null, PackageCityConfigPackageTypeEnum.COMMISSION.type);
  126. Map<Integer, List<PackageCommissionDetailDto>> packageCommissionMap = new HashMap<>();
  127. if (commissionPackageId != null) {
  128. List<PackageCommissionDetailDto> commissionDetailDtoList = iPackageCommissionDetailService.getCommissionListByPackageIdAndDeliveryType(commissionPackageId, deliveryTypes);
  129. packageCommissionMap = commissionDetailDtoList.stream().collect(Collectors.groupingBy(PackageCommissionDetailDto::getDeliveryType));
  130. }
  131. OrderReq orderReq = this.convertToOrderReq(valuationDto);
  132. // 计价
  133. List<ValuationRes> list = this.getValuationResList(orderReq, valuationDto, deliveryInfos, packageDeliveryDto, packageDiscountMap, packageCommissionMap);
  134. // 默认价格优先
  135. list.sort(Comparator.comparing(ValuationRes::getDeliveryAmount));
  136. // 运力包发单类型为自定义, 则先按照sort排,再按价格排
  137. if (packageDeliveryDto != null && PackageDeliveryTypeEnum.CUSTOM.type.equals(packageDeliveryDto.getType())) {
  138. Collections.sort(list);
  139. }
  140. // 处理发单运力
  141. List<ValuationRes> billList = this.handleBillList(member.getId(), list);
  142. // 设置发单时长
  143. if (packageDeliveryDto != null) {
  144. billList = this.setBillingDuration(packageDeliveryDto, billList);
  145. }
  146. orderReq.setMemberId(member.getId());
  147. orderReq.setValuationRes(billList);
  148. // 计价结果缓存到redis, 10分钟有效, 到时需重新计价
  149. redisCache.setCacheObject(RedisKeyConstant.VALUATION_RESULT + valuationDto.getOutOrderSn(), orderReq, AppConstant.VALUATION_RESULT_EFFECTIVE_MINUTES, TimeUnit.MINUTES);
  150. // 数据转换
  151. List<OrderValuationVo> valuationVos = this.convertResult(billList);
  152. OrderValuationResponse response = OrderValuationResponse.builder().valuationList(valuationVos).outOrderSn(valuationReq.getOutOrderSn()).build();
  153. return ResponseResult.success(response);
  154. }
  155. private List<OrderValuationVo> convertResult(List<ValuationRes> billList) {
  156. List<OrderValuationVo> valuationVos = Lists.newArrayList();
  157. for (ValuationRes valuationRes : billList) {
  158. OrderValuationVo valuationVo = new OrderValuationVo();
  159. valuationVo.setDeliveryId(valuationRes.getDeliveryType());
  160. valuationVo.setDeliveryName(valuationRes.getName());
  161. valuationVo.setDistance(valuationRes.getDesc());
  162. if (valuationRes.getDeliveryAmount() != null) {
  163. valuationVo.setDeliveryAmount(valuationRes.getDeliveryAmount().setScale(2, BigDecimal.ROUND_HALF_UP));
  164. // 暂时第三方
  165. valuationVo.setDiscountAmount(BigDecimal.ZERO);
  166. valuationVo.setNeedPayAmount(valuationVo.getDeliveryAmount().subtract(valuationVo.getDiscountAmount()));
  167. }
  168. valuationVos.add(valuationVo);
  169. }
  170. return valuationVos;
  171. }
  172. private List<ValuationRes> handleBillList(Long memberId, List<ValuationRes> list) {
  173. // 查询下单设置推荐屏蔽运力
  174. List<ValuationRes> billList = Lists.newArrayList();
  175. MemberConfig config = iMemberConfigService.getOne(new QueryWrapper<MemberConfig>().eq("member_id", memberId));
  176. if (config != null) {
  177. if (StringUtils.isNotEmpty(config.getBillDeliveryIds())) {
  178. List<String> billDeliveryIds = Arrays.asList(config.getBillDeliveryIds().split(","));
  179. // 过滤出商家设置的推荐运力, 计价页面靠前显示
  180. billList = list.stream().filter(a -> billDeliveryIds.contains(a.getDeliveryId().toString())).collect(Collectors.toList());
  181. }
  182. if (StringUtils.isNotEmpty(config.getShieldDeliveryIds())) {
  183. List<String> shieldDeliveryIds = Arrays.asList(config.getShieldDeliveryIds().split(","));
  184. // 过滤掉商家设置的屏蔽运力
  185. list = list.stream().filter(a -> !shieldDeliveryIds.contains(a.getDeliveryId().toString())).collect(Collectors.toList());
  186. }
  187. }
  188. list.removeAll(billList);
  189. billList.addAll(list);
  190. // 闪送距离替换
  191. Optional<ValuationRes> optional = billList.stream().filter(item -> !item.getDeliveryType().equals(DeliveryTypeEnums.SHAN_SONG.getType())).findFirst();
  192. if (optional.isPresent()) {
  193. String desc = optional.get().getDesc();
  194. String distance = optional.get().getDistance();
  195. for (ValuationRes res1 : billList) {
  196. if (DeliveryTypeEnums.SHAN_SONG.getType().equals(res1.getDeliveryType())) {
  197. res1.setDesc(desc);
  198. res1.setDistance(distance);
  199. break;
  200. }
  201. }
  202. }
  203. return billList;
  204. }
  205. private List<ValuationRes> getValuationResList(OrderReq orderReq, OrderValuationDto valuationDto, List<DeliveryInfo> deliveryInfos, PackageDeliveryDto packageDeliveryDto, Map<Integer, List<PackageDiscountDetailDto>> packageDiscountMap, Map<Integer, List<PackageCommissionDetailDto>> packageCommissionMap) {
  206. List<ValuationRes> valuationResList = Lists.newArrayList();
  207. for (DeliveryInfo deliveryInfo : deliveryInfos) {
  208. // OrderReq orderReq = this.convertToOrderReq(valuationDto);
  209. // 计价
  210. ValuationRes valuationRes = this.doValuation(orderReq, deliveryInfo, valuationDto.getMerchantId(), valuationDto.getShopId());
  211. if (Objects.isNull(valuationRes)) {
  212. continue;
  213. }
  214. valuationRes.setPreferredDelivery(deliveryInfo.getPreferredDelivery());
  215. valuationRes.setOriginalMoney(valuationRes.getDeliveryAmount());
  216. // 设置排序
  217. if (packageDeliveryDto != null && PackageDeliveryTypeEnum.CUSTOM.type.equals(packageDeliveryDto.getType())) {
  218. this.setBillingSort(packageDeliveryDto, valuationRes);
  219. }
  220. // 设置优惠
  221. if (packageDiscountMap.size() > 0) {
  222. this.setDiscountInfo(packageDiscountMap.get(deliveryInfo.getType()), valuationRes);
  223. }
  224. // 设置佣金
  225. if (packageCommissionMap.size() > 0) {
  226. this.setCommissionInfo(packageCommissionMap.get(deliveryInfo.getType()), valuationRes);
  227. }
  228. valuationRes.setIsMerchant(deliveryInfo.getIsMerchant());
  229. if (valuationRes.getIsMine() == 0) {
  230. // 校验余额是否充足
  231. Member member = iMemberService.getOne(new QueryWrapper<Member>().eq("member_type", MemberTypeEnum.MERCHANT.type).eq("merchant_id", valuationDto.getMerchantId()));
  232. if (member.getAmount().compareTo(valuationRes.getDeliveryAmount()) >= 0) {
  233. valuationRes.setIsEnough(StatusEnum.SHOW.status);
  234. }
  235. }
  236. valuationResList.add(valuationRes);
  237. }
  238. return valuationResList;
  239. }
  240. private OrderReq convertToOrderReq(OrderValuationDto valuationDto) {
  241. OrderReq orderReq = new OrderReq();
  242. BeanUtils.copyProperties(valuationDto, orderReq);
  243. AddressReq sendAddress = new AddressReq();
  244. sendAddress.setContact(valuationDto.getSendName());
  245. sendAddress.setPhone(valuationDto.getSendPhone());
  246. sendAddress.setProvinceName(valuationDto.getSendProvinceName());
  247. sendAddress.setCityName(valuationDto.getSendCityName());
  248. if (StringUtils.isBlank(valuationDto.getSendDistrictName())) {
  249. valuationDto.setSendDistrictName("城区");
  250. }
  251. sendAddress.setDistrictName(valuationDto.getSendDistrictName());
  252. sendAddress.setAddress(valuationDto.getSendAddress());
  253. sendAddress.setStreet(valuationDto.getSendHouseNumber());
  254. sendAddress.setLng(valuationDto.getSendLng());
  255. sendAddress.setLat(valuationDto.getSendLat());
  256. sendAddress.setCityCode(valuationDto.getSendCityCode());
  257. orderReq.setSendAddress(sendAddress);
  258. AddressReq receiptAddress = new AddressReq();
  259. receiptAddress.setContact(valuationDto.getReceiverName());
  260. receiptAddress.setPhone(valuationDto.getReceiverPhone());
  261. receiptAddress.setProvinceName(valuationDto.getReceiverProvinceName());
  262. receiptAddress.setCityName(valuationDto.getReceiverCityName());
  263. if (StringUtils.isBlank(valuationDto.getReceiverDistrictName())) {
  264. valuationDto.setReceiverDistrictName("城区");
  265. }
  266. receiptAddress.setDistrictName(valuationDto.getReceiverDistrictName());
  267. receiptAddress.setAddress(valuationDto.getReceiverAddress());
  268. receiptAddress.setStreet(valuationDto.getReceiverHouseNumber());
  269. receiptAddress.setLng(valuationDto.getReceiverLng());
  270. receiptAddress.setLat(valuationDto.getReceiverLat());
  271. receiptAddress.setCityCode(valuationDto.getReceiverCityCode());
  272. orderReq.setReceiptAddress(receiptAddress);
  273. orderReq.setDaySeq(String.valueOf(valuationDto.getDaySeq()));
  274. orderReq.setOrderNo(valuationDto.getOrderSn());
  275. orderReq.setProduct(valuationDto.getProduct());
  276. orderReq.setProductId(valuationDto.getCategoryId());
  277. if (StringUtils.isNotBlank(valuationDto.getShopCode())) {
  278. orderReq.setShopId(valuationDto.getShopId());
  279. orderReq.setShopName(valuationDto.getShopName());
  280. }
  281. orderReq.setIsMine(0);
  282. orderReq.setTransport(0);
  283. // 对接开放接口的均为余额支付
  284. orderReq.setPaymentType(PaymentTypeEnum.BALANCE.type);
  285. orderReq.setTakeRemark(valuationDto.getRemark());
  286. // 对接开放接口均为自选运力
  287. orderReq.setDeliveryType(2);
  288. // 对接开放接口均为立即取件,取件时间为当前
  289. orderReq.setTakeType(0);
  290. orderReq.setTakeTime(DateUtils.format(new Date(), DateUtils.YYYY_MM_DD_HH_MM_SS));
  291. return orderReq;
  292. }
  293. private ValuationRes doValuation(OrderReq orderReq, DeliveryInfo delivery, Long merchantId, Long shopId) {
  294. orderReq.setOrderSn(SnCodeUtils.createSn());
  295. orderReq.setAmount(orderReq.getProductAmount());
  296. if (DeliveryTypeEnums.UUPT.getType().equals(delivery.getType())&&delivery.getIsMine() != 1) {
  297. List<DspDeliveryUu> uuList = iDspDeliveryUuService.list(new QueryWrapper<DspDeliveryUu>().eq("city_name", orderReq.getSendAddress().getCityName()));
  298. if (CollectionUtils.isNotEmpty(uuList)) {
  299. for(DspDeliveryUu uu:uuList){
  300. if(uu.getProductId().equals(orderReq.getProductId())){
  301. delivery.setShopId(uu.getOpenId());
  302. break;
  303. }
  304. }
  305. }
  306. }
  307. OrderVo orderVo = OrderEntityUtils.createOrderVo(orderReq, delivery, deliveryConfig.isTest());
  308. // 获取用户配置
  309. MemberConfig memberConfig = iMemberConfigService.getShopMemberConfig(shopId, null);
  310. if (memberConfig != null && memberConfig.getSyncGoodsDetailToDelivery().equals(DeletedEnum.YES.getValue())) {
  311. // 是否同步订单商品给骑手
  312. orderVo.setMtGoods(Lists.newArrayList());
  313. }
  314. orderVo.setIsMine(delivery.getIsMine());
  315. if (DeliveryTypeEnums.FENG_NIAO.getType().equals(delivery.getType()) || DeliveryTypeEnums.MEI_TUAN.getType().equals(delivery.getType())
  316. || DeliveryTypeEnums.FENG_NIAO_PT.getType().equals(delivery.getType())) {
  317. ShopDelivery shopDelivery = iShopDeliveryService.findOne(shopId, delivery.getId());
  318. if (shopDelivery == null || !BindStatusEnum.BIND.status.equals(shopDelivery.getBindStatus())) {
  319. return null;
  320. }
  321. }
  322. // if ((DeliveryTypeEnums.FENG_NIAO.getType().equals(delivery.getType())
  323. // || DeliveryTypeEnums.MEI_TUAN.getType().equals(delivery.getType())
  324. // ||DeliveryTypeEnums.FENG_NIAO_PT.getType().equals(delivery.getType()))
  325. // && DefaultShopEnum.SHOW.status.equals(defaultShop)) {
  326. // return null;
  327. // }
  328. if ((DeliveryTypeEnums.FENG_NIAO.getType().equals(delivery.getType())||DeliveryTypeEnums.FENG_NIAO_PT.getType().equals(delivery.getType())) && shopId == null) {
  329. return null;
  330. }
  331. // 美团跑腿未绑定不参与计价
  332. if ((DeliveryTypeEnums.MEI_TUAN_ZB.getType().equals(delivery.getType()) ||DeliveryTypeEnums.MEI_TUAN_SG_ZB.getType().equals(delivery.getType())) && delivery.getIsMine() == 0){
  333. return null;
  334. }
  335. if ((DeliveryTypeEnums.MEI_TUAN_ZB.getType().equals(delivery.getType()) || DeliveryTypeEnums.MEI_TUAN_SG_ZB.getType().equals(delivery.getType()))){
  336. SysConfig sysConfig = iSysConfigService.selectSysConfigByKey("MT_PT");
  337. if (sysConfig.getConfigValue().equals("yes") && shopId != 1626){
  338. return null;
  339. }
  340. }
  341. ResObject<OrderResultVo> resObject = client.queryOrderDeliverFee(orderVo);
  342. if (resObject.getCode() == 0) {
  343. ValuationRes res = new ValuationRes();
  344. transResObject(res, delivery, resObject, orderReq, orderVo);
  345. // 判断是否是自己平台,查询金额是否充足 (对接开放平台暂时无自运力逻辑, 此处保留防止需求变更)
  346. if (delivery.getIsMine() == 1 && !delivery.getType().equals(DeliveryTypeEnums.KUAI_FU.getType())
  347. && !delivery.getType().equals(DeliveryTypeEnums.MEI_TUAN_ZB.getType())
  348. && !DeliveryTypeEnums.MEI_TUAN_ZB.getType().equals(delivery.getType())) {
  349. QueryAmount queryAmount = QueryAmountEntityUtils.queryAmount(delivery, merchantId, delivery.getIsMine());
  350. ResObject<AmountResultVo> amountRes = client.queryAmount(queryAmount);
  351. if (amountRes.getCode() == 0) {
  352. // 更新余额
  353. AmountResultVo vo = amountRes.getData();
  354. this.updateAmount(delivery, merchantId, shopId, vo.getBalanceAmount());
  355. if (vo.getBalanceAmount().compareTo(res.getDeliveryAmount()) >= 0) {
  356. res.setIsEnough(StatusEnum.SHOW.status);
  357. res.setIsMine(1);
  358. } else {
  359. //uupt需重新计价
  360. res.setIsMine(0);
  361. orderVo.setIsMine(0);
  362. if (DeliveryTypeEnums.UUPT.getName().equals(orderVo.getLbClient())||DeliveryTypeEnums.SHAN_SONG.getName().equals(orderVo.getLbClient())) {
  363. orderVo.setOpenId("");
  364. resObject = client.queryOrderDeliverFee(orderVo);
  365. if (resObject.getCode() == 0) {
  366. transResObject(res, delivery, resObject, orderReq, orderVo);
  367. } else {
  368. res = null;
  369. }
  370. }
  371. if (DeliveryTypeEnums.DADA.getType().equals(delivery.getType()) || DeliveryTypeEnums.DADA_YZ.getType().equals(delivery.getType())){
  372. // 达达/优质余额不足,重新计价
  373. log.info("余额不足----" + DeliveryTypeEnums.getNameByType(delivery.getType()) + "余额不足,重新计价");
  374. ShopDelivery sd = iShopDeliveryService.getOne(new QueryWrapper<ShopDelivery>().eq("merchant_id", merchantId).eq("delivery_id", delivery.getId())
  375. .eq("deleted", IsDeleteEnum.NORMAL.status).eq("shop_id", shopId).eq("bind_status",1));
  376. if (sd != null && sd.getThirdShopId() != null) {
  377. orderVo.setShopNo(sd.getThirdShopId());
  378. delivery.setShopId(sd.getThirdShopId());
  379. } else {
  380. // 如果默认店铺被删了,则取列表第一个
  381. List<ShopDelivery> deliveries = iShopDeliveryService.list(new QueryWrapper<ShopDelivery>().eq("merchant_id", merchantId).eq("delivery_id", delivery.getId())
  382. .eq("deleted", IsDeleteEnum.NORMAL.status).isNotNull("third_shop_id"));
  383. if (CollectionUtils.isNotEmpty(deliveries)){
  384. orderVo.setShopNo(deliveries.get(0).getThirdShopId());
  385. delivery.setShopId(deliveries.get(0).getThirdShopId());
  386. }
  387. }
  388. orderVo.setMerchantId(null);
  389. resObject = client.queryOrderDeliverFee(orderVo);
  390. if (resObject.getCode() == 0) {
  391. transResObject(res, delivery, resObject, orderReq, orderVo);
  392. }else{
  393. res = null;
  394. }
  395. }
  396. // 顺丰自运力余额不足,转猎豹平台重写计价
  397. if (DeliveryTypeEnums.SHUN_FENG.getName().equals(orderVo.getLbClient())) {
  398. delivery.setIsMine(0);
  399. delivery.setThirdShopId(null);
  400. OrderVo reOrderVo = OrderEntityUtils.createOrderVo(orderReq, delivery, deliveryConfig.isTest());
  401. reOrderVo.setIsMine(delivery.getIsMine());
  402. resObject = client.queryOrderDeliverFee(reOrderVo);
  403. if (resObject.getCode() == 0) {
  404. transResObject(res, delivery, resObject, orderReq, orderVo);
  405. }else{
  406. res = null;
  407. }
  408. }
  409. }
  410. }
  411. } else if (delivery.getIsMine() == 1 && delivery.getType().equals(DeliveryTypeEnums.KUAI_FU.getType())) {
  412. if (!resObject.getData().getFeStatus().equals("1")) {
  413. res.setIsMine(0);
  414. orderVo.setIsMine(0);
  415. orderVo.setAccessToken(null);
  416. orderVo.setOpenId(null);
  417. resObject = client.queryOrderDeliverFee(orderVo);
  418. if (resObject.getCode() == 0) {
  419. transResObject(res, delivery, resObject, orderReq, orderVo);
  420. }else{
  421. res = null;
  422. }
  423. }
  424. }
  425. return res;
  426. }
  427. return null;
  428. }
  429. private void updateAmount(DeliveryInfo delivery, Long merchantId, Long shopId, BigDecimal balanceAmount) {
  430. if (DeliveryTypeEnums.DADA.getType().equals(delivery.getType())
  431. || DeliveryTypeEnums.DADA_YZ.getType().equals(delivery.getType())
  432. || DeliveryTypeEnums.FENG_NIAO.getType().equals(delivery.getType())
  433. || DeliveryTypeEnums.SHUN_FENG.getType().equals(delivery.getType())
  434. || DeliveryTypeEnums.MEI_TUAN_ZB.getType().equals(delivery.getType())) {
  435. ShopDeliveryBind shopDeliveryBind = iShopDeliveryBindService.getOne(new QueryWrapper<ShopDeliveryBind>()
  436. .eq("merchant_id", merchantId).eq("shop_id", shopId).eq("delivery_id", delivery.getId())
  437. .eq("deleted", IsDeleteEnum.NORMAL.status).eq("bind_status", 1));
  438. // 门店模式变更余额
  439. if (shopDeliveryBind != null) {
  440. iShopDeliveryBindService.updateShopAmount(shopDeliveryBind.getMerchantId(), shopDeliveryBind.getDeliveryId(), shopDeliveryBind.getThirdShopId(), balanceAmount);
  441. }
  442. } else {
  443. ShopDeliveryBind shopDeliveryBind = iShopDeliveryBindService.getOne(new QueryWrapper<ShopDeliveryBind>()
  444. .eq("merchant_id", merchantId).eq("delivery_id", delivery.getId())
  445. .eq("deleted", IsDeleteEnum.NORMAL.status).isNull("shop_id")
  446. .eq("bind_status", 1));
  447. // 商户模式变更余额
  448. if (shopDeliveryBind != null) {
  449. iShopDeliveryBindService.updateMerchantAmount(shopDeliveryBind.getId(), balanceAmount);
  450. }
  451. }
  452. }
  453. private void transResObject(ValuationRes res, DeliveryInfo delivery, ResObject<OrderResultVo> resObject, OrderReq orderReq, OrderVo orderVo) {
  454. res.setDeliveryId(delivery.getId());
  455. res.setName(delivery.getName());
  456. res.setLogo(delivery.getLogo());
  457. res.setDesc(CommonUtils.change2Km((int) resObject.getData().getDistance()));
  458. res.setDistance(String.valueOf(resObject.getData().getDistance()));
  459. res.setDeliveryAmount(resObject.getData().getDeliverFee());
  460. res.setIsEnough(StatusEnum.STOP.status);
  461. res.setTotalMoney(resObject.getData().getTotalMoney());
  462. res.setNeedPaymoney(resObject.getData().getNeedPaymoney());
  463. res.setPriceToken(resObject.getData().getPriceToken());
  464. // res.setDeliveryInfo(delivery);
  465. res.setOrderSn(orderReq.getOrderSn());
  466. res.setIsMine(orderVo.getIsMine());
  467. res.setOrderNo(orderReq.getOrderNo());
  468. res.setCityId(resObject.getData().getCityId());
  469. res.setCityInfoRevision(resObject.getData().getCityInfoRevision());
  470. res.setOrderVehicleId(resObject.getData().getOrderVehicleId());
  471. res.setTotalPriceFen(resObject.getData().getHllAmount());
  472. res.setOrderNumber(resObject.getData().getDeliveryOrderNo());//闪送订单号
  473. res.setShopId(delivery.getShopId());
  474. res.setThirdShopId(delivery.getThirdShopId());
  475. res.setAuthToken(delivery.getAuthToken());
  476. res.setPhone(delivery.getPhone());
  477. res.setDeliveryType(delivery.getType());
  478. }
  479. private void setBillingSort(PackageDeliveryDto packageDeliveryDto, ValuationRes valuationRes) {
  480. List<PackageDeliveryDetailDto> deliveryDetailDtoList = packageDeliveryDto.getPackageDeliveryDetailDtoList();
  481. if (CollectionUtils.isNotEmpty(deliveryDetailDtoList)) {
  482. Optional<PackageDeliveryDetailDto> optional = deliveryDetailDtoList.stream().filter(item -> valuationRes.getDeliveryType().equals(item.getDeliveryType())).findFirst();
  483. if (optional.isPresent()) {
  484. PackageDeliveryDetailDto packageDeliveryDetailDto = optional.get();
  485. valuationRes.setSort((packageDeliveryDetailDto.getSort() == null || packageDeliveryDetailDto.getSort() == 0) ? BillingConstant.DEFAULT_BILL_SORT : packageDeliveryDetailDto.getSort());
  486. }
  487. }
  488. }
  489. private List<ValuationRes> setBillingDuration(PackageDeliveryDto packageDeliveryDto, List<ValuationRes> billList) {
  490. String billDurationStr = packageDeliveryDto.getBillDurationStr();
  491. List<PackageDeliveryDetailDto> deliveryDetailList = packageDeliveryDto.getPackageDeliveryDetailDtoList();
  492. if (StringUtils.isNotEmpty(billDurationStr) && CollectionUtils.isNotEmpty(deliveryDetailList)) {
  493. String[] split = billDurationStr.split(",");
  494. if (PackageDeliveryTypeEnum.CUSTOM.type.equals(packageDeliveryDto.getType())) {
  495. deliveryDetailList = deliveryDetailList.stream().filter(item -> item.getSort() != null && item.getSort() > 0).collect(Collectors.toList());
  496. deliveryDetailList.sort(Comparator.comparing(PackageDeliveryDetailDto::getSort));
  497. for (int i = 0; i < deliveryDetailList.size(); i++) {
  498. PackageDeliveryDetailDto packageDeliveryDetailDto = deliveryDetailList.get(i);
  499. if (i < split.length) {
  500. packageDeliveryDetailDto.setBillDuration(Integer.parseInt(split[i]));
  501. }
  502. }
  503. for (ValuationRes valuationRes : billList) {
  504. int billDuration = BillingConstant.DEFAULT_BILL_DURATION;
  505. Optional<PackageDeliveryDetailDto> optional = deliveryDetailList.stream().filter(item -> item.getDeliveryType().equals(valuationRes.getDeliveryType())).findAny();
  506. if (optional.isPresent()) {
  507. PackageDeliveryDetailDto packageDeliveryDetailDto = optional.get();
  508. billDuration = packageDeliveryDetailDto.getBillDuration();
  509. }
  510. valuationRes.setBillDuration(billDuration == 0 ? BillingConstant.DEFAULT_BILL_DURATION : billDuration);
  511. }
  512. } else {
  513. for (int i = 0; i < billList.size(); i++) {
  514. ValuationRes valuationRes = billList.get(i);
  515. int billDuration = BillingConstant.DEFAULT_BILL_DURATION;
  516. if (i < split.length) {
  517. billDuration = Integer.parseInt(split[i]);
  518. }
  519. valuationRes.setBillDuration(billDuration);
  520. }
  521. }
  522. } else {
  523. billList = billList.stream().map(valuationRes -> valuationRes.setBillDuration(BillingConstant.DEFAULT_BILL_DURATION)).collect(Collectors.toList());
  524. }
  525. return billList;
  526. }
  527. private void setCommissionInfo(List<PackageCommissionDetailDto> packageCommissionDetailDtoList, ValuationRes valuationRes) {
  528. BigDecimal commission = BigDecimal.ZERO;
  529. if (valuationRes.getIsMine() == 1 || DeliveryTypeEnums.HUO_LA_LA.getType().equals(valuationRes.getDeliveryType())) {
  530. valuationRes.setCommission(commission);
  531. return;
  532. }
  533. if (CollectionUtils.isNotEmpty(packageCommissionDetailDtoList) && packageCommissionDetailDtoList.size() > 0) {
  534. PackageCommissionDetailDto packageCommissionDetailDto = packageCommissionDetailDtoList.get(0);
  535. if (PackageCommissionTypeEnum.RATE.type.equals(packageCommissionDetailDto.getCommissionType())) {
  536. if (packageCommissionDetailDto.getValue() != null) {
  537. commission = packageCommissionDetailDto.getValue().multiply(valuationRes.getDeliveryAmount())
  538. .divide(new BigDecimal("100"), BigDecimal.ROUND_HALF_UP).setScale(6, BigDecimal.ROUND_HALF_UP);
  539. }
  540. } else if (PackageDiscountDetailTypeEnum.GRADIENT.type.equals(packageCommissionDetailDto.getCommissionType())) {
  541. for (PackageCommissionDetailDto item : packageCommissionDetailDtoList) {
  542. boolean inRange = BigDecimalUtils.inRange(item.getLeftValue(), item.getRightValue(), valuationRes.getDeliveryAmount());
  543. if (inRange) {
  544. if (item.getValue() != null) {
  545. commission = item.getValue();
  546. }
  547. break;
  548. }
  549. }
  550. }
  551. }
  552. valuationRes.setCommission(commission);
  553. valuationRes.setDeliveryAmount(commission.add(valuationRes.getDeliveryAmount()));
  554. }
  555. private void setDiscountInfo(List<PackageDiscountDetailDto> discountDetailDtoList, ValuationRes valuationRes) {
  556. if (valuationRes.getIsMine() == 1) {
  557. return;
  558. }
  559. if (CollectionUtils.isNotEmpty(discountDetailDtoList) && discountDetailDtoList.size() > 0) {
  560. PackageDiscountDetailDto discountDetailDto = discountDetailDtoList.get(0);
  561. if (PackageDiscountDetailTypeEnum.ZHE_KOU.type.equals(discountDetailDto.getType())) {
  562. if (discountDetailDto.getValue() != null) {
  563. BigDecimal discountValue = discountDetailDto.getValue().multiply(valuationRes.getDeliveryAmount())
  564. .divide(BigDecimal.TEN, BigDecimal.ROUND_HALF_UP).setScale(6, BigDecimal.ROUND_HALF_UP);
  565. double abs = Math.abs(valuationRes.getDeliveryAmount().subtract(discountValue).doubleValue());
  566. if (discountDetailDto.getMaxValue() != null) {
  567. abs = Math.min(abs, discountDetailDto.getMaxValue().doubleValue());
  568. }
  569. // 判断是优惠还是提价
  570. boolean positiveNum = discountValue.subtract(valuationRes.getDeliveryAmount()).compareTo(BigDecimal.ZERO) >= 0;
  571. if (positiveNum) {
  572. valuationRes.setDeliveryAmount(valuationRes.getDeliveryAmount().add(new BigDecimal(abs)));
  573. } else {
  574. valuationRes.setDeliveryAmount(valuationRes.getDeliveryAmount().subtract(new BigDecimal(abs)));
  575. }
  576. valuationRes.setZk(discountDetailDto.getValue());
  577. }
  578. } else if (PackageDiscountDetailTypeEnum.GRADIENT.type.equals(discountDetailDto.getType())) {
  579. for (PackageDiscountDetailDto item : discountDetailDtoList) {
  580. boolean inRange = BigDecimalUtils.inRange(item.getLeftValue(), item.getRightValue(), valuationRes.getDeliveryAmount());
  581. if (inRange) {
  582. if (item.getValue() != null) {
  583. BigDecimal discountAmount = valuationRes.getDeliveryAmount().subtract(item.getValue());
  584. valuationRes.setDeliveryAmount(discountAmount.compareTo(BigDecimal.ZERO) > 0 ? discountAmount : BigDecimal.ZERO);
  585. valuationRes.setMj(item.getValue());
  586. }
  587. break;
  588. }
  589. }
  590. }
  591. }
  592. }
  593. private List<DeliveryInfo> getDeliveryInfos(OrderValuationDto valuationDto, List<Integer> types) {
  594. List<DspDelivery> list = iDspDeliveryService.list(new QueryWrapper<DspDelivery>()
  595. .isNotNull("parent_id")
  596. .eq("status", StatusEnum.SHOW.status)
  597. .eq("deleted", IsDeleteEnum.NORMAL.status)
  598. .ne("type", DeliveryTypeEnums.HUO_LA_LA.getType())
  599. .in(CollectionUtils.isNotEmpty(types), "type", types));
  600. List<DeliveryInfo> infos = Lists.newArrayList();
  601. List<Integer> deliveryTypes = Arrays.asList(DeliveryTypeEnums.DADA.getType(), DeliveryTypeEnums.DADA_YZ.getType(),
  602. DeliveryTypeEnums.DWD.getType(), DeliveryTypeEnums.FENG_NIAO.getType(), DeliveryTypeEnums.FENG_NIAO_PT.getType(),
  603. DeliveryTypeEnums.MEI_TUAN.getType(), DeliveryTypeEnums.SHAN_SONG.getType(), DeliveryTypeEnums.SHUN_FENG.getType());
  604. List<Long> deliveryIds = list.stream().map(DspDelivery::getId).collect(Collectors.toList());
  605. Map<String, List<ShopDelivery>> deliveryMap = new HashMap<>();
  606. if (CollectionUtils.isNotEmpty(deliveryIds)) {
  607. deliveryMap = iShopDeliveryService.list(new QueryWrapper<ShopDelivery>()
  608. .eq("merchant_id", valuationDto.getMerchantId())
  609. .in("delivery_id", deliveryIds)
  610. .eq("deleted", IsDeleteEnum.NORMAL.status)
  611. .eq("shop_id", valuationDto.getShopId())
  612. .eq("bind_status",1))
  613. .stream()
  614. .collect(Collectors.groupingBy(item -> item.getDeliveryId() + "-" + item.getMerchantId() + "-" + item.getShopId()));
  615. }
  616. for (DspDelivery delivery : list) {
  617. DeliveryInfo info = new DeliveryInfo();
  618. BeanUtils.copyProperties(delivery, info);
  619. if (deliveryTypes.contains(info.getType()) && valuationDto.getMerchantId() != null && valuationDto.getShopId() != null) {
  620. List<ShopDelivery> shopDeliveries = deliveryMap.get(info.getId() + "-" + valuationDto.getMerchantId() + "-" + valuationDto.getShopId());
  621. ShopDelivery sd = new ShopDelivery();
  622. if (CollectionUtils.isNotEmpty(shopDeliveries)) {
  623. sd = shopDeliveries.get(0);
  624. }
  625. if (sd.getThirdShopId() != null && (DeliveryTypeEnums.DADA.getType().equals(info.getType())
  626. || DeliveryTypeEnums.DADA_YZ.getType().equals(info.getType())
  627. || DeliveryTypeEnums.SHAN_SONG.getType().equals(info.getType()))) {
  628. info.setShopId(sd.getThirdShopId());
  629. }
  630. if(sd.getThirdShopId() != null && (DeliveryTypeEnums.FENG_NIAO.getType().equals(info.getType())
  631. || DeliveryTypeEnums.FENG_NIAO_PT.getType().equals(info.getType())
  632. || DeliveryTypeEnums.MEI_TUAN.getType().equals(info.getType()))) {
  633. info.setThirdShopId(sd.getThirdShopId());
  634. }
  635. }
  636. info.setIsMine(0);
  637. infos.add(info);
  638. }
  639. return infos;
  640. }
  641. private ResponseResult validParam(OrderValuationReq valuationReq, OrderValuationDto valuationDto, Member member) {
  642. ResponseResult result = ResponseResult.success();
  643. List<Integer> platformTypes = Arrays.asList(0, 1, 2, 3, 5, 6);
  644. if (!platformTypes.contains(valuationReq.getPlatformType())) {
  645. return ResponseResult.error(ResponseResultCodeEnum.FIELD_INVALID, "platformType", null);
  646. }
  647. if (StringUtils.isBlank(valuationReq.getShopCode())) {
  648. if (StringUtils.isBlank(valuationReq.getSendName())) {
  649. return ResponseResult.error(ResponseResultCodeEnum.FIELD_EMPTY, "sendName", null);
  650. }
  651. if (StringUtils.isBlank(valuationReq.getSendPhone())) {
  652. return ResponseResult.error(ResponseResultCodeEnum.FIELD_EMPTY, "sendPhone", null);
  653. }
  654. if (StringUtils.isBlank(valuationReq.getSendProvinceName())) {
  655. return ResponseResult.error(ResponseResultCodeEnum.FIELD_EMPTY, "sendProvinceName", null);
  656. }
  657. if (StringUtils.isBlank(valuationReq.getSendCityName())) {
  658. return ResponseResult.error(ResponseResultCodeEnum.FIELD_EMPTY, "sendCityName", null);
  659. }
  660. if (StringUtils.isBlank(valuationReq.getSendCityCode())) {
  661. return ResponseResult.error(ResponseResultCodeEnum.FIELD_EMPTY, "sendCityCode", null);
  662. }
  663. if (StringUtils.isBlank(valuationReq.getSendAddress())) {
  664. return ResponseResult.error(ResponseResultCodeEnum.FIELD_EMPTY, "sendAddress", null);
  665. }
  666. if (StringUtils.isBlank(valuationReq.getSendLng())) {
  667. return ResponseResult.error(ResponseResultCodeEnum.FIELD_EMPTY, "sendLng", null);
  668. }
  669. if (StringUtils.isBlank(valuationReq.getSendLat())) {
  670. return ResponseResult.error(ResponseResultCodeEnum.FIELD_EMPTY, "sendLat", null);
  671. }
  672. valuationDto.setShopId(member.getShopId());
  673. valuationDto.setMerchantId(member.getMerchantId());
  674. } else {
  675. Shop shop = iShopService.getByCode(valuationReq.getShopCode());
  676. if (shop == null) {
  677. return ResponseResult.error(ResponseResultCodeEnum.SHOP_NOT_EXIST);
  678. }
  679. valuationReq.setSendName(shop.getContactName());
  680. valuationReq.setSendPhone(shop.getMobile());
  681. valuationReq.setSendProvinceName(shop.getProvinceName());
  682. valuationReq.setSendCityName(shop.getCityName());
  683. valuationReq.setSendDistrictName(shop.getDistrictName());
  684. valuationReq.setSendAddress(shop.getAddress());
  685. valuationReq.setSendHouseNumber(shop.getStreet());
  686. valuationReq.setSendLat(shop.getLat());
  687. valuationReq.setSendLng(shop.getLng());
  688. valuationReq.setSendCityCode(shop.getCityCode());
  689. valuationDto.setShopId(shop.getId());
  690. valuationDto.setShopName(shop.getName());
  691. valuationDto.setMerchantId(shop.getMerchantId());
  692. }
  693. BeanUtils.copyProperties(valuationReq, valuationDto);
  694. if (valuationDto.getMerchantId() != null) {
  695. Merchant merchant = iMerchantService.getById(valuationDto.getMerchantId());
  696. if (merchant == null) {
  697. return ResponseResult.error(ResponseResultCodeEnum.MERCHANT_DISABLE);
  698. }
  699. }
  700. return result;
  701. }
  702. }