| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281 |
- package modules.withdraw;
- import com.alibaba.fastjson.JSONObject;
- import com.jfinal.plugin.activerecord.Db;
- import common.jfinal.AppConfig;
- import common.model.BalanceLog;
- import common.model.User;
- import common.model.Withdraw;
- import common.utils.http.MyRet;
- import common.utils.hyg.HygSDK;
- import modules.order.OrderService;
- import java.util.ArrayList;
- import java.util.HashMap;
- import java.util.List;
- import java.util.Map;
- public class WithdrawService {
- // 提现手续费,750代表万分之750(7.5%)
- public static final long WITHDRAW_FEE = 750;
-
- public String hello() {
- return "Hello Withdraw";
- }
-
- public MyRet create(long amount, User user) {
- long amountWithoutFee = amount * (10000 - WITHDRAW_FEE) / 10000;
-
- // 用户余额判断
- if (user.getBalance() < (float)amount) {
- return MyRet.fail(String.format("提现失败,余额不足,你仅有%s而提现%s", user.getBalance(), amount));
- }
-
- try {
- String orderSn = "DLTBH_WD_" + OrderService.generateOrderSn();
- Db.tx(() -> {
- user.setBalance(user.getBalance() - (float)amount);
-
- if (!user.update()) {
- throw new RuntimeException("用户余额扣减失败");
- }
- // 保存提现单据
- Withdraw withdraw = new Withdraw();
- withdraw.setWithdrawSn(orderSn);
- withdraw.setAmount((float)amount);
- withdraw.setStatus(10);
- withdraw.setUserId(user.getId());
- withdraw.setCreateTime(System.currentTimeMillis());
- withdraw.setUpdateTime(System.currentTimeMillis());
- withdraw.setIsDeleted(0);
- // 保存资金流水
- BalanceLog l = new BalanceLog();
- l.set("create_time", System.currentTimeMillis());
- l.set("is_deleted", 0);
- l.set("description", "用户提现:" + amount); // 描述中带上百分比
- l.set("amount", -amount);
- l.set("user_id", user.getLong("id"));
- if (!l.save()) {
- throw new RuntimeException("资金流水记录创建失败: " + user.getId());
- }
-
- if (!withdraw.save()) {
- throw new RuntimeException("提现单据保存失败");
- }
-
- return true;
- });
- float amountCNY = (float)amountWithoutFee / (float)100;
- float feePercent = (float)WITHDRAW_FEE / (float)100;
- return MyRet.ok(String.format("提现%s火花,实际到账%.2f(元),手续费%s%%,申请已提交", amount, amountCNY, feePercent)).setData(findByWithdrawSn(orderSn));
- } catch (Exception e) {
- return MyRet.fail("提现申请失败: " + e.getMessage());
- }
- }
-
- public MyRet pass(Withdraw withdraw, long approverId) {
- // 记录操作人
- withdraw.setApproverId(approverId);
-
- try {
- User user = User.dao.findById(withdraw.getUserId());
- long amountWithoutFee = (long) (withdraw.getAmount() * (10000 - WITHDRAW_FEE) / 10000);
- String workerId = user.getHygWorkerId();
- String amountWithoutFeeStr = amountWithoutFee + "";
- String hygPositionId = System.getenv("HYG_POSITION_ID");
- AppConfig.LOGGER.info("{}, {}, {}, {}", workerId, amountWithoutFeeStr, withdraw.getWithdrawSn(), hygPositionId);
- JSONObject withdrawRst = HygSDK.singleDistribute(workerId, amountWithoutFeeStr, withdraw.getWithdrawSn(), hygPositionId);
-
- // 首先保证提现是成功的
- if (!withdrawRst.getString("statusCode").equals("000000")) {
- withdraw.setHygOrigin(withdrawRst.toString());
- withdraw.setReason("慧用工提现失败");
- withdraw.setStatus(40);
-
- // 原子化操作user和withdraw的状态
- Db.tx(() -> {
- // 把款项退给用户
- user.setBalance(user.getBalance() + withdraw.getAmount());
- if (!user.update()) {
- throw new RuntimeException("用户余额归还失败");
- }
- if (!withdraw.update()) {
- throw new RuntimeException("单据状态更新失败");
- }
- // 保存资金流水
- BalanceLog l = new BalanceLog();
- l.set("create_time", System.currentTimeMillis());
- l.set("is_deleted", 0);
- l.set("description", "慧用工转款失败退还"); // 描述中带上百分比
- l.set("amount", withdraw.getAmount());
- l.set("user_id", user.getLong("id"));
- if (!l.save()) {
- throw new RuntimeException("资金流水记录创建失败: " + user.getId());
- }
-
- return true;
- });
-
- return MyRet.fail("慧用工提现失败:" + withdrawRst.getString("statusText"));
- }
-
- // 如果是成功提现
- withdraw.setHygOrigin(withdrawRst.toString());
- withdraw.setStatus(20);
- if (withdraw.update()) {
- return MyRet.ok("打款请求已发起").setData(withdraw);
- } else {
- return MyRet.fail("单据状态更新失败");
- }
- } catch (Exception e) {
- return MyRet.fail("打款请求已发起失败: " + e.getMessage());
- }
- }
-
- public MyRet refuse(Withdraw withdraw, String reason, long approverId) {
- User user = User.dao.findById(withdraw.getUserId());
- try {
- Db.tx(() -> {
- user.setBalance(user.getBalance() + withdraw.getAmount());
-
- if (!user.update()) {
- throw new RuntimeException("用户余额扣减失败");
- }
-
- // 记录操作人
- withdraw.setApproverId(approverId);
- withdraw.setReason(reason);
- withdraw.setStatus(40);
- if (!withdraw.update()) {
- throw new RuntimeException("提现单据保存失败");
- }
- // 管理员拒绝
- BalanceLog l = new BalanceLog();
- l.set("create_time", System.currentTimeMillis());
- l.set("is_deleted", 0);
- l.set("description", "管理员拒绝提现,请查看原因"); // 描述中带上百分比
- l.set("amount", withdraw.getAmount());
- l.set("user_id", user.getLong("id"));
- if (!l.save()) {
- throw new RuntimeException("资金流水记录创建失败: " + user.getId());
- }
-
- return true;
- });
-
- return MyRet.ok("该单据已拒绝").setData(withdraw);
- } catch (Exception e) {
- return MyRet.fail("拒绝失败:" + e.getMessage());
- }
- }
-
- public MyRet list(int pageNumber, int pageSize, Integer status, Long userId) {
- // 接收 Integer 类型的 orderStatus
- // 构建用于查询当前页订单列表的 SQL
- String columns = " * ";
- String select = "SELECT " + columns;
- StringBuilder fromWhere = new StringBuilder("FROM t_withdraw"); // 基础 from 子句
- String orderBy = "ORDER BY update_time DESC";
- boolean hasWhereClause = false; // 标志位,用于判断是否已经添加了 WHERE 关键字
- List<Object> params = new ArrayList<>(); // 用于 SELECT 列表查询的参数
- // ✅ 根据 status 筛选
- if (status != null && status >= 0) { // status 通常是枚举,>=0 可能是有效的判断
- fromWhere.append(hasWhereClause ? " AND" : " WHERE").append(" status = ?");
- params.add(status);
- hasWhereClause = true;
- }
- // ✅ 根据 userId 筛选
- // 通常 userId 是正整数,如果 userId 可能为 0 需要特别对待
- if (userId != null && userId > 0) { // 通常 userId 从 1 开始,或者根据你的业务逻辑设定
- fromWhere.append(hasWhereClause ? " AND" : " WHERE").append(" user_id = ?");
- params.add(userId);
- hasWhereClause = true;
- }
-
- // 计算 LIMIT 的 offset (偏移量)
- int offset = (pageNumber - 1) * pageSize;
- // 构建查询当前页订单列表的最终 SQL (手动添加 LIMIT)
- String listSql = select + " " + fromWhere + " " + orderBy + " LIMIT ?, ?";
- params.add(offset);
- params.add(pageSize);
-
- List<Withdraw> withdrawList = Withdraw.dao.find(listSql, params.toArray());
- // 如果列表为空,直接返回
- if (withdrawList.isEmpty()) {
- Map<String, Object> response = new HashMap<>(); // 准备返回结构
- response.put("list", new ArrayList<>());
- response.put("total_row", 0);
- response.put("total_page", 0);
- response.put("page_size", pageSize);
- response.put("page_number", pageNumber);
- response.put("total_order_count", 0); // 与你的 total_user_count 对应
- return MyRet.ok("查询成功").setData(response);
- }
- // 获取符合条件的条目数量
- long totalRowLong = countWithdraws(status, userId);
- // 手动计算 total_page
- int totalPage = (int) Math.ceil((double) totalRowLong / pageSize);
- if (totalPage == 0 && totalRowLong > 0) { // 解决总行数大于0但总页数为0(pageSize大于totalRow)的问题
- totalPage = 1;
- }
-
- // 封装最终响应
- Map<String, Object> response = new HashMap<>();
- response.put("list", withdrawList);
- response.put("total_row", totalRowLong); // 符合条件的订单总数
- response.put("total_page", totalPage); // 手动计算的总页数
- response.put("page_size", pageSize);
- response.put("page_number", pageNumber);
- response.put("total_order_count", totalRowLong); // 对应 total_user_count,这里是符合订单状态筛选的总数
- return MyRet.ok("查询成功").setData(response);
- }
- public long countWithdraws(Integer status, Long userId) { // 接收 Integer 类型的 status
- StringBuilder sql = new StringBuilder("SELECT COUNT(*) FROM t_withdraw"); // 使用 COUNT(*),更通用
- List<Object> params = new ArrayList<>();
- boolean hasWhereClause = false; // 标志位,用于判断是否已经添加了 WHERE 关键字
- // ✅ 根据 status 筛选
- if (status != null && status >= 0) { // status 通常是枚举,>=0 可能是有效的判断
- sql.append(hasWhereClause ? " AND" : " WHERE").append(" status = ?");
- params.add(status);
- hasWhereClause = true;
- }
- // ✅ 根据 userId 筛选
- // 通常 userId 是正整数,如果 userId 可能为 0 需要特别对待
- if (userId != null && userId > 0) { // 通常 userId 从 1 开始,或者根据你的业务逻辑设定
- sql.append(hasWhereClause ? " AND" : " WHERE").append(" user_id = ?");
- params.add(userId);
- hasWhereClause = true;
- }
- // 执行查询并返回结果
- // Db.queryLong() 如果没有结果会返回 null,如果查询结果行数为 0,则返回 Long 0
- // 这符合 COUNT() 函数的预期
- return Db.queryLong(sql.toString(), params.toArray());
- }
-
- public Withdraw findByWithdrawSn(String sn) {
- return Withdraw.dao.findFirst("SELECT * FROM t_withdraw WHERE withdraw_sn=?", sn);
- }
- }
|