Files
iotlcm/worker-svr/internal/service/packagecustomer/service.go

178 lines
5.0 KiB
Go

package packagecustomer
import (
"context"
"strings"
"github.com/gogf/gf/v2/database/gdb"
"github.com/gogf/gf/v2/errors/gerror"
"github.com/gogf/gf/v2/frame/g"
"github.com/gogf/gf/v2/os/gtime"
"git.5iot.com/iotlcm-public/iotlcm-worker-svr/internal/model"
)
const (
sysDeptTable = "sys_dept"
cardInfoTable = "t_sim_card_info"
flowPackageTable = "t_sim_flow_package_info"
packageCustomerTable = "t_package_customer"
)
var ErrDeptNotFound = gerror.New("package customer sync dept not found")
type Service struct {
db gdb.DB
}
type deptRow struct {
DeptId int64 `orm:"dept_id"`
ParentId int64 `orm:"parent_id"`
Ancestors string `orm:"ancestors"`
DeptName string `orm:"dept_name"`
}
type packageRow struct {
PackageCode string `orm:"package_code"`
PackageName string `orm:"package_name"`
}
func New() *Service {
return &Service{}
}
func (s *Service) SyncDeptPackages(ctx context.Context, message model.PackageCustomerSyncMessage) error {
message.TenantId = strings.TrimSpace(message.TenantId)
message.Trigger = strings.TrimSpace(message.Trigger)
if message.TenantId == "" {
return gerror.New("package customer sync tenantId is empty")
}
if message.DeptId <= 0 {
return gerror.New("package customer sync deptId is empty")
}
var packageCount int
err := s.database().Transaction(ctx, func(ctx context.Context, tx gdb.TX) error {
dept, err := s.lockDept(ctx, tx, message.TenantId, message.DeptId)
if err != nil {
return err
}
packages, err := s.loadPackages(ctx, tx, message.TenantId, dept)
if err != nil {
return err
}
packageCount = len(packages)
return s.rebuild(ctx, tx, message.TenantId, dept, message.UserId, packages)
})
if err != nil {
return err
}
g.Log().Infof(ctx, "package customer sync finished, tenantId:%s, deptId:%d, packages:%d, trigger:%s, sourceBatchNo:%s",
message.TenantId, message.DeptId, packageCount, message.Trigger, message.SourceBatchNo)
return nil
}
func (s *Service) database() gdb.DB {
if s.db != nil {
return s.db
}
return g.DB()
}
func (s *Service) lockDept(ctx context.Context, tx gdb.TX, tenantId string, deptId int64) (*deptRow, error) {
var dept *deptRow
err := tx.Ctx(ctx).Model(sysDeptTable).Safe().
Fields("dept_id", "parent_id", "ancestors", "dept_name").
Where("tenant_id", tenantId).
Where("dept_id", deptId).
WhereNull("deleted_at").
LockUpdate().
Limit(1).
Scan(&dept)
if err != nil {
return nil, gerror.Wrap(err, "load package customer sync dept failed")
}
if dept == nil || dept.DeptId <= 0 {
return nil, ErrDeptNotFound
}
return dept, nil
}
func (s *Service) loadPackages(ctx context.Context, tx gdb.TX, tenantId string, dept *deptRow) ([]packageRow, error) {
if deptIsTop(dept) {
var packages []packageRow
err := tx.Ctx(ctx).Model(flowPackageTable).Safe().
Fields("package_code", "package_name").
Where("tenant_id", tenantId).
Scan(&packages)
if err != nil {
return nil, gerror.Wrap(err, "load top dept packages failed")
}
return packages, nil
}
var packages []packageRow
err := tx.Ctx(ctx).Model(cardInfoTable+" c").Safe().
LeftJoin(flowPackageTable+" p", "c.current_package_code = p.package_code").
Fields("DISTINCT c.current_package_code AS package_code", "p.package_name AS package_name").
Where("c.tenant_id", tenantId).
Where("c.dept_id", dept.DeptId).
Where("p.tenant_id", tenantId).
Where("c.current_package_code IS NOT NULL").
Where("c.current_package_code <> ?", "").
Where("p.package_code IS NOT NULL").
Scan(&packages)
if err != nil {
return nil, gerror.Wrap(err, "load dept packages failed")
}
return packages, nil
}
func (s *Service) rebuild(ctx context.Context, tx gdb.TX, tenantId string, dept *deptRow, userId int64, packages []packageRow) error {
if _, err := tx.Ctx(ctx).Model(packageCustomerTable).Safe().
Where("tenant_id", tenantId).
Where("dept_id", dept.DeptId).
Delete(); err != nil {
return gerror.Wrap(err, "clear dept package customer relation failed")
}
now := gtime.Now()
rows := make([]g.Map, 0, len(packages))
seen := make(map[string]struct{}, len(packages))
for _, item := range packages {
packageCode := strings.TrimSpace(item.PackageCode)
if packageCode == "" {
continue
}
if _, ok := seen[packageCode]; ok {
continue
}
seen[packageCode] = struct{}{}
rows = append(rows, g.Map{
"package_code": packageCode,
"package_name": strings.TrimSpace(item.PackageName),
"dept_id": dept.DeptId,
"dept_name": strings.TrimSpace(dept.DeptName),
"tenant_id": tenantId,
"created_dept": dept.DeptId,
"created_by": userId,
"created_at": now,
"updated_by": userId,
"updated_at": now,
})
}
if len(rows) == 0 {
return nil
}
if _, err := tx.Ctx(ctx).Model(packageCustomerTable).Safe().Data(rows).Insert(); err != nil {
return gerror.Wrap(err, "insert dept package customer relation failed")
}
return nil
}
func deptIsTop(dept *deptRow) bool {
if dept == nil {
return false
}
return dept.ParentId == 0 || strings.Trim(dept.Ancestors, ",") == "0"
}