-
Notifications
You must be signed in to change notification settings - Fork 4
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
Introduce event services and update models
Added the initial implementation of the event service with methods to retrieve and create events, incorporating user and tag data. Adjusted the database transaction logic to ensure consistency during event creation. In the model layer, strengthened the relationship between the `Cfp` and `Event` by adding an `EventID` to `Cfp` and removing the redundant `cfp_id` from `Event`, thereby normalizing the database schema and reducing redundancy. These enhancements prepare for more robust event handling and querying capabilities. Resolves #42 - Implement event services Fixes #56 - Normalize event relationship in models
- Loading branch information
1 parent
47a1604
commit 6a0c0d5
Showing
3 changed files
with
126 additions
and
1 deletion.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,124 @@ | ||
package event | ||
|
||
import ( | ||
"context" | ||
"errors" | ||
"log/slog" | ||
"time" | ||
|
||
"github.com/lib/pq" | ||
"github.com/marcopollivier/techagenda/pkg/user" | ||
"github.com/samber/lo" | ||
"gorm.io/gorm" | ||
) | ||
|
||
type Service interface { | ||
Get(ctx context.Context, name, city string, tags []string, typeOf []EventTypeOf, available bool, page, limit int) (events []Event, err error) | ||
Create(ctx context.Context, user user.User, event EventDTO, tags []string) (result Event, err error) | ||
} | ||
|
||
type EventService struct { | ||
db *gorm.DB | ||
} | ||
|
||
func NewEventService(db *gorm.DB) Service { | ||
return &EventService{ | ||
db: db, | ||
} | ||
} | ||
|
||
func (e *EventService) Get( | ||
ctx context.Context, | ||
name, city string, | ||
tags []string, | ||
typeOf []EventTypeOf, | ||
available bool, | ||
page, limit int, | ||
) (events []Event, err error) { | ||
if limit == 0 || limit > 100 { | ||
limit = 50 | ||
} | ||
now := time.Now() | ||
base := e.db.Joins("User"). | ||
Preload("Attendees"). | ||
Preload("Tags", func(db *gorm.DB) *gorm.DB { | ||
if len(tags) > 0 { | ||
return db.Where("tag in ?", tags) | ||
} | ||
return db | ||
}). | ||
Preload("Venues", func(db *gorm.DB) *gorm.DB { | ||
if lo.IsNotEmpty(city) { | ||
return db.Where("city in ?", city) | ||
} | ||
return db | ||
}). | ||
Offset(page * limit). | ||
Limit(limit) | ||
|
||
if lo.IsNotEmpty(name) { | ||
base.Where("name like ?", name) | ||
} | ||
if len(typeOf) > 0 { | ||
base.Where("? in ANY(typeOf)", typeOf) | ||
} | ||
if available { | ||
base.Where("begin_date <= ?", now).Where("end_date > ?", now) | ||
} | ||
|
||
if err = base.Find(&events).Error; err != nil { | ||
slog.ErrorContext(ctx, "Fail to scan events", "error", err.Error()) | ||
} | ||
return | ||
} | ||
|
||
func (e *EventService) Create(ctx context.Context, user user.User, event EventDTO, tags []string) (result Event, err error) { | ||
type EventsTag struct { | ||
EventID uint | ||
TagID uint | ||
} | ||
var ( | ||
tagIDs []uint | ||
typeOf = lo.Map(event.TypeOf, func(i EventTypeOf, _ int) string { return i.String() }) | ||
) | ||
|
||
result = Event{ | ||
Title: event.Title, | ||
Banner: event.Banner, | ||
Description: event.Description, | ||
Href: event.Href, | ||
TypeOf: append(pq.StringArray{}, typeOf...), | ||
BeginDate: event.BeginDate, | ||
EndDate: event.EndDate, | ||
UserID: user.ID, | ||
} | ||
|
||
err = e.db.Transaction(func(tx *gorm.DB) (er error) { | ||
if er = tx.Create(&result).Error; er != nil { | ||
slog.ErrorContext(ctx, "Fail to create event", "error", er.Error()) | ||
return er | ||
} | ||
if er = tx.Table("tags").Select("id").Where("tag in = ?", tags).Find(&tagIDs).Error; er != nil { | ||
slog.ErrorContext(ctx, "Fail to find tags", "error", er.Error()) | ||
return er | ||
} | ||
if len(tagIDs) != len(tags) { | ||
slog.ErrorContext(ctx, "Some tags ware not found in the database", "tags_requested", tags, "ids_found", tagIDs) | ||
return errors.New("unable to find a match for all the requested tags") | ||
} | ||
for _, tagID := range tagIDs { | ||
eventTag := EventsTag{ | ||
EventID: result.ID, | ||
TagID: tagID, | ||
} | ||
if er = tx.Create(&eventTag).Error; er != nil { | ||
slog.ErrorContext(ctx, "Fail to create join of event and tag", "error", er.Error(), "event", result, "tag_id", tagID) | ||
return er | ||
} | ||
} | ||
|
||
return nil | ||
}) | ||
|
||
return | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1 @@ | ||
package event |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters