From 6af18e78cad750833caae139dcbfd97e11e6f56e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Tobias=20K=C3=A4stle?= Date: Mon, 23 Oct 2023 10:45:47 +0200 Subject: [PATCH 1/6] crew event participation --- dao/participation.go | 12 +++++++++++- models/participation.go | 28 ++++++++++------------------ 2 files changed, 21 insertions(+), 19 deletions(-) diff --git a/dao/participation.go b/dao/participation.go index e58f16e..fce17c2 100644 --- a/dao/participation.go +++ b/dao/participation.go @@ -11,7 +11,16 @@ import ( ) func ParticipationInsert(ctx context.Context, i *models.ParticipationCreate, token *vcapool.AccessToken) (result *models.Participation, err error) { - database := i.ParticipationDatabase(token) + + event := new(models.Event) + if err = EventCollection.FindOne( + ctx, + bson.D{{Key: "_id", Value: i.EventID}}, + event, + ); err != nil { + return + } + database := i.ParticipationDatabase(token, event) if err = ParticipationCollection.InsertOne(ctx, database); err != nil { return } @@ -104,6 +113,7 @@ func ParticipationUpdate(ctx context.Context, i *models.ParticipationUpdate, tok ); err != nil { return } + // TODO CHECK STATE PERMISSION if err = models.ParticipationUpdatePermission(token, event); err != nil { return } diff --git a/models/participation.go b/models/participation.go index 6c3c72c..2c3e711 100644 --- a/models/participation.go +++ b/models/participation.go @@ -157,13 +157,17 @@ func (i *Participation) ToContent() *vmod.Content { return content } -func (i *ParticipationCreate) ParticipationDatabase(token *vcapool.AccessToken) *ParticipationDatabase { +func (i *ParticipationCreate) ParticipationDatabase(token *vcapool.AccessToken, event *Event) *ParticipationDatabase { + eventStatus := "requested" + if event.TypeOfEvent == "crew_meeting" { + eventStatus = "confirmed" + } return &ParticipationDatabase{ ID: uuid.NewString(), UserID: token.ID, EventID: i.EventID, Comment: i.Comment, - Status: "requested", + Status: eventStatus, CrewID: token.CrewID, Modified: vmod.NewModified(), } @@ -178,28 +182,16 @@ func (i *ParticipationImport) ParticipationDatabase() *ParticipationDatabase { } } func (i *ParticipationStateRequest) IsRequested() bool { - if i.Status == "requested" { - return true - } - return false + return i.Status == "requested" } func (i *ParticipationStateRequest) IsConfirmed() bool { - if i.Status == "confirmed" { - return true - } - return false + return i.Status == "confirmed" } func (i *ParticipationStateRequest) IsWithdrawn() bool { - if i.Status == "withdrawn" { - return true - } - return false + return i.Status == "withdrawn" } func (i *ParticipationStateRequest) IsRejected() bool { - if i.Status == "rejected" { - return true - } - return false + return i.Status == "rejected" } func (i *ParticipationQuery) PermittedFilter(token *vcapool.AccessToken) bson.D { From abd6078943ef991a9bd70ba011d7545a1b228441 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Tobias=20K=C3=A4stle?= Date: Thu, 31 Oct 2024 00:09:20 +0100 Subject: [PATCH 2/6] pre commit --- dao/participation.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/dao/participation.go b/dao/participation.go index f7f2346..c75234c 100644 --- a/dao/participation.go +++ b/dao/participation.go @@ -18,7 +18,7 @@ func ParticipationInsert(ctx context.Context, i *models.ParticipationCreate, tok bson.D{{Key: "_id", Value: i.EventID}}, event, ); err != nil { - return + return } database := i.ParticipationDatabase(token, event) if err = ParticipationCollection.InsertOne(ctx, database); err != nil { From 54159218bd5aa03ee1bbbd3500a0424b334ed21d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Tobias=20K=C3=A4stle?= Date: Fri, 1 Nov 2024 13:48:10 +0100 Subject: [PATCH 3/6] added event history --- dao/connection.go | 6 +- dao/event.go | 38 ++++++++++-- dao/event_history.go | 28 +++++++++ dao/update_ticker.go | 77 ++++++++++++++++++++++++ models/artist.go | 12 ++++ models/event.go | 16 +++++ models/event_history.go | 129 ++++++++++++++++++++++++++++++++++++++++ 7 files changed, 300 insertions(+), 6 deletions(-) create mode 100644 dao/event_history.go create mode 100644 models/event_history.go diff --git a/dao/connection.go b/dao/connection.go index 15f279c..921ae70 100644 --- a/dao/connection.go +++ b/dao/connection.go @@ -41,8 +41,9 @@ var ( AvatarCollection *vmdb.Collection // PoolRoleCollection represents the database collection of the PoolRole Collection. - PoolRoleCollection *vmdb.Collection - PoolRoleHistoryCollection *vmdb.Collection + PoolRoleCollection *vmdb.Collection + PoolRoleHistoryCollection *vmdb.Collection + EventStateHistoryCollection *vmdb.Collection MailboxCollection *vmdb.Collection MessageCollection *vmdb.Collection @@ -111,6 +112,7 @@ func InitialDatabase() { // PoolRoleCollection represents the database collection of the PoolRole Collection. PoolRoleCollection = Database.Collection(models.PoolRoleCollection).CreateIndex("user_id", false).CreateMultiIndex(bson.D{{Key: "name", Value: 1}, {Key: "user_id", Value: 1}}, true) PoolRoleHistoryCollection = Database.Collection(models.PoolRoleHistoryCollection).CreateIndex("user_id", false).CreateIndex("crew_id", false) + EventStateHistoryCollection = Database.Collection(models.EventStateHistoryCollection).CreateIndex("user_id", false).CreateIndex("crew_id", false).CreateIndex("event_id", false).CreateIndex("new_state", false).CreateIndex("date", false) // MailboxCollection = Database.Collection(models.MailboxCollection) diff --git a/dao/event.go b/dao/event.go index 05419be..da05c34 100644 --- a/dao/event.go +++ b/dao/event.go @@ -38,6 +38,10 @@ func EventInsert(ctx context.Context, i *models.EventCreate, token *vcapool.Acce if err = EventCollection.AggregateOne(ctx, models.EventPipeline(token).Match(filter).Pipe, &result); err != nil { return } + history := result.NewEventStateHistory("", result.EventState.State, token) + if err = EventStateHistoryInsert(ctx, history, token); err != nil { + return + } return } @@ -183,6 +187,10 @@ func EventUpdate(ctx context.Context, i *models.EventUpdate, token *vcapool.Acce return } if event.EventState.State != result.EventState.State { + history := result.NewEventStateHistory(event.EventState.State, result.EventState.State, token) + if err = EventStateHistoryInsert(ctx, history, token); err != nil { + return + } if result.EventState.State == "canceled" { EventParticipantsNotification(ctx, result, "event_cancel") updateTaking := bson.D{{Key: "state.no_income", Value: true}} @@ -194,7 +202,7 @@ func EventUpdate(ctx context.Context, i *models.EventUpdate, token *vcapool.Acce if result.EventState.State == "published" || result.EventState.State == "canceled" || (result.EventState.State == "requested" && result.EventState.CrewConfirmation == "") { - EventStateNotification(ctx, result, "event_state") + EventStateNotification(ctx, result) } } else if event.StartAt != result.StartAt || event.EndAt != result.EndAt || @@ -203,7 +211,7 @@ func EventUpdate(ctx context.Context, i *models.EventUpdate, token *vcapool.Acce EventParticipantsNotification(ctx, result, "event_update") } if event.EventASPID != result.EventASPID && result.EventASPID != token.ID { - EventASPNotification(ctx, result, "event_asp") + EventASPNotification(ctx, result) } if event.EndAt != i.EndAt { updateTaking := bson.D{{Key: "date_of_taking", Value: i.EndAt}} @@ -374,7 +382,7 @@ func EventParticipantsNotification(ctx context.Context, i *models.Event, templat return } -func EventASPNotification(ctx context.Context, i *models.Event, template string) (err error) { +func EventASPNotification(ctx context.Context, i *models.Event) (err error) { if i.EventASPID == "" { return vcago.NewNotFound(models.EventCollection, i) @@ -385,6 +393,7 @@ func EventASPNotification(ctx context.Context, i *models.Event, template string) return } + template := "event_asp" mail := vcago.NewMailData(user.Email, "pool-backend", template, "pool", user.Country) mail.AddUser(user.User()) mail.AddContent(i.ToContent()) @@ -397,7 +406,7 @@ func EventASPNotification(ctx context.Context, i *models.Event, template string) return } -func EventStateNotification(ctx context.Context, i *models.Event, template string) (err error) { +func EventStateNotification(ctx context.Context, i *models.Event) (err error) { if i.EventASPID == "" { return vcago.NewNotFound(models.EventCollection, i) @@ -408,6 +417,7 @@ func EventStateNotification(ctx context.Context, i *models.Event, template strin return } + template := "event_state" mail := vcago.NewMailData(eventAps.Email, "pool-backend", template, "pool", eventAps.Country) mail.AddUser(eventAps.User()) mail.AddContent(i.ToContent()) @@ -418,3 +428,23 @@ func EventStateNotification(ctx context.Context, i *models.Event, template strin //vcago.Nats.Publish("system.notification.job", notification) return } + +func EventHistoryAdminNotification(ctx context.Context, data []models.EventStateHistoryNotification) (err error) { + mail := vcago.NewMailData("netzwerk@vivaconagua.org", "pool-backend", "events_published", "pool", "de") + mail.AddContent(models.EventHistoryAdminContent(data)) + vcago.Nats.Publish("system.mail.job", mail) + + mail2 := vcago.NewMailData("festival@vivaconagua.org", "pool-backend", "events_published", "pool", "de") + mail2.AddContent(models.EventHistoryAdminContent(data)) + vcago.Nats.Publish("system.mail.job", mail2) + return +} + +func EventHistoryCrewNotification(ctx context.Context, data_collection map[string][]models.EventStateHistoryNotification) (err error) { + for email, data := range data_collection { + mail := vcago.NewMailData(email, "pool-backend", "events_crew_published", "pool", "de") + mail.AddContent(models.EventHistoryAdminContent(data)) + vcago.Nats.Publish("system.mail.job", mail) + } + return +} diff --git a/dao/event_history.go b/dao/event_history.go new file mode 100644 index 0000000..f7a7391 --- /dev/null +++ b/dao/event_history.go @@ -0,0 +1,28 @@ +package dao + +import ( + "context" + "pool-backend/models" + + "github.com/Viva-con-Agua/vcapool" +) + +func EventStateHistoryInsert(ctx context.Context, i *models.EventStateHistoryCreate, token *vcapool.AccessToken) (err error) { + if err = EventStateHistoryCollection.InsertOne(ctx, i); err != nil { + return + } + return +} + +func EventStateGet(ctx context.Context, i *models.EventStateHistoryQuery, token *vcapool.AccessToken) (result *[]models.EventStateHistory, list_size int64, err error) { + result = new([]models.EventStateHistory) + if err = EventStateHistoryCollection.Aggregate( + ctx, + models.EventStatePipeline().Match(i.Filter()).Pipe, + result, + ); err != nil { + return + } + list_size = int64(len(*result)) + return +} diff --git a/dao/update_ticker.go b/dao/update_ticker.go index 478a23f..c2b2d75 100644 --- a/dao/update_ticker.go +++ b/dao/update_ticker.go @@ -17,10 +17,14 @@ func UpdateTicker() { EventStateFinishTicker() EventStateClosedTicker() UserActiveStateTicker() + //SendWeeklyNotification() + SendWeeklyCrewNotification() go func() { for { select { case <-ticker.C: + //SendWeeklyNotification() + //SendWeeklyCrewNotification() EventStateFinishTicker() EventStateClosedTicker() UserActiveStateTicker() @@ -112,3 +116,76 @@ func UserActiveStateTicker() { } } + +// SendWeeklyNotification Send a notification mail to festival@ and netzwerk@ for all published events last 7 days +func SendWeeklyNotification() { + + h, _, _ := time.Now().Clock() + if time.Now().Weekday() != time.Monday { + return + } else if h < 9 || h >= 10 { + return + } + + filter := models.EventPublishedLastWeek() + + events := []models.EventStateHistory{} + pipeline := models.EventStatePipeline().Match(filter).Pipe + if err := EventStateHistoryCollection.Aggregate(context.Background(), pipeline, &events); err != nil { + log.Print(err) + } + + eventNotifications := []models.EventStateHistoryNotification{} + for _, e := range events { + eventNotifications = append(eventNotifications, models.EventStateHistoryNotification{ + EventID: e.EventID, + EventName: e.Event.Name, + EventCrew: e.Crew.Name, + EventStart: time.Unix(e.Event.StartAt, 0).Format("02.01.2006 15:04"), + EventArtist: models.ToArtistList(e.Event.Artists), + EventLocation: e.Event.GetLocation(), + PublishedDate: time.Unix(e.Date, 0).Format("02.01.2006"), + }) + } + + if err := EventHistoryAdminNotification(context.Background(), eventNotifications); err != nil { + log.Print(err) + + } +} + +// SendWeeklyCrewNotification Send a notification mail to each crew email address for all published events last 7 days +func SendWeeklyCrewNotification() { + + h, _, _ := time.Now().Clock() + if time.Now().Weekday() != time.Monday { + return + } else if h < 9 || h >= 10 { + return + } + + filter := models.EventPublishedLastWeek() + events := []models.EventStateHistory{} + pipeline := models.EventStatePipeline().Match(filter).Pipe + if err := EventStateHistoryCollection.Aggregate(context.Background(), pipeline, &events); err != nil { + log.Print(err) + } + m := make(map[string][]models.EventStateHistoryNotification) + for _, e := range events { + if e.CrewID == "" { + continue + } + m[e.Crew.Email] = append(m[e.Crew.Email], models.EventStateHistoryNotification{ + EventID: e.EventID, + EventName: e.Event.Name, + EventCrew: e.Crew.Name, + EventStart: time.Unix(e.Event.StartAt, 0).Format("02.01.2006 15:04"), + EventArtist: models.ToArtistList(e.Event.Artists), + EventLocation: e.Event.GetLocation(), + PublishedDate: time.Unix(e.Date, 0).Format("02.01.2006"), + }) + } + if err := EventHistoryCrewNotification(context.Background(), m); err != nil { + log.Print(err) + } +} diff --git a/models/artist.go b/models/artist.go index b27b59f..e4e0370 100644 --- a/models/artist.go +++ b/models/artist.go @@ -1,6 +1,8 @@ package models import ( + "strings" + "github.com/Viva-con-Agua/vcago" "github.com/Viva-con-Agua/vcago/vmdb" "github.com/Viva-con-Agua/vcago/vmod" @@ -51,6 +53,16 @@ func ArtistDeletePermission(token *vcapool.AccessToken) (err error) { return } +func ToArtistList(artists []Artist) string { + names := make([]string, len(artists)) + for i, artist := range artists { + names[i] = artist.Name + } + + result := strings.Join(names, ", ") + return result +} + func (i *ArtistCreate) Artist() *Artist { return &Artist{ ID: uuid.NewString(), diff --git a/models/event.go b/models/event.go index 00a7baf..8577ac9 100644 --- a/models/event.go +++ b/models/event.go @@ -1,6 +1,7 @@ package models import ( + "fmt" "strconv" "time" @@ -267,6 +268,7 @@ type ( Location struct { Name string `json:"name" bson:"name"` Street string `json:"street" bson:"street"` + Zip string `json:"zip" bson:"zip"` City string `json:"city" bson:"city"` Country string `json:"country" bson:"country"` CountryCode string `json:"country_code" bson:"country_code"` @@ -651,3 +653,17 @@ func (i *EventUpdate) EventStateValidation(token *vcapool.AccessToken, event *Ev } return } + +func (i *Event) GetLocation() string { + if i.Location.PlaceID != "" { + return fmt.Sprintf("%v, %v %v", i.Location.Name, i.Location.Zip, i.Location.City) + } + return fmt.Sprintf("Online: %v", i.MeetingURL) +} + +func (i *EventPublic) GetLocation() string { + if i.Location.PlaceID != "" { + return fmt.Sprintf("%v, %v %v", i.Location.Name, i.Location.Zip, i.Location.City) + } + return "Online" +} diff --git a/models/event_history.go b/models/event_history.go new file mode 100644 index 0000000..d5f73b3 --- /dev/null +++ b/models/event_history.go @@ -0,0 +1,129 @@ +package models + +import ( + "fmt" + "time" + + "github.com/Viva-con-Agua/vcago" + "github.com/Viva-con-Agua/vcago/vmdb" + "github.com/Viva-con-Agua/vcago/vmod" + "github.com/Viva-con-Agua/vcapool" + "github.com/google/uuid" + "go.mongodb.org/mongo-driver/bson" +) + +type EventStateHistoryCreate struct { + ID string `bson:"_id" json:"id"` + UserID string `json:"user_id" bson:"user_id"` + CrewID string `json:"crew_id" bson:"crew_id"` + EventID string `json:"event_id" bson:"event_id"` + Date int64 `json:"date" bson:"date"` + OldState string `json:"old_state" bson:"old_state"` + NewState string `json:"new_state" bson:"new_state"` +} + +type EventStateHistoryQuery struct { + ID []string `query:"id" qs:"id"` + UserID string `query:"user_id" qs:"user_id"` + CrewID string `query:"crew_id" qs:"crew_id"` + EventID string `query:"event_id" qs:"event_id"` + DateTo string `query:"date_to" qs:"date_to"` + DateFrom string `query:"date_from" qs:"date_from"` + OldState string `query:"old_state" qs:"old_state"` + NewState string `query:"new_state" qs:"new_state"` + Search string `query:"search"` + SortField string `query:"sort"` + SortDirection string `query:"sort_dir"` + Limit int64 `query:"limit"` + Skip int64 `query:"skip"` + FullCount string `query:"full_count"` +} + +type EventStateHistory struct { + ID string `bson:"_id" json:"id"` + UserID string `json:"user_id" bson:"user_id"` + User UserMinimal `json:"user" bson:"user"` + CrewID string `json:"crew_id" bson:"crew_id"` + Crew CrewSimple `json:"crew" bson:"crew"` + EventID string `json:"event_id" bson:"event_id"` + Event EventPublic `json:"event" bson:"event"` + Date int64 `json:"date" bson:"date"` + OldState string `json:"old_state" bson:"old_state"` + NewState string `json:"new_state" bson:"new_state"` +} + +type EventStateHistoryNotification struct { + EventID string `json:"event_id" bson:"event_id"` + EventName string `json:"event_name" bson:"event_name"` + EventStart string `json:"event_start" bson:"event_start"` + EventCrew string `json:"event_crew" bson:"event_crew"` + EventArtist string `json:"event_artist" bson:"event_artist"` + EventLocation string `json:"event_location" bson:"event_location"` + PublishedDate string `json:"published_date" bson:"published_date"` +} + +var EventStateHistoryCollection = "eventstate_history" + +func EventStatePipeline() (pipe *vmdb.Pipeline) { + pipe = vmdb.NewPipeline() + pipe.LookupUnwind(EventCollection, "event_id", "_id", "event") + pipe.Lookup(ArtistCollection, "event.artist_ids", "_id", "event.artists") + pipe.LookupUnwind(UserCollection, "user_id", "_id", "user") + pipe.LookupUnwind(CrewCollection, "crew_id", "_id", "crew") + return +} + +func EventStateHistoryPermission(token *vcapool.AccessToken) (err error) { + if !(token.Roles.Validate("employee;admin") || token.PoolRoles.Validate(ASPRole)) { + return vcago.NewPermissionDenied(PoolRoleHistoryCollection) + } + return +} + +func (i *Event) NewEventStateHistory(old string, new string, token *vcapool.AccessToken) *EventStateHistoryCreate { + return &EventStateHistoryCreate{ + ID: uuid.NewString(), + UserID: token.ID, + CrewID: i.CrewID, + EventID: i.ID, + OldState: old, + NewState: new, + Date: time.Now().Unix(), + } +} + +func (i *EventStateHistoryQuery) Filter() bson.D { + filter := vmdb.NewFilter() + filter.EqualStringList("_id", i.ID) + filter.EqualString("user_id", i.UserID) + filter.EqualString("event_id", i.EventID) + filter.EqualString("crew_id", i.CrewID) + filter.EqualString("old_state", i.OldState) + filter.EqualString("new_state", i.NewState) + filter.GteInt64("date", i.DateFrom) + filter.LteInt64("date", i.DateTo) + filter.SearchString([]string{"_id", "name", "crew.name"}, i.Search) + + return filter.Bson() +} + +func EventPublishedLastWeek() bson.D { + filter := vmdb.NewFilter() + + week := 7 * 24 + // if we had fix number of units to subtract, we can use following line instead fo above 2 lines. It does type convertion automatically. + // then := now.Add(-10 * time.Minute) + fmt.Printf("7 week ago: %v\n ", time.Now().Add(time.Duration(-week)*time.Hour)) + + filter.GteInt64("date", fmt.Sprint(time.Now().Add(time.Duration(-week)*time.Hour).Unix())) + filter.LteInt64("date", fmt.Sprint(time.Now().Unix())) + return filter.Bson() +} + +func EventHistoryAdminContent(data []EventStateHistoryNotification) *vmod.Content { + content := &vmod.Content{ + Fields: make(map[string]interface{}), + } + content.Fields["Events"] = data + return content +} From 3c22b613c325580b000cf2b534c60ede7a14c69b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Tobias=20K=C3=A4stle?= Date: Mon, 4 Nov 2024 09:17:00 +0100 Subject: [PATCH 4/6] naming --- dao/event_history.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/dao/event_history.go b/dao/event_history.go index f7a7391..9b2664e 100644 --- a/dao/event_history.go +++ b/dao/event_history.go @@ -14,7 +14,7 @@ func EventStateHistoryInsert(ctx context.Context, i *models.EventStateHistoryCre return } -func EventStateGet(ctx context.Context, i *models.EventStateHistoryQuery, token *vcapool.AccessToken) (result *[]models.EventStateHistory, list_size int64, err error) { +func EventStateHistoryGet(ctx context.Context, i *models.EventStateHistoryQuery, token *vcapool.AccessToken) (result *[]models.EventStateHistory, list_size int64, err error) { result = new([]models.EventStateHistory) if err = EventStateHistoryCollection.Aggregate( ctx, From 469f1068043b930ac9a944f8c0234e8f91b2c109 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Tobias=20K=C3=A4stle?= Date: Mon, 4 Nov 2024 09:50:34 +0100 Subject: [PATCH 5/6] updated count --- dao/event.go | 32 +++++++++++++++----------------- dao/event_history.go | 13 +++++++++++-- dao/users.go | 18 ++++++++---------- 3 files changed, 34 insertions(+), 29 deletions(-) diff --git a/dao/event.go b/dao/event.go index da05c34..1c0fa2c 100644 --- a/dao/event.go +++ b/dao/event.go @@ -7,10 +7,10 @@ import ( "github.com/Viva-con-Agua/vcago" "github.com/Viva-con-Agua/vcago/vmdb" + "github.com/Viva-con-Agua/vcago/vmod" "github.com/Viva-con-Agua/vcapool" "github.com/labstack/gommon/log" "go.mongodb.org/mongo-driver/bson" - "go.mongodb.org/mongo-driver/mongo/options" ) func EventInsert(ctx context.Context, i *models.EventCreate, token *vcapool.AccessToken) (result *models.Event, err error) { @@ -56,14 +56,14 @@ func EventGet(i *models.EventQuery, token *vcapool.AccessToken) (result *[]model if err = EventCollection.Aggregate(ctx, pipeline, result); err != nil { return } - opts := options.Count().SetHint("_id_") - if i.FullCount != "true" { - opts.SetSkip(i.Skip).SetLimit(i.Limit) - } - if cursor, cErr := EventViewCollection.Collection.CountDocuments(ctx, filter, opts); cErr != nil { - list_size = 0 + + count := vmod.Count{} + var cErr error + if cErr = EventCollection.AggregateOne(ctx, pipeline, &count); cErr != nil { + print(cErr) + list_size = 1 } else { - list_size = cursor + list_size = int64(count.Total) } return } @@ -127,16 +127,14 @@ func EventGetPublic(i *models.EventQuery) (result *[]models.EventPublic, list_si if err = EventCollection.Aggregate(ctx, pipeline, result); err != nil { return } - ctx, cancel = context.WithTimeout(context.Background(), 10*time.Second) - defer cancel() - opts := options.Count().SetHint("_id_") - if i.FullCount != "true" { - opts.SetSkip(i.Skip).SetLimit(i.Limit) - } - if cursor, cErr := PublicEventViewCollection.Collection.CountDocuments(ctx, filter, opts); cErr != nil { - list_size = 0 + + count := vmod.Count{} + var cErr error + if cErr = EventCollection.AggregateOne(ctx, pipeline, &count); cErr != nil { + print(cErr) + list_size = 1 } else { - list_size = cursor + list_size = int64(count.Total) } return } diff --git a/dao/event_history.go b/dao/event_history.go index 9b2664e..5a46a4a 100644 --- a/dao/event_history.go +++ b/dao/event_history.go @@ -4,6 +4,7 @@ import ( "context" "pool-backend/models" + "github.com/Viva-con-Agua/vcago/vmod" "github.com/Viva-con-Agua/vcapool" ) @@ -16,13 +17,21 @@ func EventStateHistoryInsert(ctx context.Context, i *models.EventStateHistoryCre func EventStateHistoryGet(ctx context.Context, i *models.EventStateHistoryQuery, token *vcapool.AccessToken) (result *[]models.EventStateHistory, list_size int64, err error) { result = new([]models.EventStateHistory) + pipeline := models.EventStatePipeline().Match(i.Filter()).Count().Pipe if err = EventStateHistoryCollection.Aggregate( ctx, - models.EventStatePipeline().Match(i.Filter()).Pipe, + pipeline, result, ); err != nil { return } - list_size = int64(len(*result)) + count := vmod.Count{} + var cErr error + if cErr = EventStateHistoryCollection.AggregateOne(ctx, pipeline, &count); cErr != nil { + print(cErr) + list_size = 1 + } else { + list_size = int64(count.Total) + } return } diff --git a/dao/users.go b/dao/users.go index 562e401..52d925d 100644 --- a/dao/users.go +++ b/dao/users.go @@ -6,10 +6,10 @@ import ( "pool-backend/models" "time" + "github.com/Viva-con-Agua/vcago/vmod" "github.com/Viva-con-Agua/vcapool" "go.mongodb.org/mongo-driver/bson" - "go.mongodb.org/mongo-driver/mongo/options" ) func UserInsert(ctx context.Context, i *models.UserDatabase) (result *models.User, err error) { @@ -48,16 +48,14 @@ func UsersGet(i *models.UserQuery, token *vcapool.AccessToken) (result *[]models if err = UserCollection.Aggregate(ctx, pipeline, result); err != nil { return } - ctx, cancel = context.WithTimeout(context.Background(), 10*time.Second) - defer cancel() - opts := options.Count().SetHint("_id_") - if i.FullCount != "true" { - opts.SetSkip(i.Skip).SetLimit(i.Limit) - } - if cursor, cErr := UserViewCollection.Collection.CountDocuments(ctx, filter, opts); cErr != nil { - list_size = 0 + + count := vmod.Count{} + var cErr error + if cErr = UserViewCollection.AggregateOne(ctx, pipeline, &count); cErr != nil { + print(cErr) + list_size = 1 } else { - list_size = cursor + list_size = int64(count.Total) } return } From c5ab3a1392f22474b11439bc72090a0f4e7436be Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Tobias=20K=C3=A4stle?= Date: Thu, 7 Nov 2024 10:24:58 +0100 Subject: [PATCH 6/6] fixed counts, added default_asp to organisations --- dao/event.go | 5 ++--- dao/event_history.go | 6 +++--- dao/organisation.go | 3 ++- dao/users.go | 2 +- models/organisation.go | 13 +++++++++++++ models/user.go | 38 +++++++++++++++++++++++--------------- 6 files changed, 44 insertions(+), 23 deletions(-) diff --git a/dao/event.go b/dao/event.go index a73cd8c..89bdbcb 100644 --- a/dao/event.go +++ b/dao/event.go @@ -65,8 +65,7 @@ func EventGet(i *models.EventQuery, token *models.AccessToken) (result *[]models count := vmod.Count{} var cErr error - if cErr = EventCollection.AggregateOne(ctx, pipeline, &count); cErr != nil { - print(cErr) + if cErr = EventCollection.AggregateOne(ctx, models.EventPipeline(token).Match(filter).Count().Pipe, &count); cErr != nil { list_size = 1 } else { list_size = int64(count.Total) @@ -136,7 +135,7 @@ func EventGetPublic(i *models.EventQuery) (result *[]models.EventPublic, list_si count := vmod.Count{} var cErr error - if cErr = EventCollection.AggregateOne(ctx, pipeline, &count); cErr != nil { + if cErr = EventCollection.AggregateOne(ctx, models.EventPipelinePublic().Match(filter).Count().Pipe, &count); cErr != nil { print(cErr) list_size = 1 } else { diff --git a/dao/event_history.go b/dao/event_history.go index 7d3f06f..f1efd94 100644 --- a/dao/event_history.go +++ b/dao/event_history.go @@ -16,17 +16,17 @@ func EventStateHistoryInsert(ctx context.Context, i *models.EventStateHistoryCre func EventStateHistoryGet(ctx context.Context, i *models.EventStateHistoryQuery, token *models.AccessToken) (result *[]models.EventStateHistory, list_size int64, err error) { result = new([]models.EventStateHistory) - pipeline := models.EventStatePipeline().Match(i.Filter()).Count().Pipe + pipeline := models.EventStatePipeline().Match(i.Filter()) if err = EventStateHistoryCollection.Aggregate( ctx, - pipeline, + pipeline.Pipe, result, ); err != nil { return } count := vmod.Count{} var cErr error - if cErr = EventStateHistoryCollection.AggregateOne(ctx, pipeline, &count); cErr != nil { + if cErr = EventStateHistoryCollection.AggregateOne(ctx, pipeline.Count().Pipe, &count); cErr != nil { print(cErr) list_size = 1 } else { diff --git a/dao/organisation.go b/dao/organisation.go index 1abad09..bd0d4f1 100644 --- a/dao/organisation.go +++ b/dao/organisation.go @@ -21,7 +21,8 @@ func OrganisationInsert(ctx context.Context, i *models.OrganisationCreate, token func OrganisationGet(ctx context.Context, i *models.OrganisationQuery) (result *[]models.Organisation, err error) { filter := i.Filter() result = new([]models.Organisation) - if err = OrganisationCollection.Find(ctx, filter, result); err != nil { + + if err = OrganisationCollection.Aggregate(ctx, models.OrganisationPipeline().Match(filter).Pipe, result); err != nil { return } return diff --git a/dao/users.go b/dao/users.go index 808b97d..a988369 100644 --- a/dao/users.go +++ b/dao/users.go @@ -51,7 +51,7 @@ func UsersGet(i *models.UserQuery, token *models.AccessToken) (result *[]models. count := vmod.Count{} var cErr error - if cErr = UserViewCollection.AggregateOne(ctx, pipeline, &count); cErr != nil { + if cErr = UserViewCollection.AggregateOne(ctx, models.UserPermittedPipeline(token).Match(filter).Count().Pipe, &count); cErr != nil { print(cErr) list_size = 1 } else { diff --git a/models/organisation.go b/models/organisation.go index 804e35d..ba97322 100644 --- a/models/organisation.go +++ b/models/organisation.go @@ -11,17 +11,21 @@ type ( OrganisationCreate struct { Name string `json:"name" bson:"name" validate:"required"` Abbreviation string `json:"abbreviation" bson:"abbreviation"` + DefaultAspID string `json:"default_asp_id" bson:"default_asp_id"` Email string `json:"email" bson:"email"` } Organisation struct { ID string `json:"id" bson:"_id"` Name string `json:"name" bson:"name"` Abbreviation string `json:"abbreviation" bson:"abbreviation"` + DefaultAspID string `json:"default_asp_id" bson:"default_asp_id"` + DefaultAsp UserContact `json:"default_asp" bson:"default_asp"` Email string `json:"email" bson:"email"` Modified vmod.Modified `json:"modified" bson:"modified"` } OrganisationUpdate struct { ID string `json:"id" bson:"_id"` + DefaultAspID string `json:"default_asp_id" bson:"default_asp_id"` Abbreviation string `json:"abbreviation" bson:"abbreviation"` Email string `json:"email" bson:"email"` Name string `json:"name" bson:"name"` @@ -33,6 +37,7 @@ type ( ID string `query:"id" qs:"id"` Name string `query:"name" qs:"name"` Abbreviation string `query:"abbreviation" qs:"abbreviation"` + DefaultAspID string `json:"default_asp_id" bson:"default_asp_id"` Email string `query:"email" qs:"email"` UpdatedTo string `query:"updated_to" qs:"updated_to"` UpdatedFrom string `query:"updated_from" qs:"updated_from"` @@ -43,11 +48,19 @@ type ( var OrganisationCollection = "organisations" +func OrganisationPipeline() (pipe *vmdb.Pipeline) { + pipe = vmdb.NewPipeline() + pipe.LookupUnwind(UserCollection, "default_asp_id", "_id", "default_asp") + pipe.LookupUnwind(ProfileCollection, "default_asp_id", "user_id", "default_asp.profile") + return +} + func (i *OrganisationCreate) Organisation() *Organisation { return &Organisation{ ID: uuid.NewString(), Name: i.Name, Email: i.Email, + DefaultAspID: i.DefaultAspID, Abbreviation: i.Abbreviation, Modified: vmod.NewModified(), } diff --git a/models/user.go b/models/user.go index 156b3e5..f86944b 100644 --- a/models/user.go +++ b/models/user.go @@ -54,9 +54,9 @@ type ( } User struct { ID string `json:"id,omitempty" bson:"_id"` - Email string `json:"email" bson:"email" validate:"required,email"` - FirstName string `bson:"first_name" json:"first_name" validate:"required"` - LastName string `bson:"last_name" json:"last_name" validate:"required"` + Email string `json:"email" bson:"email" ` + FirstName string `bson:"first_name" json:"first_name" ` + LastName string `bson:"last_name" json:"last_name" ` FullName string `bson:"full_name" json:"full_name"` DisplayName string `bson:"display_name" json:"display_name"` Roles vmod.RoleList `json:"system_roles" bson:"system_roles"` @@ -83,9 +83,9 @@ type ( } ListUser struct { ID string `json:"id,omitempty" bson:"_id"` - Email string `json:"email" bson:"email" validate:"required,email"` - FirstName string `bson:"first_name" json:"first_name" validate:"required"` - LastName string `bson:"last_name" json:"last_name" validate:"required"` + Email string `json:"email" bson:"email" ` + FirstName string `bson:"first_name" json:"first_name" ` + LastName string `bson:"last_name" json:"last_name" ` FullName string `bson:"full_name" json:"full_name"` DisplayName string `bson:"display_name" json:"display_name"` Roles vmod.RoleList `json:"system_roles" bson:"system_roles"` @@ -103,9 +103,9 @@ type ( } UserParticipant struct { ID string `json:"id,omitempty" bson:"_id"` - Email string `json:"email" bson:"email" validate:"required,email"` - FirstName string `bson:"first_name" json:"first_name" validate:"required"` - LastName string `bson:"last_name" json:"last_name" validate:"required"` + Email string `json:"email" bson:"email" ` + FirstName string `bson:"first_name" json:"first_name" ` + LastName string `bson:"last_name" json:"last_name" ` FullName string `bson:"full_name" json:"full_name"` DisplayName string `bson:"display_name" json:"display_name"` Country string `bson:"country" json:"country"` @@ -116,8 +116,8 @@ type ( } UserPublic struct { ID string `json:"id,omitempty" bson:"_id"` - FirstName string `bson:"first_name" json:"first_name" validate:"required"` - LastName string `bson:"last_name" json:"last_name" validate:"required"` + FirstName string `bson:"first_name" json:"first_name" ` + LastName string `bson:"last_name" json:"last_name" ` FullName string `bson:"full_name" json:"full_name"` DisplayName string `bson:"display_name" json:"display_name"` Roles vmod.RoleList `json:"system_roles" bson:"system_roles"` @@ -136,15 +136,15 @@ type ( } UserMinimal struct { ID string `json:"id,omitempty" bson:"_id"` - FirstName string `bson:"first_name" json:"first_name" validate:"required"` - LastName string `bson:"last_name" json:"last_name" validate:"required"` + FirstName string `bson:"first_name" json:"first_name" ` + LastName string `bson:"last_name" json:"last_name" ` FullName string `bson:"full_name" json:"full_name"` DisplayName string `bson:"display_name" json:"display_name"` } UserBasic struct { ID string `json:"id,omitempty" bson:"_id"` - FirstName string `bson:"first_name" json:"first_name" validate:"required"` - LastName string `bson:"last_name" json:"last_name" validate:"required"` + FirstName string `bson:"first_name" json:"first_name" ` + LastName string `bson:"last_name" json:"last_name" ` FullName string `bson:"full_name" json:"full_name"` Profile ProfileMinimal `bson:"profile" json:"profile"` DisplayName string `bson:"display_name" json:"display_name"` @@ -153,6 +153,14 @@ type ( PoolRoles vmod.RoleList `json:"pool_roles" bson:"pool_roles,omitempty"` NVM NVM `json:"nvm" bson:"nvm,omitempty"` } + UserContact struct { + ID string `json:"id,omitempty" bson:"_id"` + Email string `json:"email" bson:"email" ` + FirstName string `bson:"first_name" json:"first_name" ` + LastName string `bson:"last_name" json:"last_name" ` + FullName string `bson:"full_name" json:"full_name"` + Profile ProfileMinimal `bson:"profile" json:"profile"` + } UserParam struct { ID string `param:"id"` }