CouponServiceImpl.java 48 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788899091929394959697989910010110210310410510610710810911011111211311411511611711811912012112212312412512612712812913013113213313413513613713813914014114214314414514614714814915015115215315415515615715815916016116216316416516616716816917017117217317417517617717817918018118218318418518618718818919019119219319419519619719819920020120220320420520620720820921021121221321421521621721821922022122222322422522622722822923023123223323423523623723823924024124224324424524624724824925025125225325425525625725825926026126226326426526626726826927027127227327427527627727827928028128228328428528628728828929029129229329429529629729829930030130230330430530630730830931031131231331431531631731831932032132232332432532632732832933033133233333433533633733833934034134234334434534634734834935035135235335435535635735835936036136236336436536636736836937037137237337437537637737837938038138238338438538638738838939039139239339439539639739839940040140240340440540640740840941041141241341441541641741841942042142242342442542642742842943043143243343443543643743843944044144244344444544644744844945045145245345445545645745845946046146246346446546646746846947047147247347447547647747847948048148248348448548648748848949049149249349449549649749849950050150250350450550650750850951051151251351451551651751851952052152252352452552652752852953053153253353453553653753853954054154254354454554654754854955055155255355455555655755855956056156256356456556656756856957057157257357457557657757857958058158258358458558658758858959059159259359459559659759859960060160260360460560660760860961061161261361461561661761861962062162262362462562662762862963063163263363463563663763863964064164264364464564664764864965065165265365465565665765865966066166266366466566666766866967067167267367467567667767867968068168268368468568668768868969069169269369469569669769869970070170270370470570670770870971071171271371471571671771871972072172272372472572672772872973073173273373473573673773873974074174274374474574674774874975075175275375475575675775875976076176276376476576676776876977077177277377477577677777877978078178278378478578678778878979079179279379479579679779879980080180280380480580680780880981081181281381481581681781881982082182282382482582682782882983083183283383483583683783883984084184284384484584684784884985085185285385485585685785885986086186286386486586686786886987087187287387487587687787887988088188288388488588688788888989089189289389489589689789889990090190290390490590690790890991091191291391491591691791891992092192292392492592692792892993093193293393493593693793893994094194294394494594694794894995095195295395495595695795895996096196296396496596696796896997097197297397497597697797897998098198298398498598698798898999099199299399499599699799899910001001100210031004100510061007100810091010101110121013101410151016101710181019102010211022102310241025102610271028102910301031103210331034103510361037103810391040104110421043104410451046104710481049105010511052105310541055105610571058105910601061106210631064106510661067106810691070107110721073107410751076107710781079108010811082108310841085108610871088108910901091109210931094109510961097109810991100110111021103110411051106110711081109111011111112111311141115111611171118111911201121112211231124112511261127112811291130113111321133113411351136113711381139114011411142114311441145114611471148114911501151115211531154115511561157115811591160116111621163116411651166116711681169117011711172117311741175117611771178117911801181118211831184118511861187
  1. package com.fuint.common.service.impl;
  2. import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
  3. import com.baomidou.mybatisplus.core.toolkit.Wrappers;
  4. import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
  5. import com.fuint.common.Constants;
  6. import com.fuint.common.dto.CouponDto;
  7. import com.fuint.common.dto.ReqCouponDto;
  8. import com.fuint.common.dto.ReqSendLogDto;
  9. import com.fuint.common.enums.*;
  10. import com.fuint.common.param.CouponListParam;
  11. import com.fuint.common.service.*;
  12. import com.fuint.common.util.CommonUtil;
  13. import com.fuint.common.util.DateUtil;
  14. import com.fuint.common.util.SeqUtil;
  15. import com.fuint.framework.annoation.OperationServiceLog;
  16. import com.fuint.framework.exception.BusinessCheckException;
  17. import com.fuint.framework.pagination.PaginationRequest;
  18. import com.fuint.framework.pagination.PaginationResponse;
  19. import com.fuint.framework.web.ResponseObject;
  20. import com.fuint.repository.bean.CouponNumBean;
  21. import com.fuint.repository.mapper.*;
  22. import com.fuint.repository.model.*;
  23. import com.fuint.utils.StringUtil;
  24. import com.github.pagehelper.Page;
  25. import com.github.pagehelper.PageHelper;
  26. import lombok.AllArgsConstructor;
  27. import org.apache.commons.lang.StringUtils;
  28. import org.springframework.beans.BeanUtils;
  29. import org.springframework.context.annotation.Lazy;
  30. import org.springframework.data.domain.PageImpl;
  31. import org.springframework.data.domain.PageRequest;
  32. import org.springframework.stereotype.Service;
  33. import org.springframework.transaction.annotation.Transactional;
  34. import java.math.BigDecimal;
  35. import java.text.ParseException;
  36. import java.text.SimpleDateFormat;
  37. import java.util.*;
  38. /**
  39. * 卡券业务实现类
  40. *
  41. * Created by FSQ
  42. * CopyRight https://www.fuint.cn
  43. */
  44. @Service
  45. @AllArgsConstructor(onConstructor_= {@Lazy})
  46. public class CouponServiceImpl extends ServiceImpl<MtCouponMapper, MtCoupon> implements CouponService {
  47. private MtCouponMapper mtCouponMapper;
  48. private MtUserCouponMapper mtUserCouponMapper;
  49. private MtConfirmLogMapper mtConfirmLogMapper;
  50. private MtSendLogMapper mtSendLogMapper;
  51. private MtStoreMapper mtStoreMapper;
  52. private MtCouponGoodsMapper mtCouponGoodsMapper;
  53. private MtOrderMapper mtOrderMapper;
  54. /**
  55. * 会员卡券服务接口
  56. * */
  57. private UserCouponService userCouponService;
  58. /**
  59. * 会员服务接口
  60. * */
  61. private MemberService memberService;
  62. /**
  63. * 会员等级服务接口
  64. * */
  65. private UserGradeService userGradeService;
  66. /**
  67. * 短信发送服务接口
  68. * */
  69. private SendSmsService sendSmsService;
  70. /**
  71. * 核销记录服务接口
  72. * */
  73. private ConfirmLogService confirmLogService;
  74. /**
  75. * 卡券发放记录服务接口
  76. * */
  77. private SendLogService sendLogService;
  78. /**
  79. * 卡券分组服务接口
  80. * */
  81. private CouponGroupService couponGroupService;
  82. /**
  83. * 系统配置服务接口
  84. * */
  85. private SettingService settingService;
  86. /**
  87. * 微信相关服务接口
  88. * */
  89. private WeixinService weixinService;
  90. /**
  91. * 分页查询券列表
  92. *
  93. * @param paginationRequest
  94. * @return
  95. */
  96. @Override
  97. public PaginationResponse<MtCoupon> queryCouponListByPagination(PaginationRequest paginationRequest) {
  98. Page<MtCoupon> pageHelper = PageHelper.startPage(paginationRequest.getCurrentPage(), paginationRequest.getPageSize());
  99. LambdaQueryWrapper<MtCoupon> lambdaQueryWrapper = Wrappers.lambdaQuery();
  100. lambdaQueryWrapper.ne(MtCoupon::getStatus, StatusEnum.DISABLE.getKey());
  101. String name = paginationRequest.getSearchParams().get("name") == null ? "" : paginationRequest.getSearchParams().get("name").toString();
  102. if (StringUtils.isNotBlank(name)) {
  103. lambdaQueryWrapper.like(MtCoupon::getName, name);
  104. }
  105. String status = paginationRequest.getSearchParams().get("status") == null ? "" : paginationRequest.getSearchParams().get("status").toString();
  106. if (StringUtils.isNotBlank(status)) {
  107. lambdaQueryWrapper.eq(MtCoupon::getStatus, status);
  108. }
  109. String groupId = paginationRequest.getSearchParams().get("groupId") == null ? "" : paginationRequest.getSearchParams().get("groupId").toString();
  110. if (StringUtils.isNotBlank(groupId)) {
  111. lambdaQueryWrapper.eq(MtCoupon::getGroupId, groupId);
  112. }
  113. String type = paginationRequest.getSearchParams().get("type") == null ? "" : paginationRequest.getSearchParams().get("type").toString();
  114. if (StringUtils.isNotBlank(type)) {
  115. lambdaQueryWrapper.eq(MtCoupon::getType, type);
  116. }
  117. String merchantId = paginationRequest.getSearchParams().get("merchantId") == null ? "" : paginationRequest.getSearchParams().get("merchantId").toString();
  118. if (StringUtils.isNotBlank(merchantId)) {
  119. lambdaQueryWrapper.eq(MtCoupon::getMerchantId, merchantId);
  120. }
  121. String storeId = paginationRequest.getSearchParams().get("storeId") == null ? "" : paginationRequest.getSearchParams().get("storeId").toString();
  122. if (StringUtils.isNotBlank(storeId)) {
  123. lambdaQueryWrapper.eq(MtCoupon::getStoreId, storeId);
  124. }
  125. lambdaQueryWrapper.orderByDesc(MtCoupon::getId);
  126. List<MtCoupon> dataList = mtCouponMapper.selectList(lambdaQueryWrapper);
  127. PageRequest pageRequest = PageRequest.of(paginationRequest.getCurrentPage(), paginationRequest.getPageSize());
  128. PageImpl pageImpl = new PageImpl(dataList, pageRequest, pageHelper.getTotal());
  129. PaginationResponse<MtCoupon> paginationResponse = new PaginationResponse(pageImpl, MtCoupon.class);
  130. paginationResponse.setTotalPages(pageHelper.getPages());
  131. paginationResponse.setTotalElements(pageHelper.getTotal());
  132. paginationResponse.setContent(dataList);
  133. return paginationResponse;
  134. }
  135. /**
  136. * 保存卡券信息
  137. *
  138. * @param reqCouponDto 卡券实体
  139. * @throws BusinessCheckException
  140. * @return
  141. */
  142. @Override
  143. @Transactional(rollbackFor = Exception.class)
  144. @OperationServiceLog(description = "保存卡券信息")
  145. public MtCoupon saveCoupon(ReqCouponDto reqCouponDto) throws BusinessCheckException, ParseException {
  146. MtCoupon mtCoupon;
  147. if (reqCouponDto.getId() != null) {
  148. mtCoupon = mtCouponMapper.selectById(reqCouponDto.getId());
  149. } else {
  150. mtCoupon = new MtCoupon();
  151. }
  152. // 固定有效期验证
  153. if (reqCouponDto.getExpireType().equals(CouponExpireTypeEnum.FIX.getKey())) {
  154. Date startTime = DateUtil.parseDate(reqCouponDto.getBeginTime());
  155. Date endTime = DateUtil.parseDate(reqCouponDto.getEndTime());
  156. if (endTime.before(startTime)) {
  157. throw new BusinessCheckException("生效期结束时间不能早于开始时间");
  158. }
  159. }
  160. if (reqCouponDto.getMerchantId() != null) {
  161. mtCoupon.setMerchantId(reqCouponDto.getMerchantId());
  162. }
  163. if (reqCouponDto.getStoreId() != null) {
  164. mtCoupon.setStoreId(reqCouponDto.getStoreId());
  165. }
  166. mtCoupon.setGroupId(reqCouponDto.getGroupId());
  167. if (reqCouponDto.getType() != null) {
  168. mtCoupon.setType(reqCouponDto.getType());
  169. }
  170. if (reqCouponDto.getName() != null) {
  171. mtCoupon.setName(CommonUtil.replaceXSS(reqCouponDto.getName()));
  172. }
  173. if (reqCouponDto.getIsGive() != null) {
  174. mtCoupon.setIsGive(reqCouponDto.getIsGive().equals(1) ? true : false);
  175. }
  176. if (reqCouponDto.getPoint() != null) {
  177. mtCoupon.setPoint(reqCouponDto.getPoint());
  178. }
  179. if (mtCoupon.getPoint() == null) {
  180. mtCoupon.setPoint(0);
  181. }
  182. if (reqCouponDto.getLimitNum() != null) {
  183. mtCoupon.setLimitNum(reqCouponDto.getLimitNum());
  184. }
  185. if (mtCoupon.getLimitNum() == null) {
  186. mtCoupon.setLimitNum(1);
  187. }
  188. if (reqCouponDto.getReceiveCode() != null) {
  189. mtCoupon.setReceiveCode(reqCouponDto.getReceiveCode());
  190. }
  191. if (mtCoupon.getReceiveCode() == null) {
  192. mtCoupon.setReceiveCode("");
  193. }
  194. if (mtCoupon.getType().equals(CouponTypeEnum.TIMER.getKey())) {
  195. if (reqCouponDto.getTimerPoint() != null) {
  196. mtCoupon.setPoint(reqCouponDto.getTimerPoint());
  197. }
  198. if (reqCouponDto.getTimerReceiveCode() != null) {
  199. mtCoupon.setReceiveCode(reqCouponDto.getTimerReceiveCode());
  200. }
  201. }
  202. mtCoupon.setStoreIds(reqCouponDto.getStoreIds());
  203. mtCoupon.setGradeIds(reqCouponDto.getGradeIds());
  204. if (reqCouponDto.getSendNum() == null) {
  205. reqCouponDto.setSendNum(1);
  206. }
  207. if (mtCoupon.getType().equals(CouponTypeEnum.PRESTORE.getKey())) {
  208. mtCoupon.setSendWay(SendWayEnum.FRONT.getKey());
  209. } else {
  210. mtCoupon.setSendWay(reqCouponDto.getSendWay());
  211. }
  212. mtCoupon.setSendNum(reqCouponDto.getSendNum());
  213. if (reqCouponDto.getTotal() == null) {
  214. reqCouponDto.setTotal(0);
  215. }
  216. mtCoupon.setTotal(reqCouponDto.getTotal());
  217. if (reqCouponDto.getExpireType().equals(CouponExpireTypeEnum.FIX.getKey())) {
  218. mtCoupon.setBeginTime(DateUtil.parseDate(reqCouponDto.getBeginTime()));
  219. mtCoupon.setEndTime(DateUtil.parseDate(reqCouponDto.getEndTime()));
  220. }
  221. if (reqCouponDto.getExpireType().equals(CouponExpireTypeEnum.FLEX.getKey())) {
  222. if (reqCouponDto.getExpireTime() == null || reqCouponDto.getExpireTime() < 0) {
  223. throw new BusinessCheckException("请输入正确的有效天数");
  224. }
  225. mtCoupon.setExpireTime(reqCouponDto.getExpireTime());
  226. }
  227. mtCoupon.setExpireType(reqCouponDto.getExpireType());
  228. mtCoupon.setExceptTime(CommonUtil.replaceXSS(reqCouponDto.getExceptTime()));
  229. mtCoupon.setDescription(CommonUtil.replaceXSS(reqCouponDto.getDescription()));
  230. mtCoupon.setRemarks(CommonUtil.replaceXSS(reqCouponDto.getRemarks()));
  231. mtCoupon.setInRule(CommonUtil.replaceXSS(reqCouponDto.getInRule()));
  232. mtCoupon.setOutRule(CommonUtil.replaceXSS(reqCouponDto.getOutRule()));
  233. mtCoupon.setApplyGoods(reqCouponDto.getApplyGoods());
  234. mtCoupon.setUseFor(reqCouponDto.getUseFor());
  235. if (null == reqCouponDto.getAmount()) {
  236. reqCouponDto.setAmount(new BigDecimal(0));
  237. }
  238. mtCoupon.setAmount(reqCouponDto.getAmount());
  239. String image = reqCouponDto.getImage();
  240. if (null == image || image.equals("")) {
  241. image = "";
  242. }
  243. mtCoupon.setImage(image);
  244. mtCoupon.setRemarks(CommonUtil.replaceXSS(reqCouponDto.getRemarks()));
  245. if (reqCouponDto.getStatus() == null || StringUtil.isEmpty(reqCouponDto.getStatus())) {
  246. mtCoupon.setStatus(StatusEnum.ENABLED.getKey());
  247. } else {
  248. mtCoupon.setStatus(reqCouponDto.getStatus());
  249. }
  250. // 创建时间
  251. if (reqCouponDto.getId() == null) {
  252. mtCoupon.setCreateTime(new Date());
  253. }
  254. // 更新时间
  255. mtCoupon.setUpdateTime(new Date());
  256. // 操作人
  257. mtCoupon.setOperator(reqCouponDto.getOperator());
  258. if (mtCoupon.getId() == null) {
  259. this.save(mtCoupon);
  260. } else {
  261. mtCouponMapper.updateById(mtCoupon);
  262. }
  263. MtCoupon couponInfo = mtCouponMapper.selectById(mtCoupon.getId());
  264. // 更新已下发的会员卡券有效期
  265. if (couponInfo.getId() != null && reqCouponDto.getEndTime() != null && StringUtil.isNotEmpty(reqCouponDto.getEndTime())) {
  266. mtUserCouponMapper.updateExpireTime(couponInfo.getId(), reqCouponDto.getEndTime());
  267. }
  268. // 适用商品
  269. if (reqCouponDto.getGoodsIds() != null) {
  270. String[] goodsIds = reqCouponDto.getGoodsIds().split(",");
  271. if (goodsIds.length > 0) {
  272. // 1.先删除
  273. List<MtCouponGoods> couponGoodsList = mtCouponGoodsMapper.getCouponGoods(couponInfo.getId());
  274. for (MtCouponGoods cg : couponGoodsList) {
  275. mtCouponGoodsMapper.deleteById(cg.getId());
  276. }
  277. // 2.再添加
  278. for (int n = 0; n < goodsIds.length; n++) {
  279. if (StringUtil.isNotEmpty(goodsIds[n])) {
  280. MtCouponGoods mtCouponGoods = new MtCouponGoods();
  281. mtCouponGoods.setCouponId(couponInfo.getId());
  282. mtCouponGoods.setGoodsId(Integer.parseInt(goodsIds[n]));
  283. mtCouponGoods.setStatus(StatusEnum.ENABLED.getKey());
  284. mtCouponGoods.setCreateTime(new Date());
  285. mtCouponGoods.setUpdateTime(new Date());
  286. mtCouponGoodsMapper.insert(mtCouponGoods);
  287. }
  288. }
  289. }
  290. }
  291. // 如果是优惠券,并且是线下发放,生成会员卡券
  292. if (reqCouponDto.getId() == null && mtCoupon.getType().equals(CouponTypeEnum.COUPON.getKey()) && mtCoupon.getSendWay().equals(SendWayEnum.OFFLINE.getKey())) {
  293. Integer total = mtCoupon.getTotal() * mtCoupon.getSendNum();
  294. if (total > 0) {
  295. String uuid = UUID.randomUUID().toString().replaceAll("-", "");
  296. for (int i = 1; i <= total; i++) {
  297. MtUserCoupon userCoupon = new MtUserCoupon();
  298. userCoupon.setMerchantId(mtCoupon.getMerchantId());
  299. userCoupon.setStoreId(mtCoupon.getStoreId());
  300. userCoupon.setCouponId(couponInfo.getId());
  301. userCoupon.setGroupId(mtCoupon.getGroupId());
  302. userCoupon.setMobile("");
  303. userCoupon.setUserId(0);
  304. userCoupon.setStatus(UserCouponStatusEnum.UNSEND.getKey());
  305. userCoupon.setCreateTime(new Date());
  306. userCoupon.setUpdateTime(new Date());
  307. userCoupon.setExpireTime(couponInfo.getEndTime());
  308. if (couponInfo.getExpireType().equals(CouponExpireTypeEnum.FIX.getKey())) {
  309. userCoupon.setExpireTime(couponInfo.getEndTime());
  310. }
  311. if (couponInfo.getExpireType().equals(CouponExpireTypeEnum.FLEX.getKey())) {
  312. Date expireTime = new Date();
  313. Calendar c = Calendar.getInstance();
  314. c.setTime(expireTime);
  315. c.add(Calendar.DATE, couponInfo.getExpireTime());
  316. expireTime = c.getTime();
  317. userCoupon.setExpireTime(expireTime);
  318. }
  319. userCoupon.setUuid(uuid);
  320. userCoupon.setType(CouponTypeEnum.COUPON.getKey());
  321. userCoupon.setAmount(couponInfo.getAmount());
  322. userCoupon.setBalance(couponInfo.getAmount());
  323. userCoupon.setStoreId(0);
  324. userCoupon.setOperator(reqCouponDto.getOperator());
  325. userCoupon.setImage(couponInfo.getImage());
  326. // 12位随机数
  327. StringBuffer code = new StringBuffer();
  328. code.append(SeqUtil.getRandomNumber(4));
  329. code.append(SeqUtil.getRandomNumber(4));
  330. code.append(SeqUtil.getRandomNumber(4));
  331. code.append(SeqUtil.getRandomNumber(4));
  332. userCoupon.setCode(code.toString());
  333. mtUserCouponMapper.insert(userCoupon);
  334. }
  335. }
  336. }
  337. return mtCoupon;
  338. }
  339. /**
  340. * 根据ID获取券信息
  341. *
  342. * @param id 券ID
  343. * @return
  344. */
  345. @Override
  346. public MtCoupon queryCouponById(Integer id) {
  347. return mtCouponMapper.selectById(id);
  348. }
  349. /**
  350. * 删除卡券
  351. *
  352. * @param id 券ID
  353. * @param operator 操作人
  354. * @throws BusinessCheckException
  355. * @return
  356. */
  357. @Override
  358. @OperationServiceLog(description = "删除卡券")
  359. @Transactional(rollbackFor = Exception.class)
  360. public void deleteCoupon(Long id, String operator) throws BusinessCheckException {
  361. MtCoupon couponInfo = queryCouponById(id.intValue());
  362. if (null == couponInfo) {
  363. throw new BusinessCheckException("卡券不存在");
  364. }
  365. couponInfo.setStatus(StatusEnum.DISABLE.getKey());
  366. // 修改时间
  367. couponInfo.setUpdateTime(new Date());
  368. // 操作人
  369. couponInfo.setOperator(operator);
  370. mtCouponMapper.updateById(couponInfo);
  371. }
  372. /**
  373. * 获取卡券列表
  374. *
  375. * @param couponListParam 查询参数
  376. * @return
  377. * */
  378. @Override
  379. @Transactional(rollbackFor = Exception.class)
  380. public ResponseObject findCouponList(CouponListParam couponListParam) {
  381. Integer pageNumber = couponListParam.getPage() == null ? Constants.PAGE_NUMBER : couponListParam.getPage();
  382. Integer pageSize = couponListParam.getPageSize() == null ? Constants.PAGE_SIZE : couponListParam.getPageSize();
  383. String status = couponListParam.getStatus() == null ? StatusEnum.ENABLED.getKey() : couponListParam.getStatus();
  384. String type = couponListParam.getType() == null ? "" : couponListParam.getType();
  385. Integer userId = couponListParam.getUserId() == null ? 0 : couponListParam.getUserId();
  386. Integer needPoint = couponListParam.getNeedPoint() == null ? 0 : couponListParam.getNeedPoint();
  387. String sendWay = couponListParam.getSendWay() == null ? "front" : couponListParam.getSendWay();
  388. Page<MtCoupon> pageHelper = PageHelper.startPage(pageNumber, pageSize);
  389. LambdaQueryWrapper<MtCoupon> lambdaQueryWrapper = Wrappers.lambdaQuery();
  390. if (StringUtil.isNotEmpty(status)) {
  391. lambdaQueryWrapper.eq(MtCoupon::getStatus, status);
  392. }
  393. if (StringUtil.isNotEmpty(sendWay)) {
  394. lambdaQueryWrapper.eq(MtCoupon::getSendWay, sendWay);
  395. }
  396. if (StringUtil.isNotEmpty(type)) {
  397. lambdaQueryWrapper.eq(MtCoupon::getType, type);
  398. }
  399. if (needPoint != null && needPoint > 0) {
  400. lambdaQueryWrapper.eq(MtCoupon::getPoint, 0);
  401. }
  402. lambdaQueryWrapper.orderByDesc(MtCoupon::getId);
  403. List<MtCoupon> dataList = mtCouponMapper.selectList(lambdaQueryWrapper);
  404. // 处理已过期
  405. for (MtCoupon coupon : dataList) {
  406. // 固定期限
  407. if (coupon.getExpireType().equals(CouponExpireTypeEnum.FIX.getKey()) && (coupon.getEndTime() != null) && coupon.getEndTime().before(new Date())) {
  408. coupon.setStatus(StatusEnum.EXPIRED.getKey());
  409. coupon.setUpdateTime(new Date());
  410. mtCouponMapper.updateById(coupon);
  411. }
  412. // 领取后生效
  413. if (coupon.getExpireType().equals(CouponExpireTypeEnum.FLEX.getKey()) && (coupon.getExpireTime() != null)) {
  414. Date expireTime = new Date();
  415. Calendar c = Calendar.getInstance();
  416. c.setTime(expireTime);
  417. c.add(Calendar.DATE, coupon.getExpireTime());
  418. expireTime = c.getTime();
  419. if (expireTime.before(new Date())) {
  420. coupon.setStatus(StatusEnum.EXPIRED.getKey());
  421. coupon.setUpdateTime(new Date());
  422. mtCouponMapper.updateById(coupon);
  423. }
  424. }
  425. }
  426. List<CouponDto> content = new ArrayList<>();
  427. String baseImage = settingService.getUploadBasePath();
  428. for (int i = 0; i < dataList.size(); i++) {
  429. CouponDto item = new CouponDto();
  430. BeanUtils.copyProperties(dataList.get(i), item);
  431. item.setIsReceive(false);
  432. item.setImage(baseImage + item.getImage());
  433. // 是否领取,且领取量大于限制数
  434. List<String> statusList = Arrays.asList(UserCouponStatusEnum.UNUSED.getKey(), UserCouponStatusEnum.USED.getKey(), UserCouponStatusEnum.EXPIRE.getKey());
  435. List<MtUserCoupon> userCoupon = mtUserCouponMapper.getUserCouponListByCouponId(userId, item.getId(), statusList);
  436. if ((userCoupon.size() >= dataList.get(i).getLimitNum()) && (dataList.get(i).getLimitNum() > 0)) {
  437. item.setIsReceive(true);
  438. item.setUserCouponId(userCoupon.get(0).getId());
  439. }
  440. // 领取或预存数量
  441. CouponNumBean numData = mtUserCouponMapper.getPeopleNumByCouponId(item.getId());
  442. Long num;
  443. if (null == numData) {
  444. num = 0l;
  445. } else {
  446. num = numData.getNum();
  447. }
  448. item.setGotNum(num.intValue());
  449. // 剩余数量
  450. Integer leftNum = dataList.get(i).getTotal() - item.getGotNum();
  451. item.setLeftNum(leftNum >= 0 ? leftNum : 0);
  452. String sellingPoint = "";
  453. // 优惠券卖点
  454. if (item.getType().equals(CouponTypeEnum.COUPON.getKey())) {
  455. if (StringUtil.isNotEmpty(item.getOutRule()) && Integer.parseInt(item.getOutRule()) > 0) {
  456. sellingPoint = "满" + item.getOutRule() + "可用";
  457. } else {
  458. sellingPoint = "无门槛券";
  459. }
  460. }
  461. // 储值卡卖点
  462. if (item.getType().equals(CouponTypeEnum.PRESTORE.getKey())) {
  463. if (StringUtil.isNotEmpty(item.getInRule())) {
  464. String inRuleArr[] = item.getInRule().split(",");
  465. if (inRuleArr.length > 0) {
  466. for (int n = 0; n < inRuleArr.length; n++) {
  467. String store[] = inRuleArr[n].split("_");
  468. sellingPoint = "预存" + store[0] + "到账" + store[1];
  469. }
  470. }
  471. }
  472. }
  473. // 计次卡卖点
  474. if (item.getType().equals(CouponTypeEnum.TIMER.getKey()) && StringUtil.isNotEmpty(item.getOutRule())) {
  475. sellingPoint = "集满" + item.getOutRule() + "次即可";
  476. }
  477. item.setSellingPoint(sellingPoint);
  478. content.add(item);
  479. }
  480. PageRequest pageRequest = PageRequest.of(pageNumber, pageSize);
  481. PageImpl pageImpl = new PageImpl(dataList, pageRequest, pageHelper.getTotal());
  482. PaginationResponse<CouponDto> paginationResponse = new PaginationResponse(pageImpl, CouponDto.class);
  483. paginationResponse.setTotalPages(pageHelper.getPages());
  484. paginationResponse.setTotalElements(pageHelper.getTotal());
  485. paginationResponse.setContent(content);
  486. return new ResponseObject(200, "查询成功", paginationResponse);
  487. }
  488. /**
  489. * 根据分组ID获取卡券列表
  490. *
  491. * @param groupId 查询参数
  492. * @return
  493. * */
  494. public List<MtCoupon> queryCouponListByGroupId(Integer groupId) {
  495. List<MtCoupon> couponList = mtCouponMapper.queryByGroupId(groupId.intValue());
  496. return couponList;
  497. }
  498. /**
  499. * 发放卡券
  500. *
  501. * @param couponId 卡券ID
  502. * @param userId 会员ID
  503. * @param num 发放套数
  504. * @param sendMessage 是否发送消息
  505. * @param uuid 批次号
  506. * @param operator 操作人
  507. * @throws BusinessCheckException
  508. * @return
  509. */
  510. @Override
  511. @Transactional(rollbackFor = Exception.class)
  512. @OperationServiceLog(description = "发放卡券")
  513. public void sendCoupon(Integer couponId, Integer userId, Integer num, Boolean sendMessage, String uuid, String operator) throws BusinessCheckException {
  514. MtCoupon couponInfo = queryCouponById(couponId);
  515. MtUser userInfo = memberService.queryMemberById(userId);
  516. if (null == userInfo || !userInfo.getStatus().equals(StatusEnum.ENABLED.getKey())) {
  517. throw new BusinessCheckException("该会员不存在或已禁用,请先注册会员");
  518. }
  519. String mobile = StringUtil.isNotEmpty(userInfo.getMobile()) ? userInfo.getMobile() : "";
  520. // 判断券是否有效
  521. if (!couponInfo.getStatus().equals(StatusEnum.ENABLED.getKey())) {
  522. throw new BusinessCheckException("卡券“"+couponInfo.getName()+"”已停用,不能发放");
  523. }
  524. // 发放的是储值卡
  525. if (couponInfo.getType().equals(CouponTypeEnum.PRESTORE.getKey())) {
  526. if (StringUtil.isNotEmpty(couponInfo.getInRule())) {
  527. String storeParams = "";
  528. String[] paramArr = couponInfo.getInRule().split(",");
  529. for (int i = 0; i < paramArr.length; i++) {
  530. if (StringUtil.isNotEmpty(storeParams)) {
  531. storeParams = storeParams + "," + paramArr[i] + "_" + num;
  532. } else {
  533. storeParams = paramArr[i] + "_" + num;
  534. }
  535. }
  536. Map<String, Object> param = new HashMap<>();
  537. param.put("couponId", couponInfo.getId());
  538. param.put("userId", userInfo.getId());
  539. param.put("param", storeParams);
  540. param.put("orderId", 0);
  541. userCouponService.preStore(param);
  542. }
  543. return;
  544. }
  545. // 优惠券或计次卡,发放num套
  546. for (int k = 1; k <= num; k++) {
  547. for (int j = 1; j <= couponInfo.getSendNum(); j++) {
  548. MtUserCoupon userCoupon = new MtUserCoupon();
  549. userCoupon.setCouponId(couponInfo.getId());
  550. userCoupon.setType(couponInfo.getType());
  551. userCoupon.setImage(couponInfo.getImage());
  552. userCoupon.setMerchantId(couponInfo.getMerchantId());
  553. userCoupon.setStoreId(userInfo.getStoreId());
  554. userCoupon.setAmount(couponInfo.getAmount());
  555. userCoupon.setBalance(couponInfo.getAmount());
  556. userCoupon.setOperator(operator);
  557. userCoupon.setGroupId(couponInfo.getGroupId());
  558. userCoupon.setMobile(mobile);
  559. userCoupon.setUserId(userInfo.getId());
  560. userCoupon.setStatus(UserCouponStatusEnum.UNUSED.getKey());
  561. userCoupon.setCreateTime(new Date());
  562. userCoupon.setUpdateTime(new Date());
  563. if (couponInfo.getExpireType().equals(CouponExpireTypeEnum.FIX.getKey())) {
  564. userCoupon.setExpireTime(couponInfo.getEndTime());
  565. }
  566. if (couponInfo.getExpireType().equals(CouponExpireTypeEnum.FLEX.getKey())) {
  567. Date expireTime = new Date();
  568. Calendar c = Calendar.getInstance();
  569. c.setTime(expireTime);
  570. c.add(Calendar.DATE, couponInfo.getExpireTime());
  571. expireTime = c.getTime();
  572. userCoupon.setExpireTime(expireTime);
  573. }
  574. // 12位随机数
  575. StringBuffer code = new StringBuffer();
  576. code.append(SeqUtil.getRandomNumber(4));
  577. code.append(SeqUtil.getRandomNumber(4));
  578. code.append(SeqUtil.getRandomNumber(4));
  579. code.append(SeqUtil.getRandomNumber(4));
  580. userCoupon.setCode(code.toString());
  581. userCoupon.setUuid(uuid);
  582. mtUserCouponMapper.insert(userCoupon);
  583. }
  584. }
  585. // 发放记录
  586. MtCouponGroup mtCouponGroup = couponGroupService.queryCouponGroupById(couponInfo.getGroupId());
  587. ReqSendLogDto sendLogDto = new ReqSendLogDto();
  588. sendLogDto.setMerchantId(couponInfo.getMerchantId());
  589. sendLogDto.setType(1);
  590. sendLogDto.setMobile(mobile);
  591. sendLogDto.setUserId(userInfo.getId());
  592. sendLogDto.setFileName("");
  593. sendLogDto.setGroupId(couponInfo.getGroupId());
  594. sendLogDto.setGroupName(mtCouponGroup.getName());
  595. sendLogDto.setCouponId(couponInfo.getId());
  596. sendLogDto.setSendNum(num);
  597. sendLogDto.setOperator(operator);
  598. sendLogDto.setUuid(uuid);
  599. sendLogDto.setMerchantId(couponInfo.getMerchantId());
  600. sendLogDto.setStoreId(couponInfo.getStoreId());
  601. sendLogService.addSendLog(sendLogDto);
  602. if (sendMessage) {
  603. try {
  604. // 发送手机短信
  605. if (StringUtil.isNotEmpty(mobile)) {
  606. List<String> mobileList = new ArrayList<>();
  607. mobileList.add(mobile);
  608. Integer totalNum = 0;
  609. BigDecimal totalMoney = new BigDecimal("0.0");
  610. List<MtCoupon> couponList = queryCouponListByGroupId(couponInfo.getGroupId());
  611. for (MtCoupon coupon : couponList) {
  612. totalNum = totalNum + (coupon.getSendNum() * num);
  613. totalMoney = totalMoney.add((coupon.getAmount().multiply(new BigDecimal(num).multiply(new BigDecimal(coupon.getSendNum())))));
  614. }
  615. Map<String, String> params = new HashMap<>();
  616. params.put("totalNum", totalNum + "");
  617. params.put("totalMoney", totalMoney + "");
  618. sendSmsService.sendSms(couponInfo.getMerchantId(), "received-coupon", mobileList, params);
  619. }
  620. // 发送小程序订阅消息
  621. if (userInfo != null && couponInfo != null && couponInfo.getAmount().compareTo(new BigDecimal("0")) > 0) {
  622. Date nowTime = new Date();
  623. Date sendTime = new Date(nowTime.getTime());
  624. Map<String, Object> params = new HashMap<>();
  625. params.put("name", couponInfo.getName());
  626. params.put("amount", couponInfo.getAmount());
  627. params.put("tips", "您的卡券已到账,请查收~");
  628. weixinService.sendSubscribeMessage(userInfo.getMerchantId(), userInfo.getId(), userInfo.getOpenId(), WxMessageEnum.COUPON_ARRIVAL.getKey(), "pages/user/index", params, sendTime);
  629. }
  630. } catch (Exception e) {
  631. throw new BusinessCheckException("卡券发放失败.");
  632. }
  633. }
  634. }
  635. /**
  636. * 发放卡券
  637. *
  638. * @param couponId 券ID
  639. * @param userIds 会员ID
  640. * @param num 发放套数
  641. * @param uuid 批次号
  642. * @param operator 操作人
  643. * @throws BusinessCheckException
  644. * @return
  645. */
  646. @Override
  647. @Transactional(rollbackFor = Exception.class)
  648. @OperationServiceLog(description = "发放卡券")
  649. public Boolean batchSendCoupon(Integer couponId, List<Integer> userIds, Integer num, String uuid, String operator) throws BusinessCheckException {
  650. if (userIds == null || userIds.size() < 1) {
  651. throw new BusinessCheckException("发放对象异常,卡券发放失败");
  652. }
  653. // 发放人数大于10就不发送消息了
  654. Boolean sendMsg = userIds.size() >= 10 ? false : true;
  655. if (userIds != null && userIds.size() > 0) {
  656. for (Integer userId : userIds) {
  657. sendCoupon(couponId, userId, num, sendMsg, uuid, operator);
  658. }
  659. }
  660. return true;
  661. }
  662. /**
  663. * 核销卡券
  664. *
  665. * @param userCouponId 用户卡券ID
  666. * @param userId 员工会员ID
  667. * @param storeId 店铺ID
  668. * @param orderId 订单ID
  669. * @param amount 核销金额
  670. * @param remark 核销备注
  671. * @throws BusinessCheckException
  672. * @return
  673. */
  674. @Override
  675. @Transactional(rollbackFor = Exception.class)
  676. @OperationServiceLog(description = "核销卡券")
  677. public String useCoupon(Integer userCouponId, Integer userId, Integer storeId, Integer orderId, BigDecimal amount, String remark) throws BusinessCheckException {
  678. MtUserCoupon userCoupon = mtUserCouponMapper.selectById(userCouponId.intValue());
  679. MtOrder orderInfo = null;
  680. if (orderId != null && orderId > 0) {
  681. orderInfo = mtOrderMapper.selectById(orderId);
  682. }
  683. if (userCoupon == null) {
  684. throw new BusinessCheckException("该卡券不存在!");
  685. } else if (!userCoupon.getStatus().equals(UserCouponStatusEnum.UNUSED.getKey()) && !userCoupon.getStatus().equals(UserCouponStatusEnum.UNSEND.getKey())) {
  686. throw new BusinessCheckException("该卡券状态有误,可能已使用或已过期!");
  687. }
  688. MtStore mtStore = null;
  689. if (storeId > 0) {
  690. mtStore = mtStoreMapper.selectById(storeId);
  691. if (null == mtStore) {
  692. throw new BusinessCheckException("该店铺不存在!");
  693. } else if (!mtStore.getStatus().equals(StatusEnum.ENABLED.getKey())) {
  694. throw new BusinessCheckException("该店铺状态有误,可能已禁用");
  695. }
  696. }
  697. // 判断有效期
  698. MtCoupon couponInfo = queryCouponById(userCoupon.getCouponId());
  699. Date begin = couponInfo.getBeginTime();
  700. Date end = couponInfo.getEndTime();
  701. // 领取后有效天数
  702. if (couponInfo.getExpireType().equals(CouponExpireTypeEnum.FLEX.getKey())) {
  703. begin = userCoupon.getCreateTime();
  704. end = userCoupon.getExpireTime();
  705. }
  706. Date now = new Date();
  707. if (now.before(begin)) {
  708. throw new BusinessCheckException("该卡券还没到使用日期");
  709. }
  710. if (end.before(now)) {
  711. throw new BusinessCheckException("该卡券已过期");
  712. }
  713. // 是否在例外日期
  714. Calendar cal = Calendar.getInstance();
  715. Boolean isWeekend = false;
  716. if (cal.get(Calendar.DAY_OF_WEEK) == Calendar.SATURDAY || cal.get(Calendar.DAY_OF_WEEK) == Calendar.SUNDAY) {
  717. isWeekend = true;
  718. }
  719. String exceptTime = couponInfo.getExceptTime();
  720. if (null != exceptTime && !exceptTime.equals("")) {
  721. String[] exceptTimeList = exceptTime.split(",");
  722. if (exceptTimeList.length > 0) {
  723. for (String timeStr : exceptTimeList) {
  724. if (timeStr.equals("weekend")) {
  725. if (isWeekend) {
  726. throw new BusinessCheckException("该卡券在当前日期不可用");
  727. }
  728. } else {
  729. String[] timeItem = exceptTime.split("_");
  730. if (timeItem.length == 2) {
  731. try {
  732. Date startTime = DateUtil.parseDate(timeItem[0], "yyyy-MM-dd HH:mm");
  733. Date endTime = DateUtil.parseDate(timeItem[1], "yyyy-MM-dd HH:mm");
  734. if (now.before(endTime) && now.after(startTime)) {
  735. throw new BusinessCheckException("该卡券在当前日期不可用");
  736. }
  737. } catch (ParseException pe) {
  738. throw new BusinessCheckException("该卡券在当前日期不可用.");
  739. }
  740. }
  741. }
  742. }
  743. }
  744. }
  745. // 使用优惠券,判断满多少可用
  746. if (couponInfo.getType().equals(CouponTypeEnum.COUPON.getKey()) && StringUtil.isNotEmpty(couponInfo.getOutRule())) {
  747. if (orderInfo != null) {
  748. if (orderInfo.getAmount().compareTo(new BigDecimal(couponInfo.getOutRule())) < 0) {
  749. throw new BusinessCheckException("该卡券满"+ couponInfo.getOutRule() +"元才能使用");
  750. }
  751. }
  752. }
  753. // 判断可用店铺
  754. if (StringUtil.isNotEmpty(couponInfo.getStoreIds())) {
  755. if (StringUtil.isNotEmpty(couponInfo.getStoreIds())) {
  756. String[] storeIds = couponInfo.getStoreIds().split(",");
  757. String useStoreId = (orderInfo != null) ? orderInfo.getStoreId().toString() : (storeId > 0 ? storeId.toString() : "");
  758. if (StringUtil.isNotEmpty(useStoreId) && storeIds.length > 0 && !Arrays.asList(storeIds).contains(useStoreId)) {
  759. throw new BusinessCheckException("该卡券不能在当前门店使用");
  760. }
  761. }
  762. }
  763. // 判断适用会员等级
  764. if (userId != null && userId > 0 && StringUtil.isNotEmpty(couponInfo.getGradeIds())) {
  765. MtUser mtUser = memberService.queryMemberById(userId);
  766. if (StringUtil.isEmpty(mtUser.getGradeId())) {
  767. MtUserGrade defaultGrade = userGradeService.getInitUserGrade(mtUser.getMerchantId());
  768. if (defaultGrade != null) {
  769. mtUser.setGradeId(defaultGrade.getId().toString());
  770. } else {
  771. mtUser.setGradeId("0");
  772. }
  773. }
  774. String[] gradeIds = couponInfo.getGradeIds().split(",");
  775. if (gradeIds.length > 0 && !Arrays.asList(gradeIds).contains(mtUser.getGradeId())) {
  776. throw new BusinessCheckException("该卡券不适用该会员等级");
  777. }
  778. }
  779. if (couponInfo.getType().equals(CouponTypeEnum.COUPON.getKey())) {
  780. // 优惠券核销直接修改状态
  781. userCoupon.setStatus(UserCouponStatusEnum.USED.getKey());
  782. } else if (couponInfo.getType().equals(CouponTypeEnum.PRESTORE.getKey())) {
  783. // 储值卡核销,修改余额
  784. BigDecimal balance = userCoupon.getBalance();
  785. BigDecimal newBalance = balance.subtract(amount);
  786. if (newBalance.compareTo(new BigDecimal("0")) == -1) {
  787. throw new BusinessCheckException("余额不足,无法核销");
  788. }
  789. if (newBalance.compareTo(new BigDecimal("0")) == 0) {
  790. userCoupon.setStatus(UserCouponStatusEnum.USED.getKey());
  791. }
  792. userCoupon.setBalance(newBalance);
  793. } else if (couponInfo.getType().equals(CouponTypeEnum.TIMER.getKey())) {
  794. // 计次卡核销,增加核销次数至满
  795. Long confirmCount = confirmLogService.getConfirmNum(userCouponId);
  796. if ((confirmCount.intValue() + 1) >= Integer.parseInt(couponInfo.getOutRule())) {
  797. userCoupon.setStatus(UserCouponStatusEnum.USED.getKey());
  798. }
  799. }
  800. userCoupon.setUpdateTime(new Date());
  801. userCoupon.setUsedTime(new Date());
  802. userCoupon.setStoreId(storeId);
  803. mtUserCouponMapper.updateById(userCoupon);
  804. // 生成核销流水
  805. MtConfirmLog confirmLog = new MtConfirmLog();
  806. confirmLog.setMerchantId(couponInfo.getMerchantId());
  807. StringBuilder code = new StringBuilder();
  808. String sStoreId="00000"+storeId.toString();
  809. code.append(new SimpleDateFormat("yyMMddHHmmss").format(new Date()));
  810. code.append(sStoreId.substring(sStoreId.length()-4));
  811. code.append(SeqUtil.getRandomNumber(6));
  812. confirmLog.setCode(code.toString());
  813. confirmLog.setCouponId(couponInfo.getId());
  814. confirmLog.setUserCouponId(userCouponId.intValue());
  815. confirmLog.setOrderId(orderId);
  816. confirmLog.setCreateTime(new Date());
  817. confirmLog.setUpdateTime(new Date());
  818. confirmLog.setUserId(userCoupon.getUserId());
  819. confirmLog.setOperatorUserId(userId);
  820. MtUser userInfo = null;
  821. if (userId > 0) {
  822. userInfo = memberService.queryMemberById(userId);
  823. if (userInfo != null) {
  824. confirmLog.setOperator(userInfo.getName());
  825. }
  826. }
  827. confirmLog.setStoreId(storeId);
  828. confirmLog.setStatus(StatusEnum.ENABLED.getKey());
  829. // 优惠券核销金额
  830. if (couponInfo.getType().equals(CouponTypeEnum.COUPON.getKey())) {
  831. amount = userCoupon.getAmount();
  832. }
  833. confirmLog.setAmount(amount);
  834. confirmLog.setRemark(remark);
  835. mtConfirmLogMapper.insert(confirmLog);
  836. try {
  837. // 发送核销短信
  838. List<String> mobileList = new ArrayList<>();
  839. mobileList.add(userCoupon.getMobile());
  840. Map<String, String> params = new HashMap<>();
  841. params.put("couponName", couponInfo.getName());
  842. if (mtStore != null){
  843. params.put("storeName", mtStore.getName());
  844. }
  845. params.put("sn", code.toString());
  846. sendSmsService.sendSms(couponInfo.getMerchantId(), "confirm-coupon", mobileList, params);
  847. // 发送小程序订阅消息
  848. Date nowTime = new Date();
  849. Date sendTime = new Date(nowTime.getTime());
  850. Map<String, Object> param = new HashMap<>();
  851. String dateTime = DateUtil.formatDate(Calendar.getInstance().getTime(), "yyyy-MM-dd HH:mm");
  852. params.put("name", couponInfo.getName());
  853. params.put("time", dateTime);
  854. weixinService.sendSubscribeMessage(userInfo.getMerchantId(), userInfo.getId(), userInfo.getOpenId(), WxMessageEnum.COUPON_CONFIRM.getKey(), "pages/user/index", param, sendTime);
  855. } catch (Exception e) {
  856. //empty
  857. }
  858. return confirmLog.getCode();
  859. }
  860. /**
  861. * 根据券ID删除会员卡券
  862. *
  863. * @param id 券ID
  864. * @param operator 操作人
  865. * @throws BusinessCheckException
  866. * @return
  867. */
  868. @Override
  869. @OperationServiceLog(description = "删除会员卡券")
  870. public void deleteUserCoupon(Integer id, String operator) throws BusinessCheckException {
  871. MtUserCoupon userCoupon = mtUserCouponMapper.selectById(id);
  872. if (null == userCoupon) {
  873. return;
  874. }
  875. // 未使用状态才能作废删除
  876. if(!userCoupon.getStatus().equals(UserCouponStatusEnum.UNUSED.getKey())) {
  877. throw new BusinessCheckException("不能作废,该劵状态异常");
  878. }
  879. userCoupon.setStatus(UserCouponStatusEnum.DISABLE.getKey());
  880. // 修改时间
  881. userCoupon.setUpdateTime(new Date());
  882. // 操作人
  883. userCoupon.setOperator(operator);
  884. // 更新发券日志为部分作废状态
  885. mtSendLogMapper.updateSingleForRemove(userCoupon.getUuid(),UserCouponStatusEnum.USED.getKey());
  886. mtUserCouponMapper.updateById(userCoupon);
  887. }
  888. /**
  889. * 根据券ID 撤销卡券核销
  890. *
  891. * @param id 核销流水ID
  892. * @param userCouponId 用户卡券ID
  893. * @param operator 操作人
  894. * @throws BusinessCheckException
  895. * @return
  896. */
  897. @Override
  898. @Transactional(rollbackFor = Exception.class)
  899. @OperationServiceLog(description = "撤销卡券核销")
  900. public void rollbackUserCoupon(Integer id, Integer userCouponId,String operator) throws BusinessCheckException {
  901. MtConfirmLog mtConfirmLog = mtConfirmLogMapper.selectById(id);
  902. MtUserCoupon userCoupon = mtUserCouponMapper.selectById(userCouponId);
  903. if (null == mtConfirmLog || !mtConfirmLog.getUserCouponId().equals(userCouponId)) {
  904. throw new BusinessCheckException("卡券核销流水不存在!");
  905. }
  906. if (null == userCoupon) {
  907. throw new BusinessCheckException("用户卡券不存在");
  908. }
  909. // 卡券未过期才能撤销,当前时间小于过期日期才能删除,48小时
  910. Calendar endTimecal = Calendar.getInstance();
  911. endTimecal.setTime(mtConfirmLog.getCreateTime());
  912. endTimecal.add(Calendar.DAY_OF_MONTH, 2);
  913. if (endTimecal.getTime().before(new Date())) {
  914. throw new BusinessCheckException("卡券核销已经超过48小时,无法撤销");
  915. }
  916. MtCoupon mtCoupon = mtCouponMapper.selectById(userCoupon.getCouponId());
  917. // 卡券未过期才能撤销,当前时间小于过期日期才能删除
  918. if (mtCoupon.getEndTime().before(new Date())) {
  919. throw new BusinessCheckException("卡券未过期才能撤销");
  920. }
  921. // 优惠券只有是使用状态且核销流水正常状态才能撤销
  922. if(userCoupon.getType().equals(CouponTypeEnum.COUPON.getKey())) {
  923. if ((!userCoupon.getStatus().equals(UserCouponStatusEnum.USED.getKey())) || (!mtConfirmLog.getStatus().equals(StatusEnum.ENABLED.getKey()))) {
  924. throw new BusinessCheckException("该劵状态异常,请稍后重试");
  925. }
  926. }
  927. // 回退至可用状态
  928. userCoupon.setStatus(UserCouponStatusEnum.UNUSED.getKey());
  929. userCoupon.setStoreId(null);
  930. userCoupon.setUsedTime(null);
  931. userCoupon.setUpdateTime(new Date());
  932. // 如果是储值卡则返回余额
  933. if (userCoupon.getType().equals(CouponTypeEnum.PRESTORE.getKey())) {
  934. BigDecimal balance = userCoupon.getBalance();
  935. BigDecimal amount = mtConfirmLog.getAmount();
  936. if (amount.compareTo(new BigDecimal("0")) > 0) {
  937. BigDecimal newBalance = balance.add(amount);
  938. userCoupon.setBalance(newBalance);
  939. }
  940. }
  941. // 更新用户卡券
  942. mtUserCouponMapper.updateById(userCoupon);
  943. // 更新流水
  944. mtConfirmLog.setOperator(operator);
  945. mtConfirmLog.setStatus(StatusEnum.DISABLE.getKey());
  946. mtConfirmLog.setUpdateTime(new Date());
  947. mtConfirmLog.setCancelTime(new Date());
  948. mtConfirmLogMapper.updateById(mtConfirmLog);
  949. }
  950. /**
  951. * 根据ID获取用户卡券信息
  952. * @param userCouponId 查询参数
  953. * @throws BusinessCheckException
  954. * @return
  955. * */
  956. @Override
  957. public MtUserCoupon queryUserCouponById(Integer userCouponId) {
  958. MtUserCoupon userCoupon = mtUserCouponMapper.selectById(userCouponId);
  959. return userCoupon;
  960. }
  961. /**
  962. * 根据批次撤销卡券
  963. *
  964. * @param uuid 批次ID
  965. * @param operator 操作人
  966. * @throws BusinessCheckException
  967. */
  968. @Override
  969. @Transactional(rollbackFor = Exception.class)
  970. @OperationServiceLog(description = "根据批次撤销卡券")
  971. public void removeUserCoupon(Long id, String uuid, String operator) {
  972. Map<String, Object> searchParams = new HashMap<>();
  973. searchParams.put("uuid", uuid);
  974. List<MtUserCoupon> paginationResponse = mtUserCouponMapper.selectByMap(searchParams);
  975. Integer total = paginationResponse.size();
  976. List<Integer> coupondIdList = mtUserCouponMapper.getCouponIdsByUuid(uuid);
  977. List<Integer> couponIds = new ArrayList<>();
  978. couponIds.add(0);
  979. Date nowDate = new Date();
  980. for (int i = 0; i < coupondIdList.size(); i++) {
  981. Integer couponId = coupondIdList.get(i);
  982. MtCoupon couponInfo = queryCouponById(couponId);
  983. if (couponInfo.getStatus().equals(StatusEnum.ENABLED.getKey()) && couponInfo.getEndTime().after(nowDate)) {
  984. couponIds.add(couponId);
  985. }
  986. }
  987. Integer row = mtUserCouponMapper.removeUserCoupon(uuid, couponIds, operator);
  988. if (row.compareTo( total.intValue()) != -1) {
  989. mtSendLogMapper.updateForRemove(uuid, UserCouponStatusEnum.DISABLE.getKey(), total.intValue(), 0);
  990. } else {
  991. mtSendLogMapper.updateForRemove(uuid, UserCouponStatusEnum.USED.getKey(), row, (total.intValue()-row));
  992. }
  993. }
  994. /**
  995. * 判断卡券码是否过期
  996. * @param code 12位券码
  997. * @return
  998. * */
  999. @Override
  1000. public boolean codeExpired(String code) {
  1001. if (StringUtil.isEmpty(code)) {
  1002. return true;
  1003. }
  1004. try {
  1005. Date dateTime = DateUtil.parseDate(code.substring(0, 14), "yyyyMMddHHmmss");
  1006. Long time = dateTime.getTime();
  1007. Long nowTime = System.currentTimeMillis();
  1008. Long seconds = (nowTime - time) / 1000;
  1009. // 超过1小时
  1010. if (seconds > 3600) {
  1011. return true;
  1012. }
  1013. } catch (Exception e) {
  1014. return true;
  1015. }
  1016. return false;
  1017. }
  1018. /**
  1019. * 判断卡券是否过期
  1020. *
  1021. * @param coupon 卡券信息
  1022. * @param userCoupon 会员卡券信息
  1023. * @return
  1024. * */
  1025. @Override
  1026. public boolean isCouponEffective(MtCoupon coupon, MtUserCoupon userCoupon) {
  1027. Date begin = coupon.getBeginTime();
  1028. Date end = coupon.getEndTime();
  1029. if (coupon.getExpireType().equals(CouponExpireTypeEnum.FLEX.getKey())) {
  1030. begin = userCoupon.getCreateTime();
  1031. end = userCoupon.getExpireTime();
  1032. }
  1033. Date now = new Date();
  1034. // 未生效
  1035. if (begin != null) {
  1036. if (now.before(begin)) {
  1037. return false;
  1038. }
  1039. }
  1040. // 已过期
  1041. if (end != null) {
  1042. if (now.after(end)) {
  1043. return false;
  1044. }
  1045. }
  1046. if (coupon.getStatus() == null) {
  1047. return false;
  1048. }
  1049. // 状态异常
  1050. if (!coupon.getStatus().equals(StatusEnum.ENABLED.getKey())) {
  1051. return false;
  1052. }
  1053. return true;
  1054. }
  1055. }