Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion src/mappers/event_mapper.go
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,7 @@ func CreateEventToDbCreateEventParams(input types.CreateEvent) database.CreateEv
Valid: input.Description != "",
},
Budget: fmt.Sprintf("%f", input.Budget),
InvitationMessage: input.InviteMessage,
InvitationMessage: input.InvitationMessage,
DrawAt: input.DrawAt,
CloseAt: input.CloseAt,
}
Expand Down
39 changes: 18 additions & 21 deletions src/services/event_service.go
Original file line number Diff line number Diff line change
Expand Up @@ -5,7 +5,6 @@ import (
"fmt"

"github.com/giftxtrade/api/src/database/jet/postgres/public/table"
"github.com/giftxtrade/api/src/mappers"
"github.com/giftxtrade/api/src/types"
"github.com/go-jet/jet/v2/postgres"
)
Expand Down Expand Up @@ -83,35 +82,33 @@ func (s *EventService) FindEventById(ctx context.Context, user types.User, event
return event, err
}

func (s *EventService) CreateEvent(ctx context.Context, user *types.User, input types.CreateEvent) (types.Event, error) {
tx, err := s.DB.BeginTx(ctx, nil)
if err != nil {
tx.Rollback()
return types.Event{}, fmt.Errorf("could not process. error with database transaction")
}
q := s.Querier.WithTx(tx)
defer q.Close()
func (s *EventService) CreateEvent(ctx context.Context, user *types.User, input types.CreateEvent) (event types.Event, err error) {
s.TX, err = s.DB.BeginTx(ctx, nil)
defer s.TX.Rollback()

// create new event in transaction scope
new_event, err := q.CreateEvent(ctx, mappers.CreateEventToDbCreateEventParams(input))
if err != nil {
tx.Rollback()
qb := table.Event.INSERT(
table.Event.Name,
table.Event.Description,
table.Event.Budget,
table.Event.InvitationMessage,
table.Event.DrawAt,
table.Event.CloseAt,
).MODEL(input).RETURNING(table.Event.AllColumns)
if err = qb.QueryContext(ctx, s.TX, &event); err != nil {
return types.Event{}, fmt.Errorf("could not create event")
}

// create participants for event in transaction scope
participants, err := s.ParticipantService.BulkCreateParticipant(tx, ctx, user, &new_event, input.Participants)
s.ParticipantService.TX = s.TX
participants, err := s.ParticipantService.BulkCreateParticipant(ctx, user, &event, input.Participants)
if err != nil {
tx.Rollback()
return types.Event{}, err
}

// commit all changes! create event, and all participants
if tx.Commit() != nil {
tx.Rollback()
if s.TX.Commit() != nil {
return types.Event{}, fmt.Errorf("could not commit transaction")
}
// build new event dto
mapped_event := mappers.DbEventToEvent(new_event, participants, nil)
return mapped_event, nil
// TODO: email participants?
event.Participants = participants
return event, nil
}
58 changes: 29 additions & 29 deletions src/services/participant_service.go
Original file line number Diff line number Diff line change
Expand Up @@ -2,55 +2,55 @@ package services

import (
"context"
"database/sql"
"fmt"

"github.com/giftxtrade/api/src/database"
"github.com/giftxtrade/api/src/mappers"
"github.com/giftxtrade/api/src/database/jet/postgres/public/table"
"github.com/giftxtrade/api/src/types"
"github.com/go-jet/jet/v2/qrm"
)

type ParticipantService struct {
ServiceBase
}

func (s *ParticipantService) BulkCreateParticipant(
tx *sql.Tx, ctx context.Context,
ctx context.Context,
user *types.User,
event *database.Event,
event *types.Event,
input []types.CreateParticipant,
) ([]types.Participant, error) {
q := s.Querier.WithTx(tx)
defer q.Close()

found_creator_participant := false
participants := make([]types.Participant, len(input))
) (participants []types.Participant, err error) {
found_owner_participant := false
for i, p := range input {
data := mappers.CreateParticipantToDbCreateParticipantParams(p, event)
if p.Organizer && p.Email == user.Email {
found_creator_participant = true
data.UserID = sql.NullInt64{
Valid: true,
Int64: user.ID,
}
data.Accepted = true
}

new_participant, err := q.CreateParticipant(ctx, data)
if err != nil {
tx.Rollback()
return nil, fmt.Errorf("could not create participant %s (%s)", p.Name, p.Email)
found_owner_participant = true
input[i].UserID = &user.ID
}
participants[i] = mappers.DbParticipantToParticipant(new_participant, event, nil)
input[i].EventID = event.ID
}

if !found_creator_participant {
tx.Rollback()
if !found_owner_participant {
return nil, fmt.Errorf(
"%s (%s) must be in the participant list and have the organizer field set to 'true'",
user.Name,
user.Email,
)
}
return participants, nil

qb := table.Participant.
INSERT(
table.Participant.Email,
table.Participant.Name,
table.Participant.Address,
table.Participant.Organizer,
table.Participant.Participates,
table.Participant.UserID,
table.Participant.EventID,
).
MODELS(input).
RETURNING(table.Participant.AllColumns)
var db qrm.Queryable = s.DB
if s.TX != nil {
db = s.TX
}
err = qb.QueryContext(ctx, db, &participants)
return participants, err
}
1 change: 1 addition & 0 deletions src/services/service.go
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@ import (

type ServiceBase struct {
DB *sql.DB
TX *sql.Tx
Querier *database.Queries
Validator *validator.Validate
Tokens *types.Tokens
Expand Down
19 changes: 19 additions & 0 deletions src/tests/event_service_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -107,6 +107,25 @@ func TestEventService(t *testing.T) {
t.Fatal("event should not be created. main participant was not provided")
}
})

t.Run("no participant user", func(t *testing.T) {
event := types.CreateEvent{
Name: "Event with no matching user",
Budget: 100.00,
DrawAt: time.Now(),
CloseAt: time.Now().Add(time.Hour * 24 * 30),
Participants: append(create_participants(5), types.CreateParticipant{
Name: user_1.Name,
Email: "somerandomemail123@xyz.com",
Organizer: true,
Participates: true,
}),
}
_, err := event_service.CreateEvent(context.Background(), &user_1, event)
if err == nil {
t.Fatal("event should not be created. main participant is not provided")
}
})
})

t.Run("event authentication", func(t *testing.T) {
Expand Down
4 changes: 3 additions & 1 deletion src/types/dto.go
Original file line number Diff line number Diff line change
Expand Up @@ -132,6 +132,8 @@ type CreateParticipant struct {
Address string `json:"address,omitempty" validate:"omitempty"`
Organizer bool `json:"organizer,omitempty" validate:"omitempty"`
Participates bool `json:"participates,omitempty" validate:"omitempty"`
UserID *int64 `json:"-" validate:"omitempty"`
EventID int64 `json:"-" validate:"omitempty"`
}

type PatchParticipant struct {
Expand Down Expand Up @@ -169,7 +171,7 @@ type CreateEvent struct {
Name string `json:"name" validate:"required"`
Description string `json:"description,omitempty"`
Budget float32 `json:"budget" validate:"required,gte=1"`
InviteMessage string `json:"inviteMessage,omitempty"`
InvitationMessage string `json:"invitationMessage,omitempty"`
DrawAt time.Time `json:"drawAt" validate:"required"`
CloseAt time.Time `json:"closeAt" validate:"required"`
Participants []CreateParticipant `json:"participants,omitempty" validate:"omitempty"`
Expand Down