add shopping list and tag management
This commit is contained in:
parent
d2560630f4
commit
b7905ddded
19 changed files with 1253 additions and 11 deletions
146
internal/service/shopping_list.go
Normal file
146
internal/service/shopping_list.go
Normal file
|
|
@ -0,0 +1,146 @@
|
|||
package service
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"strings"
|
||||
"time"
|
||||
|
||||
"git.juancwu.dev/juancwu/budgit/internal/model"
|
||||
"git.juancwu.dev/juancwu/budgit/internal/repository"
|
||||
"github.com/google/uuid"
|
||||
)
|
||||
|
||||
type ShoppingListService struct {
|
||||
listRepo repository.ShoppingListRepository
|
||||
itemRepo repository.ListItemRepository
|
||||
}
|
||||
|
||||
func NewShoppingListService(listRepo repository.ShoppingListRepository, itemRepo repository.ListItemRepository) *ShoppingListService {
|
||||
return &ShoppingListService{
|
||||
listRepo: listRepo,
|
||||
itemRepo: itemRepo,
|
||||
}
|
||||
}
|
||||
|
||||
// List methods
|
||||
func (s *ShoppingListService) CreateList(spaceID, name string) (*model.ShoppingList, error) {
|
||||
name = strings.TrimSpace(name)
|
||||
if name == "" {
|
||||
return nil, fmt.Errorf("list name cannot be empty")
|
||||
}
|
||||
|
||||
now := time.Now()
|
||||
list := &model.ShoppingList{
|
||||
ID: uuid.NewString(),
|
||||
SpaceID: spaceID,
|
||||
Name: name,
|
||||
CreatedAt: now,
|
||||
UpdatedAt: now,
|
||||
}
|
||||
|
||||
err := s.listRepo.Create(list)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
return list, nil
|
||||
}
|
||||
|
||||
func (s *ShoppingListService) GetListsForSpace(spaceID string) ([]*model.ShoppingList, error) {
|
||||
return s.listRepo.GetBySpaceID(spaceID)
|
||||
}
|
||||
|
||||
func (s *ShoppingListService) GetList(listID string) (*model.ShoppingList, error) {
|
||||
return s.listRepo.GetByID(listID)
|
||||
}
|
||||
|
||||
func (s *ShoppingListService) UpdateList(listID, name string) (*model.ShoppingList, error) {
|
||||
name = strings.TrimSpace(name)
|
||||
if name == "" {
|
||||
return nil, fmt.Errorf("list name cannot be empty")
|
||||
}
|
||||
|
||||
list, err := s.listRepo.GetByID(listID)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
list.Name = name
|
||||
|
||||
err = s.listRepo.Update(list)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
return list, nil
|
||||
}
|
||||
|
||||
func (s *ShoppingListService) DeleteList(listID string) error {
|
||||
// First delete all items in the list
|
||||
err := s.itemRepo.DeleteByListID(listID)
|
||||
if err != nil {
|
||||
return fmt.Errorf("failed to delete items in list: %w", err)
|
||||
}
|
||||
// Then delete the list itself
|
||||
return s.listRepo.Delete(listID)
|
||||
}
|
||||
|
||||
// Item methods
|
||||
func (s *ShoppingListService) AddItemToList(listID, name, createdBy string) (*model.ListItem, error) {
|
||||
name = strings.TrimSpace(name)
|
||||
if name == "" {
|
||||
return nil, fmt.Errorf("item name cannot be empty")
|
||||
}
|
||||
|
||||
now := time.Now()
|
||||
item := &model.ListItem{
|
||||
ID: uuid.NewString(),
|
||||
ListID: listID,
|
||||
Name: name,
|
||||
IsChecked: false,
|
||||
CreatedBy: createdBy,
|
||||
CreatedAt: now,
|
||||
UpdatedAt: now,
|
||||
}
|
||||
|
||||
err := s.itemRepo.Create(item)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
return item, nil
|
||||
}
|
||||
|
||||
func (s *ShoppingListService) GetItem(itemID string) (*model.ListItem, error) {
|
||||
return s.itemRepo.GetByID(itemID)
|
||||
}
|
||||
|
||||
func (s *ShoppingListService) GetItemsForList(listID string) ([]*model.ListItem, error) {
|
||||
return s.itemRepo.GetByListID(listID)
|
||||
}
|
||||
|
||||
func (s *ShoppingListService) UpdateItem(itemID, name string, isChecked bool) (*model.ListItem, error) {
|
||||
name = strings.TrimSpace(name)
|
||||
if name == "" {
|
||||
return nil, fmt.Errorf("item name cannot be empty")
|
||||
}
|
||||
|
||||
item, err := s.itemRepo.GetByID(itemID)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
item.Name = name
|
||||
item.IsChecked = isChecked
|
||||
|
||||
err = s.itemRepo.Update(item)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
return item, nil
|
||||
}
|
||||
|
||||
func (s *ShoppingListService) DeleteItem(itemID string) error {
|
||||
return s.itemRepo.Delete(itemID)
|
||||
}
|
||||
|
|
@ -71,6 +71,15 @@ func (s *SpaceService) GetSpacesForUser(userID string) ([]*model.Space, error) {
|
|||
return spaces, nil
|
||||
}
|
||||
|
||||
// GetSpace retrieves a single space by its ID.
|
||||
func (s *SpaceService) GetSpace(spaceID string) (*model.Space, error) {
|
||||
space, err := s.spaceRepo.ByID(spaceID)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("failed to get space: %w", err)
|
||||
}
|
||||
return space, nil
|
||||
}
|
||||
|
||||
// IsMember checks if a user is a member of a given space.
|
||||
func (s *SpaceService) IsMember(userID, spaceID string) (bool, error) {
|
||||
isMember, err := s.spaceRepo.IsMember(spaceID, userID)
|
||||
|
|
|
|||
77
internal/service/tag.go
Normal file
77
internal/service/tag.go
Normal file
|
|
@ -0,0 +1,77 @@
|
|||
package service
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"strings"
|
||||
"time"
|
||||
|
||||
"git.juancwu.dev/juancwu/budgit/internal/model"
|
||||
"git.juancwu.dev/juancwu/budgit/internal/repository"
|
||||
"github.com/google/uuid"
|
||||
)
|
||||
|
||||
type TagService struct {
|
||||
tagRepo repository.TagRepository
|
||||
}
|
||||
|
||||
func NewTagService(tagRepo repository.TagRepository) *TagService {
|
||||
return &TagService{tagRepo: tagRepo}
|
||||
}
|
||||
|
||||
func (s *TagService) CreateTag(spaceID, name string, color *string) (*model.Tag, error) {
|
||||
name = strings.TrimSpace(name)
|
||||
if name == "" {
|
||||
return nil, fmt.Errorf("tag name cannot be empty")
|
||||
}
|
||||
|
||||
now := time.Now()
|
||||
tag := &model.Tag{
|
||||
ID: uuid.NewString(),
|
||||
SpaceID: spaceID,
|
||||
Name: name,
|
||||
Color: color,
|
||||
CreatedAt: now,
|
||||
UpdatedAt: now,
|
||||
}
|
||||
|
||||
err := s.tagRepo.Create(tag)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
return tag, nil
|
||||
}
|
||||
|
||||
func (s *TagService) GetTagsForSpace(spaceID string) ([]*model.Tag, error) {
|
||||
return s.tagRepo.GetBySpaceID(spaceID)
|
||||
}
|
||||
|
||||
func (s *TagService) GetTagByID(id string) (*model.Tag, error) {
|
||||
return s.tagRepo.GetByID(id)
|
||||
}
|
||||
|
||||
func (s *TagService) UpdateTag(id, name string, color *string) (*model.Tag, error) {
|
||||
name = strings.TrimSpace(name)
|
||||
if name == "" {
|
||||
return nil, fmt.Errorf("tag name cannot be empty")
|
||||
}
|
||||
|
||||
tag, err := s.tagRepo.GetByID(id)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
tag.Name = name
|
||||
tag.Color = color
|
||||
|
||||
err = s.tagRepo.Update(tag)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
|
||||
return tag, nil
|
||||
}
|
||||
|
||||
func (s *TagService) DeleteTag(id string) error {
|
||||
return s.tagRepo.Delete(id)
|
||||
}
|
||||
Loading…
Add table
Add a link
Reference in a new issue