feat: 账单和发票补充
This commit is contained in:
@@ -108,6 +108,13 @@
|
||||
<groupId>org.springframework.boot</groupId>
|
||||
<artifactId>spring-boot-starter-thymeleaf</artifactId>
|
||||
</dependency>
|
||||
|
||||
<dependency>
|
||||
<groupId>com.itextpdf</groupId>
|
||||
<artifactId>html2pdf</artifactId>
|
||||
<version>6.2.0</version>
|
||||
</dependency>
|
||||
|
||||
</dependencies>
|
||||
|
||||
<build>
|
||||
|
||||
@@ -1,26 +1,34 @@
|
||||
package org.wfc.user.controller;
|
||||
|
||||
|
||||
import cn.hutool.core.io.FileUtil;
|
||||
import cn.hutool.core.util.RandomUtil;
|
||||
import cn.hutool.core.util.StrUtil;
|
||||
import com.itextpdf.html2pdf.HtmlConverter;
|
||||
import lombok.RequiredArgsConstructor;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import org.springframework.validation.annotation.Validated;
|
||||
import org.springframework.web.bind.annotation.GetMapping;
|
||||
import org.springframework.web.bind.annotation.RequestMapping;
|
||||
import org.springframework.web.bind.annotation.RestController;
|
||||
import org.springframework.web.multipart.MultipartFile;
|
||||
import org.thymeleaf.TemplateEngine;
|
||||
import org.thymeleaf.context.Context;
|
||||
import org.wfc.common.core.constant.Constants;
|
||||
import org.wfc.common.core.constant.GlobalConstants;
|
||||
import org.wfc.common.core.domain.R;
|
||||
import org.wfc.common.core.utils.MessageUtils;
|
||||
import org.wfc.common.core.utils.file.MultipartFileUtil;
|
||||
import org.wfc.common.core.web.controller.BaseController;
|
||||
import org.wfc.common.mail.config.properties.MailProperties;
|
||||
import org.wfc.common.mail.utils.MailUtils;
|
||||
import org.wfc.common.redis.service.RedisService;
|
||||
import org.wfc.system.api.RemoteFileService;
|
||||
import org.wfc.system.api.domain.SysFile;
|
||||
|
||||
import javax.validation.constraints.NotBlank;
|
||||
import java.io.File;
|
||||
import java.nio.file.Files;
|
||||
import java.nio.file.Paths;
|
||||
import java.util.concurrent.TimeUnit;
|
||||
|
||||
/**
|
||||
@@ -38,6 +46,7 @@ public class UEmailController extends BaseController {
|
||||
private final MailProperties mailProperties;
|
||||
private final RedisService redisService;
|
||||
private final TemplateEngine templateEngine;
|
||||
private final RemoteFileService remoteFileService;
|
||||
|
||||
/**
|
||||
* 邮箱验证码
|
||||
@@ -56,12 +65,46 @@ public class UEmailController extends BaseController {
|
||||
Context context = new Context();
|
||||
context.setVariable("verificationCode", code);
|
||||
context.setVariable("expirationTime", Constants.MAIL_CAPTCHA_EXPIRATION);
|
||||
String htmlStr = templateEngine.process("mail", context);
|
||||
context.setVariable("username", "chason");
|
||||
context.setVariable("email", "707821112@qq.com");
|
||||
context.setVariable("invoiceNumber", "INV-2025-05-001");
|
||||
context.setVariable("invoiceDate", "2025-05-28");
|
||||
context.setVariable("hasDetails", "false");
|
||||
context.setVariable("itemName", "Network Traffic Fee");
|
||||
context.setVariable("qty", "1");
|
||||
context.setVariable("unitPrice", "$50");
|
||||
context.setVariable("total", "$50");
|
||||
context.setVariable("currency", "USD");
|
||||
context.setVariable("traffic", "200GB");
|
||||
context.setVariable("speedCap", "Upload 30 Mbps / Download 100 Mbps");
|
||||
context.setVariable("clientsNumber", "5");
|
||||
context.setVariable("billingCycle", "Monthly");
|
||||
|
||||
String htmlStr = templateEngine.process("invoice", context);
|
||||
|
||||
// String basePath = System.getProperty("user.dir") + File.separator + "invoice.pdf";
|
||||
String basePath = "D:\\documents\\projects\\wanfi\\invoice";
|
||||
FileUtil.mkdir(basePath);
|
||||
basePath = basePath + File.separator + "invoice.pdf";
|
||||
|
||||
File uploadFile = new File(basePath);
|
||||
// HtmlConverter.convertToPdf(htmlStr, outputStream);
|
||||
HtmlConverter.convertToPdf(htmlStr, Files.newOutputStream(Paths.get(basePath)));
|
||||
// HtmlConverter.convertToPdf(htmlStr, Files.newOutputStream(Paths.get("D:\\projects\\pro\\be.wfc\\invoice.pdf")));
|
||||
|
||||
MultipartFile multipartFile = MultipartFileUtil.getMultipartFile(uploadFile);
|
||||
R<SysFile> fileResult = remoteFileService.upload(multipartFile);
|
||||
String url = fileResult.getData().getUrl();
|
||||
log.info("qr code file: {}", url);
|
||||
|
||||
|
||||
String subject = mailProperties.getSubject();
|
||||
if (StrUtil.isBlank(subject)) {
|
||||
subject = "Your WANFI Verification Code";
|
||||
}
|
||||
MailUtils.sendHtml(email, subject, htmlStr);
|
||||
// MailUtils.sendHtml(email, subject, htmlStr, uploadFile);
|
||||
|
||||
// FileUtil.del(uploadFile);
|
||||
} catch (Exception e) {
|
||||
log.error("email verification code send failed => {}", e.getMessage());
|
||||
return R.fail(e.getMessage());
|
||||
|
||||
@@ -1,12 +1,12 @@
|
||||
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;
|
||||
import org.wfc.common.mybatis.domain.BaseData;
|
||||
|
||||
import java.math.BigDecimal;
|
||||
|
||||
/**
|
||||
* <p>
|
||||
@@ -38,4 +38,10 @@ public class UBill extends BaseData {
|
||||
|
||||
@Schema(description = "状态")
|
||||
private Integer status;
|
||||
|
||||
@Schema(description = "发票编号")
|
||||
private String invoiceNumber;
|
||||
|
||||
@Schema(description = "发票文件")
|
||||
private String invoiceFile;
|
||||
}
|
||||
|
||||
@@ -0,0 +1,40 @@
|
||||
package org.wfc.user.domain.bo;
|
||||
|
||||
import lombok.Data;
|
||||
|
||||
/**
|
||||
* @description: 发票模板bo
|
||||
* @author: cyc
|
||||
* @since: 2025-06-06
|
||||
*/
|
||||
@Data
|
||||
public class UInvoiceTemplateBo {
|
||||
|
||||
private String username;
|
||||
|
||||
private String email;
|
||||
|
||||
private String invoiceNumber;
|
||||
|
||||
private String invoiceDate;
|
||||
|
||||
private String itemName;
|
||||
|
||||
private String qty;
|
||||
|
||||
private String unitPrice;
|
||||
|
||||
private String total;
|
||||
|
||||
private String currency;
|
||||
|
||||
private boolean hasDetails;
|
||||
|
||||
private String traffic;
|
||||
|
||||
private String speedCap;
|
||||
|
||||
private String clientsNumber;
|
||||
|
||||
private String billingCycle;
|
||||
}
|
||||
@@ -12,8 +12,8 @@ import lombok.Getter;
|
||||
@AllArgsConstructor
|
||||
public enum OrderTypeEnum {
|
||||
|
||||
PACKAGE(0, "套餐"),
|
||||
RECHARGE(1, "充值");
|
||||
PACKAGE(0, "Package"),
|
||||
RECHARGE(1, "Recharge");
|
||||
|
||||
private final Integer code;
|
||||
private final String desc;
|
||||
|
||||
@@ -12,10 +12,10 @@ import lombok.Getter;
|
||||
@AllArgsConstructor
|
||||
public enum PeriodTypeEnum {
|
||||
|
||||
HOUR(0, "小时"),
|
||||
DAY(1, "天"),
|
||||
MONTH(2, "月"),
|
||||
YEAR(3, "年")
|
||||
HOUR(0, "Hour"),
|
||||
DAY(1, "Day"),
|
||||
MONTH(2, "Month"),
|
||||
YEAR(3, "Year")
|
||||
;
|
||||
|
||||
private final Integer code;
|
||||
|
||||
@@ -2,7 +2,10 @@ package org.wfc.user.service;
|
||||
|
||||
import com.baomidou.mybatisplus.extension.service.IService;
|
||||
import org.wfc.user.domain.UBill;
|
||||
import org.wfc.user.domain.UOrder;
|
||||
import org.wfc.user.domain.vo.UBillUserVo;
|
||||
import org.wfc.user.domain.vo.UInvoiceBillVo;
|
||||
import org.wfc.user.domain.vo.UInvoiceGenVo;
|
||||
|
||||
import java.util.List;
|
||||
|
||||
@@ -20,4 +23,5 @@ public interface IUBillService extends IService<UBill> {
|
||||
|
||||
List<UInvoiceBillVo> getInvoiceByUser();
|
||||
|
||||
UInvoiceGenVo genInvoice(UOrder order);
|
||||
}
|
||||
|
||||
@@ -1,15 +1,62 @@
|
||||
package org.wfc.user.service.impl;
|
||||
|
||||
import cn.hutool.core.collection.CollUtil;
|
||||
import cn.hutool.core.io.FileUtil;
|
||||
import cn.hutool.core.util.ObjectUtil;
|
||||
import cn.hutool.core.util.StrUtil;
|
||||
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
|
||||
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
|
||||
import com.itextpdf.html2pdf.ConverterProperties;
|
||||
import com.itextpdf.html2pdf.HtmlConverter;
|
||||
import com.itextpdf.layout.font.FontProvider;
|
||||
import lombok.RequiredArgsConstructor;
|
||||
import lombok.extern.slf4j.Slf4j;
|
||||
import org.apache.commons.lang3.math.NumberUtils;
|
||||
import org.springframework.stereotype.Service;
|
||||
import org.springframework.web.multipart.MultipartFile;
|
||||
import org.thymeleaf.TemplateEngine;
|
||||
import org.thymeleaf.context.Context;
|
||||
import org.wfc.common.core.constant.CacheConstants;
|
||||
import org.wfc.common.core.domain.LoginUser;
|
||||
import org.wfc.common.core.domain.R;
|
||||
import org.wfc.common.core.exception.ServiceException;
|
||||
import org.wfc.common.core.utils.file.MultipartFileUtil;
|
||||
import org.wfc.common.mail.config.properties.MailProperties;
|
||||
import org.wfc.common.mail.utils.MailUtils;
|
||||
import org.wfc.common.mybatis.domain.BaseData;
|
||||
import org.wfc.common.redis.service.RedisService;
|
||||
import org.wfc.common.security.utils.SecurityUtils;
|
||||
import org.wfc.system.api.RemoteFileService;
|
||||
import org.wfc.system.api.domain.SysFile;
|
||||
import org.wfc.user.api.domain.UUser;
|
||||
import org.wfc.user.domain.InvoiceBean;
|
||||
import org.wfc.user.domain.UBill;
|
||||
import org.wfc.user.domain.UOrder;
|
||||
import org.wfc.user.domain.UPackage;
|
||||
import org.wfc.user.domain.URateLimit;
|
||||
import org.wfc.user.domain.bo.UInvoiceTemplateBo;
|
||||
import org.wfc.user.domain.constant.OrderTypeEnum;
|
||||
import org.wfc.user.domain.constant.PeriodTypeEnum;
|
||||
import org.wfc.user.domain.vo.UBillUserVo;
|
||||
import org.wfc.user.domain.vo.UInvoiceBillVo;
|
||||
import org.wfc.user.domain.vo.UInvoiceGenVo;
|
||||
import org.wfc.user.mapper.UBillMapper;
|
||||
import org.wfc.user.mapper.UPackageMapper;
|
||||
import org.wfc.user.mapper.URateLimitMapper;
|
||||
import org.wfc.user.mapper.UUserMapper;
|
||||
import org.wfc.user.service.IUBillService;
|
||||
import org.wfc.user.util.TrafficConverter;
|
||||
|
||||
import java.io.File;
|
||||
import java.io.IOException;
|
||||
import java.math.RoundingMode;
|
||||
import java.nio.file.Files;
|
||||
import java.nio.file.Paths;
|
||||
import java.time.LocalDateTime;
|
||||
import java.time.format.DateTimeFormatter;
|
||||
import java.util.Collections;
|
||||
import java.util.List;
|
||||
import java.util.Map;
|
||||
|
||||
/**
|
||||
* <p>
|
||||
@@ -19,12 +66,186 @@ import java.util.List;
|
||||
* @author sys
|
||||
* @since 2025-01-06
|
||||
*/
|
||||
@Slf4j
|
||||
@Service
|
||||
@RequiredArgsConstructor
|
||||
public class UBillServiceImpl extends ServiceImpl<UBillMapper, UBill> implements IUBillService {
|
||||
|
||||
private final MailProperties mailProperties;
|
||||
private final TemplateEngine templateEngine;
|
||||
private final RemoteFileService remoteFileService;
|
||||
private final UUserMapper userMapper;
|
||||
private final RedisService redisService;
|
||||
private final UPackageMapper packageMapper;
|
||||
private final URateLimitMapper urateLimitMapper;
|
||||
private final InvoiceBean invoiceBean;
|
||||
|
||||
public static final String PRE_INVOICE_NUMBER = "INV-";
|
||||
public static final String LAST_INVOICE_NUMBER = "-001";
|
||||
private static final String DEFAULT_SYS_PAY_CURRENCY_VALUE = "USD";
|
||||
private static final String DEFAULT_SYS_PAY_CURRENCY_SYMBOL_VALUE = "$";
|
||||
|
||||
|
||||
@Override
|
||||
public List<UBillUserVo> getBillByUser() {
|
||||
LoginUser<Object> loginUser = SecurityUtils.getLoginUser();
|
||||
return this.baseMapper.getBillByUser(loginUser.getUserid());
|
||||
}
|
||||
|
||||
@Override
|
||||
public List<UInvoiceBillVo> getInvoiceByUser() {
|
||||
LoginUser<Object> loginUser = SecurityUtils.getLoginUser();
|
||||
return this.baseMapper.getInvoiceByUser(loginUser.getUserid());
|
||||
}
|
||||
|
||||
@Override
|
||||
public UInvoiceGenVo genInvoice(UOrder order) {
|
||||
String url;
|
||||
UInvoiceTemplateBo invoiceBo = new UInvoiceTemplateBo();
|
||||
if (order.getUserId() != null) {
|
||||
UUser user = userMapper.selectUserById(order.getUserId());
|
||||
invoiceBo.setUsername(user.getUserName());
|
||||
invoiceBo.setEmail(user.getEmail());
|
||||
}
|
||||
UBill bill = this.baseMapper.selectOne(Wrappers.<UBill>lambdaQuery()
|
||||
.isNotNull(UBill::getInvoiceNumber)
|
||||
.orderByDesc(BaseData::getCreateTime).last("limit 1"), false);
|
||||
|
||||
LocalDateTime dateTime = LocalDateTime.now();
|
||||
DateTimeFormatter formatter = DateTimeFormatter.ofPattern("yyyy-MM-dd");
|
||||
String dateStr = dateTime.format(formatter);
|
||||
String oldInvoiceNumber = StrUtil.EMPTY;
|
||||
if (bill != null) {
|
||||
oldInvoiceNumber = bill.getInvoiceNumber();
|
||||
}
|
||||
invoiceBo.setInvoiceNumber(genInvoiceNumber(dateStr, oldInvoiceNumber));
|
||||
invoiceBo.setInvoiceDate(dateStr);
|
||||
|
||||
Map<String, Object> cacheMap = redisService.getCacheMap(CacheConstants.SYS_PAY_CONFIG_KEY);
|
||||
String currencySymbol = DEFAULT_SYS_PAY_CURRENCY_SYMBOL_VALUE;
|
||||
String currency = DEFAULT_SYS_PAY_CURRENCY_VALUE;
|
||||
if (CollUtil.isNotEmpty(cacheMap)) {
|
||||
Object currencyObj = cacheMap.get(CacheConstants.SYS_PAY_CURRENCY_KEY);
|
||||
if (currencyObj != null) {
|
||||
currency = currencyObj.toString();
|
||||
}
|
||||
invoiceBo.setCurrency(currency);
|
||||
Object currencySymbolObj = cacheMap.get(CacheConstants.SYS_PAY_CURRENCY_SYMBOL_KEY);
|
||||
if (currencySymbolObj != null) {
|
||||
currencySymbol = currencySymbolObj.toString();
|
||||
}
|
||||
}
|
||||
|
||||
if (OrderTypeEnum.PACKAGE.getCode().equals(order.getType())) {
|
||||
// 套餐
|
||||
invoiceBo.setHasDetails(true);
|
||||
|
||||
UPackage uPackage = packageMapper.selectById(order.getPackageId());
|
||||
invoiceBo.setItemName(uPackage.getPackageName());
|
||||
invoiceBo.setTraffic(uPackage.getTrafficEnable() ? TrafficConverter.formatBytes(uPackage.getTraffic()) : "unlimited");
|
||||
invoiceBo.setClientsNumber(uPackage.getClientNumEnable() ? uPackage.getClientNum() + "" : "unlimited");
|
||||
PeriodTypeEnum periodTypeEnum = PeriodTypeEnum.getByCode(uPackage.getPeriodType());
|
||||
invoiceBo.setBillingCycle(uPackage.getPeriodNum() + " " + (periodTypeEnum == null ? "" : periodTypeEnum.getDesc()));
|
||||
|
||||
|
||||
Boolean rateLimitEnable = uPackage.getRateLimitEnable();
|
||||
rateLimitEnable = ObjectUtil.isNotNull(uPackage.getRateLimitId()) ? rateLimitEnable : false;
|
||||
String speedCap = "";
|
||||
if (rateLimitEnable) {
|
||||
URateLimit rateLimit = urateLimitMapper.selectById(uPackage.getRateLimitId());
|
||||
if (rateLimit != null) {
|
||||
String up = rateLimit.getUpLimitEnable() ? TrafficConverter.formatKbps(rateLimit.getUpLimit()) : "unlimited";
|
||||
String down = rateLimit.getDownLimitEnable() ? TrafficConverter.formatKbps(rateLimit.getDownLimit()) : "unlimited";
|
||||
speedCap = "Upload " + up + " / Download " + down;
|
||||
}
|
||||
} else {
|
||||
speedCap = "unlimited";
|
||||
}
|
||||
invoiceBo.setSpeedCap(speedCap);
|
||||
|
||||
} else if (OrderTypeEnum.RECHARGE.getCode().equals(order.getType())) {
|
||||
// 充值
|
||||
invoiceBo.setHasDetails(false);
|
||||
invoiceBo.setItemName(OrderTypeEnum.RECHARGE.getDesc());
|
||||
}
|
||||
invoiceBo.setUnitPrice(currencySymbol + order.getOrderAmount().setScale(2, RoundingMode.HALF_UP));
|
||||
invoiceBo.setTotal(currencySymbol + order.getOrderAmount().setScale(2, RoundingMode.HALF_UP));
|
||||
// 填充发票模版
|
||||
Context context = getContext(invoiceBo);
|
||||
String htmlStr = templateEngine.process("invoice", context);
|
||||
|
||||
String prefix = invoiceBean.getPath();
|
||||
String basePath = prefix + File.separator + "invoice";
|
||||
String fontsDir = prefix + File.separator + "fonts";
|
||||
FileUtil.mkdir(basePath);
|
||||
basePath = basePath + File.separator + "invoice.pdf";
|
||||
|
||||
File uploadFile = new File(basePath);
|
||||
|
||||
FontProvider fontProvider = new FontProvider();
|
||||
fontProvider.addDirectory(fontsDir);
|
||||
|
||||
try {
|
||||
HtmlConverter.convertToPdf(htmlStr, Files.newOutputStream(Paths.get(basePath)), new ConverterProperties().setFontProvider(fontProvider));
|
||||
} catch (IOException e) {
|
||||
log.error("convert pdf failed: {}", e.getMessage());
|
||||
throw new ServiceException("convert pdf failed");
|
||||
}
|
||||
|
||||
MultipartFile multipartFile = MultipartFileUtil.getMultipartFile(uploadFile);
|
||||
R<SysFile> fileResult = remoteFileService.upload(multipartFile);
|
||||
url = fileResult.getData().getUrl();
|
||||
log.info("invoice file addr: {}", url);
|
||||
|
||||
try {
|
||||
String subject = mailProperties.getSubject();
|
||||
if (StrUtil.isBlank(subject)) {
|
||||
subject = "Your WANFI Verification Code";
|
||||
}
|
||||
MailUtils.sendHtml(invoiceBo.getEmail(), subject, htmlStr, uploadFile);
|
||||
|
||||
FileUtil.del(uploadFile);
|
||||
} catch (Exception e) {
|
||||
log.error("email invoice send failed => {}", e.getMessage());
|
||||
}
|
||||
UInvoiceGenVo invoiceGenVo = new UInvoiceGenVo();
|
||||
invoiceGenVo.setInvoiceNumber(invoiceBo.getInvoiceNumber());
|
||||
invoiceGenVo.setInvoiceFile(url);
|
||||
return invoiceGenVo;
|
||||
}
|
||||
|
||||
private static Context getContext(UInvoiceTemplateBo invoiceBo) {
|
||||
Context context = new Context();
|
||||
context.setVariable("username", invoiceBo.getUsername());
|
||||
context.setVariable("email", invoiceBo.getEmail());
|
||||
context.setVariable("invoiceNumber", invoiceBo.getInvoiceNumber());
|
||||
context.setVariable("invoiceDate", invoiceBo.getInvoiceDate());
|
||||
context.setVariable("hasDetails", invoiceBo.isHasDetails() + "");
|
||||
context.setVariable("itemName", invoiceBo.getItemName());
|
||||
context.setVariable("qty", "1");
|
||||
context.setVariable("unitPrice", invoiceBo.getUnitPrice());
|
||||
context.setVariable("total", invoiceBo.getTotal());
|
||||
context.setVariable("currency", invoiceBo.getCurrency());
|
||||
context.setVariable("traffic", invoiceBo.getTraffic());
|
||||
context.setVariable("speedCap", invoiceBo.getSpeedCap());
|
||||
context.setVariable("clientsNumber", invoiceBo.getClientsNumber());
|
||||
context.setVariable("billingCycle", invoiceBo.getBillingCycle());
|
||||
return context;
|
||||
}
|
||||
|
||||
private String genInvoiceNumber(String dateStr, String oldInvoiceNumber) {
|
||||
String dateSubStr = dateStr.substring(0, 7);
|
||||
String invoiceNumber = PRE_INVOICE_NUMBER + dateSubStr + LAST_INVOICE_NUMBER;
|
||||
if (oldInvoiceNumber.contains(dateSubStr)) {
|
||||
List<String> invStr = StrUtil.split(oldInvoiceNumber, "-");
|
||||
if (CollUtil.isNotEmpty(invStr)) {
|
||||
String no = invStr.get(invStr.size() - 1);
|
||||
int integer = NumberUtils.toInt(no);
|
||||
String noStr = String.format("%0" + 3 + "d", integer + 1);
|
||||
invoiceNumber = PRE_INVOICE_NUMBER + dateSubStr + "-" + noStr;
|
||||
}
|
||||
}
|
||||
return invoiceNumber;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -33,6 +33,7 @@ import org.wfc.user.mapper.UBillMapper;
|
||||
import org.wfc.user.mapper.UBillRuleMapper;
|
||||
import org.wfc.user.mapper.UOrderMapper;
|
||||
import org.wfc.user.service.IUAccountService;
|
||||
import org.wfc.user.service.IUBillService;
|
||||
import org.wfc.user.service.IUClientService;
|
||||
import org.wfc.user.service.IUOrderService;
|
||||
import org.wfc.user.service.IUPackageService;
|
||||
@@ -76,6 +77,9 @@ public class UOrderServiceImpl extends ServiceImpl<UOrderMapper, UOrder> impleme
|
||||
@Autowired
|
||||
private UAccountPackageMapper accountPackageMapper;
|
||||
|
||||
@Autowired
|
||||
private IUBillService billService;
|
||||
|
||||
@Autowired
|
||||
private IWifiApi wifiApi;
|
||||
|
||||
@@ -108,6 +112,7 @@ public class UOrderServiceImpl extends ServiceImpl<UOrderMapper, UOrder> impleme
|
||||
|
||||
billMapper.insert(bill);
|
||||
|
||||
|
||||
// 保存或更新账户信息
|
||||
UAccount account = accountService.getOne(Wrappers.<UAccount>lambdaQuery().eq(UAccount::getUserId, order.getUserId()), false);
|
||||
Long accountId = null;
|
||||
|
||||
@@ -35,8 +35,8 @@ public class AccountUtil {
|
||||
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());
|
||||
&& (!account.getTrafficEnable() || account.getTrafficUsed() < account.getTraffic())
|
||||
&& (!account.getDurationEnable() || account.getDurationUsed() < account.getDuration());
|
||||
}
|
||||
|
||||
public static boolean isBalanceValid(UAccount account) {
|
||||
|
||||
@@ -0,0 +1,106 @@
|
||||
package org.wfc.user.util;
|
||||
|
||||
import cn.hutool.core.convert.Convert;
|
||||
|
||||
public class TrafficConverter {
|
||||
|
||||
// 定义字节单位
|
||||
private static final String[] BYTE_UNITS = {"B", "KB", "MB", "GB", "TB"};
|
||||
|
||||
private static final String[] BPS_UNITS = {"Kbps", "Mbps", "Gbps"};
|
||||
|
||||
/**
|
||||
* 将字节数转换为带单位的字符串
|
||||
*
|
||||
* @param bytes 字节数
|
||||
* @return 带单位的字符串
|
||||
*/
|
||||
public static String formatBytes(long bytes) {
|
||||
if (bytes <= 0) {
|
||||
return "0B";
|
||||
}
|
||||
int unitIndex = 0;
|
||||
double value = bytes;
|
||||
while (value >= 1024 && unitIndex < BYTE_UNITS.length - 1) {
|
||||
value /= 1024;
|
||||
unitIndex++;
|
||||
}
|
||||
return String.format("%.0f%s", value, BYTE_UNITS[unitIndex]);
|
||||
}
|
||||
|
||||
/**
|
||||
* 将kbps数转换为带单位的字符串
|
||||
*
|
||||
* @param Kbps Kbps
|
||||
* @return 带单位的字符串
|
||||
*/
|
||||
public static String formatKbps(long Kbps) {
|
||||
if (Kbps <= 0) {
|
||||
return "0Kbps";
|
||||
}
|
||||
int unitIndex = 0;
|
||||
double value = Kbps;
|
||||
while (value >= 1024 && unitIndex < BPS_UNITS.length - 1) {
|
||||
value /= 1024;
|
||||
unitIndex++;
|
||||
}
|
||||
return String.format("%.0f%s", value, BPS_UNITS[unitIndex]);
|
||||
}
|
||||
|
||||
/**
|
||||
* 将带单位的字符串转换为字节数
|
||||
*
|
||||
* @param byteStr 带单位的字符串
|
||||
* @return 字节数
|
||||
*/
|
||||
public static long parseBytes(String byteStr) {
|
||||
if (byteStr == null || byteStr.isEmpty()) {
|
||||
throw new IllegalArgumentException("Byte string cannot be null or empty");
|
||||
}
|
||||
|
||||
// 提取数字和单位
|
||||
String[] parts = byteStr.trim().split("\\s*");
|
||||
if (parts.length != 2) {
|
||||
throw new IllegalArgumentException("Invalid byte string format: " + byteStr);
|
||||
}
|
||||
|
||||
long value = Convert.toLong(parts[0]);
|
||||
String unit = parts[1].toUpperCase();
|
||||
|
||||
// 找到单位对应的指数
|
||||
int unitIndex = -1;
|
||||
for (int i = 0; i < BYTE_UNITS.length; i++) {
|
||||
if (BYTE_UNITS[i].equals(unit)) {
|
||||
unitIndex = i;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (unitIndex == -1) {
|
||||
throw new IllegalArgumentException("Unknown byte unit: " + unit);
|
||||
}
|
||||
|
||||
// 计算字节数
|
||||
long result = value;
|
||||
for (int i = 0; i < unitIndex; i++) {
|
||||
result *= 1024;
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
public static void main(String[] args) {
|
||||
// 测试字节单位转换
|
||||
long bytes = 123456789L;
|
||||
// long bytes = 1073741824L;
|
||||
String formatted = formatBytes(bytes);
|
||||
System.out.println(formatted); // 输出: 117.74MB
|
||||
|
||||
long kbps = 204800L;
|
||||
formatted = formatKbps(kbps);
|
||||
System.out.println(formatted);
|
||||
|
||||
// long parsed = parseBytes("117.74MB");
|
||||
// System.out.println(parsed); // 输出: 123456789
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user