package org import ( "context" "errors" "fmt" "strings" "gitea.d3m0k1d.ru/HellreigN/Control-plane/internal/db" ) var ( ErrNotFound = errors.New("organization not found") ErrSlugExists = errors.New("slug already taken") ) type Service struct { repo OrgRepository } func NewService(repo OrgRepository) *Service { return &Service{repo: repo} } func (s *Service) Create(ctx context.Context, req CreateOrgRequest) (*Organization, error) { req.Slug = strings.ToLower(strings.TrimSpace(req.Slug)) org := &Organization{ Name: req.Name, Slug: req.Slug, } if err := s.repo.Create(ctx, org); err != nil { if isUniqueViolation(err) { return nil, ErrSlugExists } return nil, fmt.Errorf("failed to create organization: %w", err) } return org, nil } func (s *Service) GetByID(ctx context.Context, id string) (*Organization, error) { org, err := s.repo.FindByID(ctx, id) if err != nil { if errors.Is(err, db.ErrNoRows) { return nil, ErrNotFound } return nil, fmt.Errorf("failed to find organization: %w", err) } return org, nil } func (s *Service) List(ctx context.Context, limit, offset int) (*OrgListResponse, error) { if limit <= 0 { limit = 20 } if offset < 0 { offset = 0 } total, err := s.repo.Count(ctx) if err != nil { return nil, fmt.Errorf("failed to count organizations: %w", err) } orgs, err := s.repo.FindAll(ctx, limit, offset) if err != nil { return nil, fmt.Errorf("failed to list organizations: %w", err) } if orgs == nil { orgs = []Organization{} } return &OrgListResponse{ Organizations: orgs, Total: total, Limit: limit, Offset: offset, }, nil } func (s *Service) Update( ctx context.Context, id string, req UpdateOrgRequest, ) (*Organization, error) { org, err := s.repo.FindByID(ctx, id) if err != nil { if errors.Is(err, db.ErrNoRows) { return nil, ErrNotFound } return nil, fmt.Errorf("failed to find organization: %w", err) } org.Name = req.Name if err := s.repo.Update(ctx, org); err != nil { return nil, fmt.Errorf("failed to update organization: %w", err) } return org, nil } func (s *Service) Delete(ctx context.Context, id string) error { found, err := s.repo.Delete(ctx, id) if err != nil { return fmt.Errorf("failed to delete organization: %w", err) } if !found { return ErrNotFound } return nil } func isUniqueViolation(err error) bool { return err != nil && (strings.Contains(err.Error(), "unique") || strings.Contains(err.Error(), "23505")) }