You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

450 lines
20 KiB

4 months ago
4 months ago
4 months ago
4 months ago
4 months ago
4 months ago
  1. package com.example.demo.serviceImpl.cash;
  2. import com.example.demo.Util.JWTUtil;
  3. import com.example.demo.config.RabbitMQConfig;
  4. import com.example.demo.domain.entity.*;
  5. import com.example.demo.domain.vo.cash.CashCollection;
  6. import com.example.demo.domain.vo.cash.CashCollectionMessage;
  7. import com.example.demo.domain.vo.coin.GoldUser;
  8. import com.example.demo.domain.vo.coin.Messages;
  9. import com.example.demo.domain.vo.coin.Result;
  10. import com.example.demo.mapper.cash.CashCollectionMapper;
  11. import com.example.demo.mapper.coin.MarketMapper;
  12. import com.example.demo.mapper.coin.UserMapper;
  13. import com.example.demo.service.cash.CashCollectionService;
  14. import com.github.pagehelper.PageHelper;
  15. import com.github.pagehelper.PageInfo;
  16. import jakarta.servlet.http.HttpServletRequest;
  17. import lombok.extern.slf4j.Slf4j;
  18. import org.springframework.amqp.rabbit.core.RabbitTemplate;
  19. import org.springframework.beans.factory.annotation.Autowired;
  20. import org.springframework.stereotype.Service;
  21. import org.springframework.transaction.annotation.Transactional;
  22. import org.springframework.util.CollectionUtils;
  23. import org.springframework.web.context.request.RequestContextHolder;
  24. import org.springframework.web.context.request.ServletRequestAttributes;
  25. import java.math.BigDecimal;
  26. import java.time.LocalDateTime;
  27. import java.time.ZoneOffset;
  28. import java.util.Arrays;
  29. import java.util.List;
  30. import java.util.UUID;
  31. import java.util.stream.Collectors;
  32. /**
  33. * @program: gold-java
  34. * @ClassName cashCollectionServiceImpl
  35. * @description: 处理收款相关业务逻辑
  36. * @author: Ethan
  37. * @create: 202509-26 11:23
  38. * @Version 1.0
  39. **/
  40. @Service
  41. @Slf4j
  42. public class CashCollectionServiceImpl implements CashCollectionService {
  43. @Autowired
  44. private CashCollectionMapper cashCollectionMapper;
  45. @Autowired
  46. private UserMapper userMapper;
  47. @Autowired
  48. private MarketMapper marketMapper;
  49. @Autowired
  50. private RabbitTemplate rabbitTemplate;
  51. //新增收款订单
  52. @Override
  53. public String add(CashCollection cashCollection) {
  54. if (cashCollection.getJwcode() == null) {
  55. throw new IllegalArgumentException("精网号不能为空");
  56. }
  57. if (cashCollection.getJwcode() < 10000000 || cashCollection.getJwcode() > 99999999) {
  58. throw new IllegalArgumentException("精网号必须为8位");
  59. }
  60. if (cashCollection.getName() == null || cashCollection.getName().isEmpty()){
  61. throw new IllegalArgumentException("客户姓名不能为空");
  62. }
  63. if (cashCollection.getActivity() == null || cashCollection.getActivity().isEmpty()) {
  64. throw new IllegalArgumentException("活动不能为空");
  65. }
  66. if (cashCollection.getGoodsName() == null|| cashCollection.getGoodsName().isEmpty()) {
  67. throw new IllegalArgumentException("商品名不能为空");
  68. }
  69. if (cashCollection.getGoodsName().equals("金币充值")) {
  70. if (cashCollection.getPermanentGold() == 0 && cashCollection.getFreeGold() == 0) {
  71. throw new IllegalArgumentException("金币数量不能为空");
  72. }
  73. }
  74. if (!cashCollection.getGoodsName().equals("金币充值")) {
  75. if (cashCollection.getGoodNum() == 0) {
  76. throw new IllegalArgumentException("产品数量不能为空");
  77. }
  78. if (cashCollection.getNumUnit() == null|| cashCollection.getNumUnit().isEmpty()) {
  79. throw new IllegalArgumentException("数量单位不能为空");
  80. }
  81. }
  82. if (cashCollection.getPaymentCurrency() == null || cashCollection.getPaymentCurrency().isEmpty()) {
  83. throw new IllegalArgumentException("支付币种不能为空");
  84. }
  85. if (cashCollection.getPaymentAmount() == null || cashCollection.getPaymentAmount().compareTo(BigDecimal.ZERO) == 0) {
  86. throw new IllegalArgumentException("支付金额不能为空");
  87. }
  88. if (cashCollection.getPayType() == null|| cashCollection.getPayType().isEmpty()) {
  89. throw new IllegalArgumentException("支付方式不能为空");
  90. }
  91. if (cashCollection.getReceivedMarket() == null||cashCollection.getReceivedMarket().isEmpty()) {
  92. throw new IllegalArgumentException("到账地区不能为空");
  93. }
  94. if (cashCollection.getPayTime() == null) {
  95. throw new IllegalArgumentException("付款时间不能为空");
  96. }
  97. //生成订单号后半部分
  98. String orderNumber = UUID.randomUUID().toString().replaceAll("-", "");
  99. CashRecord cashRecord = new CashRecord();
  100. //构建订单信息
  101. cashRecord.setOrderCode("XJ_" + orderNumber); //订单号
  102. cashRecord.setJwcode(cashCollection.getJwcode()); //精网号
  103. cashRecord.setName(cashCollection.getName()); //客户姓名
  104. cashRecord.setActivity(cashCollection.getActivity()); // 活动
  105. cashRecord.setGoodsName(cashCollection.getGoodsName()); //商品名称
  106. cashRecord.setGoodNum(cashCollection.getGoodNum()); //商品数量
  107. cashRecord.setNumUnit(cashCollection.getNumUnit()); //数量单位
  108. cashRecord.setPermanentGold(cashCollection.getPermanentGold()); //永久金币
  109. cashRecord.setFreeGold(cashCollection.getFreeGold()); //免费金币
  110. cashRecord.setPaymentCurrency(cashCollection.getPaymentCurrency()); //付款币种
  111. cashRecord.setPaymentAmount(cashCollection.getPaymentAmount()); //付款金额
  112. cashRecord.setReceivedMarket(cashCollection.getReceivedMarket()); //到账地区
  113. cashRecord.setPayType(cashCollection.getPayType()); //支付方式
  114. cashRecord.setPayTime(cashCollection.getPayTime()); //付款时间
  115. cashRecord.setVoucher(cashCollection.getVoucher()); //转账凭证
  116. cashRecord.setRemark(cashCollection.getRemark()); //备注
  117. cashRecord.setStatus(0); //订单状态:付款线下财务待审核
  118. cashRecord.setSubmitterId(cashCollection.getSubmitterId()); //提交人ID
  119. cashRecord.setSubmitterMarket(cashCollection.getSubmitterMarket());
  120. cashRecord.setOrderType(1); //订单类型:1-收款
  121. cashRecord.setMarket(cashCollection.getMarket());
  122. //地区,根据jwcode插入
  123. //cashRecord.setMarket(cashCollectionMapper.getMarketByJwcode(cashRecord.getJwcode()));
  124. //插入新收款订单
  125. cashCollectionMapper.add(cashRecord);
  126. // 发送收款创建消息
  127. Messages message = new Messages();
  128. message.setJwcode(cashRecord.getJwcode());
  129. message.setName(cashRecord.getName());
  130. message.setStatus(cashRecord.getStatus());
  131. message.setDesc(cashRecord.getJwcode()+"用户的现金收款申请待审核,请前往审核");
  132. message.setTitle("现金收款--新增收款");
  133. message.setType(1);
  134. message.setTypeId(cashRecord.getId());
  135. message.setMarket(Integer.valueOf(cashRecord.getMarket()));
  136. rabbitTemplate.convertAndSend(RabbitMQConfig.CASH_COLLECTION_EXCHANGE, "cash.collection.save", message);
  137. return "添加成功";
  138. }
  139. //撤回未审核的订单
  140. @Override
  141. public String cancel(String orderCode) {
  142. CashRecord cashRecord = cashCollectionMapper.selectByOrderCode(orderCode);
  143. if (cashRecord == null) {
  144. throw new IllegalArgumentException("订单不存在");
  145. }
  146. if (cashRecord.getStatus() != 0) {
  147. throw new IllegalArgumentException("订单状态不符合条件");
  148. }
  149. //修改订单状态
  150. int rows = cashCollectionMapper.updateStatus(orderCode, 5);
  151. return rows > 0 ? "撤回成功" : "撤回失败";
  152. }
  153. //编辑并重新提交收款订单
  154. @Override
  155. public String reSubmit(CashRecord cashRecord) {
  156. if (cashRecord.getJwcode() == null) {
  157. throw new IllegalArgumentException("精网号不能为空");
  158. }
  159. if (cashRecord.getJwcode() < 10000000 || cashRecord.getJwcode() > 99999999) {
  160. throw new IllegalArgumentException("精网号必须为8位");
  161. }
  162. if (cashRecord.getName() == null) {
  163. throw new IllegalArgumentException("客户姓名不能为空");
  164. }
  165. if (cashRecord.getActivity() == null) {
  166. throw new IllegalArgumentException("活动不能为空");
  167. }
  168. if (cashRecord.getGoodsName() == null) {
  169. throw new IllegalArgumentException("商品名不能为空");
  170. }
  171. if (cashRecord.getGoodsName().equals("金币充值")) {
  172. if (cashRecord.getPermanentGold() == 0 && cashRecord.getFreeGold() == 0) {
  173. throw new IllegalArgumentException("金币数量不能为空");
  174. }
  175. }
  176. if (!cashRecord.getGoodsName().equals("金币充值")) {
  177. if (cashRecord.getGoodNum() == 0) {
  178. throw new IllegalArgumentException("产品数量不能为空");
  179. }
  180. if (cashRecord.getNumUnit() == null) {
  181. throw new IllegalArgumentException("数量单位不能为空");
  182. }
  183. }
  184. if (cashRecord.getPaymentCurrency() == null) {
  185. throw new IllegalArgumentException("支付币种不能为空");
  186. }
  187. if (cashRecord.getPaymentAmount() == null || cashRecord.getPaymentAmount().compareTo(BigDecimal.ZERO) == 0) {
  188. throw new IllegalArgumentException("支付金额不能为空");
  189. }
  190. if (cashRecord.getPayType() == null) {
  191. throw new IllegalArgumentException("支付方式不能为空");
  192. }
  193. if (cashRecord.getReceivedMarket() == null) {
  194. throw new IllegalArgumentException("到账地区不能为空");
  195. }
  196. if (cashRecord.getPayTime() == null) {
  197. throw new IllegalArgumentException("付款时间不能为空");
  198. }
  199. CashRecord status = cashCollectionMapper.selectByOrderCode(cashRecord.getOrderCode());
  200. if (!status.getStatus().equals(5)) {
  201. throw new IllegalArgumentException("只允许编辑已撤回订单");
  202. }
  203. //地区,根据jwcode插入(弃用,插入前调用接口获取地区和姓名,之后前端传入)
  204. //cashRecord.setMarket(cashCollectionMapper.getMarketByJwcode(cashRecord.getJwcode()));
  205. int rows = cashCollectionMapper.updateByOrderCode(cashRecord);
  206. if (rows > 0) {
  207. // 发送重新提交消息
  208. CashCollectionMessage message = new CashCollectionMessage();
  209. message.setId(cashRecord.getId());
  210. message.setOrderCode(cashRecord.getOrderCode());
  211. message.setStatus(0); // 重新提交后状态变为待审核
  212. message.setStatusDescription("线下财务待审核");
  213. message.setMessage("收款订单已重新提交");
  214. message.setSubmitterId(cashRecord.getSubmitterId());
  215. message.setTimestamp(LocalDateTime.now());
  216. rabbitTemplate.convertAndSend(
  217. RabbitMQConfig.CASH_COLLECTION_EXCHANGE,
  218. "collection.created",
  219. message
  220. );
  221. }
  222. return rows > 0 ? "重新提交成功" : "重新提交失败";
  223. }
  224. //多条件查询收款订单列表
  225. @Override
  226. public PageInfo<CashCollection> selectCollection(Integer pageNum, Integer pageSize, CashCollection cashCollection) {
  227. /* //将操作人的地区列表改为id
  228. List<String> markets = marketMapper.getMarketIds(cashCollection.getMarkets());
  229. if (markets.contains("9") || markets.contains("9999")) {
  230. markets = null;
  231. }*/
  232. // cashCollection.setReceivedMarket(marketMapper.getMarketId(cashCollection.getReceivedMarket()));
  233. if (cashCollection.getCashRoleId() == 2) {
  234. //角色是总部时,若不特地传状态,传1346,sql处理为(1,3,4,6)筛选,
  235. if (cashCollection.getStatus() == null) {
  236. cashCollection.setStatus(1346);
  237. }
  238. cashCollection.setSubmitterId(null);
  239. cashCollection.setReceivedMarket(null);
  240. cashCollection.setSubmitterMarket(null);
  241. }
  242. if (cashCollection.getCashRoleId() == 1) {
  243. //角色是地方财务,提交人置空不设筛选条件,仅按收款地区、提交人地区筛选()
  244. if (cashCollection.getStatus() == null) {
  245. cashCollection.setStatus(123460);
  246. }
  247. //状态为待审核和已驳回时按照提交人地区筛选
  248. if (cashCollection.getStatus() == 0 || cashCollection.getStatus() == 2) {
  249. cashCollection.setReceivedMarket(null);
  250. }
  251. //状态为已通过和Link通过时,满足收款地区或提交人地区即可
  252. /* if (cashCollection.getStatus() == 13) {
  253. cashCollection.setSubmitterId(null);
  254. }*/
  255. //状态为13 或46,已通过或已完成和已退款,满足收款地区或提交人地区即可,
  256. cashCollection.setSubmitterId(null);
  257. }
  258. if (cashCollection.getCashRoleId() == 0) {
  259. //角色是地方财务,提交人置空不设筛选条件---仅当角色是0 地方客服时,按提交人筛选
  260. if (cashCollection.getStatus() == null) {
  261. cashCollection.setStatus(1234560);
  262. }
  263. cashCollection.setSubmitterId(cashCollection.getSubmitterId());
  264. cashCollection.setReceivedMarket(null);
  265. }
  266. // cashCollection.setMarkets(markets);
  267. PageHelper.startPage(pageNum, pageSize); //必须要直接跟mapper
  268. List<CashCollection> cashCollections = cashCollectionMapper.selectCollection1(pageNum, pageSize, cashCollection);
  269. return new PageInfo<>(cashCollections);
  270. }
  271. //补全手续费等内容
  272. @Override
  273. public String complete(CashRecord cashRecord) {
  274. int rows = cashCollectionMapper.complete(cashRecord);
  275. return rows > 0 ? "编辑成功" : "编辑失败";
  276. }
  277. //根据精网号查询姓名和地区
  278. @Override
  279. public User getNameAndMarket(Integer jwcode) {
  280. try {
  281. HttpServletRequest request = ((ServletRequestAttributes) RequestContextHolder.getRequestAttributes()).getRequest();
  282. String token = request.getHeader("token");
  283. Admin admin = (Admin) JWTUtil.getUserDetailsList(String.valueOf(token), Admin.class);
  284. if (admin != null) {
  285. List<String> list = Arrays.asList(admin.getMarkets().split(","));
  286. List<String> markets = marketMapper.getMarketIds(list);
  287. if (markets.contains("9") || markets.contains("9999")) {
  288. markets = null;
  289. }
  290. GoldUser gUser = userMapper.selectUserCard(jwcode.toString(), markets);
  291. if (gUser != null) {
  292. User user = new User();
  293. user.setMarket(cashCollectionMapper.getMarketByJwcode(jwcode));
  294. user.setName(cashCollectionMapper.getNameByJwcode(jwcode));
  295. user.setMarketName(cashCollectionMapper.getMarketNameByJwcode(jwcode));
  296. return user;
  297. }
  298. }
  299. } catch (Exception e) {
  300. e.printStackTrace();
  301. }
  302. // 如果没有返回有效用户信息,则抛出异常
  303. throw new RuntimeException("无法获取用户信息");
  304. }
  305. //获取收款活动列表
  306. @Override
  307. public List<RechargeActivity> getActivityList() {
  308. LocalDateTime now = LocalDateTime.now();
  309. return cashCollectionMapper.getActivityList(now);
  310. }
  311. //同步g_order订单到cash_record表
  312. @Override
  313. public Object syncToCashRecord() {
  314. int total = 0;
  315. while (true) {
  316. List<GOrder> gOrders = cashCollectionMapper.getUnSync(50);
  317. if (CollectionUtils.isEmpty(gOrders)) {
  318. break;
  319. }
  320. try {
  321. // 每批独立事务
  322. processBatch(gOrders);
  323. total += gOrders.size();
  324. log.info("✅ 同步完成一批,数量: {}, 累计: {}", gOrders.size(), total);
  325. } catch (Exception e) {
  326. List<Integer> failedIds = gOrders.stream().map(GOrder::getId).collect(Collectors.toList());
  327. log.error("失败订单ID: {}", failedIds);
  328. // 可存入 error_log 表,供人工处理
  329. // 这里选择继续下一批(容忍部分失败)
  330. }
  331. if (gOrders.size() < 50) {
  332. break; // 最后一批
  333. }
  334. }
  335. return "同步完毕,成功处理 " + total + " 条";
  336. }
  337. @Override
  338. @Transactional(rollbackFor = Exception.class)
  339. public void processBatch(List<GOrder> gOrders) {
  340. for (GOrder gOrder : gOrders) {
  341. CashRecord cashRecord = new CashRecord();
  342. //构建基础信息
  343. cashRecord.setOrderType(1);
  344. cashRecord.setJwcode(gOrder.getJwcode());
  345. String name=cashCollectionMapper.getNameByJwcode(gOrder.getJwcode());
  346. if (name!=null){
  347. cashRecord.setName(name);
  348. }else cashRecord.setName("未知");
  349. cashRecord.setMarket(cashCollectionMapper.getMarketByJwcode(gOrder.getJwcode()));
  350. if (gOrder.getType().equals("gold")){ //充金豆
  351. cashRecord.setActivity("Link日常充值");
  352. cashRecord.setGoodsName("Link充值金豆");
  353. cashRecord.setRemark("Link充值金豆");
  354. cashRecord.setNumUnit("个");
  355. cashRecord.setPermanentGold(0);
  356. cashRecord.setGoodNum(gOrder.getCount());
  357. }
  358. if (gOrder.getType().equals("gold_coin")){//充金币
  359. cashRecord.setActivity("Link日常充值");
  360. cashRecord.setGoodsName("Link充值金币");
  361. cashRecord.setRemark("Link充值金币");
  362. cashRecord.setPermanentGold(gOrder.getCount()*100);
  363. cashRecord.setGoodNum(0);
  364. }
  365. cashRecord.setOrderCode(gOrder.getOrderNo());
  366. if (gOrder != null) {
  367. switch (gOrder.getPayStyle()) {
  368. case 3:
  369. cashRecord.setPayType("IOS内购");
  370. cashRecord.setBankCode(gOrder.getIosTransactionId());
  371. cashRecord.setReceivedMarket("4");
  372. cashRecord.setPayload("IOS");
  373. break;
  374. case 5:
  375. cashRecord.setPayType("Stripe-链接收款");
  376. cashRecord.setReceivedMarket("13");
  377. cashRecord.setPayload("Stripe");
  378. break;
  379. case 6:
  380. cashRecord.setPayType("PaymentAsia-链接收款");
  381. cashRecord.setReceivedMarket("13");
  382. cashRecord.setPayload("PaymentAsia");
  383. break;
  384. case 7:
  385. cashRecord.setPayType("Ipay88-链接收款");
  386. cashRecord.setReceivedMarket("5");
  387. cashRecord.setPayload("Ipay88");
  388. break;
  389. case 9:
  390. cashRecord.setPayType("FirstData");
  391. cashRecord.setReceivedMarket("4");
  392. cashRecord.setBankCode(gOrder.getFirstdataIpgTransactionId());
  393. cashRecord.setPayload("FirstData");
  394. break;
  395. default:
  396. break;
  397. }
  398. }
  399. cashRecord.setFreeGold(0);
  400. cashRecord.setPaymentCurrency("");
  401. cashRecord.setPaymentAmount(BigDecimal.valueOf(0));
  402. cashRecord.setPayTime(LocalDateTime.ofEpochSecond(gOrder.getSuccessTime(), 0, ZoneOffset.UTC));
  403. cashRecord.setStatus(3);
  404. cashRecord.setSubmitterId(99999);
  405. //存入现金库
  406. cashCollectionMapper.add(cashRecord);
  407. cashCollectionMapper.markSynced(gOrder.getId());
  408. }
  409. }
  410. @Override
  411. public CashCollection selectById(CashCollection cashCollection) {
  412. return cashCollectionMapper.selectById(cashCollection.getId());
  413. }
  414. //根据goldcoin订单号查询收款订单
  415. @Override
  416. public CashCollection selectByGoldCoinOrderCode(String orderNo) {
  417. return cashCollectionMapper.selectByGoldCoinOrderCode(orderNo);
  418. }
  419. }