package com.doumee.service.business.impl; import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper; import com.baomidou.mybatisplus.core.conditions.update.UpdateWrapper; import com.baomidou.mybatisplus.core.metadata.IPage; import com.baomidou.mybatisplus.extension.plugins.pagination.Page; import com.doumee.core.constants.Constants; import com.doumee.core.constants.ResponseStatus; import com.doumee.core.exception.BusinessException; import com.doumee.core.model.PageData; import com.doumee.core.model.PageWrap; import com.doumee.core.utils.Utils; import com.doumee.dao.business.DriverInfoMapper; import com.doumee.dao.business.RevenueMapper; import com.doumee.dao.business.ShopInfoMapper; import com.doumee.dao.business.WithdrawalOrdersMapper; import com.doumee.dao.business.model.DriverInfo; import com.doumee.dao.business.model.Revenue; import com.doumee.dao.business.model.ShopInfo; import com.doumee.dao.business.model.WithdrawalOrders; import com.doumee.dao.dto.WithdrawalApproveDTO; import com.doumee.dao.dto.WithdrawalDTO; import com.doumee.dao.system.SystemUserMapper; import com.doumee.dao.system.model.SystemUser; import com.doumee.service.business.WithdrawalOrdersService; import com.github.yulichang.wrapper.MPJLambdaWrapper; import org.apache.commons.lang3.StringUtils; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.stereotype.Service; import java.math.BigDecimal; import java.text.SimpleDateFormat; import java.util.Arrays; import java.util.Date; import java.util.List; import java.util.Objects; import java.util.concurrent.ThreadLocalRandom; /** * 提现申请记录Service实现 * @author rk * @date 2026/04/10 */ @Service public class WithdrawalOrdersServiceImpl implements WithdrawalOrdersService { @Autowired private WithdrawalOrdersMapper withdrawalOrdersMapper; @Autowired private SystemUserMapper systemUserMapper; @Autowired private ShopInfoMapper shopInfoMapper; @Autowired private DriverInfoMapper driverInfoMapper; @Autowired private RevenueMapper revenueMapper; @Override public Integer create(WithdrawalOrders withdrawalOrders) { withdrawalOrdersMapper.insert(withdrawalOrders); return withdrawalOrders.getId(); } @Override public void deleteById(Integer id) { withdrawalOrdersMapper.update(new UpdateWrapper().lambda() .set(WithdrawalOrders::getDeleted, Constants.ONE) .eq(WithdrawalOrders::getId, id)); } @Override public void delete(WithdrawalOrders withdrawalOrders) { UpdateWrapper deleteWrapper = new UpdateWrapper<>(withdrawalOrders); withdrawalOrdersMapper.delete(deleteWrapper); } @Override public void deleteByIdInBatch(List ids) { if (ids == null || ids.isEmpty()) { return; } withdrawalOrdersMapper.deleteBatchIds(ids); } @Override public void updateById(WithdrawalOrders withdrawalOrders) { withdrawalOrdersMapper.updateById(withdrawalOrders); } @Override public void updateByIdInBatch(List withdrawalOrdersList) { if (withdrawalOrdersList == null || withdrawalOrdersList.isEmpty()) { return; } for (WithdrawalOrders withdrawalOrders : withdrawalOrdersList) { this.updateById(withdrawalOrders); } } @Override public WithdrawalOrders findById(Integer id) { WithdrawalOrders order = withdrawalOrdersMapper.selectById(id); if (Objects.isNull(order)) { throw new BusinessException(ResponseStatus.DATA_EMPTY); } // 查询审批人名称 fillUpdateUserName(order); // 根据用户类型查询关联信息 if (Constants.ONE.equals(order.getMemberType())) { fillMemberInfo(order); } else { fillShopInfo(order); } return order; } @Override public WithdrawalOrders findOne(WithdrawalOrders withdrawalOrders) { QueryWrapper wrapper = new QueryWrapper<>(withdrawalOrders); return withdrawalOrdersMapper.selectOne(wrapper); } @Override public List findList(WithdrawalOrders withdrawalOrders) { QueryWrapper wrapper = new QueryWrapper<>(withdrawalOrders); return withdrawalOrdersMapper.selectList(wrapper); } @Override public PageData findPage(PageWrap pageWrap) { IPage page = new Page<>(pageWrap.getPage(), pageWrap.getCapacity()); MPJLambdaWrapper queryWrapper = new MPJLambdaWrapper<>(); Utils.MP.blankToNull(pageWrap.getModel()); pageWrap.getModel().setDeleted(Constants.ZERO); // 公共:审批人名称 queryWrapper.selectAll(WithdrawalOrders.class) .selectAs(SystemUser::getUsername, WithdrawalOrders::getUpdateUserName) .leftJoin(SystemUser.class, SystemUser::getId, WithdrawalOrders::getUserId); // 根据用户类型关联不同表 Integer memberType = pageWrap.getModel().getMemberType(); if (Constants.ONE.equals(memberType)) { // 司机端:关联 DriverInfo 表 queryWrapper.selectAs(DriverInfo::getName, WithdrawalOrders::getMemberName) .selectAs(DriverInfo::getTelephone, WithdrawalOrders::getMemberTelephone) .leftJoin(DriverInfo.class, DriverInfo::getMemberId, WithdrawalOrders::getMemberId); } else { // 店铺端 / 不筛选:关联 ShopInfo 表 queryWrapper.selectAs(ShopInfo::getName, WithdrawalOrders::getShopName) .selectAs(ShopInfo::getLinkName, WithdrawalOrders::getLinkName) .leftJoin(ShopInfo.class, ShopInfo::getId, WithdrawalOrders::getMemberId, ext -> ext.eq(ShopInfo::getDeleted, Constants.ZERO)); } queryWrapper.eq(WithdrawalOrders::getDeleted, pageWrap.getModel().getDeleted()); if (memberType != null) { queryWrapper.eq(WithdrawalOrders::getMemberType, memberType); } if (StringUtils.isNotBlank(pageWrap.getModel().getOutBillNo())) { queryWrapper.like(WithdrawalOrders::getOutBillNo, pageWrap.getModel().getOutBillNo()); } if (pageWrap.getModel().getMemberId() != null) { queryWrapper.eq(WithdrawalOrders::getMemberId, pageWrap.getModel().getMemberId()); } if (pageWrap.getModel().getStatus() != null) { queryWrapper.eq(WithdrawalOrders::getStatus, pageWrap.getModel().getStatus()); } if (pageWrap.getModel().getType() != null) { queryWrapper.eq(WithdrawalOrders::getType, pageWrap.getModel().getType()); } if (pageWrap.getModel().getCreateStartTime() != null) { queryWrapper.ge(WithdrawalOrders::getCreateTime, Utils.Date.getStart(pageWrap.getModel().getCreateStartTime())); } if (pageWrap.getModel().getCreateEndTime() != null) { queryWrapper.le(WithdrawalOrders::getCreateTime, Utils.Date.getEnd(pageWrap.getModel().getCreateEndTime())); } for (PageWrap.SortData sortData : pageWrap.getSorts()) { if (sortData.getDirection().equalsIgnoreCase(PageWrap.DESC)) { queryWrapper.orderByDesc(sortData.getProperty()); } else { queryWrapper.orderByAsc(sortData.getProperty()); } } return PageData.from(withdrawalOrdersMapper.selectJoinPage(page, WithdrawalOrders.class, queryWrapper)); } @Override public long count(WithdrawalOrders withdrawalOrders) { QueryWrapper wrapper = new QueryWrapper<>(withdrawalOrders); return withdrawalOrdersMapper.selectCount(wrapper); } @Override public Long totalAmount(PageWrap pageWrap) { QueryWrapper queryWrapper = new QueryWrapper<>(); queryWrapper.select("IFNULL(SUM(amount), 0) as amount"); Utils.MP.blankToNull(pageWrap.getModel()); queryWrapper.lambda().eq(WithdrawalOrders::getDeleted, Constants.ZERO); queryWrapper.lambda().in(WithdrawalOrders::getStatus, Arrays.asList(Constants.ZERO, Constants.ONE)); if (pageWrap.getModel().getOutBillNo() != null) { queryWrapper.lambda().like(WithdrawalOrders::getOutBillNo, pageWrap.getModel().getOutBillNo()); } if (pageWrap.getModel().getMemberId() != null) { queryWrapper.lambda().eq(WithdrawalOrders::getMemberId, pageWrap.getModel().getMemberId()); } if (pageWrap.getModel().getStatus() != null) { queryWrapper.lambda().eq(WithdrawalOrders::getStatus, pageWrap.getModel().getStatus()); } if (pageWrap.getModel().getType() != null) { queryWrapper.lambda().eq(WithdrawalOrders::getType, pageWrap.getModel().getType()); } if (pageWrap.getModel().getCreateStartTime() != null) { queryWrapper.lambda().ge(WithdrawalOrders::getCreateTime, Utils.Date.getStart(pageWrap.getModel().getCreateStartTime())); } if (pageWrap.getModel().getCreateEndTime() != null) { queryWrapper.lambda().le(WithdrawalOrders::getCreateTime, Utils.Date.getEnd(pageWrap.getModel().getCreateEndTime())); } WithdrawalOrders result = withdrawalOrdersMapper.selectOne(queryWrapper); return result != null && result.getAmount() != null ? result.getAmount() : 0L; } @Override public void approve(WithdrawalApproveDTO dto) { if (dto == null || dto.getId() == null || dto.getStatus() == null) { throw new BusinessException(ResponseStatus.BAD_REQUEST.getCode(), "审批参数不完整"); } if (!Constants.ONE.equals(dto.getStatus()) && !Constants.TWO.equals(dto.getStatus())) { throw new BusinessException(ResponseStatus.BAD_REQUEST.getCode(), "审批结果仅支持通过或拒绝"); } WithdrawalOrders order = withdrawalOrdersMapper.selectById(dto.getId()); if (Objects.isNull(order)) { throw new BusinessException(ResponseStatus.DATA_EMPTY); } if (!Constants.ZERO.equals(order.getStatus())) { throw new BusinessException(ResponseStatus.BAD_REQUEST.getCode(), "仅申请中的提现订单可审批"); } // 获取当前登录用户 Integer currentUserId = getCurrentUserId(); Date now = new Date(); WithdrawalOrders update = new WithdrawalOrders(); update.setId(dto.getId()); update.setStatus(dto.getStatus()); update.setUserId(currentUserId); update.setApproveTime(now); update.setApproveRemark(dto.getApproveRemark()); update.setUpdateTime(now); withdrawalOrdersMapper.updateById(update); // 驳回时退回余额 if (Constants.TWO.equals(dto.getStatus())) { Long amountFen = order.getAmount() != null ? order.getAmount() : 0L; if (amountFen > 0 && order.getMemberId() != null) { if (Constants.equalsInteger(order.getMemberType(), Constants.ONE)) { // 司机:通过 memberId 查 DriverInfo,退回 balance DriverInfo driver = driverInfoMapper.selectOne(new QueryWrapper().lambda() .eq(DriverInfo::getMemberId, order.getMemberId()) .eq(DriverInfo::getDeleted, Constants.ZERO) .last("limit 1")); if (driver != null) { driverInfoMapper.update(new UpdateWrapper().lambda() .setSql(" BALANCE = IFNULL(BALANCE, 0) + " + amountFen) .eq(DriverInfo::getId, driver.getId())); } } else if (Constants.equalsInteger(order.getMemberType(), Constants.TWO)) { // 门店:通过 memberId 查 ShopInfo,退回 balance ShopInfo shop = shopInfoMapper.selectOne(new QueryWrapper().lambda() .eq(ShopInfo::getRegionMemberId, order.getMemberId()) .eq(ShopInfo::getDeleted, Constants.ZERO) .last("limit 1")); if (shop != null) { shopInfoMapper.update(new UpdateWrapper().lambda() .setSql(" BALANCE = IFNULL(BALANCE, 0) + " + amountFen) .eq(ShopInfo::getId, shop.getId())); } } // 创建退回 Revenue 记录 Revenue revenue = new Revenue(); revenue.setMemberId(order.getMemberId()); revenue.setMemberType(order.getMemberType()); revenue.setType(Constants.TWO); // 2=提现退回 revenue.setOptType(Constants.ONE); // 1=收入 revenue.setAmount(amountFen); revenue.setVaildStatus(Constants.ONE); // 已入账 revenue.setObjId(order.getId()); revenue.setObjType(Constants.ONE); // 1=提现业务 revenue.setStatus(Constants.ZERO); revenue.setDeleted(Constants.ZERO); revenue.setCreateTime(now); revenueMapper.insert(revenue); } } } private Integer getCurrentUserId() { com.doumee.core.model.LoginUserInfo user = (com.doumee.core.model.LoginUserInfo) org.apache.shiro.SecurityUtils.getSubject().getPrincipal(); return user != null ? user.getId() : null; } private void fillUpdateUserName(WithdrawalOrders order) { if (order.getUserId() != null) { SystemUser user = systemUserMapper.selectById(order.getUserId()); if (user != null) { order.setUpdateUserName(user.getUsername()); } } } private void fillShopInfo(WithdrawalOrders order) { if (order.getMemberId() != null) { ShopInfo shop = shopInfoMapper.selectById(order.getMemberId()); if (shop != null && !Constants.ONE.equals(shop.getDeleted())) { order.setShopInfo(shop); order.setShopName(shop.getName()); order.setLinkName(shop.getLinkName()); } } } private void fillMemberInfo(WithdrawalOrders order) { if (order.getMemberId() != null) { DriverInfo driver = driverInfoMapper.selectOne( new QueryWrapper().lambda() .eq(DriverInfo::getMemberId, order.getMemberId()) .eq(DriverInfo::getDeleted, Constants.ZERO) .last("limit 1")); if (driver != null) { order.setMemberName(driver.getName()); order.setMemberTelephone(driver.getTelephone()); } } } @Override public void applyDriverWithdrawal(WithdrawalDTO dto, Integer memberId) { DriverInfo driver = driverInfoMapper.selectOne(new QueryWrapper().lambda() .eq(DriverInfo::getMemberId, memberId) .eq(DriverInfo::getDeleted, Constants.ZERO) .last("limit 1")); if (driver == null) { throw new BusinessException(ResponseStatus.DATA_EMPTY.getCode(), "司机信息不存在"); } long amountFen = dto.getAmount().multiply(new BigDecimal(100)).setScale(0, BigDecimal.ROUND_HALF_UP).longValue(); long balance = driver.getBalance() != null ? driver.getBalance() : 0L; if (amountFen <= 0) { throw new BusinessException(ResponseStatus.BAD_REQUEST.getCode(), "提现金额必须大于0"); } if (amountFen > balance) { throw new BusinessException(ResponseStatus.BAD_REQUEST.getCode(), "提现金额不能超过可用余额"); } String billNo = generateBillNo(); Date now = new Date(); // 扣减司机余额 driverInfoMapper.update(new UpdateWrapper().lambda() .setSql(" BALANCE = IFNULL(BALANCE, 0) - " + amountFen) .eq(DriverInfo::getId, driver.getId())); // 创建提现记录 WithdrawalOrders order = new WithdrawalOrders(); order.setMemberId(memberId); order.setMemberType(Constants.ONE); order.setAmount(amountFen); order.setStatus(Constants.ZERO); order.setType(Constants.ZERO); order.setOutBillNo(billNo); order.setAliAccount(dto.getAliAccount()); order.setDeleted(Constants.ZERO); order.setCreateTime(now); order.setUpdateTime(now); order.setCreateUser(memberId); withdrawalOrdersMapper.insert(order); // 创建支出 Revenue 记录 Revenue revenue = new Revenue(); revenue.setMemberId(memberId); revenue.setMemberType(Constants.ONE); revenue.setType(Constants.ONE); revenue.setOptType(-Constants.ONE); revenue.setAmount(amountFen); revenue.setVaildStatus(Constants.ONE); revenue.setObjId(order.getId()); revenue.setObjType(Constants.ONE); revenue.setStatus(Constants.ZERO); revenue.setDeleted(Constants.ZERO); revenue.setCreateTime(now); revenueMapper.insert(revenue); } @Override public void applyShopWithdrawal(WithdrawalDTO dto, Integer shopId) { ShopInfo shop = shopInfoMapper.selectById(shopId); if (shop == null) { throw new BusinessException(ResponseStatus.DATA_EMPTY); } long amountFen = dto.getAmount().multiply(new BigDecimal(100)).setScale(0, BigDecimal.ROUND_HALF_UP).longValue(); long balance = shop.getBalance() != null ? shop.getBalance() : 0L; if (amountFen <= 0) { throw new BusinessException(ResponseStatus.BAD_REQUEST.getCode(), "提现金额必须大于0"); } if (amountFen > balance) { throw new BusinessException(ResponseStatus.BAD_REQUEST.getCode(), "提现金额不能超过可用余额"); } String billNo = generateBillNo(); Date now = new Date(); // 扣减门店余额 shopInfoMapper.update(new UpdateWrapper().lambda() .setSql(" BALANCE = IFNULL(BALANCE, 0) - " + amountFen) .eq(ShopInfo::getId, shopId)); // 创建提现记录 WithdrawalOrders order = new WithdrawalOrders(); order.setMemberId(shop.getRegionMemberId()); order.setMemberType(Constants.TWO); order.setAmount(amountFen); order.setStatus(Constants.ZERO); order.setType(Constants.ZERO); order.setOutBillNo(billNo); order.setAliAccount(dto.getAliAccount()); order.setDeleted(Constants.ZERO); order.setCreateTime(now); order.setUpdateTime(now); order.setCreateUser(shop.getRegionMemberId()); withdrawalOrdersMapper.insert(order); // 创建支出 Revenue 记录 Revenue revenue = new Revenue(); revenue.setMemberId(shop.getRegionMemberId()); revenue.setMemberType(Constants.TWO); revenue.setType(Constants.ONE); // 1=提现支出 revenue.setOptType(-Constants.ONE); // -1=支出 revenue.setAmount(amountFen); revenue.setVaildStatus(Constants.ONE); // 已入账 revenue.setObjId(order.getId()); revenue.setObjType(Constants.ONE); // 1=提现业务 revenue.setStatus(Constants.ZERO); revenue.setDeleted(Constants.ZERO); revenue.setCreateTime(now); revenueMapper.insert(revenue); } private String generateBillNo() { SimpleDateFormat sdf = new SimpleDateFormat("yyyyMMddHHmmss"); String random = String.valueOf(ThreadLocalRandom.current().nextInt(100000, 999999)); return "TX" + sdf.format(new Date()) + random; } }