diff --git a/sql/wfc_user_db/wfc_user_db.sql b/sql/wfc_user_db/wfc_user_db.sql
index 92a7dc8..7af33ff 100644
--- a/sql/wfc_user_db/wfc_user_db.sql
+++ b/sql/wfc_user_db/wfc_user_db.sql
@@ -29,19 +29,21 @@ CREATE TABLE `u_account` (
`id` bigint(20) NOT NULL AUTO_INCREMENT COMMENT '主键',
`user_id` bigint(20) NULL DEFAULT NULL COMMENT '用户ID',
`balance` decimal(18, 4) NULL DEFAULT NULL COMMENT '余额',
+ `balance_used` decimal(18, 4) NULL DEFAULT NULL COMMENT '余额已使用',
`package_id` bigint(20) NULL DEFAULT NULL COMMENT '套餐ID',
`start_time` datetime NULL DEFAULT NULL COMMENT '开始时间',
`end_time` datetime NULL DEFAULT NULL COMMENT '结束时间',
+ `traffic` bigint(20) NULL DEFAULT NULL COMMENT '流量',
`traffic_used` bigint(20) NULL DEFAULT NULL COMMENT '流量已使用',
+ `duration` bigint(20) NULL DEFAULT NULL COMMENT '时长',
`duration_used` bigint(20) NULL DEFAULT NULL COMMENT '时长已使用',
+ `client_num` int(11) NULL DEFAULT NULL COMMENT '在线设备数',
`client_num_used` int(11) NULL DEFAULT NULL COMMENT '在线设备数已使用',
+ `expired_time` datetime NULL DEFAULT NULL COMMENT '失效时间',
`package_name` varchar(64) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NULL DEFAULT NULL COMMENT '套餐名称',
`period_num` int(11) NULL DEFAULT NULL COMMENT '有效期数',
`period_type` tinyint(4) NULL DEFAULT NULL COMMENT '有效期类型',
`price` decimal(18, 4) NULL DEFAULT NULL COMMENT '价格',
- `traffic` bigint(20) NULL DEFAULT NULL COMMENT '流量',
- `duration` bigint(20) NULL DEFAULT NULL COMMENT '时长',
- `client_num` int(11) NULL DEFAULT NULL COMMENT '在线设备数',
`remark` varchar(500) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NULL DEFAULT NULL COMMENT '备注',
`rate_limit_enable` tinyint(1) NULL DEFAULT 0 COMMENT '带宽是否限制',
`traffic_enable` tinyint(1) NULL DEFAULT 0 COMMENT '流量是否限制',
@@ -92,22 +94,37 @@ CREATE TABLE `u_balance` (
-- ----------------------------
DROP TABLE IF EXISTS `u_bill`;
CREATE TABLE `u_bill` (
- `id` bigint(20) NOT NULL AUTO_INCREMENT COMMENT 'Bill ID',
- `user_id` bigint(20) NULL DEFAULT NULL COMMENT 'User ID link to u_user',
- `fee` double NULL DEFAULT NULL,
- `billing_begin` datetime NULL DEFAULT NULL,
- `billing_end` datetime NULL DEFAULT NULL,
- `status` enum('unpaid','paid') CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci NULL DEFAULT 'unpaid',
- `create_by` varchar(32) CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci NULL DEFAULT '' COMMENT 'create name ',
- `create_time` datetime NULL DEFAULT NULL COMMENT 'create time',
- PRIMARY KEY (`id`) USING BTREE,
- INDEX `fk_user_id`(`user_id`) USING BTREE,
- CONSTRAINT `u_bill_ibfk_1` FOREIGN KEY (`user_id`) REFERENCES `u_user` (`user_id`) ON DELETE RESTRICT ON UPDATE RESTRICT
-) ENGINE = InnoDB AUTO_INCREMENT = 1 CHARACTER SET = utf8mb4 COLLATE = utf8mb4_unicode_ci COMMENT = '用户平台_用户信息表' ROW_FORMAT = DYNAMIC;
+ `id` bigint(20) NOT NULL AUTO_INCREMENT COMMENT '主键',
+ `user_id` bigint(20) NULL DEFAULT NULL COMMENT '用户ID',
+ `cdr_history_id` bigint(20) NULL DEFAULT NULL COMMENT '话单记录ID',
+ `type` tinyint(4) NULL DEFAULT NULL COMMENT '类型',
+ `amount` decimal(18, 4) NULL DEFAULT NULL COMMENT '金额',
+ `status` tinyint(4) NULL DEFAULT NULL COMMENT '状态',
+ `del_flag` tinyint(1) NULL DEFAULT 0 COMMENT '删除标志(0存在 1删除)',
+ `create_by` bigint(20) NULL DEFAULT NULL COMMENT '创建人',
+ `create_time` datetime NULL DEFAULT NULL COMMENT '创建时间',
+ `update_by` bigint(20) NULL DEFAULT NULL COMMENT '更新人',
+ `update_time` datetime NULL DEFAULT NULL COMMENT '更新时间',
+ PRIMARY KEY (`id`) USING BTREE
+) ENGINE = InnoDB AUTO_INCREMENT = 1876451063420497923 CHARACTER SET = utf8mb4 COLLATE = utf8mb4_unicode_ci COMMENT = '用户平台-账单表' ROW_FORMAT = Dynamic;
-- ----------------------------
--- Records of u_bill
+-- Table structure for u_bill_rule
-- ----------------------------
+DROP TABLE IF EXISTS `u_bill_rule`;
+CREATE TABLE `u_bill_rule` (
+ `id` bigint(20) NOT NULL AUTO_INCREMENT COMMENT '主键',
+ `price` decimal(18, 4) NULL DEFAULT NULL COMMENT '价格',
+ `traffic` bigint(20) NULL DEFAULT NULL COMMENT '流量',
+ `unit` tinyint(4) NULL DEFAULT NULL COMMENT '单位',
+ `enable` tinyint(1) NULL DEFAULT NULL COMMENT '是否启用',
+ `del_flag` tinyint(1) NULL DEFAULT 0 COMMENT '删除标志(0存在 1删除)',
+ `create_by` bigint(20) NULL DEFAULT NULL COMMENT '创建人',
+ `create_time` datetime NULL DEFAULT NULL COMMENT '创建时间',
+ `update_by` bigint(20) NULL DEFAULT NULL COMMENT '更新人',
+ `update_time` datetime NULL DEFAULT NULL COMMENT '更新时间',
+ PRIMARY KEY (`id`) USING BTREE
+) ENGINE = InnoDB AUTO_INCREMENT = 2 CHARACTER SET = utf8mb4 COLLATE = utf8mb4_unicode_ci COMMENT = '用户平台-计费规则表' ROW_FORMAT = Dynamic;
-- ----------------------------
-- Table structure for u_cdr
diff --git a/wfc-modules/wfc-user/src/main/java/org/wfc/user/controller/UBillController.java b/wfc-modules/wfc-user/src/main/java/org/wfc/user/controller/UBillController.java
new file mode 100644
index 0000000..162cd92
--- /dev/null
+++ b/wfc-modules/wfc-user/src/main/java/org/wfc/user/controller/UBillController.java
@@ -0,0 +1,69 @@
+package org.wfc.user.controller;
+
+import cn.hutool.core.collection.CollUtil;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.web.bind.annotation.DeleteMapping;
+import org.springframework.web.bind.annotation.GetMapping;
+import org.springframework.web.bind.annotation.PathVariable;
+import org.springframework.web.bind.annotation.PostMapping;
+import org.springframework.web.bind.annotation.PutMapping;
+import org.springframework.web.bind.annotation.RequestBody;
+import org.springframework.web.bind.annotation.RequestMapping;
+import org.springframework.web.bind.annotation.RestController;
+import org.wfc.common.core.web.controller.BaseController;
+import org.wfc.common.core.web.domain.AjaxResult;
+import org.wfc.common.core.web.page.TableDataInfo;
+import org.wfc.user.domain.UBill;
+import org.wfc.user.service.IUBillService;
+
+import java.util.List;
+
+/**
+ *
+ * 用户平台-账单表 前端控制器
+ *
+ *
+ * @author sys
+ * @since 2025-01-06
+ */
+@RestController
+@RequestMapping("/user/uBill")
+public class UBillController extends BaseController {
+
+ @Autowired
+ private IUBillService uBillService;
+
+ @GetMapping("/page")
+ public TableDataInfo page(UBill uBill) {
+ startPage();
+ List list = uBillService.list();
+ return getDataTable(list);
+ }
+
+ @GetMapping("/list")
+ public AjaxResult list(UBill uBill) {
+ List list = uBillService.list();
+ return success(list);
+ }
+
+ @GetMapping(value = "/{id}")
+ public AjaxResult getById(@PathVariable("id") Long id) {
+ return success(uBillService.getById(id));
+ }
+
+ @PostMapping
+ public AjaxResult add(@RequestBody UBill uBill) {
+ return toAjax(uBillService.save(uBill));
+ }
+
+ @PutMapping
+ public AjaxResult edit(@RequestBody UBill uBill) {
+ return toAjax(uBillService.updateById(uBill));
+ }
+
+ @DeleteMapping("/{ids}")
+ public AjaxResult remove(@PathVariable Long[] ids) {
+ return toAjax(uBillService.removeByIds(CollUtil.newArrayList(ids)));
+ }
+
+}
diff --git a/wfc-modules/wfc-user/src/main/java/org/wfc/user/controller/UBillRuleController.java b/wfc-modules/wfc-user/src/main/java/org/wfc/user/controller/UBillRuleController.java
new file mode 100644
index 0000000..74f8019
--- /dev/null
+++ b/wfc-modules/wfc-user/src/main/java/org/wfc/user/controller/UBillRuleController.java
@@ -0,0 +1,69 @@
+package org.wfc.user.controller;
+
+import cn.hutool.core.collection.CollUtil;
+import org.springframework.beans.factory.annotation.Autowired;
+import org.springframework.web.bind.annotation.DeleteMapping;
+import org.springframework.web.bind.annotation.GetMapping;
+import org.springframework.web.bind.annotation.PathVariable;
+import org.springframework.web.bind.annotation.PostMapping;
+import org.springframework.web.bind.annotation.PutMapping;
+import org.springframework.web.bind.annotation.RequestBody;
+import org.springframework.web.bind.annotation.RequestMapping;
+import org.springframework.web.bind.annotation.RestController;
+import org.wfc.common.core.web.controller.BaseController;
+import org.wfc.common.core.web.domain.AjaxResult;
+import org.wfc.common.core.web.page.TableDataInfo;
+import org.wfc.user.domain.UBillRule;
+import org.wfc.user.service.IUBillRuleService;
+
+import java.util.List;
+
+/**
+ *
+ * 用户平台-计费规则表 前端控制器
+ *
+ *
+ * @author sys
+ * @since 2025-01-06
+ */
+@RestController
+@RequestMapping("/user/uBillRule")
+public class UBillRuleController extends BaseController {
+
+ @Autowired
+ private IUBillRuleService uBillRuleService;
+
+ @GetMapping("/page")
+ public TableDataInfo page(UBillRule uBillRule) {
+ startPage();
+ List list = uBillRuleService.list();
+ return getDataTable(list);
+ }
+
+ @GetMapping("/list")
+ public AjaxResult list(UBillRule uBillRule) {
+ List list = uBillRuleService.list();
+ return success(list);
+ }
+
+ @GetMapping(value = "/{id}")
+ public AjaxResult getById(@PathVariable("id") Long id) {
+ return success(uBillRuleService.getById(id));
+ }
+
+ @PostMapping
+ public AjaxResult add(@RequestBody UBillRule uBillRule) {
+ return toAjax(uBillRuleService.save(uBillRule));
+ }
+
+ @PutMapping
+ public AjaxResult edit(@RequestBody UBillRule uBillRule) {
+ return toAjax(uBillRuleService.updateById(uBillRule));
+ }
+
+ @DeleteMapping("/{ids}")
+ public AjaxResult remove(@PathVariable Long[] ids) {
+ return toAjax(uBillRuleService.removeByIds(CollUtil.newArrayList(ids)));
+ }
+
+}
diff --git a/wfc-modules/wfc-user/src/main/java/org/wfc/user/domain/UAccount.java b/wfc-modules/wfc-user/src/main/java/org/wfc/user/domain/UAccount.java
index 6aa1582..c2520d3 100644
--- a/wfc-modules/wfc-user/src/main/java/org/wfc/user/domain/UAccount.java
+++ b/wfc-modules/wfc-user/src/main/java/org/wfc/user/domain/UAccount.java
@@ -46,9 +46,15 @@ public class UAccount extends BaseData {
@Schema(description = "时长已使用")
private Long durationUsed;
+ @Schema(description = "失效时间")
+ private Date expiredTime;
+
@Schema(description = "在线设备数已使用")
private Integer clientNumUsed;
+ @Schema(description = "余额已使用")
+ private BigDecimal balanceUsed;
+
@Schema(description = "套餐名称")
private String packageName;
diff --git a/wfc-modules/wfc-user/src/main/java/org/wfc/user/domain/UBill.java b/wfc-modules/wfc-user/src/main/java/org/wfc/user/domain/UBill.java
new file mode 100644
index 0000000..6d02884
--- /dev/null
+++ b/wfc-modules/wfc-user/src/main/java/org/wfc/user/domain/UBill.java
@@ -0,0 +1,41 @@
+package org.wfc.user.domain;
+
+import com.baomidou.mybatisplus.annotation.TableName;
+import java.io.Serializable;
+import java.math.BigDecimal;
+import org.wfc.common.mybatis.domain.BaseData;
+import io.swagger.v3.oas.annotations.media.Schema;
+import lombok.Getter;
+import lombok.Setter;
+
+/**
+ *
+ * 用户平台-账单表
+ *
+ *
+ * @author sys
+ * @since 2025-01-06
+ */
+@Getter
+@Setter
+@TableName("u_bill")
+@Schema(name = "UBill", description = "用户平台-账单表")
+public class UBill extends BaseData {
+
+ private static final long serialVersionUID = 1L;
+
+ @Schema(description = "用户ID")
+ private Long userId;
+
+ @Schema(description = "话单记录ID")
+ private Long cdrHistoryId;
+
+ @Schema(description = "类型")
+ private Integer type;
+
+ @Schema(description = "金额")
+ private BigDecimal amount;
+
+ @Schema(description = "状态")
+ private Integer status;
+}
diff --git a/wfc-modules/wfc-user/src/main/java/org/wfc/user/domain/UBillRule.java b/wfc-modules/wfc-user/src/main/java/org/wfc/user/domain/UBillRule.java
new file mode 100644
index 0000000..a408ff0
--- /dev/null
+++ b/wfc-modules/wfc-user/src/main/java/org/wfc/user/domain/UBillRule.java
@@ -0,0 +1,38 @@
+package org.wfc.user.domain;
+
+import com.baomidou.mybatisplus.annotation.TableName;
+import java.io.Serializable;
+import java.math.BigDecimal;
+import org.wfc.common.mybatis.domain.BaseData;
+import io.swagger.v3.oas.annotations.media.Schema;
+import lombok.Getter;
+import lombok.Setter;
+
+/**
+ *
+ * 用户平台-计费规则表
+ *
+ *
+ * @author sys
+ * @since 2025-01-06
+ */
+@Getter
+@Setter
+@TableName("u_bill_rule")
+@Schema(name = "UBillRule", description = "用户平台-计费规则表")
+public class UBillRule extends BaseData {
+
+ private static final long serialVersionUID = 1L;
+
+ @Schema(description = "价格")
+ private BigDecimal price;
+
+ @Schema(description = "流量")
+ private Long traffic;
+
+ @Schema(description = "单位")
+ private Integer unit;
+
+ @Schema(description = "是否启用")
+ private Boolean enable;
+}
diff --git a/wfc-modules/wfc-user/src/main/java/org/wfc/user/domain/vo/UCdrLatestHistoryVo.java b/wfc-modules/wfc-user/src/main/java/org/wfc/user/domain/vo/UCdrLatestHistoryVo.java
new file mode 100644
index 0000000..2dc5005
--- /dev/null
+++ b/wfc-modules/wfc-user/src/main/java/org/wfc/user/domain/vo/UCdrLatestHistoryVo.java
@@ -0,0 +1,37 @@
+package org.wfc.user.domain.vo;
+
+import io.swagger.v3.oas.annotations.media.Schema;
+import lombok.Data;
+
+/**
+ * @description: cdr 最新记录vo
+ * @author: cyc
+ * @since: 2025-01-06
+ */
+@Data
+public class UCdrLatestHistoryVo {
+
+ @Schema(description = "ID")
+ private Long id;
+
+ @Schema(description = "user ID")
+ private Long userId;
+
+ @Schema(description = "CDR ID")
+ private Long cdrId;
+
+ @Schema(description = "Downstream traffic (Byte)")
+ private Long trafficDown;
+
+ @Schema(description = "Upstream traffic (Byte)")
+ private Long trafficUp;
+
+ @Schema(description = "Start time")
+ private Long startTime;
+
+ @Schema(description = "End time")
+ private Long endTime;
+
+ @Schema(description = "Duration(s)")
+ private Long duration;
+}
diff --git a/wfc-modules/wfc-user/src/main/java/org/wfc/user/mapper/UBillMapper.java b/wfc-modules/wfc-user/src/main/java/org/wfc/user/mapper/UBillMapper.java
new file mode 100644
index 0000000..11b4a1b
--- /dev/null
+++ b/wfc-modules/wfc-user/src/main/java/org/wfc/user/mapper/UBillMapper.java
@@ -0,0 +1,16 @@
+package org.wfc.user.mapper;
+
+import org.wfc.user.domain.UBill;
+import com.baomidou.mybatisplus.core.mapper.BaseMapper;
+
+/**
+ *
+ * 用户平台-账单表 Mapper 接口
+ *
+ *
+ * @author sys
+ * @since 2025-01-06
+ */
+public interface UBillMapper extends BaseMapper {
+
+}
diff --git a/wfc-modules/wfc-user/src/main/java/org/wfc/user/mapper/UBillRuleMapper.java b/wfc-modules/wfc-user/src/main/java/org/wfc/user/mapper/UBillRuleMapper.java
new file mode 100644
index 0000000..3dad44b
--- /dev/null
+++ b/wfc-modules/wfc-user/src/main/java/org/wfc/user/mapper/UBillRuleMapper.java
@@ -0,0 +1,16 @@
+package org.wfc.user.mapper;
+
+import org.wfc.user.domain.UBillRule;
+import com.baomidou.mybatisplus.core.mapper.BaseMapper;
+
+/**
+ *
+ * 用户平台-计费规则表 Mapper 接口
+ *
+ *
+ * @author sys
+ * @since 2025-01-06
+ */
+public interface UBillRuleMapper extends BaseMapper {
+
+}
diff --git a/wfc-modules/wfc-user/src/main/java/org/wfc/user/mapper/UCdrMapper.java b/wfc-modules/wfc-user/src/main/java/org/wfc/user/mapper/UCdrMapper.java
index eb4e6f9..fc4816c 100644
--- a/wfc-modules/wfc-user/src/main/java/org/wfc/user/mapper/UCdrMapper.java
+++ b/wfc-modules/wfc-user/src/main/java/org/wfc/user/mapper/UCdrMapper.java
@@ -6,8 +6,10 @@ import org.wfc.user.domain.UCdr;
import org.wfc.user.domain.bo.UCdrClientBo;
import org.wfc.user.domain.vo.UCdrClientVo;
import org.wfc.user.domain.vo.UCdrHistoryUserVo;
+import org.wfc.user.domain.vo.UCdrLatestHistoryVo;
import org.wfc.user.domain.vo.UCdrUserVo;
+import java.util.Date;
import java.util.List;
/**
@@ -25,4 +27,8 @@ public interface UCdrMapper extends BaseMapper {
List getByClient(@Param("client") UCdrClientBo client);
List getHistoryByUser(@Param("userId") Long userId);
-}
+
+ List getLatestHistory(@Param("userIds") List userIds, @Param("endTime") Date endTime);
+
+ Long getCurrentTraffic(@Param("userId") Long userId);
+ }
diff --git a/wfc-modules/wfc-user/src/main/java/org/wfc/user/service/IUBillRuleService.java b/wfc-modules/wfc-user/src/main/java/org/wfc/user/service/IUBillRuleService.java
new file mode 100644
index 0000000..56a5944
--- /dev/null
+++ b/wfc-modules/wfc-user/src/main/java/org/wfc/user/service/IUBillRuleService.java
@@ -0,0 +1,16 @@
+package org.wfc.user.service;
+
+import org.wfc.user.domain.UBillRule;
+import com.baomidou.mybatisplus.extension.service.IService;
+
+/**
+ *
+ * 用户平台-计费规则表 服务类
+ *
+ *
+ * @author sys
+ * @since 2025-01-06
+ */
+public interface IUBillRuleService extends IService {
+
+}
diff --git a/wfc-modules/wfc-user/src/main/java/org/wfc/user/service/IUBillService.java b/wfc-modules/wfc-user/src/main/java/org/wfc/user/service/IUBillService.java
new file mode 100644
index 0000000..cea4089
--- /dev/null
+++ b/wfc-modules/wfc-user/src/main/java/org/wfc/user/service/IUBillService.java
@@ -0,0 +1,16 @@
+package org.wfc.user.service;
+
+import org.wfc.user.domain.UBill;
+import com.baomidou.mybatisplus.extension.service.IService;
+
+/**
+ *
+ * 用户平台-账单表 服务类
+ *
+ *
+ * @author sys
+ * @since 2025-01-06
+ */
+public interface IUBillService extends IService {
+
+}
diff --git a/wfc-modules/wfc-user/src/main/java/org/wfc/user/service/impl/UAccountServiceImpl.java b/wfc-modules/wfc-user/src/main/java/org/wfc/user/service/impl/UAccountServiceImpl.java
index ff9d5a9..da0eef4 100644
--- a/wfc-modules/wfc-user/src/main/java/org/wfc/user/service/impl/UAccountServiceImpl.java
+++ b/wfc-modules/wfc-user/src/main/java/org/wfc/user/service/impl/UAccountServiceImpl.java
@@ -3,6 +3,7 @@ package org.wfc.user.service.impl;
import cn.hutool.core.collection.CollUtil;
import cn.hutool.core.date.DateTime;
import cn.hutool.core.date.DateUtil;
+import cn.hutool.core.util.NumberUtil;
import cn.hutool.core.util.ObjectUtil;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
@@ -13,24 +14,31 @@ import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.wfc.common.core.domain.LoginUser;
import org.wfc.common.security.utils.SecurityUtils;
-import org.wfc.omada.api.client.OmadaClientApi;
import org.wfc.user.api.IWifiApi;
import org.wfc.user.api.domain.bo.UClientBo;
import org.wfc.user.api.omada.domain.convert.OmadaConvert;
import org.wfc.user.api.omada.domain.dto.ClientRateLimitSettingDto;
import org.wfc.user.domain.UAccount;
+import org.wfc.user.domain.UBill;
+import org.wfc.user.domain.UBillRule;
import org.wfc.user.domain.UClient;
import org.wfc.user.domain.vo.UAccountDashboardVo;
+import org.wfc.user.domain.vo.UCdrLatestHistoryVo;
import org.wfc.user.domain.vo.UCdrUserVo;
import org.wfc.user.mapper.UAccountMapper;
+import org.wfc.user.mapper.UBillMapper;
+import org.wfc.user.mapper.UBillRuleMapper;
import org.wfc.user.mapper.UCdrMapper;
import org.wfc.user.mapper.UClientMapper;
import org.wfc.user.service.IUAccountService;
import org.wfc.user.util.AccountUtil;
import java.math.BigDecimal;
+import java.math.RoundingMode;
+import java.util.ArrayList;
import java.util.Date;
import java.util.List;
+import java.util.Optional;
import java.util.stream.Collectors;
/**
@@ -46,7 +54,7 @@ import java.util.stream.Collectors;
public class UAccountServiceImpl extends ServiceImpl implements IUAccountService {
@Autowired
- private UCdrMapper ucdrMapper;
+ private UCdrMapper cdrMapper;
@Autowired
private IWifiApi wifiApi;
@@ -55,7 +63,11 @@ public class UAccountServiceImpl extends ServiceImpl i
private UClientMapper clientMapper;
@Autowired
- private OmadaClientApi omadaClientApi;
+ private UBillMapper billMapper;
+
+ @Autowired
+ private UBillRuleMapper billRuleMapper;
+
// 定时任务时间间隔
private static final int JOB_PERIOD = -30;
@@ -66,25 +78,118 @@ public class UAccountServiceImpl extends ServiceImpl i
Date current = new Date();
DateTime endTime = DateUtil.offsetSecond(current, JOB_PERIOD);
List accounts = this.list(Wrappers.lambdaQuery()
- .le(UAccount::getStartTime, endTime).gt(UAccount::getEndTime, endTime)
+ .and(wrapper -> wrapper.isNotNull(UAccount::getBalance).gt(UAccount::getBalance, 0).or()
+ .le(UAccount::getStartTime, endTime).gt(UAccount::getEndTime, endTime))
.isNotNull(UAccount::getUserId));
+
+ List packageAccounts = accounts.stream().filter(account -> AccountUtil.isPackageValid(account, current))
+ .collect(Collectors.toList());
+
+ List balanceAccounts = accounts.stream().filter(account -> !AccountUtil.isPackageValid(account, current))
+ .collect(Collectors.toList());
+
+ // 根据使用流量扣费余额
+ List balanceUserIds = balanceAccounts.stream().map(UAccount::getUserId).collect(Collectors.toList());
+
+ List cancelUserIds = new ArrayList<>();
+ if (CollUtil.isNotEmpty(balanceUserIds)) {
+ List latestHistoryList = cdrMapper.getLatestHistory(balanceUserIds, endTime);
+ List billRules = billRuleMapper.selectList(Wrappers.lambdaQuery().eq(UBillRule::getEnable, true));
+ Optional billRuleOptional = billRules.stream().findFirst();
+ if (billRuleOptional.isPresent()) {
+ UBillRule billRule = billRuleOptional.get();
+ for (Long balanceUserId : balanceUserIds) {
+ Long currentTraffic = cdrMapper.getCurrentTraffic(balanceUserId);
+ if (ObjectUtil.isNull(currentTraffic)) {
+ continue;
+ }
+ BigDecimal traffic = BigDecimal.valueOf(currentTraffic).divide(BigDecimal.valueOf(1048576), 4, RoundingMode.HALF_UP);
+ UAccount account = this.getOne(Wrappers.lambdaQuery().eq(UAccount::getUserId, balanceUserId), false);
+ account.setBalanceUsed(NumberUtil.mul(traffic, billRule.getPrice()));
+ if (ObjectUtil.isNull(account.getBalance())) {
+ account.setBalance(BigDecimal.ZERO);
+ }
+ if (account.getBalance().compareTo(account.getBalanceUsed()) <= 0) {
+ cancelUserIds.add(account.getUserId());
+ } else {
+ account.setBalance(BigDecimal.ZERO);
+ }
+ this.updateById(account);
+ }
+
+ for (UCdrLatestHistoryVo historyVo : latestHistoryList) {
+ UBill bill = new UBill();
+ bill.setUserId(historyVo.getUserId());
+ bill.setCdrHistoryId(historyVo.getCdrId());
+ BigDecimal total = NumberUtil.div(NumberUtil.add(historyVo.getTrafficDown(), historyVo.getTrafficUp()), 1048576);
+ bill.setAmount(NumberUtil.mul(total, billRule.getPrice()));
+ billMapper.insert(bill);
+
+ UAccount account = this.getOne(Wrappers.lambdaQuery().eq(UAccount::getUserId, historyVo.getUserId()), false);
+ if (ObjectUtil.isNull(account) || (ObjectUtil.isNotNull(account.getExpiredTime())
+ && account.getExpiredTime().getTime() >= historyVo.getEndTime())) {
+ continue;
+ }
+ if (ObjectUtil.isNull(account.getBalance())) {
+ account.setBalance(BigDecimal.ZERO);
+ }
+ if (account.getBalance().compareTo(bill.getAmount()) > 0) {
+ account.setBalance(account.getBalance().subtract(bill.getAmount()));
+ } else {
+ account.setBalance(BigDecimal.ZERO);
+ cancelUserIds.add(account.getUserId());
+ }
+ this.updateById(account);
+ }
+ }
+ }
+
// 更新账户已使用流量,已使用时长
- for (UAccount account : accounts) {
+ for (UAccount account : packageAccounts) {
if (ObjectUtil.isNull(account.getUserId())) {
continue;
}
- List statCdr = ucdrMapper.getByUser(account.getUserId(), account.getStartTime().getTime(), account.getEndTime().getTime());
+ List statCdr = cdrMapper.getByUser(account.getUserId(), account.getStartTime().getTime(), account.getEndTime().getTime());
statCdr.stream().findFirst().ifPresent(stat -> {
account.setTrafficUsed(stat.getTrafficUp() + stat.getTrafficDown());
account.setDurationUsed(stat.getDuration());
});
}
- this.updateBatchById(accounts);
+ this.updateBatchById(packageAccounts);
- // 取消授权
- List userIds = accounts.stream().filter(account -> !AccountUtil.isValid(account, current))
+ List changeUserIds = packageAccounts.stream().filter(account -> !AccountUtil.isPackageValid(account, current) && AccountUtil.isBalanceValid(account))
.map(UAccount::getUserId)
.collect(Collectors.toList());
+ if (CollUtil.isNotEmpty(changeUserIds)) {
+ List clients = clientMapper.selectList(Wrappers.lambdaQuery().isNotNull(UClient::getSiteId)
+ .in(UClient::getUserId, changeUserIds));
+ for (UClient client : clients) {
+ try {
+ wifiApi.reconnectClient(client.getSiteId(), client.getClientMac());
+
+ // 取消带宽限速
+ ClientRateLimitSettingDto clientRateLimitSetting = new ClientRateLimitSettingDto();
+ clientRateLimitSetting.setRateLimitEnable(false);
+ wifiApi.updateClientRateLimitSetting(client.getSiteId(), client.getClientMac(), clientRateLimitSetting);
+ } catch (Exception e) {
+ log.info("reconnect error: {}", e.getMessage());
+ }
+ }
+ ArrayList changeAccounts = new ArrayList<>();
+ Date expiredTime = new Date();
+ for (Long changeUserId : changeUserIds) {
+ UAccount changeAccount = new UAccount();
+ changeAccount.setId(changeUserId);
+ changeAccount.setExpiredTime(expiredTime);
+ }
+ this.updateBatchById(changeAccounts);
+ }
+
+ // 取消授权
+ List userIds = packageAccounts.stream().filter(account -> !AccountUtil.isValid(account, current))
+ .map(UAccount::getUserId)
+ .collect(Collectors.toList());
+ userIds.addAll(cancelUserIds);
if (CollUtil.isNotEmpty(userIds)) {
List clients = clientMapper.selectList(Wrappers.lambdaQuery().isNotNull(UClient::getSiteId)
@@ -140,6 +245,13 @@ public class UAccountServiceImpl extends ServiceImpl i
BeanUtils.copyProperties(account, dashboardVo);
dashboardVo.setId(loginUser.getUserid());
dashboardVo.setActivity(0L);
+ BigDecimal balanceUsed = Optional.of(account.getBalanceUsed()).orElse(BigDecimal.ZERO);
+ BigDecimal balance = Optional.of(dashboardVo.getBalance()).orElse(BigDecimal.ZERO);
+ if (balance.compareTo(balanceUsed) >= 0) {
+ dashboardVo.setBalance(BigDecimal.ZERO);
+ } else {
+ dashboardVo.setBalance(balance.subtract(balanceUsed));
+ }
}
return dashboardVo;
}
diff --git a/wfc-modules/wfc-user/src/main/java/org/wfc/user/service/impl/UBillRuleServiceImpl.java b/wfc-modules/wfc-user/src/main/java/org/wfc/user/service/impl/UBillRuleServiceImpl.java
new file mode 100644
index 0000000..6dbf6c2
--- /dev/null
+++ b/wfc-modules/wfc-user/src/main/java/org/wfc/user/service/impl/UBillRuleServiceImpl.java
@@ -0,0 +1,20 @@
+package org.wfc.user.service.impl;
+
+import org.wfc.user.domain.UBillRule;
+import org.wfc.user.mapper.UBillRuleMapper;
+import org.wfc.user.service.IUBillRuleService;
+import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
+import org.springframework.stereotype.Service;
+
+/**
+ *
+ * 用户平台-计费规则表 服务实现类
+ *
+ *
+ * @author sys
+ * @since 2025-01-06
+ */
+@Service
+public class UBillRuleServiceImpl extends ServiceImpl implements IUBillRuleService {
+
+}
diff --git a/wfc-modules/wfc-user/src/main/java/org/wfc/user/service/impl/UBillServiceImpl.java b/wfc-modules/wfc-user/src/main/java/org/wfc/user/service/impl/UBillServiceImpl.java
new file mode 100644
index 0000000..983c6e3
--- /dev/null
+++ b/wfc-modules/wfc-user/src/main/java/org/wfc/user/service/impl/UBillServiceImpl.java
@@ -0,0 +1,20 @@
+package org.wfc.user.service.impl;
+
+import org.wfc.user.domain.UBill;
+import org.wfc.user.mapper.UBillMapper;
+import org.wfc.user.service.IUBillService;
+import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
+import org.springframework.stereotype.Service;
+
+/**
+ *
+ * 用户平台-账单表 服务实现类
+ *
+ *
+ * @author sys
+ * @since 2025-01-06
+ */
+@Service
+public class UBillServiceImpl extends ServiceImpl implements IUBillService {
+
+}
diff --git a/wfc-modules/wfc-user/src/main/java/org/wfc/user/service/impl/UCdrServiceImpl.java b/wfc-modules/wfc-user/src/main/java/org/wfc/user/service/impl/UCdrServiceImpl.java
index 5928401..d3516af 100644
--- a/wfc-modules/wfc-user/src/main/java/org/wfc/user/service/impl/UCdrServiceImpl.java
+++ b/wfc-modules/wfc-user/src/main/java/org/wfc/user/service/impl/UCdrServiceImpl.java
@@ -72,6 +72,7 @@ public class UCdrServiceImpl extends ServiceImpl implements IU
@Autowired
private IUAccountService accountService;
+
@Override
public UCdrUserVo getByUser() {
LoginUser