diff --git a/go.mod b/go.mod index 66b43ee..357eb5d 100644 --- a/go.mod +++ b/go.mod @@ -8,7 +8,7 @@ replace git.coopgo.io/coopgo-platform/groups-management => ../../coopgo-platform // replace git.coopgo.io/coopgo-platform/fleets => ../../coopgo-platform/fleets/ -// replace git.coopgo.io/coopgo-platform/agenda => ../../coopgo-platform/agenda/ +replace git.coopgo.io/coopgo-platform/agenda => ../../coopgo-platform/agenda/ // replace git.coopgo.io/coopgo-platform/emailing => ../../coopgo-platform/emailing/ diff --git a/handlers/application/administration.go b/handlers/application/administration.go index 7c38415..7aed121 100644 --- a/handlers/application/administration.go +++ b/handlers/application/administration.go @@ -10,10 +10,14 @@ import ( "sort" "time" + "git.coopgo.io/coopgo-apps/parcoursmob/utils/identification" "git.coopgo.io/coopgo-apps/parcoursmob/utils/sorting" + agenda "git.coopgo.io/coopgo-platform/agenda/grpcapi" + agendastorage "git.coopgo.io/coopgo-platform/agenda/storage" fleets "git.coopgo.io/coopgo-platform/fleets/grpcapi" - "git.coopgo.io/coopgo-platform/fleets/storage" + fleetsstorage "git.coopgo.io/coopgo-platform/fleets/storage" groupsmanagement "git.coopgo.io/coopgo-platform/groups-management/grpcapi" + "git.coopgo.io/coopgo-platform/groups-management/storage" groupstorage "git.coopgo.io/coopgo-platform/groups-management/storage" accounts "git.coopgo.io/coopgo-platform/mobility-accounts/grpcapi" mobilityaccountsstorage "git.coopgo.io/coopgo-platform/mobility-accounts/storage" @@ -64,8 +68,39 @@ func (h *ApplicationHandler) Administration(w http.ResponseWriter, r *http.Reque } sort.Sort(sorting.GroupsByName(groups)) + ////////////////////////////////////add event//////////////////////////////////////////// + rresp, err := h.services.GRPC.Agenda.GetEvents(context.TODO(), &agenda.GetEventsRequest{ + Namespaces: []string{"parcoursmob_dispositifs"}, + }) - h.Renderer.Administration(w, r, accounts, beneficiaries, groups, bookings) + if err != nil { + fmt.Println(err) + w.WriteHeader(http.StatusInternalServerError) + return + } + + responses := []agendastorage.Event{} + + groupids := []string{} + for _, e := range rresp.Events { + groupids = append(groupids, e.Owners...) + responses = append(responses, e.ToStorageType()) + } + + sort.Sort(sorting.EventsByStartdate(responses)) + + groupsresp, err := h.services.GRPC.GroupsManagement.GetGroupsBatch(context.TODO(), &groupsmanagement.GetGroupsBatchRequest{ + Groupids: groupids, + }) + groupps := map[string]any{} + + if err == nil { + for _, g := range groupsresp.Groups { + groupps[g.Id] = g.ToStorageType() + } + } + + h.Renderer.Administration(w, r, accounts, beneficiaries, groups, bookings, responses) } func (h *ApplicationHandler) AdministrationCreateGroup(w http.ResponseWriter, r *http.Request) { @@ -333,29 +368,83 @@ func (h *ApplicationHandler) AdministrationGroupInviteMember(w http.ResponseWrit return } +func filteVehicle(r *http.Request, v *fleets.Vehicle) bool { + g := r.Context().Value(identification.GroupKey) + if g == nil { + return false + } + + group := g.(storage.Group) + + for _, n := range v.Administrators { + if n == group.ID { + return true + } + } + + return false +} + func (h ApplicationHandler) AdminStatVehicles(w http.ResponseWriter, r *http.Request) { - request := &fleets.GetBookingsRequest{} - resp, err := h.services.GRPC.Fleets.GetBookings(context.TODO(), request) + bookings := []fleetsstorage.Booking{} + administrators := []string{} + reequest := &fleets.GetVehiclesRequest{ + Namespaces: []string{"parcoursmob"}, + } + reesp, err := h.services.GRPC.Fleets.GetVehicles(context.TODO(), reequest) if err != nil { fmt.Println(err) - w.WriteHeader(http.StatusNotFound) - return + w.WriteHeader(http.StatusInternalServerError) } - bookings := []storage.Booking{} + vehicles := []fleetsstorage.Vehicle{} + for _, vehiicle := range reesp.Vehicles { + + v := vehiicle.ToStorageType() + adminfound := false + for _, a := range administrators { + if a == v.Administrators[0] { + adminfound = true + break + } + } + if !adminfound { + administrators = append(administrators, v.Administrators[0]) + } + + vehicleBookings := []fleetsstorage.Booking{} + for _, b := range v.Bookings { + if b.Unavailableto.After(time.Now()) { + vehicleBookings = append(vehicleBookings, b) + } + } + + v.Bookings = vehicleBookings + + vehicles = append(vehicles, v) - for _, b := range resp.Bookings { - booking := b.ToStorageType() - bookings = append(bookings, booking) } + groups := map[string]any{} + if len(administrators) > 0 { + admingroups, err := h.services.GRPC.GroupsManagement.GetGroupsBatch(context.TODO(), &groupsmanagement.GetGroupsBatchRequest{ + Groupids: administrators, + }) + if err != nil { + fmt.Println(err) + w.WriteHeader(http.StatusInternalServerError) + return + } + + for _, g := range admingroups.Groups { + groups[g.Id] = g.ToStorageType() + } + + } + sort.Sort(sorting.VehiclesByLicencePlate(vehicles)) sort.Sort(sorting.BookingsByStartdate(bookings)) - - vehicles, _ := h.services.GetVehiclesMap() - groups, _ := h.services.GetGroupsMap() - - h.Renderer.VehicleBookingsList(w, r, bookings, vehicles, groups) + h.Renderer.AdminStatVehicles(w, r, vehicles, bookings, groups) } func (h *ApplicationHandler) members() ([]*accounts.Account, error) { @@ -395,3 +484,49 @@ func (h *ApplicationHandler) groupmembers(groupid string) (groupmembers []mobili return groupmembers, admins, err } + +func (h ApplicationHandler) AdminStatBeneficaires(w http.ResponseWriter, r *http.Request) { + beneficiaries, err := h.services.GetBeneficiaries() + if err != nil { + fmt.Println(err) + w.WriteHeader(http.StatusInternalServerError) + return + } + cacheid := uuid.NewString() + h.cache.PutWithTTL(cacheid, beneficiaries, 1*time.Hour) + h.Renderer.AdminStatBeneficaires(w, r, beneficiaries, cacheid) +} + +func (h ApplicationHandler) AdminStatEvents(w http.ResponseWriter, r *http.Request) { + resp, err := h.services.GRPC.Agenda.GetEvents(context.TODO(), &agenda.GetEventsRequest{ + Namespaces: []string{"parcoursmob_dispositifs"}, + }) + + if err != nil { + fmt.Println(err) + w.WriteHeader(http.StatusInternalServerError) + return + } + + responses := []agendastorage.Event{} + + groupids := []string{} + for _, e := range resp.Events { + groupids = append(groupids, e.Owners...) + responses = append(responses, e.ToStorageType()) + } + + sort.Sort(sorting.EventsByStartdate(responses)) + + groupsresp, err := h.services.GRPC.GroupsManagement.GetGroupsBatch(context.TODO(), &groupsmanagement.GetGroupsBatchRequest{ + Groupids: groupids, + }) + groups := map[string]any{} + + if err == nil { + for _, g := range groupsresp.Groups { + groups[g.Id] = g.ToStorageType() + } + } + h.Renderer.AdminStatEvents(w, r, responses, groups) +} diff --git a/handlers/application/agenda.go b/handlers/application/agenda.go index 69b1f40..70a1095 100644 --- a/handlers/application/agenda.go +++ b/handlers/application/agenda.go @@ -7,6 +7,7 @@ import ( "net/http" "sort" "strconv" + "strings" "time" formvalidators "git.coopgo.io/coopgo-apps/parcoursmob/utils/form-validators" @@ -67,10 +68,44 @@ func (h *ApplicationHandler) AgendaHome(w http.ResponseWriter, r *http.Request) groups[g.Id] = g.ToStorageType() } } - h.Renderer.AgendaHome(w, r, responses, groups) } +func (h *ApplicationHandler) AgendaHistory(w http.ResponseWriter, r *http.Request) { + resp, err := h.services.GRPC.Agenda.GetEvents(context.TODO(), &agenda.GetEventsRequest{ + Namespaces: []string{"parcoursmob_dispositifs"}, + //Maxdate: timestamppb.New(time.Now().Add(24 * time.Hour)), + }) + + if err != nil { + fmt.Println(err) + w.WriteHeader(http.StatusInternalServerError) + return + } + + responses := []agendastorage.Event{} + + groupids := []string{} + for _, e := range resp.Events { + groupids = append(groupids, e.Owners...) + responses = append(responses, e.ToStorageType()) + } + + sort.Sort(sorting.EventsByStartdate(responses)) + + groupsresp, err := h.services.GRPC.GroupsManagement.GetGroupsBatch(context.TODO(), &groupsmanagement.GetGroupsBatchRequest{ + Groupids: groupids, + }) + groups := map[string]any{} + + if err == nil { + for _, g := range groupsresp.Groups { + groups[g.Id] = g.ToStorageType() + } + } + h.Renderer.AgendaHistory(w, r, responses, groups) +} + func (h *ApplicationHandler) AgendaCreateEvent(w http.ResponseWriter, r *http.Request) { if r.Method == "POST" { // Get current group @@ -107,6 +142,7 @@ func (h *ApplicationHandler) AgendaCreateEvent(w http.ResponseWriter, r *http.Re Allday: eventForm.Allday, MaxSubscribers: int64(eventForm.MaxSubscribers), Data: data, + Deleted: false, }, } @@ -119,7 +155,7 @@ func (h *ApplicationHandler) AgendaCreateEvent(w http.ResponseWriter, r *http.Re } http.Redirect(w, r, fmt.Sprintf("/app/agenda/%s", resp.Event.Id), http.StatusFound) - + return } h.Renderer.AgendaCreateEvent(w, r) } @@ -225,13 +261,13 @@ func (h *ApplicationHandler) AgendaSubscribeEvent(w http.ResponseWriter, r *http w.WriteHeader(http.StatusBadRequest) return } - subscriber := r.FormValue("subscriber") data := map[string]any{ "subscribed_by": map[string]any{ "user": map[string]any{ "id": current_user_token.Subject, - "display_name": fmt.Sprintf("%s %s", current_user_claims["first_name"], current_user_claims["last_name"]), + "display_name": current_user_claims["first_name"].(string) + " " + current_user_claims["last_name"].(string), + "email": current_user_claims["email"].(string), }, "group": map[string]any{ "id": current_group.ID, @@ -330,11 +366,322 @@ func contains(s []*agenda.Subscription, e string) bool { return false } -// func contains[V string](s []V, e V) bool { -// for _, a := range s { -// if a == e { -// return true -// } -// } -// return false -// } +///////////////////////////////Update Event///////////////////////////////////////// +func (h *ApplicationHandler) AgendaUpdateEvent(w http.ResponseWriter, r *http.Request) { + adm := strings.Split(r.URL.Path, "/") + eventID := adm[3] + request := &agenda.GetEventRequest{ + Id: eventID, + } + + resp, err := h.services.GRPC.Agenda.GetEvent(context.TODO(), request) + if err != nil { + fmt.Println(err) + w.WriteHeader(http.StatusInternalServerError) + return + } + if r.Method == "POST" { + g := r.Context().Value(identification.GroupKey) + if g == nil { + w.WriteHeader(http.StatusBadRequest) + return + } + + group := g.(storage.Group) + + eventForm, err := parseEventsForm(r) + if err != nil { + fmt.Println(err) + w.WriteHeader(http.StatusBadRequest) + return + } + + data, _ := structpb.NewStruct(map[string]any{ + "address": eventForm.Address, + }) + + request := &agenda.UpdateEventRequest{ + Event: &agenda.Event{ + Namespace: "parcoursmob_dispositifs", + Id: eventID, + Owners: []string{group.ID}, + Type: eventForm.Type, + Name: eventForm.Name, + Description: eventForm.Description, + Startdate: timestamppb.New(*eventForm.Startdate), + Enddate: timestamppb.New(*eventForm.Enddate), + Starttime: eventForm.Starttime, + Endtime: eventForm.Endtime, + Allday: eventForm.Allday, + MaxSubscribers: int64(eventForm.MaxSubscribers), + Data: data, + Subscriptions: resp.Event.Subscriptions, + }, + } + + resp, err := h.services.GRPC.Agenda.UpdateEvent(context.TODO(), request) + + if err != nil { + fmt.Println(err) + w.WriteHeader(http.StatusInternalServerError) + return + } + + http.Redirect(w, r, fmt.Sprintf("/app/agenda/%s", resp.Event.Id), http.StatusFound) + return + } + h.Renderer.AgendaUpdateEvent(w, r, resp.Event.ToStorageType()) +} + +func (h *ApplicationHandler) AgendaDeleteEvent(w http.ResponseWriter, r *http.Request) { + + vars := mux.Vars(r) + eventID := vars["eventid"] + request := &agenda.GetEventRequest{ + Id: eventID, + } + + resp, err := h.services.GRPC.Agenda.GetEvent(context.TODO(), request) + if err != nil { + fmt.Println(err) + w.WriteHeader(http.StatusInternalServerError) + return + } + + if r.Method == "POST" { + + request := &agenda.UpdateEventRequest{ + Event: &agenda.Event{ + Namespace: resp.Event.Namespace, + Id: resp.Event.Id, + Owners: resp.Event.Owners, + Type: resp.Event.Type, + Name: resp.Event.Name, + Description: resp.Event.Description, + Startdate: resp.Event.Startdate, + Enddate: resp.Event.Enddate, + Starttime: resp.Event.Starttime, + Endtime: resp.Event.Endtime, + Allday: resp.Event.Allday, + MaxSubscribers: int64(resp.Event.MaxSubscribers), + Data: resp.Event.Data, + Subscriptions: resp.Event.Subscriptions, + Deleted: true, + }, + } + + _, err := h.services.GRPC.Agenda.UpdateEvent(context.TODO(), request) + + if err != nil { + fmt.Println(err) + w.WriteHeader(http.StatusInternalServerError) + return + } + + http.Redirect(w, r, "/app/agenda/", http.StatusFound) + return + } + h.Renderer.AgendaDeleteEvent(w, r, resp.Event.ToStorageType()) +} + +///////////////////////////Delete subscriber/////////////////////////////// +func (h *ApplicationHandler) AgendaDeleteSubscribeEvent(w http.ResponseWriter, r *http.Request) { + vars := mux.Vars(r) + eventId := vars["eventid"] + subscribeid := vars["subscribeid"] + s_b_id := "" + s_b_name := "" + s_b_email := "" + s_b_group_id := "" + s_b_group_name := "" + request := &agenda.GetEventRequest{ + Id: eventId, + } + + resp, err := h.services.GRPC.Agenda.GetEvent(context.TODO(), request) + if err != nil { + fmt.Println(err) + w.WriteHeader(http.StatusInternalServerError) + return + } + + for i := range resp.Event.Subscriptions { + if resp.Event.Subscriptions[i].Subscriber == subscribeid { + subscribed_by_id := resp.Event.Subscriptions[i].Data.Fields["subscribed_by"].GetStructValue().Fields["user"].GetStructValue().Fields["id"].GetStringValue() + subscribed_by_name := resp.Event.Subscriptions[i].Data.Fields["subscribed_by"].GetStructValue().Fields["user"].GetStructValue().Fields["display_name"].GetStringValue() + subscribed_by_email := resp.Event.Subscriptions[i].Data.Fields["subscribed_by"].GetStructValue().Fields["user"].GetStructValue().Fields["email"].GetStringValue() + subscribed_by_group_id := resp.Event.Subscriptions[i].Data.Fields["subscribed_by"].GetStructValue().Fields["group"].GetStructValue().Fields["id"].GetStringValue() + subscribed_by_group_name := resp.Event.Subscriptions[i].Data.Fields["subscribed_by"].GetStructValue().Fields["group"].GetStructValue().Fields["name"].GetStringValue() + s_b_id = subscribed_by_id + s_b_name = subscribed_by_name + s_b_email = subscribed_by_email + s_b_group_id = subscribed_by_group_id + s_b_group_name = subscribed_by_group_name + } + } + + current_group, err := h.currentGroup(r) + if err != nil { + fmt.Println(err) + w.WriteHeader(http.StatusInternalServerError) + return + } + + current_user_token, current_user_claims, err := h.currentUser(r) + if err != nil { + fmt.Println(err) + w.WriteHeader(http.StatusInternalServerError) + return + } + + data := map[string]any{ + "subscribed_by": map[string]any{ + "user": map[string]any{ + "id": s_b_id, + "display_name": s_b_name, + "email": s_b_email, + }, + "group": map[string]any{ + "id": s_b_group_id, + "name": s_b_group_name, + }, + }, + "unsubscribed_by": map[string]any{ + "user": map[string]any{ + "id": current_user_token.Subject, + "display_name": current_user_claims["first_name"].(string) + " " + current_user_claims["last_name"].(string), + "email": current_user_claims["email"], + }, + "group": map[string]any{ + "id": current_group.ID, + "name": current_group.Data["name"], + }, + }, + "motif": r.FormValue("motif"), + } + + datapb, err := structpb.NewStruct(data) + if err != nil { + fmt.Println(err) + w.WriteHeader(http.StatusInternalServerError) + return + } + + if r.Method == "POST" { + request := &agenda.DeleteSubscriptionRequest{ + Subscriber: subscribeid, + Eventid: eventId, + Data: datapb, + } + + data := map[string]any{ + "motif": r.FormValue("motif"), + "user": current_user_claims["first_name"].(string) + " " + current_user_claims["last_name"].(string), + "subscriber": fmt.Sprintf("http://localhost:9000/app/beneficiaries/%s", subscribeid), + "link": fmt.Sprintf("http://localhost:9000/app/agenda/%s", eventId), + } + + // récupérer l'adresse mail de l'utilisateur qui a créé l'événement + mail := s_b_email + fmt.Println(mail) + + _, err := h.services.GRPC.Agenda.DeleteSubscription(context.TODO(), request) + + if err != nil { + fmt.Println(err) + w.WriteHeader(http.StatusInternalServerError) + return + } + + if err := h.emailing.Send("delete_subscriber.request", mail, data); err != nil { + fmt.Println(err) + w.WriteHeader(http.StatusInternalServerError) + return + } + + http.Redirect(w, r, fmt.Sprintf("/app/agenda/%s", eventId), http.StatusFound) + return + } + h.Renderer.AgendaDeleteSubscribeEvent(w, r, eventId) +} + +//////////////////////////////////////////////////////// +// /////////////////////History Event//////////////////////// +func (h *ApplicationHandler) AgendaHistoryEvent(w http.ResponseWriter, r *http.Request) { + vars := mux.Vars(r) + eventId := vars["eventid"] + request := &agenda.GetEventRequest{ + Id: eventId, + } + + resp, err := h.services.GRPC.Agenda.GetEvent(context.TODO(), request) + if err != nil { + fmt.Println(err) + w.WriteHeader(http.StatusInternalServerError) + return + } + + grouprequest := &groupsmanagement.GetGroupRequest{ + Id: resp.Event.Owners[0], + } + + groupresp, err := h.services.GRPC.GroupsManagement.GetGroup(context.TODO(), grouprequest) + if err != nil { + fmt.Println(err) + w.WriteHeader(http.StatusInternalServerError) + return + } + + subscribers := map[string]any{} + + accids := []string{} + for _, v := range resp.Event.DeletedSubscription { + accids = append(accids, v.Subscriber) + } + + subscriberresp, err := h.services.GRPC.MobilityAccounts.GetAccountsBatch( + context.TODO(), + &mobilityaccounts.GetAccountsBatchRequest{ + Accountids: accids, + }, + ) + + if err == nil { + for _, sub := range subscriberresp.Accounts { + subscribers[sub.Id] = sub.ToStorageType() + } + } + + g := r.Context().Value(identification.GroupKey) + if g == nil { + fmt.Println(err) + w.WriteHeader(http.StatusInternalServerError) + return + } + + group := g.(storage.Group) + + accountids := []string{} + for _, m := range group.Members { + if !contains(resp.Event.DeletedSubscription, m) { + accountids = append(accountids, m) + } + } + + accountresp, err := h.services.GRPC.MobilityAccounts.GetAccountsBatch( + context.TODO(), + &mobilityaccounts.GetAccountsBatchRequest{ + Accountids: accountids, + }, + ) + + accounts := []any{} + + if err == nil { + for _, acc := range accountresp.Accounts { + accounts = append(accounts, acc) + } + } + + h.Renderer.AgendaHistoryEvent(w, r, resp.Event.ToStorageType(), groupresp.Group.ToStorageType(), subscribers, accounts) +} diff --git a/handlers/application/beneficiaries.go b/handlers/application/beneficiaries.go index f69b00a..bfbc30f 100644 --- a/handlers/application/beneficiaries.go +++ b/handlers/application/beneficiaries.go @@ -54,7 +54,6 @@ func (h *ApplicationHandler) BeneficiariesList(w http.ResponseWriter, r *http.Re cacheid := uuid.NewString() h.cache.PutWithTTL(cacheid, accounts, 1*time.Hour) - h.Renderer.BeneficiariesList(w, r, accounts, cacheid) } diff --git a/handlers/application/journeys.go b/handlers/application/journeys.go index 3aa2055..c8f143b 100644 --- a/handlers/application/journeys.go +++ b/handlers/application/journeys.go @@ -462,24 +462,27 @@ func (h *ApplicationHandler) DisplayGroupCovoiturage(w http.ResponseWriter, r *h return } //////////find all groups to store the adresse passenger/////// - grp := &groupsmanagement.GetGroupsBatchMemberRequest{ + // grp := &groupsmanagement.GetGroupsBatchMemberRequest{ - Groupids: []string{resp.Group.ToStorageType().ID}, - } - s, err := h.services.GRPC.GroupsManagement.GetGroupsBatchMember(context.TODO(), grp) - if err != nil { - fmt.Println(err) - w.WriteHeader(http.StatusInternalServerError) - return - } - groups := map[string]any{} - - if err == nil { - for _, g := range s.Groups { - groups[g.Memberid] = g.ToStorageType() - } - } + // Groupids: []string{resp.Group.ToStorageType().ID}, + // } + // s, err := h.services.GRPC.GroupsManagement.GetGroupsBatchMember(context.TODO(), grp) + // if err != nil { + // fmt.Println(err) + // w.WriteHeader(http.StatusInternalServerError) + // return + // } + // groups := map[string]any{} + // if err == nil { + // for _, g := range s.Groups { + // groups[g.Memberid] = g.ToStorageType() + // } + // } + //////////find all groups to store the adresse passenger/////// + ///////////try to optimise the code //////////////////////////// + groups, _ := h.services.GetGroupsMemberMap(resp.Group.ToStorageType().ID) + //fmt.Println(groups) var number string = strconv.Itoa(len(resp.Group.Members)) ///////////////////// accountsBeneficaire, err := h.beneficiaries(r) diff --git a/handlers/application/members.go b/handlers/application/members.go index 586b4e4..545925f 100644 --- a/handlers/application/members.go +++ b/handlers/application/members.go @@ -6,9 +6,12 @@ import ( "fmt" "net/http" "strings" + "time" formvalidators "git.coopgo.io/coopgo-apps/parcoursmob/utils/form-validators" + groupsmanagement "git.coopgo.io/coopgo-platform/groups-management/grpcapi" mobilityaccounts "git.coopgo.io/coopgo-platform/mobility-accounts/grpcapi" + "github.com/google/uuid" "google.golang.org/protobuf/types/known/structpb" ) @@ -16,7 +19,7 @@ type UserForm struct { FirstName string `json:"first_name" validate:"required"` LastName string `json:"last_name" validate:"required"` Email string `json:"email" validate:"required,email"` - PhoneNumber string `json:"phone_number" validate:"required,phoneNumber"` + PhoneNumber string `json:"phone_number" ` Address any `json:"address,omitempty"` Gender string `json:"gender"` } @@ -36,8 +39,34 @@ func (h *ApplicationHandler) MemberDisplay(w http.ResponseWriter, r *http.Reques w.WriteHeader(http.StatusInternalServerError) return } + //////////////////////////////////add organisations///////////////////////////////////////////////// - h.Renderer.MemberDisplay(w, r, resp.Account.ToStorageType()) + var allIds []string + for _, v := range resp.Account.ToStorageType().Data["groups"].([]any) { + s := fmt.Sprintf("%v", v) + if !(strings.Contains(s, "admin")) { + allIds = append(allIds, s) + } + } + reques := &groupsmanagement.GetGroupsBatchRequest{ + Groupids: allIds, + } + + res, err := h.services.GRPC.GroupsManagement.GetGroupsBatch(context.TODO(), reques) + if err != nil { + fmt.Println(err) + w.WriteHeader(http.StatusInternalServerError) + return + } + + var groupsName []string + + for _, group := range res.Groups { + g := fmt.Sprintf("%v", group.ToStorageType().Data["name"]) + groupsName = append(groupsName, g) + } + + h.Renderer.MemberDisplay(w, r, resp.Account.ToStorageType(), groupsName) } func (h *ApplicationHandler) MemberUpdate(w http.ResponseWriter, r *http.Request) { @@ -76,7 +105,7 @@ func (h *ApplicationHandler) MemberUpdate(w http.ResponseWriter, r *http.Request return } - http.Redirect(w, r, fmt.Sprintf("/app/profile/%s", resp.Account.Id), http.StatusFound) + http.Redirect(w, r, fmt.Sprintf("/app/members/%s", resp.Account.Id), http.StatusFound) return } @@ -126,3 +155,59 @@ func parseUserForm(r *http.Request) (map[string]any, error) { return dataMap, nil } + +func (h *ApplicationHandler) MembersList(w http.ResponseWriter, r *http.Request) { + + accounts, err := h.services.GetAccounts() + if err != nil { + fmt.Println(err) + w.WriteHeader(http.StatusInternalServerError) + return + } + var groupsName []string + + for _, v := range accounts { + adminid := v.ID + request := &mobilityaccounts.GetAccountRequest{ + Id: adminid, + } + + resp, err := h.services.GRPC.MobilityAccounts.GetAccount(context.TODO(), request) + if err != nil { + fmt.Println(err) + w.WriteHeader(http.StatusInternalServerError) + return + } + //////////////////////////////////add organisations///////////////////////////////////////////////// + + var allIds []string + for _, v := range resp.Account.ToStorageType().Data["groups"].([]any) { + s := fmt.Sprintf("%v", v) + if !(strings.Contains(s, "admin")) { + allIds = append(allIds, s) + } + + } + + reques := &groupsmanagement.GetGroupsBatchRequest{ + Groupids: allIds, + } + + res, err := h.services.GRPC.GroupsManagement.GetGroupsBatch(context.TODO(), reques) + if err != nil { + fmt.Println(err) + w.WriteHeader(http.StatusInternalServerError) + return + } + g := "" + for _, group := range res.Groups { + g += fmt.Sprintf("%v", group.ToStorageType().Data["name"]) + " " + } + groupsName = append(groupsName, g) + + } + cacheid := uuid.NewString() + h.cache.PutWithTTL(cacheid, accounts, 1*time.Hour) + + h.Renderer.MembersList(w, r, accounts, cacheid, groupsName) +} diff --git a/handlers/application/vehicles-management.go b/handlers/application/vehicles-management.go index 0528583..4447760 100644 --- a/handlers/application/vehicles-management.go +++ b/handlers/application/vehicles-management.go @@ -42,20 +42,24 @@ func (h *ApplicationHandler) VehiclesManagementOverview(w http.ResponseWriter, r for _, vehicle := range resp.Vehicles { if filterVehicle(r, vehicle) { v := vehicle.ToStorageType() - vehicles = append(vehicles, v) - vehicles_map[v.ID] = v + vehicleBookings := []fleetsstorage.Booking{} for _, b := range v.Bookings { if b.Status() != fleetsstorage.StatusOld { bookings = append(bookings, b) } + if b.Unavailableto.After(time.Now()) { + vehicleBookings = append(vehicleBookings, b) + } } + v.Bookings = vehicleBookings + vehicles = append(vehicles, v) + vehicles_map[v.ID] = v } } sort.Sort(sorting.VehiclesByLicencePlate(vehicles)) sort.Sort(sorting.BookingsByStartdate(bookings)) - h.Renderer.VehiclesManagementOverview(w, r, vehicles, vehicles_map, bookings) } @@ -184,7 +188,10 @@ func (h *ApplicationHandler) VehiclesFleetDisplay(w http.ResponseWriter, r *http w.WriteHeader(http.StatusInternalServerError) return } - + // if len(resp.Vehicle.ToStorageType().Bookings) == 0 { + // fmt.Println("lol") + // } + // fmt.Println(resp.Vehicle.ToStorageType().Bookings) h.Renderer.VehiclesFleetDisplay(w, r, resp.Vehicle.ToStorageType()) } @@ -320,6 +327,7 @@ func (h ApplicationHandler) VehicleManagementBookingDisplay(w http.ResponseWrite alternativerequest := &fleets.GetVehiclesRequest{ Namespaces: []string{"parcoursmob"}, + Administrators: booking.Vehicle.Administrators, AvailabilityFrom: timestamppb.New(booking.Startdate), AvailabilityTo: timestamppb.New(booking.Enddate.Add(24 * time.Hour)), } @@ -457,3 +465,28 @@ func (h ApplicationHandler) VehiclesFleetMakeUnavailable(w http.ResponseWriter, http.Redirect(w, r, fmt.Sprintf("/app/vehicles-management/fleet/%s", vehicleid), http.StatusFound) } + +// func (h *ApplicationHandler) UnbookingVehicles(w http.ResponseWriter, r *http.Request) { +// request := &fleets.GetVehiclesRequest{ +// Namespaces: []string{"parcoursmob"}, +// } +// resp, err := h.services.GRPC.Fleets.GetVehicles(context.TODO(), request) +// if err != nil { +// fmt.Println(err) +// w.WriteHeader(http.StatusInternalServerError) +// } +// vehicles := []fleetsstorage.Vehicle{} +// fmt.Println(resp.Vehicles[0].Bookings) +// for i, vehicle := range resp.Vehicles { +// if len(resp.Vehicles[i].Bookings) == 0 { +// v := vehicle.ToStorageType() +// vehicles = append(vehicles, v) +// } +// } +// // if len(resp.Vehicle.ToStorageType().Bookings) == 0 { +// // h.Renderer.UnbookingVehicles(w, r, resp.Vehicle.ToStorageType()) +// // } +// // fmt.Println(resp.Vehicle.ToStorageType().Bookings) +// fmt.Println(vehicles) +// h.Renderer.UnbookingVehicles(w, r, vehicles) +// } diff --git a/handlers/auth/onboarding.go b/handlers/auth/onboarding.go index f1c87a5..20a3982 100644 --- a/handlers/auth/onboarding.go +++ b/handlers/auth/onboarding.go @@ -37,7 +37,7 @@ func (h *AuthHandler) Onboarding(w http.ResponseWriter, r *http.Request) { if onboardingmap["admin"].(bool) { groups = append(groups, onboardingmap["group"].(string)+":admin") } - + display_name := fmt.Sprint(r.FormValue("first_name")) + " " + fmt.Sprint(r.FormValue("last_name")) account := &ma.Account{ Authentication: ma.AccountAuth{ Local: ma.LocalAuth{ @@ -46,11 +46,13 @@ func (h *AuthHandler) Onboarding(w http.ResponseWriter, r *http.Request) { }, }, Namespace: "parcoursmob", + Data: map[string]any{ - "first_name": r.FormValue("first_name"), - "last_name": r.FormValue("last_name"), - "email": onboardingmap["username"], - "groups": groups, + "display_name": display_name, + "first_name": r.FormValue("first_name"), + "last_name": r.FormValue("last_name"), + "email": onboardingmap["username"], + "groups": groups, }, } diff --git a/main.go b/main.go index 699c7ed..2420d8f 100644 --- a/main.go +++ b/main.go @@ -91,6 +91,7 @@ func main() { application.HandleFunc("/members/{beneficiaryid}/picture", applicationHandler.BeneficiaryPicture) application.HandleFunc("/members/{adminid}", applicationHandler.MemberDisplay) application.HandleFunc("/members/{adminid}/update", applicationHandler.MemberUpdate) + application.HandleFunc("/members/", applicationHandler.MembersList) application.HandleFunc("/journeys/", applicationHandler.JourneysSearch) application.HandleFunc("/vehicles/", applicationHandler.VehiclesSearch) application.HandleFunc("/vehicles/bookings/", applicationHandler.VehiclesBookingsList) @@ -104,20 +105,29 @@ func main() { application.HandleFunc("/vehicles-management/fleet/{vehicleid}/update", applicationHandler.VehiclesFleetUpdate) application.HandleFunc("/vehicles-management/bookings/", applicationHandler.VehiclesManagementBookingsList) application.HandleFunc("/vehicles-management/bookings/{bookingid}", applicationHandler.VehicleManagementBookingDisplay) + application.HandleFunc("/vehicles-management/bookings/{bookingid}/change-vehicle", applicationHandler.VehicleManagementBookingChangeVehicle) application.HandleFunc("/vehicles-management/bookings/{bookingid}/documents/{document}", applicationHandler.BookingDocumentDownload) application.HandleFunc("/agenda/", applicationHandler.AgendaHome) + application.HandleFunc("/agenda/history", applicationHandler.AgendaHistory) application.HandleFunc("/agenda/create-event", applicationHandler.AgendaCreateEvent) application.HandleFunc("/agenda/{eventid}", applicationHandler.AgendaDisplayEvent) + ///////////////////////////////Code to modify event/////////////////////// + application.HandleFunc("/agenda/{eventid}/update", applicationHandler.AgendaUpdateEvent) + application.HandleFunc("/agenda/{eventid}/delete", applicationHandler.AgendaDeleteEvent) + + ///////////////////////////////////////////////////// application.HandleFunc("/agenda/{eventid}/subscribe", applicationHandler.AgendaSubscribeEvent) application.HandleFunc("/directory/", applicationHandler.DirectoryHome) application.HandleFunc("/group/settings", applicationHandler.GroupSettingsDisplay) application.HandleFunc("/group/settings/invite-member", applicationHandler.GroupSettingsInviteMember) + /****************************Groupe Déplacement ************************************/ application.HandleFunc("/journeys/groups_covoiturage", applicationHandler.GroupsGestion) application.HandleFunc("/journeys/groups_covoiturage/create", applicationHandler.CreateGroup) application.HandleFunc("/journeys/groups_covoiturage/create/{groupid}", applicationHandler.DisplayGroupCovoiturage) application.HandleFunc("/journeys/groups_covoiturage/create/{id}/{groupid}/{memberid}", applicationHandler.UpdateGroupCovoiturage) + /****************************************************************/ /********************Code Supprt Emailing************************/ application.HandleFunc("/support/", applicationHandler.SupportSend) @@ -138,8 +148,15 @@ func main() { appAdmin.HandleFunc("/groups/{groupid}", applicationHandler.AdministrationGroupDisplay) appAdmin.HandleFunc("/groups/{groupid}/invite-admin", applicationHandler.AdministrationGroupInviteAdmin) appAdmin.HandleFunc("/groups/{groupid}/invite-member", applicationHandler.AdministrationGroupInviteMember) + //add statistiques appAdmin.HandleFunc("/stats/vehicles", applicationHandler.AdminStatVehicles) + appAdmin.HandleFunc("/stats/beneficaires", applicationHandler.AdminStatBeneficaires) + appAdmin.HandleFunc("/stats/events", applicationHandler.AdminStatEvents) + /////////////////////////////////////Delete subscriber/////////////////////////////////////////////// + application.HandleFunc("/agenda/{eventid}/{subscribeid}/delete", applicationHandler.AgendaDeleteSubscribeEvent) + application.HandleFunc("/agenda/{eventid}/history", applicationHandler.AgendaHistoryEvent) + ///////////////////////////////////////////////////////////////////////////////////////////////////// fmt.Println("-> HTTP server listening on", address) srv := &http.Server{ diff --git a/renderer/administration.go b/renderer/administration.go index 635a811..fe89393 100644 --- a/renderer/administration.go +++ b/renderer/administration.go @@ -1,14 +1,18 @@ package renderer import ( + "encoding/json" + "html/template" "net/http" + agendastorage "git.coopgo.io/coopgo-platform/agenda/storage" + fleetsstorage "git.coopgo.io/coopgo-platform/fleets/storage" mobilityaccountsstorage "git.coopgo.io/coopgo-platform/mobility-accounts/storage" ) const administrationMenu = "administration" -func (renderer *Renderer) Administration(w http.ResponseWriter, r *http.Request, accounts any, beneficiaries any, groups any, bookings any) { +func (renderer *Renderer) Administration(w http.ResponseWriter, r *http.Request, accounts any, beneficiaries any, groups any, bookings any, events []agendastorage.Event) { files := renderer.ThemeConfig.GetStringSlice("views.administration.home.files") state := NewState(r, renderer.ThemeConfig, administrationMenu) state.ViewState = map[string]any{ @@ -16,6 +20,7 @@ func (renderer *Renderer) Administration(w http.ResponseWriter, r *http.Request, "beneficiaries": beneficiaries, "bookings": bookings, "groups": groups, + "events": events, } renderer.Render("administration", w, r, files, state) @@ -39,3 +44,58 @@ func (renderer *Renderer) AdministrationGroupDisplay(w http.ResponseWriter, r *h renderer.Render("administration", w, r, files, state) } + +type BeneficiariesState struct { + Count int `json:"count"` + CacheId string `json:"cache_id"` + Beneficiaries []mobilityaccountsstorage.Account `json:"beneficiaries"` +} + +func (s BeneficiariesState) JSON() template.JS { + result, _ := json.Marshal(s) + return template.JS(result) +} + +func (s BeneficiariesState) JSONWithLimits(a int, b int) template.JS { + if b < len(s.Beneficiaries) { + s.Beneficiaries = s.Beneficiaries[a:b] + } + return s.JSON() +} + +func (renderer *Renderer) AdminStatBeneficaires(w http.ResponseWriter, r *http.Request, Beneficiaries []mobilityaccountsstorage.Account, cacheid string) { + files := renderer.ThemeConfig.GetStringSlice("views.administration.beneficaires_list.files") + + state := NewState(r, renderer.ThemeConfig, administrationMenu) + state.ViewState = BeneficiariesState{ + Count: len(Beneficiaries), + CacheId: cacheid, + Beneficiaries: Beneficiaries, + } + + renderer.Render("beneficiaries_State", w, r, files, state) +} + +func (renderer *Renderer) AdminStatEvents(w http.ResponseWriter, r *http.Request, events []agendastorage.Event, groups map[string]any) { + files := renderer.ThemeConfig.GetStringSlice("views.administration.events_list.files") + + state := NewState(r, renderer.ThemeConfig, administrationMenu) + state.ViewState = map[string]any{ + "events": events, + "groups": groups, + } + + renderer.Render("beneficiaries_State", w, r, files, state) +} + +func (renderer *Renderer) AdminStatVehicles(w http.ResponseWriter, r *http.Request, vehicles []fleetsstorage.Vehicle, bookings []fleetsstorage.Booking, admingroups map[string]any) { + files := renderer.ThemeConfig.GetStringSlice("views.administration.vehicles_list.files") + state := NewState(r, renderer.ThemeConfig, administrationMenu) + state.ViewState = map[string]any{ + "vehicles": vehicles, + "bookings": bookings, + "admingroups": admingroups, + } + + renderer.Render("vehicles_state", w, r, files, state) +} diff --git a/renderer/agenda.go b/renderer/agenda.go index 4197e01..09f41f3 100644 --- a/renderer/agenda.go +++ b/renderer/agenda.go @@ -19,6 +19,17 @@ func (renderer *Renderer) AgendaHome(w http.ResponseWriter, r *http.Request, eve renderer.Render("agenda home", w, r, files, state) } +func (renderer *Renderer) AgendaHistory(w http.ResponseWriter, r *http.Request, events []agendastorage.Event, groups map[string]any) { + files := renderer.ThemeConfig.GetStringSlice("views.agenda.history.files") + state := NewState(r, renderer.ThemeConfig, agendaMenu) + state.ViewState = map[string]any{ + "events": events, + "groups": groups, + } + + renderer.Render("agenda history", w, r, files, state) +} + func (renderer *Renderer) AgendaCreateEvent(w http.ResponseWriter, r *http.Request) { files := renderer.ThemeConfig.GetStringSlice("views.agenda.create_event.files") state := NewState(r, renderer.ThemeConfig, agendaMenu) @@ -29,6 +40,7 @@ func (renderer *Renderer) AgendaCreateEvent(w http.ResponseWriter, r *http.Reque func (renderer *Renderer) AgendaDisplayEvent(w http.ResponseWriter, r *http.Request, event any, group any, subscribers map[string]any, beneficiaries any) { files := renderer.ThemeConfig.GetStringSlice("views.agenda.display_event.files") state := NewState(r, renderer.ThemeConfig, agendaMenu) + state.ViewState = map[string]any{ "event": event, "group": group, @@ -38,3 +50,53 @@ func (renderer *Renderer) AgendaDisplayEvent(w http.ResponseWriter, r *http.Requ renderer.Render("agenda create event", w, r, files, state) } + +//////////////////////////DElete subscriber////////////////////////////////// +func (renderer *Renderer) AgendaDeleteSubscribeEvent(w http.ResponseWriter, r *http.Request, eventid string) { + files := renderer.ThemeConfig.GetStringSlice("views.agenda.delete_subscriber.files") + state := NewState(r, renderer.ThemeConfig, agendaMenu) + state.ViewState = map[string]any{ + "eventid": eventid, + } + + renderer.Render("agenda delete subscriber", w, r, files, state) +} + +////////////////////////////////////////////////////////// + +//////////////////////////History Event////////////////////////////////// +func (renderer *Renderer) AgendaHistoryEvent(w http.ResponseWriter, r *http.Request, event any, group any, subscribers map[string]any, beneficiaries any) { + files := renderer.ThemeConfig.GetStringSlice("views.agenda.history_event.files") + state := NewState(r, renderer.ThemeConfig, agendaMenu) + state.ViewState = map[string]any{ + "event": event, + "group": group, + "subscribers": subscribers, + "beneficiaries": beneficiaries, + } + + renderer.Render("agenda history event", w, r, files, state) +} + +//////////////////////////////////////////////////////////////////////// +func (renderer *Renderer) AgendaUpdateEvent(w http.ResponseWriter, r *http.Request, event any) { + files := renderer.ThemeConfig.GetStringSlice("views.agenda.update.files") + state := NewState(r, renderer.ThemeConfig, agendaMenu) + + state.ViewState = map[string]any{ + "event": event, + } + + renderer.Render("event_update", w, r, files, state) +} + +func (renderer *Renderer) AgendaDeleteEvent(w http.ResponseWriter, r *http.Request, event any) { + files := renderer.ThemeConfig.GetStringSlice("views.agenda.delete.files") + state := NewState(r, renderer.ThemeConfig, agendaMenu) + + state.ViewState = map[string]any{ + "event": event, + } + + renderer.Render("event_deleteEvent", w, r, files, state) +} diff --git a/renderer/members.go b/renderer/members.go index a95bc72..ad96005 100644 --- a/renderer/members.go +++ b/renderer/members.go @@ -1,17 +1,22 @@ package renderer import ( + "encoding/json" + "html/template" "net/http" + + mobilityaccountsstorage "git.coopgo.io/coopgo-platform/mobility-accounts/storage" ) const membersMenu = "members" -func (renderer *Renderer) MemberDisplay(w http.ResponseWriter, r *http.Request, admins any) { +func (renderer *Renderer) MemberDisplay(w http.ResponseWriter, r *http.Request, admins any, groups []string) { files := renderer.ThemeConfig.GetStringSlice("views.members.display.files") state := NewState(r, renderer.ThemeConfig, membersMenu) state.ViewState = map[string]any{ "admins": admins, + "groups": groups, } renderer.Render("members_list", w, r, files, state) } @@ -22,3 +27,41 @@ func (renderer *Renderer) MemberUpdate(w http.ResponseWriter, r *http.Request, u state.ViewState = user renderer.Render("members_update", w, r, files, state) } + +type MembersListState struct { + Count int `json:"count"` + CacheId string `json:"cache_id"` + Members []mobilityaccountsstorage.Account `json:"members"` + Groups []string `json:"groups"` +} + +func (s MembersListState) JSON() template.JS { + result, _ := json.Marshal(s) + return template.JS(result) +} + +func (s MembersListState) JSONWithLimits(a int, b int) template.JS { + if b < len(s.Members) { + s.Members = s.Members[a:b] + } + return s.JSON() +} + +func (renderer *Renderer) MembersList(w http.ResponseWriter, r *http.Request, accounts []mobilityaccountsstorage.Account, cacheid string, groups []string) { + files := renderer.ThemeConfig.GetStringSlice("views.members.list.files") + + state := NewState(r, renderer.ThemeConfig, membersMenu) + + state.ViewState = map[string]any{ + + "list": MembersListState{ + Count: len(accounts), + CacheId: cacheid, + Members: accounts, + Groups: groups, + }, + "groups": groups, + } + + renderer.Render("members_list", w, r, files, state) +} diff --git a/renderer/vehicles.go b/renderer/vehicles.go index 9f9ad11..09faa62 100644 --- a/renderer/vehicles.go +++ b/renderer/vehicles.go @@ -78,3 +78,15 @@ func (renderer *Renderer) VehicleBookingsList(w http.ResponseWriter, r *http.Req renderer.Render("vehicles search", w, r, files, state) } + +// func (renderer *Renderer) VehicleUnbookingsList(w http.ResponseWriter, r *http.Request, bookings []storage.Booking, vehiclesMap any, groupsMap any) { +// files := renderer.ThemeConfig.GetStringSlice("views.vehicles.bookings_list.files") +// state := NewState(r, renderer.ThemeConfig, vehiclesMenu) +// state.ViewState = map[string]any{ +// "bookings": bookings, +// "vehicles_map": vehiclesMap, +// "groups_map": groupsMap, +// } + +// renderer.Render("vehicles search", w, r, files, state) +// } diff --git a/services/groupsmanagement.go b/services/groupsmanagement.go index 72a3715..08647b7 100644 --- a/services/groupsmanagement.go +++ b/services/groupsmanagement.go @@ -40,3 +40,19 @@ func (s *ServicesHandler) GetGroupsMap() (groups map[string]storage.Group, err e return } + +////////////////////////////////optimize the code////////////////////////////////////// +func (s *ServicesHandler) GetGroupsMemberMap(id string) (groups map[string]any, err error) { + groups = map[string]any{} + + request := &groupsmanagement.GetGroupsBatchMemberRequest{ + Groupids: []string{id}, + } + resp, err := s.GRPC.GroupsManagement.GetGroupsBatchMember(context.TODO(), request) + if err == nil { + for _, group := range resp.Groups { + groups[group.Memberid] = group.ToStorageType() + } + } + return +}