feat: 余额计费
This commit is contained in:
@@ -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
|
||||
|
||||
@@ -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;
|
||||
|
||||
/**
|
||||
* <p>
|
||||
* 用户平台-账单表 前端控制器
|
||||
* </p>
|
||||
*
|
||||
* @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<UBill> list = uBillService.list();
|
||||
return getDataTable(list);
|
||||
}
|
||||
|
||||
@GetMapping("/list")
|
||||
public AjaxResult list(UBill uBill) {
|
||||
List<UBill> 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)));
|
||||
}
|
||||
|
||||
}
|
||||
@@ -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;
|
||||
|
||||
/**
|
||||
* <p>
|
||||
* 用户平台-计费规则表 前端控制器
|
||||
* </p>
|
||||
*
|
||||
* @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<UBillRule> list = uBillRuleService.list();
|
||||
return getDataTable(list);
|
||||
}
|
||||
|
||||
@GetMapping("/list")
|
||||
public AjaxResult list(UBillRule uBillRule) {
|
||||
List<UBillRule> 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)));
|
||||
}
|
||||
|
||||
}
|
||||
@@ -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;
|
||||
|
||||
|
||||
@@ -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;
|
||||
|
||||
/**
|
||||
* <p>
|
||||
* 用户平台-账单表
|
||||
* </p>
|
||||
*
|
||||
* @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;
|
||||
}
|
||||
@@ -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;
|
||||
|
||||
/**
|
||||
* <p>
|
||||
* 用户平台-计费规则表
|
||||
* </p>
|
||||
*
|
||||
* @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;
|
||||
}
|
||||
@@ -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;
|
||||
}
|
||||
@@ -0,0 +1,16 @@
|
||||
package org.wfc.user.mapper;
|
||||
|
||||
import org.wfc.user.domain.UBill;
|
||||
import com.baomidou.mybatisplus.core.mapper.BaseMapper;
|
||||
|
||||
/**
|
||||
* <p>
|
||||
* 用户平台-账单表 Mapper 接口
|
||||
* </p>
|
||||
*
|
||||
* @author sys
|
||||
* @since 2025-01-06
|
||||
*/
|
||||
public interface UBillMapper extends BaseMapper<UBill> {
|
||||
|
||||
}
|
||||
@@ -0,0 +1,16 @@
|
||||
package org.wfc.user.mapper;
|
||||
|
||||
import org.wfc.user.domain.UBillRule;
|
||||
import com.baomidou.mybatisplus.core.mapper.BaseMapper;
|
||||
|
||||
/**
|
||||
* <p>
|
||||
* 用户平台-计费规则表 Mapper 接口
|
||||
* </p>
|
||||
*
|
||||
* @author sys
|
||||
* @since 2025-01-06
|
||||
*/
|
||||
public interface UBillRuleMapper extends BaseMapper<UBillRule> {
|
||||
|
||||
}
|
||||
@@ -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<UCdr> {
|
||||
List<UCdrClientVo> getByClient(@Param("client") UCdrClientBo client);
|
||||
|
||||
List<UCdrHistoryUserVo> getHistoryByUser(@Param("userId") Long userId);
|
||||
|
||||
List<UCdrLatestHistoryVo> getLatestHistory(@Param("userIds") List<Long> userIds, @Param("endTime") Date endTime);
|
||||
|
||||
Long getCurrentTraffic(@Param("userId") Long userId);
|
||||
}
|
||||
|
||||
@@ -0,0 +1,16 @@
|
||||
package org.wfc.user.service;
|
||||
|
||||
import org.wfc.user.domain.UBillRule;
|
||||
import com.baomidou.mybatisplus.extension.service.IService;
|
||||
|
||||
/**
|
||||
* <p>
|
||||
* 用户平台-计费规则表 服务类
|
||||
* </p>
|
||||
*
|
||||
* @author sys
|
||||
* @since 2025-01-06
|
||||
*/
|
||||
public interface IUBillRuleService extends IService<UBillRule> {
|
||||
|
||||
}
|
||||
@@ -0,0 +1,16 @@
|
||||
package org.wfc.user.service;
|
||||
|
||||
import org.wfc.user.domain.UBill;
|
||||
import com.baomidou.mybatisplus.extension.service.IService;
|
||||
|
||||
/**
|
||||
* <p>
|
||||
* 用户平台-账单表 服务类
|
||||
* </p>
|
||||
*
|
||||
* @author sys
|
||||
* @since 2025-01-06
|
||||
*/
|
||||
public interface IUBillService extends IService<UBill> {
|
||||
|
||||
}
|
||||
@@ -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<UAccountMapper, UAccount> implements IUAccountService {
|
||||
|
||||
@Autowired
|
||||
private UCdrMapper ucdrMapper;
|
||||
private UCdrMapper cdrMapper;
|
||||
|
||||
@Autowired
|
||||
private IWifiApi wifiApi;
|
||||
@@ -55,7 +63,11 @@ public class UAccountServiceImpl extends ServiceImpl<UAccountMapper, UAccount> 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<UAccountMapper, UAccount> i
|
||||
Date current = new Date();
|
||||
DateTime endTime = DateUtil.offsetSecond(current, JOB_PERIOD);
|
||||
List<UAccount> accounts = this.list(Wrappers.<UAccount>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<UAccount> packageAccounts = accounts.stream().filter(account -> AccountUtil.isPackageValid(account, current))
|
||||
.collect(Collectors.toList());
|
||||
|
||||
List<UAccount> balanceAccounts = accounts.stream().filter(account -> !AccountUtil.isPackageValid(account, current))
|
||||
.collect(Collectors.toList());
|
||||
|
||||
// 根据使用流量扣费余额
|
||||
List<Long> balanceUserIds = balanceAccounts.stream().map(UAccount::getUserId).collect(Collectors.toList());
|
||||
|
||||
List<Long> cancelUserIds = new ArrayList<>();
|
||||
if (CollUtil.isNotEmpty(balanceUserIds)) {
|
||||
List<UCdrLatestHistoryVo> latestHistoryList = cdrMapper.getLatestHistory(balanceUserIds, endTime);
|
||||
List<UBillRule> billRules = billRuleMapper.selectList(Wrappers.<UBillRule>lambdaQuery().eq(UBillRule::getEnable, true));
|
||||
Optional<UBillRule> 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.<UAccount>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.<UAccount>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<UCdrUserVo> statCdr = ucdrMapper.getByUser(account.getUserId(), account.getStartTime().getTime(), account.getEndTime().getTime());
|
||||
List<UCdrUserVo> 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<Long> userIds = accounts.stream().filter(account -> !AccountUtil.isValid(account, current))
|
||||
List<Long> changeUserIds = packageAccounts.stream().filter(account -> !AccountUtil.isPackageValid(account, current) && AccountUtil.isBalanceValid(account))
|
||||
.map(UAccount::getUserId)
|
||||
.collect(Collectors.toList());
|
||||
if (CollUtil.isNotEmpty(changeUserIds)) {
|
||||
List<UClient> clients = clientMapper.selectList(Wrappers.<UClient>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<UAccount> 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<Long> userIds = packageAccounts.stream().filter(account -> !AccountUtil.isValid(account, current))
|
||||
.map(UAccount::getUserId)
|
||||
.collect(Collectors.toList());
|
||||
userIds.addAll(cancelUserIds);
|
||||
|
||||
if (CollUtil.isNotEmpty(userIds)) {
|
||||
List<UClient> clients = clientMapper.selectList(Wrappers.<UClient>lambdaQuery().isNotNull(UClient::getSiteId)
|
||||
@@ -140,6 +245,13 @@ public class UAccountServiceImpl extends ServiceImpl<UAccountMapper, UAccount> 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;
|
||||
}
|
||||
|
||||
@@ -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;
|
||||
|
||||
/**
|
||||
* <p>
|
||||
* 用户平台-计费规则表 服务实现类
|
||||
* </p>
|
||||
*
|
||||
* @author sys
|
||||
* @since 2025-01-06
|
||||
*/
|
||||
@Service
|
||||
public class UBillRuleServiceImpl extends ServiceImpl<UBillRuleMapper, UBillRule> implements IUBillRuleService {
|
||||
|
||||
}
|
||||
@@ -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;
|
||||
|
||||
/**
|
||||
* <p>
|
||||
* 用户平台-账单表 服务实现类
|
||||
* </p>
|
||||
*
|
||||
* @author sys
|
||||
* @since 2025-01-06
|
||||
*/
|
||||
@Service
|
||||
public class UBillServiceImpl extends ServiceImpl<UBillMapper, UBill> implements IUBillService {
|
||||
|
||||
}
|
||||
@@ -72,6 +72,7 @@ public class UCdrServiceImpl extends ServiceImpl<UCdrMapper, UCdr> implements IU
|
||||
@Autowired
|
||||
private IUAccountService accountService;
|
||||
|
||||
|
||||
@Override
|
||||
public UCdrUserVo getByUser() {
|
||||
LoginUser<Object> loginUser = SecurityUtils.getLoginUser();
|
||||
@@ -142,6 +143,7 @@ public class UCdrServiceImpl extends ServiceImpl<UCdrMapper, UCdr> implements IU
|
||||
.trafficDown(pastConn.getDownload())
|
||||
.duration(pastConn.getDuration())
|
||||
.build();
|
||||
|
||||
cdrHistoryService.save(uCdrHistory);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,8 +1,10 @@
|
||||
package org.wfc.user.util;
|
||||
|
||||
import cn.hutool.core.date.DateUtil;
|
||||
import cn.hutool.core.util.ObjectUtil;
|
||||
import org.wfc.user.domain.UAccount;
|
||||
|
||||
import java.math.BigDecimal;
|
||||
import java.util.Date;
|
||||
|
||||
/**
|
||||
@@ -20,9 +22,22 @@ public class AccountUtil {
|
||||
* @return boolean
|
||||
*/
|
||||
public static boolean isValid(UAccount account, Date current) {
|
||||
// 过期/流量已用完/时长已用完应取消授权
|
||||
return ((DateUtil.compare(account.getStartTime(), current) <= 0 && DateUtil.compare(account.getEndTime(), current) > 0)
|
||||
&& (!account.getTrafficEnable() || account.getTrafficUsed() <= account.getTraffic())
|
||||
&& (!account.getDurationEnable() || account.getDurationUsed() <= account.getDuration()))
|
||||
|| (ObjectUtil.isNotNull(account.getBalance()) && account.getBalance().compareTo(BigDecimal.ZERO) > 0);
|
||||
}
|
||||
|
||||
public static boolean isPackageValid(UAccount account, Date current) {
|
||||
// 过期/流量已用完/时长已用完应取消授权
|
||||
return (DateUtil.compare(account.getStartTime(), current) <= 0 && DateUtil.compare(account.getEndTime(), current) > 0)
|
||||
&& (!account.getTrafficEnable() || account.getTrafficUsed() <= account.getTraffic())
|
||||
&& (!account.getDurationEnable() || account.getDurationUsed() <= account.getDuration());
|
||||
}
|
||||
|
||||
public static boolean isBalanceValid(UAccount account) {
|
||||
// 过期/流量已用完/时长已用完应取消授权
|
||||
return ObjectUtil.isNotNull(account.getBalance()) && account.getBalance().compareTo(BigDecimal.ZERO) > 0;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -0,0 +1,5 @@
|
||||
<?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="org.wfc.user.mapper.UBillMapper">
|
||||
|
||||
</mapper>
|
||||
@@ -0,0 +1,5 @@
|
||||
<?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="org.wfc.user.mapper.UBillRuleMapper">
|
||||
|
||||
</mapper>
|
||||
@@ -133,4 +133,41 @@
|
||||
ORDER BY
|
||||
ch.start_time DESC
|
||||
</select>
|
||||
|
||||
<select id="getLatestHistory" resultType="org.wfc.user.domain.vo.UCdrLatestHistoryVo">
|
||||
SELECT
|
||||
h.*,
|
||||
c.user_id
|
||||
FROM
|
||||
u_cdr_history h
|
||||
LEFT JOIN u_cdr c ON h.cdr_id = c.id
|
||||
AND c.del_flag = 0
|
||||
WHERE
|
||||
h.del_flag = 0
|
||||
<if test="userIds != null and userIds.size() > 0">
|
||||
AND c.user_id in
|
||||
<foreach collection="userIds" item="userId" open="(" separator="," close=")">
|
||||
#{userId}
|
||||
</foreach>
|
||||
</if>
|
||||
<if test="endTime != null">
|
||||
AND h.create_time > #{endTime}
|
||||
</if>
|
||||
</select>
|
||||
|
||||
<select id="getCurrentTraffic" resultType="long">
|
||||
SELECT
|
||||
sum(
|
||||
ifnull( c.traffic_down, 0 )) + sum(
|
||||
ifnull( c.traffic_up, 0 )) traffic
|
||||
FROM
|
||||
u_cdr c
|
||||
LEFT JOIN ( SELECT h.cdr_id, max( h.end_time ) end_time FROM u_cdr_history h WHERE h.del_flag = 0 GROUP BY h.cdr_id ) h ON c.id = h.cdr_id
|
||||
WHERE
|
||||
c.del_flag = 0
|
||||
AND c.last_seen_time != ifnull( h.end_time, 0 )
|
||||
AND c.user_id = #{userId}
|
||||
GROUP BY
|
||||
c.user_id
|
||||
</select>
|
||||
</mapper>
|
||||
|
||||
Reference in New Issue
Block a user