429 lines
		
	
	
		
			13 KiB
		
	
	
	
		
			Go
		
	
	
	
			
		
		
	
	
			429 lines
		
	
	
		
			13 KiB
		
	
	
	
		
			Go
		
	
	
	
package application
 | 
						|
 | 
						|
import (
 | 
						|
	"context"
 | 
						|
	"encoding/json"
 | 
						|
	"fmt"
 | 
						|
	"sort"
 | 
						|
	"strconv"
 | 
						|
 | 
						|
	"git.coopgo.io/coopgo-apps/parcoursmob/core/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"
 | 
						|
	fleetsstorage "git.coopgo.io/coopgo-platform/fleets/storage"
 | 
						|
	groupsmanagement "git.coopgo.io/coopgo-platform/groups-management/grpcapi"
 | 
						|
	groupsstorage "git.coopgo.io/coopgo-platform/groups-management/storage"
 | 
						|
	accounts "git.coopgo.io/coopgo-platform/mobility-accounts/grpcapi"
 | 
						|
	accountsstorage "git.coopgo.io/coopgo-platform/mobility-accounts/storage"
 | 
						|
	"github.com/xuri/excelize/v2"
 | 
						|
)
 | 
						|
 | 
						|
type FlatMaps []map[string]any
 | 
						|
 | 
						|
func (maps FlatMaps) GetHeaders() (res []string) {
 | 
						|
	keys := map[string]bool{}
 | 
						|
	for _, m := range maps {
 | 
						|
		for k, _ := range m {
 | 
						|
			if _, ok := keys[k]; !ok {
 | 
						|
				keys[k] = true
 | 
						|
				res = append(res, k)
 | 
						|
			}
 | 
						|
		}
 | 
						|
	}
 | 
						|
	sort.Strings(res)
 | 
						|
	return
 | 
						|
}
 | 
						|
 | 
						|
func (maps FlatMaps) GetValues() (res [][]string) {
 | 
						|
	headers := maps.GetHeaders()
 | 
						|
	for _, m := range maps {
 | 
						|
		line := []string{}
 | 
						|
		for _, k := range headers {
 | 
						|
			if v, ok := m[k]; ok && v != nil {
 | 
						|
				line = append(line, fmt.Sprint(v))
 | 
						|
			} else {
 | 
						|
				line = append(line, "")
 | 
						|
			}
 | 
						|
		}
 | 
						|
		res = append(res, line)
 | 
						|
	}
 | 
						|
	return
 | 
						|
}
 | 
						|
 | 
						|
type ExportCacheResult struct {
 | 
						|
	Headers []string
 | 
						|
	Values  [][]string
 | 
						|
}
 | 
						|
 | 
						|
func (h *ApplicationHandler) ExportCacheAsCSV(cacheID string) (*ExportCacheResult, error) {
 | 
						|
	d, err := h.cache.Get(cacheID)
 | 
						|
	if err != nil {
 | 
						|
		return nil, err
 | 
						|
	}
 | 
						|
 | 
						|
	var data []any
 | 
						|
	if dataSlice, ok := d.([]any); ok {
 | 
						|
		data = dataSlice
 | 
						|
	} else {
 | 
						|
		// Convert single item to slice
 | 
						|
		jsonData, err := json.Marshal(d)
 | 
						|
		if err != nil {
 | 
						|
			return nil, err
 | 
						|
		}
 | 
						|
		if err := json.Unmarshal(jsonData, &data); err != nil {
 | 
						|
			return nil, err
 | 
						|
		}
 | 
						|
	}
 | 
						|
 | 
						|
	flatmaps := FlatMaps{}
 | 
						|
	for _, v := range data {
 | 
						|
		if vMap, ok := v.(map[string]any); ok {
 | 
						|
			fm := map[string]any{}
 | 
						|
			flatten("", vMap, fm)
 | 
						|
			flatmaps = append(flatmaps, fm)
 | 
						|
		}
 | 
						|
	}
 | 
						|
 | 
						|
	return &ExportCacheResult{
 | 
						|
		Headers: flatmaps.GetHeaders(),
 | 
						|
		Values:  flatmaps.GetValues(),
 | 
						|
	}, nil
 | 
						|
}
 | 
						|
 | 
						|
func flatten(prefix string, src map[string]any, dest map[string]any) {
 | 
						|
	if len(prefix) > 0 {
 | 
						|
		prefix += "."
 | 
						|
	}
 | 
						|
	for k, v := range src {
 | 
						|
		switch child := v.(type) {
 | 
						|
		case map[string]any:
 | 
						|
			flatten(prefix+k, child, dest)
 | 
						|
		case []any:
 | 
						|
			for i := 0; i < len(child); i++ {
 | 
						|
				dest[prefix+k+"."+strconv.Itoa(i)] = child[i]
 | 
						|
			}
 | 
						|
		default:
 | 
						|
			dest[prefix+k] = v
 | 
						|
		}
 | 
						|
	}
 | 
						|
}
 | 
						|
 | 
						|
type AgendaExportResult struct {
 | 
						|
	ExcelFile *excelize.File
 | 
						|
}
 | 
						|
 | 
						|
func (h *ApplicationHandler) ExportAllAgendaEvents() (*AgendaExportResult, error) {
 | 
						|
	resp, err := h.services.GRPC.Agenda.GetEvents(context.TODO(), &agenda.GetEventsRequest{
 | 
						|
		Namespaces: []string{"parcoursmob_dispositifs"},
 | 
						|
	})
 | 
						|
	if err != nil {
 | 
						|
		return nil, err
 | 
						|
	}
 | 
						|
 | 
						|
	events := []agendastorage.Event{}
 | 
						|
	groupids := []string{}
 | 
						|
	beneficiaries_ids := []string{}
 | 
						|
 | 
						|
	for _, e := range resp.Events {
 | 
						|
		groupids = append(groupids, e.Owners...)
 | 
						|
		events = append(events, e.ToStorageType())
 | 
						|
 | 
						|
		for _, subscriptions := range e.Subscriptions {
 | 
						|
			beneficiaries_ids = append(beneficiaries_ids, subscriptions.Subscriber)
 | 
						|
		}
 | 
						|
	}
 | 
						|
 | 
						|
	sort.Sort(sorting.EventsByStartdate(events))
 | 
						|
 | 
						|
	groups, beneficiaries_map, err := h.getAgendaMetadata(groupids, beneficiaries_ids)
 | 
						|
	if err != nil {
 | 
						|
		return nil, err
 | 
						|
	}
 | 
						|
 | 
						|
	file := h.generateAgendaExcel(events, groups, beneficiaries_map)
 | 
						|
	return &AgendaExportResult{ExcelFile: file}, nil
 | 
						|
}
 | 
						|
 | 
						|
func (h *ApplicationHandler) ExportSingleAgendaEvent(eventID string) (*AgendaExportResult, error) {
 | 
						|
	resp, err := h.services.GRPC.Agenda.GetEvent(context.TODO(), &agenda.GetEventRequest{
 | 
						|
		Id: eventID,
 | 
						|
	})
 | 
						|
	if err != nil {
 | 
						|
		return nil, err
 | 
						|
	}
 | 
						|
 | 
						|
	groupids := []string{}
 | 
						|
	beneficiaries_ids := []string{}
 | 
						|
	groupids = append(groupids, resp.Event.Owners...)
 | 
						|
 | 
						|
	for _, subscriptions := range resp.Event.Subscriptions {
 | 
						|
		beneficiaries_ids = append(beneficiaries_ids, subscriptions.Subscriber)
 | 
						|
	}
 | 
						|
 | 
						|
	groups, beneficiaries_map, err := h.getAgendaMetadata(groupids, beneficiaries_ids)
 | 
						|
	if err != nil {
 | 
						|
		return nil, err
 | 
						|
	}
 | 
						|
 | 
						|
	events := []agendastorage.Event{resp.Event.ToStorageType()}
 | 
						|
	file := h.generateAgendaExcel(events, groups, beneficiaries_map)
 | 
						|
	return &AgendaExportResult{ExcelFile: file}, nil
 | 
						|
}
 | 
						|
 | 
						|
func (h *ApplicationHandler) getAgendaMetadata(groupids, beneficiaries_ids []string) (map[string]groupsstorage.Group, map[string]accountsstorage.Account, error) {
 | 
						|
	groupsresp, err := h.services.GRPC.GroupsManagement.GetGroupsBatch(context.TODO(), &groupsmanagement.GetGroupsBatchRequest{
 | 
						|
		Groupids: groupids,
 | 
						|
	})
 | 
						|
 | 
						|
	groups := map[string]groupsstorage.Group{}
 | 
						|
	if err == nil {
 | 
						|
		for _, g := range groupsresp.Groups {
 | 
						|
			groups[g.Id] = g.ToStorageType()
 | 
						|
		}
 | 
						|
	}
 | 
						|
 | 
						|
	beneficiaries, err := h.services.GRPC.MobilityAccounts.GetAccountsBatch(context.TODO(), &accounts.GetAccountsBatchRequest{
 | 
						|
		Accountids: beneficiaries_ids,
 | 
						|
	})
 | 
						|
	if err != nil {
 | 
						|
		return nil, nil, err
 | 
						|
	}
 | 
						|
 | 
						|
	beneficiaries_map := map[string]accountsstorage.Account{}
 | 
						|
	for _, ben := range beneficiaries.Accounts {
 | 
						|
		beneficiaries_map[ben.Id] = ben.ToStorageType()
 | 
						|
	}
 | 
						|
 | 
						|
	return groups, beneficiaries_map, nil
 | 
						|
}
 | 
						|
 | 
						|
func (h *ApplicationHandler) generateAgendaExcel(events []agendastorage.Event, groups map[string]groupsstorage.Group, beneficiaries_map map[string]accountsstorage.Account) *excelize.File {
 | 
						|
	f := excelize.NewFile()
 | 
						|
 | 
						|
	f.SetCellValue("Sheet1", "A1", "Evénement")
 | 
						|
	f.SetCellValue("Sheet1", "B1", "Date de début")
 | 
						|
	f.SetCellValue("Sheet1", "C1", "Date de fin")
 | 
						|
	f.SetCellValue("Sheet1", "D1", "Nom bénéficiaire")
 | 
						|
	f.SetCellValue("Sheet1", "E1", "Prenom bénéficiaire")
 | 
						|
	f.SetCellValue("Sheet1", "F1", "Numéro allocataire / Pole emploi")
 | 
						|
	f.SetCellValue("Sheet1", "G1", "Prescipteur")
 | 
						|
	f.SetCellValue("Sheet1", "H1", "Prescipteur Nom")
 | 
						|
	f.SetCellValue("Sheet1", "I1", "Prescipteur Email")
 | 
						|
	f.SetCellValue("Sheet1", "J1", "Gestionnaire événement")
 | 
						|
 | 
						|
	i := 2
 | 
						|
	for _, e := range events {
 | 
						|
		if len(e.Owners) == 0 {
 | 
						|
			continue
 | 
						|
		}
 | 
						|
		admin := groups[e.Owners[0]]
 | 
						|
 | 
						|
		for _, s := range e.Subscriptions {
 | 
						|
			subscribedbygroup := ""
 | 
						|
			subscribedbyuser := ""
 | 
						|
			subscribedbyemail := ""
 | 
						|
			if v, ok := s.Data["subscribed_by"].(map[string]any); ok {
 | 
						|
				if v2, ok := v["group"].(map[string]any); ok {
 | 
						|
					if v3, ok := v2["name"].(string); ok {
 | 
						|
						subscribedbygroup = v3
 | 
						|
					}
 | 
						|
				}
 | 
						|
				if v4, ok := v["user"].(map[string]any); ok {
 | 
						|
					if v5, ok := v4["display_name"].(string); ok {
 | 
						|
						subscribedbyuser = v5
 | 
						|
					}
 | 
						|
					if v6, ok := v4["email"].(string); ok {
 | 
						|
						subscribedbyemail = v6
 | 
						|
					}
 | 
						|
				}
 | 
						|
			}
 | 
						|
 | 
						|
			beneficiary := beneficiaries_map[s.Subscriber]
 | 
						|
 | 
						|
			f.SetCellValue("Sheet1", fmt.Sprintf("A%d", i), e.Name)
 | 
						|
			f.SetCellValue("Sheet1", fmt.Sprintf("B%d", i), e.Startdate.Format("2006-01-02"))
 | 
						|
			f.SetCellValue("Sheet1", fmt.Sprintf("C%d", i), e.Enddate.Format("2006-01-02"))
 | 
						|
			f.SetCellValue("Sheet1", fmt.Sprintf("D%d", i), beneficiary.Data["last_name"])
 | 
						|
			f.SetCellValue("Sheet1", fmt.Sprintf("E%d", i), beneficiary.Data["first_name"])
 | 
						|
			f.SetCellValue("Sheet1", fmt.Sprintf("F%d", i), beneficiary.Data["file_number"])
 | 
						|
			f.SetCellValue("Sheet1", fmt.Sprintf("G%d", i), subscribedbygroup)
 | 
						|
			f.SetCellValue("Sheet1", fmt.Sprintf("H%d", i), subscribedbyuser)
 | 
						|
			f.SetCellValue("Sheet1", fmt.Sprintf("I%d", i), subscribedbyemail)
 | 
						|
			f.SetCellValue("Sheet1", fmt.Sprintf("J%d", i), admin.Data["name"])
 | 
						|
			i = i + 1
 | 
						|
		}
 | 
						|
	}
 | 
						|
	return f
 | 
						|
}
 | 
						|
 | 
						|
type FleetBookingsExportResult struct {
 | 
						|
	ExcelFile *excelize.File
 | 
						|
}
 | 
						|
 | 
						|
func (h *ApplicationHandler) ExportAllFleetBookings() (*FleetBookingsExportResult, error) {
 | 
						|
	vehicles, bookings, err := h.getFleetData()
 | 
						|
	if err != nil {
 | 
						|
		return nil, err
 | 
						|
	}
 | 
						|
 | 
						|
	groups, beneficiaries_map, err := h.getFleetMetadata(bookings)
 | 
						|
	if err != nil {
 | 
						|
		return nil, err
 | 
						|
	}
 | 
						|
 | 
						|
	file := h.generateFleetExcel(bookings, vehicles, groups, beneficiaries_map, "")
 | 
						|
	return &FleetBookingsExportResult{ExcelFile: file}, nil
 | 
						|
}
 | 
						|
 | 
						|
func (h *ApplicationHandler) ExportFleetBookingsByGroup(groupID string) (*FleetBookingsExportResult, error) {
 | 
						|
	vehicles, bookings, err := h.getFleetData()
 | 
						|
	if err != nil {
 | 
						|
		return nil, err
 | 
						|
	}
 | 
						|
 | 
						|
	groups, beneficiaries_map, err := h.getFleetMetadata(bookings)
 | 
						|
	if err != nil {
 | 
						|
		return nil, err
 | 
						|
	}
 | 
						|
 | 
						|
	file := h.generateFleetExcel(bookings, vehicles, groups, beneficiaries_map, groupID)
 | 
						|
	return &FleetBookingsExportResult{ExcelFile: file}, nil
 | 
						|
}
 | 
						|
 | 
						|
func (h *ApplicationHandler) getFleetData() (map[string]fleetsstorage.Vehicle, []fleetsstorage.Booking, error) {
 | 
						|
	vehicles := map[string]fleetsstorage.Vehicle{}
 | 
						|
	bookings := []fleetsstorage.Booking{}
 | 
						|
 | 
						|
	request := &fleets.GetVehiclesRequest{
 | 
						|
		Namespaces: []string{"parcoursmob"},
 | 
						|
	}
 | 
						|
	resp, err := h.services.GRPC.Fleets.GetVehicles(context.TODO(), request)
 | 
						|
	if err != nil {
 | 
						|
		return nil, nil, err
 | 
						|
	}
 | 
						|
 | 
						|
	for _, vehicle := range resp.Vehicles {
 | 
						|
		v := vehicle.ToStorageType()
 | 
						|
		for _, b := range v.Bookings {
 | 
						|
			bookings = append(bookings, b)
 | 
						|
		}
 | 
						|
		vehicles[vehicle.Id] = v
 | 
						|
	}
 | 
						|
 | 
						|
	return vehicles, bookings, nil
 | 
						|
}
 | 
						|
 | 
						|
func (h *ApplicationHandler) getFleetMetadata(bookings []fleetsstorage.Booking) (map[string]groupsstorage.Group, map[string]accountsstorage.Account, error) {
 | 
						|
	beneficiaries_ids := []string{}
 | 
						|
	for _, b := range bookings {
 | 
						|
		beneficiaries_ids = append(beneficiaries_ids, b.Driver)
 | 
						|
	}
 | 
						|
 | 
						|
	groups := map[string]groupsstorage.Group{}
 | 
						|
	admingroups, err := h.services.GRPC.GroupsManagement.GetGroups(context.TODO(), &groupsmanagement.GetGroupsRequest{
 | 
						|
		Namespaces: []string{"parcoursmob_organizations"},
 | 
						|
	})
 | 
						|
	if err != nil {
 | 
						|
		return nil, nil, err
 | 
						|
	}
 | 
						|
 | 
						|
	for _, g := range admingroups.Groups {
 | 
						|
		groups[g.Id] = g.ToStorageType()
 | 
						|
	}
 | 
						|
 | 
						|
	beneficiaries, err := h.services.GRPC.MobilityAccounts.GetAccountsBatch(context.TODO(), &accounts.GetAccountsBatchRequest{
 | 
						|
		Accountids: beneficiaries_ids,
 | 
						|
	})
 | 
						|
	if err != nil {
 | 
						|
		return nil, nil, err
 | 
						|
	}
 | 
						|
 | 
						|
	beneficiaries_map := map[string]accountsstorage.Account{}
 | 
						|
	for _, ben := range beneficiaries.Accounts {
 | 
						|
		beneficiaries_map[ben.Id] = ben.ToStorageType()
 | 
						|
	}
 | 
						|
 | 
						|
	return groups, beneficiaries_map, nil
 | 
						|
}
 | 
						|
 | 
						|
func (h *ApplicationHandler) generateFleetExcel(bookings []fleetsstorage.Booking, vehicles map[string]fleetsstorage.Vehicle, groups map[string]groupsstorage.Group, beneficiaries_map map[string]accountsstorage.Account, filterGroupID string) *excelize.File {
 | 
						|
	f := excelize.NewFile()
 | 
						|
 | 
						|
	f.SetCellValue("Sheet1", "A1", "Numéro")
 | 
						|
	f.SetCellValue("Sheet1", "B1", "Type")
 | 
						|
	f.SetCellValue("Sheet1", "C1", "Gestionnaire")
 | 
						|
	f.SetCellValue("Sheet1", "D1", "Prescripteur")
 | 
						|
	f.SetCellValue("Sheet1", "E1", "Bénéficiaire")
 | 
						|
	f.SetCellValue("Sheet1", "F1", "Numéro allocataire / Pole emploi")
 | 
						|
	f.SetCellValue("Sheet1", "G1", "Début de Mise à disposition")
 | 
						|
	f.SetCellValue("Sheet1", "H1", "Fin de mise à disposition")
 | 
						|
	f.SetCellValue("Sheet1", "I1", "Début indisponibilité")
 | 
						|
	f.SetCellValue("Sheet1", "J1", "Fin indisponibilité")
 | 
						|
	f.SetCellValue("Sheet1", "K1", "Véhicule retiré")
 | 
						|
	f.SetCellValue("Sheet1", "L1", "Commentaire - Retrait véhicule")
 | 
						|
	f.SetCellValue("Sheet1", "M1", "Réservation supprimée")
 | 
						|
	f.SetCellValue("Sheet1", "N1", "Motif de la suppression")
 | 
						|
 | 
						|
	i := 2
 | 
						|
	for _, b := range bookings {
 | 
						|
		vehicle := vehicles[b.Vehicleid]
 | 
						|
		if len(vehicle.Administrators) == 0 {
 | 
						|
			continue
 | 
						|
		}
 | 
						|
		admin := groups[vehicle.Administrators[0]]
 | 
						|
 | 
						|
		bookedby := ""
 | 
						|
		if v, ok := b.Data["booked_by"].(map[string]any); ok {
 | 
						|
			if v2, ok := v["user"].(map[string]any); ok {
 | 
						|
				if v3, ok := v2["display_name"].(string); ok {
 | 
						|
					bookedby = v3
 | 
						|
				}
 | 
						|
			}
 | 
						|
		}
 | 
						|
 | 
						|
		bookedbygroup := ""
 | 
						|
		if v4, ok := b.Data["booked_by"].(map[string]any); ok {
 | 
						|
			if v5, ok := v4["group"].(map[string]any); ok {
 | 
						|
				if v6, ok := v5["id"].(string); ok {
 | 
						|
					bookedbygroup = v6
 | 
						|
				}
 | 
						|
			}
 | 
						|
		}
 | 
						|
 | 
						|
		// Filter by group if specified
 | 
						|
		if filterGroupID != "" && bookedbygroup != filterGroupID {
 | 
						|
			continue
 | 
						|
		}
 | 
						|
 | 
						|
		beneficiary := beneficiaries_map[b.Driver]
 | 
						|
		adminunavailability := false
 | 
						|
 | 
						|
		if av, ok := b.Data["administrator_unavailability"].(bool); ok && av {
 | 
						|
			adminunavailability = true
 | 
						|
		}
 | 
						|
 | 
						|
		deleted := ""
 | 
						|
		if b.Deleted {
 | 
						|
			deleted = "DELETED"
 | 
						|
		}
 | 
						|
 | 
						|
		f.SetCellValue("Sheet1", fmt.Sprintf("A%d", i), vehicle.Data["licence_plate"])
 | 
						|
		f.SetCellValue("Sheet1", fmt.Sprintf("B%d", i), vehicle.Type)
 | 
						|
		f.SetCellValue("Sheet1", fmt.Sprintf("C%d", i), admin.Data["name"])
 | 
						|
		f.SetCellValue("Sheet1", fmt.Sprintf("D%d", i), bookedby)
 | 
						|
		f.SetCellValue("Sheet1", fmt.Sprintf("E%d", i), fmt.Sprintf("%v %v", beneficiary.Data["first_name"], beneficiary.Data["last_name"]))
 | 
						|
		f.SetCellValue("Sheet1", fmt.Sprintf("F%d", i), beneficiary.Data["file_number"])
 | 
						|
		f.SetCellValue("Sheet1", fmt.Sprintf("G%d", i), b.Startdate.Format("2006-01-02"))
 | 
						|
		f.SetCellValue("Sheet1", fmt.Sprintf("H%d", i), b.Enddate.Format("2006-01-02"))
 | 
						|
		f.SetCellValue("Sheet1", fmt.Sprintf("I%d", i), b.Unavailablefrom.Format("2006-01-02"))
 | 
						|
		f.SetCellValue("Sheet1", fmt.Sprintf("J%d", i), b.Unavailableto.Format("2006-01-02"))
 | 
						|
		f.SetCellValue("Sheet1", fmt.Sprintf("K%d", i), adminunavailability)
 | 
						|
		f.SetCellValue("Sheet1", fmt.Sprintf("L%d", i), b.Data["comment"])
 | 
						|
		f.SetCellValue("Sheet1", fmt.Sprintf("M%d", i), deleted)
 | 
						|
		f.SetCellValue("Sheet1", fmt.Sprintf("N%d", i), b.Data["motif"])
 | 
						|
		i = i + 1
 | 
						|
	}
 | 
						|
 | 
						|
	return f
 | 
						|
} |