DeviceSimChargeServiceImpl.java 20 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396
  1. package com.xy.service;
  2. import cn.hutool.core.collection.CollUtil;
  3. import cn.hutool.core.map.MapUtil;
  4. import com.alibaba.excel.annotation.ExcelProperty;
  5. import com.alibaba.excel.annotation.write.style.ColumnWidth;
  6. import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
  7. import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
  8. import com.baomidou.mybatisplus.core.metadata.IPage;
  9. import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
  10. import com.github.yitter.idgen.YitIdHelper;
  11. import com.xy.collections.list.JArrayList;
  12. import com.xy.collections.list.JList;
  13. import com.xy.config.DeviceThreadPoolConfig;
  14. import com.xy.config.FileConfig;
  15. import com.xy.device.EnumSimConfig;
  16. import com.xy.dto.DeviceSimChargeDto;
  17. import com.xy.dto.MercFeeConfigDto;
  18. import com.xy.dto.OrderMercManageDto;
  19. import com.xy.dto.be.MercDto;
  20. import com.xy.entity.DeviceSim;
  21. import com.xy.entity.DeviceSimCharge;
  22. import com.xy.entity.SysDictRedis;
  23. import com.xy.mapper.DeviceSimChargeMapper;
  24. import com.xy.service.be.MercService;
  25. import com.xy.util.ExcelUtils;
  26. import com.xy.utils.*;
  27. import io.swagger.annotations.Api;
  28. import io.swagger.annotations.ApiOperation;
  29. import lombok.AllArgsConstructor;
  30. import lombok.Data;
  31. import lombok.SneakyThrows;
  32. import lombok.experimental.Accessors;
  33. import org.springframework.stereotype.Service;
  34. import org.springframework.web.bind.annotation.PostMapping;
  35. import org.springframework.web.bind.annotation.RequestBody;
  36. import javax.servlet.http.HttpServletResponse;
  37. import java.io.File;
  38. import java.io.InputStream;
  39. import java.io.OutputStream;
  40. import java.time.LocalDateTime;
  41. import java.util.ArrayList;
  42. import java.util.Arrays;
  43. import java.util.List;
  44. import java.util.Map;
  45. import java.util.stream.Collectors;
  46. import static com.xy.utils.Beans.copy;
  47. import static com.xy.utils.PlusBeans.toIPage;
  48. import static com.xy.utils.PlusBeans.toPageBean;
  49. /**
  50. * <p>
  51. * 设备流量卡充值表 服务实现类
  52. * </p>
  53. *
  54. * @author lijin
  55. * @since 2023-10-16
  56. */
  57. @Service
  58. @AllArgsConstructor
  59. @Api(tags = "设备流量卡充值表")
  60. public class DeviceSimChargeServiceImpl extends ServiceImpl<DeviceSimChargeMapper, DeviceSimCharge> implements DeviceSimChargeService {
  61. private OrderMercManageService orderMercManageService;
  62. private MercService mercService;
  63. private DeviceChargingHistoryServiceImpl deviceChargingHistoryService;
  64. private HttpServletResponse response;
  65. private FileConfig fileConfig;
  66. private MercFeeConfigService mercFeeConfigService;
  67. private DeviceSimServiceImpl deviceSimService;
  68. @PostMapping("page")
  69. @ApiOperation("分页查询")
  70. public R<PageBean<DeviceSimChargeDto.Vo>> page(@RequestBody DeviceSimChargeDto.Page page) {
  71. PageBean pageBean = page.getPage();
  72. LambdaQueryWrapper<DeviceSimCharge> lambdaQueryWrapper = new MybatisPlusQuery().eqWrapper(page, DeviceSimCharge.class)
  73. .ge(DeviceSimCharge::getCreateTime, page.getBeginCreateTime())
  74. .le(DeviceSimCharge::getCreateTime, page.getEndCreateTime())
  75. .build()
  76. .orderByDesc(!Emptys.check(pageBean.getOrders()), DeviceSimCharge::getCreateTime);
  77. IPage<DeviceSimCharge> iPage = page(toIPage(pageBean), lambdaQueryWrapper);
  78. PageBean<DeviceSimChargeDto.Vo> voPageBean = toPageBean(DeviceSimChargeDto.Vo.class, iPage);
  79. List<DeviceSimChargeDto.Vo> records = voPageBean.getRecords();
  80. if (Emptys.check(records)) {
  81. copy(records)
  82. .target(() -> orderMercManageService.list(new OrderMercManageDto.SelectList().setId(new JArrayList<>(records).getProperty(DeviceSimChargeDto.Vo::getOrderId))).getData()
  83. , DeviceSimChargeDto.Vo::getOrderId, DeviceSimChargeDto.Vo::getFiles, OrderMercManageDto.Vo::getId, OrderMercManageDto.Vo::getFiles
  84. ).target(() -> mercService.list(new MercDto.SelectList().setMercIds(new JArrayList<>(records).getProperty(DeviceSimChargeDto.Vo::getMercId).comparing())).getData()
  85. , DeviceSimChargeDto.Vo::getMercId, DeviceSimChargeDto.Vo::getMercName, MercDto.Vo::getId, MercDto.Vo::getName)
  86. .builder();
  87. }
  88. return R.ok(voPageBean);
  89. }
  90. public R<PageBean<DeviceSimChargeDto.PageByTopMercVO>> pageByTopMerc(DeviceSimChargeDto.PageByTopMerc page) {
  91. Long curMercId = page.getCurMercId();
  92. Long chooseMercId = page.getChooseMercId();
  93. List<Long> mercIds = new ArrayList<>();
  94. if (chooseMercId == null) {
  95. mercIds = R.feignCheckData(mercService.getChildMercIds(new MercDto.QuerySubDTO().setParentMercID(curMercId)));
  96. } else {
  97. // 指定商户ID
  98. mercIds.add(chooseMercId);
  99. }
  100. if (CollUtil.isEmpty(mercIds)) {
  101. return R.ok();
  102. }
  103. PageBean pageBean = page.getPage();
  104. LambdaQueryWrapper<DeviceSimCharge> lambdaQueryWrapper = new MybatisPlusQuery().eqWrapper(page, DeviceSimCharge.class)
  105. .ge(DeviceSimCharge::getCreateTime, page.getBeginCreateTime())
  106. .le(DeviceSimCharge::getCreateTime, page.getEndCreateTime())
  107. .in(DeviceSimCharge::getMercId, mercIds)
  108. .build()
  109. .orderByDesc(!Emptys.check(pageBean.getOrders()), DeviceSimCharge::getCreateTime);
  110. IPage<DeviceSimCharge> iPage = page(toIPage(pageBean), lambdaQueryWrapper);
  111. PageBean<DeviceSimChargeDto.PageByTopMercVO> voPageBean = toPageBean(DeviceSimChargeDto.PageByTopMercVO.class, iPage);
  112. List<DeviceSimChargeDto.PageByTopMercVO> records = voPageBean.getRecords();
  113. if (Emptys.check(records)) {
  114. // 佣金配置查询
  115. List<MercFeeConfigDto.ListFeeConfigByMercVO> feeConfigByMercVOS = R.feignCheckData(mercFeeConfigService.listFeeConfigByMerc(new MercFeeConfigDto.ListFeeConfigByMercDTO().setMercId(curMercId)));
  116. Map<Long, MercFeeConfigDto.ListFeeConfigByMercVO> configByMercVOMap = MapUtil.newHashMap();
  117. if (CollUtil.isNotEmpty(feeConfigByMercVOS)) {
  118. configByMercVOMap = feeConfigByMercVOS.stream().collect(Collectors.toMap(MercFeeConfigDto.ListFeeConfigByMercVO::getMercId, f -> f));
  119. }
  120. copy(records)
  121. .target(() -> orderMercManageService.list(new OrderMercManageDto.SelectList().setId(new JArrayList<>(records).getProperty(DeviceSimChargeDto.PageByTopMercVO::getOrderId))).getData()
  122. , DeviceSimChargeDto.PageByTopMercVO::getOrderId, DeviceSimChargeDto.PageByTopMercVO::getFiles, OrderMercManageDto.Vo::getId, OrderMercManageDto.Vo::getFiles
  123. ).target(() -> mercService.list(new MercDto.SelectList().setMercIds(new JArrayList<>(records).getProperty(DeviceSimChargeDto.PageByTopMercVO::getMercId).comparing())).getData()
  124. , DeviceSimChargeDto.PageByTopMercVO::getMercId, DeviceSimChargeDto.PageByTopMercVO::getMercName, MercDto.Vo::getId, MercDto.Vo::getName)
  125. .builder();
  126. List<String> simIds = records.stream().map(DeviceSimChargeDto.PageByTopMercVO::getSimId).collect(Collectors.toList());
  127. List<DeviceSim> deviceSims = deviceSimService.listByIds(simIds);
  128. Map<String, DeviceSim> deviceSimMap = MapUtil.newHashMap();
  129. if (CollUtil.isNotEmpty(deviceSims)) {
  130. deviceSimMap = deviceSims.stream().collect(Collectors.toMap(DeviceSim::getId, ds -> ds));
  131. }
  132. Map<String, SysDictRedis> simConfig = SysDictUtils.get(EnumSimConfig.Code.CODE.getCode());
  133. Integer value = Integer.valueOf(simConfig.get(EnumSimConfig.N_200.getCode()).getValue());
  134. for (DeviceSimChargeDto.PageByTopMercVO record : records) {
  135. Long mercId = record.getMercId();
  136. String simId = record.getSimId();
  137. // 佣金初始化
  138. Integer extraMoney = 0;
  139. MercFeeConfigDto.ListFeeConfigByMercVO listFeeConfigByMercVO = configByMercVOMap.get(mercId);
  140. if (listFeeConfigByMercVO != null) {
  141. extraMoney = listFeeConfigByMercVO.getFeeConfig().getFeeSimcard();
  142. record.setAgentMoney(extraMoney);
  143. }
  144. DeviceSim sim = deviceSimMap.get(simId);
  145. // 封装过期状态说明
  146. if (Emptys.check(sim)) {
  147. LocalDateTime timeout = sim.getTimeout();
  148. if (timeout == null) {
  149. record.setTimeoutStatus("未初始化");
  150. } else {
  151. String timeoutStatus;
  152. long s = DataTime.diff(LocalDateTime.now(), timeout, "s");
  153. if (s <= 0) {
  154. timeoutStatus = "欠费(" + (~(s / 86400 - 1)) + "天)";
  155. } else {
  156. timeoutStatus = s <= value * 86400 ? "即将到期(" + s / 86400 + "天)" : "正常(" + s / 86400 + "天)";
  157. }
  158. record.setTimeoutStatus(timeoutStatus);
  159. }
  160. record.setTimeout(timeout);
  161. }
  162. }
  163. }
  164. return R.ok(voPageBean);
  165. }
  166. /**
  167. * 财务管理-支出管理-流量卡费明细
  168. *
  169. * @param page
  170. * @return
  171. */
  172. public R<PageBean<DeviceSimChargeDto.MySpendPageVO>> mySpendPage(DeviceSimChargeDto.PageByTopMerc page) {
  173. Long curMercId = page.getCurMercId();
  174. List<Long> mercIds = new ArrayList<>();
  175. // 指定商户ID
  176. mercIds.add(curMercId);
  177. PageBean pageBean = page.getPage();
  178. LambdaQueryWrapper<DeviceSimCharge> lambdaQueryWrapper = new MybatisPlusQuery().eqWrapper(page, DeviceSimCharge.class)
  179. .ge(DeviceSimCharge::getCreateTime, page.getBeginCreateTime())
  180. .le(DeviceSimCharge::getCreateTime, page.getEndCreateTime())
  181. .in(DeviceSimCharge::getMercId, mercIds)
  182. .build()
  183. .orderByDesc(!Emptys.check(pageBean.getOrders()), DeviceSimCharge::getCreateTime);
  184. IPage<DeviceSimCharge> iPage = page(toIPage(pageBean), lambdaQueryWrapper);
  185. PageBean<DeviceSimChargeDto.MySpendPageVO> voPageBean = toPageBean(DeviceSimChargeDto.MySpendPageVO.class, iPage);
  186. List<DeviceSimChargeDto.MySpendPageVO> records = voPageBean.getRecords();
  187. if (Emptys.check(records)) {
  188. copy(records)
  189. .target(() -> orderMercManageService.list(new OrderMercManageDto.SelectList().setId(new JArrayList<>(records).getProperty(DeviceSimChargeDto.MySpendPageVO::getOrderId))).getData()
  190. , DeviceSimChargeDto.MySpendPageVO::getOrderId, DeviceSimChargeDto.MySpendPageVO::getFiles, OrderMercManageDto.Vo::getId, OrderMercManageDto.Vo::getFiles
  191. ).target(() -> mercService.list(new MercDto.SelectList().setMercIds(new JArrayList<>(records).getProperty(DeviceSimChargeDto.MySpendPageVO::getMercId).comparing())).getData()
  192. , DeviceSimChargeDto.MySpendPageVO::getMercId, DeviceSimChargeDto.MySpendPageVO::getMercName, MercDto.Vo::getId, MercDto.Vo::getName)
  193. .builder();
  194. List<String> simIds = records.stream().map(DeviceSimChargeDto.MySpendPageVO::getSimId).collect(Collectors.toList());
  195. List<DeviceSim> deviceSims = deviceSimService.listByIds(simIds);
  196. Map<String, DeviceSim> deviceSimMap = MapUtil.newHashMap();
  197. if (CollUtil.isNotEmpty(deviceSims)) {
  198. deviceSimMap = deviceSims.stream().collect(Collectors.toMap(DeviceSim::getId, ds -> ds));
  199. }
  200. Map<String, SysDictRedis> simConfig = SysDictUtils.get(EnumSimConfig.Code.CODE.getCode());
  201. Integer value = Integer.valueOf(simConfig.get(EnumSimConfig.N_200.getCode()).getValue());
  202. for (DeviceSimChargeDto.MySpendPageVO record : records) {
  203. Long mercId = record.getMercId();
  204. String simId = record.getSimId();
  205. DeviceSim sim = deviceSimMap.get(simId);
  206. // 封装过期状态说明
  207. if (Emptys.check(sim)) {
  208. LocalDateTime timeout = sim.getTimeout();
  209. if (timeout == null) {
  210. record.setTimeoutStatus("未初始化");
  211. } else {
  212. String timeoutStatus;
  213. long s = DataTime.diff(LocalDateTime.now(), timeout, "s");
  214. if (s <= 0) {
  215. timeoutStatus = "欠费(" + (~(s / 86400 - 1)) + "天)";
  216. } else {
  217. timeoutStatus = s <= value * 86400 ? "即将到期(" + s / 86400 + "天)" : "正常(" + s / 86400 + "天)";
  218. }
  219. record.setTimeoutStatus(timeoutStatus);
  220. }
  221. record.setTimeout(timeout);
  222. }
  223. }
  224. }
  225. return R.ok(voPageBean);
  226. }
  227. @ApiOperation("月统计分页")
  228. @PostMapping("moonCountPage")
  229. public R<PageBean<DeviceSimChargeDto.MoonCountVo>> moonCountPage(@RequestBody DeviceSimChargeDto.MoonCountPage moonCountPage) {
  230. JList<DeviceSimChargeDto.MoonCountVo> moonCountVos = new JArrayList<>();
  231. // 查询数据
  232. List<String> attrNames = Arrays.asList(
  233. LambdaUtils.getUnderlineCaseName(DeviceSimCharge::getMercId)
  234. );
  235. List<String> selectNames = Arrays.asList(
  236. attrNames.get(0),
  237. String.format("count(*) %s", LambdaUtils.getProperty(DeviceSimCharge::getSize)),
  238. String.format("sum(%s) %s", LambdaUtils.getUnderlineCaseName(DeviceSimCharge::getMoney), LambdaUtils.getProperty(DeviceSimCharge::getMoney))
  239. );
  240. QueryWrapper<DeviceSimCharge> queryWrapper = new QueryWrapper<DeviceSimCharge>()
  241. .select(selectNames.toArray(new String[selectNames.size()]))
  242. .in(Emptys.check(moonCountPage.getMercIds()), attrNames.get(0), moonCountPage.getMercIds())
  243. .between("DATE_FORMAT(" + LambdaUtils.getUnderlineCaseName(DeviceSimCharge::getCreateTime) + ", '%Y-%m-%d')", moonCountPage.getBeginDate(), moonCountPage.getEndDate())
  244. .groupBy(attrNames);
  245. IPage<DeviceSimCharge> iPage = page(toIPage(moonCountPage.getPage()), queryWrapper);
  246. List<DeviceSimCharge> records = iPage.getRecords();
  247. if (!Emptys.check(records)) {
  248. return R.ok(new PageBean<>());
  249. }
  250. String date = String.format("%s~%s", moonCountPage.getBeginDate(), moonCountPage.getEndDate());
  251. records.forEach(deviceSimCharge -> {
  252. DeviceSimChargeDto.MoonCountVo moonCountVo = new DeviceSimChargeDto.MoonCountVo()
  253. .setDate(date)
  254. .setMercId(deviceSimCharge.getMercId())
  255. .setSimSize(deviceSimCharge.getSize())
  256. .setMoney(deviceSimCharge.getMoney());
  257. moonCountVos.add(moonCountVo);
  258. });
  259. // 翻译商户名称
  260. Beans.copy(moonCountVos).target(() -> mercService.list(new MercDto.SelectList().setMercIds(moonCountVos.getProperty(DeviceSimChargeDto.MoonCountVo::getMercId).comparing())).getData(),
  261. DeviceSimChargeDto.MoonCountVo::getMercId, DeviceSimChargeDto.MoonCountVo::getMercName, MercDto.Vo::getId, MercDto.Vo::getName)
  262. .builder();
  263. PageBean<DeviceSimChargeDto.MoonCountVo> pageBean = new PageBean<DeviceSimChargeDto.MoonCountVo>()
  264. .setCurrent(iPage.getCurrent())
  265. .setSize(iPage.getSize())
  266. .setTotal(iPage.getTotal())
  267. .setRecords(moonCountVos);
  268. return R.ok(pageBean);
  269. }
  270. @ApiOperation("月统计")
  271. @PostMapping("moonCount")
  272. public R<List<DeviceSimChargeDto.MoonCountVo>> moonCount(@RequestBody DeviceSimChargeDto.MoonCount moonCount) {
  273. JList<DeviceSimChargeDto.MoonCountVo> moonCountVos = new JArrayList<>();
  274. // 查询数据
  275. List<String> attrNames = Arrays.asList(
  276. LambdaUtils.getUnderlineCaseName(DeviceSimCharge::getMercId),
  277. "DATE_FORMAT(" + LambdaUtils.getUnderlineCaseName(DeviceSimCharge::getCreateTime) + ", '%Y-%m')"
  278. );
  279. List<String> selectNames = Arrays.asList(
  280. attrNames.get(0),
  281. attrNames.get(1) + " " + LambdaUtils.getProperty(DeviceSimCharge::getNote),
  282. String.format("count(*) %s", LambdaUtils.getProperty(DeviceSimCharge::getSize)),
  283. String.format("sum(%s) %s", LambdaUtils.getUnderlineCaseName(DeviceSimCharge::getMoney), LambdaUtils.getProperty(DeviceSimCharge::getMoney))
  284. );
  285. List<String> dateDifference = deviceChargingHistoryService.getDateDifference(moonCount.getBeginDate(), moonCount.getEndDate());
  286. ThreadPoolUtils.Execute execute = ThreadPoolUtils.excPoll(DeviceThreadPoolConfig.DEVICE_COMMON_POLL, dateDifference.size());
  287. dateDifference.forEach(date -> execute.execute(() -> {
  288. QueryWrapper<DeviceSimCharge> queryWrapper = new QueryWrapper<DeviceSimCharge>()
  289. .select(selectNames.get(0), selectNames.get(1), selectNames.get(2), selectNames.get(3))
  290. .in(Emptys.check(moonCount.getMercIds()), attrNames.get(0), moonCount.getMercIds())
  291. .eq(attrNames.get(1), date)
  292. .groupBy(attrNames.get(0), attrNames.get(1));
  293. List<DeviceSimCharge> deviceSimCharges = list(queryWrapper);
  294. deviceSimCharges.forEach(deviceSimCharge -> {
  295. DeviceSimChargeDto.MoonCountVo moonCountVo = new DeviceSimChargeDto.MoonCountVo()
  296. .setDate(deviceSimCharge.getNote())
  297. .setMercId(deviceSimCharge.getMercId())
  298. .setSimSize(deviceSimCharge.getSize())
  299. .setMoney(deviceSimCharge.getMoney());
  300. moonCountVos.add(moonCountVo);
  301. });
  302. }));
  303. execute.end();
  304. // 翻译商户名称
  305. Beans.copy(moonCountVos).target(() -> mercService.list(new MercDto.SelectList().setMercIds(moonCountVos.getProperty(DeviceSimChargeDto.MoonCountVo::getMercId).comparing())).getData(),
  306. DeviceSimChargeDto.MoonCountVo::getMercId, DeviceSimChargeDto.MoonCountVo::getMercName, MercDto.Vo::getId, MercDto.Vo::getName)
  307. .builder();
  308. return R.ok(moonCountVos.desc(DeviceSimChargeDto.MoonCountVo::getDate));
  309. }
  310. @SneakyThrows
  311. @ApiOperation("月统计导出")
  312. @PostMapping("moonCountDownload")
  313. public void moonCountDownload(@RequestBody DeviceSimChargeDto.MoonCount moonCount) {
  314. // 生成excel
  315. String name = YitIdHelper.nextId() + ".xlsx";
  316. String path = fileConfig.getPath() + File.separator + name;
  317. ExcelUtils.SheetAndData<MoonCountData> sheetAndData = ExcelUtils.create(path, MoonCountData.class);
  318. sheetAndData.sheet("设备流量卡月统计数据", () -> {
  319. List<DeviceSimChargeDto.MoonCountVo> data = moonCount(moonCount).getData();
  320. if (!Emptys.check(data)) {
  321. return null;
  322. }
  323. return Beans.copy(MoonCountData.class, data);
  324. }).builder();
  325. // 下载文件
  326. InputStream inputStream = IoUtils.inputStream(path).get();
  327. response.setHeader("Content-Disposition", "attachment; filename=" + "设备管理费月统计数据.xlsx");
  328. response.setContentType("application/xlsx");
  329. byte[] buffer = new byte[1024];
  330. int bytesRead;
  331. OutputStream outputStream = response.getOutputStream();
  332. while ((bytesRead = inputStream.read(buffer)) != -1) {
  333. outputStream.write(buffer, 0, bytesRead);
  334. }
  335. inputStream.close();
  336. outputStream.close();
  337. // 删除文件
  338. new File(path).delete();
  339. }
  340. @Data
  341. @Accessors(chain = true)
  342. public static class MoonCountData {
  343. @ColumnWidth(25)
  344. @ExcelProperty(value = "统计时间 yyyy-MM")
  345. private String date;
  346. @ColumnWidth(25)
  347. @ExcelProperty(value = "商户id")
  348. private Long mercId;
  349. @ColumnWidth(25)
  350. @ExcelProperty(value = "商户名称")
  351. private String mercName;
  352. @ColumnWidth(25)
  353. @ExcelProperty(value = "卡数")
  354. private Integer simSize;
  355. @ColumnWidth(25)
  356. @ExcelProperty(value = "续费金额")
  357. private Integer money;
  358. }
  359. }