DeviceSimChargeServiceImpl.java 21 KB

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