Skip to content

Commit

Permalink
Introduce event services and update models
Browse files Browse the repository at this point in the history
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
caioeverest committed Jan 27, 2024
1 parent 47a1604 commit 6a0c0d5
Show file tree
Hide file tree
Showing 3 changed files with 126 additions and 1 deletion.
124 changes: 124 additions & 0 deletions pkg/event/service_event.go
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
}
1 change: 1 addition & 0 deletions pkg/event/service_tag.go
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
package event
2 changes: 1 addition & 1 deletion ui/src/props/lending.generated.ts
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@ export interface Cfp {
CreatedAt: Time;
UpdatedAt: Time;
DeletedAt: DeletedAt;
EventID: number;
begin: Time;
end: Time;
href: string;
Expand Down Expand Up @@ -70,7 +71,6 @@ export interface Event {
type_of: string[];
begin: Time;
end: Time;
cfp_id: number;
user_id: number;
attendees: Attendee[];
tags: Tags[];
Expand Down

0 comments on commit 6a0c0d5

Please sign in to comment.