TOrderServiceImpl.java 30 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728
  1. package com.ylx.massage.service.impl;
  2. import cn.hutool.core.collection.CollectionUtil;
  3. import cn.hutool.json.JSONUtil;
  4. import com.alibaba.fastjson.JSONArray;
  5. import com.alibaba.fastjson.JSONObject;
  6. import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
  7. import com.baomidou.mybatisplus.core.conditions.update.LambdaUpdateWrapper;
  8. import com.baomidou.mybatisplus.core.conditions.update.UpdateWrapper;
  9. import com.baomidou.mybatisplus.core.toolkit.StringUtils;
  10. import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
  11. import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
  12. import com.ylx.common.config.WechatAccountConfig;
  13. import com.ylx.common.constant.MassageConstants;
  14. import com.ylx.common.core.domain.R;
  15. import com.ylx.common.exception.ServiceException;
  16. import com.ylx.massage.domain.*;
  17. import com.ylx.massage.domain.vo.CouponReceiveVo;
  18. import com.ylx.massage.enums.BillTypeEnum;
  19. import com.ylx.massage.enums.DiscountTypeEnum;
  20. import com.ylx.massage.enums.JsStatusEnum;
  21. import com.ylx.massage.enums.OrderStatusEnum;
  22. import com.ylx.massage.mapper.TOrderMapper;
  23. import com.ylx.massage.service.*;
  24. import com.ylx.massage.utils.*;
  25. import lombok.extern.slf4j.Slf4j;
  26. import org.apache.commons.compress.utils.Lists;
  27. import org.springframework.stereotype.Service;
  28. import org.springframework.transaction.annotation.Transactional;
  29. import javax.annotation.Resource;
  30. import java.math.BigDecimal;
  31. import java.math.RoundingMode;
  32. import java.time.LocalDateTime;
  33. import java.util.*;
  34. import java.util.stream.Collectors;
  35. /**
  36. * 订单表 服务实现类
  37. */
  38. @Service
  39. @Slf4j
  40. public class TOrderServiceImpl extends ServiceImpl<TOrderMapper, TOrder> implements TOrderService {
  41. @Resource
  42. private TOrderMapper orderMapper;
  43. @Resource
  44. private WechatAccountConfig wxPayProperties;
  45. @Resource
  46. private LocationUtil locationUtil;
  47. @Resource
  48. private TWxUserService wxUserService;
  49. @Resource
  50. private TRechargeService rechargeService;
  51. @Resource
  52. private TXiangmuService xiangmuService;
  53. @Resource
  54. private OrderNumberGenerator generator;
  55. @Resource
  56. private TJsService jsService;
  57. @Resource
  58. private TAddressService addressService;
  59. @Resource
  60. private TConsumptionLogService consumptionLogService;
  61. @Resource
  62. private MassageUtil massageUtil;
  63. @Resource
  64. private CouponReceiveService couponReceiveService;
  65. @Resource
  66. private CouponService couponService;
  67. @Resource
  68. private WeChatUtil weChatUtil;
  69. @Resource
  70. private RefundVoucherService refundVoucherService;
  71. public Boolean isFree(TJs js, BigDecimal distance) {
  72. Date date = new Date();
  73. //白天免车费(07.30-20.00)
  74. long current = Long.parseLong(DateTimeUtils.numTime(date));
  75. if (current >= MassageConstants.START_FREE && current <= MassageConstants.END_FREE) {
  76. if (js.getDaytimeMileage().compareTo(distance) >= 0) {
  77. //免车费
  78. return Boolean.TRUE;
  79. } else {
  80. return Boolean.FALSE;
  81. }
  82. } else {
  83. //夜间免车费(20.00-07.30)
  84. if (js.getNigthMileage().compareTo(distance) >= 0) {
  85. //免车费
  86. return Boolean.TRUE;
  87. } else {
  88. return Boolean.FALSE;
  89. }
  90. }
  91. }
  92. /**
  93. * 添加订单
  94. *
  95. * @param order
  96. */
  97. @Override
  98. @Transactional(rollbackFor = Exception.class)
  99. public TOrder addOrder(TOrder order) {
  100. if (StringUtils.isBlank(order.getcJsId())) {
  101. throw new ServiceException("请选择技师");
  102. }
  103. if (order.getcGoods().isEmpty()) {
  104. throw new ServiceException("请选择项目");
  105. }
  106. //优惠卷减免
  107. // List<CouponReceiveVo> coupons = couponReceiveService.getByOpenId(order.getcOpenId());
  108. // BigDecimal preferential = this.setCoupon(coupons);
  109. // order.setPreferential(preferential);
  110. order.setOrderNo(generator.generateNextOrderNumber(OrderNumberGenerator.KEY_PREFIX_ORDER));
  111. //订单价格
  112. List<TXiangmu> list = JSONObject.parseArray(order.getcGoods().toJSONString(), TXiangmu.class);
  113. BigDecimal sum = list.stream().map(TXiangmu::getSum).reduce(BigDecimal.ZERO, BigDecimal::add);
  114. order.setdTotalMoney(sum);
  115. //获取用户默认地址
  116. TAddress address = addressService.getByOpenId(order.getcOpenId());
  117. if (address == null) {
  118. throw new ServiceException("请先添加地址");
  119. }
  120. TJs js = jsService.getById(order.getcJsId());
  121. //添加位置信息
  122. locationUtil.geoAdd(LocationUtil.GEO_KEY_USER, js.getcOpenId() + order.getOrderNo(), Double.parseDouble(js.getLongitude().toString()), Double.parseDouble(js.getLatitude().toString()));
  123. locationUtil.geoAdd(LocationUtil.GEO_KEY_USER, order.getcOpenId() + order.getOrderNo(), Double.parseDouble(address.getLongitude().toString()), Double.parseDouble(address.getLatitude().toString()));
  124. double distance = locationUtil.getDistance(js.getcOpenId() + order.getOrderNo(), order.getcOpenId() + order.getOrderNo());
  125. locationUtil.remove(LocationUtil.GEO_KEY_USER, js.getcOpenId() + order.getOrderNo(), order.getcOpenId() + order.getOrderNo());
  126. order.setDistance(new BigDecimal(distance));
  127. //计算车费
  128. if (order.getDistance() != null && order.getDistance().compareTo(BigDecimal.ZERO) > 0) {
  129. //判断是否可以免车费
  130. if (!this.isFree(js, order.getDistance())) {
  131. BigDecimal bigDecimal = massageUtil.calculateTaxiFare(order.getDistance());
  132. order.setFare(bigDecimal.setScale(MassageConstants.INTEGER_TWO, RoundingMode.HALF_UP));
  133. }
  134. }
  135. //总价 = 订单 + 车费 - 优惠
  136. order.setTotalPrice(sum.add(Optional.ofNullable(order.getFare()).orElse(BigDecimal.ZERO)));
  137. if (order.getParentNo() != null && order.getOrderType() == 2) {
  138. //升级订单 补差价
  139. TOrder partOrder = this.getByNo(order.getParentNo());
  140. order.setPriceDifference(order.getTotalPrice().subtract(partOrder.getTotalPrice()));
  141. }
  142. order.setAddress(address.getAddress());
  143. order.setName(address.getName());
  144. order.setLatitude(address.getLatitude());
  145. order.setLongitude(address.getLongitude());
  146. order.setcPhone(address.getPhone());
  147. order.setcName(address.getUserName());
  148. order.setAtlasAdd(address.getAtlasAdd());
  149. order.setnStatus(OrderStatusEnum.WAIT_PAY.getCode());
  150. order.setDtCreateTime(LocalDateTime.now());
  151. Date date = DateTimeUtils.addMinute(new Date(), 10);
  152. order.setcTime(DateTimeUtils.formatDate(date, "yyyy-MM-dd HH:mm:ss"));
  153. save(order);
  154. return order;
  155. }
  156. private BigDecimal setCoupon(List<CouponReceiveVo> coupons) {
  157. //过滤过期的优惠券
  158. coupons = coupons.stream().filter(coupon -> coupon.getExpirationTime().after(new Date())).collect(Collectors.toList());
  159. //无门槛优惠券
  160. List<CouponReceiveVo> collect = coupons.stream().filter(coupon -> coupon.getDiscountType().equals(DiscountTypeEnum.NO_THRESHOLD.getCode())).collect(Collectors.toList());
  161. //支付成功 后 删除优惠卷
  162. // couponReceiveService.removeCoupons(collect);
  163. //计算优惠金额
  164. return collect.stream().map(CouponReceiveVo::getDiscountValue).reduce(BigDecimal.ZERO, BigDecimal::add);
  165. }
  166. @Override
  167. public void payNotifyOrder(String outTradeNo) {
  168. //查询未支付的订单
  169. LambdaQueryWrapper<TOrder> queryWrapper = new LambdaQueryWrapper<>();
  170. queryWrapper.eq(TOrder::getOrderNo, outTradeNo).eq(TOrder::getnStatus, OrderStatusEnum.WAIT_PAY.getCode());
  171. TOrder orderNew = this.getOne(queryWrapper);
  172. if (orderNew == null) {
  173. log.error("订单 {} 未支付状态不存在", outTradeNo);
  174. return;
  175. }
  176. orderNew.setPayType(1);
  177. TWxUser user = wxUserService.getByOpenId(orderNew.getcOpenId());
  178. orderPayManage(user, orderNew);
  179. }
  180. @Override
  181. public Object updateAddressById(TOrder borrow) {
  182. TOrder order = this.getById(borrow.getcId());
  183. if(borrow.getLatitude()!=null && borrow.getLatitude()!=0 && borrow.getLongitude()!=null && borrow.getLongitude()!=0){
  184. order.setAtlasAdd(borrow.getAtlasAdd());
  185. order.setcName(borrow.getcName());
  186. order.setcPhone(borrow.getcPhone());
  187. order.setName(borrow.getName());
  188. order.setAddress(borrow.getAddress());
  189. order.setLatitude(borrow.getLatitude());
  190. order.setLongitude(borrow.getLongitude());
  191. TJs js = jsService.getById(order.getcJsId());
  192. //添加位置信息
  193. locationUtil.geoAdd(LocationUtil.GEO_KEY_USER, js.getcOpenId() + order.getOrderNo(), Double.parseDouble(js.getLongitude().toString()), Double.parseDouble(js.getLatitude().toString()));
  194. locationUtil.geoAdd(LocationUtil.GEO_KEY_USER, order.getcOpenId() + order.getOrderNo(), Double.parseDouble(borrow.getLongitude().toString()), Double.parseDouble(borrow.getLatitude().toString()));
  195. double distance = locationUtil.getDistance(js.getcOpenId() + order.getOrderNo(), order.getcOpenId() + order.getOrderNo());
  196. locationUtil.remove(LocationUtil.GEO_KEY_USER, js.getcOpenId() + order.getOrderNo(), order.getcOpenId() + order.getOrderNo());
  197. order.setDistance(new BigDecimal(distance));
  198. //计算车费
  199. if (order.getDistance() != null && order.getDistance().compareTo(BigDecimal.ZERO) > 0) {
  200. //判断是否可以免车费
  201. if (!this.isFree(js, order.getDistance())) {
  202. BigDecimal bigDecimal = massageUtil.calculateTaxiFare(order.getDistance());
  203. order.setFare(bigDecimal.setScale(MassageConstants.INTEGER_TWO, RoundingMode.HALF_UP));
  204. }
  205. }
  206. order.setTotalPrice(order.getdTotalMoney().add(Optional.ofNullable(order.getFare()).orElse(BigDecimal.ZERO)));
  207. this.updateById(order);
  208. }
  209. return order;
  210. }
  211. @Override
  212. public Object depart(TOrder order) {
  213. LambdaQueryWrapper<TOrder> wrapper = new LambdaQueryWrapper<>();
  214. wrapper.eq(TOrder::getcId,order.getcId()).eq(TOrder::getnStatus,OrderStatusEnum.RECEIVED_ORDER.getCode());
  215. order.setnStatus(OrderStatusEnum.DEPART.getCode());
  216. order.setReachTime(LocalDateTime.now());
  217. order.setDepartTime(new Date());
  218. order.setDepartLatitude(Optional.ofNullable(order.getDepartLatitude()).orElse(BigDecimal.ZERO));
  219. order.setDepartLongitude(Optional.ofNullable(order.getDepartLongitude()).orElse(BigDecimal.ZERO));
  220. return this.update(order,wrapper);
  221. }
  222. @Override
  223. public Integer getOrderNum(String jsid, Date startDate, Date endDate) {
  224. return orderMapper.getOrderNum(jsid, startDate, endDate);
  225. }
  226. @Override
  227. public Integer getAddNum(String jsid, Date startDate, Date endDate) {
  228. return orderMapper.getAddNum(jsid, startDate, endDate);
  229. }
  230. @Override
  231. public Integer getUpgradeNum(String jsid, Date startDate, Date endDate) {
  232. return orderMapper.getUpgradeNum(jsid, startDate, endDate);
  233. }
  234. @Override
  235. public BigDecimal getTurnover(String jsid, Date startDate, Date endDate) {
  236. return orderMapper.getTurnover(jsid, startDate, endDate);
  237. }
  238. @Override
  239. public TOrder transferOrder(TOrder order) {
  240. if(StringUtils.isBlank(order.getcId())){
  241. throw new ServiceException("订单id不能为空");
  242. }
  243. if(StringUtils.isBlank(order.getcJsId())){
  244. throw new ServiceException("转单技师ID不能为空");
  245. }
  246. TOrder oldOrder = this.getById(order.getcId());
  247. oldOrder.setOldJsId(oldOrder.getcJsId());
  248. oldOrder.setcJsId(order.getcJsId());
  249. if(!this.updateById(oldOrder)){
  250. throw new ServiceException("转单失败");
  251. }
  252. //通知技师转单
  253. this.newOrderNotification(oldOrder);
  254. return oldOrder;
  255. }
  256. /**
  257. * 支付订单
  258. *
  259. * @param order
  260. */
  261. @Override
  262. public R payOrder(TOrder order) throws Exception {
  263. // 根据orderid查询订单信息
  264. TOrder orderNew = getById(order.getcId());
  265. if (!orderNew.getnStatus().equals(OrderStatusEnum.WAIT_PAY.getCode())) {
  266. throw new ServiceException("该订单已经支付或者超时被取消");
  267. }
  268. if (StringUtils.isBlank(orderNew.getParentNo())) {
  269. TJs js = jsService.getById(orderNew.getcJsId());
  270. if (null == js || js.getnStatus().equals(JsStatusEnum.JS_SERVICE.getCode())) {
  271. throw new ServiceException("该技师已在服务中请重新下单");
  272. }
  273. }
  274. orderNew.setPayType(order.getPayType());
  275. if (StringUtils.isNotBlank(order.getCouponReceiveId())) {
  276. orderNew.setCouponReceiveId(order.getCouponReceiveId());
  277. CouponReceive couponReceive = couponReceiveService.getById(order.getCouponReceiveId());
  278. Coupon coupon = couponService.getById(couponReceive.getCouponId());
  279. //无门槛优惠券
  280. orderNew.setPreferential(coupon.getDiscountValue());
  281. //todo 其他优惠卷....
  282. orderNew.setTotalPrice(orderNew.getTotalPrice().subtract(coupon.getDiscountValue()));
  283. }
  284. //判断支付方式
  285. if (order.getPayType().equals(MassageConstants.INTEGER_ONE)) {
  286. //微信支付
  287. R resp = rechargeService.getPay(orderNew.getOrderNo(), orderNew.getTotalPrice(), orderNew.getcOpenId(), BillTypeEnum.WX_PAY.getInfo(), BillTypeEnum.WX_PAY.getCode().toString());
  288. return resp;
  289. }
  290. // 从对应账户扣款
  291. TWxUser user = wxUserService.getByOpenId(orderNew.getcOpenId());
  292. if (null == user) {
  293. throw new ServiceException("用户不存在");
  294. }
  295. if (user.getdBalance().compareTo(orderNew.getTotalPrice()) < MassageConstants.INTEGER_ZERO) {
  296. throw new ServiceException("账户金额不够请充值");
  297. } else {
  298. orderPayManage(user, orderNew);
  299. return R.ok();
  300. }
  301. }
  302. public void newOrderNotification(TOrder order) {
  303. cn.hutool.json.JSONObject param = JSONUtil.createObj();
  304. //订单号
  305. param.set("character_string9", JSONUtil.createObj().set("value", order.getOrderNo()));
  306. //电话
  307. param.set("phone_number14", JSONUtil.createObj().set("value", order.getcPhone()));
  308. param.set("thing18", JSONUtil.createObj().set("value", order.getcName()));
  309. param.set("time6", JSONUtil.createObj().set("value", DateTimeUtils.formatDate(new Date(), DateTimeUtils.DATE_NUMBER_YEAR_MONTH_FORMAT)));
  310. param.set("thing27", JSONUtil.createObj().set("value", order.getName()));
  311. TJs js = jsService.getById(order.getcJsId());
  312. weChatUtil.notification(js.getcOpenId(), wxPayProperties.getTemplateId1(), param);
  313. }
  314. @Transactional(rollbackFor = Exception.class)
  315. public void orderPayManage(TWxUser user, TOrder orderNew) {
  316. //删除优惠卷
  317. // 更新用户金额 及下单此时
  318. TWxUser paramUser = new TWxUser();
  319. paramUser.setcOpenid(user.getcOpenid());
  320. if (!orderNew.getPayType().equals(MassageConstants.INTEGER_ONE)) {
  321. paramUser.setdBalance(user.getdBalance().subtract(orderNew.getTotalPrice()));
  322. }
  323. paramUser.setdMoney(user.getdMoney().add(orderNew.getTotalPrice()));
  324. paramUser.setnNum(user.getnNum() + MassageConstants.INTEGER_ZERO);
  325. paramUser.setId(user.getId());
  326. wxUserService.updateById(paramUser);
  327. //增加消费记录
  328. TConsumptionLog tConsumptionLog = new TConsumptionLog();
  329. tConsumptionLog.setAmount(orderNew.getTotalPrice().negate());
  330. tConsumptionLog.setBillNo(orderNew.getOrderNo());
  331. tConsumptionLog.setOpenId(orderNew.getcOpenId());
  332. if (!orderNew.getPayType().equals(MassageConstants.INTEGER_ONE)) {
  333. tConsumptionLog.setBillType(BillTypeEnum.BALANCE_PAYMENT.getCode());
  334. tConsumptionLog.setNote("余额支付");
  335. } else {
  336. tConsumptionLog.setBillType(BillTypeEnum.WX_PAY.getCode());
  337. tConsumptionLog.setNote("微信支付");
  338. }
  339. consumptionLogService.save(tConsumptionLog);
  340. // 更新项目数据
  341. JSONArray objects = orderNew.getcGoods();
  342. objects.forEach(item -> {
  343. UpdateWrapper<TXiangmu> wrapper = new UpdateWrapper<>();
  344. // 获取参数
  345. wrapper.lambda().eq(TXiangmu::getcId, ((JSONObject) item).getString("cId"));
  346. // 设置数量
  347. wrapper.setSql(" n_sale_number = n_sale_number + " + ((JSONObject) item).getInteger("number"));
  348. xiangmuService.update(wrapper);
  349. });
  350. TOrder orderParam = new TOrder();
  351. orderParam.setPayType(orderNew.getPayType());
  352. orderParam.setcId(orderNew.getcId());
  353. orderParam.setnStatus(OrderStatusEnum.WAIT_JD.getCode());
  354. //加钟的订单支付完直接服务中
  355. if (StringUtils.isNotBlank(orderNew.getParentNo())) {
  356. orderParam.setnStatus(OrderStatusEnum.SERVICE.getCode());
  357. }
  358. // orderParam.setnStatus(OrderStatusEnum.SERVICE.getCode());
  359. //更新及技师状态
  360. updateJs(orderNew);
  361. updateById(orderParam);
  362. this.newOrderNotification(orderNew);
  363. }
  364. /**
  365. * 拒绝订单
  366. *
  367. * @param order
  368. */
  369. @Override
  370. public Boolean jujue(TOrder order) {
  371. TOrder orderNew = getById(order.getcId());
  372. TWxUser user = wxUserService.getByOpenId(orderNew.getcOpenId());
  373. // 更新用户金额 及下单此时
  374. TWxUser paramUser = new TWxUser();
  375. paramUser.setcOpenid(user.getcOpenid());
  376. paramUser.setId(user.getId());
  377. if (orderNew.getPayType() == 2) {
  378. // 金额归还对应账户
  379. paramUser.setdBalance(user.getdBalance().add(orderNew.getTotalPrice()));
  380. } else {
  381. // 微信支付
  382. // 生成退款单退款
  383. RefundVoucher refundVoucher = new RefundVoucher();
  384. refundVoucher.setRefundNo(generator.generateNextOrderNumber(OrderNumberGenerator.KEY_PREFIX_REFUND));
  385. refundVoucher.setOrderNo(orderNew.getOrderNo());
  386. refundVoucher.setMoney(orderNew.getTotalPrice());
  387. refundVoucher.setOpenId(orderNew.getcOpenId());
  388. refundVoucher.setReStatus(MassageConstants.INTEGER_ZERO);
  389. refundVoucher.setReason("技师拒绝接单");
  390. refundVoucherService.save(refundVoucher);
  391. // 微信退款原路返回
  392. rechargeService.refund(refundVoucher.getRefundNo(), null, orderNew.getOrderNo(), orderNew.getTotalPrice());
  393. }
  394. log.info("余额支付退款user:{}",user);
  395. // 消费金额对应减少
  396. paramUser.setdMoney(user.getdMoney().subtract(orderNew.getTotalPrice()));
  397. // 下单次数减一
  398. paramUser.setnNum(user.getnNum() - MassageConstants.INTEGER_ONE);
  399. wxUserService.updateById(paramUser);
  400. // 更新项目数据
  401. JSONArray objects = orderNew.getcGoods();
  402. objects.forEach(item -> {
  403. UpdateWrapper<TXiangmu> wrapper = new UpdateWrapper<>();
  404. // 获取参数
  405. wrapper.lambda().eq(TXiangmu::getcId, ((JSONObject) item).getString("cId"));
  406. // 设置数量
  407. wrapper.setSql(" n_sale_number = n_sale_number - " + ((JSONObject) item).getInteger("number"));
  408. xiangmuService.update(wrapper);
  409. });
  410. TOrder orderParam = new TOrder();
  411. orderParam.setcId(orderNew.getcId());
  412. orderParam.setnStatus(OrderStatusEnum.REFUSE.getCode());
  413. orderParam.setReasonRefusal(order.getReasonRefusal());
  414. updateJs(orderNew);
  415. return updateById(orderParam);
  416. }
  417. /**
  418. * 确认服务完成
  419. *
  420. * @param order
  421. * @return
  422. */
  423. @Override
  424. @Transactional(rollbackFor = Exception.class)
  425. public Boolean confirm(TOrder order) {
  426. // 获取订单信息
  427. TOrder orderNew = getById(order);
  428. if (!orderNew.getnStatus().equals(OrderStatusEnum.SERVICE.getCode())) {
  429. throw new ServiceException("订单状态不是服务中");
  430. }
  431. // 更新技师信息
  432. TJs jsParam = new TJs();
  433. jsParam.setId(orderNew.getcJsId());
  434. jsParam.setnStatus(JsStatusEnum.JS_SERVICEABLE.getCode());
  435. //判断热度标识
  436. List<TOrder> list = list(new LambdaQueryWrapper<TOrder>().eq(TOrder::getcJsId, orderNew.getcJsId())
  437. .ge(TOrder::getDtCreateTime, DateTimeUtils.addDays(new Date(), -3))
  438. .ge(TOrder::getnStatus, OrderStatusEnum.WAIT_EVALUATE.getCode()));
  439. if (list.size() >= 2) {
  440. jsParam.setnB3(MassageConstants.INTEGER_ONE);
  441. }
  442. // 更新技师状态
  443. jsService.updateById(jsParam);
  444. // 更新技师钱包金额
  445. TJs jsById = jsService.getById(orderNew.getcJsId());
  446. // 获取技师抽成
  447. BigDecimal multiply = orderNew.getTotalPrice().multiply(new BigDecimal(jsById.getnBili()));
  448. multiply = multiply.divide(new BigDecimal(100), MassageConstants.INTEGER_TWO, RoundingMode.HALF_UP);
  449. // 获取技师所对应的用户
  450. TWxUser jsUser = wxUserService.getByOpenId(jsById.getcOpenId());
  451. // 更新余额
  452. jsUser.setdBalance(jsUser.getdBalance().add(multiply));
  453. // 更新总钱数
  454. jsUser.setdAllMoney(jsUser.getdAllMoney().add(multiply));
  455. wxUserService.updateById(jsUser);
  456. //增加消费记录
  457. TConsumptionLog tConsumptionLog = new TConsumptionLog();
  458. tConsumptionLog.setAmount(multiply);
  459. tConsumptionLog.setBillNo(orderNew.getOrderNo());
  460. tConsumptionLog.setOpenId(jsUser.getcOpenid());
  461. tConsumptionLog.setBillType(BillTypeEnum.INCOME.getCode());
  462. tConsumptionLog.setNote("技师收益");
  463. consumptionLogService.save(tConsumptionLog);
  464. // 如果该技师有推荐人员 一级
  465. if (StringUtils.isNotBlank(jsUser.getcUpUser())) {
  466. // 获取技师上级对应的用户
  467. TWxUser jsUp = wxUserService.getById(jsUser.getcUpUser());
  468. extracted(orderNew, jsUp);
  469. //二级
  470. if (jsUp.getcUpUser() != null) {
  471. TWxUser jsUpTwo = wxUserService.getById(jsUp.getcUpUser());
  472. extracted(orderNew, jsUpTwo);
  473. //三级
  474. if (jsUpTwo.getcUpUser() != null) {
  475. TWxUser jsUpThree = wxUserService.getById(jsUpTwo.getcUpUser());
  476. extracted(orderNew, jsUpThree);
  477. }
  478. }
  479. }
  480. // 更新订单
  481. orderNew.setnStatus(OrderStatusEnum.WAIT_EVALUATE.getCode());
  482. orderNew.setEndTime(LocalDateTime.now());
  483. return updateById(orderNew);
  484. }
  485. private void extracted(TOrder orderNew, TWxUser jsUp) {
  486. BigDecimal up = orderNew.getdTotalMoney().multiply(new BigDecimal("10"));
  487. up = up.divide(new BigDecimal(100), 2, RoundingMode.HALF_UP);
  488. // 更新余额
  489. jsUp.setdBalance(jsUp.getdBalance().add(up));
  490. // 更新总钱数
  491. jsUp.setdAllMoney(jsUp.getdAllMoney().add(up));
  492. wxUserService.updateById(jsUp);
  493. //记录分销收益
  494. TConsumptionLog tConsumptionLog = new TConsumptionLog();
  495. tConsumptionLog.setAmount(up);
  496. tConsumptionLog.setBillNo(orderNew.getOrderNo());
  497. tConsumptionLog.setOpenId(jsUp.getcOpenid());
  498. tConsumptionLog.setBillType(BillTypeEnum.DISTRIBUTION.getCode());
  499. tConsumptionLog.setNote("分销收益");
  500. consumptionLogService.save(tConsumptionLog);
  501. }
  502. /**
  503. * 取消订单
  504. *
  505. * @param order
  506. * @return
  507. */
  508. @Override
  509. @Transactional(rollbackFor = Exception.class)
  510. public Boolean cancle(TOrder order) {
  511. // 获取订单信息
  512. // 根据orderid查询订单信息
  513. TOrder orderNew = getById(order.getcId());
  514. //待接单
  515. if (Objects.equals(orderNew.getnStatus(), OrderStatusEnum.WAIT_JD.getCode())) {
  516. TWxUser user = wxUserService.getByOpenId(orderNew.getcOpenId());
  517. // 更新用户金额 及下单此时
  518. TWxUser paramUser = new TWxUser();
  519. paramUser.setId(user.getId());
  520. paramUser.setcOpenid(user.getcOpenid());
  521. if (orderNew.getPayType() == 2) {
  522. // 金额归还对应账户
  523. paramUser.setdBalance(user.getdBalance().add(orderNew.getTotalPrice()));
  524. } else {
  525. // 微信支付
  526. // 生成退款单退款
  527. RefundVoucher refundVoucher = new RefundVoucher();
  528. refundVoucher.setRefundNo(generator.generateNextOrderNumber(OrderNumberGenerator.KEY_PREFIX_REFUND));
  529. refundVoucher.setOrderNo(orderNew.getOrderNo());
  530. refundVoucher.setMoney(orderNew.getTotalPrice());
  531. refundVoucher.setOpenId(orderNew.getcOpenId());
  532. refundVoucher.setReStatus(MassageConstants.INTEGER_ZERO);
  533. refundVoucher.setReason("技师拒绝接单");
  534. refundVoucherService.save(refundVoucher);
  535. // 微信退款原路返回
  536. rechargeService.refund(refundVoucher.getRefundNo(), null, orderNew.getOrderNo(), orderNew.getTotalPrice());
  537. }
  538. // 消费金额对应减少
  539. paramUser.setdMoney(user.getdMoney().subtract(orderNew.getTotalPrice()));
  540. // 下单次数减一
  541. paramUser.setnNum(user.getnNum() - MassageConstants.INTEGER_ONE);
  542. wxUserService.updateById(paramUser);
  543. // 更新项目数据
  544. JSONArray objects = orderNew.getcGoods();
  545. objects.forEach(item -> {
  546. UpdateWrapper<TXiangmu> wrapper = new UpdateWrapper<>();
  547. // 获取参数
  548. wrapper.lambda().eq(TXiangmu::getcId, ((JSONObject) item).getString("cId"));
  549. // 设置数量
  550. wrapper.setSql(" n_sale_number = n_sale_number - " + ((JSONObject) item).getInteger("number"));
  551. xiangmuService.update(wrapper);
  552. });
  553. TOrder orderParam = new TOrder();
  554. orderParam.setcId(orderNew.getcId());
  555. orderParam.setnStatus(OrderStatusEnum.CANCEL.getCode());
  556. //更新技师状态
  557. TJs tJs = new TJs();
  558. tJs.setId(orderNew.getcJsId());
  559. tJs.setnStatus(JsStatusEnum.JS_SERVICEABLE.getCode());
  560. jsService.updateById(tJs);
  561. return updateById(orderParam);
  562. } else if (Objects.equals(orderNew.getnStatus(), OrderStatusEnum.WAIT_PAY.getCode())) {
  563. //待付款
  564. TOrder orderParam = new TOrder();
  565. orderParam.setcId(orderNew.getcId());
  566. orderParam.setnStatus(OrderStatusEnum.CANCEL.getCode());
  567. return updateById(orderParam);
  568. } else {
  569. return false;
  570. }
  571. }
  572. @Override
  573. public TOrder getByNo(String orderNo) {
  574. LambdaQueryWrapper<TOrder> objectLambdaQueryWrapper = new LambdaQueryWrapper<>();
  575. return this.getOne(objectLambdaQueryWrapper.eq(TOrder::getOrderNo, orderNo));
  576. }
  577. private TOrder gettOrder(TOrder order) {
  578. LambdaUpdateWrapper<TOrder> objectLambdaUpdateWrapper = new LambdaUpdateWrapper<>();
  579. objectLambdaUpdateWrapper.eq(TOrder::getOrderNo, order.getOrderNo());
  580. return this.getOne(objectLambdaUpdateWrapper);
  581. }
  582. @Override
  583. public Page<TOrder> getAll(Page<TOrder> page, TOrder param) {
  584. Page<TOrder> orderPage = orderMapper.getAll(page, param);
  585. if (orderPage != null && CollectionUtil.isNotEmpty(orderPage.getRecords())) {
  586. ArrayList<TOrder> orders = Lists.newArrayList();
  587. orderPage.getRecords().forEach(order -> {
  588. order.setStatusName(OrderStatusEnum.getDescByCode(order.getnStatus()));
  589. order.setJsPhone(order.getJs().getcPhone());
  590. order.setJsName(order.getJs().getcName());
  591. if (StringUtils.isEmpty(order.getcTime())) {
  592. order.setRemainingTime(0L);
  593. }
  594. if (StringUtils.isNotBlank(order.getcTime()) && DateTimeUtils.dateStringToStamp(order.getcTime()) > DateTimeUtils.dateToStamp(new Date())) {
  595. order.setRemainingTime((DateTimeUtils.dateStringToStamp(order.getcTime()) - DateTimeUtils.dateToStamp(new Date())) / 1000);
  596. }
  597. if (StringUtils.isNotBlank(order.getcTime()) && DateTimeUtils.dateStringToStamp(order.getcTime()) < DateTimeUtils.dateToStamp(new Date())) {
  598. order.setRemainingTime(0L);
  599. }
  600. orders.add(order);
  601. });
  602. orderPage.setRecords(orders);
  603. }
  604. return orderPage;
  605. }
  606. @Override
  607. @Transactional(rollbackFor = Exception.class)
  608. public void takingOrders(TOrder order) {
  609. if (order == null || StringUtils.isBlank(order.getcId())) {
  610. throw new IllegalArgumentException("订单对象不能为空");
  611. }
  612. TOrder orderNew = this.getById(order);
  613. // 检查订单对应的技师是否存在
  614. // updateJs (orderNew);
  615. // 更新订单状态
  616. TOrder orderParam = new TOrder();
  617. orderParam.setcId(order.getcId());
  618. orderParam.setnStatus(OrderStatusEnum.RECEIVED_ORDER.getCode());
  619. orderParam.setAcceptanceTime(LocalDateTime.now());
  620. this.updateById(orderParam);
  621. }
  622. private void updateJs(TOrder orderNew) {
  623. TJs js = jsService.getById(orderNew.getcJsId());
  624. if (js == null) {
  625. throw new IllegalStateException("无法找到对应的技师");
  626. }
  627. if (Objects.equals(js.getnStatus(), JsStatusEnum.JS_SERVICEABLE.getCode())) {
  628. // 更新技师状态
  629. js.setnStatus(JsStatusEnum.JS_SERVICE.getCode());
  630. // 确保js.getnNum()不为null,避免 NullPointerException
  631. int num = js.getnNum() == null ? 0 : js.getnNum();
  632. js.setnNum(num + MassageConstants.INTEGER_ONE);
  633. } else {
  634. // 更新技师状态
  635. js.setnStatus(JsStatusEnum.JS_SERVICEABLE.getCode());
  636. // 确保js.getnNum()不为null,避免 NullPointerException
  637. int num = js.getnNum() == null ? 0 : js.getnNum();
  638. js.setnNum(num - MassageConstants.INTEGER_ONE);
  639. }
  640. jsService.updateById(js);
  641. }
  642. }