HotelOrderServiceImpl.java 52 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054105510561057105810591060106110621063106410651066106710681069107010711072107310741075107610771078107910801081108210831084108510861087108810891090109110921093109410951096109710981099110011011102110311041105110611071108110911101111111211131114111511161117111811191120112111221123112411251126112711281129113011311132113311341135113611371138113911401141114211431144114511461147114811491150115111521153115411551156115711581159116011611162116311641165116611671168116911701171117211731174117511761177117811791180
  1. package com.chuanghai.ihotel.service.impl;
  2. import com.alibaba.excel.EasyExcel;
  3. import com.alibaba.excel.ExcelWriter;
  4. import com.alibaba.excel.write.metadata.WriteSheet;
  5. import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
  6. import com.baomidou.mybatisplus.core.conditions.update.UpdateWrapper;
  7. import com.baomidou.mybatisplus.core.metadata.IPage;
  8. import com.baomidou.mybatisplus.core.toolkit.IdWorker;
  9. import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
  10. import com.chuanghai.ihotel.aop.LoginCheckAspect;
  11. import com.chuanghai.ihotel.common.exception.BizCodeEnume;
  12. import com.chuanghai.ihotel.common.exception.RRException;
  13. import com.chuanghai.ihotel.common.utils.MyQuery;
  14. import com.chuanghai.ihotel.common.utils.PageParam;
  15. import com.chuanghai.ihotel.common.utils.PageUtils;
  16. import com.chuanghai.ihotel.component.PayComponent;
  17. import com.chuanghai.ihotel.component.WaterElectricComponent;
  18. import com.chuanghai.ihotel.component.WeiXiaoComponent;
  19. import com.chuanghai.ihotel.config.JXNXSPayConfig;
  20. import com.chuanghai.ihotel.config.RabbitMQConfig;
  21. import com.chuanghai.ihotel.constant.TimeConstant;
  22. import com.chuanghai.ihotel.controller.request.ConfrimOrderRequest;
  23. import com.chuanghai.ihotel.controller.request.OrderQueryRequest;
  24. import com.chuanghai.ihotel.controller.request.StatisticalReportRequest;
  25. import com.chuanghai.ihotel.controller.request.SubmitOrderRequest;
  26. import com.chuanghai.ihotel.dao.HotelOrderDao;
  27. import com.chuanghai.ihotel.dto.*;
  28. import com.chuanghai.ihotel.entity.*;
  29. import com.chuanghai.ihotel.enums.*;
  30. import com.chuanghai.ihotel.service.*;
  31. import com.chuanghai.ihotel.util.CellStyleModel;
  32. import com.chuanghai.ihotel.util.CommonUtil;
  33. import com.chuanghai.ihotel.util.FiledUtil;
  34. import com.chuanghai.ihotel.vo.*;
  35. import lombok.extern.slf4j.Slf4j;
  36. import org.apache.poi.ss.usermodel.*;
  37. import org.apache.xmlbeans.impl.piccolo.util.DuplicateKeyException;
  38. import org.springframework.amqp.rabbit.core.RabbitTemplate;
  39. import org.springframework.beans.BeanUtils;
  40. import org.springframework.beans.factory.annotation.Autowired;
  41. import org.springframework.stereotype.Service;
  42. import org.springframework.transaction.annotation.Transactional;
  43. import org.springframework.util.StringUtils;
  44. import javax.servlet.http.HttpServletResponse;
  45. import java.math.BigDecimal;
  46. import java.net.URLEncoder;
  47. import java.sql.SQLIntegrityConstraintViolationException;
  48. import java.text.SimpleDateFormat;
  49. import java.time.LocalDate;
  50. import java.time.LocalDateTime;
  51. import java.time.LocalTime;
  52. import java.time.format.DateTimeFormatter;
  53. import java.time.temporal.ChronoUnit;
  54. import java.time.temporal.TemporalAdjusters;
  55. import java.util.*;
  56. import java.util.stream.Collectors;
  57. @Slf4j
  58. @Service("hotelOrderService")
  59. public class HotelOrderServiceImpl extends ServiceImpl<HotelOrderDao, HotelOrderEntity> implements HotelOrderService {
  60. @Autowired
  61. private SystemSettingService systemSettingService;
  62. @Autowired
  63. private RoomTypeService roomTypeService;
  64. @Autowired
  65. private RoomRealtimeStatuService roomRealtimeStatuService;
  66. @Autowired
  67. private HotelUserService hotelUserService;
  68. @Autowired
  69. private RoomService roomService;
  70. @Autowired
  71. private HotelOrderBillService orderBillService;
  72. @Autowired
  73. private RoomDoorLockDataService doorLockService;
  74. @Autowired
  75. private RoomDoorLockDataService roomDoorLockDataService;
  76. @Autowired
  77. private SystemNoticeService systemNoticeService;
  78. @Autowired
  79. private RoomThirdSettingService roomThirdSettingService;
  80. @Autowired
  81. private PayComponent payComponent;
  82. @Autowired
  83. private WeiXiaoComponent weiXiaoComponent;
  84. @Autowired
  85. WaterElectricComponent waterElectricComponent;
  86. @Autowired
  87. private JXNXSPayConfig jxnxsPayConfig;
  88. @Autowired
  89. private RabbitTemplate rabbitTemplate;
  90. @Autowired
  91. private RabbitMQConfig rabbitMQConfig;
  92. @Autowired
  93. private StatisticalReportService statisticalReportService;
  94. private DateTimeFormatter dtf = DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss");
  95. private String noticeTemplate = "办理入住成功,您的房号为【%s】,房间锁密码为:【%s】,密码有效时间为【%s】,请妥善保管,退房后密码自动失效。";
  96. @Override
  97. public PageUtils queryPage(PageParam pageParam, OrderQueryRequest request) {
  98. QueryWrapper<HotelOrderEntity> queryWrapper = new QueryWrapper<>();
  99. queryWrapper.eq(request.getOrderId() != null, "id", request.getOrderId());
  100. queryWrapper.eq(StringUtils.hasText(request.getDeleteFlag()), "delete_flag", request.getDeleteFlag());
  101. if (StringUtils.hasText(request.getKeyWord())) {
  102. queryWrapper.and(e -> e.like("order_no", request.getKeyWord()).or().like("room_no", request.getKeyWord()));
  103. }
  104. //queryWrapper.like(StringUtils.hasText(request.getOrderNo()), "order_no", request.getOrderNo());
  105. queryWrapper.eq(StringUtils.hasText(request.getUserFlag()), "user_flag", request.getUserFlag());
  106. queryWrapper.eq(StringUtils.hasText(request.getUserName()), "user_name", request.getUserName());
  107. queryWrapper.eq(StringUtils.hasText(request.getUserPhone()), "user_phone", request.getUserPhone());
  108. queryWrapper.eq(StringUtils.hasText(request.getRoomNo()), "room_no", request.getRoomNo());
  109. queryWrapper.eq(request.getRoomTypeId() != null, "room_type_id", request.getRoomTypeId());
  110. String statu = request.getStatu();
  111. if (StringUtils.hasText(statu)) {
  112. if (statu.contains("-")) {
  113. String[] split = statu.split("-");
  114. queryWrapper.eq("order_statu", split[0]);
  115. queryWrapper.eq("biz_statu", split[1]);
  116. } else {
  117. queryWrapper.eq("order_statu", statu);
  118. }
  119. }
  120. queryWrapper.ge(request.getEnableStartTime() != null, "enable_start_time", request.getEnableStartTime());
  121. queryWrapper.le(request.getEnableStartTime() != null, "enable_end_time", request.getEnableStartTime());
  122. queryWrapper.ge(request.getPayTime1() != null, "pay_time", request.getPayTime1());
  123. queryWrapper.le(request.getPayTime2() != null, "pay_time", request.getPayTime2());
  124. queryWrapper.ge(request.getCreateTime1() != null, "create_time", request.getCreateTime1());
  125. queryWrapper.le(request.getCreateTime2() != null, "create_time", request.getCreateTime2());
  126. IPage<HotelOrderEntity> page = this.page(
  127. new MyQuery<HotelOrderEntity>().getPage(pageParam),
  128. queryWrapper
  129. );
  130. return new PageUtils(page);
  131. }
  132. @Override
  133. public List<HotelOrderEntity> queryList(OrderQueryRequest request) {
  134. QueryWrapper<HotelOrderEntity> queryWrapper = new QueryWrapper<>();
  135. queryWrapper.eq(request.getOrderId() != null, "id", request.getOrderId());
  136. queryWrapper.eq(StringUtils.hasText(request.getDeleteFlag()), "delete_flag", request.getDeleteFlag());
  137. if (StringUtils.hasText(request.getKeyWord())) {
  138. queryWrapper.and(e -> e.like("order_no", request.getKeyWord()).or().like("room_no", request.getKeyWord()));
  139. }
  140. //queryWrapper.like(StringUtils.hasText(request.getOrderNo()), "order_no", request.getOrderNo());
  141. queryWrapper.eq(StringUtils.hasText(request.getUserFlag()), "user_flag", request.getUserFlag());
  142. queryWrapper.eq(StringUtils.hasText(request.getUserName()), "user_name", request.getUserName());
  143. queryWrapper.eq(StringUtils.hasText(request.getUserPhone()), "user_phone", request.getUserPhone());
  144. queryWrapper.eq(StringUtils.hasText(request.getRoomNo()), "room_no", request.getRoomNo());
  145. queryWrapper.eq(request.getRoomTypeId() != null, "room_type_id", request.getRoomTypeId());
  146. String statu = request.getStatu();
  147. if (StringUtils.hasText(statu)) {
  148. if (statu.contains("-")) {
  149. String[] split = statu.split("-");
  150. queryWrapper.eq("order_statu", split[0]);
  151. queryWrapper.eq("biz_statu", split[1]);
  152. } else {
  153. queryWrapper.eq("order_statu", statu);
  154. }
  155. }
  156. queryWrapper.ge(request.getEnableStartTime() != null, "enable_start_time", request.getEnableStartTime());
  157. queryWrapper.le(request.getEnableStartTime() != null, "enable_end_time", request.getEnableStartTime());
  158. queryWrapper.ge(request.getPayTime1() != null, "pay_time", request.getPayTime1());
  159. queryWrapper.le(request.getPayTime2() != null, "pay_time", request.getPayTime2());
  160. queryWrapper.ge(request.getCreateTime1() != null, "create_time", request.getCreateTime1());
  161. queryWrapper.le(request.getCreateTime2() != null, "create_time", request.getCreateTime2());
  162. List<HotelOrderEntity> list = this.list(queryWrapper);
  163. return list;
  164. }
  165. @Override
  166. public List<AdminOrderIndexVO> listForAdmin( OrderQueryRequest request) {
  167. request.setDeleteFlag("1"); // 1未删除
  168. List<HotelOrderEntity> orderList = this.queryList(request);
  169. Set<Long> ids = orderList.stream().map(order -> order.getId()).collect(Collectors.toSet());
  170. if (ids.size() > 0) {
  171. List<HotelOrderBillEntity> orderBillList = orderBillService.findByOrderIds(ids);
  172. Map<Long, HotelOrderBillEntity> orderBillMap = orderBillList.stream().collect(Collectors.toMap(HotelOrderBillEntity::getHotelOrderId, e -> e));
  173. List<AdminOrderIndexVO> voList = orderList.stream().map(order -> {
  174. AdminOrderIndexVO vo = new AdminOrderIndexVO();
  175. vo.setOrder(order);
  176. vo.setOrderBill(orderBillMap.get(order.getId()));
  177. return vo;
  178. }).collect(Collectors.toList());
  179. List<AdminOrderIndexVO> objectVOList = new ArrayList<>();
  180. voList.forEach(adminOrderIndexVO -> {
  181. BigDecimal waterPayment = BigDecimal.ZERO;
  182. BigDecimal electricPayment = BigDecimal.ZERO;
  183. BigDecimal totalPayment = BigDecimal.ZERO;
  184. //住房总押金 单价 * 天数
  185. int housDay = 0;
  186. HotelOrderEntity order = adminOrderIndexVO.getOrder();
  187. HotelOrderBillEntity orderBill = adminOrderIndexVO.getOrderBill();
  188. //电费计算
  189. String startOfElectric = this.check(orderBill, "startOfElectric");
  190. String endOfElectric = this.check(orderBill, "endOfElectric");
  191. String priceOfElectric = this.check(orderBill, "priceOfElectric");
  192. String calculateElectric = this.calculate(startOfElectric, endOfElectric, priceOfElectric);
  193. electricPayment = electricPayment.add(new BigDecimal(calculateElectric)).setScale(2, BigDecimal.ROUND_UP);
  194. //水费计算
  195. String startOfWater = this.check(orderBill, "startOfWater");
  196. String endOfWater = this.check(orderBill, "endOfWater");
  197. String priceOfWater = this.check(orderBill, "priceOfWater");
  198. String calculateWater = this.calculate(startOfWater, endOfWater, priceOfWater);
  199. waterPayment = waterPayment.add(new BigDecimal(calculateWater)).setScale(2, BigDecimal.ROUND_UP);
  200. //收款总计
  201. totalPayment = totalPayment.add(order.getPayAmount()).setScale(2, BigDecimal.ROUND_UP);
  202. housDay = order.getEnableEndTime().getDayOfMonth() - order.getEnableStartTime().getDayOfMonth();
  203. SystemSettingEntity systemSetting = systemSettingService.get();
  204. //住房总押金 单价 * 天数
  205. BigDecimal totalHousDeposit = systemSetting.getDeposit().multiply(new BigDecimal(housDay)).setScale(2, BigDecimal.ROUND_UP);
  206. adminOrderIndexVO.setAllOfElectricPayment(electricPayment);
  207. adminOrderIndexVO.setAllOfWaterAmount(waterPayment);
  208. adminOrderIndexVO.setAllOfReceiveAmount(totalHousDeposit);
  209. BigDecimal refundPayment = totalPayment.add(totalHousDeposit).subtract(electricPayment).subtract(waterPayment).setScale(2, BigDecimal.ROUND_UP);
  210. adminOrderIndexVO.setRefundPayment(refundPayment);
  211. objectVOList.add(adminOrderIndexVO);
  212. });
  213. return objectVOList;
  214. }
  215. return null;
  216. }
  217. @Override
  218. public PageUtils userOrderPage(PageParam pageParam, OrderQueryRequest request) {
  219. pageParam.setOrderField("create_time");
  220. pageParam.setOrder("desc");
  221. LoginUserDTO loginUserVO = LoginCheckAspect.threadLocal.get();
  222. request.setUserFlag(loginUserVO.getCardNumber());
  223. request.setDeleteFlag("1"); // 1未删除
  224. PageUtils pageUtils = this.queryPage(pageParam, request);
  225. List<HotelOrderEntity> list = pageUtils.getList();
  226. List<UserOrderIndexVO> collect = list.stream().map(e -> {
  227. UserOrderIndexVO vo = new UserOrderIndexVO();
  228. BeanUtils.copyProperties(e, vo);
  229. return vo;
  230. }).collect(Collectors.toList());
  231. pageUtils.setList(collect);
  232. return pageUtils;
  233. }
  234. @Override
  235. public PageUtils pageForAdmin(PageParam pageParam, OrderQueryRequest request) {
  236. pageParam.setOrderField("create_time");
  237. pageParam.setOrder("desc");
  238. request.setDeleteFlag("1"); // 1未删除
  239. PageUtils pageUtils = this.queryPage(pageParam, request);
  240. List<HotelOrderEntity> orderList = pageUtils.getList();
  241. Set<Long> ids = orderList.stream().map(order -> order.getId()).collect(Collectors.toSet());
  242. if (ids.size() > 0) {
  243. List<HotelOrderBillEntity> orderBillList = orderBillService.findByOrderIds(ids);
  244. Map<Long, HotelOrderBillEntity> orderBillMap = orderBillList.stream().collect(Collectors.toMap(HotelOrderBillEntity::getHotelOrderId, e -> e));
  245. List<AdminOrderIndexVO> voList = orderList.stream().map(order -> {
  246. AdminOrderIndexVO vo = new AdminOrderIndexVO();
  247. vo.setOrder(order);
  248. vo.setOrderBill(orderBillMap.get(order.getId()));
  249. return vo;
  250. }).collect(Collectors.toList());
  251. List<AdminOrderIndexVO> objectVOList = new ArrayList<>();
  252. voList.forEach(adminOrderIndexVO -> {
  253. BigDecimal waterPayment = BigDecimal.ZERO;
  254. BigDecimal electricPayment = BigDecimal.ZERO;
  255. BigDecimal totalPayment = BigDecimal.ZERO;
  256. //住房总押金 单价 * 天数
  257. int housDay = 0;
  258. HotelOrderEntity order = adminOrderIndexVO.getOrder();
  259. HotelOrderBillEntity orderBill = adminOrderIndexVO.getOrderBill();
  260. //电费计算
  261. String startOfElectric = this.check(orderBill, "startOfElectric");
  262. String endOfElectric = this.check(orderBill, "endOfElectric");
  263. String priceOfElectric = this.check(orderBill, "priceOfElectric");
  264. String calculateElectric = this.calculate(startOfElectric, endOfElectric, priceOfElectric);
  265. electricPayment = electricPayment.add(new BigDecimal(calculateElectric)).setScale(2, BigDecimal.ROUND_UP);
  266. //水费计算
  267. String startOfWater = this.check(orderBill, "startOfWater");
  268. String endOfWater = this.check(orderBill, "endOfWater");
  269. String priceOfWater = this.check(orderBill, "priceOfWater");
  270. String calculateWater = this.calculate(startOfWater, endOfWater, priceOfWater);
  271. waterPayment = waterPayment.add(new BigDecimal(calculateWater)).setScale(2, BigDecimal.ROUND_UP);
  272. //收款总计
  273. totalPayment = totalPayment.add(order.getPayAmount()).setScale(2, BigDecimal.ROUND_UP);
  274. housDay = order.getEnableEndTime().getDayOfMonth() - order.getEnableStartTime().getDayOfMonth();
  275. SystemSettingEntity systemSetting = systemSettingService.get();
  276. //住房总押金 单价 * 天数
  277. BigDecimal totalHousDeposit = systemSetting.getDeposit().multiply(new BigDecimal(housDay)).setScale(2, BigDecimal.ROUND_UP);
  278. adminOrderIndexVO.setAllOfElectricPayment(electricPayment);
  279. adminOrderIndexVO.setAllOfWaterAmount(waterPayment);
  280. adminOrderIndexVO.setAllOfReceiveAmount(totalHousDeposit);
  281. BigDecimal refundPayment = totalPayment.add(totalHousDeposit).subtract(electricPayment).subtract(waterPayment).setScale(2, BigDecimal.ROUND_UP);
  282. adminOrderIndexVO.setRefundPayment(refundPayment);
  283. objectVOList.add(adminOrderIndexVO);
  284. });
  285. pageUtils.setList(objectVOList);
  286. }
  287. return pageUtils;
  288. }
  289. /**
  290. * 导出订单
  291. *
  292. * @param request
  293. */
  294. @Override
  295. public void downOrder(HttpServletResponse response, OrderQueryRequest request) {
  296. List<HotelAndBillVO> hotelAndBillVOList = new ArrayList<>();
  297. List<AdminOrderIndexVO> list = this.listForAdmin(request);
  298. list.forEach(orderAndBill -> {
  299. HotelAndBillVO hotelAndBillVO = new HotelAndBillVO();
  300. HotelOrderEntity order = orderAndBill.getOrder();
  301. HotelOrderBillEntity orderBill = orderAndBill.getOrderBill();
  302. hotelAndBillVO.setOrderNo(order.getOrderNo());
  303. hotelAndBillVO.setRoomNo(order.getRoomNo());
  304. hotelAndBillVO.setOrderStatu(order.getOrderStatu());
  305. hotelAndBillVO.setPayTime(order.getPayTime());
  306. //电费计算
  307. String startOfElectric = this.check(orderBill, "startOfElectric");
  308. String endOfElectric = this.check(orderBill, "endOfElectric");
  309. String priceOfElectric = this.check(orderBill, "priceOfElectric");
  310. String calculateElectric = this.calculate(startOfElectric, endOfElectric, priceOfElectric);
  311. hotelAndBillVO.setElectricity(calculateElectric);
  312. //水费计算
  313. String startOfWater = this.check(orderBill, "startOfWater");
  314. String endOfWater = this.check(orderBill, "endOfWater");
  315. String priceOfWater = this.check(orderBill, "priceOfWater");
  316. String calculateWater = this.calculate(startOfWater, endOfWater, priceOfWater);
  317. hotelAndBillVO.setWaterBill(calculateWater);
  318. SystemSettingEntity systemSetting = systemSettingService.get();
  319. //收预付款
  320. hotelAndBillVO.setAcceptPayment(systemSetting.getFreeTotal());
  321. //退预付款
  322. BigDecimal refundPayment = systemSetting.getFreeTotal().subtract(order.getPayAmount());
  323. hotelAndBillVO.setRefundPayment(refundPayment);
  324. hotelAndBillVO.setCreateTime(order.getCreateTime());
  325. hotelAndBillVO.setPayTime(order.getPayTime());
  326. hotelAndBillVOList.add(hotelAndBillVO);
  327. });
  328. String fileName;
  329. try {
  330. fileName = URLEncoder.encode("订单管理" + new Date().getTime(), "UTF-8");
  331. response.setContentType("application/vnd.openxmlformats-officedocument.spreadsheetml.sheet");
  332. response.setCharacterEncoding("utf-8");
  333. response.setHeader("Content-disposition", "attachment;filename=" + fileName + ".xlsx");
  334. EasyExcel.write(response.getOutputStream(), HotelAndBillVO.class).sheet("订单管理").doWrite(hotelAndBillVOList);
  335. } catch (Exception e) {
  336. e.printStackTrace();
  337. }
  338. }
  339. /**
  340. * 获取上月第一天
  341. *
  342. * @return
  343. */
  344. public String getLastMonthFirstDayStr() {
  345. SimpleDateFormat df = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
  346. Calendar cal = Calendar.getInstance();
  347. cal.setTime(new Date());
  348. int year = cal.get(Calendar.YEAR);
  349. int month = cal.get(Calendar.MONTH);
  350. int date = cal.get(Calendar.DATE);
  351. cal.set(year, month, date, 0, 0, 1);
  352. //获取当前时间上一个月
  353. cal.add(Calendar.MONTH, -1);
  354. //获取上个月的第一天
  355. cal.set(Calendar.DAY_OF_MONTH, cal.getActualMinimum(Calendar.DAY_OF_MONTH));
  356. return df.format(cal.getTime());
  357. }
  358. /**
  359. * 获取上月最后一天
  360. *
  361. * @return
  362. */
  363. public String getLastMonthLastDayStr() {
  364. SimpleDateFormat df = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
  365. Calendar cal = Calendar.getInstance();
  366. cal.setTime(new Date());
  367. int year = cal.get(Calendar.YEAR);
  368. int month = cal.get(Calendar.MONTH);
  369. int date = cal.get(Calendar.DATE);
  370. cal.set(year, month, date, 23, 59, 59);
  371. //获取当前时间上一个月
  372. cal.add(Calendar.MONTH, -1);
  373. //获取上个月的最后一天
  374. cal.set(Calendar.DAY_OF_MONTH, cal.getActualMaximum(Calendar.DAY_OF_MONTH));
  375. return df.format(cal.getTime());
  376. }
  377. /**
  378. * 统计报表
  379. */
  380. @Override
  381. public void statisticalReport() {
  382. String lastMonthFirstDayStr = this.getLastMonthFirstDayStr();
  383. String lastMonthLastDayStr = this.getLastMonthLastDayStr();
  384. DateTimeFormatter df = DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss");
  385. LocalDateTime firstDayOfMonth = LocalDateTime.parse(lastMonthFirstDayStr, df);
  386. LocalDateTime lastDayOfMonth = LocalDateTime.parse(lastMonthLastDayStr, df);
  387. List<AdminOrderIndexVO> voList = this.queryByMonthHotelOrder(firstDayOfMonth, lastDayOfMonth);
  388. BigDecimal waterPayment = BigDecimal.ZERO;
  389. BigDecimal electricPayment = BigDecimal.ZERO;
  390. BigDecimal totalPayment = BigDecimal.ZERO;
  391. //住房总押金 单价 * 天数
  392. int housDay = 0;
  393. StatisticalReportEntity statisticalReport = new StatisticalReportEntity();
  394. for (AdminOrderIndexVO orderAndBill : voList) {
  395. HotelOrderEntity order = orderAndBill.getOrder();
  396. HotelOrderBillEntity orderBill = orderAndBill.getOrderBill();
  397. //电费计算
  398. String startOfElectric = this.check(orderBill, "startOfElectric");
  399. String endOfElectric = this.check(orderBill, "endOfElectric");
  400. String priceOfElectric = this.check(orderBill, "priceOfElectric");
  401. String calculateElectric = this.calculate(startOfElectric, endOfElectric, priceOfElectric);
  402. electricPayment = electricPayment.add(new BigDecimal(calculateElectric)).setScale(2, BigDecimal.ROUND_UP);
  403. //水费计算
  404. String startOfWater = this.check(orderBill, "startOfWater");
  405. String endOfWater = this.check(orderBill, "endOfWater");
  406. String priceOfWater = this.check(orderBill, "priceOfWater");
  407. String calculateWater = this.calculate(startOfWater, endOfWater, priceOfWater);
  408. waterPayment = waterPayment.add(new BigDecimal(calculateWater)).setScale(2, BigDecimal.ROUND_UP);
  409. //收款总计
  410. totalPayment = totalPayment.add(order.getPayAmount()).setScale(2, BigDecimal.ROUND_UP);
  411. housDay = order.getEnableEndTime().getDayOfMonth() - order.getEnableStartTime().getDayOfMonth();
  412. }
  413. StatisticalReportEntity statisticalReportEntity = new StatisticalReportEntity();
  414. // statisticalReportEntity = queryByMonth(firstDayOfMonth);
  415. // if (statisticalReportEntity != null) {
  416. // statisticalReport.setId(statisticalReportEntity.getId());
  417. // }
  418. SystemSettingEntity systemSetting = systemSettingService.get();
  419. //住房总押金 单价 * 天数
  420. BigDecimal totalHousDeposit = systemSetting.getDeposit().multiply(new BigDecimal(housDay)).setScale(2, BigDecimal.ROUND_UP);
  421. statisticalReport.setTime(firstDayOfMonth);
  422. statisticalReport.setElectricPayment(electricPayment);
  423. statisticalReport.setWaterPayment(waterPayment);
  424. //退预付款 = 水电减免 + 住房押金 - 水费总额 - 电费总额
  425. statisticalReport.setRefundPayment(systemSetting.getFreeTotal().add(totalHousDeposit).subtract(electricPayment).subtract(waterPayment));
  426. statisticalReport.setTotalPayment(totalPayment);
  427. statisticalReportService.save(statisticalReport);
  428. }
  429. @Override
  430. public String check(HotelOrderBillEntity orderBill, String field) {
  431. String result = "0.0";
  432. boolean isPWaterNull = FiledUtil.checkObjFieldsIsNull(orderBill, field);
  433. if (!isPWaterNull) {
  434. switch (field){
  435. case "startOfWater" : result = orderBill.getStartOfWater(); break;
  436. case "endOfWater" : result = orderBill.getEndOfWater(); break;
  437. case "priceOfWater" : result = orderBill.getPriceOfWater(); break;
  438. case "startOfElectric" : result = orderBill.getStartOfElectric(); break;
  439. case "endOfElectric" : result = orderBill.getEndOfElectric(); break;
  440. case "priceOfElectric" : result = orderBill.getPriceOfElectric(); break;
  441. }
  442. result = result.equals("0E-8") ? "0.0" : result;
  443. }
  444. return result;
  445. }
  446. public StatisticalReportEntity queryByMonth(LocalDateTime dateTime) {
  447. QueryWrapper<StatisticalReportEntity> wrapper = new QueryWrapper<>();
  448. wrapper.eq("time", dateTime);
  449. return statisticalReportService.getOne(wrapper);
  450. }
  451. @Override
  452. public List<AdminOrderIndexVO> queryByMonthHotelOrder(LocalDateTime startTime, LocalDateTime endTime) {
  453. QueryWrapper<HotelOrderEntity> wrapper = new QueryWrapper<>();
  454. wrapper.eq("order_statu", "5");
  455. if (startTime != null && endTime != null) {
  456. wrapper.between("pay_time", startTime, endTime);
  457. }
  458. List<HotelOrderEntity> orderList = this.list(wrapper);
  459. List<AdminOrderIndexVO> voList = new ArrayList<>();
  460. Set<Long> ids = orderList.stream().map(order -> order.getId()).collect(Collectors.toSet());
  461. if (ids.size() > 0) {
  462. List<HotelOrderBillEntity> orderBillList = orderBillService.findByOrderIds(ids);
  463. Map<Long, HotelOrderBillEntity> orderBillMap = orderBillList.stream().collect(Collectors.toMap(HotelOrderBillEntity::getHotelOrderId, e -> e));
  464. voList = orderList.stream().map(order -> {
  465. AdminOrderIndexVO vo = new AdminOrderIndexVO();
  466. vo.setOrder(order);
  467. vo.setOrderBill(orderBillMap.get(order.getId()));
  468. return vo;
  469. }).collect(Collectors.toList());
  470. }
  471. return voList;
  472. }
  473. /**
  474. * 计算水电费用
  475. *
  476. * @param start
  477. * @param end
  478. * @param price
  479. * @return
  480. */
  481. @Override
  482. public String calculate(String start, String end, String price) {
  483. Double sum = Double.parseDouble(end) - Double.parseDouble(start);
  484. String result = String.valueOf(sum * Double.parseDouble(price));
  485. result = result.equals("-0.0") ? "0.0" : result;
  486. return result;
  487. }
  488. @Override
  489. public HotelOrderEntity findByOrderNo(String orderNo) {
  490. QueryWrapper<HotelOrderEntity> queryWrapper = new QueryWrapper<>();
  491. queryWrapper.eq("order_no", orderNo);
  492. queryWrapper.last("limit 1");
  493. return this.getOne(queryWrapper);
  494. }
  495. @Override
  496. public ConfirmOrderVO confirmOrder(ConfrimOrderRequest request) {
  497. SystemSettingEntity systemSetting = systemSettingService.get();
  498. // 入住日期校验
  499. Integer preDay = systemSetting.getPreDay();
  500. if (Math.abs(ChronoUnit.DAYS.between(request.getStartTime(), LocalDate.now())) > preDay) {
  501. throw new RRException(BizCodeEnume.PARAMETER_ERROR, "只能预定" + preDay + "天之内的房源");
  502. }
  503. // 查询房源是否充足
  504. Long roomTypeId = request.getRoomTypeId();
  505. RoomTypeEntity roomType = roomTypeService.myGetById(roomTypeId);
  506. if (roomType == null) {
  507. throw new RRException(BizCodeEnume.PARAMETER_ERROR, "房型不存在");
  508. } else {
  509. if (roomType.getRoomNum() < 1) {
  510. throw new RRException(BizCodeEnume.PARAMETER_ERROR, "该房型客房不足");
  511. } else {
  512. roomService.queryRoomNum(roomTypeId);
  513. }
  514. }
  515. LocalDateTime startTime = CommonUtil.localDateToTime(request.getStartTime(), TimeConstant.INTO_TIME);
  516. LocalDateTime endTime = CommonUtil.localDateToTime(request.getEndTime(), TimeConstant.OUT_TIME);
  517. long days = ChronoUnit.DAYS.between(request.getStartTime(), request.getEndTime());
  518. int busyNum = roomRealtimeStatuService.getBusyNum(roomTypeId, startTime, endTime);
  519. int enableNum = roomType.getRoomNum() - busyNum;
  520. // 查询房型价格
  521. BigDecimal discountPrice = roomType.getDiscountPrice();
  522. // 查询押金
  523. //BigDecimal deposit = systemSetting.getDeposit();
  524. //BigDecimal totalAmount = discountPrice.add(deposit).multiply(new BigDecimal(Long.toString(days)));
  525. //2023-06-30 更改为 押金 -(水费补助 + 电费补助)
  526. BigDecimal totalAmount = systemSetting.getDeposit().subtract(systemSetting.getFreeQuotaOfElectric().multiply(systemSetting.getPriceOfElectric()).add(systemSetting.getFreeQuotaOfWater().multiply(systemSetting.getPriceOfWater())));
  527. // 封装确认订单vo
  528. ConfirmOrderVO vo = new ConfirmOrderVO();
  529. vo.setStartTime(startTime);
  530. vo.setEndTime(endTime);
  531. vo.setNums(Integer.valueOf((int) days));
  532. vo.setRoomTypeId(roomTypeId);
  533. vo.setRoomTypeName(roomType.getTypeName());
  534. vo.setFreeNum(enableNum >= 0 ? enableNum : 0);
  535. vo.setDiscountPrice(roomType.getDiscountPrice());
  536. vo.setDeposit(systemSetting.getDeposit());
  537. vo.setPriceOfWater(systemSetting.getPriceOfWater());
  538. vo.setPriceOfElectric(systemSetting.getPriceOfElectric());
  539. vo.setFreeQuotaOfElectric(systemSetting.getPriceOfElectric());
  540. vo.setFreeQuotaOfWater(systemSetting.getFreeQuotaOfWater());
  541. vo.setFreeQuotaOfElectric(systemSetting.getFreeQuotaOfElectric());
  542. vo.setFreeTotal(systemSetting.getFreeTotal());
  543. vo.setTotalAmount(totalAmount.compareTo(BigDecimal.ZERO) < 0 ? BigDecimal.ZERO : totalAmount);
  544. return vo;
  545. }
  546. @Override
  547. public void orderPaySuccess(Long orderId, String orderNo, String realPayAmount, LocalDateTime payTime) {
  548. HotelOrderEntity order = null;
  549. if (orderId != null) {
  550. order = this.getById(orderId);
  551. } else {
  552. if (StringUtils.hasText(orderNo)) {
  553. order = this.findByOrderNo(orderNo);
  554. }
  555. }
  556. if (order == null) {
  557. log.warn("修改订单状态:订单【{}】不存在", orderId);
  558. return;
  559. }
  560. if (OrderStatuEnum.WAIT_PAY.getCode().equalsIgnoreCase(order.getOrderStatu())) {
  561. if (Math.abs(order.getPayAmount().subtract(new BigDecimal(realPayAmount)).doubleValue()) < 0.01) {
  562. // 订单最终支付金额验证成功
  563. if (payTime == null) {
  564. order.setPayTime(LocalDateTime.now());
  565. } else {
  566. order.setPayTime(payTime);
  567. }
  568. order.setOrderStatu(OrderStatuEnum.FINISH_PAY.getCode());
  569. this.updateById(order);
  570. }
  571. }
  572. }
  573. @Transactional
  574. @Override
  575. public OrderSubmitVO submitOrder(SubmitOrderRequest request) {
  576. LoginUserDTO loginUserVO = LoginCheckAspect.threadLocal.get();
  577. String cardNumber = loginUserVO.getCardNumber();
  578. // 身份校验
  579. HotelUserEntity hotelUser = hotelUserService.findByCardNumber(cardNumber);
  580. if (hotelUser == null) {
  581. throw new RRException(BizCodeEnume.PERMISSION_DENIED, "非法用户");
  582. }
  583. String identityType = hotelUser.getIdentityType();
  584. if (!UserIdentityTypeEnum.STAFF_OF_TEACHER.getCode().equals(identityType)) {
  585. throw new RRException(BizCodeEnume.PERMISSION_DENIED, "非法用户-非教职工");
  586. }
  587. SystemSettingEntity systemSetting = systemSettingService.get();
  588. // 入住时间校验
  589. Integer preDay = systemSetting.getPreDay();
  590. if (Math.abs(ChronoUnit.DAYS.between(request.getEnableStartTime().toLocalDate(), LocalDate.now())) > preDay) {
  591. throw new RRException(BizCodeEnume.PARAMETER_ERROR, "只能预定" + preDay + "天之内的房源");
  592. }
  593. // 校验房型
  594. RoomTypeEntity roomType = roomTypeService.myGetById(request.getRoomTypeId());
  595. if (roomType == null) {
  596. throw new RRException(BizCodeEnume.PARAMETER_ERROR, "房型不存在");
  597. }
  598. // 金额校验
  599. SystemSettingEntity data = systemSettingService.get();
  600. long days = ChronoUnit.DAYS.between(request.getEnableStartTime().toLocalDate(), request.getEnableEndTime().toLocalDate());
  601. BigDecimal deposit =data.getDeposit().subtract(data.getFreeQuotaOfElectric().multiply(data.getPriceOfElectric()).add(data.getFreeQuotaOfWater().multiply(data.getPriceOfWater())));
  602. BigDecimal totalAmount = deposit.compareTo(BigDecimal.ZERO) < 0 ? BigDecimal.ZERO : deposit;
  603. if (Math.abs(totalAmount.subtract(request.getPayAmount()).doubleValue()) > 0.01) {
  604. throw new RRException(BizCodeEnume.ORDER_SUBMIT_ERROR, "订单金额校验失败");
  605. }
  606. // 锁定房源
  607. long orderId = IdWorker.getId();
  608. LockRoomDTO lockRoomDTO = LockRoomDTO.builder()
  609. .roomTypeId(roomType.getId())
  610. .bizId(orderId)
  611. .startTime(request.getEnableStartTime())
  612. .endTime(request.getEnableEndTime())
  613. .build();
  614. Long roomId = roomRealtimeStatuService.lockRoomByRoomTypeId(lockRoomDTO);
  615. if (roomId == null) {
  616. throw new RRException(BizCodeEnume.ORDER_SUBMIT_ERROR, "【" + roomType.getTypeName() + "】房型房源不足,锁定房源失败");
  617. }
  618. RoomEntity room = roomService.getById(roomId);
  619. if (room == null) {
  620. throw new RRException(BizCodeEnume.UNKNOW_EXCEPTION, "系统异常,根据id查询房间失败");
  621. }
  622. // 订单落库
  623. HotelOrderEntity hotelOrder = new HotelOrderEntity();
  624. BeanUtils.copyProperties(request, hotelOrder);
  625. hotelOrder.setId(orderId);
  626. hotelOrder.setOrderNo(IdWorker.getTimeId());
  627. hotelOrder.setUserFlag(cardNumber);
  628. hotelOrder.setRoomId(roomId);
  629. hotelOrder.setRoomNo(room.getRoomNo());
  630. hotelOrder.setRoomTypeName(roomType.getTypeName());
  631. hotelOrder.setRoomTypeMasterImg(roomType.getTypeImage().split(",")[0]);
  632. hotelOrder.setCreateTime(LocalDateTime.now());
  633. if (totalAmount.doubleValue() == 0) {
  634. hotelOrder.setOrderStatu(OrderStatuEnum.FINISH_PAY.getCode());
  635. hotelOrder.setBizStatu(OrderBillStatuEnum.FINISH.getCode());
  636. } else {
  637. hotelOrder.setOrderStatu(OrderStatuEnum.WAIT_PAY.getCode());
  638. hotelOrder.setBizStatu(OrderBillStatuEnum.WAIT_HANDLE.getCode());
  639. }
  640. hotelOrder.setDeleteFlag("1"); // 0删除、1正常
  641. this.save(hotelOrder);
  642. if (totalAmount.doubleValue() != 0) {
  643. // 发送延迟消息
  644. EventMessageDTO eventMessage = EventMessageDTO.builder()
  645. .eventMessageType(EventMessageTypeEnum.PRODUCT_ORDER_NEW.name())
  646. .accountNo(loginUserVO.getCardNumber())
  647. .bizId(orderId)
  648. .build();
  649. rabbitTemplate.convertAndSend(rabbitMQConfig.getOrderEventExchange(), rabbitMQConfig.getOrderCloseDelayRoutingKey(), eventMessage);
  650. }
  651. // 返回支付参数
  652. String payUrl = null;
  653. if (totalAmount.doubleValue() > 0) {
  654. payUrl = String.format(jxnxsPayConfig.getPayUrl(), hotelOrder.getId(), request.getPayAmount());
  655. }
  656. return OrderSubmitVO.builder().orderId(hotelOrder.getId()).payAmount(totalAmount).payUrl(payUrl).build();
  657. }
  658. @Override
  659. public void handleOrderMessage(EventMessageDTO eventMessageDTO) {
  660. String messageType = eventMessageDTO.getEventMessageType();
  661. try {
  662. if (EventMessageTypeEnum.PRODUCT_ORDER_NEW.name().equalsIgnoreCase(messageType)) {
  663. // 关单消息
  664. this.closeOrder(eventMessageDTO);
  665. }
  666. } catch (Exception e) {
  667. log.error("订单消费者消费失败:{}", eventMessageDTO);
  668. throw new RRException(BizCodeEnume.MQ_CONSUME_EXCEPTION);
  669. }
  670. }
  671. @Override
  672. public void closeOrder(EventMessageDTO eventMessageDTO) {
  673. Long orderId = eventMessageDTO.getBizId();
  674. String cardNumber = eventMessageDTO.getAccountNo();
  675. HotelOrderEntity orderEntity = this.getById(orderId);
  676. if (orderEntity == null) {
  677. log.warn("关单:订单【{}】不存在", orderId);
  678. return;
  679. }
  680. // 判断订单状态
  681. if (!orderEntity.getOrderStatu().equalsIgnoreCase(OrderStatuEnum.WAIT_PAY.getCode())) {
  682. log.info("关单:订单不是初始状态待支付:{}", eventMessageDTO);
  683. return;
  684. }
  685. // 未支付,向第三方支付平台查询状态
  686. Map<String, String> map = payComponent.queryOrderStatus(orderEntity.getId().toString());
  687. log.info("关单:订单支付状态查询结果,【{}】"+"订单号:"+orderEntity.getId().toString(), map);
  688. String payStatus = map.get("status");
  689. if ("1".equalsIgnoreCase(payStatus)) { // 已经完成支付
  690. String amount = map.get("trade_amount");
  691. String payTimeStr = map.get("trade_pay_time");
  692. LocalDateTime payTime = LocalDateTime.parse(payTimeStr, TimeConstant.DEFAULT_DTF);
  693. String realPayAmount = new BigDecimal(amount).divide(new BigDecimal(100)).setScale(2, BigDecimal.ROUND_UP).toString(); // 分转成元
  694. this.orderPaySuccess(orderId, orderEntity.getOrderNo(), realPayAmount, payTime);
  695. } else { // 未支付,取消订单
  696. this.cancelOrder(cardNumber, orderId);
  697. }
  698. }
  699. @Override
  700. public boolean cancelOrder(String userFlag, Long orderId) {
  701. HotelOrderEntity orderEntity = this.getById(orderId);
  702. if (orderEntity == null) {
  703. log.warn("取消订单:订单【{}】不存在", orderId);
  704. return false;
  705. }
  706. if (!orderEntity.getUserFlag().equalsIgnoreCase(userFlag)) {
  707. log.warn("取消订单:操作越权,非法取消订单,订单原用户【】,操作用户【】", orderEntity.getUserFlag(), userFlag);
  708. throw new RRException(BizCodeEnume.PERMISSION_DENIED, "不能取消非自己的订单");
  709. }
  710. orderEntity.setOrderStatu(OrderStatuEnum.CANCEL.getCode());
  711. this.updateById(orderEntity);
  712. // 释放库存
  713. roomRealtimeStatuService.releaseByBizId(orderEntity.getId());
  714. return true;
  715. }
  716. @Override
  717. public UserOrderDetailVO userOrderDetail(Long orderId) {
  718. HotelOrderEntity orderEntity = userGetOrderById(orderId);
  719. UserOrderDetailVO detailVO = new UserOrderDetailVO();
  720. detailVO.setOrderId(orderId);
  721. BeanUtils.copyProperties(orderEntity, detailVO);
  722. RoomTypeEntity roomType = roomTypeService.myGetById(orderEntity.getRoomTypeId());
  723. detailVO.setRoomTypeUsualPrice(roomType.getUsualPrice());
  724. detailVO.setRoomTypeDiscountPrice(roomType.getDiscountPrice());
  725. // 订单状态为已入住之后,查询水电等相关信息
  726. String orderStatu = orderEntity.getOrderStatu();
  727. if (Integer.valueOf(orderStatu).intValue() >= Integer.valueOf(OrderStatuEnum.HOLD_ON.getCode()).intValue()) {
  728. HotelOrderBillEntity orderBill = orderBillService.findByOrderId(orderId);
  729. if (orderBill == null) {
  730. throw new RRException(BizCodeEnume.UNKNOW_EXCEPTION, "用户订单详情-订单状态错误");
  731. }
  732. BeanUtils.copyProperties(orderBill, detailVO);
  733. }
  734. // 订单状态为已入住,查询密码锁等相关信息
  735. if (OrderStatuEnum.HOLD_ON.getCode().equals(orderStatu)) {
  736. RoomDoorLockDataEntity lockData = roomDoorLockDataService.queryByOrderId(orderId);
  737. if (lockData == null) {
  738. throw new RRException(BizCodeEnume.UNKNOW_EXCEPTION, "用户订单详情-锁密码获取失败");
  739. }
  740. detailVO.setLockRealtimePassword(lockData.getLockRealtimePassword());
  741. detailVO.setPasswordStartTime(lockData.getStartTime());
  742. detailVO.setPasswordEndTime(lockData.getEndTime());
  743. }
  744. return detailVO;
  745. }
  746. @Override
  747. public OrderSubmitVO getOrderPayParam(Long orderId) {
  748. HotelOrderEntity orderEntity = userGetOrderById(orderId);
  749. if (!OrderStatuEnum.WAIT_PAY.getCode().equalsIgnoreCase(orderEntity.getOrderStatu())) {
  750. throw new RRException(BizCodeEnume.PARAMETER_ERROR, "当前订单状态为非待支付状态");
  751. }
  752. // 支付参数
  753. String payUrl = String.format(jxnxsPayConfig.getPayUrl(), orderEntity.getId(), orderEntity.getPayAmount());
  754. return OrderSubmitVO.builder().orderId(orderId).payUrl(payUrl).build();
  755. }
  756. @Override
  757. public OrderBillHandleVO getOrderBillInfo(Long orderId) {
  758. HotelOrderEntity order = userGetOrderById(orderId);
  759. if (!OrderStatuEnum.WAIT_BILL.getCode().equals(order.getOrderStatu())) {
  760. throw new RRException(BizCodeEnume.PARAMETER_ERROR, "当前订单不是带结账状态");
  761. }
  762. BillHandleResultDTO dto = orderBillService.getBill(orderId);
  763. OrderBillHandleVO vo = new OrderBillHandleVO();
  764. vo.setOrderId(orderId);
  765. vo.setBillId(dto.getBillId());
  766. vo.setFlag(dto.getResultFlag());
  767. vo.setSupperFee(dto.getRealFee());
  768. vo.setRefundFee(dto.getReturnFee());
  769. return vo;
  770. }
  771. @Override
  772. public void userDeleteOrder(Long orderId) {
  773. HotelOrderEntity order = userGetOrderById(orderId);
  774. deleteOrder(order);
  775. }
  776. @Override
  777. public boolean adminDeleteOrder(Long orderId) {
  778. HotelOrderEntity orderEntity = this.getById(orderId);
  779. return deleteOrder(orderEntity);
  780. }
  781. private boolean deleteOrder(HotelOrderEntity orderEntity) {
  782. String orderStatu = orderEntity.getOrderStatu();
  783. // 已取消、待支付、已完成订单才可以被删除
  784. if (!(OrderStatuEnum.CANCEL.getCode().equalsIgnoreCase(orderStatu)
  785. || OrderStatuEnum.WAIT_PAY.getCode().equalsIgnoreCase(orderStatu)
  786. || OrderStatuEnum.FINISH.getCode().equalsIgnoreCase(orderStatu))) {
  787. throw new RRException(BizCodeEnume.PERMISSION_DENIED, "当前订单不可删除");
  788. }
  789. UpdateWrapper<HotelOrderEntity> updateWrapper = new UpdateWrapper<>();
  790. updateWrapper.eq("id", orderEntity.getId());
  791. updateWrapper.set("delete_flag", "0"); // 0表示删除
  792. updateWrapper.last("limit 1");
  793. return this.update(null, updateWrapper);
  794. }
  795. @Override
  796. public void userCancelOrder(Long orderId) {
  797. HotelOrderEntity order = userGetOrderById(orderId);
  798. // 待支付订单才可以被取消
  799. if (!OrderStatuEnum.WAIT_PAY.getCode().equalsIgnoreCase(order.getOrderStatu())) {
  800. throw new RRException(BizCodeEnume.PERMISSION_DENIED, "当前订单不可取消");
  801. }
  802. // 释放房间锁定
  803. roomRealtimeStatuService.releaseByBizId(orderId);
  804. UpdateWrapper<HotelOrderEntity> updateWrapper = new UpdateWrapper<>();
  805. updateWrapper.eq("id", orderId);
  806. updateWrapper.set("order_statu", OrderStatuEnum.CANCEL.getCode());
  807. updateWrapper.last("limit 1");
  808. this.update(null, updateWrapper);
  809. }
  810. @Transactional
  811. @Override
  812. public void userHoldOrder(Long orderId) {
  813. HotelOrderEntity order = userGetOrderById(orderId);
  814. LocalDateTime nowTime= LocalDateTime.now();
  815. //订单必须要在到了最早入住时间才能办理入住
  816. if(nowTime.isBefore(order.getEnableStartTime())){
  817. throw new RRException(BizCodeEnume.PARAMETER_ERROR, "未到入住时间,无法办理入住");
  818. }
  819. // 支付完成状态的订单才可以办理入住
  820. if (!OrderStatuEnum.FINISH_PAY.getCode().equalsIgnoreCase(order.getOrderStatu())) {
  821. throw new RRException(BizCodeEnume.PERMISSION_DENIED, "订单状态异常");
  822. }
  823. // 订单有效时间校验
  824. LocalDateTime now = LocalDateTime.now();
  825. if (now.isAfter(order.getEnableEndTime())) {
  826. throw new RRException(BizCodeEnume.PERMISSION_DENIED, "订单超过有效时间");
  827. }
  828. Long roomId = order.getRoomId();
  829. // 水电抄表 => 生成结账单
  830. orderBillService.generateBill(orderId, roomId);
  831. // 门锁密码
  832. RoomDoorLockDataEntity roomDoorLockDataEntity = doorLockService.generatePassword(order);
  833. // 更新房态状态
  834. roomRealtimeStatuService.userHoldOrder(orderId);
  835. // 更新订单状态
  836. UpdateWrapper<HotelOrderEntity> updateWrapper = new UpdateWrapper<>();
  837. updateWrapper.eq("id", orderId);
  838. updateWrapper.set("order_statu", OrderStatuEnum.HOLD_ON.getCode());
  839. updateWrapper.last("limit 1");
  840. this.update(null, updateWrapper);
  841. // 发送通知(优化:可以使用异步的方式发送通知)
  842. try {
  843. String lockRealtimePassword = roomDoorLockDataEntity.getLockRealtimePassword();
  844. LocalDateTime startTime = roomDoorLockDataEntity.getStartTime();
  845. LocalDateTime endTime = roomDoorLockDataEntity.getEndTime();
  846. String content = String.format(noticeTemplate, order.getRoomNo(), lockRealtimePassword, dtf.format(startTime) + "-" + dtf.format(endTime));
  847. weiXiaoComponent.sendNotice(Arrays.asList(order.getUserFlag()), "公寓办理入住成功", "办理入住成功", content, null);
  848. RoomThirdSettingEntity roomThird = roomThirdSettingService.findByRoomId(order.getRoomId());
  849. if (roomThird == null) {
  850. throw new RRException(BizCodeEnume.UNKNOW_EXCEPTION, "门锁不存在");
  851. }
  852. if (roomThird != null) {
  853. //开电表
  854. waterElectricComponent.remoteDisconnect(roomThird.getElectricId(), OpenElectricStatuEnum.OPEN.getCode());
  855. System.out.println("办理入住-开电成功,订单编号"+order.getOrderNo()+"电表码:"+roomThird.getElectricId());
  856. }
  857. } catch (Exception e) {
  858. throw new RRException(BizCodeEnume.THIRD_PARTY_SERVICE_CALL_FAILED, "办理入住失败");
  859. }
  860. }
  861. String returnOrderTemplate = "订单id【%s】,用户【%s】,房间号【%s】已退房,需要清扫";
  862. @Override
  863. public OrderBillHandleVO userReturnOrder(Long orderId) {
  864. HotelOrderEntity order = userGetOrderById(orderId);
  865. // 入住状态的订单才可以办理退房
  866. if (!OrderStatuEnum.HOLD_ON.getCode().equalsIgnoreCase(order.getOrderStatu())) {
  867. throw new RRException(BizCodeEnume.PERMISSION_DENIED, "订单状态异常");
  868. }
  869. // 结算订单
  870. BigDecimal payAmount = order.getPayAmount();
  871. String orderStatu = OrderStatuEnum.WAIT_BILL.getCode();
  872. BillHandleResultDTO billHandleResult = orderBillService.calcBill(orderId);
  873. if ("1".equals(billHandleResult.getResultFlag())) { // 待退款
  874. if (billHandleResult.getReturnFee().doubleValue() > 0) {
  875. // TODO 发起退款
  876. } else {
  877. // 自动完结订单
  878. orderStatu = OrderStatuEnum.FINISH.getCode();
  879. }
  880. }else{//待结账
  881. orderStatu = OrderStatuEnum.WAIT_BILL.getCode();
  882. }
  883. // 密码锁密码删除
  884. roomDoorLockDataService.deleteByOrderId(orderId);
  885. // 更新房态状态
  886. roomRealtimeStatuService.userReturnOrder(orderId);
  887. // 更新订单状态
  888. UpdateWrapper<HotelOrderEntity> updateWrapper = new UpdateWrapper<>();
  889. updateWrapper.eq("id", orderId);
  890. updateWrapper.set("order_statu", orderStatu);
  891. if(orderStatu.equals(OrderStatuEnum.WAIT_BILL.getCode())){
  892. updateWrapper.set("order_statu", orderStatu);
  893. }
  894. updateWrapper.last("limit 1");
  895. this.update(null, updateWrapper);
  896. // 发送通知消息 优化:可以使用异步的方式
  897. String format = String.format(returnOrderTemplate, orderId, order.getUserName(), order.getRoomNo());
  898. systemNoticeService.addNotice("用户退房通知", format, SystemNoticeTypeEnum.USER_RETURN);
  899. OrderBillHandleVO vo = new OrderBillHandleVO();
  900. vo.setOrderId(orderId);
  901. vo.setBillId(billHandleResult.getBillId());
  902. if (OrderStatuEnum.FINISH.getCode().equals(orderStatu)) {
  903. vo.setFlag("3");
  904. } else {
  905. vo.setFlag(billHandleResult.getResultFlag());
  906. vo.setRefundFee(billHandleResult.getReturnFee());
  907. vo.setSupperFee(billHandleResult.getRealFee());
  908. }
  909. return vo;
  910. }
  911. @Override
  912. public List<RoomRealDataStatuVO.RoomUseInfo> getRoomUseInfoByOrderIds(Set<Long> orderIds) {
  913. if (orderIds.size() <= 0) {
  914. return null;
  915. }
  916. return this.baseMapper.getRoomUseInfoByOrderIds(orderIds);
  917. }
  918. @Override
  919. public void autoReturnOrder() {
  920. // 查询都有已经到退房时间但是未退房订单
  921. QueryWrapper<HotelOrderEntity> queryWrapper = new QueryWrapper<>();
  922. queryWrapper.eq("order_statu", OrderStatuEnum.HOLD_ON.getCode());
  923. queryWrapper.le("enable_end_time", CommonUtil.localDateToTime(LocalDate.now(), TimeConstant.OUT_TIME));
  924. List<HotelOrderEntity> orderEntityList = this.list(queryWrapper);
  925. if (orderEntityList.size() > 0) {
  926. List<Long> waitBillOrderIdList = new ArrayList<>();
  927. List<Long> finishOrderIdList = new ArrayList<>();
  928. orderEntityList.forEach(order -> {
  929. Long orderId = order.getId();
  930. // 结算订单
  931. BigDecimal payAmount = order.getPayAmount();
  932. if (payAmount.doubleValue() == 0) {
  933. finishOrderIdList.add(orderId);
  934. } else {
  935. BillHandleResultDTO billHandleResult = orderBillService.calcBill(orderId);
  936. if ("1".equals(billHandleResult.getResultFlag()) && billHandleResult.getReturnFee().doubleValue() == 0) { // 待退款
  937. finishOrderIdList.add(orderId);
  938. } else {
  939. waitBillOrderIdList.add(orderId);
  940. }
  941. }
  942. // 密码锁密码删除
  943. roomDoorLockDataService.deleteByOrderId(orderId);
  944. // 更新房态状态
  945. roomRealtimeStatuService.userReturnOrder(orderId);
  946. // 发送通知消息 优化:可以使用异步的方式
  947. String format = String.format(returnOrderTemplate, orderId, order.getUserName(), order.getRoomNo());
  948. systemNoticeService.addNotice("用户退房通知", format, SystemNoticeTypeEnum.USER_RETURN);
  949. });
  950. if (waitBillOrderIdList.size() > 0) {
  951. UpdateWrapper<HotelOrderEntity> updateWrapper = new UpdateWrapper<>();
  952. updateWrapper.in("id", orderEntityList.stream().map(e -> e.getId()).collect(Collectors.toList()));
  953. updateWrapper.set("order_statu", OrderStatuEnum.WAIT_BILL.getCode());
  954. this.update(null, updateWrapper);
  955. }
  956. if (finishOrderIdList.size() > 0) {
  957. UpdateWrapper<HotelOrderEntity> updateWrapper = new UpdateWrapper<>();
  958. updateWrapper.in("id", orderEntityList.stream().map(e -> e.getId()).collect(Collectors.toList()));
  959. updateWrapper.set("order_statu", OrderStatuEnum.FINISH.getCode());
  960. this.update(null, updateWrapper);
  961. }
  962. }
  963. }
  964. /**
  965. * 用户根据订单id获取订单
  966. *
  967. * @param orderId
  968. * @return
  969. */
  970. private HotelOrderEntity userGetOrderById(Long orderId) {
  971. HotelOrderEntity orderEntity = this.getById(orderId);
  972. if (orderEntity == null) {
  973. throw new RRException(BizCodeEnume.PARAMETER_ERROR, "订单不存在,无效的orderId");
  974. }
  975. if ("0".equalsIgnoreCase(orderEntity.getDeleteFlag())) {
  976. throw new RRException(BizCodeEnume.PARAMETER_ERROR, "订单不存在,订单已删除");
  977. }
  978. LoginUserDTO loginUserVO = LoginCheckAspect.threadLocal.get();
  979. String userFlag = loginUserVO.getCardNumber();
  980. if (!orderEntity.getUserFlag().equalsIgnoreCase(userFlag)) {
  981. throw new RRException(BizCodeEnume.PERMISSION_DENIED, "非自己的订单");
  982. }
  983. return orderEntity;
  984. }
  985. }