package application import ( "context" "fmt" "io" "net/http" "sort" "strings" "time" "git.coopgo.io/coopgo-apps/parcoursmob/utils/identification" "git.coopgo.io/coopgo-apps/parcoursmob/utils/sorting" filestorage "git.coopgo.io/coopgo-apps/parcoursmob/utils/storage" fleets "git.coopgo.io/coopgo-platform/fleets/grpcapi" "git.coopgo.io/coopgo-platform/fleets/storage" groupsmanagement "git.coopgo.io/coopgo-platform/groups-management/grpcapi" groupsmanagementstorage "git.coopgo.io/coopgo-platform/groups-management/storage" mobilityaccounts "git.coopgo.io/coopgo-platform/mobility-accounts/grpcapi" mobilityaccountsstorage "git.coopgo.io/coopgo-platform/mobility-accounts/storage" "github.com/google/uuid" "github.com/gorilla/mux" "github.com/rs/zerolog/log" "google.golang.org/protobuf/types/known/structpb" "google.golang.org/protobuf/types/known/timestamppb" ) func (h ApplicationHandler) VehiclesSearch(w http.ResponseWriter, r *http.Request) { r.ParseForm() fmt.Println("invoked") var beneficiary mobilityaccountsstorage.Account beneficiarydocuments := []filestorage.FileInfo{} vehicles := []any{} searched := false start := r.FormValue("startdate") end := r.FormValue("enddate") startdate, _ := time.Parse("2006-01-02", start) enddate, _ := time.Parse("2006-01-02", end) automatic := (r.FormValue("automatic") == "on") administrators := []string{} if r.FormValue("beneficiaryid") != "" { // Handler form searched = true requestbeneficiary := &mobilityaccounts.GetAccountRequest{ Id: r.FormValue("beneficiaryid"), } respbeneficiary, err := h.services.GRPC.MobilityAccounts.GetAccount(context.TODO(), requestbeneficiary) if err != nil { log.Error().Err(err).Msg("") w.WriteHeader(http.StatusInternalServerError) return } beneficiary = respbeneficiary.Account.ToStorageType() request := &fleets.GetVehiclesRequest{ Namespaces: []string{"parcoursmob"}, AvailabilityFrom: timestamppb.New(startdate), AvailabilityTo: timestamppb.New(enddate), } if r.FormValue("type") != "" { request.Types = []string{r.FormValue("type")} } resp, err := h.services.GRPC.Fleets.GetVehicles(context.TODO(), request) if err != nil { log.Error().Err(err).Msg("") w.WriteHeader(http.StatusInternalServerError) } for _, vehicle := range resp.Vehicles { v := vehicle.ToStorageType() if r.FormValue("type") == "Voiture" && automatic { fmt.Println(v.Data["automatic"]) if auto, ok := v.Data["automatic"].(bool); !ok || !auto { fmt.Println(v.Data["automatic"]) continue } } adminfound := false for _, a := range administrators { if a == v.Administrators[0] { adminfound = true break } } if !adminfound { administrators = append(administrators, v.Administrators[0]) } vehicles = append(vehicles, v) } beneficiarydocuments = h.filestorage.List(filestorage.PREFIX_BENEFICIARIES + "/" + beneficiary.ID) } accounts, err := h.beneficiaries(r) if err != nil { log.Error().Err(err).Msg("") w.WriteHeader(http.StatusBadRequest) return } groups := map[string]any{} if len(administrators) > 0 { admingroups, err := h.services.GRPC.GroupsManagement.GetGroupsBatch(context.TODO(), &groupsmanagement.GetGroupsBatchRequest{ Groupids: administrators, }) if err != nil { log.Error().Err(err).Msg("") w.WriteHeader(http.StatusInternalServerError) return } for _, g := range admingroups.Groups { groups[g.Id] = g.ToStorageType() } } sort.Sort(sorting.BeneficiariesByName(accounts)) mandatory_documents := h.config.GetStringSlice("modules.fleets.booking_documents.mandatory") file_types_map := h.config.GetStringMapString("storage.files.file_types") vehicles_types := h.config.GetStringSlice("modules.fleets.vehicle_types") h.Renderer.VehiclesSearch(w, r, accounts, searched, vehicles, beneficiary, r.FormValue("startdate"), r.FormValue("enddate"), mandatory_documents, file_types_map, beneficiarydocuments, r.FormValue("type"), automatic, vehicles_types, groups) } func (h ApplicationHandler) Book(w http.ResponseWriter, r *http.Request) { fmt.Println("Book") current_group, err := h.currentGroup(r) if err != nil { log.Error().Err(err).Msg("") w.WriteHeader(http.StatusInternalServerError) return } current_user_token, current_user_claims, err := h.currentUser(r) if err != nil { log.Error().Err(err).Msg("") w.WriteHeader(http.StatusInternalServerError) return } vars := mux.Vars(r) vehicleid := vars["vehicleid"] beneficiaryid := vars["beneficiaryid"] vehicle, err := h.services.GRPC.Fleets.GetVehicle(context.TODO(), &fleets.GetVehicleRequest{ Vehicleid: vehicleid, }) if err != nil { log.Error().Err(err).Msg("") w.WriteHeader(http.StatusInternalServerError) w.Write([]byte("Vehicle not found")) w.Write([]byte(err.Error())) return } r.ParseMultipartForm(100 * 1024 * 1024) start := r.FormValue("startdate") end := r.FormValue("enddate") startdate, _ := time.Parse("2006-01-02", start) enddate, _ := time.Parse("2006-01-02", end) data := map[string]any{ "booked_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"]), }, "group": map[string]any{ "id": current_group.ID, "name": current_group.Data["name"], }, }, } datapb, err := structpb.NewStruct(data) if err != nil { log.Error().Err(err).Msg("") w.WriteHeader(http.StatusInternalServerError) return } booking := &fleets.Booking{ Id: uuid.NewString(), Vehicleid: vehicleid, Driver: beneficiaryid, Startdate: timestamppb.New(startdate), Enddate: timestamppb.New(enddate), Unavailablefrom: timestamppb.New(startdate), Unavailableto: timestamppb.New(enddate.Add(72 * time.Hour)), Data: datapb, } request := &fleets.CreateBookingRequest{ Booking: booking, } for _, v := range h.config.GetStringSlice("modules.fleets.booking_documents.mandatory") { existing_file := r.FormValue("type-" + v) if existing_file == "" { file, header, err := r.FormFile("doc-" + v) if err != nil { log.Error().Err(err).Msg("") w.WriteHeader(http.StatusBadRequest) w.Write([]byte("Document manquant : " + v)) return } defer file.Close() fileid := uuid.NewString() metadata := map[string]string{ "type": v, "name": header.Filename, } if err := h.filestorage.Put(file, filestorage.PREFIX_BOOKINGS, fmt.Sprintf("%s/%s_%s", booking.Id, fileid, header.Filename), header.Size, metadata); err != nil { log.Error().Err(err).Msg("") w.WriteHeader(http.StatusInternalServerError) return } } else { path := strings.Split(existing_file, "/") if err := h.filestorage.Copy(existing_file, fmt.Sprintf("%s/%s/%s", filestorage.PREFIX_BOOKINGS, booking.Id, path[len(path)-1])); err != nil { log.Error().Err(err).Msg("") w.WriteHeader(http.StatusInternalServerError) return } } } _, err = h.services.GRPC.Fleets.CreateBooking(context.TODO(), request) if err != nil { log.Error().Err(err).Msg("") w.WriteHeader(http.StatusBadRequest) return } //NOTIFY GROUP MEMBERS members, _, err := h.groupmembers(vehicle.Vehicle.Administrators[0]) if err != nil { log.Error().Err(err).Msg("") } else { for _, m := range members { if email, ok := m.Data["email"].(string); ok { h.emailing.Send("fleets.bookings.creation_admin_alert", email, map[string]string{ "bookingid": booking.Id, }) } } } http.Redirect(w, r, fmt.Sprintf("/app/vehicles/bookings/%s", booking.Id), http.StatusFound) } func (h ApplicationHandler) VehicleBookingDisplay(w http.ResponseWriter, r *http.Request) { vars := mux.Vars(r) bookingid := vars["bookingid"] request := &fleets.GetBookingRequest{ Bookingid: bookingid, } resp, err := h.services.GRPC.Fleets.GetBooking(context.TODO(), request) if err != nil { log.Error().Err(err).Msg("") w.WriteHeader(http.StatusInternalServerError) return } booking := resp.Booking.ToStorageType() beneficiaryrequest := &mobilityaccounts.GetAccountRequest{ Id: booking.Driver, } beneficiaryresp, err := h.services.GRPC.MobilityAccounts.GetAccount(context.TODO(), beneficiaryrequest) if err != nil { beneficiaryresp = &mobilityaccounts.GetAccountResponse{ Account: &mobilityaccounts.Account{}, } } grouprequest := &groupsmanagement.GetGroupRequest{ Id: booking.Vehicle.Administrators[0], } groupresp, err := h.services.GRPC.GroupsManagement.GetGroup(context.TODO(), grouprequest) if err != nil { log.Error().Err(err).Msg("") w.WriteHeader(http.StatusInternalServerError) return } documents := h.filestorage.List(filestorage.PREFIX_BOOKINGS + "/" + bookingid) file_types_map := h.config.GetStringMapString("storage.files.file_types") h.Renderer.VehicleBookingDisplay(w, r, booking, booking.Vehicle, beneficiaryresp.Account.ToStorageType(), groupresp.Group.ToStorageType(), documents, file_types_map) } func (h ApplicationHandler) VehiclesBookingsList(w http.ResponseWriter, r *http.Request) { g := r.Context().Value(identification.GroupKey) if g == nil { w.WriteHeader(http.StatusBadRequest) return } group := g.(groupsmanagementstorage.Group) request := &fleets.GetBookingsRequest{} resp, err := h.services.GRPC.Fleets.GetBookings(context.TODO(), request) if err != nil { log.Error().Err(err).Msg("") w.WriteHeader(http.StatusNotFound) return } bookings := []storage.Booking{} for _, b := range resp.Bookings { booking := b.ToStorageType() if b1, ok := booking.Data["booked_by"].(map[string]any); ok { if b2, ok := b1["group"].(map[string]any); ok { if b2["id"] == group.ID { bookings = append(bookings, booking) } } } } sort.Sort(sorting.BookingsByStartdate(bookings)) vehicles, _ := h.services.GetVehiclesMap() groups, _ := h.services.GetGroupsMap() // fmt.Println("bookings : ", bookings) // fmt.Println("vehicles : ", vehicles) // fmt.Println("groups : ", groups) h.Renderer.VehicleBookingsList(w, r, bookings, vehicles, groups) } func (h *ApplicationHandler) BookingDocumentDownload(w http.ResponseWriter, r *http.Request) { vars := mux.Vars(r) bookingid := vars["bookingid"] document := vars["document"] fmt.Println(fmt.Sprintf("%s/%s", bookingid, document)) file, info, err := h.filestorage.Get(filestorage.PREFIX_BOOKINGS, fmt.Sprintf("%s/%s", bookingid, document)) if err != nil { log.Error().Err(err).Msg("") w.WriteHeader(http.StatusInternalServerError) return } w.Header().Set("Content-Type", info.ContentType) if _, err = io.Copy(w, file); err != nil { log.Error().Err(err).Msg("") w.WriteHeader(http.StatusInternalServerError) return } http.Redirect(w, r, fmt.Sprintf("/app/vehicles/bookings/%s", bookingid), http.StatusFound) }