UserOrderController.java 26 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606
  1. package com.ruoyi.app.order;
  2. import com.alibaba.fastjson.JSON;
  3. import com.alibaba.fastjson.JSONArray;
  4. import com.alibaba.fastjson.JSONObject;
  5. import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
  6. import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
  7. import com.ruoyi.app.order.dto.OrderCreateInput;
  8. import com.ruoyi.app.order.dto.OrderCreatItem;
  9. import com.ruoyi.app.order.dto.OrderPushBodyDto;
  10. import com.ruoyi.app.utils.DateUtil;
  11. import com.ruoyi.app.utils.OperatingUtil;
  12. import com.ruoyi.app.utils.PayPush;
  13. import com.ruoyi.app.utils.event.PushEventService;
  14. import com.ruoyi.common.annotation.Anonymous;
  15. import com.ruoyi.common.core.controller.BaseController;
  16. import com.ruoyi.common.core.domain.AjaxResult;
  17. import com.ruoyi.common.core.page.TableDataInfo;
  18. import com.ruoyi.common.exception.ServiceException;
  19. import com.ruoyi.common.utils.MessageUtils;
  20. import com.ruoyi.common.utils.StringUtils;
  21. import com.ruoyi.framework.manager.AsyncManager;
  22. import com.ruoyi.system.domain.*;
  23. import com.ruoyi.system.mapper.PosOrderPromotionMapper;
  24. import com.ruoyi.system.service.*;
  25. import com.ruoyi.system.utils.Auth;
  26. import com.ruoyi.system.utils.GetArea;
  27. import com.ruoyi.system.utils.JwtUtil;
  28. import com.ruoyi.system.utils.OrderLogHelper;
  29. import com.ruoyi.system.dto.PromotionCalcResponse;
  30. import com.ruoyi.system.domain.dto.ApplyInvoiceDto;
  31. import jakarta.validation.Valid;
  32. import org.springframework.web.bind.annotation.*;
  33. import org.springframework.beans.factory.annotation.Autowired;
  34. import org.springframework.transaction.annotation.Transactional;
  35. import java.text.SimpleDateFormat;
  36. import java.util.Date;
  37. import java.util.List;
  38. import java.util.Optional;
  39. import java.util.TimerTask;
  40. import java.util.stream.Collectors;
  41. /**
  42. * 用户订单Controller
  43. *
  44. * @author ruoyi
  45. * @date 2020-04-01
  46. */
  47. @RestController
  48. @RequestMapping("/system/userOrder")
  49. public class UserOrderController extends BaseController {
  50. @Autowired
  51. private IOrderParentService orderParentService;
  52. @Autowired
  53. private IPosOrderService posOrderService;
  54. @Autowired
  55. private IPosStoreService posStoreService;
  56. @Autowired
  57. private IInfoAddressService infoAddressService;
  58. @Autowired
  59. private IOperatingHoursService operatingHoursService;
  60. @Autowired
  61. private IUserFootprintService userFootprintService;
  62. @Autowired
  63. private IInfoUserService infoUserService;
  64. @Autowired
  65. private PushEventService pushEventService;
  66. @Autowired
  67. private OrderLogHelper orderLogHelper;
  68. @Autowired
  69. private OrderPromotionHelper orderPromotionHelper;
  70. @Autowired
  71. private PosOrderPromotionMapper posOrderPromotionMapper;
  72. @Autowired
  73. private OrderInvoiceService orderInvoiceService;
  74. /**
  75. * 申请电子发票(订单完成后,客户主动申请:B2C 邮箱 / B2B 统编 / 载具)
  76. */
  77. @PostMapping("/applyInvoice")
  78. @Auth
  79. @Anonymous
  80. public AjaxResult applyInvoice(@RequestHeader String token, @RequestBody @Valid ApplyInvoiceDto dto) {
  81. Long userId = Long.valueOf(new JwtUtil().getusid(token));
  82. return AjaxResult.success(orderInvoiceService.applyInvoice(dto, userId));
  83. }
  84. /**
  85. * 查询订单电子发票(状态 / 发票号 / 凭证);门店不可开票时 invoiceStatus=null
  86. */
  87. @GetMapping("/getInvoice")
  88. @Auth
  89. @Anonymous
  90. public AjaxResult getInvoice(@RequestHeader String token, @RequestParam Long orderId) {
  91. Long userId = Long.valueOf(new JwtUtil().getusid(token));
  92. return AjaxResult.success(orderInvoiceService.getInvoice(orderId, userId));
  93. }
  94. /**
  95. * 捐赠机构列表(客户端选择器,仅 enabled=1,按机构名/简称/捐赠码搜索;分页)
  96. */
  97. @GetMapping("/loveOrg/list")
  98. @Auth
  99. @Anonymous
  100. public TableDataInfo loveOrgList(@RequestHeader String token,
  101. @RequestParam(required = false) String keyword) {
  102. startPage();
  103. return getDataTable(orderInvoiceService.listLoveOrg(keyword));
  104. }
  105. /**
  106. * 创建订单
  107. */
  108. @PostMapping("/createOrder")
  109. @Auth
  110. @Anonymous
  111. @Transactional(rollbackFor = Exception.class)
  112. public AjaxResult createOrder(@RequestHeader String token, @RequestBody OrderCreateInput input)
  113. {
  114. JwtUtil jwtUtil = new JwtUtil();
  115. String id = jwtUtil.getusid(token);
  116. String shdz=null;
  117. if(input.getType()==0){
  118. InfoAddress usadd = infoAddressService.getById(input.getShdzId());
  119. if (usadd == null) {
  120. throw new ServiceException(MessageUtils.message("no.address.not.exist"));
  121. }
  122. shdz= JSON.toJSONString(usadd);
  123. }
  124. createOrderParent(input,Long.valueOf(id),shdz);
  125. createOrderChild(input,Long.valueOf(id),Long.valueOf(id),shdz);
  126. OrderParent result = orderParentService.getOne(new LambdaQueryWrapper<OrderParent>().eq(OrderParent::getDdId, input.getDdId().toString()));
  127. System.out.println("创建返回信息:"+result);
  128. return super.success(result);
  129. }
  130. //创建父订单
  131. private void createOrderParent(OrderCreateInput input,Long UserId,String shdz){
  132. OrderParent orderParent = new OrderParent();
  133. orderParent.setUserId(UserId);
  134. orderParent.setOrderStatus(0L);
  135. orderParent.setTotalAmount(input.getTotalAmount());
  136. orderParent.setActualPayAmount(input.getActualPayAmount());
  137. orderParent.setPaymentMethod(input.getPaymentMethod());
  138. // orderParent.setPaymentTime(new Date());
  139. orderParent.setCreateTime(new Date());
  140. // orderParent.setUpdateTime(new Date());
  141. orderParent.setDdId(input.getDdId().toString());
  142. orderParent.setTableId(input.getTableId());
  143. orderParent.setShdzId(input.getShdzId());
  144. orderParent.setShAddress(shdz);
  145. orderParent.setType(input.getType());
  146. orderParent.setRemarks(input.getRemarks());
  147. orderParentService.save(orderParent);
  148. }
  149. //创建子订单
  150. private void createOrderChild(OrderCreateInput input,Long orderParentId,Long userId,String shdz){
  151. // 检查items是否为空
  152. if (input.getItems() == null || input.getItems().isEmpty()) {
  153. throw new ServiceException(MessageUtils.message("订单商品不能为空"));
  154. }
  155. String ddId = input.getDdId().toString();
  156. List<Long> mdIdList = input.getItems().stream().map(OrderCreatItem::getMdId).collect(Collectors.toList());
  157. // 将Long类型的门店ID转换为Integer类型用于查询(因为PosStore.getId()返回Integer)
  158. List<Integer> mdIdIntegerList = mdIdList.stream().map(Long::intValue).collect(Collectors.toList());
  159. List<PosStore> storeList = posStoreService.list(new LambdaQueryWrapper<PosStore>().in(PosStore::getId, mdIdIntegerList));
  160. LambdaQueryWrapper<OperatingHours> wrapper = new LambdaQueryWrapper<>();
  161. wrapper.in(OperatingHours::getMdId, mdIdList);
  162. List<OperatingHours> hourslist = operatingHoursService.list(wrapper);
  163. boolean isMultiStore = input.getItems().size() > 1;
  164. // 循环items,为每个item创建一条PosOrder
  165. int index = 0;
  166. for (OrderCreatItem item : input.getItems()) {
  167. // 检查门店是否开放
  168. checkStoreOpen(storeList,hourslist,item);
  169. index++;
  170. // 单店铺:子订单号与父订单一致;多店铺:子订单号追加序号
  171. String subddId = isMultiStore ? ddId + String.format("%03d", index) : ddId;
  172. PosOrder posOrder = new PosOrder();
  173. posOrder.setIsDisplay(false);
  174. handleIsDisplay(posOrder);
  175. posOrder.setShdzId(input.getShdzId());
  176. // 设置子订单的基本信息
  177. posOrder.setDdId(subddId);
  178. posOrder.setParentDdId(input.getDdId().toString()); // 设置父订单ID
  179. posOrder.setCretim(new Date());
  180. // 根据item设置订单信息
  181. posOrder.setShId(item.getShId());
  182. posOrder.setMdId(item.getMdId());
  183. posOrder.setShdzId(input.getShdzId());
  184. posOrder.setUserId(userId);
  185. posOrder.setAmount(item.getAmount());
  186. posOrder.setRemarks(item.getRemarks());
  187. posOrder.setType(item.getType());
  188. //外卖设置配送状态为
  189. if(0L==posOrder.getType()){
  190. posOrder.setDeliveryStatus(0L);
  191. }
  192. posOrder.setDelryTime(item.getDelryTime());
  193. posOrder.setFood(JSON.toJSONString(item.getFood()));
  194. if("1".equals(input.getPaymentMethod()) || "2".equals(input.getPaymentMethod())){
  195. posOrder.setCollectPayment("1");
  196. }
  197. // 设置支付相关信息(从父订单继承)
  198. posOrder.setPayType(input.getPaymentMethod());
  199. //设置桌号(从父订单继承)
  200. posOrder.setTableId(input.getTableId());
  201. posOrder.setTableNo(input.getTableNo());
  202. posOrder.setLogo(item.getLogo());
  203. posOrder.setPosName(item.getPosName());
  204. posOrder.setJvli(item.getJvli());
  205. posOrder.setFreight(item.getFreight());
  206. posOrder.setShdzId(input.getShdzId());
  207. posOrder.setShAddress(shdz);
  208. posOrder.setFoodAmount(item.getFoodAmount());
  209. posOrder.setPickUpTime(input.getPickUpTime());
  210. posOrder.setReservePhone(input.getReservePhone());
  211. // 新状态字段初始化
  212. // 堂食订单(type=2)自动接单,跳过商家确认
  213. if (item.getType() != null && item.getType() == 2) {
  214. posOrder.setState(1L);
  215. } else {
  216. posOrder.setState(0L);
  217. }
  218. posOrder.setAfterSaleStatus(0L);
  219. posOrder.setDeliveryStatus(null);
  220. // 外送到付(payType=1):payStatus=1;其他:payStatus=0
  221. if (item.getType() != null && item.getType() == 0 && "1".equals(input.getPaymentMethod())) {
  222. posOrder.setPayStatus(1L);
  223. } else {
  224. posOrder.setPayStatus(0L);
  225. }
  226. Optional<PosStore> storeOptional = storeList.stream()
  227. .filter(x -> item.getMdId().equals(Long.valueOf(x.getId())))
  228. .findFirst();
  229. if (storeOptional.isEmpty()) {
  230. throw new ServiceException(MessageUtils.message("no.mendian.not.exist"));
  231. }
  232. PosStore store = storeOptional.get();
  233. posOrder.setLongitude(store.getLongitude());
  234. posOrder.setLatitude(store.getLatitude());
  235. //设置订单分类
  236. storeList.stream().filter(s -> Long.valueOf(s.getId()).equals(item.getMdId())).findFirst().ifPresent(st -> {
  237. posOrder.setOrderCategory(String.valueOf(st.getType()));
  238. });
  239. // 保存子订单
  240. // --- 促销:算价 + 校验 + 回填优惠字段(save之前) ---
  241. PromotionCalcResponse calc = orderPromotionHelper.calcPromotion(item, userId);
  242. orderPromotionHelper.validatePromotionAmount(calc, item.getPromoReduceAmount());
  243. orderPromotionHelper.fillPromotionFields(posOrder, calc);
  244. createFootprint(userId, item.getMdId());
  245. setPickUpNum(posOrder);
  246. posOrderService.save(posOrder);
  247. // --- 促销:写入快照 + 标记券已使用(save之后,需要posOrder.id) ---
  248. if (calc != null) {
  249. orderPromotionHelper.savePromotionSnapshots(posOrder.getId(), calc);
  250. if (calc.getCouponId() != null) {
  251. orderPromotionHelper.markCouponUsed(calc.getCouponId(), posOrder.getId(), userId);
  252. }
  253. }
  254. // 创建订单成功,添加操作日志
  255. InfoUser uUser = infoUserService.getOne(new LambdaQueryWrapper<InfoUser>().eq(InfoUser::getUserId, userId));
  256. String uName = uUser != null ? uUser.getNickName() : "";
  257. orderLogHelper.log(subddId, 4, userId, uName, "用户" + uName + "创建订单");
  258. // 创建订单成功,给商家推送"您有新订单了"
  259. InfoUser shUser = infoUserService.getById(item.getShId());
  260. if (shUser != null && !StringUtils.isEmpty(shUser.getCid())) {
  261. PayPush push = new PayPush();
  262. String title = "no.message.push.message";
  263. String content = "no.message.push.new.order";
  264. String body = OrderPushBodyDto.getJson(subddId, String.valueOf(posOrder.getState()), 0);
  265. Long shUserId = shUser.getUserId();
  266. String cid = shUser.getCid();
  267. AsyncManager.me().execute(new TimerTask() {
  268. @Override
  269. public void run() {
  270. PayPush.shPushHandleLocal(push, pushEventService, shUserId, cid, title, content, body, "", subddId);
  271. }
  272. });
  273. }
  274. }
  275. }
  276. //生成取餐码,根据门店id,当天取餐码从1开始累加
  277. private void setPickUpNum(PosOrder order) {
  278. if (order == null || order.getMdId() == null) {
  279. return;
  280. }
  281. try {
  282. // 获取当前日期,格式为 yyyy-MM-dd
  283. SimpleDateFormat dateFormat = new SimpleDateFormat("yyyy-MM-dd");
  284. String today = dateFormat.format(new Date());
  285. // 查询当天该门店的最大取餐码
  286. LambdaQueryWrapper<PosOrder> queryWrapper = new LambdaQueryWrapper<>();
  287. queryWrapper.eq(PosOrder::getMdId, order.getMdId());
  288. queryWrapper.like(PosOrder::getCretim, today);
  289. queryWrapper.orderByDesc(PosOrder::getPickUpNum);
  290. queryWrapper.last("LIMIT 1");
  291. PosOrder lastOrder = posOrderService.getOne(queryWrapper);
  292. long nextNum = 1L;
  293. if (lastOrder != null && lastOrder.getPickUpNum() != null) {
  294. // 直接使用Long类型的取餐码
  295. nextNum = lastOrder.getPickUpNum() + 1;
  296. }
  297. // 生成新的取餐码:直接使用Long数字
  298. order.setPickUpNum(nextNum);
  299. logger.info("生成取餐码成功:门店ID={}, 取餐码={}", order.getMdId(), nextNum);
  300. } catch (Exception e) {
  301. logger.error("生成取餐码失败:门店ID={}, 错误信息={}", order.getMdId(), e.getMessage(), e);
  302. // 生成失败时使用时间戳作为备用方案
  303. Long fallbackPickUpNum = System.currentTimeMillis() % 10000;
  304. order.setPickUpNum(fallbackPickUpNum);
  305. }
  306. }
  307. //设置显示状态
  308. private void handleIsDisplay(PosOrder posOrder){
  309. if (StringUtils.isEmpty(posOrder.getDelryTime())) {
  310. posOrder.setIsDisplay(true);
  311. posOrder.setDisplayTime(new Date());
  312. }
  313. //预约单不在时间范围内不显示
  314. if (StringUtils.isNotEmpty(posOrder.getDelryTime())) {
  315. int minute = DateUtil.getAppoinmentOrderHandleTime();
  316. boolean isNear = DateUtil.isNearOrPastStartTime(posOrder.getDelryTime(), minute);
  317. if (isNear) {
  318. posOrder.setIsDisplay(true);
  319. posOrder.setDisplayTime(new Date());
  320. }
  321. }
  322. }
  323. private void createFootprint(Long uid,Long mdId){
  324. QueryWrapper<UserFootprint> Wrapper = new QueryWrapper<>();
  325. Wrapper.eq("user_id", uid);
  326. Wrapper.eq("md_id", mdId);
  327. UserFootprint foot = userFootprintService.getOne(Wrapper);
  328. DateUtil dateString = new DateUtil();
  329. if (foot == null) {
  330. UserFootprint usf = new UserFootprint();
  331. usf.setUserId(uid);
  332. usf.setMdId(mdId);
  333. usf.setCretim(dateString.GetDate());
  334. userFootprintService.saveOrUpdate(usf);
  335. } else {
  336. foot.setCretim(dateString.GetDate());
  337. userFootprintService.saveOrUpdate(foot);
  338. }
  339. }
  340. /**
  341. * 检查门店是否开放
  342. */
  343. private void checkStoreOpen( List<PosStore> storeList,List<OperatingHours> hourslist, OrderCreatItem item) {
  344. List<OperatingHours> storeHourslist = hourslist.stream().filter(x-> x.getMdId().equals(item.getMdId())).collect(Collectors.toList());
  345. PosStore store = storeList.stream()
  346. .filter(x -> Long.valueOf(x.getId()).equals(item.getMdId()))
  347. .findFirst()
  348. .orElseThrow(() -> new ServiceException(MessageUtils.message("no.mendian.not.exist")));
  349. if (storeHourslist.isEmpty()) {
  350. throw new ServiceException(store.getPosName()+MessageUtils.message("no.mendian.not.set.business.hours"));
  351. }
  352. if (store.getState() == 1) {
  353. throw new ServiceException(store.getPosName()+MessageUtils.message("no.mendian.is.closed"));
  354. }
  355. boolean isOperating = OperatingUtil.storeIsOperatingOfDay(storeHourslist);
  356. if (!isOperating) {
  357. throw new ServiceException(store.getPosName()+MessageUtils.message("no.mendian.is.closed"));
  358. }
  359. }
  360. /**
  361. * 获取父订单详情
  362. */
  363. @GetMapping("/getParentOrderDetail")
  364. @Auth
  365. @Anonymous
  366. public AjaxResult getParentOrderDetail(@RequestHeader String token, @RequestParam String ddId){
  367. OrderParent result = orderParentService.getOne(new LambdaQueryWrapper<OrderParent>().eq(OrderParent::getDdId,ddId));
  368. List<PosOrder> posOrders = posOrderService.list(new LambdaQueryWrapper<PosOrder>().eq(PosOrder::getParentDdId,ddId).orderBy(true,true,PosOrder::getCretim));
  369. result.setItems(posOrders);
  370. // 转为JSONObject以追加非实体字段(promotions)
  371. JSONObject org = JSON.parseObject(JSON.toJSONStringWithDateFormat(result, "yyyy-MM-dd HH:mm:ss"));
  372. JSONArray items = org.getJSONArray("items");
  373. if (items != null) {
  374. for (int i = 0; i < items.size(); i++) {
  375. JSONObject item = items.getJSONObject(i);
  376. Long orderId = item.getLong("id");
  377. List<PosOrderPromotion> promotions = posOrderPromotionMapper.selectByOrderId(orderId);
  378. item.put("promotions", promotions);
  379. }
  380. }
  381. return super.success(org);
  382. }
  383. /**
  384. * 计算两个经纬度之间的距离
  385. */
  386. @GetMapping("/getDistance")
  387. @Anonymous
  388. public AjaxResult getDistance(@RequestParam Double lat1, @RequestParam Double lng1,
  389. @RequestParam Double lat2, @RequestParam Double lng2) {
  390. double distance = GetArea.getDistance(lat1, lng1, lat2, lng2);
  391. return success(distance);
  392. }
  393. /**
  394. * 用户端订单列表(Tab分页)
  395. */
  396. @GetMapping("/orderList")
  397. @Auth
  398. @Anonymous
  399. public AjaxResult orderList(@RequestHeader String token,
  400. @RequestParam(defaultValue = "1") int page,
  401. @RequestParam(defaultValue = "10") int size,
  402. @RequestParam(required = false) String tab,
  403. @RequestParam(required = false) String type) {
  404. JwtUtil jwtUtil = new JwtUtil();
  405. String userId = jwtUtil.getusid(token);
  406. LambdaQueryWrapper<PosOrder> wrapper = new LambdaQueryWrapper<>();
  407. wrapper.eq(PosOrder::getUserId, Long.valueOf(userId));
  408. // 类型筛选
  409. if (type != null && !type.isEmpty()) {
  410. wrapper.eq(PosOrder::getType, Long.valueOf(type));
  411. }
  412. switch (tab) {
  413. case "unpaid":
  414. wrapper.eq(PosOrder::getPayStatus, 0L).eq(PosOrder::getType, 0L);
  415. break;
  416. case "active":
  417. wrapper.in(PosOrder::getState, 0L, 1L, 2L)
  418. .eq(PosOrder::getAfterSaleStatus, 0L)
  419. .and(w -> w.eq(PosOrder::getPayStatus, 1L).or().in(PosOrder::getType, 1L, 2L));
  420. break;
  421. case "completed":
  422. wrapper.eq(PosOrder::getState, 3L).eq(PosOrder::getAfterSaleStatus, 0L);
  423. break;
  424. case "cancelled":
  425. wrapper.eq(PosOrder::getState, 4L).eq(PosOrder::getAfterSaleStatus, 0L);
  426. break;
  427. case "refund":
  428. wrapper.gt(PosOrder::getAfterSaleStatus, 0L);
  429. break;
  430. default:
  431. break;
  432. }
  433. wrapper.orderByDesc(PosOrder::getCretim);
  434. // 分页
  435. com.baomidou.mybatisplus.extension.plugins.pagination.Page<PosOrder> pageParam =
  436. new com.baomidou.mybatisplus.extension.plugins.pagination.Page<>(page, size);
  437. com.baomidou.mybatisplus.extension.plugins.pagination.Page<PosOrder> result = posOrderService.page(pageParam, wrapper);
  438. // 附加关联数据
  439. for (PosOrder order : result.getRecords()) {
  440. enrichOrderData(order);
  441. }
  442. java.util.Map<String, Object> data = new java.util.LinkedHashMap<>();
  443. data.put("records", result.getRecords());
  444. data.put("total", result.getTotal());
  445. data.put("page", page);
  446. data.put("size", size);
  447. return success(result);
  448. }
  449. private void enrichOrderData(PosOrder order) {
  450. try {
  451. if (order.getShId() != null) {
  452. InfoUser shanghu = infoUserService.getById(order.getShId());
  453. order.setPriceAll(shanghu != null ? String.valueOf(shanghu.getNickName()) : null);
  454. }
  455. } catch (Exception ignored) {}
  456. }
  457. /**
  458. * 确认取餐(自取类型订单,state=2 → state=3)
  459. */
  460. @Transactional(rollbackFor = Exception.class)
  461. @GetMapping("/confirmPickup")
  462. @Auth
  463. @Anonymous
  464. public AjaxResult confirmPickup(@RequestHeader String token, @RequestParam Long id) {
  465. JwtUtil jwtUtil = new JwtUtil();
  466. String userId = jwtUtil.getusid(token);
  467. PosOrder order = posOrderService.getOne(
  468. new LambdaQueryWrapper<PosOrder>()
  469. .eq(PosOrder::getId, id)
  470. .eq(PosOrder::getUserId, Long.valueOf(userId))
  471. );
  472. if (order == null) {
  473. return error("订单不存在");
  474. }
  475. if (order.getType() == null || order.getType() != 1) {
  476. return error("仅自取订单可确认取餐");
  477. }
  478. if (order.getState() == null || order.getState() != 2) {
  479. return error("当前订单状态不可确认取餐");
  480. }
  481. if (order.getPayStatus() == null || order.getPayStatus() != 1) {
  482. return error("订单未支付,不可确认取餐");
  483. }
  484. if (order.getAfterSaleStatus() != null && order.getAfterSaleStatus() > 0) {
  485. return error("订单存在售后处理中,不可确认取餐");
  486. }
  487. order.setState(3L);
  488. posOrderService.updateById(order);
  489. // 确认取餐成功,添加操作日志
  490. InfoUser uUser = infoUserService.getOne(new LambdaQueryWrapper<InfoUser>().eq(InfoUser::getUserId, Long.valueOf(userId)));
  491. String uName = uUser != null ? uUser.getNickName() : "";
  492. orderLogHelper.log(String.valueOf(order.getDdId()), 4, Long.valueOf(userId), uName, "用户" + uName + "确认取餐");
  493. return success("确认取餐成功");
  494. }
  495. /**
  496. * 用户确认完成外送订单(骑手已送达后,state=2 → state=3)
  497. */
  498. @Transactional(rollbackFor = Exception.class)
  499. @GetMapping("/confirmDelivery")
  500. @Auth
  501. @Anonymous
  502. public AjaxResult confirmDelivery(@RequestHeader String token, @RequestParam Long id) {
  503. JwtUtil jwtUtil = new JwtUtil();
  504. String userId = jwtUtil.getusid(token);
  505. PosOrder order = posOrderService.getOne(
  506. new LambdaQueryWrapper<PosOrder>()
  507. .eq(PosOrder::getId, id)
  508. .eq(PosOrder::getUserId, Long.valueOf(userId))
  509. );
  510. if (order == null) {
  511. return error("订单不存在");
  512. }
  513. if (order.getState() == null || order.getState() != 2L) {
  514. return error("当前订单状态不可确认完成");
  515. }
  516. if (order.getDeliveryStatus() == null || order.getDeliveryStatus() != 3L) {
  517. return error("骑手尚未送达,不可确认完成");
  518. }
  519. if (order.getAfterSaleStatus() != null && order.getAfterSaleStatus() > 0) {
  520. return error("订单存在售后处理中,不可确认完成");
  521. }
  522. PosOrder update = new PosOrder();
  523. update.setId(order.getId());
  524. update.setState(3L);
  525. posOrderService.updateById(update);
  526. // 用户确认完成,添加操作日志
  527. InfoUser uUser = infoUserService.getOne(new LambdaQueryWrapper<InfoUser>().eq(InfoUser::getUserId, Long.valueOf(userId)));
  528. String uName = uUser != null ? uUser.getNickName() : "";
  529. orderLogHelper.log(String.valueOf(order.getDdId()), 4, Long.valueOf(userId), uName, "用户" + uName + "确认完成订单");
  530. return success("确认完成成功");
  531. }
  532. /**
  533. * 取消订单(未接单前,state=0 → state=4)
  534. */
  535. @GetMapping("/cancelOrder")
  536. @Auth
  537. @Anonymous
  538. public AjaxResult cancelOrder(@RequestHeader String token, @RequestParam Long id) {
  539. JwtUtil jwtUtil = new JwtUtil();
  540. String userId = jwtUtil.getusid(token);
  541. PosOrder order = posOrderService.getOne(
  542. new LambdaQueryWrapper<PosOrder>()
  543. .eq(PosOrder::getId, id)
  544. .eq(PosOrder::getUserId, Long.valueOf(userId))
  545. );
  546. if (order == null) {
  547. return error("订单不存在");
  548. }
  549. if (order.getState() == null || order.getState() != 0) {
  550. return error("仅待处理状态的订单可取消");
  551. }
  552. order.setState(4L);
  553. posOrderService.updateById(order);
  554. // 取消订单成功,添加操作日志
  555. InfoUser uUser = infoUserService.getOne(new LambdaQueryWrapper<InfoUser>().eq(InfoUser::getUserId, Long.valueOf(userId)));
  556. String uName = uUser != null ? uUser.getNickName() : "";
  557. orderLogHelper.log(String.valueOf(order.getDdId()), 4, Long.valueOf(userId), uName, "用户" + uName + "取消订单");
  558. return success("取消订单成功");
  559. }
  560. }