2
0

feat: add order buy

This commit is contained in:
caiyuchao
2024-12-23 20:02:39 +08:00
parent 23eed50dd6
commit a103740be6
18 changed files with 481 additions and 10 deletions

View File

@@ -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.UAccount;
import org.wfc.user.service.IUAccountService;
import java.util.List;
/**
* <p>
* 用户平台-账户表 前端控制器
* </p>
*
* @author sys
* @since 2024-12-23
*/
@RestController
@RequestMapping("/user/uAccount")
public class UAccountController extends BaseController {
@Autowired
private IUAccountService uAccountService;
@GetMapping("/page")
public TableDataInfo page(UAccount uAccount) {
startPage();
List<UAccount> list = uAccountService.list();
return getDataTable(list);
}
@GetMapping("/list")
public AjaxResult list(UAccount uAccount) {
List<UAccount> list = uAccountService.list();
return success(list);
}
@GetMapping(value = "/{id}")
public AjaxResult getById(@PathVariable("id") Long id) {
return success(uAccountService.getById(id));
}
@PostMapping
public AjaxResult add(@RequestBody UAccount uAccount) {
return toAjax(uAccountService.save(uAccount));
}
@PutMapping
public AjaxResult edit(@RequestBody UAccount uAccount) {
return toAjax(uAccountService.updateById(uAccount));
}
@DeleteMapping("/{ids}")
public AjaxResult remove(@PathVariable Long[] ids) {
return toAjax(uAccountService.removeByIds(CollUtil.newArrayList(ids)));
}
}

View File

@@ -55,7 +55,7 @@ public class UOrderController extends BaseController {
@PostMapping
public AjaxResult add(@RequestBody UOrder uOrder) {
uOrder.setUserId(SecurityUtils.getUserId());
return toAjax(uOrderService.save(uOrder));
return toAjax(uOrderService.saveOrder(uOrder));
}
@PutMapping

View File

@@ -0,0 +1,102 @@
package org.wfc.user.domain;
import com.baomidou.mybatisplus.annotation.TableName;
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;
import java.util.Date;
/**
* <p>
* 用户平台-账户表
* </p>
*
* @author sys
* @since 2024-12-23
*/
@Getter
@Setter
@TableName("u_account")
@Schema(name = "UAccount", description = "用户平台-账户表")
public class UAccount extends BaseData {
private static final long serialVersionUID = 1L;
@Schema(description = "用户ID")
private Long userId;
@Schema(description = "余额")
private BigDecimal balance;
@Schema(description = "套餐ID")
private Long packageId;
@Schema(description = "开始时间")
private Date startTime;
@Schema(description = "结束时间")
private Date endTime;
@Schema(description = "流量已使用")
private Long trafficUsed;
@Schema(description = "时长已使用")
private Long durationUsed;
@Schema(description = "在线设备数已使用")
private Integer clientNumUsed;
@Schema(description = "套餐名称")
private String packageName;
@Schema(description = "有效期数")
private Integer periodNum;
@Schema(description = "有效期类型")
private Integer periodType;
@Schema(description = "价格")
private BigDecimal price;
@Schema(description = "流量")
private Long traffic;
@Schema(description = "时长")
private Long duration;
@Schema(description = "在线设备数")
private Integer clientNum;
@Schema(description = "备注")
private String remark;
@Schema(description = "带宽是否限制")
private Boolean rateLimitEnable;
@Schema(description = "流量是否限制")
private Boolean trafficEnable;
@Schema(description = "时长是否限制")
private Boolean durationEnable;
@Schema(description = "在线设备数是否限制")
private Boolean clientNumEnable;
@Schema(description = "限速名称")
private String rateLimitName;
@Schema(description = "下行限速")
private Long downLimit;
@Schema(description = "下行限速启用")
private Boolean downLimitEnable;
@Schema(description = "上行限速")
private Long upLimit;
@Schema(description = "上行限速启用")
private Boolean upLimitEnable;
}

View File

@@ -31,6 +31,9 @@ public class UClient extends BaseData {
@Schema(description = "User ID link to u_user")
private Long userId;
@Schema(description = "Site ID")
private String siteId;
@Schema(description = "Client Name")
private String clientName;

View File

@@ -35,7 +35,7 @@ public class UPackage extends BaseData {
private Integer periodNum;
@Schema(description = "有效期类型")
private String periodType;
private Integer periodType;
@Schema(description = "价格")
private BigDecimal price;

View File

@@ -0,0 +1,22 @@
package org.wfc.user.domain.constant;
import lombok.AllArgsConstructor;
import lombok.Getter;
/**
* @description: 订单状态枚举
* @author: cyc
* @since: 2024-12-23
*/
@Getter
@AllArgsConstructor
public enum OrderStatusEnum {
UNPAID(0, "未支付"),
PAID(1, "已支付"),
CANCELLED(2, "已取消");
private final Integer code;
private final String desc;
}

View File

@@ -0,0 +1,20 @@
package org.wfc.user.domain.constant;
import lombok.AllArgsConstructor;
import lombok.Getter;
/**
* @description: 订单类型枚举
* @author: cyc
* @since: 2024-12-23
*/
@Getter
@AllArgsConstructor
public enum OrderTypeEnum {
PACKAGE(0, "套餐"),
RECHARGE(1, "充值");
private final Integer code;
private final String desc;
}

View File

@@ -0,0 +1,35 @@
package org.wfc.user.domain.constant;
import lombok.AllArgsConstructor;
import lombok.Getter;
/**
* @description: 有效期类型枚举
* @author: cyc
* @since: 2024-12-23
*/
@Getter
@AllArgsConstructor
public enum PeriodTypeEnum {
HOUR(0, "小时"),
DAY(1, ""),
MONTH(2, ""),
YEAR(3, "")
;
private final Integer code;
private final String desc;
public static PeriodTypeEnum getByCode(Integer code) {
if (code == null) {
return null;
}
for (PeriodTypeEnum periodTypeEnum : PeriodTypeEnum.values()) {
if (periodTypeEnum.getCode().equals(code)) {
return periodTypeEnum;
}
}
return null;
}
}

View File

@@ -0,0 +1,16 @@
package org.wfc.user.mapper;
import org.wfc.user.domain.UAccount;
import com.baomidou.mybatisplus.core.mapper.BaseMapper;
/**
* <p>
* 用户平台-账户表 Mapper 接口
* </p>
*
* @author sys
* @since 2024-12-23
*/
public interface UAccountMapper extends BaseMapper<UAccount> {
}

View File

@@ -0,0 +1,16 @@
package org.wfc.user.service;
import org.wfc.user.domain.UAccount;
import com.baomidou.mybatisplus.extension.service.IService;
/**
* <p>
* 用户平台-账户表 服务类
* </p>
*
* @author sys
* @since 2024-12-23
*/
public interface IUAccountService extends IService<UAccount> {
}

View File

@@ -13,4 +13,6 @@ import com.baomidou.mybatisplus.extension.service.IService;
*/
public interface IUOrderService extends IService<UOrder> {
boolean saveOrder(UOrder order);
}

View File

@@ -0,0 +1,20 @@
package org.wfc.user.service.impl;
import org.wfc.user.domain.UAccount;
import org.wfc.user.mapper.UAccountMapper;
import org.wfc.user.service.IUAccountService;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import org.springframework.stereotype.Service;
/**
* <p>
* 用户平台-账户表 服务实现类
* </p>
*
* @author sys
* @since 2024-12-23
*/
@Service
public class UAccountServiceImpl extends ServiceImpl<UAccountMapper, UAccount> implements IUAccountService {
}

View File

@@ -1,10 +1,33 @@
package org.wfc.user.service.impl;
import org.wfc.user.domain.UOrder;
import org.wfc.user.mapper.UOrderMapper;
import org.wfc.user.service.IUOrderService;
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 com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.wfc.omada.api.hotspot.OmadaAuthorizedClientApi;
import org.wfc.user.domain.UAccount;
import org.wfc.user.domain.UClient;
import org.wfc.user.domain.UOrder;
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.UOrderMapper;
import org.wfc.user.service.IUAccountService;
import org.wfc.user.service.IUClientService;
import org.wfc.user.service.IUOrderService;
import org.wfc.user.service.IUPackageService;
import org.wfc.user.service.IURateLimitService;
import java.math.BigDecimal;
import java.util.Date;
import java.util.Optional;
/**
* <p>
@@ -17,4 +40,101 @@ import org.springframework.stereotype.Service;
@Service
public class UOrderServiceImpl extends ServiceImpl<UOrderMapper, UOrder> implements IUOrderService {
@Autowired
private IUPackageService packageService;
@Autowired
private IURateLimitService rateLimitService;
@Autowired
private IUAccountService accountService;
@Autowired
private IUClientService clientService;
@Autowired
private OmadaAuthorizedClientApi omadaAuthorizedClientApi;
public void paySuccess(Long orderId) {
// 支付成功回调(预留)
// 更新当前订单状态为已支付
UOrder order = this.getById(orderId);
order.setStatus(OrderStatusEnum.PAID.getCode());
this.updateById(order);
// 授权当前设备访问wifi
UClient client = clientService.getOne(Wrappers.<UClient>lambdaQuery().eq(UClient::getUserId, order.getUserId()), false);
if (ObjectUtil.isNull(client)) {
omadaAuthorizedClientApi.authClient(client.getSiteId(), client.getClientMac());
}
// 保存或更新账户信息
UAccount account = accountService.getOne(Wrappers.<UAccount>lambdaQuery().eq(UAccount::getUserId, order.getUserId()), false);
if (ObjectUtil.isNull(account)) {
account = new UAccount();
}
Long accountId = account.getId();
if (OrderTypeEnum.PACKAGE.getCode().equals(order.getType())) {
// 套餐
callbackPackage(order, account);
} else if (OrderTypeEnum.RECHARGE.getCode().equals(order.getType())) {
// 充值
// 更新账户余额
account.setBalance(order.getOrderAmount().add(Optional.of(account.getBalance()).orElse(BigDecimal.ZERO)));
}
account.setId(accountId);
accountService.saveOrUpdate(account);
}
private void callbackPackage(UOrder order, UAccount account) {
if (ObjectUtil.isNull(order.getPackageId())) {
return;
}
UPackage uPackage = packageService.getById(order.getPackageId());
Boolean rateLimitEnable = uPackage.getRateLimitEnable();
rateLimitEnable = ObjectUtil.isNotNull(uPackage.getRateLimitId()) ? rateLimitEnable : false;
if (rateLimitEnable) {
URateLimit rateLimit = rateLimitService.getById(uPackage.getRateLimitId());
BeanUtils.copyProperties(rateLimit, account);
}
BeanUtils.copyProperties(uPackage, account);
account.setTrafficUsed(0L);
account.setDurationUsed(0L);
account.setClientNumUsed(0);
Date current = new Date();
DateTime endTime = getEndTime(uPackage, 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 boolean saveOrder(UOrder order) {
this.save(order);
// 支付成功回调
paySuccess(order.getId());
return true;
}
}

View File

@@ -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.UAccountMapper">
</mapper>

View File

@@ -35,7 +35,7 @@ public class UPackage extends BaseData {
private Integer periodNum;
@Schema(description = "有效期类型")
private String periodType;
private Integer periodType;
@Schema(description = "价格")
private BigDecimal price;