package application import ( "encoding/json" "fmt" "net/http" "time" "git.coopgo.io/coopgo-apps/parcoursmob/core/utils/identification" "git.coopgo.io/coopgo-platform/groups-management/storage" "github.com/coreos/go-oidc/v3/oidc" "github.com/gorilla/mux" "github.com/rs/zerolog/log" ) func (h *Handler) VehiclesManagementOverviewHTTPHandler() http.HandlerFunc { return func(w http.ResponseWriter, r *http.Request) { // Extract filter parameters from request groupID := "" if g := r.Context().Value(identification.GroupKey); g != nil { group := g.(storage.Group) groupID = group.ID } result, err := h.applicationHandler.GetVehiclesManagementOverview(r.Context(), groupID) if err != nil { log.Error().Err(err).Msg("error retrieving vehicles management overview") http.Error(w, "Internal Server Error", http.StatusInternalServerError) return } h.renderer.VehiclesManagementOverview(w, r, result.Vehicles, result.VehiclesMap, result.DriversMap, result.Bookings) } } func (h *Handler) VehiclesManagementBookingsListHTTPHandler() http.HandlerFunc { return func(w http.ResponseWriter, r *http.Request) { // Extract filter parameters from request groupID := "" if g := r.Context().Value(identification.GroupKey); g != nil { group := g.(storage.Group) groupID = group.ID } // Extract filter parameters from query status := r.URL.Query().Get("status") dateStart := r.URL.Query().Get("date_start") dateEnd := r.URL.Query().Get("date_end") // Default to last month if no dates specified if dateStart == "" { dateStart = time.Now().AddDate(0, -1, 0).Format("2006-01-02") } if dateEnd == "" { dateEnd = time.Now().Format("2006-01-02") } result, err := h.applicationHandler.GetVehiclesManagementBookingsList(r.Context(), groupID, status, dateStart, dateEnd) if err != nil { log.Error().Err(err).Msg("error retrieving vehicles management bookings list") http.Error(w, "Internal Server Error", http.StatusInternalServerError) return } // Prepare filters map for template filters := map[string]string{ "status": status, "date_start": dateStart, "date_end": dateEnd, } h.renderer.VehiclesManagementBookingsList(w, r, result.VehiclesMap, result.DriversMap, result.Bookings, result.CacheID, filters) } } func (h *Handler) VehiclesFleetAddHTTPHandler() http.HandlerFunc { return func(w http.ResponseWriter, r *http.Request) { if r.Method == "POST" { // Get group from context g := r.Context().Value(identification.GroupKey) if g == nil { http.Error(w, "Bad Request", http.StatusBadRequest) return } // Parse form data if err := r.ParseForm(); err != nil { log.Error().Err(err).Msg("error parsing form") http.Error(w, "Bad Request", http.StatusBadRequest) return } // Parse address JSON var address map[string]any if addressStr := r.FormValue("address"); addressStr != "" { if err := json.Unmarshal([]byte(addressStr), &address); err != nil { log.Error().Err(err).Msg("error parsing address JSON") http.Error(w, "Internal Server Error", http.StatusInternalServerError) return } } // Parse other_properties from form fields otherProperties := make(map[string]any) vehicleOptionalFields := h.cfg.Get("modules.fleets.vehicle_optional_fields") log.Debug().Msgf("CREATE: vehicleOptionalFields type: %T, value: %+v", vehicleOptionalFields, vehicleOptionalFields) if fields, ok := vehicleOptionalFields.([]map[string]any); ok { log.Debug().Msgf("CREATE: Successfully cast to []map[string]any, length: %d", len(fields)) for _, field := range fields { log.Debug().Any("field", field).Msg("vehicle other properties field handling") if fieldName, ok := field["name"].(string); ok { value := r.FormValue(fieldName) log.Debug().Msgf("CREATE: Field %s: value='%s'", fieldName, value) if value != "" { otherProperties[fieldName] = value } } } } else { log.Debug().Msg("CREATE: Failed to cast vehicleOptionalFields to []map[string]any") } log.Debug().Msgf("CREATE: Final otherProperties: %+v", otherProperties) vehicleID, err := h.applicationHandler.CreateVehicle(r.Context(), r.FormValue("name"), r.FormValue("type"), r.FormValue("informations"), r.FormValue("licence_plate"), r.FormValue("kilometers"), r.FormValue("automatic") == "on", address, otherProperties, ) if err != nil { log.Error().Err(err).Msg("error creating vehicle") http.Error(w, "Internal Server Error", http.StatusInternalServerError) return } http.Redirect(w, r, fmt.Sprintf("/app/vehicles-management/fleet/%s", vehicleID), http.StatusFound) return } // GET request - show form vehicleTypes, err := h.applicationHandler.GetVehicleTypes(r.Context()) if err != nil { log.Error().Err(err).Msg("error getting vehicle types") http.Error(w, "Internal Server Error", http.StatusInternalServerError) return } h.renderer.VehiclesFleetAdd(w, r, vehicleTypes) } } func (h *Handler) VehiclesFleetDisplayHTTPHandler() http.HandlerFunc { return func(w http.ResponseWriter, r *http.Request) { vars := mux.Vars(r) vehicleID := vars["vehicleid"] result, err := h.applicationHandler.GetVehicleDisplay(r.Context(), vehicleID) if err != nil { log.Error().Err(err).Msg("error retrieving vehicle display") http.Error(w, "Internal Server Error", http.StatusInternalServerError) return } h.renderer.VehiclesFleetDisplay(w, r, result.Vehicle, result.Beneficiaries) } } func (h *Handler) VehicleManagementBookingDisplayHTTPHandler() http.HandlerFunc { return func(w http.ResponseWriter, r *http.Request) { vars := mux.Vars(r) bookingID := vars["bookingid"] if r.Method == "POST" { // Parse form data r.ParseForm() err := h.applicationHandler.UpdateBooking(r.Context(), bookingID, r.FormValue("startdate"), r.FormValue("enddate"), r.FormValue("unavailablefrom"), r.FormValue("unavailableto"), ) if err != nil { log.Error().Err(err).Msg("error updating booking") http.Error(w, "Internal Server Error", http.StatusInternalServerError) return } } result, err := h.applicationHandler.GetBookingDisplay(r.Context(), bookingID) if err != nil { log.Error().Err(err).Msg("error retrieving booking display") http.Error(w, "Internal Server Error", http.StatusInternalServerError) return } h.renderer.VehicleManagementBookingDisplay(w, r, result.Booking, result.Vehicle, result.Beneficiary, result.Group, result.Documents, result.FileTypesMap, result.Alternatives) } } func (h *Handler) VehicleManagementBookingChangeVehicleHTTPHandler() http.HandlerFunc { return func(w http.ResponseWriter, r *http.Request) { vars := mux.Vars(r) bookingID := vars["bookingid"] r.ParseForm() newVehicle := r.FormValue("vehicle") err := h.applicationHandler.ChangeBookingVehicle(r.Context(), bookingID, newVehicle) if err != nil { log.Error().Err(err).Msg("error changing booking vehicle") http.Error(w, "Internal Server Error", http.StatusInternalServerError) return } http.Redirect(w, r, fmt.Sprintf("/app/vehicles-management/bookings/%s", bookingID), http.StatusFound) } } func (h *Handler) VehiclesFleetMakeUnavailableHTTPHandler() http.HandlerFunc { return func(w http.ResponseWriter, r *http.Request) { // Get context values g := r.Context().Value(identification.GroupKey) if g == nil { log.Error().Msg("no current group") http.Error(w, "Internal Server Error", http.StatusInternalServerError) return } u := r.Context().Value(identification.IdtokenKey) if u == nil { log.Error().Msg("no current user") http.Error(w, "Internal Server Error", http.StatusInternalServerError) return } currentUserToken := u.(*oidc.IDToken) c := r.Context().Value(identification.ClaimsKey) if c == nil { log.Error().Msg("no current user claims") http.Error(w, "Internal Server Error", http.StatusInternalServerError) return } currentUserClaims := c.(map[string]any) vars := mux.Vars(r) vehicleID := vars["vehicleid"] r.ParseForm() err := h.applicationHandler.MakeVehicleUnavailable(r.Context(), vehicleID, r.FormValue("unavailablefrom"), r.FormValue("unavailableto"), r.FormValue("comment"), currentUserToken.Subject, currentUserClaims, ) if err != nil { log.Error().Err(err).Msg("error making vehicle unavailable") http.Error(w, "Bad Request", http.StatusBadRequest) return } http.Redirect(w, r, fmt.Sprintf("/app/vehicles-management/fleet/%s", vehicleID), http.StatusFound) } } func (h *Handler) DeleteBookingHTTPHandler() http.HandlerFunc { return func(w http.ResponseWriter, r *http.Request) { vars := mux.Vars(r) bookingID := vars["bookingid"] // Get form data motif := r.FormValue("motif") // Get current user information currentUserToken := r.Context().Value(identification.IdtokenKey).(*oidc.IDToken) currentUserClaims := r.Context().Value(identification.ClaimsKey).(map[string]any) currentGroup := r.Context().Value(identification.GroupKey) err := h.applicationHandler.UnbookVehicle(r.Context(), bookingID, motif, currentUserToken.Subject, currentUserClaims, currentGroup) if err != nil { log.Error().Err(err).Msg("error unbooking vehicle") http.Error(w, "Internal Server Error", http.StatusInternalServerError) return } http.Redirect(w, r, "/app/vehicles-management/bookings/", http.StatusSeeOther) } } func (h *Handler) UnbookingVehicleHTTPHandler() http.HandlerFunc { return func(w http.ResponseWriter, r *http.Request) { vars := mux.Vars(r) bookingID := vars["bookingid"] if r.Method == "POST" { // Extract user and group info from context currentUserToken := r.Context().Value(identification.IdtokenKey).(*oidc.IDToken) currentUserClaims := r.Context().Value(identification.ClaimsKey).(map[string]any) currentGroup := r.Context().Value(identification.GroupKey) motif := r.FormValue("motif") err := h.applicationHandler.UnbookVehicle(r.Context(), bookingID, motif, currentUserToken.Subject, currentUserClaims, currentGroup) if err != nil { log.Error().Err(err).Msg("error unbooking vehicle") http.Error(w, "Internal Server Error", http.StatusInternalServerError) return } http.Redirect(w, r, "/app/vehicles-management/", http.StatusFound) return } // GET request - show form booking, err := h.applicationHandler.GetBookingForUnbooking(r.Context(), bookingID) if err != nil { log.Error().Err(err).Msg("error retrieving booking for unbooking") http.Error(w, "Internal Server Error", http.StatusInternalServerError) return } h.renderer.UnbookingVehicle(w, r, booking) } } func (h *Handler) VehiclesFleetUpdateHTTPHandler() http.HandlerFunc { return func(w http.ResponseWriter, r *http.Request) { vars := mux.Vars(r) vehicleID := vars["vehicleid"] if r.Method == "POST" { if err := r.ParseForm(); err != nil { log.Error().Err(err).Msg("error parsing form") http.Error(w, "Bad Request", http.StatusBadRequest) return } // Parse address JSON var address map[string]any if addressStr := r.FormValue("address"); addressStr != "" { if err := json.Unmarshal([]byte(addressStr), &address); err != nil { log.Error().Err(err).Msg("error parsing address JSON") http.Error(w, "Internal Server Error", http.StatusInternalServerError) return } } // Parse other_properties from form fields otherProperties := make(map[string]any) vehicleOptionalFields := h.cfg.Get("modules.fleets.vehicle_optional_fields") log.Debug().Msgf("UPDATE: vehicleOptionalFields type: %T, value: %+v", vehicleOptionalFields, vehicleOptionalFields) if fields, ok := vehicleOptionalFields.([]any); ok { log.Debug().Msgf("UPDATE: Successfully cast to []map[string]any, length: %d", len(fields)) for _, f := range fields { if field, ok := f.(map[string]any); ok { log.Debug().Any("field", field).Msg("vehicle other properties field handling (update)") if fieldName, ok := field["name"].(string); ok { value := r.FormValue(fieldName) log.Debug().Msgf("UPDATE: Field %s: value='%s'", fieldName, value) if value != "" { otherProperties[fieldName] = value } } } } } else { log.Debug().Msg("UPDATE: Failed to cast vehicleOptionalFields to []map[string]any") } log.Debug().Msgf("UPDATE: Final otherProperties: %+v", otherProperties) updatedVehicleID, err := h.applicationHandler.UpdateVehicle(r.Context(), vehicleID, r.FormValue("name"), r.FormValue("type"), r.FormValue("informations"), r.FormValue("licence_plate"), r.FormValue("kilometers"), r.FormValue("automatic") == "on", address, otherProperties, ) if err != nil { log.Error().Err(err).Msg("error updating vehicle") http.Error(w, "Internal Server Error", http.StatusInternalServerError) return } http.Redirect(w, r, fmt.Sprintf("/app/vehicles-management/fleet/%s", updatedVehicleID), http.StatusFound) return } // GET request - show form result, err := h.applicationHandler.GetVehicleForUpdate(r.Context(), vehicleID) if err != nil { log.Error().Err(err).Msg("error retrieving vehicle for update") http.Error(w, "Internal Server Error", http.StatusInternalServerError) return } h.renderer.VehiclesFleetUpdate(w, r, result.Vehicle, result.VehicleTypes) } }