lot of new functionalities
This commit is contained in:
228
core/application/dashboard.go
Executable file
228
core/application/dashboard.go
Executable file
@@ -0,0 +1,228 @@
|
||||
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
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user