package budget import ( "context" "spend-sparrow/internal/auth_types" "spend-sparrow/internal/core" "github.com/google/uuid" ) type Service interface { Add(ctx context.Context, user *auth_types.User, budget Budget) (*Budget, error) Update(ctx context.Context, user *auth_types.User, budget Budget) (*Budget, error) Delete(ctx context.Context, user *auth_types.User, budgetId uuid.UUID) error Get(ctx context.Context, user *auth_types.User, budgetId uuid.UUID) (*Budget, error) GetAll(ctx context.Context, user *auth_types.User) ([]Budget, error) } type ServiceImpl struct { db Db clock core.Clock random core.Random } func NewService(db Db, random core.Random, clock core.Clock) Service { return ServiceImpl{ db: db, clock: clock, random: random, } } func (s ServiceImpl) Add(ctx context.Context, user *auth_types.User, budget Budget) (*Budget, error) { if user == nil { return nil, core.ErrUnauthorized } isValid := s.isBudgetValid(budget) if !isValid { return nil, core.ErrBadRequest } newId, err := s.random.UUID(ctx) if err != nil { return nil, core.ErrInternal } budget.Id = newId budget.UserId = user.Id budget.CreatedBy = user.Id budget.CreatedAt = s.clock.Now() return s.db.Insert(ctx, budget) } func (s ServiceImpl) Update(ctx context.Context, user *auth_types.User, budget Budget) (*Budget, error) { if user == nil { return nil, core.ErrUnauthorized } if user.Id != budget.UserId { return nil, core.ErrBadRequest } isValid := s.isBudgetValid(budget) if !isValid { return nil, core.ErrBadRequest } budget.UpdatedBy = &user.Id now := s.clock.Now() budget.UpdatedAt = &now return s.db.Update(ctx, budget) } func (s ServiceImpl) Delete(ctx context.Context, user *auth_types.User, budgetId uuid.UUID) error { if user == nil { return core.ErrUnauthorized } return s.db.Delete(ctx, user.Id, budgetId) } func (s ServiceImpl) Get(ctx context.Context, user *auth_types.User, budgetId uuid.UUID) (*Budget, error) { if user == nil { return nil, core.ErrUnauthorized } return s.db.Get(ctx, user.Id, budgetId) } func (s ServiceImpl) GetAll(ctx context.Context, user *auth_types.User) ([]Budget, error) { if user == nil { return nil, core.ErrUnauthorized } return s.db.GetAll(ctx, user.Id) } func (s ServiceImpl) isBudgetValid(budget Budget) bool { if budget.Description != "" { err := core.ValidateString(budget.Description, "description") if err != nil { return false } } else if budget.Value < 0 { return false } return true }