TOrderServiceImpl.java 37 KB

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