parcoursmob/servers/web/application/vehicles_management.go

409 lines
13 KiB
Go

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)
}
}