chore: 初始开源发布
iotlcm-app:小程序端 + 用户端服务。 - app/:uni-app 小程序前端(基于 unibest,MIT) - 微信 AppID → YOUR_WX_APPID,uni-app AppID → __UNI__YOURAPPID - 内网后端地址 → admin.iotlcm.example.com - 应用标题与 unibest 模板 README 重写(保留上游致谢与 MIT 声明) - server/:GoFrame 用户端服务(基于 XiuAdmin,Apache-2.0) - module xiuadmin → git.5iot.com/iotlcm-public/iotlcm-app(360 文件) - 支付回调地址 → app.iotlcm.example.com,商户名与应用名泛化 - 真实手机号 → 合法 11 位编造号(保留号段前 3 位 + 后 4 位) - 依赖号码尾部的断言同步更新 - 补 server/LICENSE(Apache-2.0) - 移除内部资产:CI 触发器 - 补根 README,LF 行尾 + .gitattributes 已知:TestSysDept_RefreshDeptAncestors 在源仓同一提交上同样失败,属既有缺陷。
This commit is contained in:
@@ -0,0 +1,187 @@
|
||||
package app
|
||||
|
||||
import (
|
||||
"context"
|
||||
"strings"
|
||||
|
||||
"git.5iot.com/iotlcm-public/iotlcm-app/internal/consts"
|
||||
"git.5iot.com/iotlcm-public/iotlcm-app/internal/dao"
|
||||
"git.5iot.com/iotlcm-public/iotlcm-app/internal/model"
|
||||
"git.5iot.com/iotlcm-public/iotlcm-app/internal/model/do"
|
||||
"git.5iot.com/iotlcm-public/iotlcm-app/internal/model/entity"
|
||||
|
||||
"github.com/gogf/gf/v2/database/gdb"
|
||||
"github.com/gogf/gf/v2/errors/gerror"
|
||||
"github.com/gogf/gf/v2/os/gtime"
|
||||
)
|
||||
|
||||
// 只处理终端用户绑卡。企业用户的持卡范围由管理平台权限逻辑决定,不写终端卡关联表。
|
||||
type appSimTerminalBindRow struct {
|
||||
Id int64 `orm:"id"`
|
||||
TerminalId int64 `orm:"terminal_id"`
|
||||
DeptId int64 `orm:"dept_id"`
|
||||
CurrentPackageCode string `orm:"current_package_code"`
|
||||
}
|
||||
|
||||
func (s *sAppCard) Bind(ctx context.Context, param *model.AppCardBindParam) (res *model.AppCardModel, err error) {
|
||||
user, err := appCurrentUser(ctx)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
if !s.isTerminalUser(ctx, user) {
|
||||
return nil, gerror.New("企业用户无需绑定卡,请在我的卡片中查询当前可见卡")
|
||||
}
|
||||
|
||||
card, err := s.findCardByValue(ctx, user.TenantId, param.CardValue)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
if card == nil {
|
||||
return nil, gerror.New("卡信息不存在,请确认查询号码是否正确")
|
||||
}
|
||||
|
||||
now := gtime.Now()
|
||||
alreadyBound := false
|
||||
err = dao.TSimTerminal.Transaction(ctx, func(ctx context.Context, tx gdb.TX) error {
|
||||
terminal, err := s.ensureTerminal(ctx, tx, user, now)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
var bind *appSimTerminalBindRow
|
||||
err = dao.TSimTerminal.Ctx(ctx).TX(tx).
|
||||
Where(dao.TSimTerminal.Columns().TenantId, user.TenantId).
|
||||
Where(dao.TSimTerminal.Columns().Iccid, card.Iccid).
|
||||
Where(dao.TSimTerminal.Columns().TerminalId, user.UserId).
|
||||
Scan(&bind)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
if bind != nil {
|
||||
alreadyBound = true
|
||||
if bind.DeptId != card.DeptId || strings.TrimSpace(bind.CurrentPackageCode) != strings.TrimSpace(card.CurrentPackageCode) {
|
||||
_, err = dao.TSimTerminal.Ctx(ctx).TX(tx).
|
||||
Where(dao.TSimTerminal.Columns().Id, bind.Id).
|
||||
Data(do.TSimTerminal{
|
||||
DeptId: card.DeptId,
|
||||
CurrentPackageCode: strings.TrimSpace(card.CurrentPackageCode),
|
||||
UpdatedBy: user.UserId,
|
||||
UpdatedAt: now,
|
||||
}).
|
||||
Update()
|
||||
}
|
||||
return err
|
||||
}
|
||||
_, err = dao.TSimTerminal.Ctx(ctx).TX(tx).Data(do.TSimTerminal{
|
||||
Iccid: card.Iccid,
|
||||
Msisdn: card.Msisdn,
|
||||
Imsi: card.Imsi,
|
||||
TerminalId: user.UserId,
|
||||
TerminalName: terminal.TerminalName,
|
||||
DeptId: card.DeptId,
|
||||
CurrentPackageCode: strings.TrimSpace(card.CurrentPackageCode),
|
||||
Remark: param.Remark,
|
||||
TenantId: user.TenantId,
|
||||
CreatedDept: appUserDeptOrDefault(user),
|
||||
CreatedBy: user.UserId,
|
||||
CreatedAt: now,
|
||||
UpdatedBy: user.UserId,
|
||||
UpdatedAt: now,
|
||||
}).Insert()
|
||||
return err
|
||||
})
|
||||
if err != nil {
|
||||
if isOldSimTerminalUniqueKeyError(err) {
|
||||
return nil, gerror.New("终端卡关联表唯一索引未更新,当前数据库仍限制一个终端用户只能绑定一张卡")
|
||||
}
|
||||
if isSimTerminalCardUniqueKeyError(err) {
|
||||
return nil, gerror.New("该卡已绑定当前用户,请刷新后重试")
|
||||
}
|
||||
return nil, err
|
||||
}
|
||||
if alreadyBound {
|
||||
return nil, gerror.New("该卡已绑定当前用户")
|
||||
}
|
||||
|
||||
cardRow, err := s.findVisibleCard(ctx, user, card.Iccid)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
if cardRow == nil {
|
||||
return nil, gerror.New("绑卡成功,但刷新卡信息失败")
|
||||
}
|
||||
return s.cardRowToModel(ctx, cardRow, user, appCardOwnerTerminal, true), nil
|
||||
}
|
||||
|
||||
func (s *sAppCard) ensureTerminal(ctx context.Context, tx gdb.TX, user *entity.SysUser, now *gtime.Time) (*entity.TTerminal, error) {
|
||||
var terminal *entity.TTerminal
|
||||
err := dao.TTerminal.Ctx(ctx).TX(tx).
|
||||
Where(dao.TTerminal.Columns().TerminalId, user.UserId).
|
||||
Scan(&terminal)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
if terminal != nil {
|
||||
if strings.TrimSpace(terminal.TerminalName) == "" {
|
||||
terminal.TerminalName = user.NickName
|
||||
}
|
||||
return terminal, nil
|
||||
}
|
||||
name := user.NickName
|
||||
if name == "" {
|
||||
name = user.UserName
|
||||
}
|
||||
_, err = dao.TTerminal.Ctx(ctx).TX(tx).Data(do.TTerminal{
|
||||
TerminalId: user.UserId,
|
||||
TerminalName: name,
|
||||
Phone: user.Phonenumber,
|
||||
Status: consts.SysUserStatusNormal,
|
||||
FullName: name,
|
||||
LegalPersonName: name,
|
||||
LegalPersonIdCard: "000000000000000000",
|
||||
Balance: 0,
|
||||
TenantId: user.TenantId,
|
||||
CreatedDept: appUserDeptOrDefault(user),
|
||||
CreatedBy: user.UserId,
|
||||
CreatedAt: now,
|
||||
UpdatedBy: user.UserId,
|
||||
UpdatedAt: now,
|
||||
}).Insert()
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return &entity.TTerminal{
|
||||
TerminalId: user.UserId,
|
||||
TerminalName: name,
|
||||
Phone: user.Phonenumber,
|
||||
TenantId: user.TenantId,
|
||||
CreatedDept: appUserDeptOrDefault(user),
|
||||
}, nil
|
||||
}
|
||||
|
||||
func (s *sAppCard) isCardBoundToUser(ctx context.Context, iccid string, user *entity.SysUser) bool {
|
||||
count, err := dao.TSimTerminal.Ctx(ctx).
|
||||
Where(dao.TSimTerminal.Columns().TenantId, user.TenantId).
|
||||
Where(dao.TSimTerminal.Columns().TerminalId, user.UserId).
|
||||
Where(dao.TSimTerminal.Columns().Iccid, iccid).
|
||||
Count()
|
||||
return err == nil && count > 0
|
||||
}
|
||||
|
||||
func isOldSimTerminalUniqueKeyError(err error) bool {
|
||||
if err == nil {
|
||||
return false
|
||||
}
|
||||
errText := err.Error()
|
||||
return strings.Contains(errText, "Duplicate entry") &&
|
||||
strings.Contains(errText, "uk_package_terminal")
|
||||
}
|
||||
|
||||
func isSimTerminalCardUniqueKeyError(err error) bool {
|
||||
if err == nil {
|
||||
return false
|
||||
}
|
||||
errText := err.Error()
|
||||
return strings.Contains(errText, "Duplicate entry") &&
|
||||
strings.Contains(errText, "uk_sim_terminal_card")
|
||||
}
|
||||
Reference in New Issue
Block a user