2026-03-18 10:19:42 +08:00
|
|
|
/*
|
|
|
|
|
* @desc:模块租户关系处理
|
|
|
|
|
* @company:云南奇讯科技有限公司
|
|
|
|
|
* @Author: system
|
|
|
|
|
* @Date: 2026/1/6
|
|
|
|
|
*/
|
|
|
|
|
|
|
|
|
|
package moduleTenant
|
|
|
|
|
|
|
|
|
|
import (
|
|
|
|
|
"context"
|
|
|
|
|
"fmt"
|
2026-03-19 17:51:36 +08:00
|
|
|
"time"
|
|
|
|
|
|
2026-06-10 15:37:11 +08:00
|
|
|
"gitea.redpowerfuture.com/red-future/common/beans"
|
|
|
|
|
"gitea.redpowerfuture.com/red-future/common/http"
|
|
|
|
|
"gitea.redpowerfuture.com/red-future/common/utils"
|
2026-03-18 10:19:42 +08:00
|
|
|
"github.com/gogf/gf/v2/database/gdb"
|
|
|
|
|
"github.com/gogf/gf/v2/frame/g"
|
|
|
|
|
"github.com/gogf/gf/v2/os/gtime"
|
|
|
|
|
"github.com/gogf/gf/v2/util/gconv"
|
|
|
|
|
"github.com/tiger1103/gfast/v3/api/v1/system"
|
|
|
|
|
"github.com/tiger1103/gfast/v3/internal/app/system/consts"
|
|
|
|
|
"github.com/tiger1103/gfast/v3/internal/app/system/dao"
|
|
|
|
|
"github.com/tiger1103/gfast/v3/internal/app/system/model/do"
|
|
|
|
|
"github.com/tiger1103/gfast/v3/internal/app/system/model/entity"
|
|
|
|
|
"github.com/tiger1103/gfast/v3/internal/app/system/service"
|
|
|
|
|
"github.com/tiger1103/gfast/v3/library/liberr"
|
|
|
|
|
)
|
|
|
|
|
|
|
|
|
|
func init() {
|
|
|
|
|
service.RegisterModuleTenant(New())
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
type sModuleTenant struct {
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
func New() *sModuleTenant {
|
|
|
|
|
return &sModuleTenant{}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// Add 添加模块租户关系
|
|
|
|
|
func (s *sModuleTenant) Add(ctx context.Context, req *system.ModuleTenantAddReq) (err error) {
|
|
|
|
|
err = g.DB().Transaction(ctx, func(ctx context.Context, tx gdb.TX) error {
|
|
|
|
|
err = g.Try(ctx, func(ctx context.Context) {
|
|
|
|
|
// 获取用户信息
|
|
|
|
|
var getUserInfo *beans.User
|
|
|
|
|
getUserInfo, err = utils.GetUserInfo(ctx)
|
|
|
|
|
liberr.ErrIsNil(ctx, err, "获取用户信息失败")
|
|
|
|
|
// 获取sku信息
|
|
|
|
|
assetSukRes := new(system.AssetSku)
|
|
|
|
|
// 获取当前请求的 headers 并传递到下游
|
|
|
|
|
headers := make(map[string]string)
|
|
|
|
|
if r := g.RequestFromCtx(ctx); r != nil {
|
|
|
|
|
for k, v := range r.Request.Header {
|
|
|
|
|
if len(v) > 0 {
|
|
|
|
|
headers[k] = v[0]
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
if err = http.Get(ctx, "asset/sku/getAssetSkuModule", headers, &assetSukRes,
|
|
|
|
|
"id", req.AssetSkuId,
|
|
|
|
|
); err != nil {
|
|
|
|
|
return
|
|
|
|
|
}
|
|
|
|
|
liberr.ErrIsNil(ctx, err, "获取资产sku信息失败")
|
|
|
|
|
if assetSukRes.ExpireAt != nil {
|
|
|
|
|
liberr.ErrIsNil(ctx, err, "sku到期时间不能为空")
|
|
|
|
|
}
|
|
|
|
|
// 获取模块key
|
|
|
|
|
var moduleKey string
|
|
|
|
|
// 遍历 map 的所有键值对
|
|
|
|
|
for key, value := range beans.ModuleAssetId {
|
2026-03-19 17:51:36 +08:00
|
|
|
if value == assetSukRes.AssetId {
|
2026-03-18 10:19:42 +08:00
|
|
|
moduleKey = key
|
|
|
|
|
break
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
// 检查是否已存在相同的模块租户关系
|
|
|
|
|
var moduleTenant *entity.ModuleTenant
|
|
|
|
|
moduleTenant, err = s.GetByModuleKeyAndTenantId(ctx, moduleKey, gconv.Uint64(getUserInfo.TenantId))
|
|
|
|
|
liberr.ErrIsNil(ctx, err, "检查模块租户关系失败")
|
|
|
|
|
if moduleTenant != nil {
|
|
|
|
|
now := gtime.Now()
|
|
|
|
|
if moduleTenant.ExpireAt != nil && !moduleTenant.ExpireAt.Before(now) {
|
|
|
|
|
// 使用原到期时间 + SKU到期时间
|
|
|
|
|
duration := assetSukRes.ExpireAt.Sub(gtime.Now())
|
|
|
|
|
assetSukRes.ExpireAt = moduleTenant.ExpireAt.Add(duration)
|
|
|
|
|
}
|
|
|
|
|
// 更新模块租户关系
|
|
|
|
|
_, err = dao.ModuleTenant.Ctx(ctx).TX(tx).WherePri(moduleTenant.Id).Update(do.ModuleTenant{
|
|
|
|
|
UpdateBy: getUserInfo.UserName,
|
|
|
|
|
ExpireAt: assetSukRes.ExpireAt,
|
|
|
|
|
})
|
|
|
|
|
return
|
|
|
|
|
}
|
|
|
|
|
// 设置认证状态
|
|
|
|
|
certificationStatus := consts.CertificationStatusPass
|
|
|
|
|
if req.TenantModuleType == beans.TenantModuleTypeSupplier {
|
|
|
|
|
certificationStatus = consts.CertificationStatusUnverified
|
|
|
|
|
}
|
|
|
|
|
// 添加模块租户关系
|
|
|
|
|
_, err = dao.ModuleTenant.Ctx(ctx).TX(tx).InsertAndGetId(do.ModuleTenant{
|
|
|
|
|
CreateBy: getUserInfo.UserName,
|
|
|
|
|
UpdateBy: getUserInfo.UserName,
|
|
|
|
|
ModuleKey: moduleKey,
|
2026-03-19 17:51:36 +08:00
|
|
|
AssetId: assetSukRes.AssetId,
|
|
|
|
|
AssetSkuId: req.AssetSkuId,
|
2026-03-18 10:19:42 +08:00
|
|
|
TenantId: getUserInfo.TenantId,
|
|
|
|
|
TenantModuleType: req.TenantModuleType,
|
|
|
|
|
CertificationStatus: certificationStatus,
|
|
|
|
|
ExpireAt: assetSukRes.ExpireAt,
|
|
|
|
|
})
|
|
|
|
|
liberr.ErrIsNil(ctx, err, "添加模块租户关系失败")
|
|
|
|
|
// 设置缓存
|
|
|
|
|
_, err = s.AddRedisByTenantId(ctx, &system.AddRedisByTenantIdReq{
|
|
|
|
|
TenantId: getUserInfo.TenantId,
|
|
|
|
|
})
|
|
|
|
|
liberr.ErrIsNil(ctx, err, "设置缓存失败")
|
|
|
|
|
})
|
|
|
|
|
return err
|
|
|
|
|
})
|
|
|
|
|
return
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// Check 检查模块开通状态
|
|
|
|
|
func (s *sModuleTenant) Check(ctx context.Context, req *system.ModuleTenantCheckReq) (res *system.ModuleTenantCheckRes, err error) {
|
|
|
|
|
err = g.Try(ctx, func(ctx context.Context) {
|
|
|
|
|
res = new(system.ModuleTenantCheckRes)
|
|
|
|
|
// 查询模块租户关系
|
|
|
|
|
moduleTenant, err := s.GetByModuleKeyAndTenantId(ctx, req.ModuleKey, req.TenantId)
|
|
|
|
|
liberr.ErrIsNil(ctx, err, "查询模块租户关系失败")
|
|
|
|
|
// 判断状态
|
|
|
|
|
if g.IsEmpty(moduleTenant) {
|
|
|
|
|
// 没有记录,未开通
|
|
|
|
|
res.Message = "您未开通此功能模块,请开通后再使用"
|
|
|
|
|
res.Status = false
|
|
|
|
|
} else {
|
|
|
|
|
_, err = s.AddRedisByTenantId(ctx, &system.AddRedisByTenantIdReq{
|
|
|
|
|
TenantId: req.TenantId,
|
|
|
|
|
})
|
|
|
|
|
liberr.ErrIsNil(ctx, err, "设置缓存失败")
|
|
|
|
|
// 有记录,检查是否到期
|
|
|
|
|
now := gtime.Now()
|
|
|
|
|
if moduleTenant.ExpireAt != nil && moduleTenant.ExpireAt.Before(now) {
|
|
|
|
|
res.Message = "功能模块已到期,请续期后再使用"
|
|
|
|
|
res.Status = false
|
|
|
|
|
} else {
|
|
|
|
|
res.Status = true
|
|
|
|
|
if moduleTenant.CertificationStatus == consts.CertificationStatusPass {
|
|
|
|
|
res.Message = "已开通"
|
|
|
|
|
res.CertificationStatus = true
|
|
|
|
|
} else {
|
|
|
|
|
keyValue := consts.GetCertificationStatusKeyValue(moduleTenant.CertificationStatus)
|
|
|
|
|
res.Message = fmt.Sprintf("功能模块认证状态:%s", keyValue.Value)
|
|
|
|
|
res.CertificationStatus = false
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
})
|
|
|
|
|
return
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// GetByModuleKeyAndTenantId 根据模块Key和租户ID获取模块租户关系
|
|
|
|
|
func (s *sModuleTenant) GetByModuleKeyAndTenantId(ctx context.Context, moduleKey string, tenantId uint64) (moduleTenant *entity.ModuleTenant, err error) {
|
|
|
|
|
err = g.Try(ctx, func(ctx context.Context) {
|
|
|
|
|
err = dao.ModuleTenant.Ctx(ctx).
|
|
|
|
|
Where(dao.ModuleTenant.Columns().ModuleKey, moduleKey).
|
|
|
|
|
Where(dao.ModuleTenant.Columns().TenantId, tenantId).
|
|
|
|
|
Scan(&moduleTenant)
|
|
|
|
|
liberr.ErrIsNil(ctx, err, "获取模块租户关系失败")
|
|
|
|
|
})
|
|
|
|
|
return
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// AddRedisByTenantId 根据租户ID获取模块租户关系存到redis
|
|
|
|
|
func (s *sModuleTenant) AddRedisByTenantId(ctx context.Context, req *system.AddRedisByTenantIdReq) (res *system.AddRedisByTenantIdRes, err error) {
|
|
|
|
|
res = new(system.AddRedisByTenantIdRes)
|
|
|
|
|
//从数据库获取
|
|
|
|
|
err = dao.ModuleTenant.Ctx(ctx).
|
|
|
|
|
Where(dao.ModuleTenant.Columns().TenantId, req.TenantId).
|
|
|
|
|
Scan(&res.List)
|
|
|
|
|
liberr.ErrIsNil(ctx, err, "获取模块租户关系失败")
|
|
|
|
|
|
|
|
|
|
if !g.IsEmpty(res.List) {
|
|
|
|
|
err = g.Redis().SetEX(ctx, fmt.Sprintf("module_tenant:tenantId-%d", gconv.Int(req.TenantId)), res.List, gconv.Int64(time.Minute*1))
|
|
|
|
|
liberr.ErrIsNil(ctx, err, "设置缓存失败")
|
|
|
|
|
}
|
|
|
|
|
return
|
|
|
|
|
}
|