package xlsx import ( "fmt" "net/http" fleetsstorage "git.coopgo.io/coopgo-platform/fleets/storage" groupsstorage "git.coopgo.io/coopgo-platform/groups-management/storage" mobilityaccountsstorage "git.coopgo.io/coopgo-platform/mobility-accounts/storage" "github.com/rs/zerolog/log" ) func (r *XLSXRenderer) VehicleBookings(w http.ResponseWriter, bookings []fleetsstorage.Booking, vehiclesMap map[string]fleetsstorage.Vehicle, driversMap map[string]mobilityaccountsstorage.Account) { // Create Excel spreadsheet spreadsheet := r.NewSpreadsheet("Réservations véhicules") // Build headers headers := []string{ "ID Réservation", "Statut", "Type de véhicule", "Nom du véhicule", "Immatriculation", } // Add beneficiary fields from config beneficiaryOptionalFields := r.Config.Get("modules.beneficiaries.profile_optional_fields") beneficiaryFields := []string{"last_name", "first_name", "email", "phone_number"} beneficiaryHeaders := []string{"Bénéficiaire - Nom", "Bénéficiaire - Prénom", "Bénéficiaire - Email", "Bénéficiaire - Téléphone"} if beneficiaryOptionalFieldsList, ok := beneficiaryOptionalFields.([]interface{}); ok { for _, field := range beneficiaryOptionalFieldsList { if fieldMap, ok := field.(map[string]interface{}); ok { if name, ok := fieldMap["name"].(string); ok { beneficiaryFields = append(beneficiaryFields, name) label := name if labelVal, ok := fieldMap["label"].(string); ok { label = labelVal } beneficiaryHeaders = append(beneficiaryHeaders, fmt.Sprintf("Bénéficiaire - %s", label)) } } } } headers = append(headers, beneficiaryHeaders...) // Add booking date headers headers = append(headers, "Date de début", "Date de fin", "Durée (jours)", "Commentaire", "Raison d'annulation", ) spreadsheet.SetHeaders(headers) // Add data rows for _, booking := range bookings { vehicle := vehiclesMap[booking.Vehicleid] beneficiary := driversMap[booking.Driver] row := []interface{}{} // Booking information row = append(row, booking.ID) // Status status := "" if booking.Deleted { status = "Annulé" } else { switch booking.Status() { case 1: status = "A venir" case 0: status = "En cours" case -1: status = "Terminé" } } row = append(row, status) // Vehicle information row = append(row, vehicle.Type) if vehicleName, ok := vehicle.Data["name"].(string); ok { row = append(row, vehicleName) } else { row = append(row, "") } if licencePlate, ok := vehicle.Data["licence_plate"].(string); ok { row = append(row, licencePlate) } else { row = append(row, "") } // Beneficiary data (including other_properties) for _, field := range beneficiaryFields { value := "" // First check direct field if val, ok := beneficiary.Data[field]; ok && val != nil { value = fmt.Sprint(val) } else { // Check in other_properties if otherProps, ok := beneficiary.Data["other_properties"]; ok { if otherPropsMap, ok := otherProps.(map[string]interface{}); ok { if val, ok := otherPropsMap[field]; ok && val != nil { value = fmt.Sprint(val) } } } } row = append(row, value) } // Booking dates row = append(row, booking.Startdate.Format("2006-01-02")) row = append(row, booking.Enddate.Format("2006-01-02")) // Duration in days duration := booking.Enddate.Sub(booking.Startdate).Hours() / 24 row = append(row, fmt.Sprintf("%.0f", duration)) // Comment comment := "" if booking.Data != nil { if commentVal, ok := booking.Data["comment"]; ok && commentVal != nil { comment = fmt.Sprint(commentVal) } } row = append(row, comment) // Cancellation reason cancellationReason := "" if booking.Deleted && booking.Data != nil { if reasonVal, ok := booking.Data["reason"]; ok && reasonVal != nil { cancellationReason = fmt.Sprint(reasonVal) } } row = append(row, cancellationReason) spreadsheet.AddRow(row) } // Write Excel to response w.Header().Set("Content-Type", "application/vnd.openxmlformats-officedocument.spreadsheetml.sheet") w.Header().Set("Content-Disposition", "attachment; filename=\"export-reservations-vehicules.xlsx\"") if err := spreadsheet.GetFile().Write(w); err != nil { log.Error().Err(err).Msg("Error generating Excel file") http.Error(w, "Error generating Excel file", http.StatusInternalServerError) return } } func (r *XLSXRenderer) VehicleBookingsAdmin(w http.ResponseWriter, bookings []fleetsstorage.Booking, vehiclesMap map[string]interface{}, driversMap map[string]interface{}, groupsMap map[string]any) { // Create Excel spreadsheet spreadsheet := r.NewSpreadsheet("Réservations véhicules") // Build headers headers := []string{ "ID Réservation", "Statut", "Date de début", "Date de fin", "Durée (jours)", "Commentaire", "Raison d'annulation", "Type de véhicule", "Nom du véhicule", "Immatriculation", "Gestionnaire véhicule", } // Add vehicle optional fields from config vehicleOptionalFields := r.Config.Get("modules.fleets.vehicle_optional_fields") vehicleFields := []string{} vehicleHeaders := []string{} if vehicleOptionalFieldsList, ok := vehicleOptionalFields.([]interface{}); ok { for _, field := range vehicleOptionalFieldsList { if fieldMap, ok := field.(map[string]interface{}); ok { if name, ok := fieldMap["name"].(string); ok { vehicleFields = append(vehicleFields, name) label := name if labelVal, ok := fieldMap["label"].(string); ok { label = labelVal } vehicleHeaders = append(vehicleHeaders, fmt.Sprintf("Véhicule - %s", label)) } } } } headers = append(headers, vehicleHeaders...) // Add beneficiary fields from config beneficiaryOptionalFields := r.Config.Get("modules.beneficiaries.profile_optional_fields") beneficiaryFields := []string{"last_name", "first_name", "email", "phone_number"} beneficiaryHeaders := []string{"Bénéficiaire - Nom", "Bénéficiaire - Prénom", "Bénéficiaire - Email", "Bénéficiaire - Téléphone"} if beneficiaryOptionalFieldsList, ok := beneficiaryOptionalFields.([]interface{}); ok { for _, field := range beneficiaryOptionalFieldsList { if fieldMap, ok := field.(map[string]interface{}); ok { if name, ok := fieldMap["name"].(string); ok { beneficiaryFields = append(beneficiaryFields, name) label := name if labelVal, ok := fieldMap["label"].(string); ok { label = labelVal } beneficiaryHeaders = append(beneficiaryHeaders, fmt.Sprintf("Bénéficiaire - %s", label)) } } } } headers = append(headers, beneficiaryHeaders...) spreadsheet.SetHeaders(headers) // Add data rows for _, booking := range bookings { // Get vehicle from map var vehicle fleetsstorage.Vehicle if v, ok := vehiclesMap[booking.Vehicleid]; ok { if vTyped, ok := v.(fleetsstorage.Vehicle); ok { vehicle = vTyped } } // Get beneficiary from map var beneficiary mobilityaccountsstorage.Account if d, ok := driversMap[booking.Driver]; ok { if dTyped, ok := d.(mobilityaccountsstorage.Account); ok { beneficiary = dTyped } } row := []interface{}{} // Booking information row = append(row, booking.ID) // Status status := "" if booking.Deleted { status = "Annulé" } else { switch booking.Status() { case 1: status = "A venir" case 0: status = "En cours" case -1: status = "Terminé" } } row = append(row, status) // Booking dates row = append(row, booking.Startdate.Format("2006-01-02")) row = append(row, booking.Enddate.Format("2006-01-02")) // Duration in days duration := booking.Enddate.Sub(booking.Startdate).Hours() / 24 row = append(row, fmt.Sprintf("%.0f", duration)) // Comment comment := "" if booking.Data != nil { if commentVal, ok := booking.Data["comment"]; ok && commentVal != nil { comment = fmt.Sprint(commentVal) } } row = append(row, comment) // Cancellation reason cancellationReason := "" if booking.Deleted && booking.Data != nil { if reasonVal, ok := booking.Data["reason"]; ok && reasonVal != nil { cancellationReason = fmt.Sprint(reasonVal) } } row = append(row, cancellationReason) // Vehicle information row = append(row, vehicle.Type) if vehicleName, ok := vehicle.Data["name"].(string); ok { row = append(row, vehicleName) } else { row = append(row, "") } if licencePlate, ok := vehicle.Data["licence_plate"].(string); ok { row = append(row, licencePlate) } else { row = append(row, "") } // Vehicle administrator (group name) administratorName := "" if len(vehicle.Administrators) > 0 { if group, ok := groupsMap[vehicle.Administrators[0]]; ok { if groupTyped, ok := group.(groupsstorage.Group); ok { if name, ok := groupTyped.Data["name"]; ok { administratorName = fmt.Sprint(name) } } } } row = append(row, administratorName) // Vehicle optional fields for _, field := range vehicleFields { value := "" if val, ok := vehicle.Data[field]; ok && val != nil { value = fmt.Sprint(val) } row = append(row, value) } // Beneficiary data (including other_properties) for _, field := range beneficiaryFields { value := "" // First check direct field if val, ok := beneficiary.Data[field]; ok && val != nil { value = fmt.Sprint(val) } else { // Check in other_properties if otherProps, ok := beneficiary.Data["other_properties"]; ok { if otherPropsMap, ok := otherProps.(map[string]interface{}); ok { if val, ok := otherPropsMap[field]; ok && val != nil { value = fmt.Sprint(val) } } } } row = append(row, value) } spreadsheet.AddRow(row) } // Write Excel to response w.Header().Set("Content-Type", "application/vnd.openxmlformats-officedocument.spreadsheetml.sheet") w.Header().Set("Content-Disposition", "attachment; filename=\"all_bookings.xlsx\"") if err := spreadsheet.GetFile().Write(w); err != nil { log.Error().Err(err).Msg("Error generating Excel file") http.Error(w, "Error generating Excel file", http.StatusInternalServerError) return } }