// MIT License // // Copyright (c) 2024 vinchent // // Permission is hereby granted, free of charge, to any person obtaining a copy // of this software and associated documentation files (the "Software"), to deal // in the Software without restriction, including without limitation the rights // to use, copy, modify, merge, publish, distribute, sublicense, and/or sell // copies of the Software, and to permit persons to whom the Software is // furnished to do so, subject to the following conditions: // // The above copyright notice and this permission notice shall be included in all // copies or substantial portions of the Software. // // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE // AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER // LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, // OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE // SOFTWARE. package repo import ( "context" "database/sql" "encoding/json" "time" "git.vinchent.xyz/vinchent/howmuch/internal/howmuch/adapter/repo/sqlc" "git.vinchent.xyz/vinchent/howmuch/internal/howmuch/model" "git.vinchent.xyz/vinchent/howmuch/internal/howmuch/usecase/repo" "git.vinchent.xyz/vinchent/howmuch/internal/pkg/log" ) type eventRepository struct { queries *sqlc.Queries } func NewEventRepository(db *sql.DB) repo.EventRepository { return &eventRepository{ queries: sqlc.New(db), } } // Create implements repo.EventRepository. func (e *eventRepository) Create( ctx context.Context, evEntity *model.EventEntity, tx any, ) (*model.EventEntity, error) { timeoutCtx, cancel := context.WithTimeout(ctx, queryTimeout) defer cancel() queries := getQueries(e.queries, tx) event, err := queries.InsertEvent(timeoutCtx, sqlc.InsertEventParams{ Name: evEntity.Name, Description: sql.NullString{String: evEntity.Description, Valid: true}, TotalAmount: sql.NullInt32{Int32: int32(evEntity.TotalAmount), Valid: true}, DefaultCurrency: evEntity.DefaultCurrency, OwnerID: int32(evEntity.OwnerID), CreatedAt: time.Now(), UpdatedAt: time.Now(), }) if err != nil { return nil, err } return &model.EventEntity{ ID: int(event.ID), Name: event.Name, Description: event.Description.String, TotalAmount: int(event.TotalAmount.Int32), DefaultCurrency: event.DefaultCurrency, OwnerID: int(event.OwnerID), CreatedAt: event.CreatedAt, UpdatedAt: event.UpdatedAt, }, nil } func convToEventRetrieved(eventDTO *sqlc.GetEventByIDRow) (*model.EventRetrieved, error) { // marshal owner and users var owner model.UserBaseRetrieved err := json.Unmarshal(eventDTO.Owner, &owner) if err != nil { // Unexpected log.ErrorLog("json unmarshal error", "err", err) return nil, err } var users []model.UserBaseRetrieved err = json.Unmarshal(eventDTO.Users, &users) if err != nil { // Unexpected log.ErrorLog("json unmarshal error", "err", err) return nil, err } eventRetrieved := &model.EventRetrieved{ ID: int(eventDTO.ID), Name: eventDTO.Name, Description: eventDTO.Description.String, TotalAmount: model.MakeMoney( int(eventDTO.TotalAmount.Int32), model.Currency(eventDTO.DefaultCurrency), ), DefaultCurrency: model.Currency(eventDTO.DefaultCurrency), CreatedAt: eventDTO.CreatedAt, UpdatedAt: eventDTO.UpdatedAt, Owner: &owner, Users: users, } return eventRetrieved, nil } // GetByID implements repo.EventRepository. func (e *eventRepository) GetByID( ctx context.Context, eventID int, tx any, ) (*model.EventRetrieved, error) { timeoutCtx, cancel := context.WithTimeout(ctx, queryTimeout) defer cancel() queries := getQueries(e.queries, tx) eventDTO, err := queries.GetEventByID(timeoutCtx, int32(eventID)) if err != nil { log.ErrorLog("query error", "err", err) return nil, err } return convToEventRetrieved(&eventDTO) } func convToEventList(eventsDTO []sqlc.ListEventsByUserIDRow) ([]model.EventListRetrieved, error) { var events []model.EventListRetrieved for _, evDTO := range eventsDTO { var owner model.UserBaseRetrieved err := json.Unmarshal(evDTO.Owner, &owner) if err != nil { // Unexpected log.ErrorLog("json unmarshal error", "err", err) return nil, err } ev := model.EventListRetrieved{ ID: int(evDTO.ID), Name: evDTO.Name, Description: evDTO.Description.String, Owner: &owner, CreatedAt: evDTO.CreatedAt, } events = append(events, ev) } return events, nil } // ListEventsByUserID implements repo.EventRepository. func (e *eventRepository) ListEventsByUserID( ctx context.Context, userID int, tx any, ) ([]model.EventListRetrieved, error) { timeoutCtx, cancel := context.WithTimeout(ctx, queryTimeout) defer cancel() queries := getQueries(e.queries, tx) eventsDTO, err := queries.ListEventsByUserID(timeoutCtx, int32(userID)) if err != nil { log.ErrorLog("query error", "err", err) return nil, err } return convToEventList(eventsDTO) } // UpdateInfo implements repo.EventRepository. func (e *eventRepository) UpdateEventByID( ctx context.Context, event *model.EventUpdateEntity, tx any, ) error { timeoutCtx, cancel := context.WithTimeout(ctx, queryTimeout) defer cancel() queries := getQueries(e.queries, tx) err := queries.UpdateEventByID(timeoutCtx, sqlc.UpdateEventByIDParams{ ID: int32(event.ID), Name: event.Name, Description: sql.NullString{String: event.Description, Valid: true}, UpdatedAt: time.Now(), }) return err }