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 loginUser = SecurityUtils.getLoginUser(); @@ -142,6 +143,7 @@ public class UCdrServiceImpl extends ServiceImpl implements IU .trafficDown(pastConn.getDownload()) .duration(pastConn.getDuration()) .build(); + cdrHistoryService.save(uCdrHistory); } } diff --git a/wfc-modules/wfc-user/src/main/java/org/wfc/user/util/AccountUtil.java b/wfc-modules/wfc-user/src/main/java/org/wfc/user/util/AccountUtil.java index ae006fe..f1efaa0 100644 --- a/wfc-modules/wfc-user/src/main/java/org/wfc/user/util/AccountUtil.java +++ b/wfc-modules/wfc-user/src/main/java/org/wfc/user/util/AccountUtil.java @@ -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; + } } diff --git a/wfc-modules/wfc-user/src/main/resources/mapper/user/UBillMapper.xml b/wfc-modules/wfc-user/src/main/resources/mapper/user/UBillMapper.xml new file mode 100644 index 0000000..d1290f5 --- /dev/null +++ b/wfc-modules/wfc-user/src/main/resources/mapper/user/UBillMapper.xml @@ -0,0 +1,5 @@ + + + + + diff --git a/wfc-modules/wfc-user/src/main/resources/mapper/user/UBillRuleMapper.xml b/wfc-modules/wfc-user/src/main/resources/mapper/user/UBillRuleMapper.xml new file mode 100644 index 0000000..d1fe984 --- /dev/null +++ b/wfc-modules/wfc-user/src/main/resources/mapper/user/UBillRuleMapper.xml @@ -0,0 +1,5 @@ + + + + + diff --git a/wfc-modules/wfc-user/src/main/resources/mapper/user/UCdrMapper.xml b/wfc-modules/wfc-user/src/main/resources/mapper/user/UCdrMapper.xml index 0c98352..942c55d 100644 --- a/wfc-modules/wfc-user/src/main/resources/mapper/user/UCdrMapper.xml +++ b/wfc-modules/wfc-user/src/main/resources/mapper/user/UCdrMapper.xml @@ -133,4 +133,41 @@ ORDER BY ch.start_time DESC + + + +