229 lines
6.8 KiB
Go
Executable File
229 lines
6.8 KiB
Go
Executable File
package application
|
|
|
|
import (
|
|
"context"
|
|
"encoding/json"
|
|
"fmt"
|
|
"sort"
|
|
"sync"
|
|
"time"
|
|
|
|
"git.coopgo.io/coopgo-apps/parcoursmob/core/utils/identification"
|
|
"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"
|
|
fleetstorage "git.coopgo.io/coopgo-platform/fleets/storage"
|
|
"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/paulmach/orb"
|
|
"github.com/paulmach/orb/geojson"
|
|
"github.com/rs/zerolog/log"
|
|
"google.golang.org/protobuf/types/known/timestamppb"
|
|
)
|
|
|
|
type DashboardResult struct {
|
|
Accounts []mobilityaccountsstorage.Account
|
|
Members []mobilityaccountsstorage.Account
|
|
Events []agendastorage.Event
|
|
Bookings []fleetstorage.Booking
|
|
SolidarityDrivers []mobilityaccountsstorage.Account
|
|
OrganizedCarpoolDrivers []mobilityaccountsstorage.Account
|
|
}
|
|
|
|
func (h *ApplicationHandler) GetDashboardData(ctx context.Context, driverAddressGeoLayer, driverAddressGeoCode string) (*DashboardResult, error) {
|
|
g := ctx.Value(identification.GroupKey)
|
|
if g == nil {
|
|
return nil, fmt.Errorf("no group found in context")
|
|
}
|
|
group := g.(storage.Group)
|
|
|
|
// Load geography polygons for driver address filtering
|
|
var driverAddressPolygons []orb.Polygon
|
|
if driverAddressGeoLayer != "" && driverAddressGeoCode != "" {
|
|
polygons, err := h.loadGeographyPolygon(driverAddressGeoLayer, driverAddressGeoCode)
|
|
if err != nil {
|
|
log.Warn().Err(err).Msg("failed to load driver address geography filter")
|
|
} else {
|
|
driverAddressPolygons = polygons
|
|
}
|
|
}
|
|
|
|
// Get accounts (recent beneficiaries)
|
|
request := &mobilityaccounts.GetAccountsBatchRequest{
|
|
Accountids: group.Members,
|
|
}
|
|
|
|
resp, err := h.services.GRPC.MobilityAccounts.GetAccountsBatch(ctx, request)
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
|
|
accounts := []mobilityaccountsstorage.Account{}
|
|
|
|
// We only display the 5 most recent here
|
|
count := len(resp.Accounts)
|
|
min := count - 5
|
|
if min < 0 {
|
|
min = 0
|
|
}
|
|
|
|
for _, account := range resp.Accounts[min:] {
|
|
// Check if not archived
|
|
if archived, ok := account.Data.AsMap()["archived"].(bool); !ok || !archived {
|
|
a := account.ToStorageType()
|
|
accounts = append([]mobilityaccountsstorage.Account{a}, accounts...)
|
|
}
|
|
}
|
|
|
|
// Fetch remaining data in parallel using goroutines
|
|
var wg sync.WaitGroup
|
|
var mu sync.Mutex
|
|
|
|
var members []mobilityaccountsstorage.Account
|
|
var events []agendastorage.Event
|
|
var bookings []fleetstorage.Booking
|
|
var solidarityDrivers []mobilityaccountsstorage.Account
|
|
var organizedCarpoolDrivers []mobilityaccountsstorage.Account
|
|
|
|
// Get members
|
|
wg.Add(1)
|
|
go func() {
|
|
defer wg.Done()
|
|
m, _, err := h.groupmembers(group.ID)
|
|
if err == nil {
|
|
mu.Lock()
|
|
members = m
|
|
mu.Unlock()
|
|
}
|
|
}()
|
|
|
|
// Get events
|
|
wg.Add(1)
|
|
go func() {
|
|
defer wg.Done()
|
|
eventsresp, err := h.services.GRPC.Agenda.GetEvents(ctx, &agenda.GetEventsRequest{
|
|
Namespaces: []string{"parcoursmob_dispositifs"},
|
|
Mindate: timestamppb.Now(),
|
|
})
|
|
if err == nil {
|
|
mu.Lock()
|
|
for _, e := range eventsresp.Events {
|
|
events = append(events, e.ToStorageType())
|
|
}
|
|
sort.Sort(sorting.EventsByStartdate(events))
|
|
mu.Unlock()
|
|
}
|
|
}()
|
|
|
|
// Get bookings
|
|
wg.Add(1)
|
|
go func() {
|
|
defer wg.Done()
|
|
bookingsresp, err := h.services.GRPC.Fleets.GetBookings(ctx, &fleets.GetBookingsRequest{
|
|
Namespaces: []string{"parcoursmob_dispositifs"},
|
|
})
|
|
if err == nil {
|
|
mu.Lock()
|
|
for _, b := range bookingsresp.Bookings {
|
|
if b.Enddate.AsTime().After(time.Now()) {
|
|
bookings = append(bookings, b.ToStorageType())
|
|
}
|
|
}
|
|
mu.Unlock()
|
|
}
|
|
}()
|
|
|
|
// Get solidarity transport drivers
|
|
wg.Add(1)
|
|
go func() {
|
|
defer wg.Done()
|
|
solidarityRequest := &mobilityaccounts.GetAccountsRequest{
|
|
Namespaces: []string{"solidarity_drivers"},
|
|
}
|
|
solidarityResp, err := h.services.GRPC.MobilityAccounts.GetAccounts(ctx, solidarityRequest)
|
|
if err == nil {
|
|
mu.Lock()
|
|
for _, account := range solidarityResp.Accounts {
|
|
// Only include non-archived drivers with addresses
|
|
if archived, ok := account.Data.AsMap()["archived"].(bool); !ok || !archived {
|
|
if address, ok := account.Data.AsMap()["address"]; ok && address != nil {
|
|
// Apply geography filter if specified
|
|
if len(driverAddressPolygons) > 0 {
|
|
if addr, ok := account.Data.AsMap()["address"].(map[string]interface{}); ok {
|
|
jsonAddr, err := json.Marshal(addr)
|
|
if err == nil {
|
|
addrGeojson, err := geojson.UnmarshalFeature(jsonAddr)
|
|
if err == nil && addrGeojson.Geometry != nil {
|
|
if point, ok := addrGeojson.Geometry.(orb.Point); ok {
|
|
if isPointInGeographies(point, driverAddressPolygons) {
|
|
solidarityDrivers = append(solidarityDrivers, account.ToStorageType())
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
} else {
|
|
solidarityDrivers = append(solidarityDrivers, account.ToStorageType())
|
|
}
|
|
}
|
|
}
|
|
}
|
|
mu.Unlock()
|
|
}
|
|
}()
|
|
|
|
// Get organized carpool drivers
|
|
wg.Add(1)
|
|
go func() {
|
|
defer wg.Done()
|
|
carpoolRequest := &mobilityaccounts.GetAccountsRequest{
|
|
Namespaces: []string{"organized_carpool_drivers"},
|
|
}
|
|
carpoolResp, err := h.services.GRPC.MobilityAccounts.GetAccounts(ctx, carpoolRequest)
|
|
if err == nil {
|
|
mu.Lock()
|
|
for _, account := range carpoolResp.Accounts {
|
|
// Only include non-archived drivers with addresses
|
|
if archived, ok := account.Data.AsMap()["archived"].(bool); !ok || !archived {
|
|
if address, ok := account.Data.AsMap()["address"]; ok && address != nil {
|
|
// Apply geography filter if specified
|
|
if len(driverAddressPolygons) > 0 {
|
|
if addr, ok := account.Data.AsMap()["address"].(map[string]interface{}); ok {
|
|
jsonAddr, err := json.Marshal(addr)
|
|
if err == nil {
|
|
addrGeojson, err := geojson.UnmarshalFeature(jsonAddr)
|
|
if err == nil && addrGeojson.Geometry != nil {
|
|
if point, ok := addrGeojson.Geometry.(orb.Point); ok {
|
|
if isPointInGeographies(point, driverAddressPolygons) {
|
|
organizedCarpoolDrivers = append(organizedCarpoolDrivers, account.ToStorageType())
|
|
}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
} else {
|
|
organizedCarpoolDrivers = append(organizedCarpoolDrivers, account.ToStorageType())
|
|
}
|
|
}
|
|
}
|
|
}
|
|
mu.Unlock()
|
|
}
|
|
}()
|
|
|
|
// Wait for all goroutines to complete
|
|
wg.Wait()
|
|
|
|
return &DashboardResult{
|
|
Accounts: accounts,
|
|
Members: members,
|
|
Events: events,
|
|
Bookings: bookings,
|
|
SolidarityDrivers: solidarityDrivers,
|
|
OrganizedCarpoolDrivers: organizedCarpoolDrivers,
|
|
}, nil
|
|
}
|
|
|