solidarity transport updates
This commit is contained in:
		
							parent
							
								
									95b60ea737
								
							
						
					
					
						commit
						9ab7b66b68
					
				| 
						 | 
					@ -10,5 +10,3 @@ This new version of PARCOURSMOB brings :
 | 
				
			||||||
- A configurable and themeable approach of rendering web pages : the default theme is located in the folder [themes/default/](themes/default/)
 | 
					- A configurable and themeable approach of rendering web pages : the default theme is located in the folder [themes/default/](themes/default/)
 | 
				
			||||||
- A modular architecture based on groups and access rights, using [COOPGO Groups Management](https://git.coopgo.io/coopgo-groups-management)
 | 
					- A modular architecture based on groups and access rights, using [COOPGO Groups Management](https://git.coopgo.io/coopgo-groups-management)
 | 
				
			||||||
- A distributed cache system through [etcd](https://etcd.io/) to handle distributed state management like pagination in a cloud native way
 | 
					- A distributed cache system through [etcd](https://etcd.io/) to handle distributed state management like pagination in a cloud native way
 | 
				
			||||||
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
							
								
								
									
										94
									
								
								config.go
								
								
								
								
							
							
						
						
									
										94
									
								
								config.go
								
								
								
								
							| 
						 | 
					@ -22,11 +22,105 @@ func ReadConfig() (*viper.Viper, error) {
 | 
				
			||||||
				"session_key": "SESSION_KEY",
 | 
									"session_key": "SESSION_KEY",
 | 
				
			||||||
			},
 | 
								},
 | 
				
			||||||
		},
 | 
							},
 | 
				
			||||||
 | 
							"storage": map[string]any{
 | 
				
			||||||
 | 
								"files": map[string]any{
 | 
				
			||||||
 | 
									"file_types": map[string]string{
 | 
				
			||||||
 | 
										"driving_licence": "Permis de conduire",
 | 
				
			||||||
 | 
										"work_contract":   "Contrat de travail",
 | 
				
			||||||
 | 
										"identity_proof":  "Pièce d'identité",
 | 
				
			||||||
 | 
										"membership_form": "Bulletin d'adhésion",
 | 
				
			||||||
 | 
										"other":           "Autre",
 | 
				
			||||||
 | 
									},
 | 
				
			||||||
 | 
								},
 | 
				
			||||||
 | 
							},
 | 
				
			||||||
 | 
							"modules": map[string]any{
 | 
				
			||||||
 | 
								"dashboard": map[string]any{
 | 
				
			||||||
 | 
									"enabled": true,
 | 
				
			||||||
 | 
								},
 | 
				
			||||||
 | 
								"beneficiaries": map[string]any{
 | 
				
			||||||
 | 
									"enabled": true,
 | 
				
			||||||
 | 
									"validated_profile": map[string]any{
 | 
				
			||||||
 | 
										"enabled": false,
 | 
				
			||||||
 | 
										"required": map[string]any{
 | 
				
			||||||
 | 
											"fields":    []string{},
 | 
				
			||||||
 | 
											"documents": []string{},
 | 
				
			||||||
 | 
										},
 | 
				
			||||||
 | 
									},
 | 
				
			||||||
 | 
								},
 | 
				
			||||||
 | 
								"journeys": map[string]any{
 | 
				
			||||||
 | 
									"enabled": true,
 | 
				
			||||||
 | 
								},
 | 
				
			||||||
 | 
								"solidarity_transport": map[string]any{
 | 
				
			||||||
 | 
									"enabled": true,
 | 
				
			||||||
 | 
									"drivers": map[string]any{
 | 
				
			||||||
 | 
										"documents_types": []string{"membership_form", "driving_licence", "identity_proof", "other"},
 | 
				
			||||||
 | 
										"validated_profile": map[string]any{
 | 
				
			||||||
 | 
											"enabled": false,
 | 
				
			||||||
 | 
											"required": map[string]any{
 | 
				
			||||||
 | 
												"fields":    []string{},
 | 
				
			||||||
 | 
												"documents": []string{},
 | 
				
			||||||
 | 
											},
 | 
				
			||||||
 | 
										},
 | 
				
			||||||
 | 
									},
 | 
				
			||||||
 | 
								},
 | 
				
			||||||
 | 
								"organized_carpool": map[string]any{
 | 
				
			||||||
 | 
									"enabled": true,
 | 
				
			||||||
 | 
									"drivers": map[string]any{
 | 
				
			||||||
 | 
										"documents_types": []string{"membership_form", "driving_licence", "identity_proof", "other"},
 | 
				
			||||||
 | 
										"validated_profile": map[string]any{
 | 
				
			||||||
 | 
											"enabled": false,
 | 
				
			||||||
 | 
											"required": map[string]any{
 | 
				
			||||||
 | 
												"fields":    []string{},
 | 
				
			||||||
 | 
												"documents": []string{},
 | 
				
			||||||
 | 
											},
 | 
				
			||||||
 | 
										},
 | 
				
			||||||
 | 
									},
 | 
				
			||||||
 | 
								},
 | 
				
			||||||
 | 
								"vehicles": map[string]any{
 | 
				
			||||||
 | 
									"enabled": true,
 | 
				
			||||||
 | 
								},
 | 
				
			||||||
 | 
								"vehicles_management": map[string]any{
 | 
				
			||||||
 | 
									"enabled": true,
 | 
				
			||||||
 | 
								},
 | 
				
			||||||
 | 
								"agenda": map[string]any{
 | 
				
			||||||
 | 
									"enabled": true,
 | 
				
			||||||
 | 
								},
 | 
				
			||||||
 | 
								"directory": map[string]any{
 | 
				
			||||||
 | 
									"enabled": true,
 | 
				
			||||||
 | 
								},
 | 
				
			||||||
 | 
								"support": map[string]any{
 | 
				
			||||||
 | 
									"enabled": true,
 | 
				
			||||||
 | 
								},
 | 
				
			||||||
 | 
							},
 | 
				
			||||||
		"geo": map[string]any{
 | 
							"geo": map[string]any{
 | 
				
			||||||
			"pelias": map[string]any{
 | 
								"pelias": map[string]any{
 | 
				
			||||||
				"url": "https://geocode.ridygo.fr",
 | 
									"url": "https://geocode.ridygo.fr",
 | 
				
			||||||
			},
 | 
								},
 | 
				
			||||||
		},
 | 
							},
 | 
				
			||||||
 | 
							"geography": map[string]any{
 | 
				
			||||||
 | 
								"storage": map[string]any{
 | 
				
			||||||
 | 
									"index": map[string]any{
 | 
				
			||||||
 | 
										"type": "memory_rtree",
 | 
				
			||||||
 | 
										"bleve": map[string]any{
 | 
				
			||||||
 | 
											"file": "index.bleve",
 | 
				
			||||||
 | 
										},
 | 
				
			||||||
 | 
									},
 | 
				
			||||||
 | 
								},
 | 
				
			||||||
 | 
								"services": map[string]any{
 | 
				
			||||||
 | 
									"grpc": map[string]any{
 | 
				
			||||||
 | 
										"enable": true,
 | 
				
			||||||
 | 
										"port":   8080,
 | 
				
			||||||
 | 
									},
 | 
				
			||||||
 | 
								},
 | 
				
			||||||
 | 
								"data": map[string]any{
 | 
				
			||||||
 | 
									"layers": map[string]string{
 | 
				
			||||||
 | 
										"regions":      "https://etalab-datasets.geo.data.gouv.fr/contours-administratifs/latest/geojson/regions-50m.geojson",
 | 
				
			||||||
 | 
										"departements": "https://etalab-datasets.geo.data.gouv.fr/contours-administratifs/latest/geojson/departements-50m.geojson",
 | 
				
			||||||
 | 
										"epci":         "https://etalab-datasets.geo.data.gouv.fr/contours-administratifs/latest/geojson/epci-50m.geojson",
 | 
				
			||||||
 | 
										"communes":     "https://etalab-datasets.geo.data.gouv.fr/contours-administratifs/latest/geojson/communes-50m.geojson",
 | 
				
			||||||
 | 
									},
 | 
				
			||||||
 | 
								},
 | 
				
			||||||
 | 
							},
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
	v := viper.New()
 | 
						v := viper.New()
 | 
				
			||||||
	for key, value := range defaults {
 | 
						for key, value := range defaults {
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
							
								
								
									
										143
									
								
								go.mod
								
								
								
								
							
							
						
						
									
										143
									
								
								go.mod
								
								
								
								
							| 
						 | 
					@ -1,6 +1,6 @@
 | 
				
			||||||
module git.coopgo.io/coopgo-apps/parcoursmob
 | 
					module git.coopgo.io/coopgo-apps/parcoursmob
 | 
				
			||||||
 | 
					
 | 
				
			||||||
go 1.23.3
 | 
					go 1.24.2
 | 
				
			||||||
 | 
					
 | 
				
			||||||
// replace git.coopgo.io/coopgo-platform/mobility-accounts => ../../coopgo-platform/mobility-accounts/
 | 
					// replace git.coopgo.io/coopgo-platform/mobility-accounts => ../../coopgo-platform/mobility-accounts/
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					@ -12,116 +12,167 @@ go 1.23.3
 | 
				
			||||||
 | 
					
 | 
				
			||||||
// replace git.coopgo.io/coopgo-platform/emailing => ../../coopgo-platform/emailing/
 | 
					// replace git.coopgo.io/coopgo-platform/emailing => ../../coopgo-platform/emailing/
 | 
				
			||||||
 | 
					
 | 
				
			||||||
replace git.coopgo.io/coopgo-platform/data-hub => ../../coopgo-platform/data-hub/
 | 
					// replace git.coopgo.io/coopgo-platform/data-hub => ../../coopgo-platform/data-hub/
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					// replace git.coopgo.io/coopgo-platform/solidarity-transport => ../../coopgo-platform/solidarity-transport/
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					// replace git.coopgo.io/coopgo-platform/carpool-service => ../../coopgo-platform/carpool-service/
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					// replace git.coopgo.io/coopgo-platform/multimodal-routing => ../../coopgo-platform/multimodal-routing/
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					// replace git.coopgo.io/coopgo-platform/payments => ../../coopgo-platform/payments/
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					// replace git.coopgo.io/coopgo-platform/geography => ../../coopgo-platform/geography/
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					// replace git.coopgo.io/coopgo-platform/sms => ../../coopgo-platform/sms/
 | 
				
			||||||
 | 
					
 | 
				
			||||||
require (
 | 
					require (
 | 
				
			||||||
	github.com/fogleman/gg v1.3.0
 | 
						github.com/fogleman/gg v1.3.0
 | 
				
			||||||
	github.com/go-playground/validator/v10 v10.11.0
 | 
						github.com/go-playground/validator/v10 v10.14.1
 | 
				
			||||||
	github.com/google/uuid v1.6.0
 | 
						github.com/google/uuid v1.6.0
 | 
				
			||||||
	github.com/gorilla/mux v1.8.0
 | 
						github.com/gorilla/mux v1.8.0
 | 
				
			||||||
	github.com/gorilla/sessions v1.2.1
 | 
						github.com/gorilla/sessions v1.2.1
 | 
				
			||||||
	github.com/paulmach/go.geojson v1.4.0
 | 
						github.com/paulmach/go.geojson v1.4.0 // indirect
 | 
				
			||||||
	github.com/spf13/viper v1.19.0
 | 
						github.com/spf13/viper v1.20.1
 | 
				
			||||||
	gitlab.scity.coop/maas/navitia-golang v0.0.0-20220429110621-5c22d6efdd0c
 | 
						gitlab.scity.coop/maas/navitia-golang v0.0.0-20220429110621-5c22d6efdd0c
 | 
				
			||||||
	go.etcd.io/etcd/client/v3 v3.5.12
 | 
						go.etcd.io/etcd/client/v3 v3.5.12
 | 
				
			||||||
	golang.org/x/image v0.5.0
 | 
						golang.org/x/image v0.5.0
 | 
				
			||||||
	golang.org/x/oauth2 v0.23.0
 | 
						golang.org/x/oauth2 v0.25.0
 | 
				
			||||||
	google.golang.org/grpc v1.68.0
 | 
						google.golang.org/grpc v1.71.1
 | 
				
			||||||
	google.golang.org/protobuf v1.35.2
 | 
						google.golang.org/protobuf v1.36.6
 | 
				
			||||||
)
 | 
					)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
require (
 | 
					require (
 | 
				
			||||||
	git.coopgo.io/coopgo-platform/agenda v1.0.0
 | 
						git.coopgo.io/coopgo-platform/agenda v1.0.0
 | 
				
			||||||
 | 
						git.coopgo.io/coopgo-platform/carpool-service v0.0.0-20250415082502-575b8129b727
 | 
				
			||||||
	git.coopgo.io/coopgo-platform/emailing v0.0.0-20250212064257-167ef5864260
 | 
						git.coopgo.io/coopgo-platform/emailing v0.0.0-20250212064257-167ef5864260
 | 
				
			||||||
	git.coopgo.io/coopgo-platform/fleets v0.0.0-20230310144446-feb935f8bf4e
 | 
						git.coopgo.io/coopgo-platform/fleets v0.0.0-20230310144446-feb935f8bf4e
 | 
				
			||||||
	git.coopgo.io/coopgo-platform/groups-management v0.0.0-20230310123255-5ef94ee0746c
 | 
						git.coopgo.io/coopgo-platform/groups-management v0.0.0-20230310123255-5ef94ee0746c
 | 
				
			||||||
	git.coopgo.io/coopgo-platform/mobility-accounts v0.0.0-20230329105908-a76c0412a386
 | 
						git.coopgo.io/coopgo-platform/mobility-accounts v0.0.0-20230329105908-a76c0412a386
 | 
				
			||||||
 | 
						git.coopgo.io/coopgo-platform/multimodal-routing v0.0.0-20250504230045-8680f560066a
 | 
				
			||||||
 | 
						git.coopgo.io/coopgo-platform/payments v0.0.0-20250616162131-77f7b00b8fc3
 | 
				
			||||||
 | 
						git.coopgo.io/coopgo-platform/routing-service v0.0.0-20250304234521-faabcc54f536
 | 
				
			||||||
 | 
						git.coopgo.io/coopgo-platform/sms v0.0.0-20250523074631-1f1e7fc6b7af
 | 
				
			||||||
 | 
						git.coopgo.io/coopgo-platform/solidarity-transport v0.0.0-20250616110116-d71da5accdfd
 | 
				
			||||||
	github.com/arran4/golang-ical v0.3.1
 | 
						github.com/arran4/golang-ical v0.3.1
 | 
				
			||||||
	github.com/coreos/go-oidc/v3 v3.11.0
 | 
						github.com/coreos/go-oidc/v3 v3.11.0
 | 
				
			||||||
	github.com/gorilla/securecookie v1.1.1
 | 
						github.com/gorilla/securecookie v1.1.1
 | 
				
			||||||
	github.com/minio/minio-go/v7 v7.0.43
 | 
						github.com/minio/minio-go/v7 v7.0.43
 | 
				
			||||||
	github.com/rs/zerolog v1.33.0
 | 
						github.com/paulmach/orb v0.11.1
 | 
				
			||||||
 | 
						github.com/rs/zerolog v1.34.0
 | 
				
			||||||
 | 
						github.com/stretchr/objx v0.5.2
 | 
				
			||||||
	github.com/xuri/excelize/v2 v2.7.1
 | 
						github.com/xuri/excelize/v2 v2.7.1
 | 
				
			||||||
)
 | 
					)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
require (
 | 
					require (
 | 
				
			||||||
	github.com/sagikazarmark/locafero v0.6.0 // indirect
 | 
						git.coopgo.io/coopgo-platform/carpool-service/interoperability/ocss v0.0.0-20250429082239-a95cd6eb5523 // indirect
 | 
				
			||||||
	github.com/sagikazarmark/slog-shim v0.1.0 // indirect
 | 
						git.coopgo.io/coopgo-platform/geography v0.0.0-20250616160304-0285c9494673 // indirect
 | 
				
			||||||
 | 
						github.com/RoaringBitmap/roaring/v2 v2.4.5 // indirect
 | 
				
			||||||
 | 
						github.com/apapsch/go-jsonmerge/v2 v2.0.0 // indirect
 | 
				
			||||||
 | 
						github.com/apparentlymart/go-textseg/v15 v15.0.0 // indirect
 | 
				
			||||||
 | 
						github.com/bits-and-blooms/bitset v1.22.0 // indirect
 | 
				
			||||||
 | 
						github.com/blevesearch/bleve/v2 v2.5.2 // indirect
 | 
				
			||||||
 | 
						github.com/blevesearch/bleve_index_api v1.2.8 // indirect
 | 
				
			||||||
 | 
						github.com/blevesearch/geo v0.2.3 // indirect
 | 
				
			||||||
 | 
						github.com/blevesearch/go-faiss v1.0.25 // indirect
 | 
				
			||||||
 | 
						github.com/blevesearch/go-porterstemmer v1.0.3 // indirect
 | 
				
			||||||
 | 
						github.com/blevesearch/gtreap v0.1.1 // indirect
 | 
				
			||||||
 | 
						github.com/blevesearch/mmap-go v1.0.4 // indirect
 | 
				
			||||||
 | 
						github.com/blevesearch/scorch_segment_api/v2 v2.3.10 // indirect
 | 
				
			||||||
 | 
						github.com/blevesearch/segment v0.9.1 // indirect
 | 
				
			||||||
 | 
						github.com/blevesearch/snowballstem v0.9.0 // indirect
 | 
				
			||||||
 | 
						github.com/blevesearch/upsidedown_store_api v1.0.2 // indirect
 | 
				
			||||||
 | 
						github.com/blevesearch/vellum v1.1.0 // indirect
 | 
				
			||||||
 | 
						github.com/blevesearch/zapx/v11 v11.4.2 // indirect
 | 
				
			||||||
 | 
						github.com/blevesearch/zapx/v12 v12.4.2 // indirect
 | 
				
			||||||
 | 
						github.com/blevesearch/zapx/v13 v13.4.2 // indirect
 | 
				
			||||||
 | 
						github.com/blevesearch/zapx/v14 v14.4.2 // indirect
 | 
				
			||||||
 | 
						github.com/blevesearch/zapx/v15 v15.4.2 // indirect
 | 
				
			||||||
 | 
						github.com/blevesearch/zapx/v16 v16.2.4 // indirect
 | 
				
			||||||
 | 
						github.com/bmatcuk/doublestar v1.3.4 // indirect
 | 
				
			||||||
 | 
						github.com/gabriel-vasile/mimetype v1.4.2 // indirect
 | 
				
			||||||
 | 
						github.com/go-viper/mapstructure/v2 v2.2.1 // indirect
 | 
				
			||||||
 | 
						github.com/gorilla/schema v1.4.1 // indirect
 | 
				
			||||||
 | 
						github.com/manterfield/go-mapreader v0.2.0 // indirect
 | 
				
			||||||
 | 
						github.com/mschoch/smat v0.2.0 // indirect
 | 
				
			||||||
 | 
						github.com/oapi-codegen/runtime v1.1.1 // indirect
 | 
				
			||||||
 | 
						github.com/sagikazarmark/locafero v0.9.0 // indirect
 | 
				
			||||||
	github.com/sourcegraph/conc v0.3.0 // indirect
 | 
						github.com/sourcegraph/conc v0.3.0 // indirect
 | 
				
			||||||
	golang.org/x/exp v0.0.0-20241108190413-2d47ceb2692f // indirect
 | 
						github.com/tidwall/geoindex v1.7.0 // indirect
 | 
				
			||||||
 | 
						github.com/tidwall/rtree v1.10.0 // indirect
 | 
				
			||||||
 | 
						github.com/twpayne/go-polyline v1.1.1 // indirect
 | 
				
			||||||
 | 
						github.com/zclconf/go-cty-yaml v1.1.0 // indirect
 | 
				
			||||||
 | 
						go.etcd.io/bbolt v1.4.0 // indirect
 | 
				
			||||||
 | 
						go.mongodb.org/mongo-driver/v2 v2.1.0 // indirect
 | 
				
			||||||
 | 
						golang.org/x/mod v0.24.0 // indirect
 | 
				
			||||||
 | 
						golang.org/x/tools v0.32.0 // indirect
 | 
				
			||||||
)
 | 
					)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
require (
 | 
					require (
 | 
				
			||||||
	ariga.io/atlas v0.12.0 // indirect
 | 
						ariga.io/atlas v0.32.0 // indirect
 | 
				
			||||||
	git.coopgo.io/coopgo-platform/diags v0.0.0-20250212093351-64da61495c9d
 | 
						git.coopgo.io/coopgo-platform/diags v0.0.0-20250212093351-64da61495c9d
 | 
				
			||||||
	github.com/agext/levenshtein v1.2.1 // indirect
 | 
						github.com/agext/levenshtein v1.2.3 // indirect
 | 
				
			||||||
	github.com/apparentlymart/go-textseg/v13 v13.0.0 // indirect
 | 
					 | 
				
			||||||
	github.com/coreos/go-semver v0.3.0 // indirect
 | 
						github.com/coreos/go-semver v0.3.0 // indirect
 | 
				
			||||||
	github.com/coreos/go-systemd/v22 v22.5.0 // indirect
 | 
						github.com/coreos/go-systemd/v22 v22.5.0 // indirect
 | 
				
			||||||
	github.com/dustin/go-humanize v1.0.0 // indirect
 | 
						github.com/dustin/go-humanize v1.0.0 // indirect
 | 
				
			||||||
	github.com/fsnotify/fsnotify v1.8.0 // indirect
 | 
						github.com/fsnotify/fsnotify v1.9.0 // indirect
 | 
				
			||||||
	github.com/go-jose/go-jose/v4 v4.0.2 // indirect
 | 
						github.com/go-jose/go-jose/v4 v4.0.2 // indirect
 | 
				
			||||||
	github.com/go-openapi/inflect v0.19.0 // indirect
 | 
						github.com/go-openapi/inflect v0.21.2 // indirect
 | 
				
			||||||
	github.com/go-playground/locales v0.14.0 // indirect
 | 
						github.com/go-playground/locales v0.14.1 // indirect
 | 
				
			||||||
	github.com/go-playground/universal-translator v0.18.0 // indirect
 | 
						github.com/go-playground/universal-translator v0.18.1 // indirect
 | 
				
			||||||
	github.com/gogo/protobuf v1.3.2 // indirect
 | 
						github.com/gogo/protobuf v1.3.2 // indirect
 | 
				
			||||||
	github.com/golang/freetype v0.0.0-20170609003504-e2365dfdc4a0 // indirect
 | 
						github.com/golang/freetype v0.0.0-20170609003504-e2365dfdc4a0 // indirect
 | 
				
			||||||
	github.com/golang/protobuf v1.5.4 // indirect
 | 
						github.com/golang/protobuf v1.5.4 // indirect
 | 
				
			||||||
	github.com/golang/snappy v0.0.4 // indirect
 | 
						github.com/golang/snappy v1.0.0 // indirect
 | 
				
			||||||
	github.com/google/go-cmp v0.6.0 // indirect
 | 
						github.com/google/go-cmp v0.7.0 // indirect
 | 
				
			||||||
	github.com/hashicorp/hcl v1.0.0 // indirect
 | 
						github.com/hashicorp/hcl/v2 v2.23.0 // indirect
 | 
				
			||||||
	github.com/hashicorp/hcl/v2 v2.10.0 // indirect
 | 
					 | 
				
			||||||
	github.com/json-iterator/go v1.1.12 // indirect
 | 
						github.com/json-iterator/go v1.1.12 // indirect
 | 
				
			||||||
	github.com/klauspost/compress v1.17.7 // indirect
 | 
						github.com/klauspost/compress v1.18.0 // indirect
 | 
				
			||||||
	github.com/klauspost/cpuid/v2 v2.1.0 // indirect
 | 
						github.com/klauspost/cpuid/v2 v2.2.5 // indirect
 | 
				
			||||||
	github.com/leodido/go-urn v1.2.1 // indirect
 | 
						github.com/leodido/go-urn v1.2.4 // indirect
 | 
				
			||||||
	github.com/lib/pq v1.10.9 // indirect
 | 
						github.com/lib/pq v1.10.9 // indirect
 | 
				
			||||||
	github.com/magiconair/properties v1.8.7 // indirect
 | 
						github.com/mattn/go-colorable v0.1.14 // indirect
 | 
				
			||||||
	github.com/mattn/go-colorable v0.1.13 // indirect
 | 
					 | 
				
			||||||
	github.com/mattn/go-isatty v0.0.20 // indirect
 | 
						github.com/mattn/go-isatty v0.0.20 // indirect
 | 
				
			||||||
	github.com/mb0/wkt v0.0.0-20170420051526-a30afd545ee1 // indirect
 | 
						github.com/mb0/wkt v0.0.0-20170420051526-a30afd545ee1 // indirect
 | 
				
			||||||
	github.com/minio/md5-simd v1.1.2 // indirect
 | 
						github.com/minio/md5-simd v1.1.2 // indirect
 | 
				
			||||||
	github.com/minio/sha256-simd v1.0.0 // indirect
 | 
						github.com/minio/sha256-simd v1.0.0 // indirect
 | 
				
			||||||
	github.com/mitchellh/go-wordwrap v0.0.0-20150314170334-ad45545899c7 // indirect
 | 
						github.com/mitchellh/go-wordwrap v1.0.1 // indirect
 | 
				
			||||||
	github.com/mitchellh/mapstructure v1.5.0 // indirect
 | 
					 | 
				
			||||||
	github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd // indirect
 | 
						github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd // indirect
 | 
				
			||||||
	github.com/modern-go/reflect2 v1.0.2 // indirect
 | 
						github.com/modern-go/reflect2 v1.0.2 // indirect
 | 
				
			||||||
	github.com/mohae/deepcopy v0.0.0-20170929034955-c48cc78d4826 // indirect
 | 
						github.com/mohae/deepcopy v0.0.0-20170929034955-c48cc78d4826 // indirect
 | 
				
			||||||
	github.com/montanaflynn/stats v0.7.1 // indirect
 | 
						github.com/montanaflynn/stats v0.7.1 // indirect
 | 
				
			||||||
	github.com/pelletier/go-toml/v2 v2.2.3 // indirect
 | 
						github.com/pelletier/go-toml/v2 v2.2.4 // indirect
 | 
				
			||||||
	github.com/pkg/errors v0.9.1 // indirect
 | 
						github.com/pkg/errors v0.9.1 // indirect
 | 
				
			||||||
	github.com/richardlehane/mscfb v1.0.4 // indirect
 | 
						github.com/richardlehane/mscfb v1.0.4 // indirect
 | 
				
			||||||
	github.com/richardlehane/msoleps v1.0.3 // indirect
 | 
						github.com/richardlehane/msoleps v1.0.3 // indirect
 | 
				
			||||||
	github.com/rs/xid v1.5.0 // indirect
 | 
						github.com/rs/xid v1.6.0 // indirect
 | 
				
			||||||
	github.com/santhosh-tekuri/jsonschema/v5 v5.0.0 // indirect
 | 
						github.com/santhosh-tekuri/jsonschema/v5 v5.0.0 // indirect
 | 
				
			||||||
	github.com/sergi/go-diff v1.1.0 // indirect
 | 
					 | 
				
			||||||
	github.com/sirupsen/logrus v1.9.3 // indirect
 | 
						github.com/sirupsen/logrus v1.9.3 // indirect
 | 
				
			||||||
	github.com/spf13/afero v1.11.0 // indirect
 | 
						github.com/spf13/afero v1.14.0 // indirect
 | 
				
			||||||
	github.com/spf13/cast v1.7.0 // indirect
 | 
						github.com/spf13/cast v1.7.1 // indirect
 | 
				
			||||||
	github.com/spf13/pflag v1.0.5 // indirect
 | 
						github.com/spf13/pflag v1.0.6 // indirect
 | 
				
			||||||
	github.com/subosito/gotenv v1.6.0 // indirect
 | 
						github.com/subosito/gotenv v1.6.0 // indirect
 | 
				
			||||||
	github.com/twpayne/go-geom v1.5.7 // indirect
 | 
						github.com/twpayne/go-geom v1.5.7 // indirect
 | 
				
			||||||
	github.com/wneessen/go-mail v0.5.2 // indirect
 | 
					 | 
				
			||||||
	github.com/xdg-go/pbkdf2 v1.0.0 // indirect
 | 
						github.com/xdg-go/pbkdf2 v1.0.0 // indirect
 | 
				
			||||||
	github.com/xdg-go/scram v1.1.2 // indirect
 | 
						github.com/xdg-go/scram v1.1.2 // indirect
 | 
				
			||||||
	github.com/xdg-go/stringprep v1.0.4 // indirect
 | 
						github.com/xdg-go/stringprep v1.0.4 // indirect
 | 
				
			||||||
	github.com/xuri/efp v0.0.0-20220603152613-6918739fd470 // indirect
 | 
						github.com/xuri/efp v0.0.0-20220603152613-6918739fd470 // indirect
 | 
				
			||||||
	github.com/xuri/nfp v0.0.0-20220409054826-5e722a1d9e22 // indirect
 | 
						github.com/xuri/nfp v0.0.0-20220409054826-5e722a1d9e22 // indirect
 | 
				
			||||||
	github.com/youmark/pkcs8 v0.0.0-20240726163527-a2c0da244d78 // indirect
 | 
						github.com/youmark/pkcs8 v0.0.0-20240726163527-a2c0da244d78 // indirect
 | 
				
			||||||
	github.com/zclconf/go-cty v1.8.0 // indirect
 | 
						github.com/zclconf/go-cty v1.16.2 // indirect
 | 
				
			||||||
	go.etcd.io/etcd/api/v3 v3.5.12 // indirect
 | 
						go.etcd.io/etcd/api/v3 v3.5.12 // indirect
 | 
				
			||||||
	go.etcd.io/etcd/client/pkg/v3 v3.5.12 // indirect
 | 
						go.etcd.io/etcd/client/pkg/v3 v3.5.12 // indirect
 | 
				
			||||||
	go.mongodb.org/mongo-driver v1.17.1 // indirect
 | 
						go.mongodb.org/mongo-driver v1.17.3 // indirect
 | 
				
			||||||
	go.uber.org/atomic v1.11.0 // indirect
 | 
						go.uber.org/atomic v1.11.0 // indirect
 | 
				
			||||||
	go.uber.org/multierr v1.11.0 // indirect
 | 
						go.uber.org/multierr v1.11.0 // indirect
 | 
				
			||||||
	go.uber.org/zap v1.21.0 // indirect
 | 
						go.uber.org/zap v1.21.0 // indirect
 | 
				
			||||||
	golang.org/x/crypto v0.28.0 // indirect
 | 
						golang.org/x/crypto v0.37.0 // indirect
 | 
				
			||||||
	golang.org/x/net v0.29.0 // indirect
 | 
						golang.org/x/net v0.39.0 // indirect
 | 
				
			||||||
	golang.org/x/sync v0.11.0 // indirect
 | 
						golang.org/x/sync v0.13.0 // indirect
 | 
				
			||||||
	golang.org/x/sys v0.30.0 // indirect
 | 
						golang.org/x/sys v0.32.0 // indirect
 | 
				
			||||||
	golang.org/x/text v0.22.0 // indirect
 | 
						golang.org/x/text v0.24.0 // indirect
 | 
				
			||||||
	google.golang.org/genproto/googleapis/api v0.0.0-20240903143218-8af14fe29dc1 // indirect
 | 
						google.golang.org/genproto/googleapis/api v0.0.0-20250106144421-5f5ef82da422 // indirect
 | 
				
			||||||
	google.golang.org/genproto/googleapis/rpc v0.0.0-20240903143218-8af14fe29dc1 // indirect
 | 
						google.golang.org/genproto/googleapis/rpc v0.0.0-20250414145226-207652e42e2e // indirect
 | 
				
			||||||
	gopkg.in/ini.v1 v1.67.0 // indirect
 | 
						gopkg.in/ini.v1 v1.67.0 // indirect
 | 
				
			||||||
	gopkg.in/mgo.v2 v2.0.0-20190816093944-a6b53ec6cb22 // indirect
 | 
						gopkg.in/mgo.v2 v2.0.0-20190816093944-a6b53ec6cb22 // indirect
 | 
				
			||||||
	gopkg.in/yaml.v3 v3.0.1 // indirect
 | 
						gopkg.in/yaml.v3 v3.0.1 // indirect
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
							
								
								
									
										392
									
								
								go.sum
								
								
								
								
							
							
						
						
									
										392
									
								
								go.sum
								
								
								
								
							| 
						 | 
					@ -1,19 +1,47 @@
 | 
				
			||||||
ariga.io/atlas v0.12.0 h1:jDfjxT3ppKhzqLS26lZv9ni7p9TVNrhy7SQquaF7bPs=
 | 
					ariga.io/atlas v0.32.0 h1:y+77nueMrExLiKlz1CcPKh/nU7VSlWfBbwCShsJyvCw=
 | 
				
			||||||
ariga.io/atlas v0.12.0/go.mod h1:+TR129FJZ5Lvzms6dvCeGWh1yR6hMvmXBhug4hrNIGk=
 | 
					ariga.io/atlas v0.32.0/go.mod h1:Oe1xWPuu5q9LzyrWfbZmEZxFYeu4BHTyzfjeW2aZp/w=
 | 
				
			||||||
git.coopgo.io/coopgo-platform/agenda v1.0.0 h1:rTHgva1JKKO0wAPlINegifMkHm+xOg3IWW4yQRy334w=
 | 
					git.coopgo.io/coopgo-platform/agenda v1.0.0 h1:rTHgva1JKKO0wAPlINegifMkHm+xOg3IWW4yQRy334w=
 | 
				
			||||||
git.coopgo.io/coopgo-platform/agenda v1.0.0/go.mod h1:/hToSla0p6SeWn1zo1MDrfxdmo7RBdZDkbLqCVituIM=
 | 
					git.coopgo.io/coopgo-platform/agenda v1.0.0/go.mod h1:/hToSla0p6SeWn1zo1MDrfxdmo7RBdZDkbLqCVituIM=
 | 
				
			||||||
 | 
					git.coopgo.io/coopgo-platform/carpool-service v0.0.0-20250415082502-575b8129b727 h1:HdE8EO1CUhwGOTeNeG6dftWtxvZIHWA7SvxBAA7Ab1s=
 | 
				
			||||||
 | 
					git.coopgo.io/coopgo-platform/carpool-service v0.0.0-20250415082502-575b8129b727/go.mod h1:edaXmIta2b5SfK1OHG/02uRAXkKZqj7dSMQoeBxfUew=
 | 
				
			||||||
 | 
					git.coopgo.io/coopgo-platform/carpool-service/interoperability/ocss v0.0.0-20250429082239-a95cd6eb5523 h1:hXoUOEZ+umiyR0SzYbGacJxiUbW4puw4phmkfTVfqPU=
 | 
				
			||||||
 | 
					git.coopgo.io/coopgo-platform/carpool-service/interoperability/ocss v0.0.0-20250429082239-a95cd6eb5523/go.mod h1:c9aJwNtY4PJuqAFYZ9afnx46UAZtWJ3P8ICZM02/DBA=
 | 
				
			||||||
git.coopgo.io/coopgo-platform/diags v0.0.0-20250212093351-64da61495c9d h1:fBxVvik4Cb/6d4+HAXZi9e8x8P9UBCJt8JcWgqnNjsE=
 | 
					git.coopgo.io/coopgo-platform/diags v0.0.0-20250212093351-64da61495c9d h1:fBxVvik4Cb/6d4+HAXZi9e8x8P9UBCJt8JcWgqnNjsE=
 | 
				
			||||||
git.coopgo.io/coopgo-platform/diags v0.0.0-20250212093351-64da61495c9d/go.mod h1:diyq11WNkgJ0kYHdT7SphXPMQUyoq4lRk7T6IgM5yPA=
 | 
					git.coopgo.io/coopgo-platform/diags v0.0.0-20250212093351-64da61495c9d/go.mod h1:diyq11WNkgJ0kYHdT7SphXPMQUyoq4lRk7T6IgM5yPA=
 | 
				
			||||||
git.coopgo.io/coopgo-platform/emailing v0.0.0-20241119141913-9836b30191c1 h1:gAhJ9wwlitMiETmnD4U2L6xLnVd5xE4hPX72IJ5s7+I=
 | 
					 | 
				
			||||||
git.coopgo.io/coopgo-platform/emailing v0.0.0-20241119141913-9836b30191c1/go.mod h1:EXy6NRvFfpW6yIHoZUixldkXrj1qzjCbTHpumDvzaKI=
 | 
					 | 
				
			||||||
git.coopgo.io/coopgo-platform/emailing v0.0.0-20250212064257-167ef5864260 h1:Li3dotY6raKu9+oxEgICU7nwdomYpjgu19i3mZNiqTc=
 | 
					git.coopgo.io/coopgo-platform/emailing v0.0.0-20250212064257-167ef5864260 h1:Li3dotY6raKu9+oxEgICU7nwdomYpjgu19i3mZNiqTc=
 | 
				
			||||||
git.coopgo.io/coopgo-platform/emailing v0.0.0-20250212064257-167ef5864260/go.mod h1:6cvvjv0RLSwBthIQ4TiuZoXFGvQXZ55hNSJchWXAgB4=
 | 
					git.coopgo.io/coopgo-platform/emailing v0.0.0-20250212064257-167ef5864260/go.mod h1:6cvvjv0RLSwBthIQ4TiuZoXFGvQXZ55hNSJchWXAgB4=
 | 
				
			||||||
git.coopgo.io/coopgo-platform/fleets v0.0.0-20230310144446-feb935f8bf4e h1:eHahRTKlC8aBWYCd6LbXNcX8HoQhuZj31OFWrw0EL0U=
 | 
					git.coopgo.io/coopgo-platform/fleets v0.0.0-20230310144446-feb935f8bf4e h1:eHahRTKlC8aBWYCd6LbXNcX8HoQhuZj31OFWrw0EL0U=
 | 
				
			||||||
git.coopgo.io/coopgo-platform/fleets v0.0.0-20230310144446-feb935f8bf4e/go.mod h1:s9OIFCNcjBAbBzRNHwoCTYV6kAntPG9CpT3GVweGdTY=
 | 
					git.coopgo.io/coopgo-platform/fleets v0.0.0-20230310144446-feb935f8bf4e/go.mod h1:s9OIFCNcjBAbBzRNHwoCTYV6kAntPG9CpT3GVweGdTY=
 | 
				
			||||||
 | 
					git.coopgo.io/coopgo-platform/geography v0.0.0-20250613055151-06d78317f9ad h1:hNjV2OrYBtSrQZE22YMKIT/iCGdVE30drEJD1pkDhhU=
 | 
				
			||||||
 | 
					git.coopgo.io/coopgo-platform/geography v0.0.0-20250613055151-06d78317f9ad/go.mod h1:TbR3g1Awa8hpAe6LR1z1EQbv2IBVgN5JQ/FjXfKX4K0=
 | 
				
			||||||
 | 
					git.coopgo.io/coopgo-platform/geography v0.0.0-20250616160304-0285c9494673 h1:cth7a8Mnx1C6C6F5rv7SoKVMHYpI/CioFubyi0xB+Dw=
 | 
				
			||||||
 | 
					git.coopgo.io/coopgo-platform/geography v0.0.0-20250616160304-0285c9494673/go.mod h1:TbR3g1Awa8hpAe6LR1z1EQbv2IBVgN5JQ/FjXfKX4K0=
 | 
				
			||||||
git.coopgo.io/coopgo-platform/groups-management v0.0.0-20230310123255-5ef94ee0746c h1:bY7PyrAgYY02f5IpDyf1WVfRqvWzivu31K6aEAYbWCw=
 | 
					git.coopgo.io/coopgo-platform/groups-management v0.0.0-20230310123255-5ef94ee0746c h1:bY7PyrAgYY02f5IpDyf1WVfRqvWzivu31K6aEAYbWCw=
 | 
				
			||||||
git.coopgo.io/coopgo-platform/groups-management v0.0.0-20230310123255-5ef94ee0746c/go.mod h1:lozSy6qlIIYhvKKXscZzz28HAtS0qBDUTv5nofLRmYA=
 | 
					git.coopgo.io/coopgo-platform/groups-management v0.0.0-20230310123255-5ef94ee0746c/go.mod h1:lozSy6qlIIYhvKKXscZzz28HAtS0qBDUTv5nofLRmYA=
 | 
				
			||||||
git.coopgo.io/coopgo-platform/mobility-accounts v0.0.0-20230329105908-a76c0412a386 h1:v1JUdx8sknw2YYhFGz5cOAa1dEWNIBKvyiOpKr3RR+s=
 | 
					git.coopgo.io/coopgo-platform/mobility-accounts v0.0.0-20230329105908-a76c0412a386 h1:v1JUdx8sknw2YYhFGz5cOAa1dEWNIBKvyiOpKr3RR+s=
 | 
				
			||||||
git.coopgo.io/coopgo-platform/mobility-accounts v0.0.0-20230329105908-a76c0412a386/go.mod h1:1typNYtO+PQT6KG77vs/PUv0fO60/nbeSGZL2tt1LLg=
 | 
					git.coopgo.io/coopgo-platform/mobility-accounts v0.0.0-20230329105908-a76c0412a386/go.mod h1:1typNYtO+PQT6KG77vs/PUv0fO60/nbeSGZL2tt1LLg=
 | 
				
			||||||
 | 
					git.coopgo.io/coopgo-platform/multimodal-routing v0.0.0-20250504230045-8680f560066a h1:Fl12RBdYDxYh7H2xluPhgTpaHKUNULWpsclBKNx2t8s=
 | 
				
			||||||
 | 
					git.coopgo.io/coopgo-platform/multimodal-routing v0.0.0-20250504230045-8680f560066a/go.mod h1:zDMfGVIvzuWV4Cw4bSi2kuEyMDbAfNfs7cGOAWNKfOo=
 | 
				
			||||||
 | 
					git.coopgo.io/coopgo-platform/payments v0.0.0-20250523113636-a98e83924818 h1:7qIY7Ebh/sR6zCvK5nEsLCxljYwiwDf8KWIqSwqmGYU=
 | 
				
			||||||
 | 
					git.coopgo.io/coopgo-platform/payments v0.0.0-20250523113636-a98e83924818/go.mod h1:32jMjsXTcdzifpsJOQ3Jv8bkieLqefJXWfwkZIZ/Ua4=
 | 
				
			||||||
 | 
					git.coopgo.io/coopgo-platform/payments v0.0.0-20250610065650-b422c8adc3d7 h1:+FUcrwnQouOi/CfVyRNy7Lyv7Wm9XJ7y+qLaugMRl0g=
 | 
				
			||||||
 | 
					git.coopgo.io/coopgo-platform/payments v0.0.0-20250610065650-b422c8adc3d7/go.mod h1:32jMjsXTcdzifpsJOQ3Jv8bkieLqefJXWfwkZIZ/Ua4=
 | 
				
			||||||
 | 
					git.coopgo.io/coopgo-platform/payments v0.0.0-20250616110159-53d3a7f51f92 h1:mXQhmMkP5xh6oDcDQ6UJex0/LwOZgO3ci8IZTpSjQTg=
 | 
				
			||||||
 | 
					git.coopgo.io/coopgo-platform/payments v0.0.0-20250616110159-53d3a7f51f92/go.mod h1:X2WqQN7ZLAucV9z1gPubkWChkHbmdOIxWdwn18DZ+YU=
 | 
				
			||||||
 | 
					git.coopgo.io/coopgo-platform/payments v0.0.0-20250616162131-77f7b00b8fc3 h1:HGEo2E4IyprzshGKKeK7xMmorLNIGF8vbxa3zkBa+KM=
 | 
				
			||||||
 | 
					git.coopgo.io/coopgo-platform/payments v0.0.0-20250616162131-77f7b00b8fc3/go.mod h1:X2WqQN7ZLAucV9z1gPubkWChkHbmdOIxWdwn18DZ+YU=
 | 
				
			||||||
 | 
					git.coopgo.io/coopgo-platform/routing-service v0.0.0-20250304234521-faabcc54f536 h1:SllXX1VJXulfhNi+Pd0R9chksm8zO6gkWcTQ/uSMsdc=
 | 
				
			||||||
 | 
					git.coopgo.io/coopgo-platform/routing-service v0.0.0-20250304234521-faabcc54f536/go.mod h1:Nh7o15LlV0OuO9zxvJIs9FlelpeAaLYkXtFdgIkFrgg=
 | 
				
			||||||
 | 
					git.coopgo.io/coopgo-platform/sms v0.0.0-20250523074631-1f1e7fc6b7af h1:KxHim1dFcOVbFhRqelec8cJ65QBD2cma6eytW8llgYY=
 | 
				
			||||||
 | 
					git.coopgo.io/coopgo-platform/sms v0.0.0-20250523074631-1f1e7fc6b7af/go.mod h1:mad9D+WICDdpJzB+8H/wEVVbllK2mU6VLVByrppc9x0=
 | 
				
			||||||
 | 
					git.coopgo.io/coopgo-platform/solidarity-transport v0.0.0-20250528053224-d237401c81ba h1:CY4DxNQVpwF2OKTu+4+7KJZdM/TH4b3uOtKsI7PKTDw=
 | 
				
			||||||
 | 
					git.coopgo.io/coopgo-platform/solidarity-transport v0.0.0-20250528053224-d237401c81ba/go.mod h1:PKjHUTpP8VNm5bm5njsyj3m6bUpxOVMjoU+llDdfB9E=
 | 
				
			||||||
 | 
					git.coopgo.io/coopgo-platform/solidarity-transport v0.0.0-20250604135203-418c7152b665 h1:5CzA5T9IHjfhawogGO+ADxlUBN+va5xOEHTGAdI03ik=
 | 
				
			||||||
 | 
					git.coopgo.io/coopgo-platform/solidarity-transport v0.0.0-20250604135203-418c7152b665/go.mod h1:jnSYIECcH/nL8bLBwYD2WmJSPgWUC2rioOXxivWBTBM=
 | 
				
			||||||
 | 
					git.coopgo.io/coopgo-platform/solidarity-transport v0.0.0-20250610065958-2f0a45ced0a2 h1:OIkREZ/b9Vah+eV7cdarcaAkJ+ac39QAEENpJ8oi4Xw=
 | 
				
			||||||
 | 
					git.coopgo.io/coopgo-platform/solidarity-transport v0.0.0-20250610065958-2f0a45ced0a2/go.mod h1:jnSYIECcH/nL8bLBwYD2WmJSPgWUC2rioOXxivWBTBM=
 | 
				
			||||||
 | 
					git.coopgo.io/coopgo-platform/solidarity-transport v0.0.0-20250616110116-d71da5accdfd h1:2mvQWRfKHxihCxF1tOH1JgJinxqGDE96x4drlEloQNM=
 | 
				
			||||||
 | 
					git.coopgo.io/coopgo-platform/solidarity-transport v0.0.0-20250616110116-d71da5accdfd/go.mod h1:jnSYIECcH/nL8bLBwYD2WmJSPgWUC2rioOXxivWBTBM=
 | 
				
			||||||
github.com/Azure/go-ansiterm v0.0.0-20170929234023-d6e3b3328b78/go.mod h1:LmzpDX56iTiv29bbRTIsUNlaFfuhWRQBWjQdVyAevI8=
 | 
					github.com/Azure/go-ansiterm v0.0.0-20170929234023-d6e3b3328b78/go.mod h1:LmzpDX56iTiv29bbRTIsUNlaFfuhWRQBWjQdVyAevI8=
 | 
				
			||||||
github.com/DATA-DOG/go-sqlmock v1.3.2/go.mod h1:f/Ixk793poVmq4qj/V1dPUg2JEAKC73Q5eFN3EC/SaM=
 | 
					github.com/DATA-DOG/go-sqlmock v1.3.2/go.mod h1:f/Ixk793poVmq4qj/V1dPUg2JEAKC73Q5eFN3EC/SaM=
 | 
				
			||||||
github.com/DATA-DOG/go-sqlmock v1.5.2 h1:OcvFkGmslmlZibjAjaHm3L//6LiuBgolP7OputlJIzU=
 | 
					github.com/DATA-DOG/go-sqlmock v1.5.2 h1:OcvFkGmslmlZibjAjaHm3L//6LiuBgolP7OputlJIzU=
 | 
				
			||||||
| 
						 | 
					@ -23,20 +51,66 @@ github.com/Masterminds/semver v1.5.0/go.mod h1:MB6lktGJrhw8PrUyiEoblNEGEQ+RzHPF0
 | 
				
			||||||
github.com/Masterminds/sprig v2.22.0+incompatible/go.mod h1:y6hNFY5UBTIWBxnzTeuNhlNS5hqE0NB0E6fgfo2Br3o=
 | 
					github.com/Masterminds/sprig v2.22.0+incompatible/go.mod h1:y6hNFY5UBTIWBxnzTeuNhlNS5hqE0NB0E6fgfo2Br3o=
 | 
				
			||||||
github.com/Microsoft/go-winio v0.4.14/go.mod h1:qXqCSQ3Xa7+6tgxaGTIe4Kpcdsi+P8jBhyzoq1bpyYA=
 | 
					github.com/Microsoft/go-winio v0.4.14/go.mod h1:qXqCSQ3Xa7+6tgxaGTIe4Kpcdsi+P8jBhyzoq1bpyYA=
 | 
				
			||||||
github.com/Nvveen/Gotty v0.0.0-20120604004816-cd527374f1e5/go.mod h1:lmUJ/7eu/Q8D7ML55dXQrVaamCz2vxCfdQBasLZfHKk=
 | 
					github.com/Nvveen/Gotty v0.0.0-20120604004816-cd527374f1e5/go.mod h1:lmUJ/7eu/Q8D7ML55dXQrVaamCz2vxCfdQBasLZfHKk=
 | 
				
			||||||
github.com/agext/levenshtein v1.2.1 h1:QmvMAjj2aEICytGiWzmxoE0x2KZvE0fvmqMOfy2tjT8=
 | 
					github.com/RaveNoX/go-jsoncommentstrip v1.0.0/go.mod h1:78ihd09MekBnJnxpICcwzCMzGrKSKYe4AqU6PDYYpjk=
 | 
				
			||||||
github.com/agext/levenshtein v1.2.1/go.mod h1:JEDfjyjHDjOF/1e4FlBE/PkbqA9OfWu2ki2W0IB5558=
 | 
					github.com/RoaringBitmap/roaring v0.4.23 h1:gpyfd12QohbqhFO4NVDUdoPOCXsyahYRQhINmlHxKeo=
 | 
				
			||||||
 | 
					github.com/RoaringBitmap/roaring/v2 v2.4.5 h1:uGrrMreGjvAtTBobc0g5IrW1D5ldxDQYe2JW2gggRdg=
 | 
				
			||||||
 | 
					github.com/RoaringBitmap/roaring/v2 v2.4.5/go.mod h1:FiJcsfkGje/nZBZgCu0ZxCPOKD/hVXDS2dXi7/eUFE0=
 | 
				
			||||||
 | 
					github.com/agext/levenshtein v1.2.3 h1:YB2fHEn0UJagG8T1rrWknE3ZQzWM06O8AMAatNn7lmo=
 | 
				
			||||||
 | 
					github.com/agext/levenshtein v1.2.3/go.mod h1:JEDfjyjHDjOF/1e4FlBE/PkbqA9OfWu2ki2W0IB5558=
 | 
				
			||||||
github.com/alecthomas/assert/v2 v2.10.0 h1:jjRCHsj6hBJhkmhznrCzoNpbA3zqy0fYiUcYZP/GkPY=
 | 
					github.com/alecthomas/assert/v2 v2.10.0 h1:jjRCHsj6hBJhkmhznrCzoNpbA3zqy0fYiUcYZP/GkPY=
 | 
				
			||||||
github.com/alecthomas/assert/v2 v2.10.0/go.mod h1:Bze95FyfUr7x34QZrjL+XP+0qgp/zg8yS+TtBj1WA3k=
 | 
					github.com/alecthomas/assert/v2 v2.10.0/go.mod h1:Bze95FyfUr7x34QZrjL+XP+0qgp/zg8yS+TtBj1WA3k=
 | 
				
			||||||
github.com/alecthomas/repr v0.4.0 h1:GhI2A8MACjfegCPVq9f1FLvIBS+DrQ2KQBFZP1iFzXc=
 | 
					github.com/alecthomas/repr v0.4.0 h1:GhI2A8MACjfegCPVq9f1FLvIBS+DrQ2KQBFZP1iFzXc=
 | 
				
			||||||
github.com/alecthomas/repr v0.4.0/go.mod h1:Fr0507jx4eOXV7AlPV6AVZLYrLIuIeSOWtW57eE/O/4=
 | 
					github.com/alecthomas/repr v0.4.0/go.mod h1:Fr0507jx4eOXV7AlPV6AVZLYrLIuIeSOWtW57eE/O/4=
 | 
				
			||||||
github.com/apparentlymart/go-dump v0.0.0-20180507223929-23540a00eaa3/go.mod h1:oL81AME2rN47vu18xqj1S1jPIPuN7afo62yKTNn3XMM=
 | 
					github.com/apapsch/go-jsonmerge/v2 v2.0.0 h1:axGnT1gRIfimI7gJifB699GoE/oq+F2MU7Dml6nw9rQ=
 | 
				
			||||||
github.com/apparentlymart/go-textseg v1.0.0/go.mod h1:z96Txxhf3xSFMPmb5X/1W05FF/Nj9VFpLOpjS5yuumk=
 | 
					github.com/apapsch/go-jsonmerge/v2 v2.0.0/go.mod h1:lvDnEdqiQrp0O42VQGgmlKpxL1AP2+08jFMw88y4klk=
 | 
				
			||||||
github.com/apparentlymart/go-textseg/v13 v13.0.0 h1:Y+KvPE1NYz0xl601PVImeQfFyEy6iT90AvPUL1NNfNw=
 | 
					github.com/apparentlymart/go-textseg/v15 v15.0.0 h1:uYvfpb3DyLSCGWnctWKGj857c6ew1u1fNQOlOtuGxQY=
 | 
				
			||||||
github.com/apparentlymart/go-textseg/v13 v13.0.0/go.mod h1:ZK2fH7c4NqDTLtiYLvIkEghdlcqw7yxLeM89kiTRPUo=
 | 
					github.com/apparentlymart/go-textseg/v15 v15.0.0/go.mod h1:K8XmNZdhEBkdlyDdvbmmsvpAG721bKi0joRfFdHIWJ4=
 | 
				
			||||||
github.com/arran4/golang-ical v0.3.1 h1:v13B3eQZ9VDHTAvT6M11vVzxYgcYmjyPBE2eAZl3VZk=
 | 
					github.com/arran4/golang-ical v0.3.1 h1:v13B3eQZ9VDHTAvT6M11vVzxYgcYmjyPBE2eAZl3VZk=
 | 
				
			||||||
github.com/arran4/golang-ical v0.3.1/go.mod h1:LZWxF8ZIu/sjBVUCV0udiVPrQAgq3V0aa0RfbO99Qkk=
 | 
					github.com/arran4/golang-ical v0.3.1/go.mod h1:LZWxF8ZIu/sjBVUCV0udiVPrQAgq3V0aa0RfbO99Qkk=
 | 
				
			||||||
github.com/benbjohnson/clock v1.1.0 h1:Q92kusRqC1XV2MjkWETPvjJVqKetz1OzxZB7mHJLju8=
 | 
					github.com/benbjohnson/clock v1.1.0 h1:Q92kusRqC1XV2MjkWETPvjJVqKetz1OzxZB7mHJLju8=
 | 
				
			||||||
github.com/benbjohnson/clock v1.1.0/go.mod h1:J11/hYXuz8f4ySSvYwY0FKfm+ezbsZBKZxNJlLklBHA=
 | 
					github.com/benbjohnson/clock v1.1.0/go.mod h1:J11/hYXuz8f4ySSvYwY0FKfm+ezbsZBKZxNJlLklBHA=
 | 
				
			||||||
 | 
					github.com/bits-and-blooms/bitset v1.12.0/go.mod h1:7hO7Gc7Pp1vODcmWvKMRA9BNmbv6a/7QIWpPxHddWR8=
 | 
				
			||||||
 | 
					github.com/bits-and-blooms/bitset v1.22.0 h1:Tquv9S8+SGaS3EhyA+up3FXzmkhxPGjQQCkcs2uw7w4=
 | 
				
			||||||
 | 
					github.com/bits-and-blooms/bitset v1.22.0/go.mod h1:7hO7Gc7Pp1vODcmWvKMRA9BNmbv6a/7QIWpPxHddWR8=
 | 
				
			||||||
 | 
					github.com/blevesearch/bleve/v2 v2.5.2 h1:Ab0r0MODV2C5A6BEL87GqLBySqp/s9xFgceCju6BQk8=
 | 
				
			||||||
 | 
					github.com/blevesearch/bleve/v2 v2.5.2/go.mod h1:5Dj6dUQxZM6aqYT3eutTD/GpWKGFSsV8f7LDidFbwXo=
 | 
				
			||||||
 | 
					github.com/blevesearch/bleve_index_api v1.2.8 h1:Y98Pu5/MdlkRyLM0qDHostYo7i+Vv1cDNhqTeR4Sy6Y=
 | 
				
			||||||
 | 
					github.com/blevesearch/bleve_index_api v1.2.8/go.mod h1:rKQDl4u51uwafZxFrPD1R7xFOwKnzZW7s/LSeK4lgo0=
 | 
				
			||||||
 | 
					github.com/blevesearch/geo v0.2.3 h1:K9/vbGI9ehlXdxjxDRJtoAMt7zGAsMIzc6n8zWcwnhg=
 | 
				
			||||||
 | 
					github.com/blevesearch/geo v0.2.3/go.mod h1:K56Q33AzXt2YExVHGObtmRSFYZKYGv0JEN5mdacJJR8=
 | 
				
			||||||
 | 
					github.com/blevesearch/go-faiss v1.0.25 h1:lel1rkOUGbT1CJ0YgzKwC7k+XH0XVBHnCVWahdCXk4U=
 | 
				
			||||||
 | 
					github.com/blevesearch/go-faiss v1.0.25/go.mod h1:OMGQwOaRRYxrmeNdMrXJPvVx8gBnvE5RYrr0BahNnkk=
 | 
				
			||||||
 | 
					github.com/blevesearch/go-porterstemmer v1.0.3 h1:GtmsqID0aZdCSNiY8SkuPJ12pD4jI+DdXTAn4YRcHCo=
 | 
				
			||||||
 | 
					github.com/blevesearch/go-porterstemmer v1.0.3/go.mod h1:angGc5Ht+k2xhJdZi511LtmxuEf0OVpvUUNrwmM1P7M=
 | 
				
			||||||
 | 
					github.com/blevesearch/gtreap v0.1.1 h1:2JWigFrzDMR+42WGIN/V2p0cUvn4UP3C4Q5nmaZGW8Y=
 | 
				
			||||||
 | 
					github.com/blevesearch/gtreap v0.1.1/go.mod h1:QaQyDRAT51sotthUWAH4Sj08awFSSWzgYICSZ3w0tYk=
 | 
				
			||||||
 | 
					github.com/blevesearch/mmap-go v1.0.4 h1:OVhDhT5B/M1HNPpYPBKIEJaD0F3Si+CrEKULGCDPWmc=
 | 
				
			||||||
 | 
					github.com/blevesearch/mmap-go v1.0.4/go.mod h1:EWmEAOmdAS9z/pi/+Toxu99DnsbhG1TIxUoRmJw/pSs=
 | 
				
			||||||
 | 
					github.com/blevesearch/scorch_segment_api/v2 v2.3.10 h1:Yqk0XD1mE0fDZAJXTjawJ8If/85JxnLd8v5vG/jWE/s=
 | 
				
			||||||
 | 
					github.com/blevesearch/scorch_segment_api/v2 v2.3.10/go.mod h1:Z3e6ChN3qyN35yaQpl00MfI5s8AxUJbpTR/DL8QOQ+8=
 | 
				
			||||||
 | 
					github.com/blevesearch/segment v0.9.1 h1:+dThDy+Lvgj5JMxhmOVlgFfkUtZV2kw49xax4+jTfSU=
 | 
				
			||||||
 | 
					github.com/blevesearch/segment v0.9.1/go.mod h1:zN21iLm7+GnBHWTao9I+Au/7MBiL8pPFtJBJTsk6kQw=
 | 
				
			||||||
 | 
					github.com/blevesearch/snowballstem v0.9.0 h1:lMQ189YspGP6sXvZQ4WZ+MLawfV8wOmPoD/iWeNXm8s=
 | 
				
			||||||
 | 
					github.com/blevesearch/snowballstem v0.9.0/go.mod h1:PivSj3JMc8WuaFkTSRDW2SlrulNWPl4ABg1tC/hlgLs=
 | 
				
			||||||
 | 
					github.com/blevesearch/upsidedown_store_api v1.0.2 h1:U53Q6YoWEARVLd1OYNc9kvhBMGZzVrdmaozG2MfoB+A=
 | 
				
			||||||
 | 
					github.com/blevesearch/upsidedown_store_api v1.0.2/go.mod h1:M01mh3Gpfy56Ps/UXHjEO/knbqyQ1Oamg8If49gRwrQ=
 | 
				
			||||||
 | 
					github.com/blevesearch/vellum v1.1.0 h1:CinkGyIsgVlYf8Y2LUQHvdelgXr6PYuvoDIajq6yR9w=
 | 
				
			||||||
 | 
					github.com/blevesearch/vellum v1.1.0/go.mod h1:QgwWryE8ThtNPxtgWJof5ndPfx0/YMBh+W2weHKPw8Y=
 | 
				
			||||||
 | 
					github.com/blevesearch/zapx/v11 v11.4.2 h1:l46SV+b0gFN+Rw3wUI1YdMWdSAVhskYuvxlcgpQFljs=
 | 
				
			||||||
 | 
					github.com/blevesearch/zapx/v11 v11.4.2/go.mod h1:4gdeyy9oGa/lLa6D34R9daXNUvfMPZqUYjPwiLmekwc=
 | 
				
			||||||
 | 
					github.com/blevesearch/zapx/v12 v12.4.2 h1:fzRbhllQmEMUuAQ7zBuMvKRlcPA5ESTgWlDEoB9uQNE=
 | 
				
			||||||
 | 
					github.com/blevesearch/zapx/v12 v12.4.2/go.mod h1:TdFmr7afSz1hFh/SIBCCZvcLfzYvievIH6aEISCte58=
 | 
				
			||||||
 | 
					github.com/blevesearch/zapx/v13 v13.4.2 h1:46PIZCO/ZuKZYgxI8Y7lOJqX3Irkc3N8W82QTK3MVks=
 | 
				
			||||||
 | 
					github.com/blevesearch/zapx/v13 v13.4.2/go.mod h1:knK8z2NdQHlb5ot/uj8wuvOq5PhDGjNYQQy0QDnopZk=
 | 
				
			||||||
 | 
					github.com/blevesearch/zapx/v14 v14.4.2 h1:2SGHakVKd+TrtEqpfeq8X+So5PShQ5nW6GNxT7fWYz0=
 | 
				
			||||||
 | 
					github.com/blevesearch/zapx/v14 v14.4.2/go.mod h1:rz0XNb/OZSMjNorufDGSpFpjoFKhXmppH9Hi7a877D8=
 | 
				
			||||||
 | 
					github.com/blevesearch/zapx/v15 v15.4.2 h1:sWxpDE0QQOTjyxYbAVjt3+0ieu8NCE0fDRaFxEsp31k=
 | 
				
			||||||
 | 
					github.com/blevesearch/zapx/v15 v15.4.2/go.mod h1:1pssev/59FsuWcgSnTa0OeEpOzmhtmr/0/11H0Z8+Nw=
 | 
				
			||||||
 | 
					github.com/blevesearch/zapx/v16 v16.2.4 h1:tGgfvleXTAkwsD5mEzgM3zCS/7pgocTCnO1oyAUjlww=
 | 
				
			||||||
 | 
					github.com/blevesearch/zapx/v16 v16.2.4/go.mod h1:Rti/REtuuMmzwsI8/C/qIzRaEoSK/wiFYw5e5ctUKKs=
 | 
				
			||||||
 | 
					github.com/bmatcuk/doublestar v1.1.1/go.mod h1:UD6OnuiIn0yFxxA2le/rnRU1G4RaI4UvFv1sNto9p6w=
 | 
				
			||||||
 | 
					github.com/bmatcuk/doublestar v1.3.4 h1:gPypJ5xD31uhX6Tf54sDPUOBXTqKH4c9aPY66CyQrS0=
 | 
				
			||||||
 | 
					github.com/bmatcuk/doublestar v1.3.4/go.mod h1:wiQtGV+rzVYxB7WIlirSN++5HPtPlXEo9MEoZQC/PmE=
 | 
				
			||||||
github.com/cenkalti/backoff v2.1.1+incompatible/go.mod h1:90ReRw6GdpyfrHakVjL/QHaoyV4aDUVVkXQJJJ3NXXM=
 | 
					github.com/cenkalti/backoff v2.1.1+incompatible/go.mod h1:90ReRw6GdpyfrHakVjL/QHaoyV4aDUVVkXQJJJ3NXXM=
 | 
				
			||||||
github.com/containerd/continuity v0.0.0-20181203112020-004b46473808/go.mod h1:GL3xCUCBDV3CZiTSEKksMWbLE66hEyuu9qyDOOqM47Y=
 | 
					github.com/containerd/continuity v0.0.0-20181203112020-004b46473808/go.mod h1:GL3xCUCBDV3CZiTSEKksMWbLE66hEyuu9qyDOOqM47Y=
 | 
				
			||||||
github.com/coreos/go-oidc/v3 v3.11.0 h1:Ia3MxdwpSw702YW0xgfmP1GVCMA9aEFWu12XUZ3/OtI=
 | 
					github.com/coreos/go-oidc/v3 v3.11.0 h1:Ia3MxdwpSw702YW0xgfmP1GVCMA9aEFWu12XUZ3/OtI=
 | 
				
			||||||
| 
						 | 
					@ -55,94 +129,103 @@ github.com/docker/go-connections v0.4.0/go.mod h1:Gbd7IOopHjR8Iph03tsViu4nIes5Xh
 | 
				
			||||||
github.com/docker/go-units v0.3.3/go.mod h1:fgPhTUdO+D/Jk86RDLlptpiXQzgHJF7gydDDbaIK4Dk=
 | 
					github.com/docker/go-units v0.3.3/go.mod h1:fgPhTUdO+D/Jk86RDLlptpiXQzgHJF7gydDDbaIK4Dk=
 | 
				
			||||||
github.com/dustin/go-humanize v1.0.0 h1:VSnTsYCnlFHaM2/igO1h6X3HA71jcobQuxemgkq4zYo=
 | 
					github.com/dustin/go-humanize v1.0.0 h1:VSnTsYCnlFHaM2/igO1h6X3HA71jcobQuxemgkq4zYo=
 | 
				
			||||||
github.com/dustin/go-humanize v1.0.0/go.mod h1:HtrtbFcZ19U5GC7JDqmcUSB87Iq5E25KnS6fMYU6eOk=
 | 
					github.com/dustin/go-humanize v1.0.0/go.mod h1:HtrtbFcZ19U5GC7JDqmcUSB87Iq5E25KnS6fMYU6eOk=
 | 
				
			||||||
 | 
					github.com/dvyukov/go-fuzz v0.0.0-20200318091601-be3528f3a813/go.mod h1:11Gm+ccJnvAhCNLlf5+cS9KjtbaD5I5zaZpFMsTHWTw=
 | 
				
			||||||
github.com/fatih/color v1.9.0/go.mod h1:eQcE1qtQxscV5RaZvpXrrb8Drkc3/DdQ+uUYCNjL+zU=
 | 
					github.com/fatih/color v1.9.0/go.mod h1:eQcE1qtQxscV5RaZvpXrrb8Drkc3/DdQ+uUYCNjL+zU=
 | 
				
			||||||
github.com/fogleman/gg v1.3.0 h1:/7zJX8F6AaYQc57WQCyN9cAIz+4bCJGO9B+dyW29am8=
 | 
					github.com/fogleman/gg v1.3.0 h1:/7zJX8F6AaYQc57WQCyN9cAIz+4bCJGO9B+dyW29am8=
 | 
				
			||||||
github.com/fogleman/gg v1.3.0/go.mod h1:R/bRT+9gY/C5z7JzPU0zXsXHKM4/ayA+zqcVNZzPa1k=
 | 
					github.com/fogleman/gg v1.3.0/go.mod h1:R/bRT+9gY/C5z7JzPU0zXsXHKM4/ayA+zqcVNZzPa1k=
 | 
				
			||||||
github.com/frankban/quicktest v1.14.6 h1:7Xjx+VpznH+oBnejlPUj8oUpdxnVs4f8XU8WnHkI4W8=
 | 
					github.com/frankban/quicktest v1.14.6 h1:7Xjx+VpznH+oBnejlPUj8oUpdxnVs4f8XU8WnHkI4W8=
 | 
				
			||||||
github.com/frankban/quicktest v1.14.6/go.mod h1:4ptaffx2x8+WTWXmUCuVU6aPUX1/Mz7zb5vbUoiM6w0=
 | 
					github.com/frankban/quicktest v1.14.6/go.mod h1:4ptaffx2x8+WTWXmUCuVU6aPUX1/Mz7zb5vbUoiM6w0=
 | 
				
			||||||
github.com/fsnotify/fsnotify v1.8.0 h1:dAwr6QBTBZIkG8roQaJjGof0pp0EeF+tNV7YBP3F/8M=
 | 
					github.com/fsnotify/fsnotify v1.9.0 h1:2Ml+OJNzbYCTzsxtv8vKSFD9PbJjmhYF14k/jKC7S9k=
 | 
				
			||||||
github.com/fsnotify/fsnotify v1.8.0/go.mod h1:8jBTzvmWwFyi3Pb8djgCCO5IBqzKJ/Jwo8TRcHyHii0=
 | 
					github.com/fsnotify/fsnotify v1.9.0/go.mod h1:8jBTzvmWwFyi3Pb8djgCCO5IBqzKJ/Jwo8TRcHyHii0=
 | 
				
			||||||
 | 
					github.com/gabriel-vasile/mimetype v1.4.2 h1:w5qFW6JKBz9Y393Y4q372O9A7cUSequkh1Q7OhCmWKU=
 | 
				
			||||||
 | 
					github.com/gabriel-vasile/mimetype v1.4.2/go.mod h1:zApsH/mKG4w07erKIaJPFiX0Tsq9BFQgN3qGY5GnNgA=
 | 
				
			||||||
github.com/go-jose/go-jose/v4 v4.0.2 h1:R3l3kkBds16bO7ZFAEEcofK0MkrAJt3jlJznWZG0nvk=
 | 
					github.com/go-jose/go-jose/v4 v4.0.2 h1:R3l3kkBds16bO7ZFAEEcofK0MkrAJt3jlJznWZG0nvk=
 | 
				
			||||||
github.com/go-jose/go-jose/v4 v4.0.2/go.mod h1:WVf9LFMHh/QVrmqrOfqun0C45tMe3RoiKJMPvgWwLfY=
 | 
					github.com/go-jose/go-jose/v4 v4.0.2/go.mod h1:WVf9LFMHh/QVrmqrOfqun0C45tMe3RoiKJMPvgWwLfY=
 | 
				
			||||||
github.com/go-openapi/inflect v0.19.0 h1:9jCH9scKIbHeV9m12SmPilScz6krDxKRasNNSNPXu/4=
 | 
					github.com/go-logr/logr v1.4.2 h1:6pFjapn8bFcIbiKo3XT4j/BhANplGihG6tvd+8rYgrY=
 | 
				
			||||||
github.com/go-openapi/inflect v0.19.0/go.mod h1:lHpZVlpIQqLyKwJ4N+YSc9hchQy/i12fJykb83CRBH4=
 | 
					github.com/go-logr/logr v1.4.2/go.mod h1:9T104GzyrTigFIr8wt5mBrctHMim0Nb2HLGrmQ40KvY=
 | 
				
			||||||
github.com/go-playground/assert/v2 v2.0.1 h1:MsBgLAaY856+nPRTKrp3/OZK38U/wa0CcBYNjji3q3A=
 | 
					github.com/go-logr/stdr v1.2.2 h1:hSWxHoqTgW2S2qGc0LTAI563KZ5YKYRhT3MFKZMbjag=
 | 
				
			||||||
github.com/go-playground/assert/v2 v2.0.1/go.mod h1:VDjEfimB/XKnb+ZQfWdccd7VUvScMdVu0Titje2rxJ4=
 | 
					github.com/go-logr/stdr v1.2.2/go.mod h1:mMo/vtBO5dYbehREoey6XUKy/eSumjCCveDpRre4VKE=
 | 
				
			||||||
github.com/go-playground/locales v0.14.0 h1:u50s323jtVGugKlcYeyzC0etD1HifMjqmJqb8WugfUU=
 | 
					github.com/go-openapi/inflect v0.21.2 h1:0gClGlGcxifcJR56zwvhaOulnNgnhc4qTAkob5ObnSM=
 | 
				
			||||||
github.com/go-playground/locales v0.14.0/go.mod h1:sawfccIbzZTqEDETgFXqTho0QybSa7l++s0DH+LDiLs=
 | 
					github.com/go-openapi/inflect v0.21.2/go.mod h1:INezMuUu7SJQc2AyR3WO0DqqYUJSj8Kb4hBd7WtjlAw=
 | 
				
			||||||
github.com/go-playground/universal-translator v0.18.0 h1:82dyy6p4OuJq4/CByFNOn/jYrnRPArHwAcmLoJZxyho=
 | 
					github.com/go-playground/assert/v2 v2.2.0 h1:JvknZsQTYeFEAhQwI4qEt9cyV5ONwRHC+lYKSsYSR8s=
 | 
				
			||||||
github.com/go-playground/universal-translator v0.18.0/go.mod h1:UvRDBj+xPUEGrFYl+lu/H90nyDXpg0fqeB/AQUGNTVA=
 | 
					github.com/go-playground/assert/v2 v2.2.0/go.mod h1:VDjEfimB/XKnb+ZQfWdccd7VUvScMdVu0Titje2rxJ4=
 | 
				
			||||||
github.com/go-playground/validator/v10 v10.11.0 h1:0W+xRM511GY47Yy3bZUbJVitCNg2BOGlCyvTqsp/xIw=
 | 
					github.com/go-playground/locales v0.14.1 h1:EWaQ/wswjilfKLTECiXz7Rh+3BjFhfDFKv/oXslEjJA=
 | 
				
			||||||
github.com/go-playground/validator/v10 v10.11.0/go.mod h1:i+3WkQ1FvaUjjxh1kSvIA4dMGDBiPU55YFDl0WbKdWU=
 | 
					github.com/go-playground/locales v0.14.1/go.mod h1:hxrqLVvrK65+Rwrd5Fc6F2O76J/NuW9t0sjnWqG1slY=
 | 
				
			||||||
 | 
					github.com/go-playground/universal-translator v0.18.1 h1:Bcnm0ZwsGyWbCzImXv+pAJnYK9S473LQFuzCbDbfSFY=
 | 
				
			||||||
 | 
					github.com/go-playground/universal-translator v0.18.1/go.mod h1:xekY+UJKNuX9WP91TpwSH2VMlDf28Uj24BCp08ZFTUY=
 | 
				
			||||||
 | 
					github.com/go-playground/validator/v10 v10.14.1 h1:9c50NUPC30zyuKprjL3vNZ0m5oG+jU0zvx4AqHGnv4k=
 | 
				
			||||||
 | 
					github.com/go-playground/validator/v10 v10.14.1/go.mod h1:9iXMNT7sEkjXb0I+enO7QXmzG6QCsPWY4zveKFVRSyU=
 | 
				
			||||||
github.com/go-test/deep v1.0.3 h1:ZrJSEWsXzPOxaZnFteGEfooLba+ju3FYIbOrS+rQd68=
 | 
					github.com/go-test/deep v1.0.3 h1:ZrJSEWsXzPOxaZnFteGEfooLba+ju3FYIbOrS+rQd68=
 | 
				
			||||||
github.com/go-test/deep v1.0.3/go.mod h1:wGDj63lr65AM2AQyKZd/NYHGb0R+1RLqB8NKt3aSFNA=
 | 
					github.com/go-test/deep v1.0.3/go.mod h1:wGDj63lr65AM2AQyKZd/NYHGb0R+1RLqB8NKt3aSFNA=
 | 
				
			||||||
 | 
					github.com/go-viper/mapstructure/v2 v2.2.1 h1:ZAaOCxANMuZx5RCeg0mBdEZk7DZasvvZIxtHqx8aGss=
 | 
				
			||||||
 | 
					github.com/go-viper/mapstructure/v2 v2.2.1/go.mod h1:oJDH3BJKyqBA2TXFhDsKDGDTlndYOZ6rGS0BRZIxGhM=
 | 
				
			||||||
github.com/godbus/dbus/v5 v5.0.4/go.mod h1:xhWf0FNVPg57R7Z0UbKHbJfkEywrmjJnf7w5xrFpKfA=
 | 
					github.com/godbus/dbus/v5 v5.0.4/go.mod h1:xhWf0FNVPg57R7Z0UbKHbJfkEywrmjJnf7w5xrFpKfA=
 | 
				
			||||||
github.com/gogo/protobuf v1.3.2 h1:Ov1cvc58UF3b5XjBnZv7+opcTcQFZebYjWzi34vdm4Q=
 | 
					github.com/gogo/protobuf v1.3.2 h1:Ov1cvc58UF3b5XjBnZv7+opcTcQFZebYjWzi34vdm4Q=
 | 
				
			||||||
github.com/gogo/protobuf v1.3.2/go.mod h1:P1XiOD3dCwIKUDQYPy72D8LYyHL2YPYrpS2s69NZV8Q=
 | 
					github.com/gogo/protobuf v1.3.2/go.mod h1:P1XiOD3dCwIKUDQYPy72D8LYyHL2YPYrpS2s69NZV8Q=
 | 
				
			||||||
github.com/golang/freetype v0.0.0-20170609003504-e2365dfdc4a0 h1:DACJavvAHhabrF08vX0COfcOBJRhZ8lUbR+ZWIs0Y5g=
 | 
					github.com/golang/freetype v0.0.0-20170609003504-e2365dfdc4a0 h1:DACJavvAHhabrF08vX0COfcOBJRhZ8lUbR+ZWIs0Y5g=
 | 
				
			||||||
github.com/golang/freetype v0.0.0-20170609003504-e2365dfdc4a0/go.mod h1:E/TSTwGwJL78qG/PmXZO1EjYhfJinVAhrmmHX6Z8B9k=
 | 
					github.com/golang/freetype v0.0.0-20170609003504-e2365dfdc4a0/go.mod h1:E/TSTwGwJL78qG/PmXZO1EjYhfJinVAhrmmHX6Z8B9k=
 | 
				
			||||||
github.com/golang/protobuf v1.1.0/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U=
 | 
					github.com/golang/protobuf v1.5.0/go.mod h1:FsONVRAS9T7sI+LIUmWTfcYkHO4aIWwzhcaSAoJOfIk=
 | 
				
			||||||
github.com/golang/protobuf v1.3.1/go.mod h1:6lQm79b+lXiMfvg/cZm0SGofjICqVBUtrP5yJMmIC1U=
 | 
					 | 
				
			||||||
github.com/golang/protobuf v1.3.4/go.mod h1:vzj43D7+SQXF/4pzW/hwtAqwc6iTitCiVSaWz5lYuqw=
 | 
					 | 
				
			||||||
github.com/golang/protobuf v1.5.4 h1:i7eJL8qZTpSEXOPTxNKhASYpMn+8e5Q6AdndVa1dWek=
 | 
					github.com/golang/protobuf v1.5.4 h1:i7eJL8qZTpSEXOPTxNKhASYpMn+8e5Q6AdndVa1dWek=
 | 
				
			||||||
github.com/golang/protobuf v1.5.4/go.mod h1:lnTiLA8Wa4RWRcIUkrtSVa5nRhsEGBg48fD6rSs7xps=
 | 
					github.com/golang/protobuf v1.5.4/go.mod h1:lnTiLA8Wa4RWRcIUkrtSVa5nRhsEGBg48fD6rSs7xps=
 | 
				
			||||||
github.com/golang/snappy v0.0.4 h1:yAGX7huGHXlcLOEtBnF4w7FQwA26wojNCwOYAEhLjQM=
 | 
					github.com/golang/snappy v0.0.1/go.mod h1:/XxbfmMg8lxefKM7IXC3fBNl/7bRcc72aCRzEWrmP2Q=
 | 
				
			||||||
github.com/golang/snappy v0.0.4/go.mod h1:/XxbfmMg8lxefKM7IXC3fBNl/7bRcc72aCRzEWrmP2Q=
 | 
					github.com/golang/snappy v1.0.0 h1:Oy607GVXHs7RtbggtPBnr2RmDArIsAefDwvrdWvRhGs=
 | 
				
			||||||
github.com/google/go-cmp v0.3.1/go.mod h1:8QqcDgzrUqlUb/G2PQTWiueGozuR1884gddMywk6iLU=
 | 
					github.com/golang/snappy v1.0.0/go.mod h1:/XxbfmMg8lxefKM7IXC3fBNl/7bRcc72aCRzEWrmP2Q=
 | 
				
			||||||
github.com/google/go-cmp v0.4.0/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE=
 | 
					github.com/google/go-cmp v0.4.0/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE=
 | 
				
			||||||
github.com/google/go-cmp v0.6.0 h1:ofyhxvXcZhMsU5ulbFiLKl/XBFqE1GSq7atu8tAmTRI=
 | 
					github.com/google/go-cmp v0.5.2/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE=
 | 
				
			||||||
 | 
					github.com/google/go-cmp v0.5.5/go.mod h1:v8dTdLbMG2kIc/vJvl+f65V22dbkXbowE6jgT/gNBxE=
 | 
				
			||||||
github.com/google/go-cmp v0.6.0/go.mod h1:17dUlkBOakJ0+DkrSSNjCkIjxS6bF9zb3elmeNGIjoY=
 | 
					github.com/google/go-cmp v0.6.0/go.mod h1:17dUlkBOakJ0+DkrSSNjCkIjxS6bF9zb3elmeNGIjoY=
 | 
				
			||||||
 | 
					github.com/google/go-cmp v0.7.0 h1:wk8382ETsv4JYUZwIsn6YpYiWiBsYLSJiTsyBybVuN8=
 | 
				
			||||||
 | 
					github.com/google/go-cmp v0.7.0/go.mod h1:pXiqmnSA92OHEEa9HXL2W4E7lf9JzCmGVUdgjX3N/iU=
 | 
				
			||||||
github.com/google/gofuzz v1.0.0/go.mod h1:dBl0BpW6vV/+mYPU4Po3pmUjxk6FQPldtuIdl/M65Eg=
 | 
					github.com/google/gofuzz v1.0.0/go.mod h1:dBl0BpW6vV/+mYPU4Po3pmUjxk6FQPldtuIdl/M65Eg=
 | 
				
			||||||
github.com/google/uuid v1.1.1/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo=
 | 
					github.com/google/uuid v1.1.1/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo=
 | 
				
			||||||
github.com/google/uuid v1.6.0 h1:NIvaJDMOsjHA8n1jAhLSgzrAzy1Hgr+hNrb57e+94F0=
 | 
					github.com/google/uuid v1.6.0 h1:NIvaJDMOsjHA8n1jAhLSgzrAzy1Hgr+hNrb57e+94F0=
 | 
				
			||||||
github.com/google/uuid v1.6.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo=
 | 
					github.com/google/uuid v1.6.0/go.mod h1:TIyPZe4MgqvfeYDBFedMoGGpEw/LqOeaOT+nhxU+yHo=
 | 
				
			||||||
github.com/gorilla/mux v1.8.0 h1:i40aqfkR1h2SlN9hojwV5ZA91wcXFOvkdNIeFDP5koI=
 | 
					github.com/gorilla/mux v1.8.0 h1:i40aqfkR1h2SlN9hojwV5ZA91wcXFOvkdNIeFDP5koI=
 | 
				
			||||||
github.com/gorilla/mux v1.8.0/go.mod h1:DVbg23sWSpFRCP0SfiEN6jmj59UnW/n46BH5rLB71So=
 | 
					github.com/gorilla/mux v1.8.0/go.mod h1:DVbg23sWSpFRCP0SfiEN6jmj59UnW/n46BH5rLB71So=
 | 
				
			||||||
 | 
					github.com/gorilla/schema v1.4.1 h1:jUg5hUjCSDZpNGLuXQOgIWGdlgrIdYvgQ0wZtdK1M3E=
 | 
				
			||||||
 | 
					github.com/gorilla/schema v1.4.1/go.mod h1:Dg5SSm5PV60mhF2NFaTV1xuYYj8tV8NOPRo4FggUMnM=
 | 
				
			||||||
github.com/gorilla/securecookie v1.1.1 h1:miw7JPhV+b/lAHSXz4qd/nN9jRiAFV5FwjeKyCS8BvQ=
 | 
					github.com/gorilla/securecookie v1.1.1 h1:miw7JPhV+b/lAHSXz4qd/nN9jRiAFV5FwjeKyCS8BvQ=
 | 
				
			||||||
github.com/gorilla/securecookie v1.1.1/go.mod h1:ra0sb63/xPlUeL+yeDciTfxMRAA+MP+HVt/4epWDjd4=
 | 
					github.com/gorilla/securecookie v1.1.1/go.mod h1:ra0sb63/xPlUeL+yeDciTfxMRAA+MP+HVt/4epWDjd4=
 | 
				
			||||||
github.com/gorilla/sessions v1.2.1 h1:DHd3rPN5lE3Ts3D8rKkQ8x/0kqfeNmBAaiSi+o7FsgI=
 | 
					github.com/gorilla/sessions v1.2.1 h1:DHd3rPN5lE3Ts3D8rKkQ8x/0kqfeNmBAaiSi+o7FsgI=
 | 
				
			||||||
github.com/gorilla/sessions v1.2.1/go.mod h1:dk2InVEVJ0sfLlnXv9EAgkf6ecYs/i80K/zI+bUmuGM=
 | 
					github.com/gorilla/sessions v1.2.1/go.mod h1:dk2InVEVJ0sfLlnXv9EAgkf6ecYs/i80K/zI+bUmuGM=
 | 
				
			||||||
github.com/gotestyourself/gotestyourself v2.2.0+incompatible/go.mod h1:zZKM6oeNM8k+FRljX1mnzVYeS8wiGgQyvST1/GafPbY=
 | 
					github.com/gotestyourself/gotestyourself v2.2.0+incompatible/go.mod h1:zZKM6oeNM8k+FRljX1mnzVYeS8wiGgQyvST1/GafPbY=
 | 
				
			||||||
github.com/hashicorp/hcl v1.0.0 h1:0Anlzjpi4vEasTeNFn2mLJgTSwt0+6sfsiTG8qcWGx4=
 | 
					github.com/hashicorp/hcl/v2 v2.23.0 h1:Fphj1/gCylPxHutVSEOf2fBOh1VE4AuLV7+kbJf3qos=
 | 
				
			||||||
github.com/hashicorp/hcl v1.0.0/go.mod h1:E5yfLk+7swimpb2L/Alb/PJmXilQ/rhwaUYs4T20WEQ=
 | 
					github.com/hashicorp/hcl/v2 v2.23.0/go.mod h1:62ZYHrXgPoX8xBnzl8QzbWq4dyDsDtfCRgIq1rbJEvA=
 | 
				
			||||||
github.com/hashicorp/hcl/v2 v2.10.0 h1:1S1UnuhDGlv3gRFV4+0EdwB+znNP5HmcGbIqwnSCByg=
 | 
					 | 
				
			||||||
github.com/hashicorp/hcl/v2 v2.10.0/go.mod h1:FwWsfWEjyV/CMj8s/gqAuiviY72rJ1/oayI9WftqcKg=
 | 
					 | 
				
			||||||
github.com/hexops/gotextdiff v1.0.3 h1:gitA9+qJrrTCsiCl7+kh75nPqQt1cx4ZkudSTLoUqJM=
 | 
					github.com/hexops/gotextdiff v1.0.3 h1:gitA9+qJrrTCsiCl7+kh75nPqQt1cx4ZkudSTLoUqJM=
 | 
				
			||||||
github.com/hexops/gotextdiff v1.0.3/go.mod h1:pSWU5MAI3yDq+fZBTazCSJysOMbxWL1BSow5/V2vxeg=
 | 
					github.com/hexops/gotextdiff v1.0.3/go.mod h1:pSWU5MAI3yDq+fZBTazCSJysOMbxWL1BSow5/V2vxeg=
 | 
				
			||||||
github.com/huandu/xstrings v1.3.0/go.mod h1:y5/lhBue+AyNmUVz9RLU9xbLR0o4KIIExikq4ovT0aE=
 | 
					github.com/huandu/xstrings v1.3.0/go.mod h1:y5/lhBue+AyNmUVz9RLU9xbLR0o4KIIExikq4ovT0aE=
 | 
				
			||||||
github.com/imdario/mergo v0.3.9/go.mod h1:2EnlNZ0deacrJVfApfmtdGgDfMuh/nq6Ok1EcJh5FfA=
 | 
					github.com/imdario/mergo v0.3.9/go.mod h1:2EnlNZ0deacrJVfApfmtdGgDfMuh/nq6Ok1EcJh5FfA=
 | 
				
			||||||
github.com/json-iterator/go v1.1.12 h1:PV8peI4a0ysnczrg+LtxykD8LfKY9ML6u2jnxaEnrnM=
 | 
					github.com/json-iterator/go v1.1.12 h1:PV8peI4a0ysnczrg+LtxykD8LfKY9ML6u2jnxaEnrnM=
 | 
				
			||||||
github.com/json-iterator/go v1.1.12/go.mod h1:e30LSqwooZae/UwlEbR2852Gd8hjQvJoHmT4TnhNGBo=
 | 
					github.com/json-iterator/go v1.1.12/go.mod h1:e30LSqwooZae/UwlEbR2852Gd8hjQvJoHmT4TnhNGBo=
 | 
				
			||||||
 | 
					github.com/juju/gnuflag v0.0.0-20171113085948-2ce1bb71843d/go.mod h1:2PavIy+JPciBPrBUjwbNvtwB6RQlve+hkpll6QSNmOE=
 | 
				
			||||||
github.com/kisielk/errcheck v1.5.0/go.mod h1:pFxgyoBC7bSaBwPgfKdkLd5X25qrDl4LWUI2bnpBCr8=
 | 
					github.com/kisielk/errcheck v1.5.0/go.mod h1:pFxgyoBC7bSaBwPgfKdkLd5X25qrDl4LWUI2bnpBCr8=
 | 
				
			||||||
github.com/kisielk/gotool v1.0.0/go.mod h1:XhKaO+MFFWcvkIS/tQcRk01m1F5IRFswLeQ+oQHNcck=
 | 
					github.com/kisielk/gotool v1.0.0/go.mod h1:XhKaO+MFFWcvkIS/tQcRk01m1F5IRFswLeQ+oQHNcck=
 | 
				
			||||||
github.com/klauspost/compress v1.17.7 h1:ehO88t2UGzQK66LMdE8tibEd1ErmzZjNEqWkjLAKQQg=
 | 
					github.com/klauspost/compress v1.13.6/go.mod h1:/3/Vjq9QcHkK5uEr5lBEmyoZ1iFhe47etQ6QUkpK6sk=
 | 
				
			||||||
github.com/klauspost/compress v1.17.7/go.mod h1:Di0epgTjJY877eYKx5yC51cX2A2Vl2ibi7bDH9ttBbw=
 | 
					github.com/klauspost/compress v1.18.0 h1:c/Cqfb0r+Yi+JtIEq73FWXVkRonBlf0CRNYc8Zttxdo=
 | 
				
			||||||
 | 
					github.com/klauspost/compress v1.18.0/go.mod h1:2Pp+KzxcywXVXMr50+X0Q/Lsb43OQHYWRCY2AiWywWQ=
 | 
				
			||||||
github.com/klauspost/cpuid/v2 v2.0.1/go.mod h1:FInQzS24/EEf25PyTYn52gqo7WaD8xa0213Md/qVLRg=
 | 
					github.com/klauspost/cpuid/v2 v2.0.1/go.mod h1:FInQzS24/EEf25PyTYn52gqo7WaD8xa0213Md/qVLRg=
 | 
				
			||||||
github.com/klauspost/cpuid/v2 v2.0.4/go.mod h1:FInQzS24/EEf25PyTYn52gqo7WaD8xa0213Md/qVLRg=
 | 
					github.com/klauspost/cpuid/v2 v2.0.4/go.mod h1:FInQzS24/EEf25PyTYn52gqo7WaD8xa0213Md/qVLRg=
 | 
				
			||||||
github.com/klauspost/cpuid/v2 v2.1.0 h1:eyi1Ad2aNJMW95zcSbmGg7Cg6cq3ADwLpMAP96d8rF0=
 | 
					github.com/klauspost/cpuid/v2 v2.2.5 h1:0E5MSMDEoAulmXNFquVs//DdoomxaoTY1kUhbc/qbZg=
 | 
				
			||||||
github.com/klauspost/cpuid/v2 v2.1.0/go.mod h1:RVVoqg1df56z8g3pUjL/3lE5UfnlrJX8tyFgg4nqhuY=
 | 
					github.com/klauspost/cpuid/v2 v2.2.5/go.mod h1:Lcz8mBdAVJIBVzewtcLocK12l3Y+JytZYpaMropDUws=
 | 
				
			||||||
github.com/konsorten/go-windows-terminal-sequences v1.0.1/go.mod h1:T0+1ngSBFLxvqU3pZ+m/2kptfBszLMUkC4ZK/EgS/cQ=
 | 
					github.com/konsorten/go-windows-terminal-sequences v1.0.1/go.mod h1:T0+1ngSBFLxvqU3pZ+m/2kptfBszLMUkC4ZK/EgS/cQ=
 | 
				
			||||||
github.com/kr/pretty v0.1.0/go.mod h1:dAy3ld7l9f0ibDNOQOHHMYYIIbhfbHSm3C4ZsoJORNo=
 | 
					github.com/kr/pretty v0.1.0/go.mod h1:dAy3ld7l9f0ibDNOQOHHMYYIIbhfbHSm3C4ZsoJORNo=
 | 
				
			||||||
github.com/kr/pretty v0.2.1/go.mod h1:ipq/a2n7PKx3OHsz4KJII5eveXtPO4qwEXGdVfWzfnI=
 | 
					 | 
				
			||||||
github.com/kr/pretty v0.3.0/go.mod h1:640gp4NfQd8pI5XOwp5fnNeVWj67G7CFk/SaSQn7NBk=
 | 
					 | 
				
			||||||
github.com/kr/pretty v0.3.1 h1:flRD4NNwYAUpkphVc1HcthR4KEIFJ65n8Mw5qdRn3LE=
 | 
					github.com/kr/pretty v0.3.1 h1:flRD4NNwYAUpkphVc1HcthR4KEIFJ65n8Mw5qdRn3LE=
 | 
				
			||||||
github.com/kr/pretty v0.3.1/go.mod h1:hoEshYVHaxMs3cyo3Yncou5ZscifuDolrwPKZanG3xk=
 | 
					github.com/kr/pretty v0.3.1/go.mod h1:hoEshYVHaxMs3cyo3Yncou5ZscifuDolrwPKZanG3xk=
 | 
				
			||||||
github.com/kr/pty v1.1.1/go.mod h1:pFQYn66WHrOpPYNljwOMqo10TkYh1fy3cYio2l3bCsQ=
 | 
					github.com/kr/pty v1.1.1/go.mod h1:pFQYn66WHrOpPYNljwOMqo10TkYh1fy3cYio2l3bCsQ=
 | 
				
			||||||
github.com/kr/text v0.1.0/go.mod h1:4Jbv+DJW3UT/LiOwJeYQe1efqtUx/iVham/4vfdArNI=
 | 
					github.com/kr/text v0.1.0/go.mod h1:4Jbv+DJW3UT/LiOwJeYQe1efqtUx/iVham/4vfdArNI=
 | 
				
			||||||
github.com/kr/text v0.2.0 h1:5Nx0Ya0ZqY2ygV366QzturHI13Jq95ApcVaJBhpS+AY=
 | 
					github.com/kr/text v0.2.0 h1:5Nx0Ya0ZqY2ygV366QzturHI13Jq95ApcVaJBhpS+AY=
 | 
				
			||||||
github.com/kr/text v0.2.0/go.mod h1:eLer722TekiGuMkidMxC/pM04lWEeraHUUmBw8l2grE=
 | 
					github.com/kr/text v0.2.0/go.mod h1:eLer722TekiGuMkidMxC/pM04lWEeraHUUmBw8l2grE=
 | 
				
			||||||
github.com/kylelemons/godebug v0.0.0-20170820004349-d65d576e9348 h1:MtvEpTB6LX3vkb4ax0b5D2DHbNAUsen0Gx5wZoq3lV4=
 | 
					github.com/leodido/go-urn v1.2.4 h1:XlAE/cm/ms7TE/VMVoduSpNBoyc2dOxHs5MZSwAN63Q=
 | 
				
			||||||
github.com/kylelemons/godebug v0.0.0-20170820004349-d65d576e9348/go.mod h1:B69LEHPfb2qLo0BaaOLcbitczOKLWTsrBG9LczfCD4k=
 | 
					github.com/leodido/go-urn v1.2.4/go.mod h1:7ZrI8mTSeBSHl/UaRyKQW1qZeMgak41ANeCNaVckg+4=
 | 
				
			||||||
github.com/leodido/go-urn v1.2.1 h1:BqpAaACuzVSgi/VLzGZIobT2z4v53pjosyNd9Yv6n/w=
 | 
					 | 
				
			||||||
github.com/leodido/go-urn v1.2.1/go.mod h1:zt4jvISO2HfUBqxjfIshjdMTYS56ZS/qv49ictyFfxY=
 | 
					 | 
				
			||||||
github.com/lib/pq v1.3.0/go.mod h1:5WUZQaWbwv1U+lTReE5YruASi9Al49XbQIvNi/34Woo=
 | 
					github.com/lib/pq v1.3.0/go.mod h1:5WUZQaWbwv1U+lTReE5YruASi9Al49XbQIvNi/34Woo=
 | 
				
			||||||
github.com/lib/pq v1.10.9 h1:YXG7RB+JIjhP29X+OtkiDnYaXQwpS4JEWq7dtCCRUEw=
 | 
					github.com/lib/pq v1.10.9 h1:YXG7RB+JIjhP29X+OtkiDnYaXQwpS4JEWq7dtCCRUEw=
 | 
				
			||||||
github.com/lib/pq v1.10.9/go.mod h1:AlVN5x4E4T544tWzH6hKfbfQvm3HdbOxrmggDNAPY9o=
 | 
					github.com/lib/pq v1.10.9/go.mod h1:AlVN5x4E4T544tWzH6hKfbfQvm3HdbOxrmggDNAPY9o=
 | 
				
			||||||
github.com/magiconair/properties v1.8.7 h1:IeQXZAiQcpL9mgcAe1Nu6cX9LLw6ExEHKjN0VQdvPDY=
 | 
					github.com/manterfield/go-mapreader v0.2.0 h1:ZDJbja6bZCatRG725SDchdudqYnULyk04wSH58gvyqM=
 | 
				
			||||||
github.com/magiconair/properties v1.8.7/go.mod h1:Dhd985XPs7jluiymwWYZ0G4Z61jb3vdS329zhj2hYo0=
 | 
					github.com/manterfield/go-mapreader v0.2.0/go.mod h1:dYr8DHvSqfhrwTHBO1h8dLa9nUUnushqBYuWBns1Z0s=
 | 
				
			||||||
github.com/mattn/go-colorable v0.1.4/go.mod h1:U0ppj6V5qS13XJ6of8GYAs25YV2eR4EVcfRqFIhoBtE=
 | 
					github.com/mattn/go-colorable v0.1.4/go.mod h1:U0ppj6V5qS13XJ6of8GYAs25YV2eR4EVcfRqFIhoBtE=
 | 
				
			||||||
github.com/mattn/go-colorable v0.1.13 h1:fFA4WZxdEF4tXPZVKMLwD8oUnCTTo08duU7wxecdEvA=
 | 
					 | 
				
			||||||
github.com/mattn/go-colorable v0.1.13/go.mod h1:7S9/ev0klgBDR4GtXTXX8a3vIGJpMovkB8vQcUbaXHg=
 | 
					github.com/mattn/go-colorable v0.1.13/go.mod h1:7S9/ev0klgBDR4GtXTXX8a3vIGJpMovkB8vQcUbaXHg=
 | 
				
			||||||
 | 
					github.com/mattn/go-colorable v0.1.14 h1:9A9LHSqF/7dyVVX6g0U9cwm9pG3kP9gSzcuIPHPsaIE=
 | 
				
			||||||
 | 
					github.com/mattn/go-colorable v0.1.14/go.mod h1:6LmQG8QLFO4G5z1gPvYEzlUgJ2wF+stgPZH1UqBm1s8=
 | 
				
			||||||
github.com/mattn/go-isatty v0.0.8/go.mod h1:Iq45c/XA43vh69/j3iqttzPXn0bhXyGjM0Hdxcsrc5s=
 | 
					github.com/mattn/go-isatty v0.0.8/go.mod h1:Iq45c/XA43vh69/j3iqttzPXn0bhXyGjM0Hdxcsrc5s=
 | 
				
			||||||
github.com/mattn/go-isatty v0.0.11/go.mod h1:PhnuNfih5lzO57/f3n+odYbM4JtupLOxQOAqxQCu2WE=
 | 
					github.com/mattn/go-isatty v0.0.11/go.mod h1:PhnuNfih5lzO57/f3n+odYbM4JtupLOxQOAqxQCu2WE=
 | 
				
			||||||
github.com/mattn/go-isatty v0.0.16/go.mod h1:kYGgaQfpe5nmfYZH+SKPsOc2e4SrIfOl2e/yFXSvRLM=
 | 
					github.com/mattn/go-isatty v0.0.16/go.mod h1:kYGgaQfpe5nmfYZH+SKPsOc2e4SrIfOl2e/yFXSvRLM=
 | 
				
			||||||
| 
						 | 
					@ -158,10 +241,8 @@ github.com/minio/minio-go/v7 v7.0.43/go.mod h1:nCrRzjoSUQh8hgKKtu3Y708OLvRLtuASM
 | 
				
			||||||
github.com/minio/sha256-simd v1.0.0 h1:v1ta+49hkWZyvaKwrQB8elexRqm6Y0aMLjCNsrYxo6g=
 | 
					github.com/minio/sha256-simd v1.0.0 h1:v1ta+49hkWZyvaKwrQB8elexRqm6Y0aMLjCNsrYxo6g=
 | 
				
			||||||
github.com/minio/sha256-simd v1.0.0/go.mod h1:OuYzVNI5vcoYIAmbIvHPl3N3jUzVedXbKy5RFepssQM=
 | 
					github.com/minio/sha256-simd v1.0.0/go.mod h1:OuYzVNI5vcoYIAmbIvHPl3N3jUzVedXbKy5RFepssQM=
 | 
				
			||||||
github.com/mitchellh/copystructure v1.0.0/go.mod h1:SNtv71yrdKgLRyLFxmLdkAbkKEFWgYaq1OVrnRcwhnw=
 | 
					github.com/mitchellh/copystructure v1.0.0/go.mod h1:SNtv71yrdKgLRyLFxmLdkAbkKEFWgYaq1OVrnRcwhnw=
 | 
				
			||||||
github.com/mitchellh/go-wordwrap v0.0.0-20150314170334-ad45545899c7 h1:DpOJ2HYzCv8LZP15IdmG+YdwD2luVPHITV96TkirNBM=
 | 
					github.com/mitchellh/go-wordwrap v1.0.1 h1:TLuKupo69TCn6TQSyGxwI1EblZZEsQ0vMlAFQflz0v0=
 | 
				
			||||||
github.com/mitchellh/go-wordwrap v0.0.0-20150314170334-ad45545899c7/go.mod h1:ZXFpozHsX6DPmq2I0TCekCxypsnAUbP2oI0UX1GXzOo=
 | 
					github.com/mitchellh/go-wordwrap v1.0.1/go.mod h1:R62XHJLzvMFRBbcrT7m7WgmE1eOyTSsCt+hzestvNj0=
 | 
				
			||||||
github.com/mitchellh/mapstructure v1.5.0 h1:jeMsZIYE/09sWLaz43PL7Gy6RuMjD2eJVyuac5Z2hdY=
 | 
					 | 
				
			||||||
github.com/mitchellh/mapstructure v1.5.0/go.mod h1:bFUtVrKA4DC2yAKiSyO/QUcy7e+RRV2QTWOzhPopBRo=
 | 
					 | 
				
			||||||
github.com/mitchellh/reflectwalk v1.0.0/go.mod h1:mSTlrgnPZtwu0c4WaC2kGObEpuNDbx0jmZXqmk4esnw=
 | 
					github.com/mitchellh/reflectwalk v1.0.0/go.mod h1:mSTlrgnPZtwu0c4WaC2kGObEpuNDbx0jmZXqmk4esnw=
 | 
				
			||||||
github.com/modern-go/concurrent v0.0.0-20180228061459-e0a39a4cb421/go.mod h1:6dJC0mAP4ikYIbvyc7fijjWJddQyLn8Ig3JB5CqoB9Q=
 | 
					github.com/modern-go/concurrent v0.0.0-20180228061459-e0a39a4cb421/go.mod h1:6dJC0mAP4ikYIbvyc7fijjWJddQyLn8Ig3JB5CqoB9Q=
 | 
				
			||||||
github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd h1:TRLaZ9cD/w8PVh93nsPXa1VrQ6jlwL5oN8l14QlcNfg=
 | 
					github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd h1:TRLaZ9cD/w8PVh93nsPXa1VrQ6jlwL5oN8l14QlcNfg=
 | 
				
			||||||
| 
						 | 
					@ -170,18 +251,26 @@ github.com/modern-go/reflect2 v1.0.2 h1:xBagoLtFs94CBntxluKeaWgTMpvLxC4ur3nMaC9G
 | 
				
			||||||
github.com/modern-go/reflect2 v1.0.2/go.mod h1:yWuevngMOJpCy52FWWMvUC8ws7m/LJsjYzDa0/r8luk=
 | 
					github.com/modern-go/reflect2 v1.0.2/go.mod h1:yWuevngMOJpCy52FWWMvUC8ws7m/LJsjYzDa0/r8luk=
 | 
				
			||||||
github.com/mohae/deepcopy v0.0.0-20170929034955-c48cc78d4826 h1:RWengNIwukTxcDr9M+97sNutRR1RKhG96O6jWumTTnw=
 | 
					github.com/mohae/deepcopy v0.0.0-20170929034955-c48cc78d4826 h1:RWengNIwukTxcDr9M+97sNutRR1RKhG96O6jWumTTnw=
 | 
				
			||||||
github.com/mohae/deepcopy v0.0.0-20170929034955-c48cc78d4826/go.mod h1:TaXosZuwdSHYgviHp1DAtfrULt5eUgsSMsZf+YrPgl8=
 | 
					github.com/mohae/deepcopy v0.0.0-20170929034955-c48cc78d4826/go.mod h1:TaXosZuwdSHYgviHp1DAtfrULt5eUgsSMsZf+YrPgl8=
 | 
				
			||||||
 | 
					github.com/montanaflynn/stats v0.0.0-20171201202039-1bf9dbcd8cbe/go.mod h1:wL8QJuTMNUDYhXwkmfOly8iTdp5TEcJFWZD2D7SIkUc=
 | 
				
			||||||
github.com/montanaflynn/stats v0.7.1 h1:etflOAAHORrCC44V+aR6Ftzort912ZU+YLiSTuV8eaE=
 | 
					github.com/montanaflynn/stats v0.7.1 h1:etflOAAHORrCC44V+aR6Ftzort912ZU+YLiSTuV8eaE=
 | 
				
			||||||
github.com/montanaflynn/stats v0.7.1/go.mod h1:etXPPgVO6n31NxCd9KQUMvCM+ve0ruNzt6R8Bnaayow=
 | 
					github.com/montanaflynn/stats v0.7.1/go.mod h1:etXPPgVO6n31NxCd9KQUMvCM+ve0ruNzt6R8Bnaayow=
 | 
				
			||||||
 | 
					github.com/mschoch/smat v0.2.0 h1:8imxQsjDm8yFEAVBe7azKmKSgzSkZXDuKkSq9374khM=
 | 
				
			||||||
 | 
					github.com/mschoch/smat v0.2.0/go.mod h1:kc9mz7DoBKqDyiRL7VZN8KvXQMWeTaVnttLRXOlotKw=
 | 
				
			||||||
 | 
					github.com/niemeyer/pretty v0.0.0-20200227124842-a10e7caefd8e h1:fD57ERR4JtEqsWbfPhv4DMiApHyliiK5xCTNVSPiaAs=
 | 
				
			||||||
github.com/niemeyer/pretty v0.0.0-20200227124842-a10e7caefd8e/go.mod h1:zD1mROLANZcx1PVRCS0qkT7pwLkGfwJo4zjcN/Tysno=
 | 
					github.com/niemeyer/pretty v0.0.0-20200227124842-a10e7caefd8e/go.mod h1:zD1mROLANZcx1PVRCS0qkT7pwLkGfwJo4zjcN/Tysno=
 | 
				
			||||||
 | 
					github.com/oapi-codegen/runtime v1.1.1 h1:EXLHh0DXIJnWhdRPN2w4MXAzFyE4CskzhNLUmtpMYro=
 | 
				
			||||||
 | 
					github.com/oapi-codegen/runtime v1.1.1/go.mod h1:SK9X900oXmPWilYR5/WKPzt3Kqxn/uS/+lbpREv+eCg=
 | 
				
			||||||
github.com/opencontainers/go-digest v1.0.0-rc1/go.mod h1:cMLVZDEM3+U2I4VmLI6N8jQYUd2OVphdqWwCJHrFt2s=
 | 
					github.com/opencontainers/go-digest v1.0.0-rc1/go.mod h1:cMLVZDEM3+U2I4VmLI6N8jQYUd2OVphdqWwCJHrFt2s=
 | 
				
			||||||
github.com/opencontainers/image-spec v1.0.1/go.mod h1:BtxoFyWECRxE4U/7sNtV5W15zMzWCbyJoFRP3s7yZA0=
 | 
					github.com/opencontainers/image-spec v1.0.1/go.mod h1:BtxoFyWECRxE4U/7sNtV5W15zMzWCbyJoFRP3s7yZA0=
 | 
				
			||||||
github.com/opencontainers/runc v0.1.1/go.mod h1:qT5XzbpPznkRYVz/mWwUaVBUv2rmF59PVA73FjuZG0U=
 | 
					github.com/opencontainers/runc v0.1.1/go.mod h1:qT5XzbpPznkRYVz/mWwUaVBUv2rmF59PVA73FjuZG0U=
 | 
				
			||||||
github.com/ory/dockertest v3.3.4+incompatible/go.mod h1:1vX4m9wsvi00u5bseYwXaSnhNrne+V0E6LAcBILJdPs=
 | 
					github.com/ory/dockertest v3.3.4+incompatible/go.mod h1:1vX4m9wsvi00u5bseYwXaSnhNrne+V0E6LAcBILJdPs=
 | 
				
			||||||
github.com/paulmach/go.geojson v1.4.0 h1:5x5moCkCtDo5x8af62P9IOAYGQcYHtxz2QJ3x1DoCgY=
 | 
					github.com/paulmach/go.geojson v1.4.0 h1:5x5moCkCtDo5x8af62P9IOAYGQcYHtxz2QJ3x1DoCgY=
 | 
				
			||||||
github.com/paulmach/go.geojson v1.4.0/go.mod h1:YaKx1hKpWF+T2oj2lFJPsW/t1Q5e1jQI61eoQSTwpIs=
 | 
					github.com/paulmach/go.geojson v1.4.0/go.mod h1:YaKx1hKpWF+T2oj2lFJPsW/t1Q5e1jQI61eoQSTwpIs=
 | 
				
			||||||
github.com/pelletier/go-toml/v2 v2.2.3 h1:YmeHyLY8mFWbdkNWwpr+qIL2bEqT0o95WSdkNHvL12M=
 | 
					github.com/paulmach/orb v0.11.1 h1:3koVegMC4X/WeiXYz9iswopaTwMem53NzTJuTF20JzU=
 | 
				
			||||||
github.com/pelletier/go-toml/v2 v2.2.3/go.mod h1:MfCQTFTvCcUyyvvwm1+G6H/jORL20Xlb6rzQu9GuUkc=
 | 
					github.com/paulmach/orb v0.11.1/go.mod h1:5mULz1xQfs3bmQm63QEJA6lNGujuRafwA5S/EnuLaLU=
 | 
				
			||||||
github.com/pkg/diff v0.0.0-20210226163009-20ebb0f2a09e/go.mod h1:pJLUxLENpZxwdsKMEsNbx1VGcRFpLqf3715MtcvvzbA=
 | 
					github.com/paulmach/protoscan v0.2.1/go.mod h1:SpcSwydNLrxUGSDvXvO0P7g7AuhJ7lcKfDlhJCDw2gY=
 | 
				
			||||||
 | 
					github.com/pelletier/go-toml/v2 v2.2.4 h1:mye9XuhQ6gvn5h28+VilKrrPoQVanw5PMw/TB0t5Ec4=
 | 
				
			||||||
 | 
					github.com/pelletier/go-toml/v2 v2.2.4/go.mod h1:2gIqNv+qfxSVS7cM2xJQKtLSTLUE9V8t9Stt+h56mCY=
 | 
				
			||||||
github.com/pkg/errors v0.8.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0=
 | 
					github.com/pkg/errors v0.8.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0=
 | 
				
			||||||
github.com/pkg/errors v0.9.1 h1:FEBLx1zS214owpjy7qsBeixbURkuhQAwrK5UwLGTwt4=
 | 
					github.com/pkg/errors v0.9.1 h1:FEBLx1zS214owpjy7qsBeixbURkuhQAwrK5UwLGTwt4=
 | 
				
			||||||
github.com/pkg/errors v0.9.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0=
 | 
					github.com/pkg/errors v0.9.1/go.mod h1:bwawxfHBFNV+L2hUp1rHADufV3IMtnDRdf1r5NINEl0=
 | 
				
			||||||
| 
						 | 
					@ -193,66 +282,69 @@ github.com/richardlehane/mscfb v1.0.4/go.mod h1:YzVpcZg9czvAuhk9T+a3avCpcFPMUWm7
 | 
				
			||||||
github.com/richardlehane/msoleps v1.0.1/go.mod h1:BWev5JBpU9Ko2WAgmZEuiz4/u3ZYTKbjLycmwiWUfWg=
 | 
					github.com/richardlehane/msoleps v1.0.1/go.mod h1:BWev5JBpU9Ko2WAgmZEuiz4/u3ZYTKbjLycmwiWUfWg=
 | 
				
			||||||
github.com/richardlehane/msoleps v1.0.3 h1:aznSZzrwYRl3rLKRT3gUk9am7T/mLNSnJINvN0AQoVM=
 | 
					github.com/richardlehane/msoleps v1.0.3 h1:aznSZzrwYRl3rLKRT3gUk9am7T/mLNSnJINvN0AQoVM=
 | 
				
			||||||
github.com/richardlehane/msoleps v1.0.3/go.mod h1:BWev5JBpU9Ko2WAgmZEuiz4/u3ZYTKbjLycmwiWUfWg=
 | 
					github.com/richardlehane/msoleps v1.0.3/go.mod h1:BWev5JBpU9Ko2WAgmZEuiz4/u3ZYTKbjLycmwiWUfWg=
 | 
				
			||||||
github.com/rogpeppe/go-internal v1.6.1/go.mod h1:xXDCJY+GAPziupqXw64V24skbSoqbTEfhy4qGm1nDQc=
 | 
					 | 
				
			||||||
github.com/rogpeppe/go-internal v1.8.0/go.mod h1:WmiCO8CzOY8rg0OYDC4/i/2WRWAB6poM+XZ2dLUbcbE=
 | 
					 | 
				
			||||||
github.com/rogpeppe/go-internal v1.9.0 h1:73kH8U+JUqXU8lRuOHeVHaa/SZPifC7BkcraZVejAe8=
 | 
					github.com/rogpeppe/go-internal v1.9.0 h1:73kH8U+JUqXU8lRuOHeVHaa/SZPifC7BkcraZVejAe8=
 | 
				
			||||||
github.com/rogpeppe/go-internal v1.9.0/go.mod h1:WtVeX8xhTBvf0smdhujwtBcq4Qrzq/fJaraNFVN+nFs=
 | 
					github.com/rogpeppe/go-internal v1.9.0/go.mod h1:WtVeX8xhTBvf0smdhujwtBcq4Qrzq/fJaraNFVN+nFs=
 | 
				
			||||||
github.com/rs/xid v1.5.0 h1:mKX4bl4iPYJtEIxp6CYiUuLQ/8DYMoz0PUdtGgMFRVc=
 | 
					github.com/rs/xid v1.6.0 h1:fV591PaemRlL6JfRxGDEPl69wICngIQ3shQtzfy2gxU=
 | 
				
			||||||
github.com/rs/xid v1.5.0/go.mod h1:trrq9SKmegXys3aeAKXMUTdJsYXVwGY3RLcfgqegfbg=
 | 
					github.com/rs/xid v1.6.0/go.mod h1:7XoLgs4eV+QndskICGsho+ADou8ySMSjJKDIan90Nz0=
 | 
				
			||||||
github.com/rs/zerolog v1.33.0 h1:1cU2KZkvPxNyfgEmhHAz/1A9Bz+llsdYzklWFzgp0r8=
 | 
					github.com/rs/zerolog v1.34.0 h1:k43nTLIwcTVQAncfCw4KZ2VY6ukYoZaBPNOE8txlOeY=
 | 
				
			||||||
github.com/rs/zerolog v1.33.0/go.mod h1:/7mN4D5sKwJLZQ2b/znpjC3/GQWY/xaDXUM0kKWRHss=
 | 
					github.com/rs/zerolog v1.34.0/go.mod h1:bJsvje4Z08ROH4Nhs5iH600c3IkWhwp44iRc54W6wYQ=
 | 
				
			||||||
github.com/sagikazarmark/locafero v0.6.0 h1:ON7AQg37yzcRPU69mt7gwhFEBwxI6P9T4Qu3N51bwOk=
 | 
					github.com/sagikazarmark/locafero v0.9.0 h1:GbgQGNtTrEmddYDSAH9QLRyfAHY12md+8YFTqyMTC9k=
 | 
				
			||||||
github.com/sagikazarmark/locafero v0.6.0/go.mod h1:77OmuIc6VTraTXKXIs/uvUxKGUXjE1GbemJYHqdNjX0=
 | 
					github.com/sagikazarmark/locafero v0.9.0/go.mod h1:UBUyz37V+EdMS3hDF3QWIiVr/2dPrx49OMO0Bn0hJqk=
 | 
				
			||||||
github.com/sagikazarmark/slog-shim v0.1.0 h1:diDBnUNK9N/354PgrxMywXnAwEr1QZcOr6gto+ugjYE=
 | 
					 | 
				
			||||||
github.com/sagikazarmark/slog-shim v0.1.0/go.mod h1:SrcSrq8aKtyuqEI1uvTDTK1arOWRIczQRv+GVI1AkeQ=
 | 
					 | 
				
			||||||
github.com/santhosh-tekuri/jsonschema/v5 v5.0.0 h1:TToq11gyfNlrMFZiYujSekIsPd9AmsA2Bj/iv+s4JHE=
 | 
					github.com/santhosh-tekuri/jsonschema/v5 v5.0.0 h1:TToq11gyfNlrMFZiYujSekIsPd9AmsA2Bj/iv+s4JHE=
 | 
				
			||||||
github.com/santhosh-tekuri/jsonschema/v5 v5.0.0/go.mod h1:FKdcjfQW6rpZSnxxUvEA5H/cDPdvJ/SZJQLWWXWGrZ0=
 | 
					github.com/santhosh-tekuri/jsonschema/v5 v5.0.0/go.mod h1:FKdcjfQW6rpZSnxxUvEA5H/cDPdvJ/SZJQLWWXWGrZ0=
 | 
				
			||||||
github.com/sergi/go-diff v1.0.0/go.mod h1:0CfEIISq7TuYL3j771MWULgwwjU+GofnZX9QAmXWZgo=
 | 
					 | 
				
			||||||
github.com/sergi/go-diff v1.1.0 h1:we8PVUC3FE2uYfodKH/nBHMSetSfHDR6scGdBi+erh0=
 | 
					 | 
				
			||||||
github.com/sergi/go-diff v1.1.0/go.mod h1:STckp+ISIX8hZLjrqAeVduY0gWCT9IjLuqbuNXdaHfM=
 | 
					 | 
				
			||||||
github.com/sirupsen/logrus v1.4.1/go.mod h1:ni0Sbl8bgC9z8RoU9G6nDWqqs/fq4eDPysMBDgk/93Q=
 | 
					github.com/sirupsen/logrus v1.4.1/go.mod h1:ni0Sbl8bgC9z8RoU9G6nDWqqs/fq4eDPysMBDgk/93Q=
 | 
				
			||||||
github.com/sirupsen/logrus v1.9.3 h1:dueUQJ1C2q9oE3F7wvmSGAaVtTmUizReu6fjN8uqzbQ=
 | 
					github.com/sirupsen/logrus v1.9.3 h1:dueUQJ1C2q9oE3F7wvmSGAaVtTmUizReu6fjN8uqzbQ=
 | 
				
			||||||
github.com/sirupsen/logrus v1.9.3/go.mod h1:naHLuLoDiP4jHNo9R0sCBMtWGeIprob74mVsIT4qYEQ=
 | 
					github.com/sirupsen/logrus v1.9.3/go.mod h1:naHLuLoDiP4jHNo9R0sCBMtWGeIprob74mVsIT4qYEQ=
 | 
				
			||||||
github.com/sourcegraph/conc v0.3.0 h1:OQTbbt6P72L20UqAkXXuLOj79LfEanQ+YQFNpLA9ySo=
 | 
					github.com/sourcegraph/conc v0.3.0 h1:OQTbbt6P72L20UqAkXXuLOj79LfEanQ+YQFNpLA9ySo=
 | 
				
			||||||
github.com/sourcegraph/conc v0.3.0/go.mod h1:Sdozi7LEKbFPqYX2/J+iBAM6HpqSLTASQIKqDmF7Mt0=
 | 
					github.com/sourcegraph/conc v0.3.0/go.mod h1:Sdozi7LEKbFPqYX2/J+iBAM6HpqSLTASQIKqDmF7Mt0=
 | 
				
			||||||
github.com/spf13/afero v1.11.0 h1:WJQKhtpdm3v2IzqG8VMqrr6Rf3UYpEF239Jy9wNepM8=
 | 
					github.com/spf13/afero v1.14.0 h1:9tH6MapGnn/j0eb0yIXiLjERO8RB6xIVZRDCX7PtqWA=
 | 
				
			||||||
github.com/spf13/afero v1.11.0/go.mod h1:GH9Y3pIexgf1MTIWtNGyogA5MwRIDXGUr+hbWNoBjkY=
 | 
					github.com/spf13/afero v1.14.0/go.mod h1:acJQ8t0ohCGuMN3O+Pv0V0hgMxNYDlvdk+VTfyZmbYo=
 | 
				
			||||||
github.com/spf13/cast v1.7.0 h1:ntdiHjuueXFgm5nzDRdOS4yfT43P5Fnud6DH50rz/7w=
 | 
					github.com/spf13/cast v1.7.1 h1:cuNEagBQEHWN1FnbGEjCXL2szYEXqfJPbP2HNUaca9Y=
 | 
				
			||||||
github.com/spf13/cast v1.7.0/go.mod h1:ancEpBxwJDODSW/UG4rDrAqiKolqNNh2DX3mk86cAdo=
 | 
					github.com/spf13/cast v1.7.1/go.mod h1:ancEpBxwJDODSW/UG4rDrAqiKolqNNh2DX3mk86cAdo=
 | 
				
			||||||
github.com/spf13/pflag v1.0.2/go.mod h1:DYY7MBk1bdzusC3SYhjObp+wFpr4gzcvqqNjLnInEg4=
 | 
					github.com/spf13/pflag v1.0.6 h1:jFzHGLGAlb3ruxLB8MhbI6A8+AQX/2eW4qeyNZXNp2o=
 | 
				
			||||||
github.com/spf13/pflag v1.0.5 h1:iy+VFUOCP1a+8yFto/drg2CJ5u0yRoB7fZw3DKv/JXA=
 | 
					github.com/spf13/pflag v1.0.6/go.mod h1:McXfInJRrz4CZXVZOBLb0bTZqETkiAhM9Iw0y3An2Bg=
 | 
				
			||||||
github.com/spf13/pflag v1.0.5/go.mod h1:McXfInJRrz4CZXVZOBLb0bTZqETkiAhM9Iw0y3An2Bg=
 | 
					github.com/spf13/viper v1.20.1 h1:ZMi+z/lvLyPSCoNtFCpqjy0S4kPbirhpTMwl8BkW9X4=
 | 
				
			||||||
github.com/spf13/viper v1.19.0 h1:RWq5SEjt8o25SROyN3z2OrDB9l7RPd3lwTWU8EcEdcI=
 | 
					github.com/spf13/viper v1.20.1/go.mod h1:P9Mdzt1zoHIG8m2eZQinpiBjo6kCmZSKBClNNqjJvu4=
 | 
				
			||||||
github.com/spf13/viper v1.19.0/go.mod h1:GQUN9bilAbhU/jgc1bKs99f/suXKeUMct8Adx5+Ntkg=
 | 
					github.com/spkg/bom v0.0.0-20160624110644-59b7046e48ad/go.mod h1:qLr4V1qq6nMqFKkMo8ZTx3f+BZEkzsRUY10Xsm2mwU0=
 | 
				
			||||||
github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME=
 | 
					github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME=
 | 
				
			||||||
github.com/stretchr/objx v0.1.1/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME=
 | 
					github.com/stretchr/objx v0.1.1/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+wExME=
 | 
				
			||||||
 | 
					github.com/stretchr/objx v0.3.0/go.mod h1:qt09Ya8vawLte6SNmTgCsAVtYtaKzEcn8ATUoHMkEqE=
 | 
				
			||||||
github.com/stretchr/objx v0.4.0/go.mod h1:YvHI0jy2hoMjB+UWwv71VJQ9isScKT/TqJzVSSt89Yw=
 | 
					github.com/stretchr/objx v0.4.0/go.mod h1:YvHI0jy2hoMjB+UWwv71VJQ9isScKT/TqJzVSSt89Yw=
 | 
				
			||||||
 | 
					github.com/stretchr/objx v0.5.0/go.mod h1:Yh+to48EsGEfYuaHDzXPcE3xhTkx73EhmCGUpEOglKo=
 | 
				
			||||||
 | 
					github.com/stretchr/objx v0.5.2 h1:xuMeJ0Sdp5ZMRXx/aWO6RZxdr3beISkG5/G/aIRr3pY=
 | 
				
			||||||
 | 
					github.com/stretchr/objx v0.5.2/go.mod h1:FRsXN1f5AsAjCGJKqEizvkpNtU+EGNCLh3NxZ/8L+MA=
 | 
				
			||||||
github.com/stretchr/testify v1.2.2/go.mod h1:a8OnRcib4nhh0OaRAV+Yts87kKdq0PP7pXfy6kDkUVs=
 | 
					github.com/stretchr/testify v1.2.2/go.mod h1:a8OnRcib4nhh0OaRAV+Yts87kKdq0PP7pXfy6kDkUVs=
 | 
				
			||||||
github.com/stretchr/testify v1.3.0/go.mod h1:M5WIy9Dh21IEIfnGCwXGc5bZfKNJtfHm1UVUgZn+9EI=
 | 
					github.com/stretchr/testify v1.3.0/go.mod h1:M5WIy9Dh21IEIfnGCwXGc5bZfKNJtfHm1UVUgZn+9EI=
 | 
				
			||||||
github.com/stretchr/testify v1.4.0/go.mod h1:j7eGeouHqKxXV5pUuKE4zz7dFj8WfuZ+81PSLYec5m4=
 | 
					 | 
				
			||||||
github.com/stretchr/testify v1.5.1/go.mod h1:5W2xD1RspED5o8YsWQXVCued0rvSQ+mT+I5cxcmMvtA=
 | 
					github.com/stretchr/testify v1.5.1/go.mod h1:5W2xD1RspED5o8YsWQXVCued0rvSQ+mT+I5cxcmMvtA=
 | 
				
			||||||
github.com/stretchr/testify v1.6.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg=
 | 
					github.com/stretchr/testify v1.6.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg=
 | 
				
			||||||
github.com/stretchr/testify v1.7.0/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg=
 | 
					github.com/stretchr/testify v1.7.0/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg=
 | 
				
			||||||
github.com/stretchr/testify v1.7.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg=
 | 
					github.com/stretchr/testify v1.7.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg=
 | 
				
			||||||
github.com/stretchr/testify v1.8.0/go.mod h1:yNjHg4UonilssWZ8iaSj1OCr/vHnekPRkoO+kdMU+MU=
 | 
					github.com/stretchr/testify v1.8.0/go.mod h1:yNjHg4UonilssWZ8iaSj1OCr/vHnekPRkoO+kdMU+MU=
 | 
				
			||||||
github.com/stretchr/testify v1.9.0 h1:HtqpIVDClZ4nwg75+f6Lvsy/wHu+3BoSGCbBAcpTsTg=
 | 
					github.com/stretchr/testify v1.8.2/go.mod h1:w2LPCIKwWwSfY2zedu0+kehJoqGctiVI29o6fzry7u4=
 | 
				
			||||||
github.com/stretchr/testify v1.9.0/go.mod h1:r2ic/lqez/lEtzL7wO/rwa5dbSLXVDPFyf8C91i36aY=
 | 
					github.com/stretchr/testify v1.10.0 h1:Xv5erBjTwe/5IxqUQTdXv5kgmIvbHo3QQyRwhJsOfJA=
 | 
				
			||||||
 | 
					github.com/stretchr/testify v1.10.0/go.mod h1:r2ic/lqez/lEtzL7wO/rwa5dbSLXVDPFyf8C91i36aY=
 | 
				
			||||||
github.com/subosito/gotenv v1.6.0 h1:9NlTDc1FTs4qu0DDq7AEtTPNw6SVm7uBMsUCUjABIf8=
 | 
					github.com/subosito/gotenv v1.6.0 h1:9NlTDc1FTs4qu0DDq7AEtTPNw6SVm7uBMsUCUjABIf8=
 | 
				
			||||||
github.com/subosito/gotenv v1.6.0/go.mod h1:Dk4QP5c2W3ibzajGcXpNraDfq2IrhjMIvMSWPKKo0FU=
 | 
					github.com/subosito/gotenv v1.6.0/go.mod h1:Dk4QP5c2W3ibzajGcXpNraDfq2IrhjMIvMSWPKKo0FU=
 | 
				
			||||||
 | 
					github.com/tidwall/cities v0.1.0/go.mod h1:lV/HDp2gCcRcHJWqgt6Di54GiDrTZwh1aG2ZUPNbqa4=
 | 
				
			||||||
 | 
					github.com/tidwall/geoindex v1.7.0 h1:jtk41sfgwIt8MEDyC3xyKSj75iXXf6rjReJGDNPtR5o=
 | 
				
			||||||
 | 
					github.com/tidwall/geoindex v1.7.0/go.mod h1:rvVVNEFfkJVWGUdEfU8QaoOg/9zFX0h9ofWzA60mz1I=
 | 
				
			||||||
 | 
					github.com/tidwall/lotsa v1.0.2/go.mod h1:X6NiU+4yHA3fE3Puvpnn1XMDrFZrE9JO2/w+UMuqgR8=
 | 
				
			||||||
 | 
					github.com/tidwall/pretty v1.0.0/go.mod h1:XNkn88O1ChpSDQmQeStsy+sBenx6DDtFZJxhVysOjyk=
 | 
				
			||||||
 | 
					github.com/tidwall/rtree v1.10.0 h1:+EcI8fboEaW1L3/9oW/6AMoQ8HiEIHyR7bQOGnmz4Mg=
 | 
				
			||||||
 | 
					github.com/tidwall/rtree v1.10.0/go.mod h1:iDJQ9NBRtbfKkzZu02za+mIlaP+bjYPnunbSNidpbCQ=
 | 
				
			||||||
github.com/twpayne/go-geom v1.2.1/go.mod h1:90yvs0wf/gyT5eQ9W4v5WOZ9w/Xnrj5RMlA9XNKqxyA=
 | 
					github.com/twpayne/go-geom v1.2.1/go.mod h1:90yvs0wf/gyT5eQ9W4v5WOZ9w/Xnrj5RMlA9XNKqxyA=
 | 
				
			||||||
github.com/twpayne/go-geom v1.5.7 h1:7fdceDUr03/MP7rAKOaTV6x9njMiQdxB/D0PDzMTCDc=
 | 
					github.com/twpayne/go-geom v1.5.7 h1:7fdceDUr03/MP7rAKOaTV6x9njMiQdxB/D0PDzMTCDc=
 | 
				
			||||||
github.com/twpayne/go-geom v1.5.7/go.mod h1:y4fTAQtLedXW8eG2Yo4tYrIGN1yIwwKkmA+K3iSHKBA=
 | 
					github.com/twpayne/go-geom v1.5.7/go.mod h1:y4fTAQtLedXW8eG2Yo4tYrIGN1yIwwKkmA+K3iSHKBA=
 | 
				
			||||||
github.com/twpayne/go-kml v1.5.0/go.mod h1:g/OG8Q8JUxqFw8LGXE44W7osn1uXDAYaVFr1Yld43yc=
 | 
					github.com/twpayne/go-kml v1.5.0/go.mod h1:g/OG8Q8JUxqFw8LGXE44W7osn1uXDAYaVFr1Yld43yc=
 | 
				
			||||||
github.com/twpayne/go-polyline v1.0.0/go.mod h1:ICh24bcLYBX8CknfvNPKqoTbe+eg+MX1NPyJmSBo7pU=
 | 
					github.com/twpayne/go-polyline v1.0.0/go.mod h1:ICh24bcLYBX8CknfvNPKqoTbe+eg+MX1NPyJmSBo7pU=
 | 
				
			||||||
github.com/vmihailenco/msgpack v3.3.3+incompatible/go.mod h1:fy3FlTQTDXWkZ7Bh6AcGMlsjHatGryHQYUTf1ShIgkk=
 | 
					github.com/twpayne/go-polyline v1.1.1 h1:/tSF1BR7rN4HWj4XKqvRUNrCiYVMCvywxTFVofvDV0w=
 | 
				
			||||||
github.com/vmihailenco/msgpack/v4 v4.3.12/go.mod h1:gborTTJjAo/GWTqqRjrLCn9pgNN+NXzzngzBKDPIqw4=
 | 
					github.com/twpayne/go-polyline v1.1.1/go.mod h1:ybd9IWWivW/rlXPXuuckeKUyF3yrIim+iqA7kSl4NFY=
 | 
				
			||||||
github.com/vmihailenco/tagparser v0.1.1/go.mod h1:OeAg3pn3UbLjkWt+rN9oFYB6u/cQgqMEUPoW2WPyhdI=
 | 
					 | 
				
			||||||
github.com/wneessen/go-mail v0.5.2 h1:MZKwgHJoRboLJ+EHMLuHpZc95wo+u1xViL/4XSswDT8=
 | 
					 | 
				
			||||||
github.com/wneessen/go-mail v0.5.2/go.mod h1:kRroJvEq2hOSEPFRiKjN7Csrz0G1w+RpiGR3b6yo+Ck=
 | 
					 | 
				
			||||||
github.com/xdg-go/pbkdf2 v1.0.0 h1:Su7DPu48wXMwC3bs7MCNG+z4FhcyEuz5dlvchbq0B0c=
 | 
					github.com/xdg-go/pbkdf2 v1.0.0 h1:Su7DPu48wXMwC3bs7MCNG+z4FhcyEuz5dlvchbq0B0c=
 | 
				
			||||||
github.com/xdg-go/pbkdf2 v1.0.0/go.mod h1:jrpuAogTd400dnrH08LKmI/xc1MbPOebTwRqcT5RDeI=
 | 
					github.com/xdg-go/pbkdf2 v1.0.0/go.mod h1:jrpuAogTd400dnrH08LKmI/xc1MbPOebTwRqcT5RDeI=
 | 
				
			||||||
 | 
					github.com/xdg-go/scram v1.1.1/go.mod h1:RaEWvsqvNKKvBPvcKeFjrG2cJqOkHTiyTpzz23ni57g=
 | 
				
			||||||
github.com/xdg-go/scram v1.1.2 h1:FHX5I5B4i4hKRVRBCFRxq1iQRej7WO3hhBuJf+UUySY=
 | 
					github.com/xdg-go/scram v1.1.2 h1:FHX5I5B4i4hKRVRBCFRxq1iQRej7WO3hhBuJf+UUySY=
 | 
				
			||||||
github.com/xdg-go/scram v1.1.2/go.mod h1:RT/sEzTbU5y00aCK8UOx6R7YryM0iF1N2MOmC3kKLN4=
 | 
					github.com/xdg-go/scram v1.1.2/go.mod h1:RT/sEzTbU5y00aCK8UOx6R7YryM0iF1N2MOmC3kKLN4=
 | 
				
			||||||
 | 
					github.com/xdg-go/stringprep v1.0.3/go.mod h1:W3f5j4i+9rC0kuIEJL0ky1VpHXQU3ocBgklLGvcBnW8=
 | 
				
			||||||
github.com/xdg-go/stringprep v1.0.4 h1:XLI/Ng3O1Atzq0oBs3TWm+5ZVgkq2aqdlvP9JtoZ6c8=
 | 
					github.com/xdg-go/stringprep v1.0.4 h1:XLI/Ng3O1Atzq0oBs3TWm+5ZVgkq2aqdlvP9JtoZ6c8=
 | 
				
			||||||
github.com/xdg-go/stringprep v1.0.4/go.mod h1:mPGuuIYwz7CmR2bT9j4GbQqutWS1zV24gijq1dTyGkM=
 | 
					github.com/xdg-go/stringprep v1.0.4/go.mod h1:mPGuuIYwz7CmR2bT9j4GbQqutWS1zV24gijq1dTyGkM=
 | 
				
			||||||
github.com/xuri/efp v0.0.0-20220603152613-6918739fd470 h1:6932x8ltq1w4utjmfMPVj09jdMlkY0aiA6+Skbtl3/c=
 | 
					github.com/xuri/efp v0.0.0-20220603152613-6918739fd470 h1:6932x8ltq1w4utjmfMPVj09jdMlkY0aiA6+Skbtl3/c=
 | 
				
			||||||
| 
						 | 
					@ -261,26 +353,46 @@ github.com/xuri/excelize/v2 v2.7.1 h1:gm8q0UCAyaTt3MEF5wWMjVdmthm2EHAWesGSKS9tdV
 | 
				
			||||||
github.com/xuri/excelize/v2 v2.7.1/go.mod h1:qc0+2j4TvAUrBw36ATtcTeC1VCM0fFdAXZOmcF4nTpY=
 | 
					github.com/xuri/excelize/v2 v2.7.1/go.mod h1:qc0+2j4TvAUrBw36ATtcTeC1VCM0fFdAXZOmcF4nTpY=
 | 
				
			||||||
github.com/xuri/nfp v0.0.0-20220409054826-5e722a1d9e22 h1:OAmKAfT06//esDdpi/DZ8Qsdt4+M5+ltca05dA5bG2M=
 | 
					github.com/xuri/nfp v0.0.0-20220409054826-5e722a1d9e22 h1:OAmKAfT06//esDdpi/DZ8Qsdt4+M5+ltca05dA5bG2M=
 | 
				
			||||||
github.com/xuri/nfp v0.0.0-20220409054826-5e722a1d9e22/go.mod h1:WwHg+CVyzlv/TX9xqBFXEZAuxOPxn2k1GNHwG41IIUQ=
 | 
					github.com/xuri/nfp v0.0.0-20220409054826-5e722a1d9e22/go.mod h1:WwHg+CVyzlv/TX9xqBFXEZAuxOPxn2k1GNHwG41IIUQ=
 | 
				
			||||||
 | 
					github.com/youmark/pkcs8 v0.0.0-20181117223130-1be2e3e5546d/go.mod h1:rHwXgn7JulP+udvsHwJoVG1YGAP6VLg4y9I5dyZdqmA=
 | 
				
			||||||
github.com/youmark/pkcs8 v0.0.0-20240726163527-a2c0da244d78 h1:ilQV1hzziu+LLM3zUTJ0trRztfwgjqKnBWNtSRkbmwM=
 | 
					github.com/youmark/pkcs8 v0.0.0-20240726163527-a2c0da244d78 h1:ilQV1hzziu+LLM3zUTJ0trRztfwgjqKnBWNtSRkbmwM=
 | 
				
			||||||
github.com/youmark/pkcs8 v0.0.0-20240726163527-a2c0da244d78/go.mod h1:aL8wCCfTfSfmXjznFBSZNN13rSJjlIOI1fUNAtF7rmI=
 | 
					github.com/youmark/pkcs8 v0.0.0-20240726163527-a2c0da244d78/go.mod h1:aL8wCCfTfSfmXjznFBSZNN13rSJjlIOI1fUNAtF7rmI=
 | 
				
			||||||
github.com/yuin/goldmark v1.1.27/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74=
 | 
					github.com/yuin/goldmark v1.1.27/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74=
 | 
				
			||||||
github.com/yuin/goldmark v1.2.1/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74=
 | 
					github.com/yuin/goldmark v1.2.1/go.mod h1:3hX8gzYuyVAZsxl0MRgGTJEmQBFcNTphYh9decYSb74=
 | 
				
			||||||
github.com/yuin/goldmark v1.3.5/go.mod h1:mwnBkeHKe2W/ZEtQ+71ViKU8L12m81fl3OWwC1Zlc8k=
 | 
					github.com/yuin/goldmark v1.3.5/go.mod h1:mwnBkeHKe2W/ZEtQ+71ViKU8L12m81fl3OWwC1Zlc8k=
 | 
				
			||||||
github.com/yuin/goldmark v1.4.13/go.mod h1:6yULJ656Px+3vBD8DxQVa3kxgyrAnzto9xy5taEt/CY=
 | 
					github.com/yuin/goldmark v1.4.13/go.mod h1:6yULJ656Px+3vBD8DxQVa3kxgyrAnzto9xy5taEt/CY=
 | 
				
			||||||
github.com/zclconf/go-cty v1.2.0/go.mod h1:hOPWgoHbaTUnI5k4D2ld+GRpFJSCe6bCM7m1q/N4PQ8=
 | 
					github.com/zclconf/go-cty v1.16.2 h1:LAJSwc3v81IRBZyUVQDUdZ7hs3SYs9jv0eZJDWHD/70=
 | 
				
			||||||
github.com/zclconf/go-cty v1.8.0 h1:s4AvqaeQzJIu3ndv4gVIhplVD0krU+bgrcLSVUnaWuA=
 | 
					github.com/zclconf/go-cty v1.16.2/go.mod h1:VvMs5i0vgZdhYawQNq5kePSpLAoz8u1xvZgrPIxfnZE=
 | 
				
			||||||
github.com/zclconf/go-cty v1.8.0/go.mod h1:vVKLxnk3puL4qRAv72AO+W99LUD4da90g3uUAzyuvAk=
 | 
					github.com/zclconf/go-cty-debug v0.0.0-20240509010212-0d6042c53940 h1:4r45xpDWB6ZMSMNJFMOjqrGHynW3DIBuR2H9j0ug+Mo=
 | 
				
			||||||
github.com/zclconf/go-cty-debug v0.0.0-20191215020915-b22d67c1ba0b/go.mod h1:ZRKQfBXbGkpdV6QMzT3rU1kSTAnfu1dO8dPKjYprgj8=
 | 
					github.com/zclconf/go-cty-debug v0.0.0-20240509010212-0d6042c53940/go.mod h1:CmBdvvj3nqzfzJ6nTCIwDTPZ56aVGvDrmztiO5g3qrM=
 | 
				
			||||||
 | 
					github.com/zclconf/go-cty-yaml v1.1.0 h1:nP+jp0qPHv2IhUVqmQSzjvqAWcObN0KBkUl2rWBdig0=
 | 
				
			||||||
 | 
					github.com/zclconf/go-cty-yaml v1.1.0/go.mod h1:9YLUH4g7lOhVWqUbctnVlZ5KLpg7JAprQNgxSZ1Gyxs=
 | 
				
			||||||
gitlab.scity.coop/maas/navitia-golang v0.0.0-20220429110621-5c22d6efdd0c h1:pCazzEsTvjDopl3bvo6H2f2xjo1cDjOZ9QpJRNFCc00=
 | 
					gitlab.scity.coop/maas/navitia-golang v0.0.0-20220429110621-5c22d6efdd0c h1:pCazzEsTvjDopl3bvo6H2f2xjo1cDjOZ9QpJRNFCc00=
 | 
				
			||||||
gitlab.scity.coop/maas/navitia-golang v0.0.0-20220429110621-5c22d6efdd0c/go.mod h1:M1U2osA6dYQF8zuJOTb/0O1F/Xgcb+4AkRdw+Un6Rp4=
 | 
					gitlab.scity.coop/maas/navitia-golang v0.0.0-20220429110621-5c22d6efdd0c/go.mod h1:M1U2osA6dYQF8zuJOTb/0O1F/Xgcb+4AkRdw+Un6Rp4=
 | 
				
			||||||
 | 
					go.etcd.io/bbolt v1.4.0 h1:TU77id3TnN/zKr7CO/uk+fBCwF2jGcMuw2B/FMAzYIk=
 | 
				
			||||||
 | 
					go.etcd.io/bbolt v1.4.0/go.mod h1:AsD+OCi/qPN1giOX1aiLAha3o1U8rAz65bvN4j0sRuk=
 | 
				
			||||||
go.etcd.io/etcd/api/v3 v3.5.12 h1:W4sw5ZoU2Juc9gBWuLk5U6fHfNVyY1WC5g9uiXZio/c=
 | 
					go.etcd.io/etcd/api/v3 v3.5.12 h1:W4sw5ZoU2Juc9gBWuLk5U6fHfNVyY1WC5g9uiXZio/c=
 | 
				
			||||||
go.etcd.io/etcd/api/v3 v3.5.12/go.mod h1:Ot+o0SWSyT6uHhA56al1oCED0JImsRiU9Dc26+C2a+4=
 | 
					go.etcd.io/etcd/api/v3 v3.5.12/go.mod h1:Ot+o0SWSyT6uHhA56al1oCED0JImsRiU9Dc26+C2a+4=
 | 
				
			||||||
go.etcd.io/etcd/client/pkg/v3 v3.5.12 h1:EYDL6pWwyOsylrQyLp2w+HkQ46ATiOvoEdMarindU2A=
 | 
					go.etcd.io/etcd/client/pkg/v3 v3.5.12 h1:EYDL6pWwyOsylrQyLp2w+HkQ46ATiOvoEdMarindU2A=
 | 
				
			||||||
go.etcd.io/etcd/client/pkg/v3 v3.5.12/go.mod h1:seTzl2d9APP8R5Y2hFL3NVlD6qC/dOT+3kvrqPyTas4=
 | 
					go.etcd.io/etcd/client/pkg/v3 v3.5.12/go.mod h1:seTzl2d9APP8R5Y2hFL3NVlD6qC/dOT+3kvrqPyTas4=
 | 
				
			||||||
go.etcd.io/etcd/client/v3 v3.5.12 h1:v5lCPXn1pf1Uu3M4laUE2hp/geOTc5uPcYYsNe1lDxg=
 | 
					go.etcd.io/etcd/client/v3 v3.5.12 h1:v5lCPXn1pf1Uu3M4laUE2hp/geOTc5uPcYYsNe1lDxg=
 | 
				
			||||||
go.etcd.io/etcd/client/v3 v3.5.12/go.mod h1:tSbBCakoWmmddL+BKVAJHa9km+O/E+bumDe9mSbPiqw=
 | 
					go.etcd.io/etcd/client/v3 v3.5.12/go.mod h1:tSbBCakoWmmddL+BKVAJHa9km+O/E+bumDe9mSbPiqw=
 | 
				
			||||||
go.mongodb.org/mongo-driver v1.17.1 h1:Wic5cJIwJgSpBhe3lx3+/RybR5PiYRMpVFgO7cOHyIM=
 | 
					go.mongodb.org/mongo-driver v1.11.4/go.mod h1:PTSz5yu21bkT/wXpkS7WR5f0ddqw5quethTUn9WM+2g=
 | 
				
			||||||
go.mongodb.org/mongo-driver v1.17.1/go.mod h1:wwWm/+BuOddhcq3n68LKRmgk2wXzmF6s0SFOa0GINL4=
 | 
					go.mongodb.org/mongo-driver v1.17.3 h1:TQyXhnsWfWtgAhMtOgtYHMTkZIfBTpMTsMnd9ZBeHxQ=
 | 
				
			||||||
 | 
					go.mongodb.org/mongo-driver v1.17.3/go.mod h1:Hy04i7O2kC4RS06ZrhPRqj/u4DTYkFDAAccj+rVKqgQ=
 | 
				
			||||||
 | 
					go.mongodb.org/mongo-driver/v2 v2.1.0 h1:/ELnVNjmfUKDsoBisXxuJL0noR9CfeUIrP7Yt3R+egg=
 | 
				
			||||||
 | 
					go.mongodb.org/mongo-driver/v2 v2.1.0/go.mod h1:AWiLRShSrk5RHQS3AEn3RL19rqOzVq49MCpWQ3x/huI=
 | 
				
			||||||
 | 
					go.opentelemetry.io/auto/sdk v1.1.0 h1:cH53jehLUN6UFLY71z+NDOiNJqDdPRaXzTel0sJySYA=
 | 
				
			||||||
 | 
					go.opentelemetry.io/auto/sdk v1.1.0/go.mod h1:3wSPjt5PWp2RhlCcmmOial7AvC4DQqZb7a7wCow3W8A=
 | 
				
			||||||
 | 
					go.opentelemetry.io/otel v1.34.0 h1:zRLXxLCgL1WyKsPVrgbSdMN4c0FMkDAskSTQP+0hdUY=
 | 
				
			||||||
 | 
					go.opentelemetry.io/otel v1.34.0/go.mod h1:OWFPOQ+h4G8xpyjgqo4SxJYdDQ/qmRH+wivy7zzx9oI=
 | 
				
			||||||
 | 
					go.opentelemetry.io/otel/metric v1.34.0 h1:+eTR3U0MyfWjRDhmFMxe2SsW64QrZ84AOhvqS7Y+PoQ=
 | 
				
			||||||
 | 
					go.opentelemetry.io/otel/metric v1.34.0/go.mod h1:CEDrp0fy2D0MvkXE+dPV7cMi8tWZwX3dmaIhwPOaqHE=
 | 
				
			||||||
 | 
					go.opentelemetry.io/otel/sdk v1.34.0 h1:95zS4k/2GOy069d321O8jWgYsW3MzVV+KuSPKp7Wr1A=
 | 
				
			||||||
 | 
					go.opentelemetry.io/otel/sdk v1.34.0/go.mod h1:0e/pNiaMAqaykJGKbi+tSjWfNNHMTxoC9qANsCzbyxU=
 | 
				
			||||||
 | 
					go.opentelemetry.io/otel/sdk/metric v1.34.0 h1:5CeK9ujjbFVL5c1PhLuStg1wxA7vQv7ce1EK0Gyvahk=
 | 
				
			||||||
 | 
					go.opentelemetry.io/otel/sdk/metric v1.34.0/go.mod h1:jQ/r8Ze28zRKoNRdkjCZxfs6YvBTG1+YIqyFVFYec5w=
 | 
				
			||||||
 | 
					go.opentelemetry.io/otel/trace v1.34.0 h1:+ouXS2V8Rd4hp4580a8q23bg0azF2nI8cqLYnC8mh/k=
 | 
				
			||||||
 | 
					go.opentelemetry.io/otel/trace v1.34.0/go.mod h1:Svm7lSjQD7kG7KJ/MUHPVXSDGz2OX4h0M2jHBhmSfRE=
 | 
				
			||||||
go.uber.org/atomic v1.7.0/go.mod h1:fEN4uk6kAWBTFdckzkM89CLk9XfWZrxpCo0nPH17wJc=
 | 
					go.uber.org/atomic v1.7.0/go.mod h1:fEN4uk6kAWBTFdckzkM89CLk9XfWZrxpCo0nPH17wJc=
 | 
				
			||||||
go.uber.org/atomic v1.11.0 h1:ZvwS0R+56ePWxUNi+Atn9dWONBPp/AUETXlHW0DxSjE=
 | 
					go.uber.org/atomic v1.11.0 h1:ZvwS0R+56ePWxUNi+Atn9dWONBPp/AUETXlHW0DxSjE=
 | 
				
			||||||
go.uber.org/atomic v1.11.0/go.mod h1:LUxbIzbOniOlMKjJjyPfpl4v+PKK2cNJn91OQbhoJI0=
 | 
					go.uber.org/atomic v1.11.0/go.mod h1:LUxbIzbOniOlMKjJjyPfpl4v+PKK2cNJn91OQbhoJI0=
 | 
				
			||||||
| 
						 | 
					@ -292,20 +404,14 @@ go.uber.org/multierr v1.11.0/go.mod h1:20+QtiLqy0Nd6FdQB9TLXag12DsQkrbs3htMFfDN8
 | 
				
			||||||
go.uber.org/zap v1.21.0 h1:WefMeulhovoZ2sYXz7st6K0sLj7bBhpiFaud4r4zST8=
 | 
					go.uber.org/zap v1.21.0 h1:WefMeulhovoZ2sYXz7st6K0sLj7bBhpiFaud4r4zST8=
 | 
				
			||||||
go.uber.org/zap v1.21.0/go.mod h1:wjWOCqI0f2ZZrJF/UufIOkiC8ii6tm1iqIsLo76RfJw=
 | 
					go.uber.org/zap v1.21.0/go.mod h1:wjWOCqI0f2ZZrJF/UufIOkiC8ii6tm1iqIsLo76RfJw=
 | 
				
			||||||
golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w=
 | 
					golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w=
 | 
				
			||||||
golang.org/x/crypto v0.0.0-20190426145343-a29dc8fdc734/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI=
 | 
					 | 
				
			||||||
golang.org/x/crypto v0.0.0-20191011191535-87dc89f01550/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI=
 | 
					golang.org/x/crypto v0.0.0-20191011191535-87dc89f01550/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI=
 | 
				
			||||||
golang.org/x/crypto v0.0.0-20200323165209-0ec3e9974c59/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto=
 | 
					golang.org/x/crypto v0.0.0-20200323165209-0ec3e9974c59/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto=
 | 
				
			||||||
golang.org/x/crypto v0.0.0-20200622213623-75b288015ac9/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto=
 | 
					golang.org/x/crypto v0.0.0-20200622213623-75b288015ac9/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto=
 | 
				
			||||||
golang.org/x/crypto v0.0.0-20210921155107-089bfa567519/go.mod h1:GvvjBRRGRdwPK5ydBHafDWAxML/pGHZbMvKqRZ5+Abc=
 | 
					golang.org/x/crypto v0.0.0-20210921155107-089bfa567519/go.mod h1:GvvjBRRGRdwPK5ydBHafDWAxML/pGHZbMvKqRZ5+Abc=
 | 
				
			||||||
golang.org/x/crypto v0.0.0-20211215153901-e495a2d5b3d3/go.mod h1:IxCIyHEi3zRg3s0A5j5BB6A9Jmi73HwBIUl50j+osU4=
 | 
					golang.org/x/crypto v0.0.0-20220622213112-05595931fe9d/go.mod h1:IxCIyHEi3zRg3s0A5j5BB6A9Jmi73HwBIUl50j+osU4=
 | 
				
			||||||
golang.org/x/crypto v0.8.0/go.mod h1:mRqEX+O9/h5TFCrQhkgjo2yKi0yYA+9ecGkdQoHrywE=
 | 
					golang.org/x/crypto v0.8.0/go.mod h1:mRqEX+O9/h5TFCrQhkgjo2yKi0yYA+9ecGkdQoHrywE=
 | 
				
			||||||
golang.org/x/crypto v0.13.0/go.mod h1:y6Z2r+Rw4iayiXXAIxJIDAJ1zMW4yaTpebo8fPOliYc=
 | 
					golang.org/x/crypto v0.37.0 h1:kJNSjF/Xp7kU0iB2Z+9viTPMW4EqqsrywMXLJOOsXSE=
 | 
				
			||||||
golang.org/x/crypto v0.19.0/go.mod h1:Iy9bg/ha4yyC70EfRS8jz+B6ybOBKMaSxLj6P6oBDfU=
 | 
					golang.org/x/crypto v0.37.0/go.mod h1:vg+k43peMZ0pUMhYmVAWysMK35e6ioLh3wB8ZCAfbVc=
 | 
				
			||||||
golang.org/x/crypto v0.23.0/go.mod h1:CKFgDieR+mRhux2Lsu27y0fO304Db0wZe70UKqHu0v8=
 | 
					 | 
				
			||||||
golang.org/x/crypto v0.28.0 h1:GBDwsMXVQi34v5CCYUm2jkJvu4cbtru2U4TN2PSyQnw=
 | 
					 | 
				
			||||||
golang.org/x/crypto v0.28.0/go.mod h1:rmgy+3RHxRZMyY0jjAJShp2zgEdOqj2AO7U0pYmeQ7U=
 | 
					 | 
				
			||||||
golang.org/x/exp v0.0.0-20241108190413-2d47ceb2692f h1:XdNn9LlyWAhLVp6P/i8QYBW+hlyhrhei9uErw2B5GJo=
 | 
					 | 
				
			||||||
golang.org/x/exp v0.0.0-20241108190413-2d47ceb2692f/go.mod h1:D5SMRVC3C2/4+F/DB1wZsLRnSNimn2Sp/NPsCrsv8ak=
 | 
					 | 
				
			||||||
golang.org/x/image v0.5.0 h1:5JMiNunQeQw++mMOz48/ISeNu3Iweh/JaZU8ZLqHRrI=
 | 
					golang.org/x/image v0.5.0 h1:5JMiNunQeQw++mMOz48/ISeNu3Iweh/JaZU8ZLqHRrI=
 | 
				
			||||||
golang.org/x/image v0.5.0/go.mod h1:FVC7BI/5Ym8R25iw5OLsgshdUBbT1h5jZTpA+mvAdZ4=
 | 
					golang.org/x/image v0.5.0/go.mod h1:FVC7BI/5Ym8R25iw5OLsgshdUBbT1h5jZTpA+mvAdZ4=
 | 
				
			||||||
golang.org/x/lint v0.0.0-20190930215403-16217165b5de/go.mod h1:6SW0HCj/g11FgYtHlgUYUwCkIfeOF89ocIRzGO/8vkc=
 | 
					golang.org/x/lint v0.0.0-20190930215403-16217165b5de/go.mod h1:6SW0HCj/g11FgYtHlgUYUwCkIfeOF89ocIRzGO/8vkc=
 | 
				
			||||||
| 
						 | 
					@ -314,16 +420,12 @@ golang.org/x/mod v0.3.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA=
 | 
				
			||||||
golang.org/x/mod v0.4.2/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA=
 | 
					golang.org/x/mod v0.4.2/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA=
 | 
				
			||||||
golang.org/x/mod v0.6.0-dev.0.20220419223038-86c51ed26bb4/go.mod h1:jJ57K6gSWd91VN4djpZkiMVwK6gcyfeH4XE8wZrZaV4=
 | 
					golang.org/x/mod v0.6.0-dev.0.20220419223038-86c51ed26bb4/go.mod h1:jJ57K6gSWd91VN4djpZkiMVwK6gcyfeH4XE8wZrZaV4=
 | 
				
			||||||
golang.org/x/mod v0.8.0/go.mod h1:iBbtSCu2XBx23ZKBPSOrRkjjQPZFPuis4dIYUhu/chs=
 | 
					golang.org/x/mod v0.8.0/go.mod h1:iBbtSCu2XBx23ZKBPSOrRkjjQPZFPuis4dIYUhu/chs=
 | 
				
			||||||
golang.org/x/mod v0.12.0/go.mod h1:iBbtSCu2XBx23ZKBPSOrRkjjQPZFPuis4dIYUhu/chs=
 | 
					golang.org/x/mod v0.24.0 h1:ZfthKaKaT4NrhGVZHO1/WDTwGES4De8KtWO0SIbNJMU=
 | 
				
			||||||
golang.org/x/mod v0.15.0/go.mod h1:hTbmBsO62+eylJbnUtE2MGJUyE7QWk4xUqPFrRgJ+7c=
 | 
					golang.org/x/mod v0.24.0/go.mod h1:IXM97Txy2VM4PJ3gI61r1YEk/gAj6zAHN3AdZt6S9Ww=
 | 
				
			||||||
golang.org/x/mod v0.17.0/go.mod h1:hTbmBsO62+eylJbnUtE2MGJUyE7QWk4xUqPFrRgJ+7c=
 | 
					 | 
				
			||||||
golang.org/x/net v0.0.0-20180811021610-c39426892332/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
 | 
					 | 
				
			||||||
golang.org/x/net v0.0.0-20190311183353-d8887717615a/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg=
 | 
					golang.org/x/net v0.0.0-20190311183353-d8887717615a/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg=
 | 
				
			||||||
golang.org/x/net v0.0.0-20190404232315-eb5bcb51f2a3/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg=
 | 
					golang.org/x/net v0.0.0-20190404232315-eb5bcb51f2a3/go.mod h1:t9HGtf8HONx5eT2rtn7q6eTqICYqUVnKs3thJo3Qplg=
 | 
				
			||||||
golang.org/x/net v0.0.0-20190603091049-60506f45cf65/go.mod h1:HSz+uSET+XFnRR8LxR5pz3Of3rY3CfYBVs4xY44aLks=
 | 
					 | 
				
			||||||
golang.org/x/net v0.0.0-20190620200207-3b0461eec859/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
 | 
					golang.org/x/net v0.0.0-20190620200207-3b0461eec859/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
 | 
				
			||||||
golang.org/x/net v0.0.0-20200226121028-0de0cce0169b/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
 | 
					golang.org/x/net v0.0.0-20200226121028-0de0cce0169b/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
 | 
				
			||||||
golang.org/x/net v0.0.0-20200301022130-244492dfa37a/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s=
 | 
					 | 
				
			||||||
golang.org/x/net v0.0.0-20201021035429-f5854403a974/go.mod h1:sp8m0HH+o8qH0wwXwYZr8TS3Oi6o0r6Gce1SSxlDquU=
 | 
					golang.org/x/net v0.0.0-20201021035429-f5854403a974/go.mod h1:sp8m0HH+o8qH0wwXwYZr8TS3Oi6o0r6Gce1SSxlDquU=
 | 
				
			||||||
golang.org/x/net v0.0.0-20210226172049-e18ecbb05110/go.mod h1:m0MpNAwzfU5UDzcl9v0D8zg8gWTRqZa9RBIspLL5mdg=
 | 
					golang.org/x/net v0.0.0-20210226172049-e18ecbb05110/go.mod h1:m0MpNAwzfU5UDzcl9v0D8zg8gWTRqZa9RBIspLL5mdg=
 | 
				
			||||||
golang.org/x/net v0.0.0-20210405180319-a5a99cb37ef4/go.mod h1:p54w0d4576C0XHj96bSt6lcn1PtDYWL6XObtHCRCNQM=
 | 
					golang.org/x/net v0.0.0-20210405180319-a5a99cb37ef4/go.mod h1:p54w0d4576C0XHj96bSt6lcn1PtDYWL6XObtHCRCNQM=
 | 
				
			||||||
| 
						 | 
					@ -331,33 +433,22 @@ golang.org/x/net v0.0.0-20211112202133-69e39bad7dc2/go.mod h1:9nx3DQGgdP8bBQD5qx
 | 
				
			||||||
golang.org/x/net v0.0.0-20220722155237-a158d28d115b/go.mod h1:XRhObCWvk6IyKnWLug+ECip1KBveYUHfp+8e9klMJ9c=
 | 
					golang.org/x/net v0.0.0-20220722155237-a158d28d115b/go.mod h1:XRhObCWvk6IyKnWLug+ECip1KBveYUHfp+8e9klMJ9c=
 | 
				
			||||||
golang.org/x/net v0.6.0/go.mod h1:2Tu9+aMcznHK/AK1HMvgo6xiTLG5rD5rZLDS+rp2Bjs=
 | 
					golang.org/x/net v0.6.0/go.mod h1:2Tu9+aMcznHK/AK1HMvgo6xiTLG5rD5rZLDS+rp2Bjs=
 | 
				
			||||||
golang.org/x/net v0.9.0/go.mod h1:d48xBJpPfHeWQsugry2m+kC02ZBRGRgulfHnEXEuWns=
 | 
					golang.org/x/net v0.9.0/go.mod h1:d48xBJpPfHeWQsugry2m+kC02ZBRGRgulfHnEXEuWns=
 | 
				
			||||||
golang.org/x/net v0.10.0/go.mod h1:0qNGK6F8kojg2nk9dLZ2mShWaEBan6FAoqfSigmmuDg=
 | 
					golang.org/x/net v0.39.0 h1:ZCu7HMWDxpXpaiKdhzIfaltL9Lp31x/3fCP11bc6/fY=
 | 
				
			||||||
golang.org/x/net v0.15.0/go.mod h1:idbUs1IY1+zTqbi8yxTbhexhEEk5ur9LInksu6HrEpk=
 | 
					golang.org/x/net v0.39.0/go.mod h1:X7NRbYVEA+ewNkCNyJ513WmMdQ3BineSwVtN2zD/d+E=
 | 
				
			||||||
golang.org/x/net v0.21.0/go.mod h1:bIjVDfnllIU7BJ2DNgfnXvpSvtn8VRwhlsaeUTyUS44=
 | 
					golang.org/x/oauth2 v0.25.0 h1:CY4y7XT9v0cRI9oupztF8AgiIu99L/ksR/Xp/6jrZ70=
 | 
				
			||||||
golang.org/x/net v0.25.0/go.mod h1:JkAGAh7GEvH74S6FOH42FLoXpXbE/aqXSrIQjXgsiwM=
 | 
					golang.org/x/oauth2 v0.25.0/go.mod h1:XYTD2NtWslqkgxebSiOHnXEap4TF09sJSc7H1sXbhtI=
 | 
				
			||||||
golang.org/x/net v0.29.0 h1:5ORfpBpCs4HzDYoodCDBbwHzdR5UrLBZ3sOnUJmFoHo=
 | 
					 | 
				
			||||||
golang.org/x/net v0.29.0/go.mod h1:gLkgy8jTGERgjzMic6DS9+SP0ajcu6Xu3Orq/SpETg0=
 | 
					 | 
				
			||||||
golang.org/x/oauth2 v0.23.0 h1:PbgcYx2W7i4LvjJWEbf0ngHV6qJYr86PkAV3bXdLEbs=
 | 
					 | 
				
			||||||
golang.org/x/oauth2 v0.23.0/go.mod h1:XYTD2NtWslqkgxebSiOHnXEap4TF09sJSc7H1sXbhtI=
 | 
					 | 
				
			||||||
golang.org/x/sync v0.0.0-20180314180146-1d60e4601c6f/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
 | 
					 | 
				
			||||||
golang.org/x/sync v0.0.0-20190423024810-112230192c58/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
 | 
					golang.org/x/sync v0.0.0-20190423024810-112230192c58/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
 | 
				
			||||||
golang.org/x/sync v0.0.0-20190911185100-cd5d95a43a6e/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
 | 
					golang.org/x/sync v0.0.0-20190911185100-cd5d95a43a6e/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
 | 
				
			||||||
golang.org/x/sync v0.0.0-20201020160332-67f06af15bc9/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
 | 
					golang.org/x/sync v0.0.0-20201020160332-67f06af15bc9/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
 | 
				
			||||||
golang.org/x/sync v0.0.0-20210220032951-036812b2e83c/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
 | 
					golang.org/x/sync v0.0.0-20210220032951-036812b2e83c/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
 | 
				
			||||||
golang.org/x/sync v0.0.0-20220722155255-886fb9371eb4/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
 | 
					golang.org/x/sync v0.0.0-20220722155255-886fb9371eb4/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
 | 
				
			||||||
golang.org/x/sync v0.1.0/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
 | 
					golang.org/x/sync v0.1.0/go.mod h1:RxMgew5VJxzue5/jJTE5uejpjVlOe/izrB70Jof72aM=
 | 
				
			||||||
golang.org/x/sync v0.3.0/go.mod h1:FU7BRWz2tNW+3quACPkgCx/L+uEAv1htQ0V83Z9Rj+Y=
 | 
					golang.org/x/sync v0.13.0 h1:AauUjRAJ9OSnvULf/ARrrVywoJDy0YS2AwQ98I37610=
 | 
				
			||||||
golang.org/x/sync v0.6.0/go.mod h1:Czt+wKu1gCyEFDUtn0jG5QVvpJ6rzVqr5aXyt9drQfk=
 | 
					golang.org/x/sync v0.13.0/go.mod h1:1dzgHSNfp02xaA81J2MS99Qcpr2w7fw1gpm99rleRqA=
 | 
				
			||||||
golang.org/x/sync v0.7.0/go.mod h1:Czt+wKu1gCyEFDUtn0jG5QVvpJ6rzVqr5aXyt9drQfk=
 | 
					 | 
				
			||||||
golang.org/x/sync v0.8.0/go.mod h1:Czt+wKu1gCyEFDUtn0jG5QVvpJ6rzVqr5aXyt9drQfk=
 | 
					 | 
				
			||||||
golang.org/x/sync v0.9.0 h1:fEo0HyrW1GIgZdpbhCRO0PkJajUS5H9IFUztCgEo2jQ=
 | 
					 | 
				
			||||||
golang.org/x/sync v0.9.0/go.mod h1:Czt+wKu1gCyEFDUtn0jG5QVvpJ6rzVqr5aXyt9drQfk=
 | 
					 | 
				
			||||||
golang.org/x/sync v0.11.0/go.mod h1:Czt+wKu1gCyEFDUtn0jG5QVvpJ6rzVqr5aXyt9drQfk=
 | 
					 | 
				
			||||||
golang.org/x/sys v0.0.0-20180905080454-ebe1bf3edb33/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
 | 
					golang.org/x/sys v0.0.0-20180905080454-ebe1bf3edb33/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
 | 
				
			||||||
golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
 | 
					golang.org/x/sys v0.0.0-20190215142949-d0b11bdaac8a/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
 | 
				
			||||||
golang.org/x/sys v0.0.0-20190222072716-a9d3bda3a223/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
 | 
					golang.org/x/sys v0.0.0-20190222072716-a9d3bda3a223/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY=
 | 
				
			||||||
golang.org/x/sys v0.0.0-20190412213103-97732733099d/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
 | 
					golang.org/x/sys v0.0.0-20190412213103-97732733099d/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
 | 
				
			||||||
golang.org/x/sys v0.0.0-20190502175342-a43fa875dd82/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
 | 
					 | 
				
			||||||
golang.org/x/sys v0.0.0-20190507160741-ecd444e8653b/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
 | 
					golang.org/x/sys v0.0.0-20190507160741-ecd444e8653b/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
 | 
				
			||||||
golang.org/x/sys v0.0.0-20191026070338-33540a1f6037/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
 | 
					golang.org/x/sys v0.0.0-20191026070338-33540a1f6037/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
 | 
				
			||||||
golang.org/x/sys v0.0.0-20200930185726-fdedc70b468f/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
 | 
					golang.org/x/sys v0.0.0-20200930185726-fdedc70b468f/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
 | 
				
			||||||
| 
						 | 
					@ -366,51 +457,30 @@ golang.org/x/sys v0.0.0-20210330210617-4fbd30eecc44/go.mod h1:h1NjWce9XRLGQEsW7w
 | 
				
			||||||
golang.org/x/sys v0.0.0-20210423082822-04245dca01da/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
 | 
					golang.org/x/sys v0.0.0-20210423082822-04245dca01da/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
 | 
				
			||||||
golang.org/x/sys v0.0.0-20210510120138-977fb7262007/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
 | 
					golang.org/x/sys v0.0.0-20210510120138-977fb7262007/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
 | 
				
			||||||
golang.org/x/sys v0.0.0-20210615035016-665e8c7367d1/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
 | 
					golang.org/x/sys v0.0.0-20210615035016-665e8c7367d1/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
 | 
				
			||||||
golang.org/x/sys v0.0.0-20210806184541-e5e7981a1069/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
 | 
					 | 
				
			||||||
golang.org/x/sys v0.0.0-20220520151302-bc2c85ada10a/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
 | 
					golang.org/x/sys v0.0.0-20220520151302-bc2c85ada10a/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
 | 
				
			||||||
golang.org/x/sys v0.0.0-20220704084225-05e143d24a9e/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
 | 
					 | 
				
			||||||
golang.org/x/sys v0.0.0-20220715151400-c0bba94af5f8/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
 | 
					golang.org/x/sys v0.0.0-20220715151400-c0bba94af5f8/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
 | 
				
			||||||
golang.org/x/sys v0.0.0-20220722155257-8c9f86f7a55f/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
 | 
					golang.org/x/sys v0.0.0-20220722155257-8c9f86f7a55f/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
 | 
				
			||||||
golang.org/x/sys v0.0.0-20220811171246-fbc7d0a398ab/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
 | 
					golang.org/x/sys v0.0.0-20220811171246-fbc7d0a398ab/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
 | 
				
			||||||
golang.org/x/sys v0.5.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
 | 
					golang.org/x/sys v0.5.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
 | 
				
			||||||
golang.org/x/sys v0.6.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
 | 
					golang.org/x/sys v0.6.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
 | 
				
			||||||
golang.org/x/sys v0.7.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
 | 
					golang.org/x/sys v0.7.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
 | 
				
			||||||
golang.org/x/sys v0.8.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
 | 
					 | 
				
			||||||
golang.org/x/sys v0.12.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
 | 
					golang.org/x/sys v0.12.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
 | 
				
			||||||
golang.org/x/sys v0.17.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA=
 | 
					golang.org/x/sys v0.32.0 h1:s77OFDvIQeibCmezSnk/q6iAfkdiQaJi4VzroCFrN20=
 | 
				
			||||||
golang.org/x/sys v0.20.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA=
 | 
					golang.org/x/sys v0.32.0/go.mod h1:BJP2sWEmIv4KK5OTEluFJCKSidICx8ciO85XgH3Ak8k=
 | 
				
			||||||
golang.org/x/sys v0.26.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA=
 | 
					 | 
				
			||||||
golang.org/x/sys v0.27.0 h1:wBqf8DvsY9Y/2P8gAfPDEYNuS30J4lPHJxXSb/nJZ+s=
 | 
					 | 
				
			||||||
golang.org/x/sys v0.27.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA=
 | 
					 | 
				
			||||||
golang.org/x/sys v0.30.0 h1:QjkSwP/36a20jFYWkSue1YwXzLmsV5Gfq7Eiy72C1uc=
 | 
					 | 
				
			||||||
golang.org/x/sys v0.30.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA=
 | 
					 | 
				
			||||||
golang.org/x/telemetry v0.0.0-20240228155512-f48c80bd79b2/go.mod h1:TeRTkGYfJXctD9OcfyVLyj2J3IxLnKwHJR8f4D8a3YE=
 | 
					 | 
				
			||||||
golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo=
 | 
					golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo=
 | 
				
			||||||
golang.org/x/term v0.0.0-20210927222741-03fcf44c2211/go.mod h1:jbD1KX2456YbFQfuXm/mYQcufACuNUgVhRMnK/tPxf8=
 | 
					golang.org/x/term v0.0.0-20210927222741-03fcf44c2211/go.mod h1:jbD1KX2456YbFQfuXm/mYQcufACuNUgVhRMnK/tPxf8=
 | 
				
			||||||
golang.org/x/term v0.5.0/go.mod h1:jMB1sMXY+tzblOD4FWmEbocvup2/aLOaQEp7JmGp78k=
 | 
					golang.org/x/term v0.5.0/go.mod h1:jMB1sMXY+tzblOD4FWmEbocvup2/aLOaQEp7JmGp78k=
 | 
				
			||||||
golang.org/x/term v0.7.0/go.mod h1:P32HKFT3hSsZrRxla30E9HqToFYAQPCMs/zFMBUFqPY=
 | 
					golang.org/x/term v0.7.0/go.mod h1:P32HKFT3hSsZrRxla30E9HqToFYAQPCMs/zFMBUFqPY=
 | 
				
			||||||
golang.org/x/term v0.8.0/go.mod h1:xPskH00ivmX89bAKVGSKKtLOWNx2+17Eiy94tnKShWo=
 | 
					 | 
				
			||||||
golang.org/x/term v0.12.0/go.mod h1:owVbMEjm3cBLCHdkQu9b1opXd4ETQWc3BhuQGKgXgvU=
 | 
					 | 
				
			||||||
golang.org/x/term v0.17.0/go.mod h1:lLRBjIVuehSbZlaOtGMbcMncT+aqLLLmKrsjNrUguwk=
 | 
					 | 
				
			||||||
golang.org/x/term v0.20.0/go.mod h1:8UkIAJTvZgivsXaD6/pH6U9ecQzZ45awqEOzuCvwpFY=
 | 
					 | 
				
			||||||
golang.org/x/term v0.25.0/go.mod h1:RPyXicDX+6vLxogjjRxjgD2TKtmAO6NZBsBRfrOLu7M=
 | 
					 | 
				
			||||||
golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
 | 
					golang.org/x/text v0.3.0/go.mod h1:NqM8EUOU14njkJ3fqMW+pc6Ldnwhi/IjpwHt7yyuwOQ=
 | 
				
			||||||
golang.org/x/text v0.3.2/go.mod h1:bEr9sfX3Q8Zfm5fL9x+3itogRgK3+ptLWKqgva+5dAk=
 | 
					golang.org/x/text v0.3.2/go.mod h1:bEr9sfX3Q8Zfm5fL9x+3itogRgK3+ptLWKqgva+5dAk=
 | 
				
			||||||
golang.org/x/text v0.3.3/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ=
 | 
					golang.org/x/text v0.3.3/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ=
 | 
				
			||||||
golang.org/x/text v0.3.5/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ=
 | 
					 | 
				
			||||||
golang.org/x/text v0.3.6/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ=
 | 
					golang.org/x/text v0.3.6/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ=
 | 
				
			||||||
golang.org/x/text v0.3.7/go.mod h1:u+2+/6zg+i71rQMx5EYifcz6MCKuco9NR6JIITiCfzQ=
 | 
					golang.org/x/text v0.3.7/go.mod h1:u+2+/6zg+i71rQMx5EYifcz6MCKuco9NR6JIITiCfzQ=
 | 
				
			||||||
golang.org/x/text v0.3.8/go.mod h1:E6s5w1FMmriuDzIBO73fBruAKo1PCIq6d2Q6DHfQ8WQ=
 | 
					golang.org/x/text v0.3.8/go.mod h1:E6s5w1FMmriuDzIBO73fBruAKo1PCIq6d2Q6DHfQ8WQ=
 | 
				
			||||||
golang.org/x/text v0.7.0/go.mod h1:mrYo+phRRbMaCq/xk9113O4dZlRixOauAjOtrjsXDZ8=
 | 
					golang.org/x/text v0.7.0/go.mod h1:mrYo+phRRbMaCq/xk9113O4dZlRixOauAjOtrjsXDZ8=
 | 
				
			||||||
golang.org/x/text v0.9.0/go.mod h1:e1OnstbJyHTd6l/uOt8jFFHp6TRDWZR/bV3emEE/zU8=
 | 
					golang.org/x/text v0.9.0/go.mod h1:e1OnstbJyHTd6l/uOt8jFFHp6TRDWZR/bV3emEE/zU8=
 | 
				
			||||||
golang.org/x/text v0.13.0/go.mod h1:TvPlkZtksWOMsz7fbANvkp4WM8x/WCo/om8BMLbz+aE=
 | 
					golang.org/x/text v0.24.0 h1:dd5Bzh4yt5KYA8f9CJHCP4FB4D51c2c6JvN37xJJkJ0=
 | 
				
			||||||
golang.org/x/text v0.14.0/go.mod h1:18ZOQIKpY8NJVqYksKHtTdi31H5itFRjB5/qKTNYzSU=
 | 
					golang.org/x/text v0.24.0/go.mod h1:L8rBsPeo2pSS+xqN0d5u2ikmjtmoJbDBT1b7nHvFCdU=
 | 
				
			||||||
golang.org/x/text v0.15.0/go.mod h1:18ZOQIKpY8NJVqYksKHtTdi31H5itFRjB5/qKTNYzSU=
 | 
					 | 
				
			||||||
golang.org/x/text v0.19.0/go.mod h1:BuEKDfySbSR4drPmRPG/7iBdf8hvFMuRexcpahXilzY=
 | 
					 | 
				
			||||||
golang.org/x/text v0.20.0 h1:gK/Kv2otX8gz+wn7Rmb3vT96ZwuoxnQlY+HlJVj7Qug=
 | 
					 | 
				
			||||||
golang.org/x/text v0.20.0/go.mod h1:D4IsuqiFMhST5bX19pQ9ikHC2GsaKyk/oF+pn3ducp4=
 | 
					 | 
				
			||||||
golang.org/x/text v0.22.0 h1:bofq7m3/HAFvbF51jz3Q9wLg3jkvSPuiZu/pD1XwgtM=
 | 
					 | 
				
			||||||
golang.org/x/text v0.22.0/go.mod h1:YRoo4H8PVmsu+E3Ou7cqLVH8oXWIHVoX0jqUWALQhfY=
 | 
					 | 
				
			||||||
golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ=
 | 
					golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ=
 | 
				
			||||||
golang.org/x/tools v0.0.0-20190311212946-11955173bddd/go.mod h1:LCzVGOaR6xXOjkQ3onu1FJEFr0SW1gC7cKk1uF8kGRs=
 | 
					golang.org/x/tools v0.0.0-20190311212946-11955173bddd/go.mod h1:LCzVGOaR6xXOjkQ3onu1FJEFr0SW1gC7cKk1uF8kGRs=
 | 
				
			||||||
golang.org/x/tools v0.0.0-20191119224855-298f0cb1881e/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo=
 | 
					golang.org/x/tools v0.0.0-20191119224855-298f0cb1881e/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo=
 | 
				
			||||||
| 
						 | 
					@ -419,35 +489,31 @@ golang.org/x/tools v0.0.0-20210106214847-113979e3529a/go.mod h1:emZCQorbCU4vsT4f
 | 
				
			||||||
golang.org/x/tools v0.1.5/go.mod h1:o0xws9oXOQQZyjljx8fwUC0k7L1pTE6eaCbjGeHmOkk=
 | 
					golang.org/x/tools v0.1.5/go.mod h1:o0xws9oXOQQZyjljx8fwUC0k7L1pTE6eaCbjGeHmOkk=
 | 
				
			||||||
golang.org/x/tools v0.1.12/go.mod h1:hNGJHUnrk76NpqgfD5Aqm5Crs+Hm0VOH/i9J2+nxYbc=
 | 
					golang.org/x/tools v0.1.12/go.mod h1:hNGJHUnrk76NpqgfD5Aqm5Crs+Hm0VOH/i9J2+nxYbc=
 | 
				
			||||||
golang.org/x/tools v0.6.0/go.mod h1:Xwgl3UAJ/d3gWutnCtw505GrjyAbvKui8lOU390QaIU=
 | 
					golang.org/x/tools v0.6.0/go.mod h1:Xwgl3UAJ/d3gWutnCtw505GrjyAbvKui8lOU390QaIU=
 | 
				
			||||||
golang.org/x/tools v0.13.0/go.mod h1:HvlwmtVNQAhOuCjW7xxvovg8wbNq7LwfXh/k7wXUl58=
 | 
					golang.org/x/tools v0.32.0 h1:Q7N1vhpkQv7ybVzLFtTjvQya2ewbwNDZzUgfXGqtMWU=
 | 
				
			||||||
golang.org/x/tools v0.21.1-0.20240508182429-e35e4ccd0d2d/go.mod h1:aiJjzUbINMkxbQROHiO6hDPo2LHcIPhhQsa9DLh0yGk=
 | 
					golang.org/x/tools v0.32.0/go.mod h1:ZxrU41P/wAbZD8EDa6dDCa6XfpkhJ7HFMjHJXfBDu8s=
 | 
				
			||||||
golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
 | 
					golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
 | 
				
			||||||
golang.org/x/xerrors v0.0.0-20191011141410-1b5146add898/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
 | 
					golang.org/x/xerrors v0.0.0-20191011141410-1b5146add898/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
 | 
				
			||||||
golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
 | 
					golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
 | 
				
			||||||
golang.org/x/xerrors v0.0.0-20200804184101-5ec99f83aff1/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
 | 
					golang.org/x/xerrors v0.0.0-20200804184101-5ec99f83aff1/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
 | 
				
			||||||
google.golang.org/appengine v1.1.0/go.mod h1:EbEs0AVv82hx2wNQdGPgUI5lhzA/G0D9YwlJXL52JkM=
 | 
					google.golang.org/genproto/googleapis/api v0.0.0-20250106144421-5f5ef82da422 h1:GVIKPyP/kLIyVOgOnTwFOrvQaQUzOzGMCxgFUOEmm24=
 | 
				
			||||||
google.golang.org/appengine v1.6.5/go.mod h1:8WjMMxjGQR8xUklV/ARdw2HLXBOI7O7uCIDZVag1xfc=
 | 
					google.golang.org/genproto/googleapis/api v0.0.0-20250106144421-5f5ef82da422/go.mod h1:b6h1vNKhxaSoEI+5jc3PJUCustfli/mRab7295pY7rw=
 | 
				
			||||||
google.golang.org/genproto/googleapis/api v0.0.0-20240903143218-8af14fe29dc1 h1:hjSy6tcFQZ171igDaN5QHOw2n6vx40juYbC/x67CEhc=
 | 
					google.golang.org/genproto/googleapis/rpc v0.0.0-20250414145226-207652e42e2e h1:ztQaXfzEXTmCBvbtWYRhJxW+0iJcz2qXfd38/e9l7bA=
 | 
				
			||||||
google.golang.org/genproto/googleapis/api v0.0.0-20240903143218-8af14fe29dc1/go.mod h1:qpvKtACPCQhAdu3PyQgV4l3LMXZEtft7y8QcarRsp9I=
 | 
					google.golang.org/genproto/googleapis/rpc v0.0.0-20250414145226-207652e42e2e/go.mod h1:qQ0YXyHHx3XkvlzUtpXDkS29lDSafHMZBAZDc03LQ3A=
 | 
				
			||||||
google.golang.org/genproto/googleapis/rpc v0.0.0-20240903143218-8af14fe29dc1 h1:pPJltXNxVzT4pK9yD8vR9X75DaWYYmLGMsEvBfFQZzQ=
 | 
					google.golang.org/grpc v1.71.1 h1:ffsFWr7ygTUscGPI0KKK6TLrGz0476KUvvsbqWK0rPI=
 | 
				
			||||||
google.golang.org/genproto/googleapis/rpc v0.0.0-20240903143218-8af14fe29dc1/go.mod h1:UqMtugtsSgubUsoxbuAoiCXvqvErP7Gf0so0mK9tHxU=
 | 
					google.golang.org/grpc v1.71.1/go.mod h1:H0GRtasmQOh9LkFoCPDu3ZrwUtD1YGE+b2vYBYd/8Ec=
 | 
				
			||||||
google.golang.org/grpc v1.68.0 h1:aHQeeJbo8zAkAa3pRzrVjZlbz6uSfeOXlJNQM0RAbz0=
 | 
					google.golang.org/protobuf v1.26.0-rc.1/go.mod h1:jlhhOSvTdKEhbULTjvd4ARK9grFBp09yW+WbY/TyQbw=
 | 
				
			||||||
google.golang.org/grpc v1.68.0/go.mod h1:fmSPC5AsjSBCK54MyHRx48kpOti1/jRfOlwEWywNjWA=
 | 
					google.golang.org/protobuf v1.27.1/go.mod h1:9q0QmTI4eRPtz6boOQmLYwt+qCgq0jsYwAQnmE0givc=
 | 
				
			||||||
google.golang.org/protobuf v1.35.2 h1:8Ar7bF+apOIoThw1EdZl0p1oWvMqTHmpA2fRTyZO8io=
 | 
					google.golang.org/protobuf v1.36.6 h1:z1NpPI8ku2WgiWnf+t9wTPsn6eP1L7ksHUlkfLvd9xY=
 | 
				
			||||||
google.golang.org/protobuf v1.35.2/go.mod h1:9fA7Ob0pmnwhb644+1+CVWFRbNajQ6iRojtC/QF5bRE=
 | 
					google.golang.org/protobuf v1.36.6/go.mod h1:jduwjTPXsFjZGTmRluh+L6NjiWu7pchiJ2/5YcXBHnY=
 | 
				
			||||||
gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
 | 
					gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
 | 
				
			||||||
gopkg.in/check.v1 v1.0.0-20180628173108-788fd7840127/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
 | 
					gopkg.in/check.v1 v1.0.0-20180628173108-788fd7840127/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
 | 
				
			||||||
gopkg.in/check.v1 v1.0.0-20190902080502-41f04d3bba15/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
 | 
					gopkg.in/check.v1 v1.0.0-20200227125254-8fa46927fb4f h1:BLraFXnmrev5lT+xlilqcH8XK9/i0At2xKjWk4p6zsU=
 | 
				
			||||||
gopkg.in/check.v1 v1.0.0-20200227125254-8fa46927fb4f/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
 | 
					gopkg.in/check.v1 v1.0.0-20200227125254-8fa46927fb4f/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
 | 
				
			||||||
gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c h1:Hei/4ADfdWqJk1ZMxUNpqntNwaWcugrBjAiHlqqRiVk=
 | 
					 | 
				
			||||||
gopkg.in/check.v1 v1.0.0-20201130134442-10cb98267c6c/go.mod h1:JHkPIbrfpd72SG/EVd6muEfDQjcINNoR0C8j2r3qZ4Q=
 | 
					 | 
				
			||||||
gopkg.in/errgo.v2 v2.1.0/go.mod h1:hNsd1EY+bozCKY1Ytp96fpM3vjJbqLJn88ws8XvfDNI=
 | 
					 | 
				
			||||||
gopkg.in/ini.v1 v1.67.0 h1:Dgnx+6+nfE+IfzjUEISNeydPJh9AXNNsWbGP9KzCsOA=
 | 
					gopkg.in/ini.v1 v1.67.0 h1:Dgnx+6+nfE+IfzjUEISNeydPJh9AXNNsWbGP9KzCsOA=
 | 
				
			||||||
gopkg.in/ini.v1 v1.67.0/go.mod h1:pNLf8WUiyNEtQjuu5G5vTm06TEv9tsIgeAvK8hOrP4k=
 | 
					gopkg.in/ini.v1 v1.67.0/go.mod h1:pNLf8WUiyNEtQjuu5G5vTm06TEv9tsIgeAvK8hOrP4k=
 | 
				
			||||||
gopkg.in/mgo.v2 v2.0.0-20190816093944-a6b53ec6cb22 h1:VpOs+IwYnYBaFnrNAeB8UUWtL3vEUnzSCL1nVjPhqrw=
 | 
					gopkg.in/mgo.v2 v2.0.0-20190816093944-a6b53ec6cb22 h1:VpOs+IwYnYBaFnrNAeB8UUWtL3vEUnzSCL1nVjPhqrw=
 | 
				
			||||||
gopkg.in/mgo.v2 v2.0.0-20190816093944-a6b53ec6cb22/go.mod h1:yeKp02qBN3iKW1OzL3MGk2IdtZzaj7SFntXj72NppTA=
 | 
					gopkg.in/mgo.v2 v2.0.0-20190816093944-a6b53ec6cb22/go.mod h1:yeKp02qBN3iKW1OzL3MGk2IdtZzaj7SFntXj72NppTA=
 | 
				
			||||||
gopkg.in/yaml.v2 v2.2.2/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
 | 
					gopkg.in/yaml.v2 v2.2.2/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
 | 
				
			||||||
gopkg.in/yaml.v2 v2.2.4/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
 | 
					 | 
				
			||||||
gopkg.in/yaml.v2 v2.2.8/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
 | 
					gopkg.in/yaml.v2 v2.2.8/go.mod h1:hI93XBmqTisBFMUTm0b8Fm+jr3Dg1NNxqwp+5A1VGuI=
 | 
				
			||||||
gopkg.in/yaml.v2 v2.4.0 h1:D8xgwECY7CYvx+Y2n4sBz93Jn9JRvxdiyyo8CTfuKaY=
 | 
					gopkg.in/yaml.v2 v2.4.0 h1:D8xgwECY7CYvx+Y2n4sBz93Jn9JRvxdiyyo8CTfuKaY=
 | 
				
			||||||
gopkg.in/yaml.v2 v2.4.0/go.mod h1:RDklbk79AGWmwhnvt/jBztapEOGDOx6ZbXqjP6csGnQ=
 | 
					gopkg.in/yaml.v2 v2.4.0/go.mod h1:RDklbk79AGWmwhnvt/jBztapEOGDOx6ZbXqjP6csGnQ=
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -0,0 +1,32 @@
 | 
				
			||||||
 | 
					package protected
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					import (
 | 
				
			||||||
 | 
						"net/http"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						"git.coopgo.io/coopgo-apps/parcoursmob/services"
 | 
				
			||||||
 | 
						"git.coopgo.io/coopgo-apps/parcoursmob/utils/identification"
 | 
				
			||||||
 | 
						cache "git.coopgo.io/coopgo-apps/parcoursmob/utils/storage"
 | 
				
			||||||
 | 
						"github.com/spf13/viper"
 | 
				
			||||||
 | 
					)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					type ProtectedAPIHandler struct {
 | 
				
			||||||
 | 
						ApiKey   string
 | 
				
			||||||
 | 
						idp      *identification.IdentificationProvider
 | 
				
			||||||
 | 
						config   *viper.Viper
 | 
				
			||||||
 | 
						services *services.ServicesHandler
 | 
				
			||||||
 | 
						cache    cache.CacheHandler
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					func NewProtectedAPIHandler(cfg *viper.Viper, idp *identification.IdentificationProvider, svc *services.ServicesHandler, cache cache.CacheHandler) (*ProtectedAPIHandler, error) {
 | 
				
			||||||
 | 
						return &ProtectedAPIHandler{
 | 
				
			||||||
 | 
							ApiKey:   cfg.GetString("services.api.api_key"),
 | 
				
			||||||
 | 
							idp:      idp,
 | 
				
			||||||
 | 
							config:   cfg,
 | 
				
			||||||
 | 
							services: svc,
 | 
				
			||||||
 | 
							cache:    cache,
 | 
				
			||||||
 | 
						}, nil
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					func (h *ProtectedAPIHandler) NotFound(w http.ResponseWriter, r *http.Request) {
 | 
				
			||||||
 | 
						w.WriteHeader(http.StatusNotFound)
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
| 
						 | 
					@ -0,0 +1,65 @@
 | 
				
			||||||
 | 
					package protected
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					import (
 | 
				
			||||||
 | 
						"context"
 | 
				
			||||||
 | 
						"encoding/json"
 | 
				
			||||||
 | 
						"net/http"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						groupsgrpc "git.coopgo.io/coopgo-platform/groups-management/grpcapi"
 | 
				
			||||||
 | 
						"git.coopgo.io/coopgo-platform/mobility-accounts/grpcapi"
 | 
				
			||||||
 | 
						"git.coopgo.io/coopgo-platform/mobility-accounts/storage"
 | 
				
			||||||
 | 
						"github.com/rs/zerolog/log"
 | 
				
			||||||
 | 
					)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					func (h *ProtectedAPIHandler) Users(w http.ResponseWriter, r *http.Request) {
 | 
				
			||||||
 | 
						if r.Method == "POST" {
 | 
				
			||||||
 | 
							h.postUsers(w, r)
 | 
				
			||||||
 | 
							return
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						w.WriteHeader(http.StatusMethodNotAllowed)
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					func (h *ProtectedAPIHandler) postUsers(w http.ResponseWriter, r *http.Request) {
 | 
				
			||||||
 | 
						var user storage.Account
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						decoder := json.NewDecoder(r.Body)
 | 
				
			||||||
 | 
						err := decoder.Decode(&user)
 | 
				
			||||||
 | 
						if err != nil {
 | 
				
			||||||
 | 
							log.Error().Err(err).Msg("could not read account input")
 | 
				
			||||||
 | 
							w.WriteHeader(http.StatusBadRequest)
 | 
				
			||||||
 | 
							return
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						account, err := grpcapi.AccountFromStorageType(&user)
 | 
				
			||||||
 | 
						if err != nil {
 | 
				
			||||||
 | 
							log.Error().Err(err).Msg("could not generate protobuf for account")
 | 
				
			||||||
 | 
							w.WriteHeader(http.StatusBadRequest)
 | 
				
			||||||
 | 
							return
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						resp, err := h.services.GRPC.MobilityAccounts.Register(context.Background(), &grpcapi.RegisterRequest{
 | 
				
			||||||
 | 
							Account: account,
 | 
				
			||||||
 | 
						})
 | 
				
			||||||
 | 
						if err != nil {
 | 
				
			||||||
 | 
							log.Error().Err(err).Msg("grpc request issue")
 | 
				
			||||||
 | 
							w.WriteHeader(http.StatusInternalServerError)
 | 
				
			||||||
 | 
							return
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						if g, ok := user.Metadata["import_in_group"]; ok {
 | 
				
			||||||
 | 
							if group, ok := g.(string); ok {
 | 
				
			||||||
 | 
								_, err = h.services.GRPC.GroupsManagement.Subscribe(context.Background(), &groupsgrpc.SubscribeRequest{
 | 
				
			||||||
 | 
									Groupid:  group,
 | 
				
			||||||
 | 
									Memberid: resp.Account.Id,
 | 
				
			||||||
 | 
								})
 | 
				
			||||||
 | 
								if err != nil {
 | 
				
			||||||
 | 
									log.Error().Err(err).Msg("grpc request issue, groups")
 | 
				
			||||||
 | 
									w.WriteHeader(http.StatusInternalServerError)
 | 
				
			||||||
 | 
									return
 | 
				
			||||||
 | 
								}
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						w.WriteHeader(http.StatusOK)
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
| 
						 | 
					@ -25,7 +25,7 @@ type ApplicationHandler struct {
 | 
				
			||||||
 | 
					
 | 
				
			||||||
func NewApplicationHandler(cfg *viper.Viper, svc *services.ServicesHandler, cache cache.CacheHandler, filestorage cache.FileStorage, emailing *emailing.Mailer) (*ApplicationHandler, error) {
 | 
					func NewApplicationHandler(cfg *viper.Viper, svc *services.ServicesHandler, cache cache.CacheHandler, filestorage cache.FileStorage, emailing *emailing.Mailer) (*ApplicationHandler, error) {
 | 
				
			||||||
	templates_root := cfg.GetString("templates.root")
 | 
						templates_root := cfg.GetString("templates.root")
 | 
				
			||||||
	renderer := renderer.NewRenderer(cfg, templates_root)
 | 
						renderer := renderer.NewRenderer(cfg, templates_root, filestorage)
 | 
				
			||||||
	return &ApplicationHandler{
 | 
						return &ApplicationHandler{
 | 
				
			||||||
		config:      cfg,
 | 
							config:      cfg,
 | 
				
			||||||
		Renderer:    renderer,
 | 
							Renderer:    renderer,
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -28,21 +28,25 @@ import (
 | 
				
			||||||
	"git.coopgo.io/coopgo-platform/groups-management/storage"
 | 
						"git.coopgo.io/coopgo-platform/groups-management/storage"
 | 
				
			||||||
	mobilityaccounts "git.coopgo.io/coopgo-platform/mobility-accounts/grpcapi"
 | 
						mobilityaccounts "git.coopgo.io/coopgo-platform/mobility-accounts/grpcapi"
 | 
				
			||||||
	mobilityaccountsstorage "git.coopgo.io/coopgo-platform/mobility-accounts/storage"
 | 
						mobilityaccountsstorage "git.coopgo.io/coopgo-platform/mobility-accounts/storage"
 | 
				
			||||||
 | 
						"git.coopgo.io/coopgo-platform/solidarity-transport/servers/grpc/proto/gen"
 | 
				
			||||||
 | 
						"git.coopgo.io/coopgo-platform/solidarity-transport/servers/grpc/transformers"
 | 
				
			||||||
	"github.com/google/uuid"
 | 
						"github.com/google/uuid"
 | 
				
			||||||
	"github.com/gorilla/mux"
 | 
						"github.com/gorilla/mux"
 | 
				
			||||||
	"github.com/rs/zerolog/log"
 | 
						"github.com/rs/zerolog/log"
 | 
				
			||||||
	"google.golang.org/protobuf/types/known/structpb"
 | 
						"google.golang.org/protobuf/types/known/structpb"
 | 
				
			||||||
 | 
						"google.golang.org/protobuf/types/known/timestamppb"
 | 
				
			||||||
)
 | 
					)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
type BeneficiariesForm struct {
 | 
					type BeneficiariesForm struct {
 | 
				
			||||||
	FirstName   string     `json:"first_name" validate:"required"`
 | 
						FirstName       string     `json:"first_name" validate:"required"`
 | 
				
			||||||
	LastName    string     `json:"last_name" validate:"required"`
 | 
						LastName        string     `json:"last_name" validate:"required"`
 | 
				
			||||||
	Email       string     `json:"email" validate:"required,email"`
 | 
						Email           string     `json:"email" validate:"required,email"`
 | 
				
			||||||
	Birthdate   *time.Time `json:"birthdate" validate:"required"`
 | 
						Birthdate       *time.Time `json:"birthdate" validate:"required"`
 | 
				
			||||||
	PhoneNumber string     `json:"phone_number" validate:"required,phoneNumber"`
 | 
						PhoneNumber     string     `json:"phone_number" validate:"required,phoneNumber"`
 | 
				
			||||||
	FileNumber  string     `json:"file_number"`
 | 
						FileNumber      string     `json:"file_number"`
 | 
				
			||||||
	Address     any        `json:"address,omitempty"`
 | 
						Address         any        `json:"address,omitempty"`
 | 
				
			||||||
	Gender      string     `json:"gender"`
 | 
						Gender          string     `json:"gender"`
 | 
				
			||||||
 | 
						OtherProperties any        `json:"other_properties,omitempty"`
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
type Event_Beneficiary interface {
 | 
					type Event_Beneficiary interface {
 | 
				
			||||||
| 
						 | 
					@ -192,7 +196,7 @@ func (h *ApplicationHandler) BeneficiaryDisplay(w http.ResponseWriter, r *http.R
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	resp, err := h.services.GRPC.MobilityAccounts.GetAccount(context.TODO(), request)
 | 
						resp, err := h.services.GRPC.MobilityAccounts.GetAccount(context.TODO(), request)
 | 
				
			||||||
	if err != nil {
 | 
						if err != nil {
 | 
				
			||||||
		log.Error().Err(err).Msg("")
 | 
							log.Error().Err(err).Msg("cannot retrieve account")
 | 
				
			||||||
		w.WriteHeader(http.StatusInternalServerError)
 | 
							w.WriteHeader(http.StatusInternalServerError)
 | 
				
			||||||
		return
 | 
							return
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
| 
						 | 
					@ -305,6 +309,34 @@ func (h *ApplicationHandler) BeneficiaryDisplay(w http.ResponseWriter, r *http.R
 | 
				
			||||||
			events_list = append(events_list, event)
 | 
								events_list = append(events_list, event)
 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
						solidarity, err := h.services.GRPC.SolidarityTransport.GetSolidarityTransportBookings(context.Background(), &gen.GetSolidarityTransportBookingsRequest{
 | 
				
			||||||
 | 
							Passengerid: beneficiaryID,
 | 
				
			||||||
 | 
							StartDate:   timestamppb.New(time.Now().Add(-36 * 730 * time.Hour)),
 | 
				
			||||||
 | 
							EndDate:     timestamppb.New(time.Now().Add(12 * 730 * time.Hour)),
 | 
				
			||||||
 | 
						})
 | 
				
			||||||
 | 
						solidarityTransportStats := map[string]int64{
 | 
				
			||||||
 | 
							"count": 0,
 | 
				
			||||||
 | 
							"km":    0,
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						for _, s := range solidarity.Bookings {
 | 
				
			||||||
 | 
							b, _ := transformers.BookingProtoToType(s)
 | 
				
			||||||
 | 
							event := Event{
 | 
				
			||||||
 | 
								NameVal:    fmt.Sprintf("%s (%d km)", b.Journey.PassengerDrop.Properties.MustString("label", ""), b.Journey.PassengerDistance),
 | 
				
			||||||
 | 
								DateVal:    b.Journey.PassengerPickupDate,
 | 
				
			||||||
 | 
								DateEndVal: b.Journey.PassengerPickupDate,
 | 
				
			||||||
 | 
								TypeVal:    "Transport solidaire",
 | 
				
			||||||
 | 
								IDVal:      b.Id,
 | 
				
			||||||
 | 
								DbVal:      "/app/solidarity-transport/bookings/",
 | 
				
			||||||
 | 
								IconSet:    "vehicle",
 | 
				
			||||||
 | 
								StatusVal:  1,
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							events_list = append(events_list, event)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							solidarityTransportStats["count"] = solidarityTransportStats["count"] + 1
 | 
				
			||||||
 | 
							solidarityTransportStats["km"] = solidarityTransportStats["km"] + b.Journey.PassengerDistance
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
	sortByDate(events_list)
 | 
						sortByDate(events_list)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	diag := []diagsstorage.Diag{}
 | 
						diag := []diagsstorage.Diag{}
 | 
				
			||||||
| 
						 | 
					@ -349,7 +381,7 @@ func (h *ApplicationHandler) BeneficiaryDisplay(w http.ResponseWriter, r *http.R
 | 
				
			||||||
	for i, d := range diag {
 | 
						for i, d := range diag {
 | 
				
			||||||
		diagsAny[i] = d
 | 
							diagsAny[i] = d
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
	h.Renderer.BeneficiaryDisplay(w, r, resp.Account.ToStorageType(), bookings, organizations, beneficiaries_file_types, file_types_map, documents, events_list, diagsAny)
 | 
						h.Renderer.BeneficiaryDisplay(w, r, resp.Account.ToStorageType(), bookings, organizations, beneficiaries_file_types, file_types_map, documents, events_list, diagsAny, solidarityTransportStats)
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
func (h *ApplicationHandler) BeneficiaryUpdate(w http.ResponseWriter, r *http.Request) {
 | 
					func (h *ApplicationHandler) BeneficiaryUpdate(w http.ResponseWriter, r *http.Request) {
 | 
				
			||||||
| 
						 | 
					@ -409,6 +441,58 @@ func (h *ApplicationHandler) BeneficiaryUpdate(w http.ResponseWriter, r *http.Re
 | 
				
			||||||
	h.Renderer.BeneficiaryUpdate(w, r, resp.Account.ToStorageType())
 | 
						h.Renderer.BeneficiaryUpdate(w, r, resp.Account.ToStorageType())
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					func (h *ApplicationHandler) BeneficiaryArchive(w http.ResponseWriter, r *http.Request) {
 | 
				
			||||||
 | 
						vars := mux.Vars(r)
 | 
				
			||||||
 | 
						beneficiaryID := vars["beneficiaryid"]
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						data, err := structpb.NewValue(map[string]any{
 | 
				
			||||||
 | 
							"archived": true,
 | 
				
			||||||
 | 
						})
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						request := &mobilityaccounts.UpdateDataRequest{
 | 
				
			||||||
 | 
							Account: &mobilityaccounts.Account{
 | 
				
			||||||
 | 
								Id:        beneficiaryID,
 | 
				
			||||||
 | 
								Namespace: "parcoursmob_beneficiaries",
 | 
				
			||||||
 | 
								Data:      data.GetStructValue(),
 | 
				
			||||||
 | 
							},
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						resp, err := h.services.GRPC.MobilityAccounts.UpdateData(context.TODO(), request)
 | 
				
			||||||
 | 
						if err != nil {
 | 
				
			||||||
 | 
							log.Error().Err(err).Msg("")
 | 
				
			||||||
 | 
							w.WriteHeader(http.StatusInternalServerError)
 | 
				
			||||||
 | 
							return
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						http.Redirect(w, r, fmt.Sprintf("/app/beneficiaries/%s", resp.Account.Id), http.StatusFound)
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					func (h *ApplicationHandler) BeneficiaryUnarchive(w http.ResponseWriter, r *http.Request) {
 | 
				
			||||||
 | 
						vars := mux.Vars(r)
 | 
				
			||||||
 | 
						beneficiaryID := vars["beneficiaryid"]
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						data, err := structpb.NewValue(map[string]any{
 | 
				
			||||||
 | 
							"archived": false,
 | 
				
			||||||
 | 
						})
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						request := &mobilityaccounts.UpdateDataRequest{
 | 
				
			||||||
 | 
							Account: &mobilityaccounts.Account{
 | 
				
			||||||
 | 
								Id:        beneficiaryID,
 | 
				
			||||||
 | 
								Namespace: "parcoursmob_beneficiaries",
 | 
				
			||||||
 | 
								Data:      data.GetStructValue(),
 | 
				
			||||||
 | 
							},
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						resp, err := h.services.GRPC.MobilityAccounts.UpdateData(context.TODO(), request)
 | 
				
			||||||
 | 
						if err != nil {
 | 
				
			||||||
 | 
							log.Error().Err(err).Msg("")
 | 
				
			||||||
 | 
							w.WriteHeader(http.StatusInternalServerError)
 | 
				
			||||||
 | 
							return
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						http.Redirect(w, r, fmt.Sprintf("/app/beneficiaries/%s", resp.Account.Id), http.StatusFound)
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
func (h *ApplicationHandler) BeneficiaryPicture(w http.ResponseWriter, r *http.Request) {
 | 
					func (h *ApplicationHandler) BeneficiaryPicture(w http.ResponseWriter, r *http.Request) {
 | 
				
			||||||
	vars := mux.Vars(r)
 | 
						vars := mux.Vars(r)
 | 
				
			||||||
	beneficiaryID := vars["beneficiaryid"]
 | 
						beneficiaryID := vars["beneficiaryid"]
 | 
				
			||||||
| 
						 | 
					@ -496,7 +580,7 @@ func (h *ApplicationHandler) BeneficiaryDocumentDownload(w http.ResponseWriter,
 | 
				
			||||||
		return
 | 
							return
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	http.Redirect(w, r, fmt.Sprintf("/app/beneficiaries/%s", beneficiaryID), http.StatusFound)
 | 
						// http.Redirect(w, r, fmt.Sprintf("/app/beneficiaries/%s", beneficiaryID), http.StatusFound)
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
func filterAccount(r *http.Request, a *mobilityaccounts.Account) bool {
 | 
					func filterAccount(r *http.Request, a *mobilityaccounts.Account) bool {
 | 
				
			||||||
| 
						 | 
					@ -509,6 +593,18 @@ func filterAccount(r *http.Request, a *mobilityaccounts.Account) bool {
 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						archivedFilter, ok := r.URL.Query()["archived"]
 | 
				
			||||||
 | 
						if ok && archivedFilter[0] == "true" {
 | 
				
			||||||
 | 
							if archived, ok := a.Data.AsMap()["archived"].(bool); ok && archived {
 | 
				
			||||||
 | 
								return true
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
							return false
 | 
				
			||||||
 | 
						} else {
 | 
				
			||||||
 | 
							if archived, ok := a.Data.AsMap()["archived"].(bool); ok && archived {
 | 
				
			||||||
 | 
								return false
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	return true
 | 
						return true
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					@ -529,6 +625,7 @@ func (h *ApplicationHandler) beneficiaries(r *http.Request) ([]mobilityaccountss
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	resp, err := h.services.GRPC.MobilityAccounts.GetAccountsBatch(context.TODO(), request)
 | 
						resp, err := h.services.GRPC.MobilityAccounts.GetAccountsBatch(context.TODO(), request)
 | 
				
			||||||
	if err != nil {
 | 
						if err != nil {
 | 
				
			||||||
 | 
							log.Error().Err(err).Msg("issue in mobilityaccounts call")
 | 
				
			||||||
		return accounts, err
 | 
							return accounts, err
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					@ -566,6 +663,7 @@ func parseBeneficiariesForm(r *http.Request) (map[string]any, error) {
 | 
				
			||||||
		FileNumber:  r.PostFormValue("file_number"),
 | 
							FileNumber:  r.PostFormValue("file_number"),
 | 
				
			||||||
		Gender:      r.PostFormValue("gender"),
 | 
							Gender:      r.PostFormValue("gender"),
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
						log.Trace().Any("address", r.PostFormValue("address")).Msg("address")
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	if r.PostFormValue("address") != "" {
 | 
						if r.PostFormValue("address") != "" {
 | 
				
			||||||
		var a any
 | 
							var a any
 | 
				
			||||||
| 
						 | 
					@ -574,6 +672,15 @@ func parseBeneficiariesForm(r *http.Request) (map[string]any, error) {
 | 
				
			||||||
		formData.Address = a
 | 
							formData.Address = a
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						log.Trace().Any("otther properties", r.PostFormValue("other_properties")).Msg("other propperties ?")
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						if r.PostFormValue("other_properties") != "" {
 | 
				
			||||||
 | 
							var a any
 | 
				
			||||||
 | 
							json.Unmarshal([]byte(r.PostFormValue("other_properties")), &a)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							formData.OtherProperties = a
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	validate := formvalidators.New()
 | 
						validate := formvalidators.New()
 | 
				
			||||||
	if err := validate.Struct(formData); err != nil {
 | 
						if err := validate.Struct(formData); err != nil {
 | 
				
			||||||
		return nil, err
 | 
							return nil, err
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -5,6 +5,7 @@ import (
 | 
				
			||||||
	"fmt"
 | 
						"fmt"
 | 
				
			||||||
	"net/http"
 | 
						"net/http"
 | 
				
			||||||
	"sort"
 | 
						"sort"
 | 
				
			||||||
 | 
						"time"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	"git.coopgo.io/coopgo-apps/parcoursmob/utils/identification"
 | 
						"git.coopgo.io/coopgo-apps/parcoursmob/utils/identification"
 | 
				
			||||||
	"git.coopgo.io/coopgo-apps/parcoursmob/utils/sorting"
 | 
						"git.coopgo.io/coopgo-apps/parcoursmob/utils/sorting"
 | 
				
			||||||
| 
						 | 
					@ -87,7 +88,9 @@ func (h *ApplicationHandler) Dashboard(w http.ResponseWriter, r *http.Request) {
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	if err == nil {
 | 
						if err == nil {
 | 
				
			||||||
		for _, b := range bookingsresp.Bookings {
 | 
							for _, b := range bookingsresp.Bookings {
 | 
				
			||||||
			bookings = append(bookings, b.ToStorageType())
 | 
								if b.Enddate.AsTime().After(time.Now()) {
 | 
				
			||||||
 | 
									bookings = append(bookings, b.ToStorageType())
 | 
				
			||||||
 | 
								}
 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -5,23 +5,33 @@ import (
 | 
				
			||||||
	"encoding/json"
 | 
						"encoding/json"
 | 
				
			||||||
	"fmt"
 | 
						"fmt"
 | 
				
			||||||
	"net/http"
 | 
						"net/http"
 | 
				
			||||||
 | 
						"slices"
 | 
				
			||||||
	"sort"
 | 
						"sort"
 | 
				
			||||||
	"strconv"
 | 
						"strconv"
 | 
				
			||||||
	"strings"
 | 
						"strings"
 | 
				
			||||||
 | 
						"sync"
 | 
				
			||||||
	"time"
 | 
						"time"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						"git.coopgo.io/coopgo-apps/parcoursmob/utils/sorting"
 | 
				
			||||||
 | 
						carpoolproto "git.coopgo.io/coopgo-platform/carpool-service/servers/grpc/proto"
 | 
				
			||||||
	fleets "git.coopgo.io/coopgo-platform/fleets/grpcapi"
 | 
						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"
 | 
						groupsmanagement "git.coopgo.io/coopgo-platform/groups-management/grpcapi"
 | 
				
			||||||
	groupstorage "git.coopgo.io/coopgo-platform/groups-management/storage"
 | 
						groupstorage "git.coopgo.io/coopgo-platform/groups-management/storage"
 | 
				
			||||||
	mobilityaccounts "git.coopgo.io/coopgo-platform/mobility-accounts/grpcapi"
 | 
						mobilityaccounts "git.coopgo.io/coopgo-platform/mobility-accounts/grpcapi"
 | 
				
			||||||
	mobilityaccountsstorage "git.coopgo.io/coopgo-platform/mobility-accounts/storage"
 | 
						mobilityaccountsstorage "git.coopgo.io/coopgo-platform/mobility-accounts/storage"
 | 
				
			||||||
 | 
						"git.coopgo.io/coopgo-platform/multimodal-routing/libs/transit/motis"
 | 
				
			||||||
 | 
						"git.coopgo.io/coopgo-platform/solidarity-transport/servers/grpc/proto/gen"
 | 
				
			||||||
 | 
						"git.coopgo.io/coopgo-platform/solidarity-transport/servers/grpc/transformers"
 | 
				
			||||||
	"github.com/google/uuid"
 | 
						"github.com/google/uuid"
 | 
				
			||||||
	"github.com/gorilla/mux"
 | 
						"github.com/gorilla/mux"
 | 
				
			||||||
	geojson "github.com/paulmach/go.geojson"
 | 
						"github.com/paulmach/orb/geojson"
 | 
				
			||||||
	"github.com/rs/zerolog/log"
 | 
						"github.com/rs/zerolog/log"
 | 
				
			||||||
	"gitlab.scity.coop/maas/navitia-golang"
 | 
					
 | 
				
			||||||
	"gitlab.scity.coop/maas/navitia-golang/types"
 | 
						//"gitlab.scity.coop/maas/navitia-golang"
 | 
				
			||||||
 | 
						//"gitlab.scity.coop/maas/navitia-golang/types"
 | 
				
			||||||
	"google.golang.org/protobuf/types/known/structpb"
 | 
						"google.golang.org/protobuf/types/known/structpb"
 | 
				
			||||||
 | 
						"google.golang.org/protobuf/types/known/timestamppb"
 | 
				
			||||||
)
 | 
					)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
var (
 | 
					var (
 | 
				
			||||||
| 
						 | 
					@ -32,14 +42,16 @@ var (
 | 
				
			||||||
func (h *ApplicationHandler) JourneysSearch(w http.ResponseWriter, r *http.Request) {
 | 
					func (h *ApplicationHandler) JourneysSearch(w http.ResponseWriter, r *http.Request) {
 | 
				
			||||||
	r.ParseForm()
 | 
						r.ParseForm()
 | 
				
			||||||
	var (
 | 
						var (
 | 
				
			||||||
		journeys_results *navitia.JourneyResults
 | 
							transit_results []*motis.Itinerary
 | 
				
			||||||
		carpool_results  any
 | 
							carpool_results []*geojson.FeatureCollection
 | 
				
			||||||
		vehicle_results  []any
 | 
							vehicle_results []fleetsstorage.Vehicle
 | 
				
			||||||
	)
 | 
						)
 | 
				
			||||||
	availableDrivers := []mobilityaccountsstorage.Account{}
 | 
						// availableDrivers := []mobilityaccountsstorage.Account{}
 | 
				
			||||||
	vehiclech := make(chan []any, 1)
 | 
						drivers := map[string]mobilityaccountsstorage.Account{}
 | 
				
			||||||
	navitiaCh := make(chan *navitia.JourneyResults, 1)
 | 
						driverJourneys := []*gen.SolidarityTransportDriverJourney{}
 | 
				
			||||||
	carpoolCh := make(chan any, 1)
 | 
						var organizedCarpools []*carpoolproto.CarpoolServiceDriverJourney
 | 
				
			||||||
 | 
						// navitiaCh := make(chan *navitia.JourneyResults, 1)
 | 
				
			||||||
 | 
						// carpoolCh := make(chan []any, 1)
 | 
				
			||||||
	locTime, errTime := time.LoadLocation("Europe/Paris")
 | 
						locTime, errTime := time.LoadLocation("Europe/Paris")
 | 
				
			||||||
	if errTime != nil {
 | 
						if errTime != nil {
 | 
				
			||||||
		log.Panic().Err(errTime).Msg("Tried to load timezone location Europe/Paris. Error. Missing zones in container ?")
 | 
							log.Panic().Err(errTime).Msg("Tried to load timezone location Europe/Paris. Error. Missing zones in container ?")
 | 
				
			||||||
| 
						 | 
					@ -51,15 +63,15 @@ func (h *ApplicationHandler) JourneysSearch(w http.ResponseWriter, r *http.Reque
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	departure := r.FormValue("departure")
 | 
						departure := r.FormValue("departure")
 | 
				
			||||||
	destination := r.FormValue("destination")
 | 
						destination := r.FormValue("destination")
 | 
				
			||||||
 | 
						kb_results := []any{}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	searched := false
 | 
						searched := false
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	var (
 | 
						var (
 | 
				
			||||||
		departuregeo   *geojson.Feature
 | 
							departuregeo   *geojson.Feature
 | 
				
			||||||
		destinationgeo *geojson.Feature
 | 
							destinationgeo *geojson.Feature
 | 
				
			||||||
		journeys       *navitia.JourneyResults
 | 
							// journeys       *navitia.JourneyResults
 | 
				
			||||||
		carpoolresults any
 | 
							// carpoolresults []any
 | 
				
			||||||
		vehicles       = []any{}
 | 
					 | 
				
			||||||
	)
 | 
						)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	if departuredate != "" && departuretime != "" && departure != "" && destination != "" {
 | 
						if departuredate != "" && departuretime != "" && departure != "" && destination != "" {
 | 
				
			||||||
| 
						 | 
					@ -69,132 +81,191 @@ func (h *ApplicationHandler) JourneysSearch(w http.ResponseWriter, r *http.Reque
 | 
				
			||||||
 | 
					
 | 
				
			||||||
		departuregeo, err = geojson.UnmarshalFeature([]byte(departure))
 | 
							departuregeo, err = geojson.UnmarshalFeature([]byte(departure))
 | 
				
			||||||
		if err != nil {
 | 
							if err != nil {
 | 
				
			||||||
			log.Error().Err(err).Msg("")
 | 
								log.Error().Err(err).Msg("error unmarshalling departure")
 | 
				
			||||||
			w.WriteHeader(http.StatusBadRequest)
 | 
								w.WriteHeader(http.StatusBadRequest)
 | 
				
			||||||
			return
 | 
								return
 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
		destinationgeo, err = geojson.UnmarshalFeature([]byte(destination))
 | 
							destinationgeo, err = geojson.UnmarshalFeature([]byte(destination))
 | 
				
			||||||
		if err != nil {
 | 
							if err != nil {
 | 
				
			||||||
			log.Error().Err(err).Msg("")
 | 
								log.Error().Err(err).Msg("error unmarshalling destination")
 | 
				
			||||||
			w.WriteHeader(http.StatusBadRequest)
 | 
								w.WriteHeader(http.StatusBadRequest)
 | 
				
			||||||
			return
 | 
								return
 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
		////////////////////////////////////////////////////////////////////////////////////////////////////////////////
 | 
					
 | 
				
			||||||
		journeysRequest := func() {
 | 
							// SOLIDARITY TRANSPORT
 | 
				
			||||||
			// TODO make it a library
 | 
							drivers, err = h.services.GetAccountsInNamespacesMap([]string{"solidarity_drivers", "organized_carpool_drivers"})
 | 
				
			||||||
			session, _ := navitia.NewCustom(
 | 
							if err != nil {
 | 
				
			||||||
				h.config.GetString("services.navitia.api_key"),
 | 
								drivers = map[string]mobilityaccountsstorage.Account{}
 | 
				
			||||||
				"https://api.navitia.io/v1",
 | 
							}
 | 
				
			||||||
				&http.Client{})
 | 
					
 | 
				
			||||||
 | 
							protodep, _ := transformers.GeoJsonToProto(departuregeo)
 | 
				
			||||||
 | 
							protodest, _ := transformers.GeoJsonToProto(destinationgeo)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							log.Debug().Time("departure time", departuredatetime).Msg("calling driver journeys with ...")
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							res, err := h.services.GRPC.SolidarityTransport.GetDriverJourneys(context.Background(), &gen.GetDriverJourneysRequest{
 | 
				
			||||||
 | 
								Departure:     protodep,
 | 
				
			||||||
 | 
								Arrival:       protodest,
 | 
				
			||||||
 | 
								DepartureDate: timestamppb.New(departuredatetime),
 | 
				
			||||||
 | 
							})
 | 
				
			||||||
 | 
							if err != nil {
 | 
				
			||||||
 | 
								log.Error().Err(err).Msg("error in grpc call to GetDriverJourneys")
 | 
				
			||||||
 | 
							} else {
 | 
				
			||||||
 | 
								driverJourneys = slices.Collect(func(yield func(*gen.SolidarityTransportDriverJourney) bool) {
 | 
				
			||||||
 | 
									for _, dj := range res.DriverJourneys {
 | 
				
			||||||
 | 
										if a, ok := drivers[dj.DriverId].Data["archived"]; ok {
 | 
				
			||||||
 | 
											if archived, ok := a.(bool); ok {
 | 
				
			||||||
 | 
												if archived {
 | 
				
			||||||
 | 
													continue
 | 
				
			||||||
 | 
												}
 | 
				
			||||||
 | 
											}
 | 
				
			||||||
 | 
										}
 | 
				
			||||||
 | 
										if !yield(dj) {
 | 
				
			||||||
 | 
											return
 | 
				
			||||||
 | 
										}
 | 
				
			||||||
 | 
									}
 | 
				
			||||||
 | 
								})
 | 
				
			||||||
 | 
								// res.DriverJourneys
 | 
				
			||||||
 | 
								sort.Slice(driverJourneys, func(i, j int) bool {
 | 
				
			||||||
 | 
									return driverJourneys[i].DriverDistance < driverJourneys[j].DriverDistance
 | 
				
			||||||
 | 
								})
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							// ORGANIZED CARPOOL
 | 
				
			||||||
 | 
							organizedCarpoolsRes, err := h.services.GRPC.CarpoolService.DriverJourneys(context.Background(), &carpoolproto.DriverJourneysRequest{
 | 
				
			||||||
 | 
								DepartureLat:  departuregeo.Point().Lat(),
 | 
				
			||||||
 | 
								DepartureLng:  departuregeo.Point().Lon(),
 | 
				
			||||||
 | 
								ArrivalLat:    destinationgeo.Point().Lat(),
 | 
				
			||||||
 | 
								ArrivalLng:    destinationgeo.Point().Lon(),
 | 
				
			||||||
 | 
								DepartureDate: timestamppb.New(departuredatetime),
 | 
				
			||||||
 | 
							})
 | 
				
			||||||
 | 
							if err != nil {
 | 
				
			||||||
 | 
								log.Error().Err(err).Msg("error retrieving organized carpools")
 | 
				
			||||||
 | 
							} else {
 | 
				
			||||||
 | 
								organizedCarpools = organizedCarpoolsRes.DriverJourneys
 | 
				
			||||||
 | 
								sort.Slice(organizedCarpools, func(i, j int) bool {
 | 
				
			||||||
 | 
									return *organizedCarpools[i].Distance < *organizedCarpools[j].Distance
 | 
				
			||||||
 | 
								})
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							var wg sync.WaitGroup
 | 
				
			||||||
 | 
							// CARPOOL OPERATORS
 | 
				
			||||||
 | 
							carpools := make(chan *geojson.FeatureCollection)
 | 
				
			||||||
 | 
							go h.services.InteropCarpool.Search(carpools, *departuregeo, *destinationgeo, departuredatetime)
 | 
				
			||||||
 | 
							wg.Add(1)
 | 
				
			||||||
 | 
							go func() {
 | 
				
			||||||
 | 
								defer wg.Done()
 | 
				
			||||||
 | 
								for c := range carpools {
 | 
				
			||||||
 | 
									carpool_results = append(carpool_results, c)
 | 
				
			||||||
 | 
								}
 | 
				
			||||||
 | 
							}()
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							// TRANSIT
 | 
				
			||||||
 | 
							transitch := make(chan *motis.Itinerary)
 | 
				
			||||||
 | 
							go func(transitch chan *motis.Itinerary, departure *geojson.Feature, destination *geojson.Feature, datetime *time.Time) {
 | 
				
			||||||
 | 
								defer close(transitch)
 | 
				
			||||||
 | 
								// timetableView := false
 | 
				
			||||||
 | 
								searchWindows := 1800
 | 
				
			||||||
 | 
								response, err := h.services.TransitRouting.PlanWithResponse(context.Background(), &motis.PlanParams{
 | 
				
			||||||
 | 
									FromPlace: fmt.Sprintf("%f,%f", departure.Point().Lat(), departure.Point().Lon()),
 | 
				
			||||||
 | 
									ToPlace:   fmt.Sprintf("%f,%f", destination.Point().Lat(), destination.Point().Lon()),
 | 
				
			||||||
 | 
									Time:      datetime,
 | 
				
			||||||
 | 
									// TimetableView: &timetableView,
 | 
				
			||||||
 | 
									SearchWindow: &searchWindows,
 | 
				
			||||||
 | 
								})
 | 
				
			||||||
			if err != nil {
 | 
								if err != nil {
 | 
				
			||||||
				log.Error().Err(err).Msg("")
 | 
									log.Error().Err(err).Msg("error retrieving transit data from MOTIS server")
 | 
				
			||||||
				w.WriteHeader(http.StatusBadRequest)
 | 
					 | 
				
			||||||
				navitiaCh <- nil
 | 
					 | 
				
			||||||
				return
 | 
									return
 | 
				
			||||||
			}
 | 
								}
 | 
				
			||||||
 | 
								for _, i := range response.JSON200.Itineraries {
 | 
				
			||||||
			request := navitia.JourneyRequest{
 | 
									transitch <- &i
 | 
				
			||||||
				From:          types.ID(fmt.Sprintf("%f", departuregeo.Geometry.Point[0]) + ";" + fmt.Sprintf("%f", departuregeo.Geometry.Point[1])),
 | 
					 | 
				
			||||||
				To:            types.ID(fmt.Sprintf("%f", destinationgeo.Geometry.Point[0]) + ";" + fmt.Sprintf("%f", destinationgeo.Geometry.Point[1])),
 | 
					 | 
				
			||||||
				Date:          departuredatetime.Add(-2 * time.Hour),
 | 
					 | 
				
			||||||
				DateIsArrival: false, // TODO
 | 
					 | 
				
			||||||
			}
 | 
								}
 | 
				
			||||||
 | 
							}(transitch, departuregeo, destinationgeo, &departuredatetime)
 | 
				
			||||||
			journeys, err = session.Journeys(context.Background(), request)
 | 
							wg.Add(1)
 | 
				
			||||||
			if err != nil {
 | 
							go func() {
 | 
				
			||||||
				log.Error().Err(err).Msg("")
 | 
								defer wg.Done()
 | 
				
			||||||
				// w.WriteHeader(http.StatusBadRequest)
 | 
								for itinerary := range transitch {
 | 
				
			||||||
				// return
 | 
									transit_results = append(transit_results, itinerary)
 | 
				
			||||||
			}
 | 
								}
 | 
				
			||||||
			navitiaCh <- journeys
 | 
							}()
 | 
				
			||||||
		}
 | 
					
 | 
				
			||||||
		////////////////////////////////////////////////////////////////////////////////////////////////////////////////
 | 
							// VEHICLES
 | 
				
			||||||
		// SOLIDARITY TRANSPORT
 | 
							vehiclech := make(chan fleetsstorage.Vehicle)
 | 
				
			||||||
		drivers, err := h.services.GetAccountsInNamespace("solidarity_drivers")
 | 
							go h.vehicleRequest(vehiclech, departuredatetime.Add(-24*time.Hour), departuredatetime.Add(168*time.Hour))
 | 
				
			||||||
		if err != nil {
 | 
							wg.Add(1)
 | 
				
			||||||
			drivers = []mobilityaccountsstorage.Account{}
 | 
							go func() {
 | 
				
			||||||
		}
 | 
								defer wg.Done()
 | 
				
			||||||
		for _, a := range drivers {
 | 
								for vehicle := range vehiclech {
 | 
				
			||||||
			if availabilities, ok := a.Data["solidarity_transport_availabilities"].([]any); ok {
 | 
									vehicle_results = append(vehicle_results, vehicle)
 | 
				
			||||||
				for _, availability := range availabilities {
 | 
								}
 | 
				
			||||||
					if av, ok := availability.(map[string]any); ok {
 | 
								slices.SortFunc(vehicle_results, sorting.VehiclesByDistanceFrom(*departuregeo))
 | 
				
			||||||
						day := av["day"].(float64)
 | 
							}()
 | 
				
			||||||
						starttime := av["start_time"].(string)
 | 
							// journeys_results = <-navitiaCh
 | 
				
			||||||
						endtime := av["end_time"].(string)
 | 
							wg.Wait()
 | 
				
			||||||
						if departuretime >= starttime && departuretime <= endtime && departuredatetime.Weekday() == time.Weekday(int(day)) {
 | 
							// KNOWLEDGE BASE
 | 
				
			||||||
							availableDrivers = append(availableDrivers, a)
 | 
							departureGeo, _ := h.services.Geography.GeoSearch(departuregeo)
 | 
				
			||||||
							break
 | 
							kbData := h.config.Get("knowledge_base")
 | 
				
			||||||
 | 
							if kb, ok := kbData.([]any); ok {
 | 
				
			||||||
 | 
								log.Debug().Msg("1")
 | 
				
			||||||
 | 
								for _, sol := range kb {
 | 
				
			||||||
 | 
									log.Debug().Msg("2")
 | 
				
			||||||
 | 
									if solution, ok := sol.(map[string]any); ok {
 | 
				
			||||||
 | 
										log.Debug().Msg("3")
 | 
				
			||||||
 | 
										if g, ok := solution["geography"]; ok {
 | 
				
			||||||
 | 
											log.Debug().Msg("4")
 | 
				
			||||||
 | 
											if geography, ok := g.([]any); ok {
 | 
				
			||||||
 | 
												log.Debug().Msg("5")
 | 
				
			||||||
 | 
												for _, gg := range geography {
 | 
				
			||||||
 | 
													log.Debug().Msg("6")
 | 
				
			||||||
 | 
													if geog, ok := gg.(map[string]any); ok {
 | 
				
			||||||
 | 
														log.Debug().Msg("7")
 | 
				
			||||||
 | 
														if layer, ok := geog["layer"].(string); ok {
 | 
				
			||||||
 | 
															log.Debug().Msg("8")
 | 
				
			||||||
 | 
															code := geog["code"]
 | 
				
			||||||
 | 
															log.Debug().Any("code", fmt.Sprintf("%s", code)).Any("departure geo", departureGeo[layer].Properties.MustString("code")).Msg("9")
 | 
				
			||||||
 | 
															if strings.Compare(fmt.Sprintf("%v", code), departureGeo[layer].Properties.MustString("code")) == 0 {
 | 
				
			||||||
 | 
																log.Debug().Msg("10")
 | 
				
			||||||
 | 
																kb_results = append(kb_results, solution)
 | 
				
			||||||
 | 
																break
 | 
				
			||||||
 | 
															}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
														}
 | 
				
			||||||
 | 
													}
 | 
				
			||||||
 | 
												}
 | 
				
			||||||
						}
 | 
											}
 | 
				
			||||||
					}
 | 
										}
 | 
				
			||||||
				}
 | 
									}
 | 
				
			||||||
			}
 | 
								}
 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
		////////////////////////////////////////////////////////////////////////////////////////////////////////////////
 | 
					 | 
				
			||||||
		//CARPOOL
 | 
					 | 
				
			||||||
		carpoolRequest := func() {
 | 
					 | 
				
			||||||
			carpoolrequest := "https://api.rdex.ridygo.fr/journeys.json"
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
			client := &http.Client{}
 | 
					 | 
				
			||||||
			req, err := http.NewRequest("GET", carpoolrequest, nil)
 | 
					 | 
				
			||||||
			if err != nil {
 | 
					 | 
				
			||||||
				log.Error().Err(err).Msg("")
 | 
					 | 
				
			||||||
			}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
			req.URL.RawQuery = fmt.Sprintf(
 | 
					 | 
				
			||||||
				"p[driver][state]=1&frequency=punctual&p[passenger][state]=0&p[from][latitude]=%f&p[from][longitude]=%f&p[to][latitude]=%f&p[to][longitude]=%f&p[outward][mindate]=%s&p[outward][maxdate]=%s",
 | 
					 | 
				
			||||||
				departuregeo.Geometry.Point[1], departuregeo.Geometry.Point[0],
 | 
					 | 
				
			||||||
				destinationgeo.Geometry.Point[1], destinationgeo.Geometry.Point[0],
 | 
					 | 
				
			||||||
				departuredatetime.Format("2006-01-02"), departuredatetime.Format("2006-01-02"))
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
			req.Header.Set("X-API-KEY", "123456")
 | 
					 | 
				
			||||||
			resp, err := client.Do(req)
 | 
					 | 
				
			||||||
			if err != nil {
 | 
					 | 
				
			||||||
				log.Error().Err(err).Msg("")
 | 
					 | 
				
			||||||
			}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
			if err == nil && resp.StatusCode == http.StatusOK {
 | 
					 | 
				
			||||||
				err = json.NewDecoder(resp.Body).Decode(&carpoolresults)
 | 
					 | 
				
			||||||
				if err != nil {
 | 
					 | 
				
			||||||
					log.Error().Err(err).Msg("")
 | 
					 | 
				
			||||||
				}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
				if carpoolresults == nil {
 | 
					 | 
				
			||||||
					carpoolresults = []any{}
 | 
					 | 
				
			||||||
				}
 | 
					 | 
				
			||||||
			} else {
 | 
					 | 
				
			||||||
				carpoolresults = []any{}
 | 
					 | 
				
			||||||
			}
 | 
					 | 
				
			||||||
			carpoolCh <- carpoolresults
 | 
					 | 
				
			||||||
		}
 | 
					 | 
				
			||||||
		////////////////////////////////////////////////////////////////////////////////////////////////////////////////
 | 
					 | 
				
			||||||
		// Vehicles
 | 
					 | 
				
			||||||
		vehicleRequest := func() {
 | 
					 | 
				
			||||||
			vehiclerequest := &fleets.GetVehiclesRequest{
 | 
					 | 
				
			||||||
				Namespaces: []string{"parcoursmob"},
 | 
					 | 
				
			||||||
			}
 | 
					 | 
				
			||||||
			vehicleresp, err := h.services.GRPC.Fleets.GetVehicles(context.TODO(), vehiclerequest)
 | 
					 | 
				
			||||||
			if err != nil {
 | 
					 | 
				
			||||||
				log.Error().Err(err).Msg("")
 | 
					 | 
				
			||||||
				w.WriteHeader(http.StatusInternalServerError)
 | 
					 | 
				
			||||||
			}
 | 
					 | 
				
			||||||
			for _, vehicle := range vehicleresp.Vehicles {
 | 
					 | 
				
			||||||
				v := vehicle.ToStorageType()
 | 
					 | 
				
			||||||
				if v.Free(departuredatetime.Add(-24*time.Hour), departuredatetime.Add(168*time.Hour)) {
 | 
					 | 
				
			||||||
					vehicles = append(vehicles, v)
 | 
					 | 
				
			||||||
				}
 | 
					 | 
				
			||||||
			}
 | 
					 | 
				
			||||||
			vehiclech <- vehicles
 | 
					 | 
				
			||||||
		}
 | 
					 | 
				
			||||||
		go journeysRequest()
 | 
					 | 
				
			||||||
		go carpoolRequest()
 | 
					 | 
				
			||||||
		go vehicleRequest()
 | 
					 | 
				
			||||||
		carpool_results = <-carpoolCh
 | 
					 | 
				
			||||||
		journeys_results = <-navitiaCh
 | 
					 | 
				
			||||||
		vehicle_results = <-vehiclech
 | 
					 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	h.Renderer.JourneysSearch(w, r, carpool_results, journeys_results, vehicle_results, searched, departuregeo, destinationgeo, departuredate, departuretime, availableDrivers)
 | 
						beneficiaries, err := h.beneficiaries(r)
 | 
				
			||||||
 | 
						if err != nil {
 | 
				
			||||||
 | 
							log.Error().Err(err).Msg("issue retrieving beneficiaries")
 | 
				
			||||||
 | 
							w.WriteHeader(http.StatusInternalServerError)
 | 
				
			||||||
 | 
							return
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						h.Renderer.JourneysSearch(w, r, carpool_results, transit_results, vehicle_results, searched, departuregeo, destinationgeo, departuredate, departuretime, driverJourneys, drivers, organizedCarpools, beneficiaries, kb_results)
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					func (h *ApplicationHandler) vehicleRequest(vehiclech chan fleetsstorage.Vehicle, start time.Time, end time.Time) {
 | 
				
			||||||
 | 
						defer close(vehiclech)
 | 
				
			||||||
 | 
						vehiclerequest := &fleets.GetVehiclesRequest{
 | 
				
			||||||
 | 
							Namespaces: []string{"parcoursmob"},
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						vehicleresp, err := h.services.GRPC.Fleets.GetVehicles(context.TODO(), vehiclerequest)
 | 
				
			||||||
 | 
						if err != nil {
 | 
				
			||||||
 | 
							log.Error().Err(err).Msg("")
 | 
				
			||||||
 | 
							return
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						for _, vehicle := range vehicleresp.Vehicles {
 | 
				
			||||||
 | 
							v := vehicle.ToStorageType()
 | 
				
			||||||
 | 
							if v.Free(start, end) {
 | 
				
			||||||
 | 
								vehiclech <- v
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
type GroupsModule []groupstorage.Group
 | 
					type GroupsModule []groupstorage.Group
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -0,0 +1,639 @@
 | 
				
			||||||
 | 
					package application
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					import (
 | 
				
			||||||
 | 
						"cmp"
 | 
				
			||||||
 | 
						"context"
 | 
				
			||||||
 | 
						"encoding/json"
 | 
				
			||||||
 | 
						"fmt"
 | 
				
			||||||
 | 
						"io"
 | 
				
			||||||
 | 
						"net/http"
 | 
				
			||||||
 | 
						"slices"
 | 
				
			||||||
 | 
						"strings"
 | 
				
			||||||
 | 
						"time"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						formvalidators "git.coopgo.io/coopgo-apps/parcoursmob/utils/form-validators"
 | 
				
			||||||
 | 
						filestorage "git.coopgo.io/coopgo-apps/parcoursmob/utils/storage"
 | 
				
			||||||
 | 
						"git.coopgo.io/coopgo-platform/carpool-service/servers/grpc/proto"
 | 
				
			||||||
 | 
						mobilityaccounts "git.coopgo.io/coopgo-platform/mobility-accounts/grpcapi"
 | 
				
			||||||
 | 
						mobilityaccountsstorage "git.coopgo.io/coopgo-platform/mobility-accounts/storage"
 | 
				
			||||||
 | 
						"github.com/google/uuid"
 | 
				
			||||||
 | 
						"github.com/gorilla/mux"
 | 
				
			||||||
 | 
						"github.com/paulmach/orb"
 | 
				
			||||||
 | 
						"github.com/paulmach/orb/geojson"
 | 
				
			||||||
 | 
						"github.com/rs/zerolog/log"
 | 
				
			||||||
 | 
						"google.golang.org/protobuf/types/known/structpb"
 | 
				
			||||||
 | 
						"google.golang.org/protobuf/types/known/timestamppb"
 | 
				
			||||||
 | 
					)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					type OrganizedCarpoolDriversForm struct {
 | 
				
			||||||
 | 
						FirstName          string     `json:"first_name" validate:"required"`
 | 
				
			||||||
 | 
						LastName           string     `json:"last_name" validate:"required"`
 | 
				
			||||||
 | 
						Email              string     `json:"email" validate:"required,email"`
 | 
				
			||||||
 | 
						Birthdate          *time.Time `json:"birthdate" validate:"required"`
 | 
				
			||||||
 | 
						PhoneNumber        string     `json:"phone_number" validate:"required,phoneNumber"`
 | 
				
			||||||
 | 
						FileNumber         string     `json:"file_number"`
 | 
				
			||||||
 | 
						Address            any        `json:"address,omitempty"`
 | 
				
			||||||
 | 
						AddressDestination any        `json:"address_destination,omitempty"`
 | 
				
			||||||
 | 
						Gender             string     `json:"gender"`
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					func (h *ApplicationHandler) OrganizedCarpoolOverview(w http.ResponseWriter, r *http.Request) {
 | 
				
			||||||
 | 
						accounts, err := h.organizedCarpoolDrivers(r)
 | 
				
			||||||
 | 
						if err != nil {
 | 
				
			||||||
 | 
							log.Error().Err(err).Msg("issue getting solidarity drivers")
 | 
				
			||||||
 | 
							accounts = []mobilityaccountsstorage.Account{}
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						accountsMap := map[string]mobilityaccountsstorage.Account{}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						for _, a := range accounts {
 | 
				
			||||||
 | 
							accountsMap[a.ID] = a
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						beneficiariesMap, err := h.services.GetBeneficiariesMap()
 | 
				
			||||||
 | 
						if err != nil {
 | 
				
			||||||
 | 
							beneficiariesMap = map[string]mobilityaccountsstorage.Account{}
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						bookingsproto, err := h.services.GRPC.CarpoolService.GetCarpoolBookings(context.Background(), &proto.GetCarpoolBookingsRequest{
 | 
				
			||||||
 | 
							MinDate: timestamppb.Now(),
 | 
				
			||||||
 | 
							MaxDate: timestamppb.New(time.Now().Add(24 * 365 * time.Hour)),
 | 
				
			||||||
 | 
						})
 | 
				
			||||||
 | 
						if err != nil {
 | 
				
			||||||
 | 
							log.Error().Err(err).Msg("issue retreving bookings")
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						bookings := []*proto.CarpoolServiceBooking{}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						if err == nil {
 | 
				
			||||||
 | 
							for _, b := range bookingsproto.Bookings {
 | 
				
			||||||
 | 
								// booking, _ := transformers.BookingProtoToType(b)
 | 
				
			||||||
 | 
								bookings = append(bookings, b)
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						slices.SortFunc(accounts, func(a, b mobilityaccountsstorage.Account) int {
 | 
				
			||||||
 | 
							return strings.Compare(
 | 
				
			||||||
 | 
								strings.ToLower(fmt.Sprintf("%s %s", a.Data["first_name"].(string), a.Data["last_name"].(string))),
 | 
				
			||||||
 | 
								strings.ToLower(fmt.Sprintf("%s %s", b.Data["first_name"].(string), b.Data["last_name"].(string))),
 | 
				
			||||||
 | 
							)
 | 
				
			||||||
 | 
						})
 | 
				
			||||||
 | 
						slices.SortFunc(bookings, func(a, b *proto.CarpoolServiceBooking) int {
 | 
				
			||||||
 | 
							return cmp.Compare(a.PassengerPickupDate.AsTime().Unix(), b.PassengerPickupDate.AsTime().Unix())
 | 
				
			||||||
 | 
						})
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						h.Renderer.OrganizedCarpoolOverview(w, r, accounts, accountsMap, beneficiariesMap, bookings)
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					func (h *ApplicationHandler) organizedCarpoolDrivers(r *http.Request) ([]mobilityaccountsstorage.Account, error) {
 | 
				
			||||||
 | 
						accounts := []mobilityaccountsstorage.Account{}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						request := &mobilityaccounts.GetAccountsRequest{
 | 
				
			||||||
 | 
							Namespaces: []string{"organized_carpool_drivers"},
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						resp, err := h.services.GRPC.MobilityAccounts.GetAccounts(context.TODO(), request)
 | 
				
			||||||
 | 
						if err != nil {
 | 
				
			||||||
 | 
							return accounts, err
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						for _, account := range resp.Accounts {
 | 
				
			||||||
 | 
							if filterAccount(r, account) {
 | 
				
			||||||
 | 
								a := account.ToStorageType()
 | 
				
			||||||
 | 
								accounts = append(accounts, a)
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						return accounts, err
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					func (h *ApplicationHandler) OrganizedCarpoolCreateDriver(w http.ResponseWriter, r *http.Request) {
 | 
				
			||||||
 | 
						if r.Method == "POST" {
 | 
				
			||||||
 | 
							dataMap, err := parseOrganizedCarpoolDriversForm(r)
 | 
				
			||||||
 | 
							if err != nil {
 | 
				
			||||||
 | 
								log.Error().Err(err).Msg("")
 | 
				
			||||||
 | 
								w.WriteHeader(http.StatusBadRequest)
 | 
				
			||||||
 | 
								return
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							data, err := structpb.NewValue(dataMap)
 | 
				
			||||||
 | 
							if err != nil {
 | 
				
			||||||
 | 
								log.Error().Err(err).Msg("")
 | 
				
			||||||
 | 
								w.WriteHeader(http.StatusInternalServerError)
 | 
				
			||||||
 | 
								return
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							request := &mobilityaccounts.RegisterRequest{
 | 
				
			||||||
 | 
								Account: &mobilityaccounts.Account{
 | 
				
			||||||
 | 
									Namespace: "organized_carpool_drivers",
 | 
				
			||||||
 | 
									Data:      data.GetStructValue(),
 | 
				
			||||||
 | 
								},
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							resp, err := h.services.GRPC.MobilityAccounts.Register(context.TODO(), request)
 | 
				
			||||||
 | 
							if err != nil {
 | 
				
			||||||
 | 
								log.Error().Err(err).Msg("")
 | 
				
			||||||
 | 
								w.WriteHeader(http.StatusInternalServerError)
 | 
				
			||||||
 | 
								return
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							http.Redirect(w, r, fmt.Sprintf("/app/organized-carpool/drivers/%s", resp.Account.Id), http.StatusFound)
 | 
				
			||||||
 | 
							return
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						h.Renderer.OrganizedCarpoolCreateDriver(w, r)
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					func (h *ApplicationHandler) OrganizedCarpoolDriverDisplay(w http.ResponseWriter, r *http.Request) {
 | 
				
			||||||
 | 
						vars := mux.Vars(r)
 | 
				
			||||||
 | 
						driverID := vars["driverid"]
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						documents := h.filestorage.List(filestorage.PREFIX_ORGANIZED_CARPOOL_DRIVERS + "/" + driverID)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						driver, err := h.services.GetAccount(driverID)
 | 
				
			||||||
 | 
						if err != nil {
 | 
				
			||||||
 | 
							log.Error().Err(err).Msg("Issue retrieving driver account")
 | 
				
			||||||
 | 
							w.WriteHeader(http.StatusInternalServerError)
 | 
				
			||||||
 | 
							return
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						log.Info().Any("driver data", driver.Data).Msg("driver retrieved")
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						trips := []*geojson.FeatureCollection{}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						resp, err := h.services.GRPC.CarpoolService.GetRegularRoutes(context.Background(), &proto.GetRegularRoutesRequest{
 | 
				
			||||||
 | 
							UserId: driverID,
 | 
				
			||||||
 | 
						})
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						for _, r := range resp.Routes {
 | 
				
			||||||
 | 
							t, err := geojson.UnmarshalFeatureCollection([]byte(r.Serialized))
 | 
				
			||||||
 | 
							if err != nil {
 | 
				
			||||||
 | 
								log.Error().Err(err).Msg("could not unmarshall feature collection")
 | 
				
			||||||
 | 
								continue
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							trips = append(trips, t)
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						h.Renderer.OrganizedCarpoolDriverDisplay(w, r, driver, trips, documents)
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					func (h *ApplicationHandler) OrganizedCarpoolArchiveDriver(w http.ResponseWriter, r *http.Request) {
 | 
				
			||||||
 | 
						vars := mux.Vars(r)
 | 
				
			||||||
 | 
						driverID := vars["driverid"]
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						data, _ := structpb.NewValue(map[string]any{
 | 
				
			||||||
 | 
							"archived": true,
 | 
				
			||||||
 | 
						})
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						request := &mobilityaccounts.UpdateDataRequest{
 | 
				
			||||||
 | 
							Account: &mobilityaccounts.Account{
 | 
				
			||||||
 | 
								Id:        driverID,
 | 
				
			||||||
 | 
								Namespace: "organized_carpool_drivers",
 | 
				
			||||||
 | 
								Data:      data.GetStructValue(),
 | 
				
			||||||
 | 
							},
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						resp, err := h.services.GRPC.MobilityAccounts.UpdateData(context.TODO(), request)
 | 
				
			||||||
 | 
						if err != nil {
 | 
				
			||||||
 | 
							log.Error().Err(err).Msg("")
 | 
				
			||||||
 | 
							w.WriteHeader(http.StatusInternalServerError)
 | 
				
			||||||
 | 
							return
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						http.Redirect(w, r, fmt.Sprintf("/app/organized-carpool/drivers/%s", resp.Account.Id), http.StatusFound)
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					func (h *ApplicationHandler) OrganizedCarpoolUnarchiveDriver(w http.ResponseWriter, r *http.Request) {
 | 
				
			||||||
 | 
						vars := mux.Vars(r)
 | 
				
			||||||
 | 
						driverID := vars["driverid"]
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						data, _ := structpb.NewValue(map[string]any{
 | 
				
			||||||
 | 
							"archived": false,
 | 
				
			||||||
 | 
						})
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						request := &mobilityaccounts.UpdateDataRequest{
 | 
				
			||||||
 | 
							Account: &mobilityaccounts.Account{
 | 
				
			||||||
 | 
								Id:        driverID,
 | 
				
			||||||
 | 
								Namespace: "organized_carpool_drivers",
 | 
				
			||||||
 | 
								Data:      data.GetStructValue(),
 | 
				
			||||||
 | 
							},
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						resp, err := h.services.GRPC.MobilityAccounts.UpdateData(context.TODO(), request)
 | 
				
			||||||
 | 
						if err != nil {
 | 
				
			||||||
 | 
							log.Error().Err(err).Msg("")
 | 
				
			||||||
 | 
							w.WriteHeader(http.StatusInternalServerError)
 | 
				
			||||||
 | 
							return
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						http.Redirect(w, r, fmt.Sprintf("/app/organized-carpool/drivers/%s", resp.Account.Id), http.StatusFound)
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					func (h *ApplicationHandler) OrganizedCarpoolDriverDocuments(w http.ResponseWriter, r *http.Request) {
 | 
				
			||||||
 | 
						vars := mux.Vars(r)
 | 
				
			||||||
 | 
						driverID := vars["driverid"]
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						// r.ParseForm()
 | 
				
			||||||
 | 
						r.ParseMultipartForm(100 * 1024 * 1024)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						document_type := r.FormValue("type")
 | 
				
			||||||
 | 
						document_name := r.FormValue("name")
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						file, header, err := r.FormFile("file-upload")
 | 
				
			||||||
 | 
						if err != nil {
 | 
				
			||||||
 | 
							log.Error().Err(err).Msg("")
 | 
				
			||||||
 | 
							return
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						defer file.Close()
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						fileid := uuid.NewString()
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						metadata := map[string]string{
 | 
				
			||||||
 | 
							"type": document_type,
 | 
				
			||||||
 | 
							"name": document_name,
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						log.Debug().Any("metadata", metadata).Msg("Metadata")
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						if err := h.filestorage.Put(file, filestorage.PREFIX_ORGANIZED_CARPOOL_DRIVERS, fmt.Sprintf("%s/%s_%s", driverID, fileid, header.Filename), header.Size, metadata); err != nil {
 | 
				
			||||||
 | 
							log.Error().Err(err).Msg("")
 | 
				
			||||||
 | 
							w.WriteHeader(http.StatusInternalServerError)
 | 
				
			||||||
 | 
							return
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						http.Redirect(w, r, fmt.Sprintf("/app/organized-carpool/drivers/%s", driverID), http.StatusFound)
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					func (h *ApplicationHandler) OrganizedCarpoolDocumentDownload(w http.ResponseWriter, r *http.Request) {
 | 
				
			||||||
 | 
						vars := mux.Vars(r)
 | 
				
			||||||
 | 
						driverID := vars["driverid"]
 | 
				
			||||||
 | 
						document := vars["document"]
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						file, info, err := h.filestorage.Get(filestorage.PREFIX_ORGANIZED_CARPOOL_DRIVERS, fmt.Sprintf("%s/%s", driverID, document))
 | 
				
			||||||
 | 
						if err != nil {
 | 
				
			||||||
 | 
							log.Error().Err(err).Msg("")
 | 
				
			||||||
 | 
							w.WriteHeader(http.StatusInternalServerError)
 | 
				
			||||||
 | 
							return
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						w.Header().Set("Content-Type", info.ContentType)
 | 
				
			||||||
 | 
						if _, err = io.Copy(w, file); err != nil {
 | 
				
			||||||
 | 
							log.Error().Err(err).Msg("")
 | 
				
			||||||
 | 
							w.WriteHeader(http.StatusInternalServerError)
 | 
				
			||||||
 | 
							return
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						// http.Redirect(w, r, fmt.Sprintf("/app/solidarity-transport/drivers/%s", driverID), http.StatusFound)
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					func (h *ApplicationHandler) OrganizedCarpoolAddTrip(w http.ResponseWriter, r *http.Request) {
 | 
				
			||||||
 | 
						if r.Method != "POST" {
 | 
				
			||||||
 | 
							log.Error().Msg("Wrong method")
 | 
				
			||||||
 | 
							w.WriteHeader(http.StatusMethodNotAllowed)
 | 
				
			||||||
 | 
							return
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						if err := r.ParseForm(); err != nil {
 | 
				
			||||||
 | 
							log.Error().Err(err).Msg("error parsong availabilities form")
 | 
				
			||||||
 | 
							w.WriteHeader(http.StatusInternalServerError)
 | 
				
			||||||
 | 
							return
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						vars := mux.Vars(r)
 | 
				
			||||||
 | 
						driverID := vars["driverid"]
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						trips := []*proto.CarpoolFeatureCollection{}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						outwardtime := r.PostFormValue("outwardtime")
 | 
				
			||||||
 | 
						returntime := r.PostFormValue("returntime")
 | 
				
			||||||
 | 
						dep := r.PostFormValue("address_departure")
 | 
				
			||||||
 | 
						dest := r.PostFormValue("address_destination")
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						departure, err := geojson.UnmarshalFeature([]byte(dep))
 | 
				
			||||||
 | 
						if err != nil {
 | 
				
			||||||
 | 
							log.Error().Err(err).Msg("failed parsong departure geojson")
 | 
				
			||||||
 | 
							w.WriteHeader(http.StatusInternalServerError)
 | 
				
			||||||
 | 
							return
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						destination, err := geojson.UnmarshalFeature([]byte(dest))
 | 
				
			||||||
 | 
						if err != nil {
 | 
				
			||||||
 | 
							log.Error().Err(err).Msg("failed parsong departure geojson")
 | 
				
			||||||
 | 
							w.WriteHeader(http.StatusInternalServerError)
 | 
				
			||||||
 | 
							return
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						outwardroute, err := h.services.Routing.Route([]orb.Point{departure.Point(), destination.Point()})
 | 
				
			||||||
 | 
						if err != nil {
 | 
				
			||||||
 | 
							log.Error().Err(err).Msg("failed calling route search")
 | 
				
			||||||
 | 
							w.WriteHeader(http.StatusInternalServerError)
 | 
				
			||||||
 | 
							return
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						returnroute, err := h.services.Routing.Route([]orb.Point{destination.Point(), departure.Point()})
 | 
				
			||||||
 | 
						if err != nil {
 | 
				
			||||||
 | 
							log.Error().Err(err).Msg("failed calling route search")
 | 
				
			||||||
 | 
							w.WriteHeader(http.StatusInternalServerError)
 | 
				
			||||||
 | 
							return
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						outwardschedules := []map[string]any{}
 | 
				
			||||||
 | 
						returnschedules := []map[string]any{}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						if r.PostFormValue("days.monday") == "on" {
 | 
				
			||||||
 | 
							outwardschedules = append(outwardschedules, map[string]any{
 | 
				
			||||||
 | 
								"day":         "MON",
 | 
				
			||||||
 | 
								"time_of_day": outwardtime,
 | 
				
			||||||
 | 
							})
 | 
				
			||||||
 | 
							returnschedules = append(returnschedules, map[string]any{
 | 
				
			||||||
 | 
								"day":         "MON",
 | 
				
			||||||
 | 
								"time_of_day": returntime,
 | 
				
			||||||
 | 
							})
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						if r.PostFormValue("days.tuesday") == "on" {
 | 
				
			||||||
 | 
							outwardschedules = append(outwardschedules, map[string]any{
 | 
				
			||||||
 | 
								"day":         "TUE",
 | 
				
			||||||
 | 
								"time_of_day": outwardtime,
 | 
				
			||||||
 | 
							})
 | 
				
			||||||
 | 
							returnschedules = append(returnschedules, map[string]any{
 | 
				
			||||||
 | 
								"day":         "TUE",
 | 
				
			||||||
 | 
								"time_of_day": returntime,
 | 
				
			||||||
 | 
							})
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						if r.PostFormValue("days.wednesday") == "on" {
 | 
				
			||||||
 | 
							outwardschedules = append(outwardschedules, map[string]any{
 | 
				
			||||||
 | 
								"day":         "WED",
 | 
				
			||||||
 | 
								"time_of_day": outwardtime,
 | 
				
			||||||
 | 
							})
 | 
				
			||||||
 | 
							returnschedules = append(returnschedules, map[string]any{
 | 
				
			||||||
 | 
								"day":         "WED",
 | 
				
			||||||
 | 
								"time_of_day": returntime,
 | 
				
			||||||
 | 
							})
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						if r.PostFormValue("days.thursday") == "on" {
 | 
				
			||||||
 | 
							outwardschedules = append(outwardschedules, map[string]any{
 | 
				
			||||||
 | 
								"day":         "THU",
 | 
				
			||||||
 | 
								"time_of_day": outwardtime,
 | 
				
			||||||
 | 
							})
 | 
				
			||||||
 | 
							returnschedules = append(returnschedules, map[string]any{
 | 
				
			||||||
 | 
								"day":         "THU",
 | 
				
			||||||
 | 
								"time_of_day": returntime,
 | 
				
			||||||
 | 
							})
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						if r.PostFormValue("days.friday") == "on" {
 | 
				
			||||||
 | 
							outwardschedules = append(outwardschedules, map[string]any{
 | 
				
			||||||
 | 
								"day":         "FRI",
 | 
				
			||||||
 | 
								"time_of_day": outwardtime,
 | 
				
			||||||
 | 
							})
 | 
				
			||||||
 | 
							returnschedules = append(returnschedules, map[string]any{
 | 
				
			||||||
 | 
								"day":         "FRI",
 | 
				
			||||||
 | 
								"time_of_day": returntime,
 | 
				
			||||||
 | 
							})
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						if r.PostFormValue("days.saturday") == "on" {
 | 
				
			||||||
 | 
							outwardschedules = append(outwardschedules, map[string]any{
 | 
				
			||||||
 | 
								"day":         "SAT",
 | 
				
			||||||
 | 
								"time_of_day": outwardtime,
 | 
				
			||||||
 | 
							})
 | 
				
			||||||
 | 
							returnschedules = append(returnschedules, map[string]any{
 | 
				
			||||||
 | 
								"day":         "SAT",
 | 
				
			||||||
 | 
								"time_of_day": returntime,
 | 
				
			||||||
 | 
							})
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						if r.PostFormValue("days.sunday") == "on" {
 | 
				
			||||||
 | 
							outwardschedules = append(outwardschedules, map[string]any{
 | 
				
			||||||
 | 
								"day":         "SUN",
 | 
				
			||||||
 | 
								"time_of_day": outwardtime,
 | 
				
			||||||
 | 
							})
 | 
				
			||||||
 | 
							returnschedules = append(returnschedules, map[string]any{
 | 
				
			||||||
 | 
								"day":         "SUN",
 | 
				
			||||||
 | 
								"time_of_day": returntime,
 | 
				
			||||||
 | 
							})
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						outward_fc := geojson.NewFeatureCollection()
 | 
				
			||||||
 | 
						outward_fc.Append(departure)
 | 
				
			||||||
 | 
						outward_fc.Append(destination)
 | 
				
			||||||
 | 
						outward_fc.ExtraMembers = geojson.Properties{}
 | 
				
			||||||
 | 
						outward_fc.ExtraMembers["properties"] = map[string]any{
 | 
				
			||||||
 | 
							"is_driver":    true,
 | 
				
			||||||
 | 
							"is_passenger": false,
 | 
				
			||||||
 | 
							"user": mobilityaccountsstorage.Account{
 | 
				
			||||||
 | 
								ID: driverID,
 | 
				
			||||||
 | 
							},
 | 
				
			||||||
 | 
							"polyline":          outwardroute.Summary.Polyline,
 | 
				
			||||||
 | 
							"schedules":         outwardschedules,
 | 
				
			||||||
 | 
							"driver_options":    map[string]any{},
 | 
				
			||||||
 | 
							"passenger_options": map[string]any{},
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						outwardtrip, err := outward_fc.MarshalJSON()
 | 
				
			||||||
 | 
						if err != nil {
 | 
				
			||||||
 | 
							log.Error().Err(err).Msg("failed parsong return geojson")
 | 
				
			||||||
 | 
							w.WriteHeader(http.StatusInternalServerError)
 | 
				
			||||||
 | 
							return
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						return_fc := geojson.NewFeatureCollection()
 | 
				
			||||||
 | 
						return_fc.Append(destination)
 | 
				
			||||||
 | 
						return_fc.Append(departure)
 | 
				
			||||||
 | 
						return_fc.ExtraMembers = geojson.Properties{}
 | 
				
			||||||
 | 
						return_fc.ExtraMembers["properties"] = map[string]any{
 | 
				
			||||||
 | 
							"is_driver":    true,
 | 
				
			||||||
 | 
							"is_passenger": false,
 | 
				
			||||||
 | 
							"user": mobilityaccountsstorage.Account{
 | 
				
			||||||
 | 
								ID: driverID,
 | 
				
			||||||
 | 
							},
 | 
				
			||||||
 | 
							"polyline":          returnroute.Summary.Polyline,
 | 
				
			||||||
 | 
							"schedules":         returnschedules,
 | 
				
			||||||
 | 
							"driver_options":    map[string]any{},
 | 
				
			||||||
 | 
							"passenger_options": map[string]any{},
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						returntrip, err := return_fc.MarshalJSON()
 | 
				
			||||||
 | 
						if err != nil {
 | 
				
			||||||
 | 
							log.Error().Err(err).Msg("failed parsong return geojson")
 | 
				
			||||||
 | 
							w.WriteHeader(http.StatusInternalServerError)
 | 
				
			||||||
 | 
							return
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						trips = append(trips, &proto.CarpoolFeatureCollection{
 | 
				
			||||||
 | 
							Serialized: string(outwardtrip),
 | 
				
			||||||
 | 
						})
 | 
				
			||||||
 | 
						trips = append(trips, &proto.CarpoolFeatureCollection{
 | 
				
			||||||
 | 
							Serialized: string(returntrip),
 | 
				
			||||||
 | 
						})
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						req := &proto.CreateRegularRoutesRequest{
 | 
				
			||||||
 | 
							Routes: trips,
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						_, err = h.services.GRPC.CarpoolService.CreateRegularRoutes(context.Background(), req)
 | 
				
			||||||
 | 
						if err != nil {
 | 
				
			||||||
 | 
							log.Error().Err(err).Msg("could not create regular routes")
 | 
				
			||||||
 | 
							w.WriteHeader(http.StatusInternalServerError)
 | 
				
			||||||
 | 
							return
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						log.Info().Msg("Finished creating carpool routes")
 | 
				
			||||||
 | 
						http.Redirect(w, r, fmt.Sprintf("/app/organized-carpool/drivers/%s", driverID), http.StatusFound)
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					func (h *ApplicationHandler) OrganizedCarpoolDeleteTrip(w http.ResponseWriter, r *http.Request) {
 | 
				
			||||||
 | 
						vars := mux.Vars(r)
 | 
				
			||||||
 | 
						driverID := vars["driverid"]
 | 
				
			||||||
 | 
						tripID := vars["tripid"]
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						req := &proto.DeleteRegularRoutesRequest{
 | 
				
			||||||
 | 
							Ids: []string{tripID},
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						_, err := h.services.GRPC.CarpoolService.DeleteRegularRoutes(context.Background(), req)
 | 
				
			||||||
 | 
						if err != nil {
 | 
				
			||||||
 | 
							log.Error().Err(err).Msg("could not delete regular routes")
 | 
				
			||||||
 | 
							w.WriteHeader(http.StatusInternalServerError)
 | 
				
			||||||
 | 
							return
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						http.Redirect(w, r, fmt.Sprintf("/app/organized-carpool/drivers/%s", driverID), http.StatusFound)
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					func (h *ApplicationHandler) OrganizedCarpoolJourney(w http.ResponseWriter, r *http.Request) {
 | 
				
			||||||
 | 
						vars := mux.Vars(r)
 | 
				
			||||||
 | 
						driverId := vars["driverid"]
 | 
				
			||||||
 | 
						journeyId := vars["journeyid"]
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						var passenger mobilityaccountsstorage.Account
 | 
				
			||||||
 | 
						passengerId := r.URL.Query().Get("passengerid")
 | 
				
			||||||
 | 
						log.Info().Str("journeyid", journeyId).Str("driverid", driverId).Str("passengerid", passengerId).Msg("driver journey")
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						journeyResp, err := h.services.GRPC.CarpoolService.GetPlannedTrip(context.Background(), &proto.GetPlannedTripRequest{
 | 
				
			||||||
 | 
							Id: journeyId,
 | 
				
			||||||
 | 
						})
 | 
				
			||||||
 | 
						if err != nil {
 | 
				
			||||||
 | 
							log.Error().Err(err).Msg("could not get driver journey")
 | 
				
			||||||
 | 
							w.WriteHeader(http.StatusNotFound)
 | 
				
			||||||
 | 
							return
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						journey, err := geojson.UnmarshalFeatureCollection([]byte(journeyResp.PlannedTrip.Serialized))
 | 
				
			||||||
 | 
						if err != nil {
 | 
				
			||||||
 | 
							log.Error().Err(err).Msg("could not unmarshal driver journey")
 | 
				
			||||||
 | 
							w.WriteHeader(http.StatusNotFound)
 | 
				
			||||||
 | 
							return
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						if r.Method == "POST" {
 | 
				
			||||||
 | 
							if passengerId == "" {
 | 
				
			||||||
 | 
								log.Error().Err(err).Msg("could not get driver journey")
 | 
				
			||||||
 | 
								w.WriteHeader(http.StatusNotFound)
 | 
				
			||||||
 | 
								return
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							/*if _, err := h.services.GRPC.CarpoolService.CreateBooking(context.Background(), &proto.CreateCarpoolBookingRequest{
 | 
				
			||||||
 | 
								Booking: &proto.CarpoolServiceBooking{
 | 
				
			||||||
 | 
									Passenger: &proto.CarpoolServiceUser{
 | 
				
			||||||
 | 
										Id: passengerId,
 | 
				
			||||||
 | 
									},
 | 
				
			||||||
 | 
									Driver: &proto.CarpoolServiceUser{
 | 
				
			||||||
 | 
										Id: driverId,
 | 
				
			||||||
 | 
									},
 | 
				
			||||||
 | 
								}
 | 
				
			||||||
 | 
								PassengerId:     passengerId,
 | 
				
			||||||
 | 
								DriverId:        driverId,
 | 
				
			||||||
 | 
								DriverJourneyId: journeyId,
 | 
				
			||||||
 | 
							}); err != nil {
 | 
				
			||||||
 | 
								log.Error().Err(err).Msg("cannot create booking")
 | 
				
			||||||
 | 
								w.WriteHeader(http.StatusInternalServerError)
 | 
				
			||||||
 | 
								return
 | 
				
			||||||
 | 
							}*/
 | 
				
			||||||
 | 
							http.Redirect(w, r, fmt.Sprintf("/app/organized_carpool/"), http.StatusFound)
 | 
				
			||||||
 | 
							return
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						driver, err := h.services.GetAccount(driverId)
 | 
				
			||||||
 | 
						if err != nil {
 | 
				
			||||||
 | 
							log.Error().Err(err).Msg("could not get driver")
 | 
				
			||||||
 | 
							w.WriteHeader(http.StatusNotFound)
 | 
				
			||||||
 | 
							return
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						if passengerId != "" {
 | 
				
			||||||
 | 
							passenger, err = h.services.GetAccount(passengerId)
 | 
				
			||||||
 | 
							if err != nil {
 | 
				
			||||||
 | 
								log.Error().Err(err).Msg("could not get account")
 | 
				
			||||||
 | 
								w.WriteHeader(http.StatusNotFound)
 | 
				
			||||||
 | 
								return
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						beneficiaries, err := h.beneficiaries(r)
 | 
				
			||||||
 | 
						if err != nil {
 | 
				
			||||||
 | 
							log.Error().Err(err).Msg("")
 | 
				
			||||||
 | 
							w.WriteHeader(http.StatusBadRequest)
 | 
				
			||||||
 | 
							return
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						/*driverjourney, err := transformers.DriverJourneyProtoToType(journey.DriverJourney)
 | 
				
			||||||
 | 
						if err != nil {
 | 
				
			||||||
 | 
							log.Error().Err(err).Msg("could not transform driver journey type")
 | 
				
			||||||
 | 
							w.WriteHeader(http.StatusBadRequest)
 | 
				
			||||||
 | 
							return
 | 
				
			||||||
 | 
						}*/
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						h.Renderer.OrganizedCarpoolJourney(w, r, journey, driver, passenger, beneficiaries)
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					func parseOrganizedCarpoolDriversForm(r *http.Request) (map[string]any, error) {
 | 
				
			||||||
 | 
						if err := r.ParseForm(); err != nil {
 | 
				
			||||||
 | 
							return nil, err
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						log.Info().Any("form content", r.Form).Msg("parsing form")
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						var date *time.Time
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						if r.PostFormValue("birthdate") != "" {
 | 
				
			||||||
 | 
							d, err := time.Parse("2006-01-02", r.PostFormValue("birthdate"))
 | 
				
			||||||
 | 
							if err != nil {
 | 
				
			||||||
 | 
								return nil, err
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
							date = &d
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						formData := OrganizedCarpoolDriversForm{
 | 
				
			||||||
 | 
							FirstName:   r.PostFormValue("first_name"),
 | 
				
			||||||
 | 
							LastName:    r.PostFormValue("last_name"),
 | 
				
			||||||
 | 
							Email:       r.PostFormValue("email"),
 | 
				
			||||||
 | 
							Birthdate:   date,
 | 
				
			||||||
 | 
							PhoneNumber: r.PostFormValue("phone_number"),
 | 
				
			||||||
 | 
							FileNumber:  r.PostFormValue("file_number"),
 | 
				
			||||||
 | 
							Gender:      r.PostFormValue("gender"),
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						if r.PostFormValue("address") != "" {
 | 
				
			||||||
 | 
							var a any
 | 
				
			||||||
 | 
							json.Unmarshal([]byte(r.PostFormValue("address")), &a)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							formData.Address = a
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						if r.PostFormValue("address_destination") != "" {
 | 
				
			||||||
 | 
							var a any
 | 
				
			||||||
 | 
							json.Unmarshal([]byte(r.PostFormValue("address_destination")), &a)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							formData.AddressDestination = a
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						validate := formvalidators.New()
 | 
				
			||||||
 | 
						if err := validate.Struct(formData); err != nil {
 | 
				
			||||||
 | 
							return nil, err
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						d, err := json.Marshal(formData)
 | 
				
			||||||
 | 
						if err != nil {
 | 
				
			||||||
 | 
							return nil, err
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						var dataMap map[string]any
 | 
				
			||||||
 | 
						err = json.Unmarshal(d, &dataMap)
 | 
				
			||||||
 | 
						if err != nil {
 | 
				
			||||||
 | 
							return nil, err
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						return dataMap, nil
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
| 
						 | 
					@ -0,0 +1,58 @@
 | 
				
			||||||
 | 
					package application
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					import (
 | 
				
			||||||
 | 
						"errors"
 | 
				
			||||||
 | 
						"net/http"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						"github.com/rs/zerolog/log"
 | 
				
			||||||
 | 
					)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					func (h *ApplicationHandler) SendSMS(w http.ResponseWriter, r *http.Request) {
 | 
				
			||||||
 | 
						if r.Method != "POST" {
 | 
				
			||||||
 | 
							w.WriteHeader(http.StatusMethodNotAllowed)
 | 
				
			||||||
 | 
							return
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						referer := r.Referer()
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						if err := r.ParseForm(); err != nil {
 | 
				
			||||||
 | 
							log.Error().Err(err).Msg("Bad request")
 | 
				
			||||||
 | 
							w.WriteHeader(http.StatusBadRequest)
 | 
				
			||||||
 | 
							return
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						message := r.PostFormValue("message")
 | 
				
			||||||
 | 
						beneficiaryid := r.PostFormValue("beneficiaryid")
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						h.GenerateSMS(beneficiaryid, message)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						http.Redirect(w, r, referer, http.StatusFound)
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					func (h *ApplicationHandler) GenerateSMS(recipientid string, message string) error {
 | 
				
			||||||
 | 
						recipient, err := h.services.GetAccount(recipientid)
 | 
				
			||||||
 | 
						if err != nil {
 | 
				
			||||||
 | 
							log.Error().Err(err).Msg("user not found")
 | 
				
			||||||
 | 
							return err
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						pn, ok := recipient.Data["phone_number"]
 | 
				
			||||||
 | 
						if !ok {
 | 
				
			||||||
 | 
							log.Error().Msg("Beneficiary doesn't have a phone number")
 | 
				
			||||||
 | 
							return errors.New("missing phone number")
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						phoneNumber, ok := pn.(string)
 | 
				
			||||||
 | 
						if !ok {
 | 
				
			||||||
 | 
							log.Error().Msg("phone number type error")
 | 
				
			||||||
 | 
							return errors.New("phone number type error")
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						sender := h.config.GetString("service_name")
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						err = h.services.SMS.Send(phoneNumber, message, sender)
 | 
				
			||||||
 | 
						if err != nil {
 | 
				
			||||||
 | 
							log.Error().Err(err).Msg("cannot send SMS")
 | 
				
			||||||
 | 
							return err
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						return nil
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
| 
						 | 
					@ -0,0 +1,80 @@
 | 
				
			||||||
 | 
					package application
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					import (
 | 
				
			||||||
 | 
						"context"
 | 
				
			||||||
 | 
						"net/http"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						"git.coopgo.io/coopgo-platform/solidarity-transport/servers/grpc/proto/gen"
 | 
				
			||||||
 | 
						"git.coopgo.io/coopgo-platform/solidarity-transport/servers/grpc/transformers"
 | 
				
			||||||
 | 
						"github.com/gorilla/mux"
 | 
				
			||||||
 | 
						"github.com/rs/zerolog/log"
 | 
				
			||||||
 | 
					)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					func (h *ApplicationHandler) SolidarityTransportExternalBookingProposal(w http.ResponseWriter, r *http.Request) {
 | 
				
			||||||
 | 
						vars := mux.Vars(r)
 | 
				
			||||||
 | 
						bookingId := vars["bookingid"]
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						resp, err := h.services.GRPC.SolidarityTransport.GetSolidarityTransportBooking(context.Background(), &gen.GetSolidarityTransportBookingRequest{
 | 
				
			||||||
 | 
							Id: bookingId,
 | 
				
			||||||
 | 
						})
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						booking, err := transformers.BookingProtoToType(resp.Booking)
 | 
				
			||||||
 | 
						if err != nil {
 | 
				
			||||||
 | 
							log.Error().Err(err).Msg("could not transform booking type")
 | 
				
			||||||
 | 
							w.WriteHeader(http.StatusBadRequest)
 | 
				
			||||||
 | 
							return
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						driver, err := h.services.GetAccount(booking.DriverId)
 | 
				
			||||||
 | 
						if err != nil {
 | 
				
			||||||
 | 
							log.Error().Err(err).Msg("driver retrieval issue")
 | 
				
			||||||
 | 
							w.WriteHeader(http.StatusInternalServerError)
 | 
				
			||||||
 | 
							return
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						passenger, err := h.services.GetAccount(booking.PassengerId)
 | 
				
			||||||
 | 
						if err != nil {
 | 
				
			||||||
 | 
							log.Error().Err(err).Msg("passenger retrieval issue")
 | 
				
			||||||
 | 
							w.WriteHeader(http.StatusInternalServerError)
 | 
				
			||||||
 | 
							return
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						if r.Method == "POST" {
 | 
				
			||||||
 | 
							if err = r.ParseForm(); err != nil {
 | 
				
			||||||
 | 
								log.Error().Err(err).Msg("error parsing form data")
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
							message := r.FormValue("message")
 | 
				
			||||||
 | 
							action := r.FormValue("action")
 | 
				
			||||||
 | 
							var status string
 | 
				
			||||||
 | 
							if action == "confirm" {
 | 
				
			||||||
 | 
								status = "VALIDATED"
 | 
				
			||||||
 | 
							} else if action == "cancel" {
 | 
				
			||||||
 | 
								status = "CANCELLED"
 | 
				
			||||||
 | 
							} else if action == "waitconfirmation" {
 | 
				
			||||||
 | 
								status = "WAITING_CONFIRMATION"
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
							if status != "" {
 | 
				
			||||||
 | 
								if _, err := h.services.GRPC.SolidarityTransport.UpdateSolidarityTransportBookingStatus(context.Background(), &gen.UpdateSolidarityTransportBookingStatusRequest{
 | 
				
			||||||
 | 
									BookingId: bookingId,
 | 
				
			||||||
 | 
									NewStatus: status,
 | 
				
			||||||
 | 
									Reason:    "Refusé par le bénévole",
 | 
				
			||||||
 | 
								}); err != nil {
 | 
				
			||||||
 | 
									log.Error().Err(err).Msg("update booking status issue")
 | 
				
			||||||
 | 
									w.WriteHeader(http.StatusInternalServerError)
 | 
				
			||||||
 | 
									return
 | 
				
			||||||
 | 
								}
 | 
				
			||||||
 | 
								booking.Status = status
 | 
				
			||||||
 | 
								if status == "VALIDATED" {
 | 
				
			||||||
 | 
									h.GenerateSMS(passenger.ID, message)
 | 
				
			||||||
 | 
								} else if status == "CANCELLED" {
 | 
				
			||||||
 | 
									if err := h.creditWallet(passenger.ID, booking.Journey.Price.Amount); err != nil {
 | 
				
			||||||
 | 
										log.Error().Err(err).Msg("could not credit wallet")
 | 
				
			||||||
 | 
										w.WriteHeader(http.StatusInternalServerError)
 | 
				
			||||||
 | 
										return
 | 
				
			||||||
 | 
									}
 | 
				
			||||||
 | 
								}
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						h.Renderer.SolidarityTransportExternalBookingDisplay(w, r, booking, driver, passenger)
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
| 
						 | 
					@ -1,23 +1,34 @@
 | 
				
			||||||
package application
 | 
					package application
 | 
				
			||||||
 | 
					
 | 
				
			||||||
import (
 | 
					import (
 | 
				
			||||||
 | 
						"cmp"
 | 
				
			||||||
	"context"
 | 
						"context"
 | 
				
			||||||
	"encoding/json"
 | 
						"encoding/json"
 | 
				
			||||||
	"errors"
 | 
					 | 
				
			||||||
	"fmt"
 | 
						"fmt"
 | 
				
			||||||
 | 
						"io"
 | 
				
			||||||
	"net/http"
 | 
						"net/http"
 | 
				
			||||||
	"reflect"
 | 
						"slices"
 | 
				
			||||||
	"sort"
 | 
						"sort"
 | 
				
			||||||
 | 
						"strconv"
 | 
				
			||||||
 | 
						"strings"
 | 
				
			||||||
	"time"
 | 
						"time"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						mobilityaccounts "git.coopgo.io/coopgo-platform/mobility-accounts/grpcapi"
 | 
				
			||||||
 | 
						mobilityaccountsstorage "git.coopgo.io/coopgo-platform/mobility-accounts/storage"
 | 
				
			||||||
 | 
						"git.coopgo.io/coopgo-platform/payments/pricing"
 | 
				
			||||||
 | 
						"git.coopgo.io/coopgo-platform/solidarity-transport/servers/grpc/proto/gen"
 | 
				
			||||||
 | 
						"git.coopgo.io/coopgo-platform/solidarity-transport/servers/grpc/transformers"
 | 
				
			||||||
 | 
						"git.coopgo.io/coopgo-platform/solidarity-transport/types"
 | 
				
			||||||
 | 
						"github.com/google/uuid"
 | 
				
			||||||
 | 
						"github.com/gorilla/mux"
 | 
				
			||||||
 | 
						"github.com/paulmach/orb/geojson"
 | 
				
			||||||
 | 
						"github.com/rs/zerolog/log"
 | 
				
			||||||
 | 
						"google.golang.org/protobuf/types/known/structpb"
 | 
				
			||||||
 | 
						"google.golang.org/protobuf/types/known/timestamppb"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	formvalidators "git.coopgo.io/coopgo-apps/parcoursmob/utils/form-validators"
 | 
						formvalidators "git.coopgo.io/coopgo-apps/parcoursmob/utils/form-validators"
 | 
				
			||||||
	"git.coopgo.io/coopgo-apps/parcoursmob/utils/sorting"
 | 
						"git.coopgo.io/coopgo-apps/parcoursmob/utils/sorting"
 | 
				
			||||||
	mobilityaccounts "git.coopgo.io/coopgo-platform/mobility-accounts/grpcapi"
 | 
						filestorage "git.coopgo.io/coopgo-apps/parcoursmob/utils/storage"
 | 
				
			||||||
	mobilityaccountsstorage "git.coopgo.io/coopgo-platform/mobility-accounts/storage"
 | 
					 | 
				
			||||||
	"github.com/google/uuid"
 | 
					 | 
				
			||||||
	"github.com/gorilla/mux"
 | 
					 | 
				
			||||||
	"github.com/rs/zerolog/log"
 | 
					 | 
				
			||||||
	"google.golang.org/protobuf/types/known/structpb"
 | 
					 | 
				
			||||||
)
 | 
					)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
type DriversForm struct {
 | 
					type DriversForm struct {
 | 
				
			||||||
| 
						 | 
					@ -43,16 +54,68 @@ const (
 | 
				
			||||||
func (h *ApplicationHandler) SolidarityTransportOverview(w http.ResponseWriter, r *http.Request) {
 | 
					func (h *ApplicationHandler) SolidarityTransportOverview(w http.ResponseWriter, r *http.Request) {
 | 
				
			||||||
	accounts, err := h.solidarityDrivers(r)
 | 
						accounts, err := h.solidarityDrivers(r)
 | 
				
			||||||
	if err != nil {
 | 
						if err != nil {
 | 
				
			||||||
		log.Error().Err(err).Msg("")
 | 
							log.Error().Err(err).Msg("issue getting solidarity drivers")
 | 
				
			||||||
		w.WriteHeader(http.StatusBadRequest)
 | 
							accounts = []mobilityaccountsstorage.Account{}
 | 
				
			||||||
		return
 | 
					 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	sort.Sort(sorting.SolidarityDriversByName(accounts))
 | 
						accountsMap := map[string]mobilityaccountsstorage.Account{}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	// cacheid := uuid.NewString()
 | 
						for _, a := range accounts {
 | 
				
			||||||
	// h.cache.PutWithTTL(cacheid, accounts, 1*time.Hour)
 | 
							accountsMap[a.ID] = a
 | 
				
			||||||
	h.Renderer.SolidarityTransportOverview(w, r, accounts)
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						beneficiariesMap, err := h.services.GetBeneficiariesMap()
 | 
				
			||||||
 | 
						if err != nil {
 | 
				
			||||||
 | 
							beneficiariesMap = map[string]mobilityaccountsstorage.Account{}
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						bookingsproto, err := h.services.GRPC.SolidarityTransport.GetSolidarityTransportBookings(context.Background(), &gen.GetSolidarityTransportBookingsRequest{
 | 
				
			||||||
 | 
							StartDate: timestamppb.Now(),
 | 
				
			||||||
 | 
							EndDate:   timestamppb.New(time.Now().Add(24 * 365 * time.Hour)),
 | 
				
			||||||
 | 
						})
 | 
				
			||||||
 | 
						if err != nil {
 | 
				
			||||||
 | 
							log.Error().Err(err).Msg("issue retreving bookings")
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						bookings := []*types.Booking{}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						if err == nil {
 | 
				
			||||||
 | 
							for _, b := range bookingsproto.Bookings {
 | 
				
			||||||
 | 
								booking, _ := transformers.BookingProtoToType(b)
 | 
				
			||||||
 | 
								bookings = append(bookings, booking)
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						bookingshistoryproto, err := h.services.GRPC.SolidarityTransport.GetSolidarityTransportBookings(context.Background(), &gen.GetSolidarityTransportBookingsRequest{
 | 
				
			||||||
 | 
							EndDate:   timestamppb.Now(),
 | 
				
			||||||
 | 
							StartDate: timestamppb.New(time.Now().Add(-1 * 24 * 365 * time.Hour)),
 | 
				
			||||||
 | 
						})
 | 
				
			||||||
 | 
						if err != nil {
 | 
				
			||||||
 | 
							log.Error().Err(err).Msg("issue retreving bookings")
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						bookingshistory := []*types.Booking{}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						if err == nil {
 | 
				
			||||||
 | 
							for _, b := range bookingshistoryproto.Bookings {
 | 
				
			||||||
 | 
								booking, _ := transformers.BookingProtoToType(b)
 | 
				
			||||||
 | 
								bookingshistory = append(bookingshistory, booking)
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						slices.SortFunc(accounts, func(a, b mobilityaccountsstorage.Account) int {
 | 
				
			||||||
 | 
							return strings.Compare(
 | 
				
			||||||
 | 
								strings.ToLower(fmt.Sprintf("%s %s", a.Data["first_name"].(string), a.Data["last_name"].(string))),
 | 
				
			||||||
 | 
								strings.ToLower(fmt.Sprintf("%s %s", b.Data["first_name"].(string), b.Data["last_name"].(string))),
 | 
				
			||||||
 | 
							)
 | 
				
			||||||
 | 
						})
 | 
				
			||||||
 | 
						slices.SortFunc(bookings, func(a, b *types.Booking) int {
 | 
				
			||||||
 | 
							return cmp.Compare(a.Journey.PassengerPickupDate.Unix(), b.Journey.PassengerPickupDate.Unix())
 | 
				
			||||||
 | 
						})
 | 
				
			||||||
 | 
						slices.SortFunc(bookingshistory, func(a, b *types.Booking) int {
 | 
				
			||||||
 | 
							return cmp.Compare(a.Journey.PassengerPickupDate.Unix(), b.Journey.PassengerPickupDate.Unix())
 | 
				
			||||||
 | 
						})
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						h.Renderer.SolidarityTransportOverview(w, r, accounts, accountsMap, beneficiariesMap, bookings, bookingshistory)
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
func (h *ApplicationHandler) SolidarityTransportCreateDriver(w http.ResponseWriter, r *http.Request) {
 | 
					func (h *ApplicationHandler) SolidarityTransportCreateDriver(w http.ResponseWriter, r *http.Request) {
 | 
				
			||||||
| 
						 | 
					@ -92,7 +155,7 @@ func (h *ApplicationHandler) SolidarityTransportCreateDriver(w http.ResponseWrit
 | 
				
			||||||
	h.Renderer.SolidarityTransportCreateDriver(w, r)
 | 
						h.Renderer.SolidarityTransportCreateDriver(w, r)
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
func (h *ApplicationHandler) SolidarityTransportDriverDisplay(w http.ResponseWriter, r *http.Request) {
 | 
					func (h *ApplicationHandler) SolidarityTransportUpdateDriver(w http.ResponseWriter, r *http.Request) {
 | 
				
			||||||
	vars := mux.Vars(r)
 | 
						vars := mux.Vars(r)
 | 
				
			||||||
	driverID := vars["driverid"]
 | 
						driverID := vars["driverid"]
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					@ -102,7 +165,94 @@ func (h *ApplicationHandler) SolidarityTransportDriverDisplay(w http.ResponseWri
 | 
				
			||||||
		w.WriteHeader(http.StatusInternalServerError)
 | 
							w.WriteHeader(http.StatusInternalServerError)
 | 
				
			||||||
		return
 | 
							return
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
	h.Renderer.SolidarityTransportDriverDisplay(w, r, driver)
 | 
					
 | 
				
			||||||
 | 
						if r.Method == "POST" {
 | 
				
			||||||
 | 
							dataMap, err := parseBeneficiariesForm(r)
 | 
				
			||||||
 | 
							if err != nil {
 | 
				
			||||||
 | 
								log.Error().Err(err).Msg("")
 | 
				
			||||||
 | 
								w.WriteHeader(http.StatusBadRequest)
 | 
				
			||||||
 | 
								return
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							data, err := structpb.NewValue(dataMap)
 | 
				
			||||||
 | 
							if err != nil {
 | 
				
			||||||
 | 
								log.Error().Err(err).Msg("")
 | 
				
			||||||
 | 
								w.WriteHeader(http.StatusInternalServerError)
 | 
				
			||||||
 | 
								return
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							request := &mobilityaccounts.UpdateDataRequest{
 | 
				
			||||||
 | 
								Account: &mobilityaccounts.Account{
 | 
				
			||||||
 | 
									Id:        driverID,
 | 
				
			||||||
 | 
									Namespace: "solidarity_drivers",
 | 
				
			||||||
 | 
									Data:      data.GetStructValue(),
 | 
				
			||||||
 | 
								},
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							resp, err := h.services.GRPC.MobilityAccounts.UpdateData(context.TODO(), request)
 | 
				
			||||||
 | 
							if err != nil {
 | 
				
			||||||
 | 
								log.Error().Err(err).Msg("")
 | 
				
			||||||
 | 
								w.WriteHeader(http.StatusInternalServerError)
 | 
				
			||||||
 | 
								return
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							http.Redirect(w, r, fmt.Sprintf("/app/solidarity-transport/drivers/%s", resp.Account.Id), http.StatusFound)
 | 
				
			||||||
 | 
							return
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						h.Renderer.SolidarityTransportUpdateDriver(w, r, driver)
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					func (h *ApplicationHandler) SolidarityTransportDriverDisplay(w http.ResponseWriter, r *http.Request) {
 | 
				
			||||||
 | 
						vars := mux.Vars(r)
 | 
				
			||||||
 | 
						driverID := vars["driverid"]
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						documents := h.filestorage.List(filestorage.PREFIX_SOLIDARITY_TRANSPORT_DRIVERS + "/" + driverID)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						driver, err := h.services.GetAccount(driverID)
 | 
				
			||||||
 | 
						if err != nil {
 | 
				
			||||||
 | 
							log.Error().Err(err).Msg("Issue retrieving driver account")
 | 
				
			||||||
 | 
							w.WriteHeader(http.StatusInternalServerError)
 | 
				
			||||||
 | 
							return
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						availabilities := []*gen.DriverRegularAvailability{}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						resp, err := h.services.GRPC.SolidarityTransport.GetDriverRegularAvailabilities(context.Background(), &gen.GetDriverRegularAvailabilitiesRequest{DriverId: driverID})
 | 
				
			||||||
 | 
						if err != nil {
 | 
				
			||||||
 | 
							log.Error().Err(err).Msg("error calling GetDriverRegularAvailabilities")
 | 
				
			||||||
 | 
						} else {
 | 
				
			||||||
 | 
							availabilities = resp.Results
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						sort.Sort(sorting.SolidarityAvailabilitiesByDay(availabilities))
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						bookingsresp, err := h.services.GRPC.SolidarityTransport.GetSolidarityTransportBookings(context.Background(), &gen.GetSolidarityTransportBookingsRequest{Driverid: driverID})
 | 
				
			||||||
 | 
						if err != nil {
 | 
				
			||||||
 | 
							log.Error().Err(err).Msg("could not get driver bookings")
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						log.Debug().Any("bookings", bookingsresp.Bookings).Msg("bookings list")
 | 
				
			||||||
 | 
						kmnb := int64(0)
 | 
				
			||||||
 | 
						bookings := slices.Collect(func(yield func(*gen.SolidarityTransportBooking) bool) {
 | 
				
			||||||
 | 
							for _, b := range bookingsresp.Bookings {
 | 
				
			||||||
 | 
								log.Debug().Str("bokking status", b.Status).Msg("candidate booking")
 | 
				
			||||||
 | 
								if b.Status == "VALIDATED" {
 | 
				
			||||||
 | 
									kmnb = kmnb + b.Journey.DriverDistance
 | 
				
			||||||
 | 
									if !yield(b) {
 | 
				
			||||||
 | 
										return
 | 
				
			||||||
 | 
									}
 | 
				
			||||||
 | 
								}
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
						})
 | 
				
			||||||
 | 
						log.Debug().Any("bookings", bookings).Msg("bookings list")
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						stats := map[string]any{
 | 
				
			||||||
 | 
							"bookings": map[string]any{
 | 
				
			||||||
 | 
								"count": len(bookings),
 | 
				
			||||||
 | 
								"km":    kmnb,
 | 
				
			||||||
 | 
							},
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						h.Renderer.SolidarityTransportDriverDisplay(w, r, driver, availabilities, documents, bookings, stats)
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
func (h *ApplicationHandler) SolidarityTransportAddAvailability(w http.ResponseWriter, r *http.Request) {
 | 
					func (h *ApplicationHandler) SolidarityTransportAddAvailability(w http.ResponseWriter, r *http.Request) {
 | 
				
			||||||
| 
						 | 
					@ -121,105 +271,164 @@ func (h *ApplicationHandler) SolidarityTransportAddAvailability(w http.ResponseW
 | 
				
			||||||
	vars := mux.Vars(r)
 | 
						vars := mux.Vars(r)
 | 
				
			||||||
	driverID := vars["driverid"]
 | 
						driverID := vars["driverid"]
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	availabilities := []any{}
 | 
						availabilities := []*gen.DriverRegularAvailability{}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						starttime := r.PostFormValue("starttime")
 | 
				
			||||||
 | 
						endtime := r.PostFormValue("endtime")
 | 
				
			||||||
 | 
						address := r.PostFormValue("address")
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	if r.PostFormValue("days.monday") == "on" {
 | 
						if r.PostFormValue("days.monday") == "on" {
 | 
				
			||||||
		a := map[string]any{
 | 
							a := &gen.DriverRegularAvailability{
 | 
				
			||||||
			"id":         uuid.NewString(),
 | 
								DriverId:  driverID,
 | 
				
			||||||
			"day":        Monday,
 | 
								Day:       Monday,
 | 
				
			||||||
			"start_time": r.PostFormValue("starttime"),
 | 
								StartTime: starttime,
 | 
				
			||||||
			"end_time":   r.PostFormValue("endtime"),
 | 
								EndTime:   endtime,
 | 
				
			||||||
 | 
								Address: &gen.GeoJsonFeature{
 | 
				
			||||||
 | 
									Serialized: address,
 | 
				
			||||||
 | 
								},
 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
		availabilities = append(availabilities, a)
 | 
							availabilities = append(availabilities, a)
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
	if r.PostFormValue("days.tuesday") == "on" {
 | 
						if r.PostFormValue("days.tuesday") == "on" {
 | 
				
			||||||
		a := map[string]any{
 | 
							a := &gen.DriverRegularAvailability{
 | 
				
			||||||
			"id":         uuid.NewString(),
 | 
								DriverId:  driverID,
 | 
				
			||||||
			"day":        Tuesday,
 | 
								Day:       Tuesday,
 | 
				
			||||||
			"start_time": r.PostFormValue("starttime"),
 | 
								StartTime: starttime,
 | 
				
			||||||
			"end_time":   r.PostFormValue("endtime"),
 | 
								EndTime:   endtime,
 | 
				
			||||||
 | 
								Address: &gen.GeoJsonFeature{
 | 
				
			||||||
 | 
									Serialized: address,
 | 
				
			||||||
 | 
								},
 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
		availabilities = append(availabilities, a)
 | 
							availabilities = append(availabilities, a)
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
	if r.PostFormValue("days.Wednesday") == "on" {
 | 
						if r.PostFormValue("days.wednesday") == "on" {
 | 
				
			||||||
		a := map[string]any{
 | 
							a := &gen.DriverRegularAvailability{
 | 
				
			||||||
			"id":         uuid.NewString(),
 | 
								DriverId:  driverID,
 | 
				
			||||||
			"day":        Wednesday,
 | 
								Day:       Wednesday,
 | 
				
			||||||
			"start_time": r.PostFormValue("starttime"),
 | 
								StartTime: starttime,
 | 
				
			||||||
			"end_time":   r.PostFormValue("endtime"),
 | 
								EndTime:   endtime,
 | 
				
			||||||
 | 
								Address: &gen.GeoJsonFeature{
 | 
				
			||||||
 | 
									Serialized: address,
 | 
				
			||||||
 | 
								},
 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
		availabilities = append(availabilities, a)
 | 
							availabilities = append(availabilities, a)
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
	if r.PostFormValue("days.thursday") == "on" {
 | 
						if r.PostFormValue("days.thursday") == "on" {
 | 
				
			||||||
		a := map[string]any{
 | 
							a := &gen.DriverRegularAvailability{
 | 
				
			||||||
			"id":         uuid.NewString(),
 | 
								DriverId:  driverID,
 | 
				
			||||||
			"day":        Thursday,
 | 
								Day:       Thursday,
 | 
				
			||||||
			"start_time": r.PostFormValue("starttime"),
 | 
								StartTime: starttime,
 | 
				
			||||||
			"end_time":   r.PostFormValue("endtime"),
 | 
								EndTime:   endtime,
 | 
				
			||||||
 | 
								Address: &gen.GeoJsonFeature{
 | 
				
			||||||
 | 
									Serialized: address,
 | 
				
			||||||
 | 
								},
 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
		availabilities = append(availabilities, a)
 | 
							availabilities = append(availabilities, a)
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
	if r.PostFormValue("days.friday") == "on" {
 | 
						if r.PostFormValue("days.friday") == "on" {
 | 
				
			||||||
		a := map[string]any{
 | 
							a := &gen.DriverRegularAvailability{
 | 
				
			||||||
			"id":         uuid.NewString(),
 | 
								DriverId:  driverID,
 | 
				
			||||||
			"day":        Friday,
 | 
								Day:       Friday,
 | 
				
			||||||
			"start_time": r.PostFormValue("starttime"),
 | 
								StartTime: starttime,
 | 
				
			||||||
			"end_time":   r.PostFormValue("endtime"),
 | 
								EndTime:   endtime,
 | 
				
			||||||
 | 
								Address: &gen.GeoJsonFeature{
 | 
				
			||||||
 | 
									Serialized: address,
 | 
				
			||||||
 | 
								},
 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
		availabilities = append(availabilities, a)
 | 
							availabilities = append(availabilities, a)
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
	if r.PostFormValue("days.saturday") == "on" {
 | 
						if r.PostFormValue("days.saturday") == "on" {
 | 
				
			||||||
		a := map[string]any{
 | 
							a := &gen.DriverRegularAvailability{
 | 
				
			||||||
			"id":         uuid.NewString(),
 | 
								DriverId:  driverID,
 | 
				
			||||||
			"day":        Saturday,
 | 
								Day:       Saturday,
 | 
				
			||||||
			"start_time": r.PostFormValue("starttime"),
 | 
								StartTime: starttime,
 | 
				
			||||||
			"end_time":   r.PostFormValue("endtime"),
 | 
								EndTime:   endtime,
 | 
				
			||||||
 | 
								Address: &gen.GeoJsonFeature{
 | 
				
			||||||
 | 
									Serialized: address,
 | 
				
			||||||
 | 
								},
 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
		availabilities = append(availabilities, a)
 | 
							availabilities = append(availabilities, a)
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
	if r.PostFormValue("days.sunday") == "on" {
 | 
						if r.PostFormValue("days.sunday") == "on" {
 | 
				
			||||||
		a := map[string]any{
 | 
							a := &gen.DriverRegularAvailability{
 | 
				
			||||||
			"id":         uuid.NewString(),
 | 
								DriverId:  driverID,
 | 
				
			||||||
			"day":        Sunday,
 | 
								Day:       Sunday,
 | 
				
			||||||
			"start_time": r.PostFormValue("starttime"),
 | 
								StartTime: starttime,
 | 
				
			||||||
			"end_time":   r.PostFormValue("endtime"),
 | 
								EndTime:   endtime,
 | 
				
			||||||
 | 
								Address: &gen.GeoJsonFeature{
 | 
				
			||||||
 | 
									Serialized: address,
 | 
				
			||||||
 | 
								},
 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
		availabilities = append(availabilities, a)
 | 
							availabilities = append(availabilities, a)
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	account, err := h.services.GetAccount(driverID)
 | 
						req := &gen.AddDriverRegularAvailabilitiesRequest{
 | 
				
			||||||
 | 
							Availabilities: availabilities,
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						_, err := h.services.GRPC.SolidarityTransport.AddDriverRegularAvailabilities(context.Background(), req)
 | 
				
			||||||
	if err != nil {
 | 
						if err != nil {
 | 
				
			||||||
		log.Error().Err(err).Msg("driver not found")
 | 
							log.Error().Err(err).Msg("could not add availabilities")
 | 
				
			||||||
		w.WriteHeader(http.StatusNotFound)
 | 
							w.WriteHeader(http.StatusInternalServerError)
 | 
				
			||||||
		return
 | 
							return
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	existing_availabilities, ok := account.Data["solidarity_transport_availabilities"].([]any)
 | 
						log.Info().Msg("Finished creating availabilities")
 | 
				
			||||||
	if !ok {
 | 
						http.Redirect(w, r, fmt.Sprintf("/app/solidarity-transport/drivers/%s", driverID), http.StatusFound)
 | 
				
			||||||
		existing_availabilities = []any{}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					func (h *ApplicationHandler) SolidarityTransportUnarchiveDriver(w http.ResponseWriter, r *http.Request) {
 | 
				
			||||||
 | 
						vars := mux.Vars(r)
 | 
				
			||||||
 | 
						driverID := vars["driverid"]
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						data, _ := structpb.NewValue(map[string]any{
 | 
				
			||||||
 | 
							"archived": false,
 | 
				
			||||||
 | 
						})
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						request := &mobilityaccounts.UpdateDataRequest{
 | 
				
			||||||
 | 
							Account: &mobilityaccounts.Account{
 | 
				
			||||||
 | 
								Id:        driverID,
 | 
				
			||||||
 | 
								Namespace: "solidarity_transport_drivers",
 | 
				
			||||||
 | 
								Data:      data.GetStructValue(),
 | 
				
			||||||
 | 
							},
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	for _, av := range availabilities {
 | 
						resp, err := h.services.GRPC.MobilityAccounts.UpdateData(context.TODO(), request)
 | 
				
			||||||
		existing_availabilities = append(existing_availabilities, av)
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	account.Data["solidarity_transport_availabilities"] = existing_availabilities
 | 
					 | 
				
			||||||
	data, err := structpb.NewValue(account.Data)
 | 
					 | 
				
			||||||
	if err != nil {
 | 
						if err != nil {
 | 
				
			||||||
		log.Error().Err(err).Msg("")
 | 
							log.Error().Err(err).Msg("")
 | 
				
			||||||
		w.WriteHeader(http.StatusInternalServerError)
 | 
							w.WriteHeader(http.StatusInternalServerError)
 | 
				
			||||||
		return
 | 
							return
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	request := &mobilityaccounts.UpdateDataRequest{
 | 
						http.Redirect(w, r, fmt.Sprintf("/app/solidarity-transport/drivers/%s", resp.Account.Id), http.StatusFound)
 | 
				
			||||||
		Account: &mobilityaccounts.Account{
 | 
					}
 | 
				
			||||||
			Id:        account.ID,
 | 
					
 | 
				
			||||||
			Namespace: account.Namespace,
 | 
					func (h *ApplicationHandler) SolidarityTransportDriverDocuments(w http.ResponseWriter, r *http.Request) {
 | 
				
			||||||
			Data:      data.GetStructValue(),
 | 
						vars := mux.Vars(r)
 | 
				
			||||||
		},
 | 
						driverID := vars["driverid"]
 | 
				
			||||||
	}
 | 
					
 | 
				
			||||||
	_, err = h.services.GRPC.MobilityAccounts.UpdateData(context.TODO(), request)
 | 
						// r.ParseForm()
 | 
				
			||||||
 | 
						r.ParseMultipartForm(100 * 1024 * 1024)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						document_type := r.FormValue("type")
 | 
				
			||||||
 | 
						document_name := r.FormValue("name")
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						file, header, err := r.FormFile("file-upload")
 | 
				
			||||||
	if err != nil {
 | 
						if err != nil {
 | 
				
			||||||
 | 
							log.Error().Err(err).Msg("")
 | 
				
			||||||
 | 
							return
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						defer file.Close()
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						fileid := uuid.NewString()
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						metadata := map[string]string{
 | 
				
			||||||
 | 
							"type": document_type,
 | 
				
			||||||
 | 
							"name": document_name,
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						log.Debug().Any("metadata", metadata).Msg("Metadata")
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						if err := h.filestorage.Put(file, filestorage.PREFIX_SOLIDARITY_TRANSPORT_DRIVERS, fmt.Sprintf("%s/%s_%s", driverID, fileid, header.Filename), header.Size, metadata); err != nil {
 | 
				
			||||||
		log.Error().Err(err).Msg("")
 | 
							log.Error().Err(err).Msg("")
 | 
				
			||||||
		w.WriteHeader(http.StatusInternalServerError)
 | 
							w.WriteHeader(http.StatusInternalServerError)
 | 
				
			||||||
		return
 | 
							return
 | 
				
			||||||
| 
						 | 
					@ -228,61 +437,402 @@ func (h *ApplicationHandler) SolidarityTransportAddAvailability(w http.ResponseW
 | 
				
			||||||
	http.Redirect(w, r, fmt.Sprintf("/app/solidarity-transport/drivers/%s", driverID), http.StatusFound)
 | 
						http.Redirect(w, r, fmt.Sprintf("/app/solidarity-transport/drivers/%s", driverID), http.StatusFound)
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					func (h *ApplicationHandler) SolidarityTransportDocumentDownload(w http.ResponseWriter, r *http.Request) {
 | 
				
			||||||
 | 
						vars := mux.Vars(r)
 | 
				
			||||||
 | 
						driverID := vars["driverid"]
 | 
				
			||||||
 | 
						document := vars["document"]
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						file, info, err := h.filestorage.Get(filestorage.PREFIX_SOLIDARITY_TRANSPORT_DRIVERS, fmt.Sprintf("%s/%s", driverID, document))
 | 
				
			||||||
 | 
						if err != nil {
 | 
				
			||||||
 | 
							log.Error().Err(err).Msg("")
 | 
				
			||||||
 | 
							w.WriteHeader(http.StatusInternalServerError)
 | 
				
			||||||
 | 
							return
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						w.Header().Set("Content-Type", info.ContentType)
 | 
				
			||||||
 | 
						if _, err = io.Copy(w, file); err != nil {
 | 
				
			||||||
 | 
							log.Error().Err(err).Msg("")
 | 
				
			||||||
 | 
							w.WriteHeader(http.StatusInternalServerError)
 | 
				
			||||||
 | 
							return
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						// http.Redirect(w, r, fmt.Sprintf("/app/solidarity-transport/drivers/%s", driverID), http.StatusFound)
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					func (h *ApplicationHandler) SolidarityTransportArchiveDriver(w http.ResponseWriter, r *http.Request) {
 | 
				
			||||||
 | 
						vars := mux.Vars(r)
 | 
				
			||||||
 | 
						driverID := vars["driverid"]
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						data, _ := structpb.NewValue(map[string]any{
 | 
				
			||||||
 | 
							"archived": true,
 | 
				
			||||||
 | 
						})
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						request := &mobilityaccounts.UpdateDataRequest{
 | 
				
			||||||
 | 
							Account: &mobilityaccounts.Account{
 | 
				
			||||||
 | 
								Id:        driverID,
 | 
				
			||||||
 | 
								Namespace: "solidarity_transport_drivers",
 | 
				
			||||||
 | 
								Data:      data.GetStructValue(),
 | 
				
			||||||
 | 
							},
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						resp, err := h.services.GRPC.MobilityAccounts.UpdateData(context.TODO(), request)
 | 
				
			||||||
 | 
						if err != nil {
 | 
				
			||||||
 | 
							log.Error().Err(err).Msg("")
 | 
				
			||||||
 | 
							w.WriteHeader(http.StatusInternalServerError)
 | 
				
			||||||
 | 
							return
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						http.Redirect(w, r, fmt.Sprintf("/app/solidarity-transport/drivers/%s", resp.Account.Id), http.StatusFound)
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
func (h *ApplicationHandler) SolidarityTransportDeleteAvailability(w http.ResponseWriter, r *http.Request) {
 | 
					func (h *ApplicationHandler) SolidarityTransportDeleteAvailability(w http.ResponseWriter, r *http.Request) {
 | 
				
			||||||
	vars := mux.Vars(r)
 | 
						vars := mux.Vars(r)
 | 
				
			||||||
	driverID := vars["driverid"]
 | 
						driverID := vars["driverid"]
 | 
				
			||||||
	availabilityID := vars["availabilityid"]
 | 
						availabilityID := vars["availabilityid"]
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	account, err := h.services.GetAccount(driverID)
 | 
						req := &gen.DeleteDriverRegularAvailabilityRequest{
 | 
				
			||||||
 | 
							DriverId:       driverID,
 | 
				
			||||||
 | 
							AvailabilityId: availabilityID,
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						if _, err := h.services.GRPC.SolidarityTransport.DeleteDriverRegularAvailability(context.Background(), req); err != nil {
 | 
				
			||||||
 | 
							log.Error().Err(err).Msg("could not delete availability")
 | 
				
			||||||
 | 
							w.WriteHeader(http.StatusNotFound)
 | 
				
			||||||
 | 
							return
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						http.Redirect(w, r, fmt.Sprintf("/app/solidarity-transport/drivers/%s", driverID), http.StatusFound)
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					func (h *ApplicationHandler) SolidarityTransportDriverJourney(w http.ResponseWriter, r *http.Request) {
 | 
				
			||||||
 | 
						vars := mux.Vars(r)
 | 
				
			||||||
 | 
						driverId := vars["driverid"]
 | 
				
			||||||
 | 
						journeyId := vars["journeyid"]
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						var passenger mobilityaccountsstorage.Account
 | 
				
			||||||
 | 
						passengerId := r.URL.Query().Get("passengerid")
 | 
				
			||||||
 | 
						log.Info().Str("journeyid", journeyId).Str("driverid", driverId).Msg("driver journey")
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						journey, err := h.services.GRPC.SolidarityTransport.GetDriverJourney(context.Background(), &gen.GetDriverJourneyRequest{
 | 
				
			||||||
 | 
							DriverId:  driverId,
 | 
				
			||||||
 | 
							JourneyId: journeyId,
 | 
				
			||||||
 | 
						})
 | 
				
			||||||
	if err != nil {
 | 
						if err != nil {
 | 
				
			||||||
		log.Error().Err(err).Msg("driver not found")
 | 
							log.Error().Err(err).Msg("could not get driver journey")
 | 
				
			||||||
		w.WriteHeader(http.StatusNotFound)
 | 
							w.WriteHeader(http.StatusNotFound)
 | 
				
			||||||
		return
 | 
							return
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
						if passengerId != "" {
 | 
				
			||||||
 | 
							passenger, err = h.services.GetAccount(passengerId)
 | 
				
			||||||
 | 
							if err != nil {
 | 
				
			||||||
 | 
								log.Error().Err(err).Msg("could not get account")
 | 
				
			||||||
 | 
								w.WriteHeader(http.StatusNotFound)
 | 
				
			||||||
 | 
								return
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	existing_availabilities, ok := account.Data["solidarity_transport_availabilities"].([]any)
 | 
						j, err := transformers.DriverJourneyProtoToType(journey.DriverJourney)
 | 
				
			||||||
	if !ok {
 | 
						if err != nil {
 | 
				
			||||||
		log.Error().Err(errors.New("no availability found")).Msg("no availability")
 | 
							log.Error().Err(err).Msg("could not get driver journey")
 | 
				
			||||||
		w.WriteHeader(http.StatusNotFound)
 | 
							w.WriteHeader(http.StatusNotFound)
 | 
				
			||||||
		return
 | 
							return
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
						solidarity, err := h.services.GRPC.SolidarityTransport.GetSolidarityTransportBookings(context.Background(), &gen.GetSolidarityTransportBookingsRequest{
 | 
				
			||||||
 | 
							Passengerid: passengerId,
 | 
				
			||||||
 | 
							StartDate:   timestamppb.New(time.Now().Add(-12 * 730 * time.Hour)),
 | 
				
			||||||
 | 
							EndDate:     timestamppb.New(time.Now().Add(12 * 730 * time.Hour)),
 | 
				
			||||||
 | 
						})
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	new_availabilities := []any{}
 | 
						priority := false
 | 
				
			||||||
 | 
						if a, ok := passenger.Data["other_properties"]; ok {
 | 
				
			||||||
	for _, av := range existing_availabilities {
 | 
							if b, ok := a.(map[string]any); ok {
 | 
				
			||||||
		log.Info().Str("type", reflect.TypeOf(av).Name()).Msg("info on type")
 | 
								if c, ok := b["status"]; ok {
 | 
				
			||||||
		if m, ok := av.(map[string]any); ok {
 | 
									if p, ok := c.(string); ok {
 | 
				
			||||||
			if id, ok2 := m["id"].(string); ok2 {
 | 
										priority = (p == "Prioritaire")
 | 
				
			||||||
				if id != availabilityID {
 | 
					 | 
				
			||||||
					new_availabilities = append(new_availabilities, av)
 | 
					 | 
				
			||||||
				}
 | 
									}
 | 
				
			||||||
			}
 | 
								}
 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	account.Data["solidarity_transport_availabilities"] = new_availabilities
 | 
						history := 0
 | 
				
			||||||
	data, err := structpb.NewValue(account.Data)
 | 
						if op, ok := passenger.Data["other_properties"]; ok {
 | 
				
			||||||
	if err != nil {
 | 
							if op_map, ok := op.(map[string]any); ok {
 | 
				
			||||||
		log.Error().Err(err).Msg("")
 | 
								if pst, ok := op_map["previous_solidarity_transport"]; ok {
 | 
				
			||||||
		w.WriteHeader(http.StatusInternalServerError)
 | 
									if pst_str, ok := pst.(string); ok {
 | 
				
			||||||
		return
 | 
										if pst_str != "" {
 | 
				
			||||||
 | 
											if n, err := strconv.Atoi(pst_str); err == nil {
 | 
				
			||||||
 | 
												history = history + n
 | 
				
			||||||
 | 
											} else {
 | 
				
			||||||
 | 
												log.Error().Err(err).Str("n", pst_str).Msg("string to int conversion error")
 | 
				
			||||||
 | 
											}
 | 
				
			||||||
 | 
										}
 | 
				
			||||||
 | 
									}
 | 
				
			||||||
 | 
								}
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	request := &mobilityaccounts.UpdateDataRequest{
 | 
						history = history + len(solidarity.Bookings)
 | 
				
			||||||
		Account: &mobilityaccounts.Account{
 | 
					
 | 
				
			||||||
			Id:        account.ID,
 | 
						log.Debug().Any("history", history).Msg("history check")
 | 
				
			||||||
			Namespace: account.Namespace,
 | 
					
 | 
				
			||||||
			Data:      data.GetStructValue(),
 | 
						benefParams := pricing.BeneficiaryParams{}
 | 
				
			||||||
 | 
						if passengerId == "" {
 | 
				
			||||||
 | 
							benefParams = pricing.BeneficiaryParams{
 | 
				
			||||||
 | 
								Address:  h.pricingGeography(j.PassengerPickup),
 | 
				
			||||||
 | 
								History:  99,
 | 
				
			||||||
 | 
								Priority: false,
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
						} else {
 | 
				
			||||||
 | 
							log.Debug().Any("passenger data", passenger.Data).Msg("0")
 | 
				
			||||||
 | 
							var passengerGeo pricing.GeographyParams
 | 
				
			||||||
 | 
							if pa, ok := passenger.Data["address"]; ok {
 | 
				
			||||||
 | 
								jsonpa, err := json.Marshal(pa)
 | 
				
			||||||
 | 
								if err == nil {
 | 
				
			||||||
 | 
									passGeojson, err := geojson.UnmarshalFeature(jsonpa)
 | 
				
			||||||
 | 
									if err == nil {
 | 
				
			||||||
 | 
										passengerGeo = h.pricingGeography(passGeojson)
 | 
				
			||||||
 | 
									}
 | 
				
			||||||
 | 
								}
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
							benefParams = pricing.BeneficiaryParams{
 | 
				
			||||||
 | 
								Address:  passengerGeo,
 | 
				
			||||||
 | 
								History:  history,
 | 
				
			||||||
 | 
								Priority: priority,
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						pricing, err := h.services.Pricing.Prices(pricing.PricingParams{
 | 
				
			||||||
 | 
							MobilityType: "solidarity_transport",
 | 
				
			||||||
 | 
							Beneficiary:  benefParams,
 | 
				
			||||||
 | 
							SharedMobility: pricing.SharedMobilityParams{
 | 
				
			||||||
 | 
								DriverDistance:    journey.DriverJourney.DriverDistance,
 | 
				
			||||||
 | 
								PassengerDistance: journey.DriverJourney.PassengerDistance,
 | 
				
			||||||
 | 
								Departure:         h.pricingGeography(j.PassengerPickup),
 | 
				
			||||||
 | 
								Destination:       h.pricingGeography(j.PassengerDrop),
 | 
				
			||||||
 | 
								OutwardOnly:       journey.DriverJourney.Noreturn,
 | 
				
			||||||
		},
 | 
							},
 | 
				
			||||||
 | 
						})
 | 
				
			||||||
 | 
						if err != nil {
 | 
				
			||||||
 | 
							log.Error().Err(err).Msg("error in pricing calculation")
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
	_, err = h.services.GRPC.MobilityAccounts.UpdateData(context.TODO(), request)
 | 
					
 | 
				
			||||||
 | 
						journey.DriverJourney.Price.Amount = pricing["passenger"].Amount
 | 
				
			||||||
 | 
						journey.DriverJourney.Price.Currency = "EUR"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						if r.Method == "POST" {
 | 
				
			||||||
 | 
							if passengerId == "" {
 | 
				
			||||||
 | 
								log.Error().Err(err).Msg("could not get driver journey")
 | 
				
			||||||
 | 
								w.WriteHeader(http.StatusNotFound)
 | 
				
			||||||
 | 
								return
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							if err := r.ParseForm(); err != nil {
 | 
				
			||||||
 | 
								log.Error().Err(err).Msg("could not parse form input")
 | 
				
			||||||
 | 
								w.WriteHeader(http.StatusBadRequest)
 | 
				
			||||||
 | 
								return
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							rwt := r.PostFormValue("return_waiting_time")
 | 
				
			||||||
 | 
							return_waiting_time := int64(0)
 | 
				
			||||||
 | 
							return_waiting_time, err := strconv.ParseInt(rwt, 10, 64)
 | 
				
			||||||
 | 
							if err == nil {
 | 
				
			||||||
 | 
								log.Error().Err(err).Msg("return waiting time error")
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
							motivation := r.PostFormValue("motivation")
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							data, err := structpb.NewStruct(map[string]any{
 | 
				
			||||||
 | 
								"motivation": motivation,
 | 
				
			||||||
 | 
							})
 | 
				
			||||||
 | 
							if err != nil {
 | 
				
			||||||
 | 
								log.Error().Err(err).Msg("issue creating data struct")
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							bookingRes, err := h.services.GRPC.SolidarityTransport.BookDriverJourney(context.Background(), &gen.BookDriverJourneyRequest{
 | 
				
			||||||
 | 
								PassengerId:           passengerId,
 | 
				
			||||||
 | 
								DriverId:              driverId,
 | 
				
			||||||
 | 
								DriverJourneyId:       journeyId,
 | 
				
			||||||
 | 
								ReturnWaitingDuration: return_waiting_time * int64(time.Minute),
 | 
				
			||||||
 | 
								PriceAmount:           journey.DriverJourney.Price.Amount,
 | 
				
			||||||
 | 
								PriceCurrency:         journey.DriverJourney.Price.Currency,
 | 
				
			||||||
 | 
								Data:                  data,
 | 
				
			||||||
 | 
							})
 | 
				
			||||||
 | 
							if err != nil {
 | 
				
			||||||
 | 
								log.Error().Err(err).Msg("cannot create booking")
 | 
				
			||||||
 | 
								w.WriteHeader(http.StatusInternalServerError)
 | 
				
			||||||
 | 
								return
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							message := r.PostFormValue("message")
 | 
				
			||||||
 | 
							doNotSend := r.PostFormValue("do_not_send")
 | 
				
			||||||
 | 
							send_message := strings.ReplaceAll(message, "{booking_id}", bookingRes.Booking.Id)
 | 
				
			||||||
 | 
							log.Debug().Str("message", send_message).Str("do not send", doNotSend).Msg("Driver journey booked : sending message")
 | 
				
			||||||
 | 
							if doNotSend != "on" {
 | 
				
			||||||
 | 
								h.GenerateSMS(driverId, send_message)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
								if err := h.creditWallet(passengerId, float64(-1)*journey.DriverJourney.Price.Amount); err != nil {
 | 
				
			||||||
 | 
									log.Error().Err(err).Msg("could not credit wallet")
 | 
				
			||||||
 | 
									w.WriteHeader(http.StatusInternalServerError)
 | 
				
			||||||
 | 
									return
 | 
				
			||||||
 | 
								}
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							http.Redirect(w, r, fmt.Sprintf("/app/solidarity-transport/"), http.StatusFound)
 | 
				
			||||||
 | 
							return
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						driver, err := h.services.GetAccount(driverId)
 | 
				
			||||||
 | 
						if err != nil {
 | 
				
			||||||
 | 
							log.Error().Err(err).Msg("could not get driver")
 | 
				
			||||||
 | 
							w.WriteHeader(http.StatusNotFound)
 | 
				
			||||||
 | 
							return
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						beneficiaries, err := h.beneficiaries(r)
 | 
				
			||||||
	if err != nil {
 | 
						if err != nil {
 | 
				
			||||||
		log.Error().Err(err).Msg("")
 | 
							log.Error().Err(err).Msg("")
 | 
				
			||||||
 | 
							w.WriteHeader(http.StatusBadRequest)
 | 
				
			||||||
 | 
							return
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						driverjourney, err := transformers.DriverJourneyProtoToType(journey.DriverJourney)
 | 
				
			||||||
 | 
						if err != nil {
 | 
				
			||||||
 | 
							log.Error().Err(err).Msg("could not transform driver journey type")
 | 
				
			||||||
 | 
							w.WriteHeader(http.StatusBadRequest)
 | 
				
			||||||
 | 
							return
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						h.Renderer.SolidarityTransportDriverJourney(w, r, driverjourney, driver, passenger, beneficiaries)
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					func (h *ApplicationHandler) SolidarityTransportDriverJourneyToggleNoreturn(w http.ResponseWriter, r *http.Request) {
 | 
				
			||||||
 | 
						vars := mux.Vars(r)
 | 
				
			||||||
 | 
						journeyId := vars["journeyid"]
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						_, err := h.services.GRPC.SolidarityTransport.ToggleSolidarityTransportNoreturn(context.Background(), &gen.ToggleSolidarityTransportNoreturnRequest{
 | 
				
			||||||
 | 
							JourneyId: journeyId,
 | 
				
			||||||
 | 
						})
 | 
				
			||||||
 | 
						if err != nil {
 | 
				
			||||||
 | 
							log.Error().Err(err).Msg("could not get driver journey")
 | 
				
			||||||
 | 
							w.WriteHeader(http.StatusNotFound)
 | 
				
			||||||
 | 
							return
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						log.Debug().Msg("here")
 | 
				
			||||||
 | 
						http.Redirect(w, r, r.Referer(), http.StatusFound)
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					func (h *ApplicationHandler) SolidarityTransportBookingDisplay(w http.ResponseWriter, r *http.Request) {
 | 
				
			||||||
 | 
						vars := mux.Vars(r)
 | 
				
			||||||
 | 
						bookingId := vars["bookingid"]
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						resp, err := h.services.GRPC.SolidarityTransport.GetSolidarityTransportBooking(context.Background(), &gen.GetSolidarityTransportBookingRequest{
 | 
				
			||||||
 | 
							Id: bookingId,
 | 
				
			||||||
 | 
						})
 | 
				
			||||||
 | 
						if r.Method == "POST" {
 | 
				
			||||||
 | 
							if err := r.ParseForm(); err != nil {
 | 
				
			||||||
 | 
								log.Error().Err(err).Msg("could not parse form")
 | 
				
			||||||
 | 
								w.WriteHeader(http.StatusBadRequest)
 | 
				
			||||||
 | 
								return
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							driverDistanceStr := r.PostFormValue("driver_distance")
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							driverDistance, err := strconv.Atoi(driverDistanceStr)
 | 
				
			||||||
 | 
							if err != nil {
 | 
				
			||||||
 | 
								log.Error().Err(err).Msg("could not read distance")
 | 
				
			||||||
 | 
								w.WriteHeader(http.StatusBadRequest)
 | 
				
			||||||
 | 
								return
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
							resp.Booking.Journey.DriverDistance = int64(driverDistance)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							_, err = h.services.GRPC.SolidarityTransport.UpdateSolidarityTransportBooking(context.Background(), &gen.UpdateSolidarityTransportBookingRequest{
 | 
				
			||||||
 | 
								Booking: resp.Booking,
 | 
				
			||||||
 | 
							})
 | 
				
			||||||
 | 
							if err != nil {
 | 
				
			||||||
 | 
								log.Error().Err(err).Msg("could not update booking")
 | 
				
			||||||
 | 
								w.WriteHeader(http.StatusInternalServerError)
 | 
				
			||||||
 | 
								return
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						booking, err := transformers.BookingProtoToType(resp.Booking)
 | 
				
			||||||
 | 
						if err != nil {
 | 
				
			||||||
 | 
							log.Error().Err(err).Msg("could not transform booking type")
 | 
				
			||||||
 | 
							w.WriteHeader(http.StatusBadRequest)
 | 
				
			||||||
 | 
							return
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						driver, err := h.services.GetAccount(booking.DriverId)
 | 
				
			||||||
 | 
						if err != nil {
 | 
				
			||||||
 | 
							log.Error().Err(err).Msg("driver retrieval issue")
 | 
				
			||||||
		w.WriteHeader(http.StatusInternalServerError)
 | 
							w.WriteHeader(http.StatusInternalServerError)
 | 
				
			||||||
		return
 | 
							return
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	http.Redirect(w, r, fmt.Sprintf("/app/solidarity-transport/drivers/%s", driverID), http.StatusFound)
 | 
						passenger, err := h.services.GetAccount(booking.PassengerId)
 | 
				
			||||||
 | 
						if err != nil {
 | 
				
			||||||
 | 
							log.Error().Err(err).Msg("passenger retrieval issue")
 | 
				
			||||||
 | 
							w.WriteHeader(http.StatusInternalServerError)
 | 
				
			||||||
 | 
							return
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						h.Renderer.SolidarityTransportBookingDisplay(w, r, booking, driver, passenger)
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					func (h *ApplicationHandler) SolidarityTransportBookingStatus(action string) func(w http.ResponseWriter, r *http.Request) {
 | 
				
			||||||
 | 
						return func(w http.ResponseWriter, r *http.Request) {
 | 
				
			||||||
 | 
							vars := mux.Vars(r)
 | 
				
			||||||
 | 
							bookingId := vars["bookingid"]
 | 
				
			||||||
 | 
							reason := ""
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							status := ""
 | 
				
			||||||
 | 
							if action == "confirm" {
 | 
				
			||||||
 | 
								status = "VALIDATED"
 | 
				
			||||||
 | 
							} else if action == "cancel" {
 | 
				
			||||||
 | 
								status = "CANCELLED"
 | 
				
			||||||
 | 
								if r.Method == "POST" {
 | 
				
			||||||
 | 
									r.ParseForm()
 | 
				
			||||||
 | 
									reason = r.PostFormValue("reason")
 | 
				
			||||||
 | 
								}
 | 
				
			||||||
 | 
							} else if action == "waitconfirmation" {
 | 
				
			||||||
 | 
								status = "WAITING_CONFIRMATION"
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							if status != "" {
 | 
				
			||||||
 | 
								if _, err := h.services.GRPC.SolidarityTransport.UpdateSolidarityTransportBookingStatus(context.Background(), &gen.UpdateSolidarityTransportBookingStatusRequest{
 | 
				
			||||||
 | 
									BookingId: bookingId,
 | 
				
			||||||
 | 
									NewStatus: status,
 | 
				
			||||||
 | 
									Reason:    reason,
 | 
				
			||||||
 | 
								}); err != nil {
 | 
				
			||||||
 | 
									log.Error().Err(err).Msg("update booking status issue")
 | 
				
			||||||
 | 
									w.WriteHeader(http.StatusInternalServerError)
 | 
				
			||||||
 | 
									return
 | 
				
			||||||
 | 
								}
 | 
				
			||||||
 | 
								if status == "CANCELLED" {
 | 
				
			||||||
 | 
									booking, err := h.services.GRPC.SolidarityTransport.GetSolidarityTransportBooking(context.Background(), &gen.GetSolidarityTransportBookingRequest{
 | 
				
			||||||
 | 
										Id: bookingId,
 | 
				
			||||||
 | 
									})
 | 
				
			||||||
 | 
									if err == nil {
 | 
				
			||||||
 | 
										if err := h.creditWallet(booking.Booking.PassengerId, booking.Booking.Journey.Price.Amount); err != nil {
 | 
				
			||||||
 | 
											log.Error().Err(err).Msg("could not credit wallet")
 | 
				
			||||||
 | 
											w.WriteHeader(http.StatusInternalServerError)
 | 
				
			||||||
 | 
											return
 | 
				
			||||||
 | 
										}
 | 
				
			||||||
 | 
									}
 | 
				
			||||||
 | 
								}
 | 
				
			||||||
 | 
								if status == "WAITING_CONFIRMATION" {
 | 
				
			||||||
 | 
									booking, err := h.services.GRPC.SolidarityTransport.GetSolidarityTransportBooking(context.Background(), &gen.GetSolidarityTransportBookingRequest{
 | 
				
			||||||
 | 
										Id: bookingId,
 | 
				
			||||||
 | 
									})
 | 
				
			||||||
 | 
									if err == nil {
 | 
				
			||||||
 | 
										if err := h.creditWallet(booking.Booking.PassengerId, float64(-1)*booking.Booking.Journey.Price.Amount); err != nil {
 | 
				
			||||||
 | 
											log.Error().Err(err).Msg("could not credit wallet")
 | 
				
			||||||
 | 
											w.WriteHeader(http.StatusInternalServerError)
 | 
				
			||||||
 | 
											return
 | 
				
			||||||
 | 
										}
 | 
				
			||||||
 | 
									}
 | 
				
			||||||
 | 
								}
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
							http.Redirect(w, r, fmt.Sprintf("/app/solidarity-transport/bookings/%s", bookingId), http.StatusFound)
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
func parseDriversForm(r *http.Request) (map[string]any, error) {
 | 
					func parseDriversForm(r *http.Request) (map[string]any, error) {
 | 
				
			||||||
| 
						 | 
					@ -356,3 +906,22 @@ func (h *ApplicationHandler) solidarityDrivers(r *http.Request) ([]mobilityaccou
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	return accounts, err
 | 
						return accounts, err
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					func (h *ApplicationHandler) pricingGeography(loc *geojson.Feature) pricing.GeographyParams {
 | 
				
			||||||
 | 
						if loc == nil {
 | 
				
			||||||
 | 
							return pricing.GeographyParams{}
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						geo, err := h.services.Geography.GeoSearch(loc)
 | 
				
			||||||
 | 
						if err != nil {
 | 
				
			||||||
 | 
							log.Error().Err(err).Msg("issue in geosearch")
 | 
				
			||||||
 | 
							return pricing.GeographyParams{}
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						return pricing.GeographyParams{
 | 
				
			||||||
 | 
							Location:             loc,
 | 
				
			||||||
 | 
							CityCode:             geo["communes"].Properties.MustString("code"),
 | 
				
			||||||
 | 
							IntercommunalityCode: geo["epci"].Properties.MustString("code"),
 | 
				
			||||||
 | 
							RegionCode:           geo["regions"].Properties.MustString("code"),
 | 
				
			||||||
 | 
							DepartmentCode:       geo["departements"].Properties.MustString("code"),
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -4,7 +4,6 @@ import (
 | 
				
			||||||
	"net/http"
 | 
						"net/http"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	"git.coopgo.io/coopgo-apps/parcoursmob/utils/identification"
 | 
						"git.coopgo.io/coopgo-apps/parcoursmob/utils/identification"
 | 
				
			||||||
	"git.coopgo.io/coopgo-platform/emailing"
 | 
					 | 
				
			||||||
	"github.com/rs/zerolog/log"
 | 
						"github.com/rs/zerolog/log"
 | 
				
			||||||
)
 | 
					)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					@ -13,7 +12,6 @@ type Message struct {
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
func (h *ApplicationHandler) SupportSend(w http.ResponseWriter, r *http.Request) {
 | 
					func (h *ApplicationHandler) SupportSend(w http.ResponseWriter, r *http.Request) {
 | 
				
			||||||
 | 
					 | 
				
			||||||
	c := r.Context().Value(identification.ClaimsKey)
 | 
						c := r.Context().Value(identification.ClaimsKey)
 | 
				
			||||||
	if c == nil {
 | 
						if c == nil {
 | 
				
			||||||
		log.Error().Msg("no current user claims")
 | 
							log.Error().Msg("no current user claims")
 | 
				
			||||||
| 
						 | 
					@ -23,11 +21,10 @@ func (h *ApplicationHandler) SupportSend(w http.ResponseWriter, r *http.Request)
 | 
				
			||||||
	current_user_claims := c.(map[string]any)
 | 
						current_user_claims := c.(map[string]any)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	comment := r.PostFormValue(("comment"))
 | 
						comment := r.PostFormValue(("comment"))
 | 
				
			||||||
		
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
	if r.Method == "POST" {
 | 
						if r.Method == "POST" {
 | 
				
			||||||
		user_email := current_user_claims["email"].(string)
 | 
							user_email := current_user_claims["email"].(string)
 | 
				
			||||||
		
 | 
					
 | 
				
			||||||
		data := map[string]any{
 | 
							data := map[string]any{
 | 
				
			||||||
			"key":  comment,
 | 
								"key":  comment,
 | 
				
			||||||
			"user": user_email,
 | 
								"user": user_email,
 | 
				
			||||||
| 
						 | 
					@ -35,10 +32,10 @@ func (h *ApplicationHandler) SupportSend(w http.ResponseWriter, r *http.Request)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
		log.Debug().Str("user_email", user_email).Msg("Sending message")
 | 
							log.Debug().Str("user_email", user_email).Msg("Sending message")
 | 
				
			||||||
 | 
					
 | 
				
			||||||
		if err := h.emailing.Send("support.request", "support@parcoursmob.fr", data, emailing.WithReplyTo(user_email), emailing.WithTLSOpportunistic()); err != nil {
 | 
							if err := h.emailing.Send("support.request", "support@parcoursmob.fr", data); err != nil {
 | 
				
			||||||
			log.Error().Err(err).Msg("error sending email")
 | 
								log.Error().Err(err).Msg("error sending email")
 | 
				
			||||||
			w.WriteHeader(http.StatusInternalServerError)
 | 
								w.WriteHeader(http.StatusInternalServerError)
 | 
				
			||||||
			return 
 | 
								return
 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
		http.Redirect(w, r, "/app/", http.StatusFound)
 | 
							http.Redirect(w, r, "/app/", http.StatusFound)
 | 
				
			||||||
		return
 | 
							return
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -11,8 +11,6 @@ import (
 | 
				
			||||||
	"git.coopgo.io/coopgo-apps/parcoursmob/utils/identification"
 | 
						"git.coopgo.io/coopgo-apps/parcoursmob/utils/identification"
 | 
				
			||||||
	"git.coopgo.io/coopgo-apps/parcoursmob/utils/sorting"
 | 
						"git.coopgo.io/coopgo-apps/parcoursmob/utils/sorting"
 | 
				
			||||||
	filestorage "git.coopgo.io/coopgo-apps/parcoursmob/utils/storage"
 | 
						filestorage "git.coopgo.io/coopgo-apps/parcoursmob/utils/storage"
 | 
				
			||||||
	diags "git.coopgo.io/coopgo-platform/diags/grpcapi"
 | 
					 | 
				
			||||||
	diagsstorage "git.coopgo.io/coopgo-platform/diags/storage"
 | 
					 | 
				
			||||||
	fleets "git.coopgo.io/coopgo-platform/fleets/grpcapi"
 | 
						fleets "git.coopgo.io/coopgo-platform/fleets/grpcapi"
 | 
				
			||||||
	fleetsstorage "git.coopgo.io/coopgo-platform/fleets/storage"
 | 
						fleetsstorage "git.coopgo.io/coopgo-platform/fleets/storage"
 | 
				
			||||||
	groupsmanagement "git.coopgo.io/coopgo-platform/groups-management/grpcapi"
 | 
						groupsmanagement "git.coopgo.io/coopgo-platform/groups-management/grpcapi"
 | 
				
			||||||
| 
						 | 
					@ -205,30 +203,30 @@ func (h *ApplicationHandler) VehiclesFleetDisplay(w http.ResponseWriter, r *http
 | 
				
			||||||
		w.WriteHeader(http.StatusInternalServerError)
 | 
							w.WriteHeader(http.StatusInternalServerError)
 | 
				
			||||||
		return
 | 
							return
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
	diag := []diagsstorage.Diag{}
 | 
						/*diag := []diagsstorage.Diag{}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	diagsrequest := &diags.GetDiagsRequest{
 | 
						diagsrequest := &diags.GetDiagsRequest{
 | 
				
			||||||
		Namespaces: []string{"parcoursmob_vehicles"},
 | 
							Namespaces: []string{"parcoursmob_vehicles"},
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	diagsresp, err := h.services.GRPC.Diags.GetDiags(context.TODO(), diagsrequest)
 | 
							diagsresp, err := h.services.GRPC.Diags.GetDiags(context.TODO(), diagsrequest)
 | 
				
			||||||
	if err != nil {
 | 
							if err != nil {
 | 
				
			||||||
		log.Error().Err(err).Msg("did not retrieve diags")
 | 
								log.Error().Err(err).Msg("did not retrieve diags")
 | 
				
			||||||
		w.WriteHeader(http.StatusInternalServerError)
 | 
								w.WriteHeader(http.StatusInternalServerError)
 | 
				
			||||||
		return
 | 
								return
 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	for _, d := range diagsresp.Diags {
 | 
					 | 
				
			||||||
		diagData := d.Data.AsMap()
 | 
					 | 
				
			||||||
		if vehicle, ok := diagData["vehicle"].(string); ok && vehicle == vehicleid {
 | 
					 | 
				
			||||||
			diag = append(diag, d.ToStorageType())
 | 
					 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
	diagsAny := make([]any, len(diag))
 | 
							for _, d := range diagsresp.Diags {
 | 
				
			||||||
	for i, d := range diag {
 | 
								diagData := d.Data.AsMap()
 | 
				
			||||||
 | 
								if vehicle, ok := diagData["vehicle"].(string); ok && vehicle == vehicleid {
 | 
				
			||||||
 | 
									diag = append(diag, d.ToStorageType())
 | 
				
			||||||
 | 
								}
 | 
				
			||||||
 | 
							} */
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						diagsAny := []any{}
 | 
				
			||||||
 | 
						/*for i, d := range diag {
 | 
				
			||||||
		diagsAny[i] = d
 | 
							diagsAny[i] = d
 | 
				
			||||||
	}
 | 
						}*/
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	h.Renderer.VehiclesFleetDisplay(w, r, resp.Vehicle.ToStorageType(), beneficiaries, diagsAny)
 | 
						h.Renderer.VehiclesFleetDisplay(w, r, resp.Vehicle.ToStorageType(), beneficiaries, diagsAny)
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
| 
						 | 
					@ -362,30 +360,30 @@ func (h ApplicationHandler) VehicleManagementBookingDisplay(w http.ResponseWrite
 | 
				
			||||||
	documents := h.filestorage.List(filestorage.PREFIX_BOOKINGS + "/" + bookingid)
 | 
						documents := h.filestorage.List(filestorage.PREFIX_BOOKINGS + "/" + bookingid)
 | 
				
			||||||
	file_types_map := h.config.GetStringMapString("storage.files.file_types")
 | 
						file_types_map := h.config.GetStringMapString("storage.files.file_types")
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	diag := []diagsstorage.Diag{}
 | 
						/*	diag := []diagsstorage.Diag{}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	diagsrequest := &diags.GetDiagsRequest{
 | 
							diagsrequest := &diags.GetDiagsRequest{
 | 
				
			||||||
		Namespaces: []string{"parcoursmob_bookings"},
 | 
								Namespaces: []string{"parcoursmob_bookings"},
 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	diagsresp, err := h.services.GRPC.Diags.GetDiags(context.TODO(), diagsrequest)
 | 
					 | 
				
			||||||
	if err != nil {
 | 
					 | 
				
			||||||
		log.Error().Err(err).Msg("")
 | 
					 | 
				
			||||||
		w.WriteHeader(http.StatusInternalServerError)
 | 
					 | 
				
			||||||
		return
 | 
					 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	for _, d := range diagsresp.Diags {
 | 
					 | 
				
			||||||
		diagData := d.Data.AsMap()
 | 
					 | 
				
			||||||
		if booking, ok := diagData["booking"].(string); ok && booking == bookingid {
 | 
					 | 
				
			||||||
			diag = append(diag, d.ToStorageType())
 | 
					 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
	}
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
	diagsAny := make([]any, len(diag))
 | 
							diagsresp, err := h.services.GRPC.Diags.GetDiags(context.TODO(), diagsrequest)
 | 
				
			||||||
	for i, d := range diag {
 | 
							if err != nil {
 | 
				
			||||||
 | 
								log.Error().Err(err).Msg("")
 | 
				
			||||||
 | 
								w.WriteHeader(http.StatusInternalServerError)
 | 
				
			||||||
 | 
								return
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							for _, d := range diagsresp.Diags {
 | 
				
			||||||
 | 
								diagData := d.Data.AsMap()
 | 
				
			||||||
 | 
								if booking, ok := diagData["booking"].(string); ok && booking == bookingid {
 | 
				
			||||||
 | 
									diag = append(diag, d.ToStorageType())
 | 
				
			||||||
 | 
								}
 | 
				
			||||||
 | 
							}*/
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						diagsAny := []any{}
 | 
				
			||||||
 | 
						/*for i, d := range diag {
 | 
				
			||||||
		diagsAny[i] = d
 | 
							diagsAny[i] = d
 | 
				
			||||||
	}
 | 
						}*/
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	h.Renderer.VehicleManagementBookingDisplay(w, r, booking, booking.Vehicle, beneficiary, groupresp.Group.ToStorageType(), documents, file_types_map, alternatives, diagsAny)
 | 
						h.Renderer.VehicleManagementBookingDisplay(w, r, booking, booking.Vehicle, beneficiary, groupresp.Group.ToStorageType(), documents, file_types_map, alternatives, diagsAny)
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -2,9 +2,11 @@ package application
 | 
				
			||||||
 | 
					
 | 
				
			||||||
import (
 | 
					import (
 | 
				
			||||||
	"context"
 | 
						"context"
 | 
				
			||||||
 | 
						"encoding/json"
 | 
				
			||||||
	"fmt"
 | 
						"fmt"
 | 
				
			||||||
	"io"
 | 
						"io"
 | 
				
			||||||
	"net/http"
 | 
						"net/http"
 | 
				
			||||||
 | 
						"slices"
 | 
				
			||||||
	"sort"
 | 
						"sort"
 | 
				
			||||||
	"strings"
 | 
						"strings"
 | 
				
			||||||
	"time"
 | 
						"time"
 | 
				
			||||||
| 
						 | 
					@ -12,8 +14,6 @@ import (
 | 
				
			||||||
	"git.coopgo.io/coopgo-apps/parcoursmob/utils/identification"
 | 
						"git.coopgo.io/coopgo-apps/parcoursmob/utils/identification"
 | 
				
			||||||
	"git.coopgo.io/coopgo-apps/parcoursmob/utils/sorting"
 | 
						"git.coopgo.io/coopgo-apps/parcoursmob/utils/sorting"
 | 
				
			||||||
	filestorage "git.coopgo.io/coopgo-apps/parcoursmob/utils/storage"
 | 
						filestorage "git.coopgo.io/coopgo-apps/parcoursmob/utils/storage"
 | 
				
			||||||
	diags "git.coopgo.io/coopgo-platform/diags/grpcapi"
 | 
					 | 
				
			||||||
	diagsstorage "git.coopgo.io/coopgo-platform/diags/storage"
 | 
					 | 
				
			||||||
	fleets "git.coopgo.io/coopgo-platform/fleets/grpcapi"
 | 
						fleets "git.coopgo.io/coopgo-platform/fleets/grpcapi"
 | 
				
			||||||
	"git.coopgo.io/coopgo-platform/fleets/storage"
 | 
						"git.coopgo.io/coopgo-platform/fleets/storage"
 | 
				
			||||||
	groupsmanagement "git.coopgo.io/coopgo-platform/groups-management/grpcapi"
 | 
						groupsmanagement "git.coopgo.io/coopgo-platform/groups-management/grpcapi"
 | 
				
			||||||
| 
						 | 
					@ -22,6 +22,7 @@ import (
 | 
				
			||||||
	mobilityaccountsstorage "git.coopgo.io/coopgo-platform/mobility-accounts/storage"
 | 
						mobilityaccountsstorage "git.coopgo.io/coopgo-platform/mobility-accounts/storage"
 | 
				
			||||||
	"github.com/google/uuid"
 | 
						"github.com/google/uuid"
 | 
				
			||||||
	"github.com/gorilla/mux"
 | 
						"github.com/gorilla/mux"
 | 
				
			||||||
 | 
						"github.com/paulmach/orb/geojson"
 | 
				
			||||||
	"github.com/rs/zerolog/log"
 | 
						"github.com/rs/zerolog/log"
 | 
				
			||||||
	"google.golang.org/protobuf/types/known/structpb"
 | 
						"google.golang.org/protobuf/types/known/structpb"
 | 
				
			||||||
	"google.golang.org/protobuf/types/known/timestamppb"
 | 
						"google.golang.org/protobuf/types/known/timestamppb"
 | 
				
			||||||
| 
						 | 
					@ -33,7 +34,7 @@ func (h ApplicationHandler) VehiclesSearch(w http.ResponseWriter, r *http.Reques
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	beneficiarydocuments := []filestorage.FileInfo{}
 | 
						beneficiarydocuments := []filestorage.FileInfo{}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	vehicles := []any{}
 | 
						vehicles := []storage.Vehicle{}
 | 
				
			||||||
	searched := false
 | 
						searched := false
 | 
				
			||||||
	start := r.FormValue("startdate")
 | 
						start := r.FormValue("startdate")
 | 
				
			||||||
	end := r.FormValue("enddate")
 | 
						end := r.FormValue("enddate")
 | 
				
			||||||
| 
						 | 
					@ -100,6 +101,21 @@ func (h ApplicationHandler) VehiclesSearch(w http.ResponseWriter, r *http.Reques
 | 
				
			||||||
			vehicles = append(vehicles, v)
 | 
								vehicles = append(vehicles, v)
 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							// Sort vehicles if beneficiary address is set
 | 
				
			||||||
 | 
							if beneficiaryAddress, ok := beneficiary.Data["address"]; ok {
 | 
				
			||||||
 | 
								beneficiaryAddressJson, err := json.Marshal(beneficiaryAddress)
 | 
				
			||||||
 | 
								if err == nil {
 | 
				
			||||||
 | 
									beneficiaryAddressGeojson, err := geojson.UnmarshalFeature(beneficiaryAddressJson)
 | 
				
			||||||
 | 
									if err == nil {
 | 
				
			||||||
 | 
										slices.SortFunc(vehicles, sorting.VehiclesByDistanceFrom(*beneficiaryAddressGeojson))
 | 
				
			||||||
 | 
									} else {
 | 
				
			||||||
 | 
										log.Error().Err(err).Msg("error transforming beneficiary address to GeoJSON")
 | 
				
			||||||
 | 
									}
 | 
				
			||||||
 | 
								} else {
 | 
				
			||||||
 | 
									log.Error().Err(err).Msg("error transforming beneficiary address to JSON")
 | 
				
			||||||
 | 
								}
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
		beneficiarydocuments = h.filestorage.List(filestorage.PREFIX_BENEFICIARIES + "/" + beneficiary.ID)
 | 
							beneficiarydocuments = h.filestorage.List(filestorage.PREFIX_BENEFICIARIES + "/" + beneficiary.ID)
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					@ -307,7 +323,7 @@ func (h ApplicationHandler) VehicleBookingDisplay(w http.ResponseWriter, r *http
 | 
				
			||||||
	documents := h.filestorage.List(filestorage.PREFIX_BOOKINGS + "/" + bookingid)
 | 
						documents := h.filestorage.List(filestorage.PREFIX_BOOKINGS + "/" + bookingid)
 | 
				
			||||||
	file_types_map := h.config.GetStringMapString("storage.files.file_types")
 | 
						file_types_map := h.config.GetStringMapString("storage.files.file_types")
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	diag := []diagsstorage.Diag{}
 | 
						/*diag := []diagsstorage.Diag{}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	diagsrequest := &diags.GetDiagsRequest{
 | 
						diagsrequest := &diags.GetDiagsRequest{
 | 
				
			||||||
		Namespaces: []string{"parcoursmob_bookings"},
 | 
							Namespaces: []string{"parcoursmob_bookings"},
 | 
				
			||||||
| 
						 | 
					@ -325,12 +341,12 @@ func (h ApplicationHandler) VehicleBookingDisplay(w http.ResponseWriter, r *http
 | 
				
			||||||
		if booking, ok := diagData["booking"].(string); ok && booking == bookingid {
 | 
							if booking, ok := diagData["booking"].(string); ok && booking == bookingid {
 | 
				
			||||||
			diag = append(diag, d.ToStorageType())
 | 
								diag = append(diag, d.ToStorageType())
 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
	}
 | 
						} */
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	diagsAny := make([]any, len(diag))
 | 
						diagsAny := []any{}
 | 
				
			||||||
	for i, d := range diag {
 | 
						/*for i, d := range diag {
 | 
				
			||||||
		diagsAny[i] = d
 | 
							diagsAny[i] = d
 | 
				
			||||||
	}
 | 
						}*/
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	h.Renderer.VehicleBookingDisplay(w, r, booking, booking.Vehicle, beneficiaryresp.Account.ToStorageType(), groupresp.Group.ToStorageType(), documents, file_types_map, diagsAny)
 | 
						h.Renderer.VehicleBookingDisplay(w, r, booking, booking.Vehicle, beneficiaryresp.Account.ToStorageType(), groupresp.Group.ToStorageType(), documents, file_types_map, diagsAny)
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -0,0 +1,69 @@
 | 
				
			||||||
 | 
					package application
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					import (
 | 
				
			||||||
 | 
						"context"
 | 
				
			||||||
 | 
						"net/http"
 | 
				
			||||||
 | 
						"strconv"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						"git.coopgo.io/coopgo-platform/mobility-accounts/grpcapi"
 | 
				
			||||||
 | 
						"github.com/gorilla/mux"
 | 
				
			||||||
 | 
						"github.com/rs/zerolog/log"
 | 
				
			||||||
 | 
					)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					func (h ApplicationHandler) CreditWallet(w http.ResponseWriter, r *http.Request) {
 | 
				
			||||||
 | 
						vars := mux.Vars(r)
 | 
				
			||||||
 | 
						userid := vars["userid"]
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						if r.Method != "POST" {
 | 
				
			||||||
 | 
							w.WriteHeader(http.StatusMethodNotAllowed)
 | 
				
			||||||
 | 
							return
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						r.ParseForm()
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						amountStr := r.FormValue("amount")
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						amount, err := strconv.ParseFloat(amountStr, 64)
 | 
				
			||||||
 | 
						if err != nil {
 | 
				
			||||||
 | 
							log.Error().Err(err).Msg("could not read amount")
 | 
				
			||||||
 | 
							w.WriteHeader(http.StatusBadRequest)
 | 
				
			||||||
 | 
							return
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						if err := h.creditWallet(userid, amount); err != nil {
 | 
				
			||||||
 | 
							log.Error().Err(err).Msg("could not credit wallet")
 | 
				
			||||||
 | 
							w.WriteHeader(http.StatusInternalServerError)
 | 
				
			||||||
 | 
							return
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						http.Redirect(w, r, r.Referer(), http.StatusFound)
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					func (h *ApplicationHandler) creditWallet(userid string, amount float64) error {
 | 
				
			||||||
 | 
						account, err := h.services.GetAccount(userid)
 | 
				
			||||||
 | 
						if err != nil {
 | 
				
			||||||
 | 
							log.Error().Err(err).Msg("could not retrieve account")
 | 
				
			||||||
 | 
							return err
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						if account.Data["wallet"] == nil {
 | 
				
			||||||
 | 
							account.Data["wallet"] = float64(0)
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						account.Data["wallet"] = account.Data["wallet"].(float64) + amount
 | 
				
			||||||
 | 
						accountproto, err := grpcapi.AccountFromStorageType(&account)
 | 
				
			||||||
 | 
						if err != nil {
 | 
				
			||||||
 | 
							log.Error().Err(err).Msg("account type transformation issue")
 | 
				
			||||||
 | 
							return err
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						_, err = h.services.GRPC.MobilityAccounts.UpdateData(context.Background(), &grpcapi.UpdateDataRequest{
 | 
				
			||||||
 | 
							Account: accountproto,
 | 
				
			||||||
 | 
						})
 | 
				
			||||||
 | 
						if err != nil {
 | 
				
			||||||
 | 
							log.Error().Err(err).Msg("account type transformation issue")
 | 
				
			||||||
 | 
							return err
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						return nil
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
| 
						 | 
					@ -18,9 +18,9 @@ type AuthHandler struct {
 | 
				
			||||||
	emailing *emailing.Mailer
 | 
						emailing *emailing.Mailer
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
func NewAuthHandler(cfg *viper.Viper, idp *identification.IdentificationProvider, svc *services.ServicesHandler, cache cache.CacheHandler, emailing *emailing.Mailer) (*AuthHandler, error) {
 | 
					func NewAuthHandler(cfg *viper.Viper, idp *identification.IdentificationProvider, svc *services.ServicesHandler, cache cache.CacheHandler, emailing *emailing.Mailer, filestorage cache.FileStorage) (*AuthHandler, error) {
 | 
				
			||||||
	templates_root := cfg.GetString("templates.root")
 | 
						templates_root := cfg.GetString("templates.root")
 | 
				
			||||||
	renderer := renderer.NewRenderer(cfg, templates_root)
 | 
						renderer := renderer.NewRenderer(cfg, templates_root, filestorage)
 | 
				
			||||||
	return &AuthHandler{
 | 
						return &AuthHandler{
 | 
				
			||||||
		idp:      idp,
 | 
							idp:      idp,
 | 
				
			||||||
		config:   cfg,
 | 
							config:   cfg,
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -17,7 +17,6 @@ import (
 | 
				
			||||||
)
 | 
					)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
func (h *ExportsHandler) Bookings(w http.ResponseWriter, r *http.Request) {
 | 
					func (h *ExportsHandler) Bookings(w http.ResponseWriter, r *http.Request) {
 | 
				
			||||||
 | 
					 | 
				
			||||||
	vehicles := map[string]fleetsstorage.Vehicle{}
 | 
						vehicles := map[string]fleetsstorage.Vehicle{}
 | 
				
			||||||
	bookings := []fleetsstorage.Booking{}
 | 
						bookings := []fleetsstorage.Booking{}
 | 
				
			||||||
	reequest := &fleets.GetVehiclesRequest{
 | 
						reequest := &fleets.GetVehiclesRequest{
 | 
				
			||||||
| 
						 | 
					@ -112,7 +111,6 @@ func (h *ExportsHandler) Bookings(w http.ResponseWriter, r *http.Request) {
 | 
				
			||||||
				if v3, ok := v2["display_name"].(string); ok {
 | 
									if v3, ok := v2["display_name"].(string); ok {
 | 
				
			||||||
					bookedby = v3
 | 
										bookedby = v3
 | 
				
			||||||
				}
 | 
									}
 | 
				
			||||||
 | 
					 | 
				
			||||||
			}
 | 
								}
 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					@ -170,5 +168,141 @@ func (h *ExportsHandler) Bookings(w http.ResponseWriter, r *http.Request) {
 | 
				
			||||||
	w.Header().Set("Content-Transfer-Encoding", "binary")
 | 
						w.Header().Set("Content-Transfer-Encoding", "binary")
 | 
				
			||||||
	w.Header().Set("Expires", "0")
 | 
						w.Header().Set("Expires", "0")
 | 
				
			||||||
	f.Write(w)
 | 
						f.Write(w)
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					func (h *ExportsHandler) AllBookings(w http.ResponseWriter, r *http.Request) {
 | 
				
			||||||
 | 
						vehicles := map[string]fleetsstorage.Vehicle{}
 | 
				
			||||||
 | 
						bookings := []fleetsstorage.Booking{}
 | 
				
			||||||
 | 
						reequest := &fleets.GetVehiclesRequest{
 | 
				
			||||||
 | 
							Namespaces: []string{"parcoursmob"},
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						reesp, err := h.services.GRPC.Fleets.GetVehicles(context.TODO(), reequest)
 | 
				
			||||||
 | 
						if err != nil {
 | 
				
			||||||
 | 
							log.Error().Err(err).Msg("")
 | 
				
			||||||
 | 
							w.WriteHeader(http.StatusInternalServerError)
 | 
				
			||||||
 | 
							return
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						beneficiaries_ids := []string{}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						for _, vehicle := range reesp.Vehicles {
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							v := vehicle.ToStorageType()
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							for _, b := range v.Bookings {
 | 
				
			||||||
 | 
								bookings = append(bookings, b)
 | 
				
			||||||
 | 
								beneficiaries_ids = append(beneficiaries_ids, b.Driver)
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							vehicles[vehicle.Id] = v
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						groups := map[string]groupsstorage.Group{}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						admingroups, err := h.services.GRPC.GroupsManagement.GetGroups(context.TODO(), &groupsmanagement.GetGroupsRequest{
 | 
				
			||||||
 | 
							Namespaces: []string{"parcoursmob_organizations"},
 | 
				
			||||||
 | 
						})
 | 
				
			||||||
 | 
						if err != nil {
 | 
				
			||||||
 | 
							log.Error().Err(err).Msg("")
 | 
				
			||||||
 | 
							w.WriteHeader(http.StatusInternalServerError)
 | 
				
			||||||
 | 
							return
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						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 {
 | 
				
			||||||
 | 
							log.Error().Err(err).Msg("")
 | 
				
			||||||
 | 
							w.WriteHeader(http.StatusInternalServerError)
 | 
				
			||||||
 | 
							return
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						beneficiaries_map := map[string]accountsstorage.Account{}
 | 
				
			||||||
 | 
						for _, ben := range beneficiaries.Accounts {
 | 
				
			||||||
 | 
							beneficiaries_map[ben.Id] = ben.ToStorageType()
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						/////////////// Generate file
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						f := excelize.NewFile()
 | 
				
			||||||
 | 
						defer func() {
 | 
				
			||||||
 | 
							if err := f.Close(); err != nil {
 | 
				
			||||||
 | 
								log.Error().Err(err).Msg("")
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
						}()
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						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
 | 
				
			||||||
 | 
									}
 | 
				
			||||||
 | 
								}
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							beneficiary := beneficiaries_map[b.Driver]
 | 
				
			||||||
 | 
							adminunavailability := false
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							if av, ok := b.Data["administrator_unavailability"].(bool); ok && av {
 | 
				
			||||||
 | 
								adminunavailability = true
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							deleted := ""
 | 
				
			||||||
 | 
							v, ok := b.Data["Deleted"]
 | 
				
			||||||
 | 
							fmt.Println(v)
 | 
				
			||||||
 | 
							fmt.Println(ok)
 | 
				
			||||||
 | 
							if b.Deleted || (ok && v.(bool)) {
 | 
				
			||||||
 | 
								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
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						w.Header().Set("Content-Type", "application/octet-stream")
 | 
				
			||||||
 | 
						w.Header().Set("Content-Disposition", "attachment; filename="+"Workbook.xlsx")
 | 
				
			||||||
 | 
						w.Header().Set("Content-Transfer-Encoding", "binary")
 | 
				
			||||||
 | 
						w.Header().Set("Expires", "0")
 | 
				
			||||||
 | 
						f.Write(w)
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
							
								
								
									
										61
									
								
								main.go
								
								
								
								
							
							
						
						
									
										61
									
								
								main.go
								
								
								
								
							| 
						 | 
					@ -8,23 +8,24 @@ import (
 | 
				
			||||||
	"github.com/rs/zerolog"
 | 
						"github.com/rs/zerolog"
 | 
				
			||||||
	"github.com/rs/zerolog/log"
 | 
						"github.com/rs/zerolog/log"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						"github.com/gorilla/mux"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	"git.coopgo.io/coopgo-apps/parcoursmob/handlers/api"
 | 
						"git.coopgo.io/coopgo-apps/parcoursmob/handlers/api"
 | 
				
			||||||
 | 
						"git.coopgo.io/coopgo-apps/parcoursmob/handlers/api/protected"
 | 
				
			||||||
	"git.coopgo.io/coopgo-apps/parcoursmob/handlers/application"
 | 
						"git.coopgo.io/coopgo-apps/parcoursmob/handlers/application"
 | 
				
			||||||
	"git.coopgo.io/coopgo-apps/parcoursmob/handlers/auth"
 | 
						"git.coopgo.io/coopgo-apps/parcoursmob/handlers/auth"
 | 
				
			||||||
	"git.coopgo.io/coopgo-apps/parcoursmob/handlers/exports"
 | 
						"git.coopgo.io/coopgo-apps/parcoursmob/handlers/exports"
 | 
				
			||||||
	"git.coopgo.io/coopgo-apps/parcoursmob/renderer"
 | 
						"git.coopgo.io/coopgo-apps/parcoursmob/renderer"
 | 
				
			||||||
	"git.coopgo.io/coopgo-apps/parcoursmob/services"
 | 
						"git.coopgo.io/coopgo-apps/parcoursmob/services"
 | 
				
			||||||
	"git.coopgo.io/coopgo-apps/parcoursmob/utils/identification"
 | 
						"git.coopgo.io/coopgo-apps/parcoursmob/utils/identification"
 | 
				
			||||||
 | 
						"git.coopgo.io/coopgo-apps/parcoursmob/utils/protectapi"
 | 
				
			||||||
	cache "git.coopgo.io/coopgo-apps/parcoursmob/utils/storage"
 | 
						cache "git.coopgo.io/coopgo-apps/parcoursmob/utils/storage"
 | 
				
			||||||
	"github.com/gorilla/mux"
 | 
					 | 
				
			||||||
)
 | 
					)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
func main() {
 | 
					func main() {
 | 
				
			||||||
	zerolog.TimeFieldFormat = zerolog.TimeFormatUnix
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
	cfg, err := ReadConfig()
 | 
						cfg, err := ReadConfig()
 | 
				
			||||||
	if err != nil {
 | 
						if err != nil {
 | 
				
			||||||
		log.Fatal().Err(err).Msg("cannot read config")
 | 
							log.Fatal().Err(err).Msg("cannot read config!")
 | 
				
			||||||
		return
 | 
							return
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					@ -37,6 +38,8 @@ func main() {
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	if dev_env {
 | 
						if dev_env {
 | 
				
			||||||
		log.Logger = log.Output(zerolog.ConsoleWriter{Out: os.Stderr})
 | 
							log.Logger = log.Output(zerolog.ConsoleWriter{Out: os.Stderr})
 | 
				
			||||||
 | 
						} else {
 | 
				
			||||||
 | 
							zerolog.TimeFieldFormat = zerolog.TimeFormatUnix
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	svc, err := services.NewServicesHandler(cfg)
 | 
						svc, err := services.NewServicesHandler(cfg)
 | 
				
			||||||
| 
						 | 
					@ -61,9 +64,10 @@ func main() {
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	apiHandler, _ := api.NewAPIHandler(cfg, idp, svc, kv)
 | 
						apiHandler, _ := api.NewAPIHandler(cfg, idp, svc, kv)
 | 
				
			||||||
 | 
						protectedApiHandler, _ := protected.NewProtectedAPIHandler(cfg, idp, svc, kv)
 | 
				
			||||||
	applicationHandler, _ := application.NewApplicationHandler(cfg, svc, kv, filestorage, emailing)
 | 
						applicationHandler, _ := application.NewApplicationHandler(cfg, svc, kv, filestorage, emailing)
 | 
				
			||||||
	exportsHandler, _ := exports.NewExportsHandler(cfg, svc, emailing)
 | 
						exportsHandler, _ := exports.NewExportsHandler(cfg, svc, emailing)
 | 
				
			||||||
	authHandler, _ := auth.NewAuthHandler(cfg, idp, svc, kv, emailing)
 | 
						authHandler, _ := auth.NewAuthHandler(cfg, idp, svc, kv, emailing, filestorage)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	r := mux.NewRouter()
 | 
						r := mux.NewRouter()
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					@ -85,6 +89,9 @@ func main() {
 | 
				
			||||||
	calendars_router.HandleFunc("/global.ics", apiHandler.CalendarGlobal)
 | 
						calendars_router.HandleFunc("/global.ics", apiHandler.CalendarGlobal)
 | 
				
			||||||
	calendars_router.HandleFunc("/organizations/{groupid}.ics", apiHandler.CalendarOrganizations)
 | 
						calendars_router.HandleFunc("/organizations/{groupid}.ics", apiHandler.CalendarOrganizations)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						ext_router := r.PathPrefix("/ext").Subrouter()
 | 
				
			||||||
 | 
						ext_router.HandleFunc("/st/bp/{bookingid}", applicationHandler.SolidarityTransportExternalBookingProposal)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	api_router := r.PathPrefix("/api").Subrouter()
 | 
						api_router := r.PathPrefix("/api").Subrouter()
 | 
				
			||||||
	api_router.HandleFunc("/", apiHandler.NotFound)
 | 
						api_router.HandleFunc("/", apiHandler.NotFound)
 | 
				
			||||||
	api_router.HandleFunc("/geo/autocomplete", apiHandler.GeoAutocomplete)
 | 
						api_router.HandleFunc("/geo/autocomplete", apiHandler.GeoAutocomplete)
 | 
				
			||||||
| 
						 | 
					@ -92,15 +99,25 @@ func main() {
 | 
				
			||||||
	api_router.HandleFunc("/cache/{cacheid}/export", apiHandler.CacheExport)
 | 
						api_router.HandleFunc("/cache/{cacheid}/export", apiHandler.CacheExport)
 | 
				
			||||||
	api_router.HandleFunc("/oauth2/callback", apiHandler.OAuth2Callback)
 | 
						api_router.HandleFunc("/oauth2/callback", apiHandler.OAuth2Callback)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						protected_api_router := api_router.PathPrefix("/protected").Subrouter()
 | 
				
			||||||
 | 
						protected_api_router.HandleFunc("/users", protectedApiHandler.Users)
 | 
				
			||||||
 | 
						protected_api_router.Use(protectapi.ApiKey(cfg.GetString("services.api.api_key")))
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						interact_router := r.PathPrefix("/int").Subrouter()
 | 
				
			||||||
 | 
						interact_router.HandleFunc("/", apiHandler.NotFound)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	application := r.PathPrefix("/app").Subrouter()
 | 
						application := r.PathPrefix("/app").Subrouter()
 | 
				
			||||||
	application.HandleFunc("/", applicationHandler.Dashboard)
 | 
						application.HandleFunc("/", applicationHandler.Dashboard)
 | 
				
			||||||
	application.HandleFunc("/beneficiaries/", applicationHandler.BeneficiariesList)
 | 
						application.HandleFunc("/beneficiaries/", applicationHandler.BeneficiariesList)
 | 
				
			||||||
	application.HandleFunc("/beneficiaries/create", applicationHandler.BeneficiaryCreate)
 | 
						application.HandleFunc("/beneficiaries/create", applicationHandler.BeneficiaryCreate)
 | 
				
			||||||
	application.HandleFunc("/beneficiaries/{beneficiaryid}", applicationHandler.BeneficiaryDisplay)
 | 
						application.HandleFunc("/beneficiaries/{beneficiaryid}", applicationHandler.BeneficiaryDisplay)
 | 
				
			||||||
	application.HandleFunc("/beneficiaries/{beneficiaryid}/update", applicationHandler.BeneficiaryUpdate)
 | 
						application.HandleFunc("/beneficiaries/{beneficiaryid}/update", applicationHandler.BeneficiaryUpdate)
 | 
				
			||||||
 | 
						application.HandleFunc("/beneficiaries/{beneficiaryid}/archive", applicationHandler.BeneficiaryArchive)
 | 
				
			||||||
 | 
						application.HandleFunc("/beneficiaries/{beneficiaryid}/unarchive", applicationHandler.BeneficiaryUnarchive)
 | 
				
			||||||
	application.HandleFunc("/beneficiaries/{beneficiaryid}/documents", applicationHandler.BeneficiaryDocuments)
 | 
						application.HandleFunc("/beneficiaries/{beneficiaryid}/documents", applicationHandler.BeneficiaryDocuments)
 | 
				
			||||||
	application.HandleFunc("/beneficiaries/{beneficiaryid}/documents/{document}", applicationHandler.BeneficiaryDocumentDownload)
 | 
						application.HandleFunc("/beneficiaries/{beneficiaryid}/documents/{document}", applicationHandler.BeneficiaryDocumentDownload)
 | 
				
			||||||
	application.HandleFunc("/beneficiaries/{beneficiaryid}/picture", applicationHandler.BeneficiaryPicture)
 | 
						application.HandleFunc("/beneficiaries/{beneficiaryid}/picture", applicationHandler.BeneficiaryPicture)
 | 
				
			||||||
 | 
						application.HandleFunc("/wallets/{userid}/credit", applicationHandler.CreditWallet)
 | 
				
			||||||
	application.HandleFunc("/members/{beneficiaryid}/picture", applicationHandler.BeneficiaryPicture)
 | 
						application.HandleFunc("/members/{beneficiaryid}/picture", applicationHandler.BeneficiaryPicture)
 | 
				
			||||||
	application.HandleFunc("/members/{adminid}", applicationHandler.MemberDisplay)
 | 
						application.HandleFunc("/members/{adminid}", applicationHandler.MemberDisplay)
 | 
				
			||||||
	application.HandleFunc("/members/{adminid}/update", applicationHandler.MemberUpdate)
 | 
						application.HandleFunc("/members/{adminid}/update", applicationHandler.MemberUpdate)
 | 
				
			||||||
| 
						 | 
					@ -108,9 +125,30 @@ func main() {
 | 
				
			||||||
	application.HandleFunc("/journeys/", applicationHandler.JourneysSearch)
 | 
						application.HandleFunc("/journeys/", applicationHandler.JourneysSearch)
 | 
				
			||||||
	application.HandleFunc("/solidarity-transport/", applicationHandler.SolidarityTransportOverview)
 | 
						application.HandleFunc("/solidarity-transport/", applicationHandler.SolidarityTransportOverview)
 | 
				
			||||||
	application.HandleFunc("/solidarity-transport/drivers/create", applicationHandler.SolidarityTransportCreateDriver)
 | 
						application.HandleFunc("/solidarity-transport/drivers/create", applicationHandler.SolidarityTransportCreateDriver)
 | 
				
			||||||
	application.HandleFunc("/solidarity-transport/drivers/{driverid}", applicationHandler.SolidarityTransportDriverDisplay)
 | 
						application.HandleFunc("/solidarity-transport/drivers/{driverid}/update", applicationHandler.SolidarityTransportUpdateDriver)
 | 
				
			||||||
	application.HandleFunc("/solidarity-transport/drivers/{driverid}/availabilities", applicationHandler.SolidarityTransportAddAvailability)
 | 
						application.HandleFunc("/solidarity-transport/drivers/{driverid}/availabilities", applicationHandler.SolidarityTransportAddAvailability)
 | 
				
			||||||
 | 
						application.HandleFunc("/solidarity-transport/drivers/{driverid}/archive", applicationHandler.SolidarityTransportArchiveDriver)
 | 
				
			||||||
 | 
						application.HandleFunc("/solidarity-transport/drivers/{driverid}/unarchive", applicationHandler.SolidarityTransportUnarchiveDriver)
 | 
				
			||||||
 | 
						application.HandleFunc("/solidarity-transport/drivers/{driverid}/documents", applicationHandler.SolidarityTransportDriverDocuments)
 | 
				
			||||||
 | 
						application.HandleFunc("/solidarity-transport/drivers/{driverid}/documents/{document}", applicationHandler.SolidarityTransportDocumentDownload)
 | 
				
			||||||
	application.HandleFunc("/solidarity-transport/drivers/{driverid}/availabilities/{availabilityid}/delete", applicationHandler.SolidarityTransportDeleteAvailability)
 | 
						application.HandleFunc("/solidarity-transport/drivers/{driverid}/availabilities/{availabilityid}/delete", applicationHandler.SolidarityTransportDeleteAvailability)
 | 
				
			||||||
 | 
						application.HandleFunc("/solidarity-transport/drivers/{driverid}/journeys/{journeyid}", applicationHandler.SolidarityTransportDriverJourney)
 | 
				
			||||||
 | 
						application.HandleFunc("/solidarity-transport/drivers/{driverid}/journeys/{journeyid}/noreturn", applicationHandler.SolidarityTransportDriverJourneyToggleNoreturn)
 | 
				
			||||||
 | 
						application.HandleFunc("/solidarity-transport/drivers/{driverid}", applicationHandler.SolidarityTransportDriverDisplay)
 | 
				
			||||||
 | 
						application.HandleFunc("/solidarity-transport/bookings/{bookingid}", applicationHandler.SolidarityTransportBookingDisplay)
 | 
				
			||||||
 | 
						application.HandleFunc("/solidarity-transport/bookings/{bookingid}/confirm", applicationHandler.SolidarityTransportBookingStatus("confirm"))
 | 
				
			||||||
 | 
						application.HandleFunc("/solidarity-transport/bookings/{bookingid}/cancel", applicationHandler.SolidarityTransportBookingStatus("cancel"))
 | 
				
			||||||
 | 
						application.HandleFunc("/solidarity-transport/bookings/{bookingid}/waitconfirmation", applicationHandler.SolidarityTransportBookingStatus("waitconfirmation"))
 | 
				
			||||||
 | 
						application.HandleFunc("/organized-carpool/", applicationHandler.OrganizedCarpoolOverview)
 | 
				
			||||||
 | 
						application.HandleFunc("/organized-carpool/drivers/create", applicationHandler.OrganizedCarpoolCreateDriver)
 | 
				
			||||||
 | 
						application.HandleFunc("/organized-carpool/drivers/{driverid}/trips", applicationHandler.OrganizedCarpoolAddTrip)
 | 
				
			||||||
 | 
						application.HandleFunc("/organized-carpool/drivers/{driverid}/archive", applicationHandler.OrganizedCarpoolArchiveDriver)
 | 
				
			||||||
 | 
						application.HandleFunc("/organized-carpool/drivers/{driverid}/unarchive", applicationHandler.OrganizedCarpoolUnarchiveDriver)
 | 
				
			||||||
 | 
						application.HandleFunc("/organized-carpool/drivers/{driverid}/documents", applicationHandler.OrganizedCarpoolDriverDocuments)
 | 
				
			||||||
 | 
						application.HandleFunc("/organized-carpool/drivers/{driverid}/documents/{document}", applicationHandler.OrganizedCarpoolDocumentDownload)
 | 
				
			||||||
 | 
						application.HandleFunc("/organized-carpool/drivers/{driverid}/trips/{tripid}/delete", applicationHandler.OrganizedCarpoolDeleteTrip)
 | 
				
			||||||
 | 
						application.HandleFunc("/organized-carpool/drivers/{driverid}", applicationHandler.OrganizedCarpoolDriverDisplay)
 | 
				
			||||||
 | 
						application.HandleFunc("/organized-carpool/drivers/{driverid}/journeys/{journeyid}", applicationHandler.OrganizedCarpoolJourney)
 | 
				
			||||||
	application.HandleFunc("/vehicles/", applicationHandler.VehiclesSearch)
 | 
						application.HandleFunc("/vehicles/", applicationHandler.VehiclesSearch)
 | 
				
			||||||
	application.HandleFunc("/vehicles/bookings/", applicationHandler.VehiclesBookingsList)
 | 
						application.HandleFunc("/vehicles/bookings/", applicationHandler.VehiclesBookingsList)
 | 
				
			||||||
	application.HandleFunc("/vehicles/bookings/{bookingid}", applicationHandler.VehicleBookingDisplay)
 | 
						application.HandleFunc("/vehicles/bookings/{bookingid}", applicationHandler.VehicleBookingDisplay)
 | 
				
			||||||
| 
						 | 
					@ -144,17 +182,15 @@ func main() {
 | 
				
			||||||
	application.HandleFunc("/group/settings", applicationHandler.GroupSettingsDisplay)
 | 
						application.HandleFunc("/group/settings", applicationHandler.GroupSettingsDisplay)
 | 
				
			||||||
	application.HandleFunc("/group/settings/invite-member", applicationHandler.GroupSettingsInviteMember)
 | 
						application.HandleFunc("/group/settings/invite-member", applicationHandler.GroupSettingsInviteMember)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	/****************************Groupe Déplacement ************************************/
 | 
					 | 
				
			||||||
	application.HandleFunc("/journeys/groups_covoiturage", applicationHandler.GroupsGestion)
 | 
						application.HandleFunc("/journeys/groups_covoiturage", applicationHandler.GroupsGestion)
 | 
				
			||||||
	application.HandleFunc("/journeys/groups_covoiturage/create", applicationHandler.CreateGroup)
 | 
						application.HandleFunc("/journeys/groups_covoiturage/create", applicationHandler.CreateGroup)
 | 
				
			||||||
	application.HandleFunc("/journeys/groups_covoiturage/create/{groupid}", applicationHandler.DisplayGroupCovoiturage)
 | 
						application.HandleFunc("/journeys/groups_covoiturage/create/{groupid}", applicationHandler.DisplayGroupCovoiturage)
 | 
				
			||||||
	application.HandleFunc("/journeys/groups_covoiturage/create/{id}/{groupid}/{memberid}", applicationHandler.UpdateGroupCovoiturage)
 | 
						application.HandleFunc("/journeys/groups_covoiturage/create/{id}/{groupid}/{memberid}", applicationHandler.UpdateGroupCovoiturage)
 | 
				
			||||||
	/****************************************************************/
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
	/********************Code Supprt Emailing************************/
 | 
						application.HandleFunc("/sms/send", applicationHandler.SendSMS)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	application.HandleFunc("/support/", applicationHandler.SupportSend)
 | 
						application.HandleFunc("/support/", applicationHandler.SupportSend)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	/*********************** CODE GROUP **************************/
 | 
					 | 
				
			||||||
	appGroup := application.PathPrefix("/group_module").Subrouter()
 | 
						appGroup := application.PathPrefix("/group_module").Subrouter()
 | 
				
			||||||
	appGroup.HandleFunc("/", applicationHandler.Groups)
 | 
						appGroup.HandleFunc("/", applicationHandler.Groups)
 | 
				
			||||||
	appGroup.HandleFunc("/groups", applicationHandler.CreateGroupModule)
 | 
						appGroup.HandleFunc("/groups", applicationHandler.CreateGroupModule)
 | 
				
			||||||
| 
						 | 
					@ -211,10 +247,9 @@ func main() {
 | 
				
			||||||
	application.HandleFunc("/diags/{diagid}", applicationHandler.DiagsDisplayDiag)
 | 
						application.HandleFunc("/diags/{diagid}", applicationHandler.DiagsDisplayDiag)
 | 
				
			||||||
	application.HandleFunc("/diags/{diagid}/update", applicationHandler.DiagUpdate)
 | 
						application.HandleFunc("/diags/{diagid}/update", applicationHandler.DiagUpdate)
 | 
				
			||||||
	application.HandleFunc("/diags/{diagid}/delete", applicationHandler.DiagDelete)
 | 
						application.HandleFunc("/diags/{diagid}/delete", applicationHandler.DiagDelete)
 | 
				
			||||||
	// application.HandleFunc("/diags/history", applicationHandler.DiagsHistory)
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
	export := r.PathPrefix("/exports").Subrouter()
 | 
						export := r.PathPrefix("/exports").Subrouter()
 | 
				
			||||||
	export.HandleFunc("/fleets/bookings", exportsHandler.Bookings)
 | 
						export.HandleFunc("/fleets/bookings", exportsHandler.AllBookings)
 | 
				
			||||||
	export.HandleFunc("/fleets/bookings/{groupid}", exportsHandler.Bookings)
 | 
						export.HandleFunc("/fleets/bookings/{groupid}", exportsHandler.Bookings)
 | 
				
			||||||
	export.HandleFunc("/agenda/subscriptions", exportsHandler.Agenda("allEvents"))
 | 
						export.HandleFunc("/agenda/subscriptions", exportsHandler.Agenda("allEvents"))
 | 
				
			||||||
	export.HandleFunc("/agenda/{eventid}", exportsHandler.Agenda("oneEvent"))
 | 
						export.HandleFunc("/agenda/{eventid}", exportsHandler.Agenda("oneEvent"))
 | 
				
			||||||
| 
						 | 
					@ -224,7 +259,7 @@ func main() {
 | 
				
			||||||
	srv := &http.Server{
 | 
						srv := &http.Server{
 | 
				
			||||||
		Handler:      r,
 | 
							Handler:      r,
 | 
				
			||||||
		Addr:         address,
 | 
							Addr:         address,
 | 
				
			||||||
		WriteTimeout: 15 * time.Second,
 | 
							WriteTimeout: 30 * time.Second,
 | 
				
			||||||
		ReadTimeout:  15 * time.Second,
 | 
							ReadTimeout:  15 * time.Second,
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -53,18 +53,19 @@ type BeneficiariesDisplayState struct {
 | 
				
			||||||
	Beneficiary any
 | 
						Beneficiary any
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
func (renderer *Renderer) BeneficiaryDisplay(w http.ResponseWriter, r *http.Request, beneficiary any, bookings []fleetsstorage.Booking, organizations []any, beneficiaries_file_types []string, file_types_map map[string]string, documents any, event interface{}, diags []any) {
 | 
					func (renderer *Renderer) BeneficiaryDisplay(w http.ResponseWriter, r *http.Request, beneficiary any, bookings []fleetsstorage.Booking, organizations []any, beneficiaries_file_types []string, file_types_map map[string]string, documents any, event interface{}, diags []any, solidarityTransportStats any) {
 | 
				
			||||||
	files := renderer.ThemeConfig.GetStringSlice("views.beneficiaries.display.files")
 | 
						files := renderer.ThemeConfig.GetStringSlice("views.beneficiaries.display.files")
 | 
				
			||||||
	state := NewState(r, renderer.ThemeConfig, beneficiariesMenu)
 | 
						state := NewState(r, renderer.ThemeConfig, beneficiariesMenu)
 | 
				
			||||||
	state.ViewState = map[string]any{
 | 
						state.ViewState = map[string]any{
 | 
				
			||||||
		"beneficiary":              beneficiary,
 | 
							"beneficiary":                beneficiary,
 | 
				
			||||||
		"bookings":                 bookings,
 | 
							"bookings":                   bookings,
 | 
				
			||||||
		"beneficiaries_file_types": beneficiaries_file_types,
 | 
							"beneficiaries_file_types":   beneficiaries_file_types,
 | 
				
			||||||
		"file_types_map":           file_types_map,
 | 
							"file_types_map":             file_types_map,
 | 
				
			||||||
		"documents":                documents,
 | 
							"documents":                  documents,
 | 
				
			||||||
		"organizations":            organizations,
 | 
							"organizations":              organizations,
 | 
				
			||||||
		"event":                    event,
 | 
							"event":                      event,
 | 
				
			||||||
		"diags":                    diags,
 | 
							"diags":                      diags,
 | 
				
			||||||
 | 
							"solidarity_transport_stats": solidarityTransportStats,
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
	renderer.Render("beneficiaries_display", w, r, files, state)
 | 
						renderer.Render("beneficiaries_display", w, r, files, state)
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -8,19 +8,44 @@ import (
 | 
				
			||||||
	"strings"
 | 
						"strings"
 | 
				
			||||||
	"time"
 | 
						"time"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						groupsstorage "git.coopgo.io/coopgo-platform/groups-management/storage"
 | 
				
			||||||
 | 
						"github.com/rs/zerolog/log"
 | 
				
			||||||
 | 
						"github.com/spf13/viper"
 | 
				
			||||||
	"gitlab.scity.coop/maas/navitia-golang/types"
 | 
						"gitlab.scity.coop/maas/navitia-golang/types"
 | 
				
			||||||
)
 | 
					)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
func TimeFrom(d any) *time.Time {
 | 
					func ModuleAvailable(group groupsstorage.Group, configmodules *viper.Viper) func(string) bool {
 | 
				
			||||||
 | 
						return func(module string) bool {
 | 
				
			||||||
 | 
							if module == "dashboard" {
 | 
				
			||||||
 | 
								return true
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
							groupmodules := group.Data["modules"].(map[string]any)
 | 
				
			||||||
 | 
							modAvailable, ok := groupmodules[module].(bool)
 | 
				
			||||||
 | 
							if ok && modAvailable && configmodules.GetBool(fmt.Sprintf("modules.%s.enabled", module)) {
 | 
				
			||||||
 | 
								return true
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
							return false
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					func TimeFrom(d any) *time.Time {
 | 
				
			||||||
 | 
						paris, err := time.LoadLocation("Europe/Paris")
 | 
				
			||||||
	if date, ok := d.(time.Time); ok {
 | 
						if date, ok := d.(time.Time); ok {
 | 
				
			||||||
		return &date
 | 
							if err != nil {
 | 
				
			||||||
 | 
								return &date
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
							nd := date.In(paris)
 | 
				
			||||||
 | 
							return &nd
 | 
				
			||||||
	} else if date, ok := d.(string); ok {
 | 
						} else if date, ok := d.(string); ok {
 | 
				
			||||||
		datetime, err := time.Parse("2006-01-02T15:04:05Z", date)
 | 
							datetime, err := time.Parse("2006-01-02T15:04:05Z", date)
 | 
				
			||||||
		if err != nil {
 | 
							if err != nil {
 | 
				
			||||||
			panic(err)
 | 
								datetime, err = time.Parse("2006-01-02", date)
 | 
				
			||||||
 | 
								if err != nil {
 | 
				
			||||||
 | 
									log.Error().Err(err).Msg("cannot parse date")
 | 
				
			||||||
 | 
								}
 | 
				
			||||||
		}
 | 
							}
 | 
				
			||||||
		return &datetime
 | 
							dt := datetime.In(paris)
 | 
				
			||||||
 | 
							return &dt
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
	return nil
 | 
						return nil
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
| 
						 | 
					@ -78,7 +103,6 @@ func RawJSON(v any) string {
 | 
				
			||||||
		return ""
 | 
							return ""
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
	return strings.TrimSuffix(buf.String(), "\n")
 | 
						return strings.TrimSuffix(buf.String(), "\n")
 | 
				
			||||||
 | 
					 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
func UnescapeHTML(s string) template.HTML {
 | 
					func UnescapeHTML(s string) template.HTML {
 | 
				
			||||||
| 
						 | 
					@ -127,3 +151,14 @@ func strval(v interface{}) string {
 | 
				
			||||||
func Divide[V int | float64](a, b V) V {
 | 
					func Divide[V int | float64](a, b V) V {
 | 
				
			||||||
	return a / b
 | 
						return a / b
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					func ShortDuration(d time.Duration) string {
 | 
				
			||||||
 | 
						s := d.String()
 | 
				
			||||||
 | 
						if strings.HasSuffix(s, "m0s") {
 | 
				
			||||||
 | 
							s = s[:len(s)-2]
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						if strings.HasSuffix(s, "h0m") {
 | 
				
			||||||
 | 
							s = s[:len(s)-2]
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						return s
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -7,6 +7,7 @@ import (
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	groupstorage "git.coopgo.io/coopgo-platform/groups-management/storage"
 | 
						groupstorage "git.coopgo.io/coopgo-platform/groups-management/storage"
 | 
				
			||||||
	mobilityaccountsstorage "git.coopgo.io/coopgo-platform/mobility-accounts/storage"
 | 
						mobilityaccountsstorage "git.coopgo.io/coopgo-platform/mobility-accounts/storage"
 | 
				
			||||||
 | 
						geojson "github.com/paulmach/orb/geojson"
 | 
				
			||||||
)
 | 
					)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
const journeysMenu = "journeys"
 | 
					const journeysMenu = "journeys"
 | 
				
			||||||
| 
						 | 
					@ -35,7 +36,7 @@ func (s BeneficiariesCovoiturage) JSONWithLimits(a int, b int) template.JS {
 | 
				
			||||||
	return s.JSON()
 | 
						return s.JSON()
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
func (renderer *Renderer) JourneysSearch(w http.ResponseWriter, r *http.Request, carpools any, transitjourneys any, vehicles []any, searched bool, departure any, destination any, departuredate string, departuretime string, solidarityDrivers any) {
 | 
					func (renderer *Renderer) JourneysSearch(w http.ResponseWriter, r *http.Request, carpools []*geojson.FeatureCollection, transitjourneys any, vehicles any, searched bool, departure any, destination any, departuredate string, departuretime string, driverJourneys any, solidarityDrivers any, organizedCarpools any, beneficiaries any, kbData any) {
 | 
				
			||||||
	files := renderer.ThemeConfig.GetStringSlice("views.journeys.search.files")
 | 
						files := renderer.ThemeConfig.GetStringSlice("views.journeys.search.files")
 | 
				
			||||||
	state := NewState(r, renderer.ThemeConfig, journeysMenu)
 | 
						state := NewState(r, renderer.ThemeConfig, journeysMenu)
 | 
				
			||||||
	state.ViewState = map[string]any{
 | 
						state.ViewState = map[string]any{
 | 
				
			||||||
| 
						 | 
					@ -46,8 +47,13 @@ func (renderer *Renderer) JourneysSearch(w http.ResponseWriter, r *http.Request,
 | 
				
			||||||
		"destination":        destination,
 | 
							"destination":        destination,
 | 
				
			||||||
		"journeys":           transitjourneys,
 | 
							"journeys":           transitjourneys,
 | 
				
			||||||
		"carpools":           carpools,
 | 
							"carpools":           carpools,
 | 
				
			||||||
 | 
							"organized_carpools": organizedCarpools,
 | 
				
			||||||
		"vehicles":           vehicles,
 | 
							"vehicles":           vehicles,
 | 
				
			||||||
 | 
							"driver_journeys":    driverJourneys,
 | 
				
			||||||
		"solidarity_drivers": solidarityDrivers,
 | 
							"solidarity_drivers": solidarityDrivers,
 | 
				
			||||||
 | 
							"querystring":        r.URL.RawQuery,
 | 
				
			||||||
 | 
							"beneficiaries":      beneficiaries,
 | 
				
			||||||
 | 
							"kb_data":            kbData,
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	renderer.Render("journeys", w, r, files, state)
 | 
						renderer.Render("journeys", w, r, files, state)
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -2,9 +2,14 @@ package renderer
 | 
				
			||||||
 | 
					
 | 
				
			||||||
type LayoutState struct {
 | 
					type LayoutState struct {
 | 
				
			||||||
	AdministrationState AdministrationState
 | 
						AdministrationState AdministrationState
 | 
				
			||||||
	MenuItems           []MenuItem
 | 
						Menu                any
 | 
				
			||||||
 | 
						ActiveMenu          string
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						// DEPRECATED
 | 
				
			||||||
 | 
						MenuItems []MenuItem
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					// DEPRECATED
 | 
				
			||||||
type MenuItem struct {
 | 
					type MenuItem struct {
 | 
				
			||||||
	Title  string
 | 
						Title  string
 | 
				
			||||||
	Link   string
 | 
						Link   string
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -0,0 +1,61 @@
 | 
				
			||||||
 | 
					package renderer
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					import (
 | 
				
			||||||
 | 
						"net/http"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						mobilityaccountsstorage "git.coopgo.io/coopgo-platform/mobility-accounts/storage"
 | 
				
			||||||
 | 
					)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					const organizedCarpoolMenu = "organized_carpool"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					func (renderer *Renderer) OrganizedCarpoolOverview(w http.ResponseWriter, r *http.Request, drivers any, driversMap any, passengersMap any, bookings any) {
 | 
				
			||||||
 | 
						files := renderer.ThemeConfig.GetStringSlice("views.organized_carpool.overview.files")
 | 
				
			||||||
 | 
						state := NewState(r, renderer.ThemeConfig, organizedCarpoolMenu)
 | 
				
			||||||
 | 
						state.ViewState = map[string]any{
 | 
				
			||||||
 | 
							"drivers":        drivers,
 | 
				
			||||||
 | 
							"drivers_map":    driversMap,
 | 
				
			||||||
 | 
							"passengers_map": passengersMap,
 | 
				
			||||||
 | 
							"bookings":       bookings,
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						renderer.Render("organized carpool overview", w, r, files, state)
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					func (renderer *Renderer) OrganizedCarpoolCreateDriver(w http.ResponseWriter, r *http.Request) {
 | 
				
			||||||
 | 
						files := renderer.ThemeConfig.GetStringSlice("views.organized_carpool.driver_create.files")
 | 
				
			||||||
 | 
						state := NewState(r, renderer.ThemeConfig, organizedCarpoolMenu)
 | 
				
			||||||
 | 
						state.ViewState = map[string]any{}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						renderer.Render("organized carpool driver creation", w, r, files, state)
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					func (renderer *Renderer) OrganizedCarpoolDriverDisplay(w http.ResponseWriter, r *http.Request, driver mobilityaccountsstorage.Account, trips any, documents any) {
 | 
				
			||||||
 | 
						files := renderer.ThemeConfig.GetStringSlice("views.organized_carpool.driver_display.files")
 | 
				
			||||||
 | 
						state := NewState(r, renderer.ThemeConfig, organizedCarpoolMenu)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						drivers_file_types := renderer.GlobalConfig.GetStringSlice("modules.organized_carpool.drivers.documents_types")
 | 
				
			||||||
 | 
						file_types_map := renderer.GlobalConfig.GetStringMapString("storage.files.file_types")
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						state.ViewState = map[string]any{
 | 
				
			||||||
 | 
							"driver":             driver,
 | 
				
			||||||
 | 
							"trips":              trips,
 | 
				
			||||||
 | 
							"documents":          documents,
 | 
				
			||||||
 | 
							"drivers_file_types": drivers_file_types,
 | 
				
			||||||
 | 
							"file_types_map":     file_types_map,
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						renderer.Render("organized carpool driver display", w, r, files, state)
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					func (renderer *Renderer) OrganizedCarpoolJourney(w http.ResponseWriter, r *http.Request, journey any, driver any, passenger any, beneficiaries any) {
 | 
				
			||||||
 | 
						files := renderer.ThemeConfig.GetStringSlice("views.organized_carpool.journey.files")
 | 
				
			||||||
 | 
						state := NewState(r, renderer.ThemeConfig, solidarityTransportMenu)
 | 
				
			||||||
 | 
						state.ViewState = map[string]any{
 | 
				
			||||||
 | 
							"driver":        driver,
 | 
				
			||||||
 | 
							"passenger":     passenger,
 | 
				
			||||||
 | 
							"beneficiaries": beneficiaries,
 | 
				
			||||||
 | 
							"journey":       journey,
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						renderer.Render("organized carpool journey", w, r, files, state)
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
| 
						 | 
					@ -8,6 +8,9 @@ import (
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	"git.coopgo.io/coopgo-apps/parcoursmob/utils/icons"
 | 
						"git.coopgo.io/coopgo-apps/parcoursmob/utils/icons"
 | 
				
			||||||
	"git.coopgo.io/coopgo-apps/parcoursmob/utils/identification"
 | 
						"git.coopgo.io/coopgo-apps/parcoursmob/utils/identification"
 | 
				
			||||||
 | 
						cache "git.coopgo.io/coopgo-apps/parcoursmob/utils/storage"
 | 
				
			||||||
 | 
						filestorage "git.coopgo.io/coopgo-apps/parcoursmob/utils/storage"
 | 
				
			||||||
 | 
						validatedprofile "git.coopgo.io/coopgo-apps/parcoursmob/utils/validated-profile"
 | 
				
			||||||
	"git.coopgo.io/coopgo-platform/emailing"
 | 
						"git.coopgo.io/coopgo-platform/emailing"
 | 
				
			||||||
	"git.coopgo.io/coopgo-platform/groups-management/storage"
 | 
						"git.coopgo.io/coopgo-platform/groups-management/storage"
 | 
				
			||||||
	"github.com/coreos/go-oidc/v3/oidc"
 | 
						"github.com/coreos/go-oidc/v3/oidc"
 | 
				
			||||||
| 
						 | 
					@ -20,9 +23,10 @@ type Renderer struct {
 | 
				
			||||||
	GlobalConfig *viper.Viper
 | 
						GlobalConfig *viper.Viper
 | 
				
			||||||
	ThemeConfig  *viper.Viper
 | 
						ThemeConfig  *viper.Viper
 | 
				
			||||||
	Mailer       *emailing.Mailer
 | 
						Mailer       *emailing.Mailer
 | 
				
			||||||
 | 
						FileStorage  cache.FileStorage
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
func NewRenderer(global *viper.Viper, templates_dir string) *Renderer {
 | 
					func NewRenderer(global *viper.Viper, templates_dir string, filestorage cache.FileStorage) *Renderer {
 | 
				
			||||||
	theme := viper.New()
 | 
						theme := viper.New()
 | 
				
			||||||
	theme.SetConfigName("config")
 | 
						theme.SetConfigName("config")
 | 
				
			||||||
	theme.AddConfigPath(templates_dir)
 | 
						theme.AddConfigPath(templates_dir)
 | 
				
			||||||
| 
						 | 
					@ -34,6 +38,7 @@ func NewRenderer(global *viper.Viper, templates_dir string) *Renderer {
 | 
				
			||||||
		TemplatesDir: templates_dir,
 | 
							TemplatesDir: templates_dir,
 | 
				
			||||||
		GlobalConfig: global,
 | 
							GlobalConfig: global,
 | 
				
			||||||
		ThemeConfig:  theme,
 | 
							ThemeConfig:  theme,
 | 
				
			||||||
 | 
							FileStorage:  filestorage,
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					@ -51,24 +56,41 @@ func (renderer *Renderer) Render(name string, w http.ResponseWriter, r *http.Req
 | 
				
			||||||
	w.WriteHeader(http.StatusOK)
 | 
						w.WriteHeader(http.StatusOK)
 | 
				
			||||||
	t := template.New(name).Funcs(
 | 
						t := template.New(name).Funcs(
 | 
				
			||||||
		template.FuncMap{
 | 
							template.FuncMap{
 | 
				
			||||||
			"timeFrom":      TimeFrom,
 | 
								"moduleAvailable":                  ModuleAvailable(state.Group, renderer.GlobalConfig),
 | 
				
			||||||
			"timeFormat":    TimeFormat,
 | 
								"timeFrom":                         TimeFrom,
 | 
				
			||||||
			"genderISO5218": GenderISO5218,
 | 
								"timeFormat":                       TimeFormat,
 | 
				
			||||||
			"dict":          Dict,
 | 
								"genderISO5218":                    GenderISO5218,
 | 
				
			||||||
			"json":          JSON,
 | 
								"dict":                             Dict,
 | 
				
			||||||
			"rawjson":       RawJSON,
 | 
								"json":                             JSON,
 | 
				
			||||||
			"unescapeHTML":  UnescapeHTML,
 | 
								"rawjson":                          RawJSON,
 | 
				
			||||||
			"walkingLength": WalkingLength,
 | 
								"unescapeHTML":                     UnescapeHTML,
 | 
				
			||||||
			"divideFloat64": Divide[float64],
 | 
								"walkingLength":                    WalkingLength,
 | 
				
			||||||
			"divideInt":     Divide[int],
 | 
								"divideFloat64":                    Divide[float64],
 | 
				
			||||||
			"typeOf":        reflect.TypeOf,
 | 
								"divideInt":                        Divide[int],
 | 
				
			||||||
 | 
								"typeOf":                           reflect.TypeOf,
 | 
				
			||||||
 | 
								"shortDuration":                    ShortDuration,
 | 
				
			||||||
 | 
								"beneficiaryValidatedProfile":      validatedprofile.ValidateProfile(renderer.GlobalConfig.Sub("modules.beneficiaries.validated_profile")),
 | 
				
			||||||
 | 
								"solidarityDriverValidatedProfile": validatedprofile.ValidateProfile(renderer.GlobalConfig.Sub("modules.solidarity_transport.drivers.validated_profile")),
 | 
				
			||||||
 | 
								"carpoolDriverValidatedProfile":    validatedprofile.ValidateProfile(renderer.GlobalConfig.Sub("modules.organized_carpool.drivers.validated_profile")),
 | 
				
			||||||
 | 
								"beneficiaryDocuments": func(id string) []filestorage.FileInfo {
 | 
				
			||||||
 | 
									documents := renderer.FileStorage.List(filestorage.PREFIX_BENEFICIARIES + "/" + id)
 | 
				
			||||||
 | 
									return documents
 | 
				
			||||||
 | 
								},
 | 
				
			||||||
 | 
								"solidarityDocuments": func(id string) []filestorage.FileInfo {
 | 
				
			||||||
 | 
									documents := renderer.FileStorage.List(filestorage.PREFIX_SOLIDARITY_TRANSPORT_DRIVERS + "/" + id)
 | 
				
			||||||
 | 
									return documents
 | 
				
			||||||
 | 
								},
 | 
				
			||||||
 | 
								"carpoolDocuments": func(id string) []filestorage.FileInfo {
 | 
				
			||||||
 | 
									documents := renderer.FileStorage.List(filestorage.PREFIX_ORGANIZED_CARPOOL_DRIVERS + "/" + id)
 | 
				
			||||||
 | 
									return documents
 | 
				
			||||||
 | 
								},
 | 
				
			||||||
		},
 | 
							},
 | 
				
			||||||
	)
 | 
						)
 | 
				
			||||||
	t = template.Must(t.ParseFiles(prefixed_files...))
 | 
						t = template.Must(t.ParseFiles(prefixed_files...))
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	err := t.ExecuteTemplate(w, "main", state)
 | 
						err := t.ExecuteTemplate(w, "main", state)
 | 
				
			||||||
	if err != nil {
 | 
						if err != nil {
 | 
				
			||||||
		log.Error().Err(err).Msg("")
 | 
							log.Error().Err(err).Msg("issue executing template")
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					@ -81,23 +103,39 @@ func (renderer *Renderer) RenderNoLayout(name string, w http.ResponseWriter, r *
 | 
				
			||||||
	w.WriteHeader(http.StatusOK)
 | 
						w.WriteHeader(http.StatusOK)
 | 
				
			||||||
	t := template.New(name).Funcs(
 | 
						t := template.New(name).Funcs(
 | 
				
			||||||
		template.FuncMap{
 | 
							template.FuncMap{
 | 
				
			||||||
			"timeFrom":      TimeFrom,
 | 
								"timeFrom":                         TimeFrom,
 | 
				
			||||||
			"timeFormat":    TimeFormat,
 | 
								"timeFormat":                       TimeFormat,
 | 
				
			||||||
			"genderISO5218": GenderISO5218,
 | 
								"genderISO5218":                    GenderISO5218,
 | 
				
			||||||
			"dict":          Dict,
 | 
								"dict":                             Dict,
 | 
				
			||||||
			"json":          JSON,
 | 
								"json":                             JSON,
 | 
				
			||||||
			"rawjson":       RawJSON,
 | 
								"rawjson":                          RawJSON,
 | 
				
			||||||
			"unsescapeHTML": UnescapeHTML,
 | 
								"unsescapeHTML":                    UnescapeHTML,
 | 
				
			||||||
			"divideFloat64": Divide[float64],
 | 
								"divideFloat64":                    Divide[float64],
 | 
				
			||||||
			"divideInt":     Divide[int],
 | 
								"divideInt":                        Divide[int],
 | 
				
			||||||
			"typeOf":        reflect.TypeOf,
 | 
								"typeOf":                           reflect.TypeOf,
 | 
				
			||||||
 | 
								"shortDuration":                    ShortDuration,
 | 
				
			||||||
 | 
								"beneficiaryValidatedProfile":      validatedprofile.ValidateProfile(renderer.GlobalConfig.Sub("modules.beneficiaries.validated_profile")),
 | 
				
			||||||
 | 
								"solidarityDriverValidatedProfile": validatedprofile.ValidateProfile(renderer.GlobalConfig.Sub("modules.solidarity_transport.drivers.validated_profile")),
 | 
				
			||||||
 | 
								"carpoolDriverValidatedProfile":    validatedprofile.ValidateProfile(renderer.GlobalConfig.Sub("modules.organized_carpool.drivers.validated_profile")),
 | 
				
			||||||
 | 
								"beneficiaryDocuments": func(id string) []filestorage.FileInfo {
 | 
				
			||||||
 | 
									documents := renderer.FileStorage.List(filestorage.PREFIX_BENEFICIARIES + "/" + id)
 | 
				
			||||||
 | 
									return documents
 | 
				
			||||||
 | 
								},
 | 
				
			||||||
 | 
								"solidarityDocuments": func(id string) []filestorage.FileInfo {
 | 
				
			||||||
 | 
									documents := renderer.FileStorage.List(filestorage.PREFIX_SOLIDARITY_TRANSPORT_DRIVERS + "/" + id)
 | 
				
			||||||
 | 
									return documents
 | 
				
			||||||
 | 
								},
 | 
				
			||||||
 | 
								"carpoolDocuments": func(id string) []filestorage.FileInfo {
 | 
				
			||||||
 | 
									documents := renderer.FileStorage.List(filestorage.PREFIX_ORGANIZED_CARPOOL_DRIVERS + "/" + id)
 | 
				
			||||||
 | 
									return documents
 | 
				
			||||||
 | 
								},
 | 
				
			||||||
		},
 | 
							},
 | 
				
			||||||
	)
 | 
						)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	t = template.Must(t.ParseFiles(prefixed_files...))
 | 
						t = template.Must(t.ParseFiles(prefixed_files...))
 | 
				
			||||||
	err := t.ExecuteTemplate(w, "main", state)
 | 
						err := t.ExecuteTemplate(w, "main", state)
 | 
				
			||||||
	if err != nil {
 | 
						if err != nil {
 | 
				
			||||||
		log.Error().Err(err).Msg("")
 | 
							log.Error().Err(err).Msg("issue executing template")
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					@ -117,6 +155,7 @@ type RenderState struct {
 | 
				
			||||||
 | 
					
 | 
				
			||||||
func NewState(r *http.Request, themeConfig *viper.Viper, menuState string) RenderState {
 | 
					func NewState(r *http.Request, themeConfig *viper.Viper, menuState string) RenderState {
 | 
				
			||||||
	iconset := themeConfig.GetStringMapString("icons.svg")
 | 
						iconset := themeConfig.GetStringMapString("icons.svg")
 | 
				
			||||||
 | 
						menu := themeConfig.Get("menu_items")
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	// Get State elements from Request
 | 
						// Get State elements from Request
 | 
				
			||||||
	var userid string
 | 
						var userid string
 | 
				
			||||||
| 
						 | 
					@ -162,6 +201,9 @@ func NewState(r *http.Request, themeConfig *viper.Viper, menuState string) Rende
 | 
				
			||||||
			Active:  menuState == administrationMenu,
 | 
								Active:  menuState == administrationMenu,
 | 
				
			||||||
		},
 | 
							},
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							Menu: menu,
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							// DEPRECATED
 | 
				
			||||||
		MenuItems: []MenuItem{
 | 
							MenuItems: []MenuItem{
 | 
				
			||||||
			{
 | 
								{
 | 
				
			||||||
				Title:  "Tableau de bord",
 | 
									Title:  "Tableau de bord",
 | 
				
			||||||
| 
						 | 
					@ -172,6 +214,7 @@ func NewState(r *http.Request, themeConfig *viper.Viper, menuState string) Rende
 | 
				
			||||||
		},
 | 
							},
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						// DEPRECATED
 | 
				
			||||||
	if modules["beneficiaries"] != nil && modules["beneficiaries"].(bool) {
 | 
						if modules["beneficiaries"] != nil && modules["beneficiaries"].(bool) {
 | 
				
			||||||
		ls.MenuItems = append(ls.MenuItems, MenuItem{
 | 
							ls.MenuItems = append(ls.MenuItems, MenuItem{
 | 
				
			||||||
			Title:  "Bénéficiaires",
 | 
								Title:  "Bénéficiaires",
 | 
				
			||||||
| 
						 | 
					@ -252,14 +295,6 @@ func NewState(r *http.Request, themeConfig *viper.Viper, menuState string) Rende
 | 
				
			||||||
			Icon:   "hero:outline/document-text",
 | 
								Icon:   "hero:outline/document-text",
 | 
				
			||||||
		})
 | 
							})
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
	/*if modules["conseillers"] != nil && modules["conseillers"].(bool) {
 | 
					 | 
				
			||||||
		ls.MenuItems = append(ls.MenuItems, MenuItem{
 | 
					 | 
				
			||||||
			Title:  "Conseillers",
 | 
					 | 
				
			||||||
			Link:   "/app/conseillers/",
 | 
					 | 
				
			||||||
			Active: menuState == membersMenu,
 | 
					 | 
				
			||||||
			Icon:   "hero:outline/user-group",
 | 
					 | 
				
			||||||
		})
 | 
					 | 
				
			||||||
	}*/
 | 
					 | 
				
			||||||
	/*if modules["diags"] != nil && modules["diags"].(bool) {
 | 
						/*if modules["diags"] != nil && modules["diags"].(bool) {
 | 
				
			||||||
		ls.MenuItems = append(ls.MenuItems, MenuItem{
 | 
							ls.MenuItems = append(ls.MenuItems, MenuItem{
 | 
				
			||||||
			Title:  "Diagnostics",
 | 
								Title:  "Diagnostics",
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -0,0 +1,16 @@
 | 
				
			||||||
 | 
					package renderer
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					import "net/http"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					func (renderer *Renderer) SolidarityTransportExternalBookingDisplay(w http.ResponseWriter, r *http.Request, booking any, driver any, passenger any) {
 | 
				
			||||||
 | 
						files := renderer.ThemeConfig.GetStringSlice("views.solidarity_transport.ext.booking_proposal.files")
 | 
				
			||||||
 | 
						state := NewState(r, renderer.ThemeConfig, solidarityTransportMenu)
 | 
				
			||||||
 | 
						state.ViewState = map[string]any{
 | 
				
			||||||
 | 
							"driver":    driver,
 | 
				
			||||||
 | 
							"passenger": passenger,
 | 
				
			||||||
 | 
							"booking":   booking,
 | 
				
			||||||
 | 
							"config":    renderer.GlobalConfig,
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						renderer.RenderNoLayout("booking display", w, r, files, state)
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
| 
						 | 
					@ -8,11 +8,15 @@ import (
 | 
				
			||||||
 | 
					
 | 
				
			||||||
const solidarityTransportMenu = "solidarity_transport"
 | 
					const solidarityTransportMenu = "solidarity_transport"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
func (renderer *Renderer) SolidarityTransportOverview(w http.ResponseWriter, r *http.Request, drivers []mobilityaccountsstorage.Account) {
 | 
					func (renderer *Renderer) SolidarityTransportOverview(w http.ResponseWriter, r *http.Request, drivers any, driversMap any, passengersMap any, bookings any, bookingsHistory any) {
 | 
				
			||||||
	files := renderer.ThemeConfig.GetStringSlice("views.solidarity_transport.overview.files")
 | 
						files := renderer.ThemeConfig.GetStringSlice("views.solidarity_transport.overview.files")
 | 
				
			||||||
	state := NewState(r, renderer.ThemeConfig, solidarityTransportMenu)
 | 
						state := NewState(r, renderer.ThemeConfig, solidarityTransportMenu)
 | 
				
			||||||
	state.ViewState = map[string]any{
 | 
						state.ViewState = map[string]any{
 | 
				
			||||||
		"drivers": drivers,
 | 
							"drivers":          drivers,
 | 
				
			||||||
 | 
							"drivers_map":      driversMap,
 | 
				
			||||||
 | 
							"passengers_map":   passengersMap,
 | 
				
			||||||
 | 
							"bookings":         bookings,
 | 
				
			||||||
 | 
							"bookings_history": bookingsHistory,
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	renderer.Render("solidarity transport overview", w, r, files, state)
 | 
						renderer.Render("solidarity transport overview", w, r, files, state)
 | 
				
			||||||
| 
						 | 
					@ -26,13 +30,58 @@ func (renderer *Renderer) SolidarityTransportCreateDriver(w http.ResponseWriter,
 | 
				
			||||||
	renderer.Render("solidarity transport driver creation", w, r, files, state)
 | 
						renderer.Render("solidarity transport driver creation", w, r, files, state)
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
func (renderer *Renderer) SolidarityTransportDriverDisplay(w http.ResponseWriter, r *http.Request, driver mobilityaccountsstorage.Account) {
 | 
					func (renderer *Renderer) SolidarityTransportUpdateDriver(w http.ResponseWriter, r *http.Request, driver any) {
 | 
				
			||||||
	files := renderer.ThemeConfig.GetStringSlice("views.solidarity_transport.driver_display.files")
 | 
						files := renderer.ThemeConfig.GetStringSlice("views.solidarity_transport.driver_update.files")
 | 
				
			||||||
	state := NewState(r, renderer.ThemeConfig, solidarityTransportMenu)
 | 
						state := NewState(r, renderer.ThemeConfig, solidarityTransportMenu)
 | 
				
			||||||
	state.ViewState = map[string]any{
 | 
						state.ViewState = map[string]any{
 | 
				
			||||||
		"driver":    driver,
 | 
							"driver": driver,
 | 
				
			||||||
		"documents": []any{},
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						renderer.Render("solidarity transport driver update", w, r, files, state)
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					func (renderer *Renderer) SolidarityTransportDriverDisplay(w http.ResponseWriter, r *http.Request, driver mobilityaccountsstorage.Account, availabilities any, documents any, bookings any, stats map[string]any) {
 | 
				
			||||||
 | 
						files := renderer.ThemeConfig.GetStringSlice("views.solidarity_transport.driver_display.files")
 | 
				
			||||||
 | 
						state := NewState(r, renderer.ThemeConfig, solidarityTransportMenu)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						drivers_file_types := renderer.GlobalConfig.GetStringSlice("modules.solidarity_transport.drivers.documents_types")
 | 
				
			||||||
 | 
						file_types_map := renderer.GlobalConfig.GetStringMapString("storage.files.file_types")
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						state.ViewState = map[string]any{
 | 
				
			||||||
 | 
							"driver":             driver,
 | 
				
			||||||
 | 
							"availabilities":     availabilities,
 | 
				
			||||||
 | 
							"bookings":           bookings,
 | 
				
			||||||
 | 
							"documents":          documents,
 | 
				
			||||||
 | 
							"drivers_file_types": drivers_file_types,
 | 
				
			||||||
 | 
							"file_types_map":     file_types_map,
 | 
				
			||||||
 | 
							"stats":              stats,
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	renderer.Render("solidarity transport driver creation", w, r, files, state)
 | 
						renderer.Render("solidarity transport driver creation", w, r, files, state)
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					func (renderer *Renderer) SolidarityTransportDriverJourney(w http.ResponseWriter, r *http.Request, driverJourney any, driver any, passenger any, beneficiaries any) {
 | 
				
			||||||
 | 
						files := renderer.ThemeConfig.GetStringSlice("views.solidarity_transport.driver_journey.files")
 | 
				
			||||||
 | 
						state := NewState(r, renderer.ThemeConfig, solidarityTransportMenu)
 | 
				
			||||||
 | 
						state.ViewState = map[string]any{
 | 
				
			||||||
 | 
							"driver":         driver,
 | 
				
			||||||
 | 
							"passenger":      passenger,
 | 
				
			||||||
 | 
							"beneficiaries":  beneficiaries,
 | 
				
			||||||
 | 
							"driver_journey": driverJourney,
 | 
				
			||||||
 | 
							"config":         renderer.GlobalConfig,
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						renderer.Render("solidarity transport driver creation", w, r, files, state)
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					func (renderer *Renderer) SolidarityTransportBookingDisplay(w http.ResponseWriter, r *http.Request, booking any, driver any, passenger any) {
 | 
				
			||||||
 | 
						files := renderer.ThemeConfig.GetStringSlice("views.solidarity_transport.booking_display.files")
 | 
				
			||||||
 | 
						state := NewState(r, renderer.ThemeConfig, solidarityTransportMenu)
 | 
				
			||||||
 | 
						state.ViewState = map[string]any{
 | 
				
			||||||
 | 
							"driver":    driver,
 | 
				
			||||||
 | 
							"passenger": passenger,
 | 
				
			||||||
 | 
							"booking":   booking,
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						renderer.Render("booking display", w, r, files, state)
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -5,6 +5,7 @@ import (
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	filestorage "git.coopgo.io/coopgo-apps/parcoursmob/utils/storage"
 | 
						filestorage "git.coopgo.io/coopgo-apps/parcoursmob/utils/storage"
 | 
				
			||||||
	"git.coopgo.io/coopgo-platform/fleets/storage"
 | 
						"git.coopgo.io/coopgo-platform/fleets/storage"
 | 
				
			||||||
 | 
						fleetsstorage "git.coopgo.io/coopgo-platform/fleets/storage"
 | 
				
			||||||
	mobilityaccountsstorage "git.coopgo.io/coopgo-platform/mobility-accounts/storage"
 | 
						mobilityaccountsstorage "git.coopgo.io/coopgo-platform/mobility-accounts/storage"
 | 
				
			||||||
)
 | 
					)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					@ -22,7 +23,7 @@ func selectDocumentsDefaults(beneficiarydocuments []filestorage.FileInfo, mandat
 | 
				
			||||||
	return res
 | 
						return res
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
func (renderer *Renderer) VehiclesSearch(w http.ResponseWriter, r *http.Request, beneficiaries []mobilityaccountsstorage.Account, searched bool, vehicles []any, beneficiary any, startdate any, enddate any, mandatory_documents []string, file_types_map map[string]string, beneficiarydocuments []filestorage.FileInfo, selected_type string, automatic bool, vehicles_types []string, admingroups map[string]any) {
 | 
					func (renderer *Renderer) VehiclesSearch(w http.ResponseWriter, r *http.Request, beneficiaries []mobilityaccountsstorage.Account, searched bool, vehicles []fleetsstorage.Vehicle, beneficiary any, startdate any, enddate any, mandatory_documents []string, file_types_map map[string]string, beneficiarydocuments []filestorage.FileInfo, selected_type string, automatic bool, vehicles_types []string, admingroups map[string]any) {
 | 
				
			||||||
	files := renderer.ThemeConfig.GetStringSlice("views.vehicles.search.files")
 | 
						files := renderer.ThemeConfig.GetStringSlice("views.vehicles.search.files")
 | 
				
			||||||
	state := NewState(r, renderer.ThemeConfig, vehiclesMenu)
 | 
						state := NewState(r, renderer.ThemeConfig, vehiclesMenu)
 | 
				
			||||||
	viewstate := map[string]any{
 | 
						viewstate := map[string]any{
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -0,0 +1,23 @@
 | 
				
			||||||
 | 
					package services
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					import (
 | 
				
			||||||
 | 
						"git.coopgo.io/coopgo-platform/carpool-service/servers/grpc/proto"
 | 
				
			||||||
 | 
						"google.golang.org/grpc"
 | 
				
			||||||
 | 
					)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					type CarpoolService struct {
 | 
				
			||||||
 | 
						proto.CarpoolServiceClient
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					func NewCarpoolService(dial string) (*CarpoolService, error) {
 | 
				
			||||||
 | 
						conn, err := grpc.Dial(dial, grpc.WithInsecure())
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						client := proto.NewCarpoolServiceClient(conn)
 | 
				
			||||||
 | 
						if err != nil {
 | 
				
			||||||
 | 
							return nil, err
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						return &CarpoolService{
 | 
				
			||||||
 | 
							CarpoolServiceClient: client,
 | 
				
			||||||
 | 
						}, nil
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
| 
						 | 
					@ -91,6 +91,37 @@ func (s *ServicesHandler) GetAccountsInNamespace(namespace string) (accounts []s
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	return
 | 
						return
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					func (s *ServicesHandler) GetAccountsInNamespaceMap(namespace string) (accounts map[string]storage.Account, err error) {
 | 
				
			||||||
 | 
						accounts = map[string]storage.Account{}
 | 
				
			||||||
 | 
						request := &mobilityaccounts.GetAccountsRequest{
 | 
				
			||||||
 | 
							Namespaces: []string{namespace},
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						resp, err := s.GRPC.MobilityAccounts.GetAccounts(context.TODO(), request)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						if err == nil {
 | 
				
			||||||
 | 
							for _, v := range resp.Accounts {
 | 
				
			||||||
 | 
								accounts[v.Id] = v.ToStorageType()
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						return
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					func (s *ServicesHandler) GetAccountsInNamespacesMap(namespaces []string) (accounts map[string]storage.Account, err error) {
 | 
				
			||||||
 | 
						accounts = map[string]storage.Account{}
 | 
				
			||||||
 | 
						request := &mobilityaccounts.GetAccountsRequest{
 | 
				
			||||||
 | 
							Namespaces: namespaces,
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						resp, err := s.GRPC.MobilityAccounts.GetAccounts(context.TODO(), request)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						if err == nil {
 | 
				
			||||||
 | 
							for _, v := range resp.Accounts {
 | 
				
			||||||
 | 
								accounts[v.Id] = v.ToStorageType()
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						return
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
func (s *ServicesHandler) GetAccount(id string) (account storage.Account, err error) {
 | 
					func (s *ServicesHandler) GetAccount(id string) (account storage.Account, err error) {
 | 
				
			||||||
	request := &mobilityaccounts.GetAccountRequest{
 | 
						request := &mobilityaccounts.GetAccountRequest{
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -2,32 +2,53 @@ package services
 | 
				
			||||||
 | 
					
 | 
				
			||||||
import (
 | 
					import (
 | 
				
			||||||
	agenda "git.coopgo.io/coopgo-platform/agenda/grpcapi"
 | 
						agenda "git.coopgo.io/coopgo-platform/agenda/grpcapi"
 | 
				
			||||||
 | 
						carpoolservice "git.coopgo.io/coopgo-platform/carpool-service/servers/grpc/proto"
 | 
				
			||||||
	diags "git.coopgo.io/coopgo-platform/diags/grpcapi"
 | 
						diags "git.coopgo.io/coopgo-platform/diags/grpcapi"
 | 
				
			||||||
	fleets "git.coopgo.io/coopgo-platform/fleets/grpcapi"
 | 
						fleets "git.coopgo.io/coopgo-platform/fleets/grpcapi"
 | 
				
			||||||
 | 
						"git.coopgo.io/coopgo-platform/geography/handlers/admin"
 | 
				
			||||||
	groupsmanagement "git.coopgo.io/coopgo-platform/groups-management/grpcapi"
 | 
						groupsmanagement "git.coopgo.io/coopgo-platform/groups-management/grpcapi"
 | 
				
			||||||
	mobilityaccounts "git.coopgo.io/coopgo-platform/mobility-accounts/grpcapi"
 | 
						mobilityaccounts "git.coopgo.io/coopgo-platform/mobility-accounts/grpcapi"
 | 
				
			||||||
 | 
						multimodal "git.coopgo.io/coopgo-platform/multimodal-routing/handlers"
 | 
				
			||||||
 | 
						"git.coopgo.io/coopgo-platform/multimodal-routing/libs/transit/motis"
 | 
				
			||||||
 | 
						"git.coopgo.io/coopgo-platform/payments/pricing"
 | 
				
			||||||
 | 
						"git.coopgo.io/coopgo-platform/routing-service"
 | 
				
			||||||
 | 
						"git.coopgo.io/coopgo-platform/sms"
 | 
				
			||||||
 | 
						solidaritytransport "git.coopgo.io/coopgo-platform/solidarity-transport/servers/grpc/proto/gen"
 | 
				
			||||||
	"github.com/rs/zerolog/log"
 | 
						"github.com/rs/zerolog/log"
 | 
				
			||||||
	"github.com/spf13/viper"
 | 
						"github.com/spf13/viper"
 | 
				
			||||||
)
 | 
					)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
type ServicesHandler struct {
 | 
					type ServicesHandler struct {
 | 
				
			||||||
	GRPC GRPCServices
 | 
						GRPC           GRPCServices
 | 
				
			||||||
 | 
						InteropCarpool *multimodal.CarpoolRoutingHandler
 | 
				
			||||||
 | 
						Routing        routing.RoutingService
 | 
				
			||||||
 | 
						TransitRouting *motis.ClientWithResponses
 | 
				
			||||||
 | 
						SMS            *sms.SMSHandler
 | 
				
			||||||
 | 
						Pricing        pricing.PricingService
 | 
				
			||||||
 | 
						Geography      admin.AdminIndex
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
type GRPCServices struct {
 | 
					type GRPCServices struct {
 | 
				
			||||||
	MobilityAccounts mobilityaccounts.MobilityAccountsClient
 | 
						MobilityAccounts    mobilityaccounts.MobilityAccountsClient
 | 
				
			||||||
	GroupsManagement groupsmanagement.GroupsManagementClient
 | 
						GroupsManagement    groupsmanagement.GroupsManagementClient
 | 
				
			||||||
	Fleets           fleets.FleetsClient
 | 
						Fleets              fleets.FleetsClient
 | 
				
			||||||
	Agenda           agenda.AgendaClient
 | 
						Agenda              agenda.AgendaClient
 | 
				
			||||||
	Diags            diags.DiagsClient
 | 
						SolidarityTransport solidaritytransport.SolidarityTransportClient
 | 
				
			||||||
 | 
						CarpoolService      carpoolservice.CarpoolServiceClient
 | 
				
			||||||
 | 
						Diags               diags.DiagsClient
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
func NewServicesHandler(cfg *viper.Viper) (*ServicesHandler, error) {
 | 
					func NewServicesHandler(cfg *viper.Viper) (*ServicesHandler, error) {
 | 
				
			||||||
	var (
 | 
						var (
 | 
				
			||||||
		mobilityAccountsDial = cfg.GetString("services.grpc.mobilityaccounts.dial")
 | 
							mobilityAccountsDial    = cfg.GetString("services.grpc.mobilityaccounts.dial")
 | 
				
			||||||
		groupsManagementDial = cfg.GetString("services.grpc.groupsmanagement.dial")
 | 
							groupsManagementDial    = cfg.GetString("services.grpc.groupsmanagement.dial")
 | 
				
			||||||
		fleetsDial           = cfg.GetString("services.grpc.fleets.dial")
 | 
							fleetsDial              = cfg.GetString("services.grpc.fleets.dial")
 | 
				
			||||||
		agendaDial           = cfg.GetString("services.grpc.agenda.dial")
 | 
							agendaDial              = cfg.GetString("services.grpc.agenda.dial")
 | 
				
			||||||
 | 
							solidarityTransportDial = cfg.GetString("services.grpc.solidaritytransport.dial")
 | 
				
			||||||
 | 
							carpoolServiceDial      = cfg.GetString("services.grpc.carpoolservice.dial")
 | 
				
			||||||
 | 
							routing_service_type    = cfg.GetString("routing.type")
 | 
				
			||||||
 | 
							valhalla_base_url       = cfg.GetString("routing.valhalla.base_url")
 | 
				
			||||||
 | 
					
 | 
				
			||||||
		// diagsDial            = cfg.GetString("services.grpc.diags.dial")
 | 
							// diagsDial            = cfg.GetString("services.grpc.diags.dial")
 | 
				
			||||||
	)
 | 
						)
 | 
				
			||||||
	mobilityAccounts, err := NewMobilityAccountService(mobilityAccountsDial)
 | 
						mobilityAccounts, err := NewMobilityAccountService(mobilityAccountsDial)
 | 
				
			||||||
| 
						 | 
					@ -37,20 +58,31 @@ func NewServicesHandler(cfg *viper.Viper) (*ServicesHandler, error) {
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	groupsManagement, err := NewGroupsManagementService(groupsManagementDial)
 | 
						groupsManagement, err := NewGroupsManagementService(groupsManagementDial)
 | 
				
			||||||
	log.Error().Err(err).Msg("Groups mgmt service issue")
 | 
					 | 
				
			||||||
	if err != nil {
 | 
						if err != nil {
 | 
				
			||||||
 | 
							log.Error().Err(err).Msg("Groups mgmt service issue")
 | 
				
			||||||
		return nil, err
 | 
							return nil, err
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	fleetsSvc, err := NewFleetsService(fleetsDial)
 | 
						fleetsSvc, err := NewFleetsService(fleetsDial)
 | 
				
			||||||
	log.Error().Err(err).Msg("Fleets service issue")
 | 
					 | 
				
			||||||
	if err != nil {
 | 
						if err != nil {
 | 
				
			||||||
 | 
							log.Error().Err(err).Msg("Fleets service issue")
 | 
				
			||||||
		return nil, err
 | 
							return nil, err
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	agendaSvc, err := NewAgendaService(agendaDial)
 | 
						agendaSvc, err := NewAgendaService(agendaDial)
 | 
				
			||||||
	log.Error().Err(err).Msg("Agenda service issue")
 | 
					 | 
				
			||||||
	if err != nil {
 | 
						if err != nil {
 | 
				
			||||||
 | 
							log.Error().Err(err).Msg("Agenda service issue")
 | 
				
			||||||
 | 
							return nil, err
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						solidarityTransportSvc, err := NewSolidarityTransportService(solidarityTransportDial)
 | 
				
			||||||
 | 
						if err != nil {
 | 
				
			||||||
 | 
							log.Error().Err(err).Msg("Solidarity Transport service issue")
 | 
				
			||||||
 | 
							return nil, err
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						carpoolSvc, err := NewCarpoolService(carpoolServiceDial)
 | 
				
			||||||
 | 
						if err != nil {
 | 
				
			||||||
 | 
							log.Error().Err(err).Msg("Carpool service service issue")
 | 
				
			||||||
		return nil, err
 | 
							return nil, err
 | 
				
			||||||
	}
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					@ -59,14 +91,61 @@ func NewServicesHandler(cfg *viper.Viper) (*ServicesHandler, error) {
 | 
				
			||||||
	//if err != nil {
 | 
						//if err != nil {
 | 
				
			||||||
	//		return nil, err
 | 
						//		return nil, err
 | 
				
			||||||
	//}
 | 
						//}
 | 
				
			||||||
 | 
						routing, err := routing.NewRoutingService(routing_service_type, valhalla_base_url)
 | 
				
			||||||
 | 
						if err != nil {
 | 
				
			||||||
 | 
							log.Fatal().Err(err).Msg("Could not initiate the routing service")
 | 
				
			||||||
 | 
							return nil, err
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						carpoolRouting, err := multimodal.NewCarpoolRoutingHandler(cfg.Sub("multimodal.modes.carpool"))
 | 
				
			||||||
 | 
						if err != nil {
 | 
				
			||||||
 | 
							log.Fatal().Err(err).Msg("Could not initiate the carpool routing service")
 | 
				
			||||||
 | 
							return nil, err
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						motisRouting, err := motis.NewClientWithResponses(cfg.GetString("multimodal.modes.transit.motis.server"))
 | 
				
			||||||
 | 
						if err != nil {
 | 
				
			||||||
 | 
							log.Fatal().Err(err).Msg("Could not initiate the transit routing service")
 | 
				
			||||||
 | 
							return nil, err
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						pricing_type := cfg.GetString("payments.pricing.type")
 | 
				
			||||||
 | 
						if pricing_type == "" {
 | 
				
			||||||
 | 
							pricing_type = "mms43"
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						pricingService, err := pricing.NewPricingService(pricing_type)
 | 
				
			||||||
 | 
						if err != nil {
 | 
				
			||||||
 | 
							log.Fatal().Err(err).Msg("Could not initiate the pricing service")
 | 
				
			||||||
 | 
							return nil, err
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						smsHandler, err := sms.NewSMSHandler(cfg.Sub("sms"))
 | 
				
			||||||
 | 
						if err != nil {
 | 
				
			||||||
 | 
							log.Fatal().Err(err).Msg("Could not initiate the SMS handler")
 | 
				
			||||||
 | 
							return nil, err
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						geography, err := admin.NewAdminIndex(cfg.Sub("geography"))
 | 
				
			||||||
 | 
						if err != nil {
 | 
				
			||||||
 | 
							log.Fatal().Err(err).Msg("could not initiate admin index")
 | 
				
			||||||
 | 
							return nil, err
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
	return &ServicesHandler{
 | 
						return &ServicesHandler{
 | 
				
			||||||
		GRPC: GRPCServices{
 | 
							GRPC: GRPCServices{
 | 
				
			||||||
			MobilityAccounts: mobilityAccounts,
 | 
								MobilityAccounts:    mobilityAccounts,
 | 
				
			||||||
			GroupsManagement: groupsManagement,
 | 
								GroupsManagement:    groupsManagement,
 | 
				
			||||||
			Fleets:           fleetsSvc,
 | 
								Fleets:              fleetsSvc,
 | 
				
			||||||
			Agenda:           agendaSvc,
 | 
								Agenda:              agendaSvc,
 | 
				
			||||||
 | 
								SolidarityTransport: solidarityTransportSvc,
 | 
				
			||||||
 | 
								CarpoolService:      carpoolSvc,
 | 
				
			||||||
			//		Diags:            diagsSvc,
 | 
								//		Diags:            diagsSvc,
 | 
				
			||||||
		},
 | 
							},
 | 
				
			||||||
 | 
							Routing:        routing,
 | 
				
			||||||
 | 
							InteropCarpool: carpoolRouting,
 | 
				
			||||||
 | 
							TransitRouting: motisRouting,
 | 
				
			||||||
 | 
							SMS:            smsHandler,
 | 
				
			||||||
 | 
							Pricing:        pricingService,
 | 
				
			||||||
 | 
							Geography:      geography,
 | 
				
			||||||
	}, nil
 | 
						}, nil
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -0,0 +1,23 @@
 | 
				
			||||||
 | 
					package services
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					import (
 | 
				
			||||||
 | 
						"git.coopgo.io/coopgo-platform/solidarity-transport/servers/grpc/proto/gen"
 | 
				
			||||||
 | 
						"google.golang.org/grpc"
 | 
				
			||||||
 | 
					)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					type SolidarityTransportService struct {
 | 
				
			||||||
 | 
						gen.SolidarityTransportClient
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					func NewSolidarityTransportService(dial string) (*SolidarityTransportService, error) {
 | 
				
			||||||
 | 
						conn, err := grpc.Dial(dial, grpc.WithInsecure())
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						client := gen.NewSolidarityTransportClient(conn)
 | 
				
			||||||
 | 
						if err != nil {
 | 
				
			||||||
 | 
							return nil, err
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						return &SolidarityTransportService{
 | 
				
			||||||
 | 
							SolidarityTransportClient: client,
 | 
				
			||||||
 | 
						}, nil
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
| 
						 | 
					@ -0,0 +1,19 @@
 | 
				
			||||||
 | 
					package protectapi
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					import (
 | 
				
			||||||
 | 
						"net/http"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						"github.com/rs/zerolog/log"
 | 
				
			||||||
 | 
					)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					func ApiKey(apiKey string) func(http.Handler) http.Handler {
 | 
				
			||||||
 | 
						return func(next http.Handler) http.Handler {
 | 
				
			||||||
 | 
							return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
 | 
				
			||||||
 | 
								if apiKey == "" || r.Header.Get("X_API_KEY") != apiKey {
 | 
				
			||||||
 | 
									log.Info().Msg("call to api not allowed")
 | 
				
			||||||
 | 
									w.WriteHeader(http.StatusForbidden)
 | 
				
			||||||
 | 
								}
 | 
				
			||||||
 | 
								next.ServeHTTP(w, r)
 | 
				
			||||||
 | 
							})
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
| 
						 | 
					@ -1,9 +1,15 @@
 | 
				
			||||||
package sorting
 | 
					package sorting
 | 
				
			||||||
 | 
					
 | 
				
			||||||
import (
 | 
					import (
 | 
				
			||||||
 | 
						"cmp"
 | 
				
			||||||
 | 
						"encoding/json"
 | 
				
			||||||
	"strings"
 | 
						"strings"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						"git.coopgo.io/coopgo-platform/fleets/storage"
 | 
				
			||||||
	fleetsstorage "git.coopgo.io/coopgo-platform/fleets/storage"
 | 
						fleetsstorage "git.coopgo.io/coopgo-platform/fleets/storage"
 | 
				
			||||||
 | 
						"github.com/paulmach/orb/geo"
 | 
				
			||||||
 | 
						"github.com/paulmach/orb/geojson"
 | 
				
			||||||
 | 
						"github.com/rs/zerolog/log"
 | 
				
			||||||
)
 | 
					)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
type VehiclesByLicencePlate []fleetsstorage.Vehicle
 | 
					type VehiclesByLicencePlate []fleetsstorage.Vehicle
 | 
				
			||||||
| 
						 | 
					@ -21,3 +27,47 @@ func (a BookingsByStartdate) Less(i, j int) bool {
 | 
				
			||||||
	return a[i].Startdate.Before(a[j].Startdate)
 | 
						return a[i].Startdate.Before(a[j].Startdate)
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
func (a BookingsByStartdate) Swap(i, j int) { a[i], a[j] = a[j], a[i] }
 | 
					func (a BookingsByStartdate) Swap(i, j int) { a[i], a[j] = a[j], a[i] }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					// Functions
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					func VehiclesByDistanceFrom(from geojson.Feature) func(vehicle1, vehicle2 storage.Vehicle) int {
 | 
				
			||||||
 | 
						return func(vehicle1, vehicle2 storage.Vehicle) int {
 | 
				
			||||||
 | 
							vehicle1Address, ok := vehicle1.Data["address"]
 | 
				
			||||||
 | 
							if !ok {
 | 
				
			||||||
 | 
								return 1
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
							vehicle1Json, err := json.Marshal(vehicle1Address)
 | 
				
			||||||
 | 
							if err != nil {
 | 
				
			||||||
 | 
								log.Error().Err(err).Msg("failed marshalling vehicle 1 json")
 | 
				
			||||||
 | 
								return 1
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							vehicle1Geojson, err := geojson.UnmarshalFeature(vehicle1Json)
 | 
				
			||||||
 | 
							if err != nil {
 | 
				
			||||||
 | 
								log.Error().Err(err).Msg("failed unmarshalling vehicle 1 geojson")
 | 
				
			||||||
 | 
								return 1
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							vehicle2Address, ok := vehicle2.Data["address"]
 | 
				
			||||||
 | 
							if !ok {
 | 
				
			||||||
 | 
								log.Debug().Msg("Vehicle 2 does not have an address")
 | 
				
			||||||
 | 
								return -1
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
							vehicle2Json, err := json.Marshal(vehicle2Address)
 | 
				
			||||||
 | 
							if err != nil {
 | 
				
			||||||
 | 
								log.Error().Err(err).Msg("failed marshalling vehicle 2 json")
 | 
				
			||||||
 | 
								return -1
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							vehicle2Geojson, err := geojson.UnmarshalFeature(vehicle2Json)
 | 
				
			||||||
 | 
							if err != nil {
 | 
				
			||||||
 | 
								log.Error().Err(err).Msg("failed unmarshalling vehicle 2 geojson")
 | 
				
			||||||
 | 
								return -1
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							distance1 := geo.Distance(from.Point(), vehicle1Geojson.Point())
 | 
				
			||||||
 | 
							distance2 := geo.Distance(from.Point(), vehicle2Geojson.Point())
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							return cmp.Compare(distance1, distance2)
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -1,13 +0,0 @@
 | 
				
			||||||
package sorting
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
import (
 | 
					 | 
				
			||||||
	mobilityaccountsstorage "git.coopgo.io/coopgo-platform/mobility-accounts/storage"
 | 
					 | 
				
			||||||
)
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
type SolidarityDriversByName []mobilityaccountsstorage.Account
 | 
					 | 
				
			||||||
 | 
					 | 
				
			||||||
func (e SolidarityDriversByName) Len() int { return len(e) }
 | 
					 | 
				
			||||||
func (e SolidarityDriversByName) Less(i, j int) bool {
 | 
					 | 
				
			||||||
	return e[i].Data["first_name"].(string) < e[j].Data["first_name"].(string)
 | 
					 | 
				
			||||||
}
 | 
					 | 
				
			||||||
func (e SolidarityDriversByName) Swap(i, j int) { e[i], e[j] = e[j], e[i] }
 | 
					 | 
				
			||||||
| 
						 | 
					@ -0,0 +1,32 @@
 | 
				
			||||||
 | 
					package sorting
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					import (
 | 
				
			||||||
 | 
						"strings"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						mobilityaccountsstorage "git.coopgo.io/coopgo-platform/mobility-accounts/storage"
 | 
				
			||||||
 | 
						"git.coopgo.io/coopgo-platform/solidarity-transport/servers/grpc/proto/gen"
 | 
				
			||||||
 | 
					)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					type SolidarityDriversByName []mobilityaccountsstorage.Account
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					func (e SolidarityDriversByName) Len() int { return len(e) }
 | 
				
			||||||
 | 
					func (e SolidarityDriversByName) Less(i, j int) bool {
 | 
				
			||||||
 | 
						return e[i].Data["first_name"].(string) < e[j].Data["first_name"].(string)
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					func (e SolidarityDriversByName) Swap(i, j int) { e[i], e[j] = e[j], e[i] }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					type SolidarityAvailabilitiesByDay []*gen.DriverRegularAvailability
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					func (e SolidarityAvailabilitiesByDay) Len() int { return len(e) }
 | 
				
			||||||
 | 
					func (e SolidarityAvailabilitiesByDay) Less(i, j int) bool {
 | 
				
			||||||
 | 
						if e[i].Day == e[j].Day {
 | 
				
			||||||
 | 
							return strings.Compare(e[i].StartTime, e[j].StartTime) < 0
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						if e[i].Day == 0 {
 | 
				
			||||||
 | 
							return false
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						return e[i].Day < e[j].Day
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					func (e SolidarityAvailabilitiesByDay) Swap(i, j int) { e[i], e[j] = e[j], e[i] }
 | 
				
			||||||
| 
						 | 
					@ -8,10 +8,12 @@ import (
 | 
				
			||||||
)
 | 
					)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
const (
 | 
					const (
 | 
				
			||||||
	PREFIX_BENEFICIARIES = "beneficiaries"
 | 
						PREFIX_BENEFICIARIES                = "beneficiaries"
 | 
				
			||||||
	PREFIX_BOOKINGS      = "fleets_bookings"
 | 
						PREFIX_SOLIDARITY_TRANSPORT_DRIVERS = "solidarity_transport/drivers"
 | 
				
			||||||
	PREFIX_AGENDA		 = "event_files"
 | 
						PREFIX_ORGANIZED_CARPOOL_DRIVERS    = "organized_carpool/drivers"
 | 
				
			||||||
	PREFIX_DIAGS		 = "diags"
 | 
						PREFIX_BOOKINGS                     = "fleets_bookings"
 | 
				
			||||||
 | 
						PREFIX_AGENDA                       = "event_files"
 | 
				
			||||||
 | 
						PREFIX_DIAGS                        = "diags"
 | 
				
			||||||
)
 | 
					)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
type FileInfo struct {
 | 
					type FileInfo struct {
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -0,0 +1,102 @@
 | 
				
			||||||
 | 
					package validatedprofile
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					import (
 | 
				
			||||||
 | 
						"cmp"
 | 
				
			||||||
 | 
						"slices"
 | 
				
			||||||
 | 
						"time"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
						"git.coopgo.io/coopgo-apps/parcoursmob/utils/storage"
 | 
				
			||||||
 | 
						mobilityaccountsstorage "git.coopgo.io/coopgo-platform/mobility-accounts/storage"
 | 
				
			||||||
 | 
						"github.com/go-viper/mapstructure/v2"
 | 
				
			||||||
 | 
						"github.com/rs/zerolog/log"
 | 
				
			||||||
 | 
						"github.com/spf13/viper"
 | 
				
			||||||
 | 
						"github.com/stretchr/objx"
 | 
				
			||||||
 | 
					)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					type Comparison struct {
 | 
				
			||||||
 | 
						Field string
 | 
				
			||||||
 | 
						Type  string
 | 
				
			||||||
 | 
						Value any
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					func ValidateProfile(cfg *viper.Viper) func(mobilityaccountsstorage.Account, []storage.FileInfo) bool {
 | 
				
			||||||
 | 
						enabled := cfg.GetBool("enabled")
 | 
				
			||||||
 | 
						requiredDocuments := cfg.GetStringSlice("required.documents")
 | 
				
			||||||
 | 
						requiredFields := cfg.GetStringSlice("required.fields")
 | 
				
			||||||
 | 
						comp := cfg.Get("assert.compare")
 | 
				
			||||||
 | 
						var comparisons []Comparison
 | 
				
			||||||
 | 
						err := mapstructure.Decode(comp, &comparisons)
 | 
				
			||||||
 | 
						if err != nil {
 | 
				
			||||||
 | 
							log.Error().Err(err).Msg("reading comparisons issue")
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
						return func(account mobilityaccountsstorage.Account, docs []storage.FileInfo) bool {
 | 
				
			||||||
 | 
							if !enabled {
 | 
				
			||||||
 | 
								return true
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							for _, d := range requiredDocuments {
 | 
				
			||||||
 | 
								if !slices.ContainsFunc(docs, func(f storage.FileInfo) bool {
 | 
				
			||||||
 | 
									log.Debug().Str("required", d).Str("checked", f.Metadata["Type"]).Msg("file check")
 | 
				
			||||||
 | 
									return f.Metadata["Type"] == d
 | 
				
			||||||
 | 
								}) {
 | 
				
			||||||
 | 
									log.Debug().Msg("file missing")
 | 
				
			||||||
 | 
									return false
 | 
				
			||||||
 | 
								}
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							obj := objx.Map(account.Data)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							for _, f := range requiredFields {
 | 
				
			||||||
 | 
								if obj.Get(f) == nil {
 | 
				
			||||||
 | 
									log.Debug().Msg("field missing")
 | 
				
			||||||
 | 
									return false
 | 
				
			||||||
 | 
								}
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							for _, c := range comparisons {
 | 
				
			||||||
 | 
								val := obj.Get(c.Field)
 | 
				
			||||||
 | 
								if val == nil {
 | 
				
			||||||
 | 
									return false
 | 
				
			||||||
 | 
								}
 | 
				
			||||||
 | 
								value := ""
 | 
				
			||||||
 | 
								if v, ok := c.Value.(string); ok {
 | 
				
			||||||
 | 
									value = v
 | 
				
			||||||
 | 
								} else if v, ok := c.Value.(time.Time); ok {
 | 
				
			||||||
 | 
									value = v.Format("2006-01-02")
 | 
				
			||||||
 | 
								} else {
 | 
				
			||||||
 | 
									log.Error().Msg("could not get type")
 | 
				
			||||||
 | 
									return false
 | 
				
			||||||
 | 
								}
 | 
				
			||||||
 | 
								result := cmp.Compare(val.String(), value)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
								if c.Type == "gte" {
 | 
				
			||||||
 | 
									if result < 0 {
 | 
				
			||||||
 | 
										log.Debug().Int("comparison result", result).Str("operand", c.Type).Msg("comparison issue")
 | 
				
			||||||
 | 
										return false
 | 
				
			||||||
 | 
									}
 | 
				
			||||||
 | 
								} else if c.Type == "gt" {
 | 
				
			||||||
 | 
									if result <= 0 {
 | 
				
			||||||
 | 
										log.Debug().Int("comparison result", result).Str("operand", c.Type).Msg("comparison issue")
 | 
				
			||||||
 | 
										return false
 | 
				
			||||||
 | 
									}
 | 
				
			||||||
 | 
								} else if c.Type == "lt" {
 | 
				
			||||||
 | 
									if result >= 0 {
 | 
				
			||||||
 | 
										log.Debug().Int("comparison result", result).Str("operand", c.Type).Msg("comparison issue")
 | 
				
			||||||
 | 
										return false
 | 
				
			||||||
 | 
									}
 | 
				
			||||||
 | 
								} else if c.Type == "lte" {
 | 
				
			||||||
 | 
									if result < 0 {
 | 
				
			||||||
 | 
										log.Debug().Int("comparison result", result).Str("operand", c.Type).Msg("comparison issue")
 | 
				
			||||||
 | 
										return false
 | 
				
			||||||
 | 
									}
 | 
				
			||||||
 | 
								} else if c.Type == "eq" {
 | 
				
			||||||
 | 
									if result != 0 {
 | 
				
			||||||
 | 
										log.Debug().Int("comparison result", result).Str("operand", c.Type).Msg("comparison issue")
 | 
				
			||||||
 | 
										return false
 | 
				
			||||||
 | 
									}
 | 
				
			||||||
 | 
								}
 | 
				
			||||||
 | 
							}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
							return true
 | 
				
			||||||
 | 
						}
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
		Loading…
	
		Reference in New Issue