skyline 1 éve
szülő
commit
ac4e8741ea

+ 3 - 1
admin-web/src/views/admin/station/account/index.vue

@@ -94,7 +94,7 @@
             <template v-else-if="field.prop==='type'">
               <ext-d-label type="Object.type" :model-value="row[field.prop]"></ext-d-label>
             </template>
-            <template v-else-if="['balance','frozenAmount','unusedAmount','frozenAmountSplit','amount'].includes(field.prop)">
+            <template v-else-if="['balance','frozenAmount','unusedAmount','frozenAmountSplit','amount','withdrawnAmount','withdrawnFrozenAmount'].includes(field.prop)">
               {{ u.fmt.fmtMoney(row[field.prop]) }}
             </template>
             <template v-else-if="field.prop==='idleRemainTime'||field.prop==='operationRemainTime'">
@@ -160,6 +160,8 @@ const state = reactive({
     {label: '冻结金额(元)', width: 180, prop: 'frozenAmount', query: true, type: '', resizable: true},
     {label: '充值未消费金额(元)', width: 180, prop: 'unusedAmount', query: true, type: '', resizable: true},
     {label: '未消费可分账金额(元)', width: 200, prop: 'frozenAmountSplit', query: true, type: '', resizable: true},
+    {label: '已提现金额(元)', width: 200, prop: 'withdrawnAmount', query: true, type: '', resizable: true},
+    {label: '提现中金额(元)', width: 200, prop: 'withdrawnFrozenAmount', query: true, type: '', resizable: true},
     {label: '创建时间', width: 180, prop: 'createTime', query: true, sortable: 'custom', type: 'datetime', resizable: true, conf: {format: (val: any) => u.fmt.fmtDate(val)}},
     {label: '更新时间', width: 180, prop: 'updateTime', query: true, sortable: 'custom', type: 'datetime', resizable: true, conf: {format: (val: any) => u.fmt.fmtDate(val)}},
   ],

+ 53 - 1
car-wash-admin/src/main/java/com/kym/admin/controller/FinanceController.java

@@ -3,8 +3,10 @@ package com.kym.admin.controller;
 import com.kym.common.R;
 import com.kym.entity.queryParams.SplitRecordQueryParams;
 import com.kym.entity.queryParams.StationQueryParam;
+import com.kym.entity.queryParams.WithdrawnQueryParam;
 import com.kym.service.SplitRecordService;
 import com.kym.service.StationAccountService;
+import com.kym.service.WithdrawnRecordService;
 import org.springframework.web.bind.annotation.PostMapping;
 import org.springframework.web.bind.annotation.RequestBody;
 import org.springframework.web.bind.annotation.RequestMapping;
@@ -22,10 +24,12 @@ public class FinanceController {
 
     private final SplitRecordService splitRecordService;
     private final StationAccountService stationAccountService;
+    private final WithdrawnRecordService withdrawnRecordService;
 
-    public FinanceController(SplitRecordService splitRecordService, StationAccountService stationAccountService) {
+    public FinanceController(SplitRecordService splitRecordService, StationAccountService stationAccountService, WithdrawnRecordService withdrawnRecordService) {
         this.splitRecordService = splitRecordService;
         this.stationAccountService = stationAccountService;
+        this.withdrawnRecordService = withdrawnRecordService;
     }
 
     /**
@@ -50,4 +54,52 @@ public class FinanceController {
         return R.success(splitRecordService.listSplitRecords(params));
     }
 
+    /**
+     * 申请提现
+     *
+     * @param params
+     * @return
+     */
+    @PostMapping("/applyWithdrawn")
+    public R<?> applyWithdrawn(@RequestBody WithdrawnQueryParam params) {
+        stationAccountService.applyWithdrawn(params);
+        return R.success();
+    }
+
+    /**
+     * 提现记录列表
+     *
+     * @param params
+     * @return
+     */
+    @PostMapping("/withdrawnRecords")
+    public R<?> withdrawnRecords(@RequestBody WithdrawnQueryParam params) {
+        return R.success(withdrawnRecordService.listWithdrawnRecords(params));
+    }
+
+    /**
+     * 提现记录审核
+     *
+     * @param params
+     * @return
+     */
+    @PostMapping("/reviewWithdrawn")
+    public R<?> reviewWithdrawn(@RequestBody WithdrawnQueryParam params) {
+        withdrawnRecordService.reviewWithdrawn(params);
+        return R.success();
+    }
+
+    /**
+     * 提现记录打款确认
+     *
+     * @param params
+     * @return
+     */
+    @PostMapping("/confirmWithdrawnPayment")
+    public R<?> confirmWithdrawnPayment(@RequestBody WithdrawnQueryParam params) {
+        withdrawnRecordService.confirmWithdrawnPayment(params);
+        return R.success();
+    }
+
+
 }

+ 11 - 3
car-wash-entity/src/main/java/com/kym/entity/StationAccount.java

@@ -15,8 +15,6 @@ import lombok.Setter;
 @TableName("t_station_account")
 public class StationAccount extends BaseEntity {
 
-    private static final long serialVersionUID = 1L;
-
     /**
      * 平台账户ID
      */
@@ -25,7 +23,7 @@ public class StationAccount extends BaseEntity {
      * 平台站点ID
      */
     public static final String PLATFORM_STATION_ID = "0";
-
+    private static final long serialVersionUID = 1L;
     /**
      * 站点ID
      */
@@ -39,4 +37,14 @@ public class StationAccount extends BaseEntity {
      * 冻结金额(分)
      */
     private Integer frozenAmount;
+
+    /**
+     * 申请提现冻结金额(分)
+     */
+    private Integer withdrawnFrozenAmount;
+
+    /**
+     * 已提现金额(分)
+     */
+    private Integer withdrawnAmount;
 }

+ 75 - 0
car-wash-entity/src/main/java/com/kym/entity/WithdrawnRecord.java

@@ -0,0 +1,75 @@
+package com.kym.entity;
+
+import com.baomidou.mybatisplus.annotation.TableName;
+import com.kym.entity.BaseEntity;
+import java.io.Serializable;
+import java.time.LocalDateTime;
+import lombok.Getter;
+import lombok.Setter;
+import lombok.experimental.Accessors;
+
+/**
+ * <p>
+ * 站点账户提现记录表
+ * </p>
+ *
+ * @author skyline
+ * @since 2025-04-19
+ */
+@Getter
+@Setter
+@Accessors(chain = true)
+@TableName("t_withdrawn_record")
+public class WithdrawnRecord extends BaseEntity {
+
+    public static final int STATUS_待审核= 0;
+    public static final int STATUS_审核通过= 1;
+    public static final int STATUS_审核失败= 2;
+
+    private static final long serialVersionUID = 1L;
+
+    /**
+     * 站点id
+     */
+    private String stationId;
+
+    /**
+     * 提现金额(分)
+     */
+    private Integer withdrawnAmount;
+
+    /**
+     * 状态:0-待审核,1-审核通过,2-审核失败
+     */
+    private Integer status;
+
+    /**
+     * 打款状态:0-未打款,1-已打款
+     */
+    private Integer paymentStatus;
+
+    /**
+     * 审核人
+     */
+    private String reviewer;
+
+    /**
+     * 审核时间
+     */
+    private LocalDateTime reviewTime;
+
+    /**
+     * 打款人
+     */
+    private String payer;
+
+    /**
+     * 打款时间
+     */
+    private LocalDateTime paymentTime;
+
+    /**
+     * 备注
+     */
+    private String remark;
+}

+ 19 - 0
car-wash-entity/src/main/java/com/kym/entity/queryParams/WithdrawnQueryParam.java

@@ -0,0 +1,19 @@
+package com.kym.entity.queryParams;
+
+import com.kym.entity.common.PageParams;
+import lombok.Data;
+import org.hibernate.validator.constraints.Length;
+
+/**
+ * 站点账户提现参数
+ */
+@Data
+public class WithdrawnQueryParam extends PageParams {
+    private Long id;
+    private String stationId;
+    private Integer amount;
+    private Integer status;
+    private Integer paymentStatus;
+    @Length(max = 128, message = "备注长度不能超过128个字符")
+    private String remark;
+}

+ 11 - 0
car-wash-entity/src/main/java/com/kym/entity/vo/StationAccountVo.java

@@ -42,4 +42,15 @@ public class StationAccountVo extends BaseEntity {
      * 未消费可分账金额(分)
      */
     private Integer frozenAmountSplit;
+
+
+    /**
+     * 申请提现冻结金额(分)
+     */
+    private Integer withdrawnFrozenAmount;
+
+    /**
+     * 已提现金额(分)
+     */
+    private Integer withdrawnAmount;
 }

+ 16 - 0
car-wash-mapper/src/main/java/com/kym/mapper/WithdrawnRecordMapper.java

@@ -0,0 +1,16 @@
+package com.kym.mapper;
+
+import com.kym.entity.WithdrawnRecord;
+import com.kym.mapper.mybatisplus.MyBaseMapper;
+
+/**
+ * <p>
+ * 站点账户提现记录表 Mapper 接口
+ * </p>
+ *
+ * @author skyline
+ * @since 2025-04-19
+ */
+public interface WithdrawnRecordMapper extends MyBaseMapper<WithdrawnRecord> {
+
+}

+ 23 - 0
car-wash-mapper/src/main/resources/mappers/WithdrawnRecordMapper.xml

@@ -0,0 +1,23 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<!DOCTYPE mapper PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN" "http://mybatis.org/dtd/mybatis-3-mapper.dtd">
+<mapper namespace="com.kym.mapper.WithdrawnRecordMapper">
+
+    <!-- 通用查询映射结果 -->
+    <resultMap id="BaseResultMap" type="com.kym.entity.WithdrawnRecord">
+        <result column="station_id" property="stationId" />
+        <result column="withdrawn_amount" property="withdrawnAmount" />
+        <result column="status" property="status" />
+        <result column="payment_status" property="paymentStatus" />
+        <result column="reviewer" property="reviewer" />
+        <result column="review_time" property="reviewTime" />
+        <result column="payer" property="payer" />
+        <result column="payment_time" property="paymentTime" />
+        <result column="remark" property="remark" />
+    </resultMap>
+
+    <!-- 通用查询结果列 -->
+    <sql id="Base_Column_List">
+        station_id, withdrawn_amount, status, payment_status, reviewer, review_time, payer, payment_time, remark
+    </sql>
+
+</mapper>

+ 3 - 0
car-wash-service/src/main/java/com/kym/service/StationAccountService.java

@@ -3,6 +3,7 @@ package com.kym.service;
 import com.kym.entity.StationAccount;
 import com.kym.entity.common.PageBean;
 import com.kym.entity.queryParams.StationQueryParam;
+import com.kym.entity.queryParams.WithdrawnQueryParam;
 import com.kym.entity.vo.StationAccountVo;
 import com.kym.service.mybatisplus.MyBaseService;
 
@@ -19,4 +20,6 @@ public interface StationAccountService extends MyBaseService<StationAccount> {
     StationAccount getStationAccount(String stationId);
 
     PageBean<StationAccountVo> listStationAccounts(StationQueryParam stationId);
+
+    void applyWithdrawn(WithdrawnQueryParam params);
 }

+ 25 - 0
car-wash-service/src/main/java/com/kym/service/WithdrawnRecordService.java

@@ -0,0 +1,25 @@
+package com.kym.service;
+
+import com.kym.entity.WithdrawnRecord;
+import com.kym.entity.common.PageBean;
+import com.kym.entity.queryParams.WithdrawnQueryParam;
+import com.kym.service.mybatisplus.MyBaseService;
+import org.springframework.transaction.annotation.Transactional;
+
+/**
+ * <p>
+ * 站点账户提现记录表 服务类
+ * </p>
+ *
+ * @author skyline
+ * @since 2025-04-19
+ */
+public interface WithdrawnRecordService extends MyBaseService<WithdrawnRecord> {
+
+    PageBean<WithdrawnRecord> listWithdrawnRecords(WithdrawnQueryParam params);
+
+    void reviewWithdrawn(WithdrawnQueryParam params);
+
+    @Transactional
+    void confirmWithdrawnPayment(WithdrawnQueryParam params);
+}

+ 36 - 0
car-wash-service/src/main/java/com/kym/service/impl/StationAccountServiceImpl.java

@@ -2,17 +2,22 @@ package com.kym.service.impl;
 
 import cn.dev33.satoken.stp.StpUtil;
 import com.github.pagehelper.PageHelper;
+import com.kym.common.exception.BusinessException;
 import com.kym.common.utils.CommUtil;
 import com.kym.entity.StationAccount;
+import com.kym.entity.WithdrawnRecord;
 import com.kym.entity.common.PageBean;
 import com.kym.entity.queryParams.StationQueryParam;
+import com.kym.entity.queryParams.WithdrawnQueryParam;
 import com.kym.entity.vo.StationAccountVo;
 import com.kym.mapper.StationAccountMapper;
 import com.kym.service.StationAccountService;
+import com.kym.service.WithdrawnRecordService;
 import com.kym.service.cache.KymCache;
 import com.kym.service.mybatisplus.MyBaseServiceImpl;
 import org.springframework.beans.BeanUtils;
 import org.springframework.stereotype.Service;
+import org.springframework.transaction.annotation.Transactional;
 
 /**
  * <p>
@@ -25,6 +30,12 @@ import org.springframework.stereotype.Service;
 @Service
 public class StationAccountServiceImpl extends MyBaseServiceImpl<StationAccountMapper, StationAccount> implements StationAccountService {
 
+    private final WithdrawnRecordService withdrawnRecordService;
+
+    public StationAccountServiceImpl(WithdrawnRecordService withdrawnRecordService) {
+        this.withdrawnRecordService = withdrawnRecordService;
+    }
+
     @Override
     public StationAccount getStationAccount(String stationId) {
         return lambdaQuery().eq(StationAccount::getStationId, stationId).one();
@@ -57,4 +68,29 @@ public class StationAccountServiceImpl extends MyBaseServiceImpl<StationAccountM
         }).toList();
         return new PageBean<>(voList);
     }
+
+    /**
+     * 提现申请
+     *
+     * @param params
+     * @return
+     */
+    @Override
+    @Transactional
+    public void applyWithdrawn(WithdrawnQueryParam params) {
+        // 校验可提现金额
+        var stationAccount = getStationAccount(params.getStationId());
+        if (stationAccount.getFrozenAmount() < params.getAmount()) {
+            throw new BusinessException("提现金额超出可提现金额!");
+        }
+        // 冻结提现金额
+        lambdaUpdate().setSql("balance = balance - {0}, withdrawn_frozen_amount = withdrawn_frozen_amount + {0}", params.getAmount())
+                .eq(StationAccount::getStationId, params.getStationId()).update();
+
+        // 提现记录
+        var withdrawnRecord = new WithdrawnRecord()
+                .setStationId(params.getStationId())
+                .setWithdrawnAmount(params.getAmount());
+        withdrawnRecordService.save(withdrawnRecord);
+    }
 }

+ 61 - 0
car-wash-service/src/main/java/com/kym/service/impl/WithdrawnRecordServiceImpl.java

@@ -0,0 +1,61 @@
+package com.kym.service.impl;
+
+import cn.dev33.satoken.stp.StpUtil;
+import com.github.pagehelper.PageHelper;
+import com.kym.common.utils.CommUtil;
+import com.kym.entity.WithdrawnRecord;
+import com.kym.entity.common.PageBean;
+import com.kym.entity.queryParams.WithdrawnQueryParam;
+import com.kym.mapper.WithdrawnRecordMapper;
+import com.kym.service.WithdrawnRecordService;
+import com.kym.service.mybatisplus.MyBaseServiceImpl;
+import org.springframework.stereotype.Service;
+import org.springframework.transaction.annotation.Transactional;
+
+import java.time.LocalDateTime;
+
+/**
+ * <p>
+ * 站点账户提现记录表 服务实现类
+ * </p>
+ *
+ * @author skyline
+ * @since 2025-04-19
+ */
+@Service
+public class WithdrawnRecordServiceImpl extends MyBaseServiceImpl<WithdrawnRecordMapper, WithdrawnRecord> implements WithdrawnRecordService {
+
+    @Override
+    public PageBean<WithdrawnRecord> listWithdrawnRecords(WithdrawnQueryParam params) {
+        PageHelper.startPage(params.getPageNum(), params.getPageSize());
+        var res = lambdaQuery()
+                .eq(CommUtil.isNotEmptyAndNull(params.getStationId()), WithdrawnRecord::getStationId, params.getStationId())
+                .orderByDesc(WithdrawnRecord::getId)
+                .list();
+        return new PageBean<>(res);
+    }
+
+    @Override
+    @Transactional
+    public void reviewWithdrawn(WithdrawnQueryParam params) {
+        CommUtil.asserts(CommUtil.isNotEmptyAndNull(params.getStatus()), "审核异常");
+        lambdaUpdate()
+                .set(WithdrawnRecord::getStatus, params.getStatus())
+                .set(WithdrawnRecord::getReviewer, StpUtil.getSession().getString("username"))
+                .set(WithdrawnRecord::getReviewTime, LocalDateTime.now())
+                .eq(WithdrawnRecord::getId, params.getId())
+                .update();
+    }
+
+    @Override
+    @Transactional
+    public void confirmWithdrawnPayment(WithdrawnQueryParam params) {
+        CommUtil.asserts(CommUtil.isNotEmptyAndNull(params.getPaymentStatus()), "确认打款异常");
+        lambdaUpdate()
+                .set(WithdrawnRecord::getPaymentStatus, params.getPaymentStatus())
+                .set(WithdrawnRecord::getPayer, StpUtil.getSession().getString("username"))
+                .set(WithdrawnRecord::getWithdrawnAmount, LocalDateTime.now())
+                .eq(WithdrawnRecord::getId, params.getId())
+                .update();
+    }
+}