package usecase import ( "context" "errors" "strings" "time" member "gateway/internal/model/member/domain" "gateway/internal/model/member/domain/entity" "gateway/internal/model/member/domain/enum" domrepo "gateway/internal/model/member/domain/repository" domusecase "gateway/internal/model/member/domain/usecase" ) type tenantUseCase struct { tenants domrepo.TenantRepository } // TenantUseCaseParam wires TenantUseCase. type TenantUseCaseParam struct { Tenants domrepo.TenantRepository } // MustTenantUseCase constructs TenantUseCase. func MustTenantUseCase(param TenantUseCaseParam) domusecase.TenantUseCase { if param.Tenants == nil { panic("member: tenant repository is required") } return &tenantUseCase{tenants: param.Tenants} } func (uc *tenantUseCase) Create(ctx context.Context, req *domusecase.CreateTenantRequest) (*domusecase.TenantDTO, error) { if req == nil || req.TenantID == "" || req.Slug == "" || req.Name == "" { return nil, errb.InputMissingRequired("tenant_id, slug and name are required") } prefix := normalizeUIDPrefix(req.UIDPrefix) if prefix == "" { prefix = normalizeUIDPrefix(req.Slug) } if len(prefix) < member.UIDPrefixMinLength || len(prefix) > member.UIDPrefixMaxLength { return nil, errb.InputInvalidFormat("uid_prefix must be 2-4 uppercase letters") } if _, err := uc.tenants.GetByUIDPrefix(ctx, prefix); err == nil { return nil, errb.ResAlreadyExist("uid_prefix already exists") } else if !errors.Is(err, member.ErrTenantNotFound) { return nil, errb.SysInternal("read tenant failed").WithCause(err) } now := time.Now().UTC().UnixMilli() rec := &entity.Tenant{ TenantID: req.TenantID, Slug: strings.ToLower(req.Slug), Name: req.Name, UIDPrefix: prefix, Status: enum.TenantStatusActive, CreateAt: now, UpdateAt: now, } if err := uc.tenants.Insert(ctx, rec); err != nil { if errors.Is(err, member.ErrDuplicateTenant) { return nil, errb.ResAlreadyExist("tenant already exists").WithCause(err) } return nil, errb.SysInternal("create tenant failed").WithCause(err) } return tenantToDTO(rec), nil } func (uc *tenantUseCase) ResolveBySlug(ctx context.Context, slug string) (*domusecase.TenantDTO, error) { if slug == "" { return nil, errb.InputMissingRequired("slug is required") } rec, err := uc.tenants.GetBySlug(ctx, strings.ToLower(slug)) if err != nil { if errors.Is(err, member.ErrTenantNotFound) { return nil, errb.ResNotFound("tenant", slug).WithCause(err) } return nil, errb.SysInternal("read tenant failed").WithCause(err) } return tenantToDTO(rec), nil }