1
0

CouponGroupServiceImpl.java 21 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529
  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.dto.CouponCellDto;
  6. import com.fuint.common.dto.ReqCouponGroupDto;
  7. import com.fuint.common.dto.ReqSendLogDto;
  8. import com.fuint.common.enums.StatusEnum;
  9. import com.fuint.common.service.*;
  10. import com.fuint.common.util.CommonUtil;
  11. import com.fuint.common.util.DateUtil;
  12. import com.fuint.common.util.XlsUtil;
  13. import com.fuint.framework.annoation.OperationServiceLog;
  14. import com.fuint.framework.exception.BusinessCheckException;
  15. import com.fuint.framework.pagination.PaginationRequest;
  16. import com.fuint.framework.pagination.PaginationResponse;
  17. import com.fuint.repository.mapper.MtCouponGroupMapper;
  18. import com.fuint.repository.mapper.MtCouponMapper;
  19. import com.fuint.repository.mapper.MtUserCouponMapper;
  20. import com.fuint.repository.model.*;
  21. import com.fuint.utils.StringUtil;
  22. import com.github.pagehelper.Page;
  23. import com.github.pagehelper.PageHelper;
  24. import lombok.AllArgsConstructor;
  25. import org.apache.commons.lang.StringUtils;
  26. import org.slf4j.Logger;
  27. import org.slf4j.LoggerFactory;
  28. import org.springframework.core.env.Environment;
  29. import org.springframework.data.domain.PageImpl;
  30. import org.springframework.data.domain.PageRequest;
  31. import org.springframework.stereotype.Service;
  32. import org.springframework.transaction.annotation.Transactional;
  33. import org.springframework.util.ResourceUtils;
  34. import org.springframework.web.multipart.MultipartFile;
  35. import javax.servlet.http.HttpServletRequest;
  36. import java.io.File;
  37. import java.io.IOException;
  38. import java.math.BigDecimal;
  39. import java.lang.String;
  40. import java.util.*;
  41. import java.util.regex.Pattern;
  42. /**
  43. * 卡券分组业务实现类
  44. *
  45. * Created by FSQ
  46. * CopyRight https://www.fuint.cn
  47. */
  48. @Service
  49. @AllArgsConstructor
  50. public class CouponGroupServiceImpl extends ServiceImpl<MtCouponGroupMapper, MtCouponGroup> implements CouponGroupService {
  51. private static final Logger log = LoggerFactory.getLogger(CouponGroupServiceImpl.class);
  52. private MtCouponGroupMapper mtCouponGroupMapper;
  53. private MtCouponMapper mtCouponMapper;
  54. private MtUserCouponMapper mtUserCouponMapper;
  55. /**
  56. * 卡券服务接口
  57. * */
  58. private CouponService couponService;
  59. /**
  60. * 会员服务接口
  61. * */
  62. private MemberService memberService;
  63. /**
  64. * 卡券发放记录服务接口
  65. * */
  66. private SendLogService sendLogService;
  67. /**
  68. * 短信发送服务接口
  69. * */
  70. private SendSmsService sendSmsService;
  71. /**
  72. * 系统环境变量
  73. * */
  74. private Environment env;
  75. /**
  76. * 分页查询卡券分组列表
  77. *
  78. * @param paginationRequest
  79. * @return
  80. */
  81. @Override
  82. public PaginationResponse<MtCouponGroup> queryCouponGroupListByPagination(PaginationRequest paginationRequest) {
  83. Page<MtCouponGroup> pageHelper = PageHelper.startPage(paginationRequest.getCurrentPage(), paginationRequest.getPageSize());
  84. LambdaQueryWrapper<MtCouponGroup> lambdaQueryWrapper = Wrappers.lambdaQuery();
  85. lambdaQueryWrapper.ne(MtCouponGroup::getStatus, StatusEnum.DISABLE.getKey());
  86. String name = paginationRequest.getSearchParams().get("name") == null ? "" : paginationRequest.getSearchParams().get("name").toString();
  87. if (StringUtils.isNotBlank(name)) {
  88. lambdaQueryWrapper.like(MtCouponGroup::getName, name);
  89. }
  90. String status = paginationRequest.getSearchParams().get("status") == null ? "" : paginationRequest.getSearchParams().get("status").toString();
  91. if (StringUtils.isNotBlank(status)) {
  92. lambdaQueryWrapper.eq(MtCouponGroup::getStatus, status);
  93. }
  94. String id = paginationRequest.getSearchParams().get("id") == null ? "" : paginationRequest.getSearchParams().get("id").toString();
  95. if (StringUtils.isNotBlank(id)) {
  96. lambdaQueryWrapper.eq(MtCouponGroup::getId, id);
  97. }
  98. String merchantId = paginationRequest.getSearchParams().get("merchantId") == null ? "" : paginationRequest.getSearchParams().get("merchantId").toString();
  99. if (StringUtils.isNotBlank(merchantId)) {
  100. lambdaQueryWrapper.eq(MtCouponGroup::getMerchantId, merchantId);
  101. }
  102. String storeId = paginationRequest.getSearchParams().get("storeId") == null ? "" : paginationRequest.getSearchParams().get("storeId").toString();
  103. if (StringUtils.isNotBlank(storeId)) {
  104. lambdaQueryWrapper.eq(MtCouponGroup::getStoreId, storeId);
  105. }
  106. lambdaQueryWrapper.orderByDesc(MtCouponGroup::getId);
  107. List<MtCouponGroup> dataList = mtCouponGroupMapper.selectList(lambdaQueryWrapper);
  108. PageRequest pageRequest = PageRequest.of(paginationRequest.getCurrentPage(), paginationRequest.getPageSize());
  109. PageImpl pageImpl = new PageImpl(dataList, pageRequest, pageHelper.getTotal());
  110. PaginationResponse<MtCouponGroup> paginationResponse = new PaginationResponse(pageImpl, MtCouponGroup.class);
  111. paginationResponse.setTotalPages(pageHelper.getPages());
  112. paginationResponse.setTotalElements(pageHelper.getTotal());
  113. paginationResponse.setContent(dataList);
  114. return paginationResponse;
  115. }
  116. /**
  117. * 添加卡券分组
  118. *
  119. * @param reqCouponGroupDto
  120. * @throws BusinessCheckException
  121. */
  122. @Override
  123. @OperationServiceLog(description = "新增卡券分组")
  124. public MtCouponGroup addCouponGroup(ReqCouponGroupDto reqCouponGroupDto) {
  125. MtCouponGroup couponGroup = new MtCouponGroup();
  126. couponGroup.setMerchantId(reqCouponGroupDto.getMerchantId());
  127. couponGroup.setStoreId(reqCouponGroupDto.getStoreId());
  128. couponGroup.setName(CommonUtil.replaceXSS(reqCouponGroupDto.getName()));
  129. couponGroup.setMoney(new BigDecimal("0"));
  130. couponGroup.setTotal(0);
  131. couponGroup.setDescription(CommonUtil.replaceXSS(reqCouponGroupDto.getDescription()));
  132. couponGroup.setStatus(StatusEnum.ENABLED.getKey());
  133. couponGroup.setCreateTime(new Date());
  134. couponGroup.setUpdateTime(new Date());
  135. couponGroup.setNum(0);
  136. couponGroup.setOperator(reqCouponGroupDto.getOperator());
  137. this.save(couponGroup);
  138. return couponGroup;
  139. }
  140. /**
  141. * 根据分组ID获取卡券分组信息
  142. *
  143. * @param id 卡券分组ID
  144. * @throws BusinessCheckException
  145. */
  146. @Override
  147. public MtCouponGroup queryCouponGroupById(Integer id) {
  148. return mtCouponGroupMapper.selectById(id);
  149. }
  150. /**
  151. * 根据ID删除卡券分组
  152. *
  153. * @param id 分组ID
  154. * @param operator 操作人
  155. * @throws BusinessCheckException
  156. */
  157. @Override
  158. @OperationServiceLog(description = "删除卡券分组")
  159. public void deleteCouponGroup(Integer id, String operator) {
  160. MtCouponGroup couponGroup = queryCouponGroupById(id);
  161. if (null == couponGroup) {
  162. return;
  163. }
  164. couponGroup.setStatus(StatusEnum.DISABLE.getKey());
  165. couponGroup.setUpdateTime(new Date());
  166. couponGroup.setOperator(operator);
  167. this.updateById(couponGroup);
  168. }
  169. /**
  170. * 修改卡券分组
  171. *
  172. * @param reqcouponGroupDto
  173. * @throws BusinessCheckException
  174. */
  175. @Override
  176. @Transactional(rollbackFor = Exception.class)
  177. @OperationServiceLog(description = "更新卡券分组")
  178. public MtCouponGroup updateCouponGroup(ReqCouponGroupDto reqcouponGroupDto) throws BusinessCheckException {
  179. MtCouponGroup couponGroup = queryCouponGroupById(reqcouponGroupDto.getId());
  180. if (null == couponGroup || StatusEnum.DISABLE.getKey().equalsIgnoreCase(couponGroup.getStatus())) {
  181. throw new BusinessCheckException("该分组不存在或已被删除");
  182. }
  183. if (reqcouponGroupDto.getName() != null) {
  184. couponGroup.setName(CommonUtil.replaceXSS(reqcouponGroupDto.getName()));
  185. }
  186. if (reqcouponGroupDto.getDescription() != null) {
  187. couponGroup.setDescription(CommonUtil.replaceXSS(reqcouponGroupDto.getDescription()));
  188. }
  189. if (couponGroup.getTotal() == null) {
  190. couponGroup.setTotal(0);
  191. }
  192. if (reqcouponGroupDto.getStatus() != null) {
  193. couponGroup.setStatus(reqcouponGroupDto.getStatus());
  194. }
  195. couponGroup.setUpdateTime(new Date());
  196. couponGroup.setOperator(reqcouponGroupDto.getOperator());
  197. this.updateById(couponGroup);
  198. return couponGroup;
  199. }
  200. /**
  201. * 获取卡券种类数量
  202. *
  203. * @param id
  204. * @throws BusinessCheckException
  205. */
  206. @Override
  207. @Transactional(rollbackFor = Exception.class)
  208. public Integer getCouponNum(Integer id) {
  209. Long num = mtCouponMapper.queryNumByGroupId(id);
  210. return num.intValue();
  211. }
  212. /**
  213. * 获取卡券总价值
  214. *
  215. * @param groupId
  216. * @throws BusinessCheckException
  217. */
  218. @Override
  219. @Transactional(rollbackFor = Exception.class)
  220. public BigDecimal getCouponMoney(Integer groupId) {
  221. List<MtCoupon> couponList = mtCouponMapper.queryByGroupId(groupId.intValue());
  222. MtCouponGroup groupInfo = queryCouponGroupById(groupId);
  223. BigDecimal money = BigDecimal.valueOf(0);
  224. if (couponList.size() > 0) {
  225. for (int i = 0; i<couponList.size(); i++) {
  226. BigDecimal number = couponList.get(i).getAmount().multiply(BigDecimal.valueOf(couponList.get(i).getSendNum()));
  227. number = number.multiply(BigDecimal.valueOf(groupInfo.getTotal()));
  228. money = money.add(number);
  229. }
  230. }
  231. return money;
  232. }
  233. /**
  234. * 获取已发放套数
  235. *
  236. * @param couponId 卡券ID
  237. * @throws BusinessCheckException
  238. * */
  239. @Override
  240. public Integer getSendNum(Integer couponId) {
  241. Long num = mtUserCouponMapper.getSendNum(couponId);
  242. return num.intValue();
  243. }
  244. /**
  245. * 导入发券列表
  246. *
  247. * @param file excel文件
  248. * @param operator 操作者
  249. * */
  250. @Override
  251. @Transactional(rollbackFor = Exception.class)
  252. @OperationServiceLog(description = "导入发券列表")
  253. public String importSendCoupon(MultipartFile file, String operator, String filePath) throws BusinessCheckException {
  254. String originalFileName = file.getOriginalFilename();
  255. boolean isExcel2003 = XlsUtil.isExcel2003(originalFileName);
  256. boolean isExcel2007 = XlsUtil.isExcel2007(originalFileName);
  257. if (!isExcel2003 && !isExcel2007) {
  258. log.error("importSendCouponController->uploadFile:{}", "文件类型不正确");
  259. throw new BusinessCheckException("文件类型不正确");
  260. }
  261. List<List<String>> content = new ArrayList<>();
  262. try {
  263. content = XlsUtil.readExcelContent(file.getInputStream(), isExcel2003, 1, null, null, null);
  264. } catch (IOException e) {
  265. log.error("CouponGroupServiceImpl->parseExcelContent{}", e);
  266. throw new BusinessCheckException("导入失败"+e.getMessage());
  267. } catch (Exception e) {
  268. e.printStackTrace();
  269. }
  270. StringBuffer errorMsg = new StringBuffer();
  271. StringBuffer errorMsgNoGroup = new StringBuffer();
  272. StringBuffer errorMsgNoNum = new StringBuffer();
  273. StringBuffer errorMsgNoRegister = new StringBuffer();
  274. List<CouponCellDto> rows = new ArrayList<>();
  275. for (int i = 0; i < content.size(); i++) {
  276. List<Integer> groupIdArr = new ArrayList<>();
  277. List<Integer> numArr = new ArrayList<>();
  278. List<String> rowContent = content.get(i);
  279. String mobile = rowContent.get(0);
  280. String merchantId = rowContent.get(1);
  281. if (StringUtil.isBlank(mobile) || mobile.length() < 11 || mobile.length() > 11) {
  282. errorMsg.append("第" + i + "行错误,手机号有误:"+mobile);
  283. continue;
  284. }
  285. for (int j = 1; j < rowContent.size(); j++) {
  286. Integer item = 0;
  287. String cellContent = rowContent.get(j);
  288. if (null == cellContent || cellContent.equals("")) {
  289. continue;
  290. }
  291. Pattern pattern = Pattern.compile("^[1-9]\\d*$");
  292. if ((j%2) != 0) {
  293. if (item == null || (!pattern.matcher(cellContent).matches())) {
  294. throw new BusinessCheckException("第" + (i+1) + "行第"+ j +"列错误, 卡券ID异常");
  295. }
  296. item = Integer.parseInt(cellContent);
  297. if (item < 0) {
  298. errorMsg.append("第" + (i+1) + "行第"+ j +"列错误, 卡券ID异常");
  299. continue;
  300. }
  301. groupIdArr.add(item);
  302. } else {
  303. if (item == null || (!pattern.matcher(rowContent.get(j)).matches())) {
  304. throw new BusinessCheckException("第" + (i+1) + "行第"+ j +"列错误, 数量异常");
  305. }
  306. item = Integer.parseInt(rowContent.get(j));
  307. if (item < 0) {
  308. errorMsg.append("第" + (i+1) + "行第"+ j +"列错误, 数量异常");
  309. continue;
  310. }
  311. numArr.add(item);
  312. }
  313. }
  314. if (groupIdArr.size() != numArr.size()) {
  315. throw new BusinessCheckException("表格数据有问题导致无法导入");
  316. }
  317. CouponCellDto item = new CouponCellDto();
  318. item.setMobile(mobile);
  319. item.setGroupId(groupIdArr);
  320. item.setNum(numArr);
  321. item.setMerchantId(Integer.parseInt(merchantId));
  322. rows.add(item);
  323. }
  324. if (rows.size() < 1) {
  325. throw new BusinessCheckException("表格数据为空导致无法导入");
  326. }
  327. if (rows.size() > 1000) {
  328. throw new BusinessCheckException("每次导入最多不能超过1000人");
  329. }
  330. // 获取每个分组的总数
  331. Map<String, Integer> couponIdMap = new HashMap<>();
  332. for (CouponCellDto dto : rows) {
  333. MtUser userInfo = memberService.queryMemberByMobile(dto.getMerchantId(), dto.getMobile());
  334. if (userInfo == null) {
  335. userInfo = memberService.addMemberByMobile(dto.getMerchantId(), dto.getMobile(), "0", "");
  336. }
  337. if (null == userInfo || !userInfo.getStatus().equals(StatusEnum.ENABLED.getKey())) {
  338. if (StringUtil.isNotBlank(errorMsgNoGroup.toString())) {
  339. errorMsgNoGroup.append("," + dto.getMobile());
  340. } else {
  341. errorMsgNoGroup.append("手机号没有注册或已禁用:"+dto.getMobile());
  342. }
  343. }
  344. for (int k = 0; k < dto.getGroupId().size(); k++) {
  345. Integer num = dto.getNum().get(k);
  346. Integer total = couponIdMap.get(dto.getGroupId().get(k).toString()) == null ? 0 : couponIdMap.get(dto.getGroupId().get(k).toString());
  347. couponIdMap.put(dto.getGroupId().get(k).toString(), (total+num));
  348. }
  349. }
  350. if (StringUtil.isNotBlank(errorMsgNoRegister.toString())) {
  351. throw new BusinessCheckException(errorMsgNoRegister.toString());
  352. }
  353. for (String couponId : couponIdMap.keySet()) {
  354. MtCoupon couponInfo = couponService.queryCouponById(Integer.parseInt(couponId));
  355. if (null == couponInfo) {
  356. if (StringUtil.isNotBlank(errorMsgNoGroup.toString())) {
  357. errorMsgNoGroup.append("," + couponId);
  358. } else {
  359. errorMsgNoGroup.append("卡券ID不存在:"+couponId);
  360. }
  361. continue;
  362. }
  363. if (!couponInfo.getStatus().equals(StatusEnum.ENABLED.getKey())) {
  364. throw new BusinessCheckException("卡券ID"+couponId+"可能已删除或禁用");
  365. }
  366. Integer totalNum = couponInfo.getTotal() == null ? 0 : couponInfo.getTotal();
  367. Integer sendNum = couponIdMap.get(couponId);
  368. Integer hasSendNum = getSendNum(Integer.parseInt(couponId));
  369. if (totalNum > 0 && ((totalNum - hasSendNum) < sendNum)) {
  370. Integer needNum = sendNum - (totalNum - hasSendNum);
  371. if (StringUtil.isNotBlank(errorMsgNoNum.toString())) {
  372. errorMsgNoNum.append(";卡券ID:" + couponId + "存量不足,至少再添加" + needNum + "套");
  373. } else {
  374. errorMsgNoNum.append("卡券ID:" + couponId + "存量不足,至少再添加" + needNum + "套");
  375. }
  376. }
  377. }
  378. if (StringUtil.isNotBlank(errorMsgNoGroup.toString())) {
  379. throw new BusinessCheckException(errorMsgNoGroup.toString());
  380. }
  381. if (StringUtil.isNotBlank(errorMsgNoNum.toString())) {
  382. throw new BusinessCheckException(errorMsgNoNum.toString());
  383. }
  384. if (StringUtil.isNotBlank(errorMsg.toString())) {
  385. throw new BusinessCheckException(errorMsg.toString());
  386. }
  387. // 导入批次
  388. String uuid = UUID.randomUUID().toString().replaceAll("-", "");
  389. // 至此,验证都通过了,开始发券
  390. try {
  391. for (CouponCellDto cellDto : rows) {
  392. // 发送张数
  393. Integer totalNum = 0;
  394. // 发送总价值
  395. BigDecimal totalMoney = new BigDecimal("0.0");
  396. for (int gid = 0; gid < cellDto.getGroupId().size(); gid++) {
  397. MtCouponGroup mtCouponGroup = getById(cellDto.getGroupId().get(gid).intValue());
  398. MtUser mtUser = memberService.queryMemberByMobile(mtCouponGroup.getMerchantId(), cellDto.getMobile());
  399. couponService.sendCoupon(cellDto.getGroupId().get(gid).intValue(), mtUser.getId(), cellDto.getNum().get(gid), false, uuid, operator);
  400. List<MtCoupon> couponList = couponService.queryCouponListByGroupId(cellDto.getGroupId().get(gid).intValue());
  401. // 累加总张数、总价值
  402. for (MtCoupon coupon : couponList) {
  403. totalNum = totalNum + (coupon.getSendNum()*cellDto.getNum().get(gid));
  404. totalMoney = totalMoney.add((coupon.getAmount().multiply(new BigDecimal(cellDto.getNum().get(gid)).multiply(new BigDecimal(coupon.getSendNum())))));
  405. }
  406. }
  407. MtUser mtUser = memberService.queryMemberByMobile(cellDto.getMerchantId(), cellDto.getMobile());
  408. // 发放记录
  409. ReqSendLogDto dto = new ReqSendLogDto();
  410. dto.setMerchantId(cellDto.getMerchantId());
  411. dto.setType(2);
  412. dto.setMobile(cellDto.getMobile());
  413. dto.setUserId(mtUser.getId());
  414. dto.setFileName(originalFileName);
  415. dto.setFilePath(filePath);
  416. dto.setGroupId(0);
  417. dto.setCouponId(0);
  418. dto.setGroupName("");
  419. dto.setSendNum(0);
  420. dto.setOperator(operator);
  421. dto.setUuid(uuid);
  422. sendLogService.addSendLog(dto);
  423. // 发送短信
  424. try {
  425. List<String> mobileList = new ArrayList<>();
  426. mobileList.add(cellDto.getMobile());
  427. Map<String, String> params = new HashMap<>();
  428. params.put("totalNum", totalNum+"");
  429. params.put("totalMoney", totalMoney+"");
  430. sendSmsService.sendSms(cellDto.getMerchantId(), "received-coupon", mobileList, params);
  431. } catch (Exception e) {
  432. log.error("发券发送短信出错:", e.getMessage());
  433. }
  434. }
  435. } catch (BusinessCheckException e) {
  436. throw new BusinessCheckException(e.getMessage());
  437. }
  438. return uuid;
  439. }
  440. /**
  441. * 保存文件
  442. *
  443. * @param file excel文件
  444. * @param request
  445. * */
  446. public String saveExcelFile(MultipartFile file, HttpServletRequest request) throws Exception {
  447. String fileName = file.getOriginalFilename();
  448. String imageName = fileName.substring(fileName.lastIndexOf("."));
  449. String pathRoot = env.getProperty("images.root");
  450. if (pathRoot == null || StringUtil.isEmpty(pathRoot)) {
  451. pathRoot = ResourceUtils.getURL("classpath:").getPath();
  452. }
  453. String uuid = UUID.randomUUID().toString().replaceAll("-", "");
  454. String filePath = "/static/uploadFiles/"+ DateUtil.formatDate(new Date(), "yyyyMMdd")+"/";
  455. String path = filePath + uuid + imageName;
  456. try {
  457. File tempFile = new File(pathRoot + path);
  458. if (!tempFile.getParentFile().exists()) {
  459. tempFile.getParentFile().mkdirs();
  460. }
  461. CommonUtil.saveMultipartFile(file, pathRoot + path);
  462. } catch (Exception e) {
  463. log.error("上传保存文件出错:", e.getMessage());
  464. }
  465. return path;
  466. }
  467. }