Compare commits
9 Commits
main
...
feature/mu
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
4ed514a806 | ||
|
|
42fb1c3d7a | ||
|
|
16dc1360ef | ||
|
|
f586059272 | ||
|
|
3d7c2cb156 | ||
|
|
4c059f6a27 | ||
|
|
9087a0cf93 | ||
|
|
675171c15f | ||
|
|
287c4a3b0f |
@@ -24,10 +24,10 @@ import java.util.List;
|
||||
* </p>
|
||||
*
|
||||
* @author sys
|
||||
* @since 2025-02-10
|
||||
* @since 2025-03-13
|
||||
*/
|
||||
@RestController
|
||||
@RequestMapping("/user/uAccountPackage")
|
||||
@RequestMapping("/accountPackage")
|
||||
public class UAccountPackageController extends BaseController {
|
||||
|
||||
@Autowired
|
||||
@@ -36,13 +36,13 @@ public class UAccountPackageController extends BaseController {
|
||||
@GetMapping("/page")
|
||||
public TableDataInfo page(UAccountPackage uAccountPackage) {
|
||||
startPage();
|
||||
List<UAccountPackage> list = uAccountPackageService.list();
|
||||
List<UAccountPackage> list = uAccountPackageService.queryList(uAccountPackage);
|
||||
return getDataTable(list);
|
||||
}
|
||||
|
||||
@GetMapping("/list")
|
||||
public AjaxResult list(UAccountPackage uAccountPackage) {
|
||||
List<UAccountPackage> list = uAccountPackageService.list();
|
||||
List<UAccountPackage> list = uAccountPackageService.queryList(uAccountPackage);
|
||||
return success(list);
|
||||
}
|
||||
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
package org.wfc.user.domain;
|
||||
|
||||
import com.baomidou.mybatisplus.annotation.TableField;
|
||||
import com.baomidou.mybatisplus.annotation.TableName;
|
||||
import io.swagger.v3.oas.annotations.media.Schema;
|
||||
import lombok.Getter;
|
||||
@@ -84,4 +85,8 @@ public class UAccountPackage extends BaseData {
|
||||
|
||||
@Schema(description = "上行限速启用")
|
||||
private Boolean upLimitEnable;
|
||||
|
||||
@Schema(description = "上行限速启用")
|
||||
@TableField(exist = false)
|
||||
private Integer status;
|
||||
}
|
||||
|
||||
@@ -0,0 +1,20 @@
|
||||
package org.wfc.user.domain.constant;
|
||||
|
||||
import lombok.AllArgsConstructor;
|
||||
import lombok.Getter;
|
||||
|
||||
/**
|
||||
* @description: 套餐状态
|
||||
* @author: cyc
|
||||
* @since: 2025-03-14
|
||||
*/
|
||||
@Getter
|
||||
@AllArgsConstructor
|
||||
public enum PackageStatusEnum {
|
||||
|
||||
INVALID(0, "未生效"),
|
||||
VALID(1, "生效");
|
||||
|
||||
private final Integer code;
|
||||
private final String desc;
|
||||
}
|
||||
@@ -0,0 +1,18 @@
|
||||
package org.wfc.user.domain.convert;
|
||||
|
||||
import org.mapstruct.Mapper;
|
||||
import org.mapstruct.factory.Mappers;
|
||||
import org.wfc.user.domain.UAccount;
|
||||
import org.wfc.user.domain.UAccountPackage;
|
||||
|
||||
/**
|
||||
* @description: AccountPackageConvert
|
||||
* @author: cyc
|
||||
* @since: 2025-03-14
|
||||
*/
|
||||
@Mapper
|
||||
public interface AccountPackageConvert {
|
||||
AccountPackageConvert INSTANCE = Mappers.getMapper(AccountPackageConvert.class);
|
||||
|
||||
UAccountPackage toAccountPackage(UAccount account);
|
||||
}
|
||||
@@ -67,4 +67,6 @@ public class UAccountDashboardVo {
|
||||
private Long activity;
|
||||
|
||||
private Integer status;
|
||||
|
||||
private Integer packageNum;
|
||||
}
|
||||
|
||||
@@ -3,14 +3,17 @@ package org.wfc.user.service;
|
||||
import org.wfc.user.domain.UAccountPackage;
|
||||
import com.baomidou.mybatisplus.extension.service.IService;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
/**
|
||||
* <p>
|
||||
* 用户平台-账户套餐表 服务类
|
||||
* </p>
|
||||
*
|
||||
* @author sys
|
||||
* @since 2025-02-10
|
||||
* @since 2025-03-13
|
||||
*/
|
||||
public interface IUAccountPackageService extends IService<UAccountPackage> {
|
||||
|
||||
List<UAccountPackage> queryList(UAccountPackage uAccountPackage);
|
||||
}
|
||||
|
||||
@@ -1,10 +1,28 @@
|
||||
package org.wfc.user.service.impl;
|
||||
|
||||
import cn.hutool.core.util.ObjectUtil;
|
||||
import cn.hutool.core.util.StrUtil;
|
||||
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
|
||||
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
|
||||
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
|
||||
import org.springframework.beans.factory.annotation.Autowired;
|
||||
import org.springframework.stereotype.Service;
|
||||
import org.wfc.common.mybatis.domain.BaseData;
|
||||
import org.wfc.common.security.utils.SecurityUtils;
|
||||
import org.wfc.user.domain.UAccount;
|
||||
import org.wfc.user.domain.UAccountPackage;
|
||||
import org.wfc.user.domain.constant.PackageStatusEnum;
|
||||
import org.wfc.user.domain.convert.AccountPackageConvert;
|
||||
import org.wfc.user.mapper.UAccountMapper;
|
||||
import org.wfc.user.mapper.UAccountPackageMapper;
|
||||
import org.wfc.user.service.IUAccountPackageService;
|
||||
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
|
||||
import org.springframework.stereotype.Service;
|
||||
import org.wfc.user.util.AccountUtil;
|
||||
|
||||
import java.util.ArrayList;
|
||||
import java.util.Collections;
|
||||
import java.util.Date;
|
||||
import java.util.List;
|
||||
import java.util.stream.Collectors;
|
||||
|
||||
/**
|
||||
* <p>
|
||||
@@ -12,9 +30,58 @@ import org.springframework.stereotype.Service;
|
||||
* </p>
|
||||
*
|
||||
* @author sys
|
||||
* @since 2025-02-10
|
||||
* @since 2025-03-13
|
||||
*/
|
||||
@Service
|
||||
public class UAccountPackageServiceImpl extends ServiceImpl<UAccountPackageMapper, UAccountPackage> implements IUAccountPackageService {
|
||||
|
||||
@Autowired
|
||||
private UAccountMapper accountMapper;
|
||||
|
||||
@Override
|
||||
public List<UAccountPackage> queryList(UAccountPackage uAccountPackage) {
|
||||
UAccount account = accountMapper.selectOne(Wrappers.<UAccount>lambdaQuery().eq(UAccount::getUserId, SecurityUtils.getLoginUser().getUserid()), false);
|
||||
if (ObjectUtil.isNull(account) || !AccountUtil.isPackageValid(account, new Date())) {
|
||||
return Collections.emptyList();
|
||||
}
|
||||
List<UAccountPackage> packages = new ArrayList<>();
|
||||
// 添加当前生效的
|
||||
UAccountPackage accountPackage = AccountPackageConvert.INSTANCE.toAccountPackage(account);
|
||||
accountPackage.setAccountId(account.getId());
|
||||
accountPackage.setStatus(PackageStatusEnum.VALID.getCode());
|
||||
packages.add(accountPackage);
|
||||
|
||||
uAccountPackage.setAccountId(account.getId());
|
||||
List<UAccountPackage> invalidPackages = this.list(buildQueryWrapper(uAccountPackage));
|
||||
invalidPackages = invalidPackages.stream().peek(p -> p.setStatus(PackageStatusEnum.INVALID.getCode()))
|
||||
.collect(Collectors.toList());
|
||||
packages.addAll(invalidPackages);
|
||||
return packages;
|
||||
}
|
||||
|
||||
private LambdaQueryWrapper<UAccountPackage> buildQueryWrapper(UAccountPackage bo) {
|
||||
LambdaQueryWrapper<UAccountPackage> lqw = Wrappers.lambdaQuery();
|
||||
lqw.eq(bo.getAccountId() != null, UAccountPackage::getAccountId, bo.getAccountId());
|
||||
lqw.eq(bo.getPackageId() != null, UAccountPackage::getPackageId, bo.getPackageId());
|
||||
lqw.eq(bo.getTraffic() != null, UAccountPackage::getTraffic, bo.getTraffic());
|
||||
lqw.eq(bo.getDuration() != null, UAccountPackage::getDuration, bo.getDuration());
|
||||
lqw.eq(bo.getClientNum() != null, UAccountPackage::getClientNum, bo.getClientNum());
|
||||
lqw.eq(bo.getExpiredTime() != null, UAccountPackage::getExpiredTime, bo.getExpiredTime());
|
||||
lqw.like(StrUtil.isNotBlank(bo.getPackageName()), UAccountPackage::getPackageName, bo.getPackageName());
|
||||
lqw.eq(bo.getPeriodNum() != null, UAccountPackage::getPeriodNum, bo.getPeriodNum());
|
||||
lqw.eq(bo.getPeriodType() != null, UAccountPackage::getPeriodType, bo.getPeriodType());
|
||||
lqw.eq(bo.getPrice() != null, UAccountPackage::getPrice, bo.getPrice());
|
||||
lqw.like(StrUtil.isNotBlank(bo.getRemark()), UAccountPackage::getRemark, bo.getRemark());
|
||||
lqw.eq(bo.getRateLimitEnable() != null, UAccountPackage::getRateLimitEnable, bo.getRateLimitEnable());
|
||||
lqw.eq(bo.getTrafficEnable() != null, UAccountPackage::getTrafficEnable, bo.getTrafficEnable());
|
||||
lqw.eq(bo.getDurationEnable() != null, UAccountPackage::getDurationEnable, bo.getDurationEnable());
|
||||
lqw.eq(bo.getClientNumEnable() != null, UAccountPackage::getClientNumEnable, bo.getClientNumEnable());
|
||||
lqw.like(StrUtil.isNotBlank(bo.getRateLimitName()), UAccountPackage::getRateLimitName, bo.getRateLimitName());
|
||||
lqw.eq(bo.getDownLimit() != null, UAccountPackage::getDownLimit, bo.getDownLimit());
|
||||
lqw.eq(bo.getDownLimitEnable() != null, UAccountPackage::getDownLimitEnable, bo.getDownLimitEnable());
|
||||
lqw.eq(bo.getUpLimit() != null, UAccountPackage::getUpLimit, bo.getUpLimit());
|
||||
lqw.eq(bo.getUpLimitEnable() != null, UAccountPackage::getUpLimitEnable, bo.getUpLimitEnable());
|
||||
lqw.orderByAsc(BaseData::getCreateTime);
|
||||
return lqw;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
package org.wfc.user.service.impl;
|
||||
|
||||
import cn.hutool.core.collection.CollUtil;
|
||||
import cn.hutool.core.date.DateTime;
|
||||
import cn.hutool.core.util.ObjectUtil;
|
||||
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
|
||||
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
|
||||
@@ -26,6 +27,7 @@ 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.UAccountPackage;
|
||||
import org.wfc.user.domain.UBill;
|
||||
import org.wfc.user.domain.UBillRule;
|
||||
import org.wfc.user.domain.UClient;
|
||||
@@ -39,6 +41,7 @@ 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.IUAccountPackageService;
|
||||
import org.wfc.user.service.IUAccountService;
|
||||
import org.wfc.user.service.IUClientService;
|
||||
import org.wfc.user.util.AccountUtil;
|
||||
@@ -88,6 +91,9 @@ public class UAccountServiceImpl extends ServiceImpl<UAccountMapper, UAccount> i
|
||||
@Lazy
|
||||
private IUClientService uClientService;
|
||||
|
||||
@Autowired
|
||||
private IUAccountPackageService accountPackageService;
|
||||
|
||||
@Transactional(rollbackFor = Exception.class)
|
||||
public void statAndCancelAuthUser() {
|
||||
// 定时任务查询所有未过期或刚过期(失效时间+定时任务间隔时间)的账户套餐,套餐过期/流量用完/时长用完则取消授权
|
||||
@@ -163,6 +169,30 @@ public class UAccountServiceImpl extends ServiceImpl<UAccountMapper, UAccount> i
|
||||
continue;
|
||||
}
|
||||
UAccount account = this.getOne(Wrappers.<UAccount>lambdaQuery().eq(UAccount::getUserId, loginClient.getUserId()), false);
|
||||
// 套餐失效,但是还有其他可用套餐
|
||||
if (!AccountUtil.isPackageValid(account, current)) {
|
||||
List<UAccountPackage> accountPackages = accountPackageService.list(Wrappers.<UAccountPackage>lambdaQuery()
|
||||
.eq(UAccountPackage::getAccountId, account.getId()).orderByAsc(UAccountPackage::getCreateTime));
|
||||
Optional<UAccountPackage> accountPackageOptional = accountPackages.stream().findFirst();
|
||||
if (accountPackageOptional.isPresent()) {
|
||||
wifiApi.reconnectClient(site.getSiteId(), client.getMac());
|
||||
UAccountPackage accountPackage = accountPackageOptional.get();
|
||||
Long accountId = account.getId();
|
||||
BeanUtils.copyProperties(accountPackage, account);
|
||||
account.setId(accountId);
|
||||
account.setTrafficUsed(0L);
|
||||
account.setDurationUsed(0L);
|
||||
account.setClientNumUsed(0);
|
||||
Date startTime = new Date();
|
||||
DateTime endTime = AccountUtil.getEndTime(accountPackage.getPeriodType(), accountPackage.getPeriodNum(), startTime);
|
||||
account.setStartTime(current);
|
||||
account.setEndTime(endTime);
|
||||
// 更新账号套餐和删除使用套餐
|
||||
this.updateById(account);
|
||||
accountPackageService.removeById(accountPackage.getId());
|
||||
}
|
||||
}
|
||||
|
||||
// 套餐失效,但是有余额且没有已使用余额,reconnect
|
||||
if (AccountUtil.isPackageUnValidBalanceValid(account, current)) {
|
||||
wifiApi.reconnectClient(site.getSiteId(), client.getMac());
|
||||
@@ -254,8 +284,10 @@ public class UAccountServiceImpl extends ServiceImpl<UAccountMapper, UAccount> i
|
||||
} else {
|
||||
dashboardVo.setStatus(0);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
List<UAccountPackage> accountPackages = accountPackageService.queryList(new UAccountPackage());
|
||||
dashboardVo.setPackageNum(accountPackages.size());
|
||||
return dashboardVo;
|
||||
}
|
||||
|
||||
|
||||
@@ -135,6 +135,9 @@ public class UCdrServiceImpl extends ServiceImpl<UCdrMapper, UCdr> implements IU
|
||||
|
||||
// 新增cdr历史
|
||||
for (UClient client : allClients) {
|
||||
if (!Objects.equals(client.getSiteId(), site.getSiteId())) {
|
||||
continue;
|
||||
}
|
||||
UCdr uCdr = this.getOne(Wrappers.<UCdr>lambdaQuery().eq(UCdr::getUserId, client.getUserId())
|
||||
.eq(UCdr::getClientId, client.getId()), false);
|
||||
if (ObjectUtil.isNotNull(uCdr)) {
|
||||
@@ -286,6 +289,7 @@ public class UCdrServiceImpl extends ServiceImpl<UCdrMapper, UCdr> implements IU
|
||||
userId = hasClient.getUserId();
|
||||
}
|
||||
UClient uClient = UClient.builder().clientMac(client.getMac())
|
||||
.siteId(siteId)
|
||||
.userId(userId)
|
||||
.clientName(client.getName())
|
||||
.clientDeviceType(client.getDeviceType())
|
||||
|
||||
@@ -1,8 +1,6 @@
|
||||
package org.wfc.user.service.impl;
|
||||
|
||||
import cn.hutool.core.date.DateField;
|
||||
import cn.hutool.core.date.DateTime;
|
||||
import cn.hutool.core.date.DateUtil;
|
||||
import cn.hutool.core.util.ObjectUtil;
|
||||
import cn.hutool.core.util.StrUtil;
|
||||
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
|
||||
@@ -26,7 +24,6 @@ import org.wfc.user.domain.UPackage;
|
||||
import org.wfc.user.domain.URateLimit;
|
||||
import org.wfc.user.domain.constant.OrderStatusEnum;
|
||||
import org.wfc.user.domain.constant.OrderTypeEnum;
|
||||
import org.wfc.user.domain.constant.PeriodTypeEnum;
|
||||
import org.wfc.user.mapper.UAccountPackageMapper;
|
||||
import org.wfc.user.mapper.UBillMapper;
|
||||
import org.wfc.user.mapper.UBillRuleMapper;
|
||||
@@ -111,11 +108,11 @@ public class UOrderServiceImpl extends ServiceImpl<UOrderMapper, UOrder> impleme
|
||||
} else {
|
||||
accountId = account.getId();
|
||||
oldBalance = account.getBalance();
|
||||
isValid = AccountUtil.isValid(account, new Date());
|
||||
isValid = AccountUtil.isPackageValid(account, new Date());
|
||||
}
|
||||
if (OrderTypeEnum.PACKAGE.getCode().equals(order.getType())) {
|
||||
// 套餐
|
||||
callbackPackage(order, account, false);
|
||||
callbackPackage(order, account, isValid);
|
||||
} else if (OrderTypeEnum.RECHARGE.getCode().equals(order.getType())) {
|
||||
// 充值
|
||||
// 更新账户余额
|
||||
@@ -138,7 +135,7 @@ public class UOrderServiceImpl extends ServiceImpl<UOrderMapper, UOrder> impleme
|
||||
wifiApi.authClient(client.getSiteId(), client.getClientMac());
|
||||
// 套餐生效已授权时,调reconnect重连接口,以便截取时间
|
||||
if (isValid && !(OrderTypeEnum.RECHARGE.getCode().equals(order.getType()) && oldBalance.compareTo(BigDecimal.ZERO) > 0)) {
|
||||
wifiApi.reconnectClient(client.getSiteId(), client.getClientMac());
|
||||
// wifiApi.reconnectClient(client.getSiteId(), client.getClientMac());
|
||||
}
|
||||
// 带宽限速
|
||||
ClientRateLimitSettingDto clientRateLimitSetting = OmadaConvert.INSTANCE.toClientRateLimitSettingDto(account);
|
||||
@@ -197,6 +194,9 @@ public class UOrderServiceImpl extends ServiceImpl<UOrderMapper, UOrder> impleme
|
||||
|
||||
if (isValid) {
|
||||
BeanUtils.copyProperties(uPackage, accountPackage);
|
||||
accountPackage.setId(null);
|
||||
accountPackage.setCreateTime(null);
|
||||
accountPackage.setAccountId(account.getId());
|
||||
accountPackage.setPackageId(order.getPackageId());
|
||||
accountPackageMapper.insert(accountPackage);
|
||||
} else {
|
||||
@@ -206,33 +206,12 @@ public class UOrderServiceImpl extends ServiceImpl<UOrderMapper, UOrder> impleme
|
||||
account.setDurationUsed(0L);
|
||||
account.setClientNumUsed(0);
|
||||
Date current = new Date();
|
||||
DateTime endTime = getEndTime(uPackage, current);
|
||||
DateTime endTime = AccountUtil.getEndTime(uPackage.getPeriodType(), uPackage.getPeriodNum(), current);
|
||||
account.setStartTime(current);
|
||||
account.setEndTime(endTime);
|
||||
}
|
||||
}
|
||||
|
||||
private static DateTime getEndTime(UPackage uPackage, Date current) {
|
||||
DateTime endTime = null;
|
||||
// 计算有效时间
|
||||
switch (PeriodTypeEnum.getByCode(uPackage.getPeriodType())) {
|
||||
case HOUR:
|
||||
endTime = DateUtil.offset(current, DateField.HOUR, uPackage.getPeriodNum());
|
||||
break;
|
||||
case DAY:
|
||||
endTime = DateUtil.offset(current, DateField.DAY_OF_YEAR, uPackage.getPeriodNum());
|
||||
break;
|
||||
case MONTH:
|
||||
endTime = DateUtil.offset(current, DateField.MONTH, uPackage.getPeriodNum());
|
||||
break;
|
||||
case YEAR:
|
||||
endTime = DateUtil.offset(current, DateField.YEAR, uPackage.getPeriodNum());
|
||||
break;
|
||||
default:
|
||||
}
|
||||
return endTime;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Long saveOrder(UOrder order) {
|
||||
order.setUserId(SecurityUtils.getUserId());
|
||||
|
||||
@@ -1,8 +1,11 @@
|
||||
package org.wfc.user.util;
|
||||
|
||||
import cn.hutool.core.date.DateField;
|
||||
import cn.hutool.core.date.DateTime;
|
||||
import cn.hutool.core.date.DateUtil;
|
||||
import cn.hutool.core.util.ObjectUtil;
|
||||
import org.wfc.user.domain.UAccount;
|
||||
import org.wfc.user.domain.constant.PeriodTypeEnum;
|
||||
|
||||
import java.math.BigDecimal;
|
||||
import java.util.Date;
|
||||
@@ -69,4 +72,25 @@ public class AccountUtil {
|
||||
&& (!account.getDurationEnable() || account.getDurationUsed() <= account.getDuration()))
|
||||
&& (ObjectUtil.isNull(account.getBalanceUsed()) || account.getBalanceUsed().compareTo(BigDecimal.ZERO) == 0);
|
||||
}
|
||||
|
||||
public static DateTime getEndTime(Integer periodType, Integer periodNum, Date current) {
|
||||
DateTime endTime = null;
|
||||
// 计算有效时间
|
||||
switch (PeriodTypeEnum.getByCode(periodType)) {
|
||||
case HOUR:
|
||||
endTime = DateUtil.offset(current, DateField.HOUR, periodNum);
|
||||
break;
|
||||
case DAY:
|
||||
endTime = DateUtil.offset(current, DateField.DAY_OF_YEAR, periodNum);
|
||||
break;
|
||||
case MONTH:
|
||||
endTime = DateUtil.offset(current, DateField.MONTH, periodNum);
|
||||
break;
|
||||
case YEAR:
|
||||
endTime = DateUtil.offset(current, DateField.YEAR, periodNum);
|
||||
break;
|
||||
default:
|
||||
}
|
||||
return endTime;
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user