init push
This commit is contained in:
151
internal/service/base_service.go
Normal file
151
internal/service/base_service.go
Normal file
@@ -0,0 +1,151 @@
|
||||
package service
|
||||
|
||||
import (
|
||||
"context"
|
||||
"errors"
|
||||
"strings"
|
||||
"time"
|
||||
|
||||
"wucher/internal/domain/base"
|
||||
"wucher/internal/shared/pkg/appctx"
|
||||
"wucher/internal/shared/pkg/sortkey"
|
||||
)
|
||||
|
||||
type BaseService struct {
|
||||
repo base.Repository
|
||||
}
|
||||
|
||||
func NewBaseService(repo base.Repository) *BaseService {
|
||||
return &BaseService{repo: repo}
|
||||
}
|
||||
|
||||
var errInvalidBaseCategoryType = errors.New("invalid base category type")
|
||||
|
||||
func (s *BaseService) CreateBase(ctx context.Context, row *base.Base, categoryType string) error {
|
||||
category, ok := base.NormalizeCategoryType(categoryType)
|
||||
if !ok {
|
||||
return errInvalidBaseCategoryType
|
||||
}
|
||||
if err := validateBaseCoordinates(row); err != nil {
|
||||
return err
|
||||
}
|
||||
row.DefaultStartTimeType = normalizeBaseShiftTimeType(row.DefaultStartTimeType)
|
||||
row.DefaultEndTimeType = normalizeBaseShiftTimeType(row.DefaultEndTimeType)
|
||||
if row.DefaultStartTimeType == base.ShiftTimeTypeFixed && strings.TrimSpace(row.DefaultShiftStart) == "" {
|
||||
return errors.New("default_shift_start is required")
|
||||
}
|
||||
if row.DefaultEndTimeType == base.ShiftTimeTypeFixed && strings.TrimSpace(row.DefaultShiftEnd) == "" {
|
||||
return errors.New("default_shift_end is required")
|
||||
}
|
||||
return s.repo.CreateBase(ctx, row, category)
|
||||
}
|
||||
|
||||
func (s *BaseService) UpdateBase(ctx context.Context, row *base.Base, categoryType string) error {
|
||||
category, ok := base.NormalizeCategoryType(categoryType)
|
||||
if !ok {
|
||||
return errInvalidBaseCategoryType
|
||||
}
|
||||
if err := validateBaseCoordinates(row); err != nil {
|
||||
return err
|
||||
}
|
||||
row.DefaultStartTimeType = normalizeBaseShiftTimeType(row.DefaultStartTimeType)
|
||||
row.DefaultEndTimeType = normalizeBaseShiftTimeType(row.DefaultEndTimeType)
|
||||
if row.DefaultStartTimeType == base.ShiftTimeTypeFixed && strings.TrimSpace(row.DefaultShiftStart) == "" {
|
||||
return errors.New("default_shift_start is required")
|
||||
}
|
||||
if row.DefaultEndTimeType == base.ShiftTimeTypeFixed && strings.TrimSpace(row.DefaultShiftEnd) == "" {
|
||||
return errors.New("default_shift_end is required")
|
||||
}
|
||||
return s.repo.UpdateBase(ctx, row, category)
|
||||
}
|
||||
|
||||
func (s *BaseService) DeleteBase(ctx context.Context, id []byte, categoryType string) (*base.Base, error) {
|
||||
category, ok := base.NormalizeCategoryType(categoryType)
|
||||
if !ok {
|
||||
return nil, errInvalidBaseCategoryType
|
||||
}
|
||||
|
||||
// fetch existing row before deleting so we can return a copy
|
||||
row, err := s.repo.GetBaseByID(ctx, id, category)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
if err := s.repo.DeleteBase(ctx, id, category); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
// if we had a row, populate DeletedAt/DeletedBy to reflect the repository update
|
||||
if row != nil {
|
||||
now := time.Now().UTC()
|
||||
row.DeletedAt = &now
|
||||
// try to pick actor from context if available
|
||||
if actor := appctx.GetUserID(ctx); len(actor) > 0 {
|
||||
row.DeletedBy = make([]byte, len(actor))
|
||||
copy(row.DeletedBy, actor)
|
||||
}
|
||||
}
|
||||
|
||||
return row, nil
|
||||
}
|
||||
|
||||
func (s *BaseService) GetBaseByID(ctx context.Context, id []byte, categoryType string) (*base.Base, error) {
|
||||
category, ok := base.NormalizeCategoryType(categoryType)
|
||||
if !ok {
|
||||
return nil, errInvalidBaseCategoryType
|
||||
}
|
||||
return s.repo.GetBaseByID(ctx, id, category)
|
||||
}
|
||||
|
||||
func (s *BaseService) ListBases(ctx context.Context, filter, sort string, limit, offset int, categoryType string, dul *bool) ([]base.Base, int64, error) {
|
||||
if strings.TrimSpace(categoryType) == "" {
|
||||
return s.repo.ListBases(ctx, filter, normalizeBaseSort(sort), limit, offset, "", dul)
|
||||
}
|
||||
category, ok := base.NormalizeCategoryType(categoryType)
|
||||
if !ok {
|
||||
return nil, 0, errInvalidBaseCategoryType
|
||||
}
|
||||
return s.repo.ListBases(ctx, filter, normalizeBaseSort(sort), limit, offset, category, dul)
|
||||
}
|
||||
|
||||
func normalizeBaseSort(sort string) string {
|
||||
return normalizeSortByRules(sort,
|
||||
sortExpr(
|
||||
joinSortClauses(sortkey.ActivePositiveSortClauses("", "is_active", "sortkey", "base", false)),
|
||||
joinSortClauses(sortkey.ActivePositiveSortClauses("", "is_active", "sortkey", "base", true)),
|
||||
"sortkey",
|
||||
),
|
||||
sortField("base"),
|
||||
sortField("base_abbreviation"),
|
||||
sortField("notes", "note", "notes"),
|
||||
sortField("is_active"),
|
||||
sortField("created_at"),
|
||||
sortField("updated_at"),
|
||||
)
|
||||
}
|
||||
|
||||
func validateBaseCoordinates(row *base.Base) error {
|
||||
if row == nil {
|
||||
return nil
|
||||
}
|
||||
if row.Latitude < -90 || row.Latitude > 90 {
|
||||
return errors.New("latitude must be between -90 and 90")
|
||||
}
|
||||
if row.Longitude < -180 || row.Longitude > 180 {
|
||||
return errors.New("longitude must be between -180 and 180")
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func normalizeBaseShiftTimeType(raw string) string {
|
||||
switch strings.ToUpper(strings.TrimSpace(raw)) {
|
||||
case "", base.ShiftTimeTypeFixed:
|
||||
return base.ShiftTimeTypeFixed
|
||||
case base.ShiftTimeTypeBMCT:
|
||||
return base.ShiftTimeTypeBMCT
|
||||
case base.ShiftTimeTypeECET:
|
||||
return base.ShiftTimeTypeECET
|
||||
default:
|
||||
return strings.ToUpper(strings.TrimSpace(raw))
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user