Yimaru-BackEnd/internal/services/personas/service.go
Yared Yemane 5399d33af6 Add optional gender to LMS personas.
Migration 000065 adds nullable gender text column; persona API and Postman expose it alongside profile_picture.

Co-authored-by: Cursor <cursoragent@cursor.com>
2026-05-20 06:37:21 -07:00

104 lines
2.4 KiB
Go

package personas
import (
"context"
"errors"
"strings"
"Yimaru-Backend/internal/domain"
"Yimaru-Backend/internal/ports"
"github.com/jackc/pgx/v5"
)
var ErrPersonaNotFound = domain.ErrPersonaNotFound
// ErrNameRequired indicates a missing trim-empty name on create.
var ErrNameRequired = errors.New("name is required")
// ErrNameEmptyUpdate indicates an update attempted to clear the persona name.
var ErrNameEmptyUpdate = errors.New("name cannot be empty")
type Service struct {
store ports.LmsPersonaStore
}
func NewService(store ports.LmsPersonaStore) *Service {
return &Service{store: store}
}
func clampPage(limit, offset int32) (int32, int32) {
if limit <= 0 {
limit = 20
}
if limit > 200 {
limit = 200
}
if offset < 0 {
offset = 0
}
return limit, offset
}
func (s *Service) Create(ctx context.Context, in domain.CreateLmsPersonaInput) (domain.LmsPersona, error) {
name := strings.TrimSpace(in.Name)
if name == "" {
return domain.LmsPersona{}, ErrNameRequired
}
in.Name = name
if in.Gender != nil {
t := strings.TrimSpace(*in.Gender)
if t == "" {
in.Gender = nil
} else {
in.Gender = &t
}
}
return s.store.CreateLmsPersona(ctx, in)
}
func (s *Service) GetByID(ctx context.Context, id int64) (domain.LmsPersona, error) {
p, err := s.store.GetLmsPersonaByID(ctx, id)
if err != nil {
if errors.Is(err, pgx.ErrNoRows) {
return domain.LmsPersona{}, ErrPersonaNotFound
}
return domain.LmsPersona{}, err
}
return p, nil
}
func (s *Service) Update(ctx context.Context, id int64, in domain.UpdateLmsPersonaInput) (domain.LmsPersona, error) {
if in.Name != nil {
t := strings.TrimSpace(*in.Name)
if t == "" {
return domain.LmsPersona{}, ErrNameEmptyUpdate
}
in.Name = &t
}
if in.Gender != nil {
t := strings.TrimSpace(*in.Gender)
in.Gender = &t // empty string clears stored gender when client sends gender: ""
}
p, err := s.store.UpdateLmsPersona(ctx, id, in)
if err != nil {
if errors.Is(err, pgx.ErrNoRows) {
return domain.LmsPersona{}, ErrPersonaNotFound
}
return domain.LmsPersona{}, err
}
return p, nil
}
func (s *Service) Delete(ctx context.Context, id int64) error {
if err := s.store.DeleteLmsPersona(ctx, id); err != nil {
return err
}
return nil
}
func (s *Service) List(ctx context.Context, activeOnly bool, limit, offset int32) ([]domain.LmsPersona, int64, error) {
limit, offset = clampPage(limit, offset)
return s.store.ListLmsPersonas(ctx, activeOnly, limit, offset)
}