|
@@ -6,6 +6,8 @@ import com.pengrad.telegrambot.request.SendMessage;
|
|
|
import com.pengrad.telegrambot.response.SendResponse;
|
|
|
import lombok.extern.slf4j.Slf4j;
|
|
|
import org.jebot.constant.Constant;
|
|
|
+import org.jebot.handler.HandlerManager;
|
|
|
+import org.jebot.handler.dto.BotMessage;
|
|
|
import org.jebot.models.jebot.BotAccountBook;
|
|
|
import org.jebot.models.jebot.BotGroup;
|
|
|
import org.jebot.models.jebot.BotWarn;
|
|
@@ -17,19 +19,19 @@ import org.jebot.repository.jebot.BotWarnRepository;
|
|
|
import org.jebot.repository.xxpay.MchAccountRepository;
|
|
|
import org.jebot.repository.xxpay.PayOrderRepository;
|
|
|
import org.jebot.repository.xxpay.TransOrderRepository;
|
|
|
+import org.jebot.service.dto.UpdateBalance;
|
|
|
import org.springframework.context.annotation.Configuration;
|
|
|
import org.springframework.scheduling.annotation.Scheduled;
|
|
|
|
|
|
import javax.annotation.Resource;
|
|
|
import java.math.BigDecimal;
|
|
|
import java.math.RoundingMode;
|
|
|
-import java.util.Date;
|
|
|
-import java.util.HashMap;
|
|
|
-import java.util.List;
|
|
|
-import java.util.Map;
|
|
|
+import java.util.*;
|
|
|
import java.util.stream.Collectors;
|
|
|
|
|
|
+import static org.jebot.constant.Constant.DATA_TYPE_MERCHANT;
|
|
|
import static org.jebot.util.DateUtil.getTodayMidnight;
|
|
|
+import static org.jebot.util.DateUtil.getYesnight;
|
|
|
|
|
|
@Slf4j
|
|
|
@Configuration
|
|
@@ -37,7 +39,7 @@ public class MchScheduled {
|
|
|
|
|
|
@Resource
|
|
|
TelegramBot telegramBot;
|
|
|
-
|
|
|
+ public HandlerManager handlerManager;
|
|
|
|
|
|
@Resource
|
|
|
private BotWarnRepository botWarnRepository;
|
|
@@ -182,4 +184,197 @@ public class MchScheduled {
|
|
|
}
|
|
|
}
|
|
|
|
|
|
+
|
|
|
+ // 每日0:06触发结算
|
|
|
+ @Scheduled(cron = "0 6 0 * * ?")
|
|
|
+ public void dailyMchSettlement() {
|
|
|
+ log.info("定时任务开始:每日商户结算");
|
|
|
+
|
|
|
+ Date endDate = getYesnight(); // 前一天 23:59:59
|
|
|
+ Date todayMidnight = getTodayMidnight(endDate); // 前一天 00:00:00
|
|
|
+
|
|
|
+ List<BotGroup> botGroups = handlerManager.getGroupRepository()
|
|
|
+ .findAllByAgentWarningThresholdOrPaymentWarningThresholdGreaterThanZero();
|
|
|
+
|
|
|
+ List<BotGroup> mchGroups = botGroups.stream()
|
|
|
+ .filter(botGroup -> Constant.DATA_TYPE_MERCHANT.equals(botGroup.getDataType()))
|
|
|
+ .collect(Collectors.toList());
|
|
|
+
|
|
|
+ if (mchGroups.isEmpty()) {
|
|
|
+ log.info("没有商户群组");
|
|
|
+ return;
|
|
|
+ }
|
|
|
+
|
|
|
+ List<Long> mchIds = mchGroups.stream().map(BotGroup::getDataId).collect(Collectors.toList());
|
|
|
+ List<MchAccount> mchAccounts = handlerManager.getMchAccountRepository().findByMchIds(mchIds);
|
|
|
+
|
|
|
+ if (mchAccounts.isEmpty()) {
|
|
|
+ log.info("没有商户账户数据");
|
|
|
+ return;
|
|
|
+ }
|
|
|
+
|
|
|
+ Map<Long, MchAccount> mchAccountMap = mchAccounts.stream()
|
|
|
+ .collect(Collectors.toMap(MchAccount::getMchId, mchAccount -> mchAccount));
|
|
|
+
|
|
|
+ StringBuilder messageText = new StringBuilder();
|
|
|
+
|
|
|
+ for (BotGroup mchGroup : mchGroups) {
|
|
|
+ MchAccount mchAccount = mchAccountMap.get(mchGroup.getDataId());
|
|
|
+ if (mchAccount == null) {
|
|
|
+ messageText.append(mchGroup.getDataName()).append("[").append(mchGroup.getDataId()).append("]: 商户不存在\n");
|
|
|
+ continue;
|
|
|
+ }
|
|
|
+
|
|
|
+ if (mchAccount.getStatus() != 1) {
|
|
|
+ messageText.append(mchAccount.getName()).append(": 商户状态异常\n");
|
|
|
+ continue;
|
|
|
+ }
|
|
|
+
|
|
|
+ List<PayOrder> payOrderList = handlerManager.getPayOrderRepository()
|
|
|
+ .findSuccessPayOrderByMchIdAndCreateTime(mchGroup.getDataId(), todayMidnight, endDate);
|
|
|
+
|
|
|
+ if (payOrderList.isEmpty()) {
|
|
|
+ messageText.append(mchAccount.getName()).append(": 无订单数据\n");
|
|
|
+ continue;
|
|
|
+ }
|
|
|
+
|
|
|
+ if (SettlementMch(null, mchGroup, payOrderList, todayMidnight, endDate)) {
|
|
|
+ messageText.append(mchAccount.getName()).append(": 结算成功\n");
|
|
|
+ } else {
|
|
|
+ messageText.append(mchAccount.getName()).append(": 结算失败\n");
|
|
|
+ }
|
|
|
+
|
|
|
+ // 防止发送消息过快
|
|
|
+ try {
|
|
|
+ Thread.sleep(500);
|
|
|
+ } catch (InterruptedException e) {
|
|
|
+ log.error(e.getMessage(), e);
|
|
|
+ }
|
|
|
+ // 发送结算结果到管理员群或指定群
|
|
|
+ SendMessage sendMessage = new SendMessage(mchGroup.getGroupId(), messageText.toString());
|
|
|
+ SendResponse execute = telegramBot.execute(sendMessage);
|
|
|
+ if (!execute.isOk()) {
|
|
|
+ log.error("每日结算发送消息失败, 错误信息: {}", execute.description());
|
|
|
+ } else {
|
|
|
+ log.info("每日结算发送消息成功, 结算记录: {}", messageText);
|
|
|
+ }
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
+
|
|
|
+ private boolean SettlementMch(BotMessage message, BotGroup mchGroup, List<PayOrder> payOrderList, Date todayMidnight, Date endDate) {
|
|
|
+
|
|
|
+ StringBuilder stringBuilder = new StringBuilder();
|
|
|
+
|
|
|
+ // 计算总金额(未扣手续费)
|
|
|
+ BigDecimal totalAmount = payOrderList.stream()
|
|
|
+ .map(PayOrder::getAmount)
|
|
|
+ .reduce(BigDecimal.ZERO, BigDecimal::add);
|
|
|
+
|
|
|
+ // 成功总笔数
|
|
|
+ long totalOrders = payOrderList.size();
|
|
|
+
|
|
|
+ // 扣除手续费后的总跑量
|
|
|
+ BigDecimal totalAmountByMchRate = payOrderList.stream()
|
|
|
+ .map(order -> BigDecimal.ONE
|
|
|
+ .subtract(order.getMchRate().movePointLeft(Constant.AMOUNT_MOVE_POINT))
|
|
|
+ .multiply(order.getAmount()))
|
|
|
+ .reduce(BigDecimal.ZERO, BigDecimal::add);
|
|
|
+
|
|
|
+ stringBuilder.append(DateUtil.formatDate(endDate)).append("账单,请核对:\n");
|
|
|
+ stringBuilder.append("总跑量: ").append(totalAmount.movePointLeft(Constant.AMOUNT_MOVE_POINT).doubleValue()).append("\n");
|
|
|
+ stringBuilder.append("成功笔数: ").append(totalOrders).append("\n");
|
|
|
+ stringBuilder.append("扣除手续费总跑量: ").append(totalAmountByMchRate.movePointLeft(Constant.AMOUNT_MOVE_POINT).doubleValue()).append("\n");
|
|
|
+
|
|
|
+ // 扣除金额(手续费)
|
|
|
+ // 下发金额 = 总跑量 - 手续费
|
|
|
+ BigDecimal deductionAmount = totalAmountByMchRate.movePointLeft(Constant.AMOUNT_MOVE_POINT);
|
|
|
+
|
|
|
+
|
|
|
+ // ================= 按费率分组汇总 =================
|
|
|
+ stringBuilder.append("按费率统计:\n");
|
|
|
+
|
|
|
+ Map<BigDecimal, List<PayOrder>> groupedByMchRate = payOrderList.stream()
|
|
|
+ .collect(Collectors.groupingBy(PayOrder::getMchRate));
|
|
|
+
|
|
|
+ groupedByMchRate.entrySet().stream()
|
|
|
+ .sorted(Map.Entry.comparingByKey()) // 按费率排序
|
|
|
+ .forEach(entry -> {
|
|
|
+ BigDecimal mchRate = entry.getKey();
|
|
|
+ BigDecimal amount = entry.getValue().stream()
|
|
|
+ .map(PayOrder::getAmount)
|
|
|
+ .reduce(BigDecimal.ZERO, BigDecimal::add);
|
|
|
+
|
|
|
+ stringBuilder.append("费率").append(mchRate.doubleValue())
|
|
|
+ .append(": ")
|
|
|
+ .append(amount.movePointLeft(Constant.AMOUNT_MOVE_POINT).doubleValue())
|
|
|
+ .append("\n");
|
|
|
+ });
|
|
|
+
|
|
|
+ // ================= 发送账单 =================
|
|
|
+ SendMessage sendMessage = new SendMessage(mchGroup.getGroupId(), stringBuilder.toString());
|
|
|
+ SendResponse execute = message.getTelegramBot().execute(sendMessage);
|
|
|
+ if (!execute.isOk()) {
|
|
|
+ log.error("一键结算发送消息失败, 错误信息: {}", execute.description());
|
|
|
+ return false;
|
|
|
+ } else {
|
|
|
+ // ================= 更新商户账本 =================
|
|
|
+ BotAccountBook accountBook = handlerManager.getAccountBookRepository()
|
|
|
+ .findByBelongIdAndType(mchGroup.getDataId(), DATA_TYPE_MERCHANT);
|
|
|
+
|
|
|
+ if (accountBook == null) {
|
|
|
+ accountBook = new BotAccountBook();
|
|
|
+ accountBook.setBelongId(mchGroup.getDataId());
|
|
|
+ accountBook.setType(DATA_TYPE_MERCHANT);
|
|
|
+ accountBook.setPaymentBalance(0);
|
|
|
+ accountBook.setAgentBalance(0);
|
|
|
+ handlerManager.getAccountBookRepository().save(accountBook);
|
|
|
+ }
|
|
|
+
|
|
|
+ log.info("一键结算发送消息成功, 群组ID: {}, 结算记录: {}", mchGroup.getGroupId(), stringBuilder.toString());
|
|
|
+
|
|
|
+ double oldPaymentBalance = accountBook.getPaymentBalance();
|
|
|
+ double newPaymentBalance = BigDecimal.valueOf(oldPaymentBalance)
|
|
|
+ .subtract(deductionAmount).doubleValue();
|
|
|
+
|
|
|
+ BotMessage botMessage = new BotMessage();
|
|
|
+ botMessage.setBotGroup(mchGroup);
|
|
|
+ botMessage.setBotUser(message.getBotUser());
|
|
|
+
|
|
|
+ try {
|
|
|
+ UpdateBalance updateMerchantPaymentBalance = new UpdateBalance();
|
|
|
+ updateMerchantPaymentBalance.setId(accountBook.getId());
|
|
|
+ updateMerchantPaymentBalance.setOldBalance(oldPaymentBalance);
|
|
|
+ updateMerchantPaymentBalance.setNewBalance(newPaymentBalance);
|
|
|
+ updateMerchantPaymentBalance.setAmount(deductionAmount.doubleValue());
|
|
|
+ updateMerchantPaymentBalance.setMessage(botMessage);
|
|
|
+
|
|
|
+ handlerManager.getAccountBookService()
|
|
|
+ .updatePaymentBalanceByIdAndPaymentBalance(updateMerchantPaymentBalance);
|
|
|
+
|
|
|
+ sendMessage = new SendMessage(mchGroup.getGroupId(),
|
|
|
+ String.format("下发提醒\n下发金额: %.2f\n下发前: %.2f\n下发后: %.2f",
|
|
|
+ deductionAmount.doubleValue(), oldPaymentBalance, newPaymentBalance));
|
|
|
+
|
|
|
+ } catch (Exception e) {
|
|
|
+ log.error("更新商户群组账本失败,群组ID:{},群组名称:{},用户ID:{},用户名称:{},金额:{},错误信息:{}",
|
|
|
+ message.getBotGroup().getDataId(),
|
|
|
+ message.getBotGroup().getDataName(),
|
|
|
+ message.getBotUser().getUserId(),
|
|
|
+ message.getBotUser().getUserName(),
|
|
|
+ deductionAmount.doubleValue(),
|
|
|
+ e.getMessage());
|
|
|
+ e.printStackTrace();
|
|
|
+ sendMessage = new SendMessage(message.getMessage().chat().id(),
|
|
|
+ "下发处理失败,请手动处理");
|
|
|
+ } finally {
|
|
|
+ if (sendMessage != null) {
|
|
|
+ message.getTelegramBot().execute(sendMessage);
|
|
|
+ log.info("一键结算发送消息成功, 群组ID: {}, 结算记录: {}", message.getMessage().chat().id(), sendMessage);
|
|
|
+ }
|
|
|
+ }
|
|
|
+ return true;
|
|
|
+ }
|
|
|
+ }
|
|
|
+
|
|
|
}
|