From 20a3b6ed3b885c0183ea086fe306237914c301ea Mon Sep 17 00:00:00 2001 From: Arnaud Delcasse Date: Thu, 25 Sep 2025 16:36:35 +0200 Subject: [PATCH] Add history of operatons to wallets --- config.go | 23 ++ go.mod | 34 +- go.sum | 101 +++--- handlers/application/beneficiaries.go | 6 +- handlers/application/journeys.go | 43 ++- handlers/application/organized-carpool.go | 295 ++++++++++++++++-- .../application/solidarity-transport-ext.go | 7 +- handlers/application/solidarity-transport.go | 38 ++- handlers/application/wallets.go | 123 +++++++- main.go | 4 + renderer/beneficiaries.go | 3 +- renderer/func-maps.go | 19 +- renderer/organized-carpool.go | 15 + renderer/solidarity-transport.go | 52 +-- services/services.go | 12 +- 15 files changed, 612 insertions(+), 163 deletions(-) diff --git a/config.go b/config.go index 5585147..5b928ed 100755 --- a/config.go +++ b/config.go @@ -126,6 +126,29 @@ func ReadConfig() (*viper.Viper, error) { "documents": []string{}, }, }, + "profile_optional_fields": []map[string]any{ + { + "name": "gender", + "label": "Genre", + "type": "select", + "options": []map[string]string{ + {"value": "0", "label": "Inconnu"}, + {"value": "1", "label": "Masculin"}, + {"value": "2", "label": "Féminin"}, + {"value": "9", "label": "Sans objet"}, + }, + }, + { + "name": "last_subscription_date", + "label": "Date de dernière adhésion", + "type": "date", + }, + { + "name": "comment", + "label": "Commentaire", + "type": "textarea", + }, + }, }, }, "organized_carpool": map[string]any{ diff --git a/go.mod b/go.mod index 2eae516..938c520 100755 --- a/go.mod +++ b/go.mod @@ -37,25 +37,27 @@ require ( gitlab.scity.coop/maas/navitia-golang v0.0.0-20220429110621-5c22d6efdd0c go.etcd.io/etcd/client/v3 v3.5.12 golang.org/x/image v0.5.0 - golang.org/x/oauth2 v0.25.0 - google.golang.org/grpc v1.71.1 + golang.org/x/oauth2 v0.30.0 + google.golang.org/grpc v1.75.1 google.golang.org/protobuf v1.36.6 ) require ( 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/carpool-service v0.0.0-20250925043614-b7ac71741f43 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/geography v0.0.0-20250616160304-0285c9494673 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/multimodal-routing v0.0.0-20250504230045-8680f560066a + git.coopgo.io/coopgo-platform/multimodal-routing v0.0.0-20250925053957-63fc3e7c834f 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-20250910141021-fc5b33e88c2c github.com/arran4/golang-ical v0.3.1 github.com/coreos/go-oidc/v3 v3.11.0 + github.com/go-viper/mapstructure/v2 v2.2.1 github.com/gorilla/securecookie v1.1.1 github.com/minio/minio-go/v7 v7.0.43 github.com/paulmach/orb v0.11.1 @@ -66,7 +68,6 @@ require ( require ( git.coopgo.io/coopgo-platform/carpool-service/interoperability/ocss v0.0.0-20250429082239-a95cd6eb5523 // 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 @@ -91,9 +92,7 @@ require ( 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 @@ -103,9 +102,8 @@ require ( 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 + golang.org/x/mod v0.25.0 // indirect + golang.org/x/tools v0.33.0 // indirect ) require ( @@ -116,7 +114,7 @@ require ( github.com/coreos/go-systemd/v22 v22.5.0 // indirect github.com/dustin/go-humanize v1.0.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.1.1 // indirect github.com/go-openapi/inflect v0.21.2 // indirect github.com/go-playground/locales v0.14.1 // indirect github.com/go-playground/universal-translator v0.18.1 // indirect @@ -166,13 +164,13 @@ require ( go.uber.org/atomic v1.11.0 // indirect go.uber.org/multierr v1.11.0 // indirect go.uber.org/zap v1.21.0 // indirect - golang.org/x/crypto v0.37.0 // indirect - golang.org/x/net v0.39.0 // indirect - golang.org/x/sync v0.13.0 // indirect - golang.org/x/sys v0.32.0 // indirect - golang.org/x/text v0.24.0 // indirect - google.golang.org/genproto/googleapis/api v0.0.0-20250106144421-5f5ef82da422 // indirect - google.golang.org/genproto/googleapis/rpc v0.0.0-20250414145226-207652e42e2e // indirect + golang.org/x/crypto v0.39.0 // indirect + golang.org/x/net v0.41.0 // indirect + golang.org/x/sync v0.15.0 // indirect + golang.org/x/sys v0.33.0 // indirect + golang.org/x/text v0.26.0 // indirect + google.golang.org/genproto/googleapis/api v0.0.0-20250707201910-8d1bb00bc6a7 // indirect + google.golang.org/genproto/googleapis/rpc v0.0.0-20250707201910-8d1bb00bc6a7 // indirect gopkg.in/ini.v1 v1.67.0 // indirect gopkg.in/mgo.v2 v2.0.0-20190816093944-a6b53ec6cb22 // indirect gopkg.in/yaml.v3 v3.0.1 // indirect diff --git a/go.sum b/go.sum index 63b6bc2..b318d5e 100644 --- a/go.sum +++ b/go.sum @@ -4,6 +4,8 @@ git.coopgo.io/coopgo-platform/agenda v1.0.0 h1:rTHgva1JKKO0wAPlINegifMkHm+xOg3IW 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 v0.0.0-20250925043614-b7ac71741f43 h1:6gFe8+7tiAiUie7qCl4UaLv5QyUUtJvt23ju1Wa6Xg0= +git.coopgo.io/coopgo-platform/carpool-service v0.0.0-20250925043614-b7ac71741f43/go.mod h1:J0vTvTd+NJ3dKcJ28Ca2xV7OMuglpJ9i4KPRb2SJqew= 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= @@ -12,8 +14,6 @@ git.coopgo.io/coopgo-platform/emailing v0.0.0-20250212064257-167ef5864260 h1:Li3 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/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= @@ -22,26 +22,14 @@ git.coopgo.io/coopgo-platform/mobility-accounts v0.0.0-20230329105908-a76c0412a3 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/multimodal-routing v0.0.0-20250925053957-63fc3e7c834f h1:uePG+xhXdFiOhSyoNjJ3ZElwe/cWRm/++6iUHseY3Q8= +git.coopgo.io/coopgo-platform/multimodal-routing v0.0.0-20250925053957-63fc3e7c834f/go.mod h1:zDMfGVIvzuWV4Cw4bSi2kuEyMDbAfNfs7cGOAWNKfOo= 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= git.coopgo.io/coopgo-platform/solidarity-transport v0.0.0-20250910141021-fc5b33e88c2c h1:U7EgF5Asj6a65nNXo6m4luR27CL5nDfxhY6GFWX46uU= git.coopgo.io/coopgo-platform/solidarity-transport v0.0.0-20250910141021-fc5b33e88c2c/go.mod h1:jnSYIECcH/nL8bLBwYD2WmJSPgWUC2rioOXxivWBTBM= github.com/Azure/go-ansiterm v0.0.0-20170929234023-d6e3b3328b78/go.mod h1:LmzpDX56iTiv29bbRTIsUNlaFfuhWRQBWjQdVyAevI8= @@ -54,7 +42,6 @@ github.com/Masterminds/sprig v2.22.0+incompatible/go.mod h1:y6hNFY5UBTIWBxnzTeuN 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/RaveNoX/go-jsoncommentstrip v1.0.0/go.mod h1:78ihd09MekBnJnxpICcwzCMzGrKSKYe4AqU6PDYYpjk= -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= @@ -141,10 +128,10 @@ github.com/fsnotify/fsnotify v1.9.0 h1:2Ml+OJNzbYCTzsxtv8vKSFD9PbJjmhYF14k/jKC7S 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/go.mod h1:WVf9LFMHh/QVrmqrOfqun0C45tMe3RoiKJMPvgWwLfY= -github.com/go-logr/logr v1.4.2 h1:6pFjapn8bFcIbiKo3XT4j/BhANplGihG6tvd+8rYgrY= -github.com/go-logr/logr v1.4.2/go.mod h1:9T104GzyrTigFIr8wt5mBrctHMim0Nb2HLGrmQ40KvY= +github.com/go-jose/go-jose/v4 v4.1.1 h1:JYhSgy4mXXzAdF3nUx3ygx347LRXJRrpgyU3adRmkAI= +github.com/go-jose/go-jose/v4 v4.1.1/go.mod h1:BdsZGqgdO3b6tTc6LSE56wcDbMMLuPsw5d4ZD5f94kA= +github.com/go-logr/logr v1.4.3 h1:CjnDlHq8ikf6E492q6eKboGOC0T8CDaOvkHCIg8idEI= +github.com/go-logr/logr v1.4.3/go.mod h1:9T104GzyrTigFIr8wt5mBrctHMim0Nb2HLGrmQ40KvY= github.com/go-logr/stdr v1.2.2 h1:hSWxHoqTgW2S2qGc0LTAI563KZ5YKYRhT3MFKZMbjag= github.com/go-logr/stdr v1.2.2/go.mod h1:mMo/vtBO5dYbehREoey6XUKy/eSumjCCveDpRre4VKE= github.com/go-openapi/inflect v0.21.2 h1:0gClGlGcxifcJR56zwvhaOulnNgnhc4qTAkob5ObnSM= @@ -222,8 +209,6 @@ github.com/leodido/go-urn v1.2.4/go.mod h1:7ZrI8mTSeBSHl/UaRyKQW1qZeMgak41ANeCNa 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/go.mod h1:AlVN5x4E4T544tWzH6hKfbfQvm3HdbOxrmggDNAPY9o= -github.com/manterfield/go-mapreader v0.2.0 h1:ZDJbja6bZCatRG725SDchdudqYnULyk04wSH58gvyqM= -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.13/go.mod h1:7S9/ev0klgBDR4GtXTXX8a3vIGJpMovkB8vQcUbaXHg= github.com/mattn/go-colorable v0.1.14 h1:9A9LHSqF/7dyVVX6g0U9cwm9pG3kP9gSzcuIPHPsaIE= @@ -327,9 +312,11 @@ github.com/stretchr/testify v1.10.0 h1:Xv5erBjTwe/5IxqUQTdXv5kgmIvbHo3QQyRwhJsOf 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/go.mod h1:Dk4QP5c2W3ibzajGcXpNraDfq2IrhjMIvMSWPKKo0FU= +github.com/tidwall/cities v0.1.0 h1:CVNkmMf7NEC9Bvokf5GoSsArHCKRMTgLuubRTHnH0mE= 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 h1:dNVBH5MErdaQ/xd9s769R31/n2dXavsQ0Yf4TMEHHw8= 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= @@ -381,20 +368,18 @@ go.etcd.io/etcd/client/v3 v3.5.12/go.mod h1:tSbBCakoWmmddL+BKVAJHa9km+O/E+bumDe9 go.mongodb.org/mongo-driver v1.11.4/go.mod h1:PTSz5yu21bkT/wXpkS7WR5f0ddqw5quethTUn9WM+2g= 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.opentelemetry.io/otel v1.37.0 h1:9zhNfelUvx0KBfu/gb+ZgeAfAgtWrfHJZcAqFC228wQ= +go.opentelemetry.io/otel v1.37.0/go.mod h1:ehE/umFRLnuLa/vSccNq9oS1ErUlkkK71gMcN34UG8I= +go.opentelemetry.io/otel/metric v1.37.0 h1:mvwbQS5m0tbmqML4NqK+e3aDiO02vsf/WgbsdpcPoZE= +go.opentelemetry.io/otel/metric v1.37.0/go.mod h1:04wGrZurHYKOc+RKeye86GwKiTb9FKm1WHtO+4EVr2E= +go.opentelemetry.io/otel/sdk v1.37.0 h1:ItB0QUqnjesGRvNcmAcU0LyvkVyGJ2xftD29bWdDvKI= +go.opentelemetry.io/otel/sdk v1.37.0/go.mod h1:VredYzxUvuo2q3WRcDnKDjbdvmO0sCzOvVAiY+yUkAg= +go.opentelemetry.io/otel/sdk/metric v1.37.0 h1:90lI228XrB9jCMuSdA0673aubgRobVZFhbjxHHspCPc= +go.opentelemetry.io/otel/sdk/metric v1.37.0/go.mod h1:cNen4ZWfiD37l5NhS+Keb5RXVWZWpRE+9WyVCpbo5ps= +go.opentelemetry.io/otel/trace v1.37.0 h1:HLdcFNbRQBE2imdSEgm/kwqmQj1Or1l/7bW6mxVK7z4= +go.opentelemetry.io/otel/trace v1.37.0/go.mod h1:TlgrlQ+PtQO5XFerSPUYG0JSgGyryXewPGyayAWSBS0= 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/go.mod h1:LUxbIzbOniOlMKjJjyPfpl4v+PKK2cNJn91OQbhoJI0= @@ -412,8 +397,8 @@ golang.org/x/crypto v0.0.0-20200622213623-75b288015ac9/go.mod h1:LzIPMQfyMNhhGPh golang.org/x/crypto v0.0.0-20210921155107-089bfa567519/go.mod h1:GvvjBRRGRdwPK5ydBHafDWAxML/pGHZbMvKqRZ5+Abc= 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.37.0 h1:kJNSjF/Xp7kU0iB2Z+9viTPMW4EqqsrywMXLJOOsXSE= -golang.org/x/crypto v0.37.0/go.mod h1:vg+k43peMZ0pUMhYmVAWysMK35e6ioLh3wB8ZCAfbVc= +golang.org/x/crypto v0.39.0 h1:SHs+kF4LP+f+p14esP5jAoDpHU8Gu/v9lFRK6IT5imM= +golang.org/x/crypto v0.39.0/go.mod h1:L+Xg3Wf6HoL4Bn4238Z6ft6KfEpN0tJGo53AAPC632U= 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/lint v0.0.0-20190930215403-16217165b5de/go.mod h1:6SW0HCj/g11FgYtHlgUYUwCkIfeOF89ocIRzGO/8vkc= @@ -422,8 +407,8 @@ 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.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.24.0 h1:ZfthKaKaT4NrhGVZHO1/WDTwGES4De8KtWO0SIbNJMU= -golang.org/x/mod v0.24.0/go.mod h1:IXM97Txy2VM4PJ3gI61r1YEk/gAj6zAHN3AdZt6S9Ww= +golang.org/x/mod v0.25.0 h1:n7a+ZbQKQA/Ysbyb0/6IbB1H/X41mKgbhfv7AfG/44w= +golang.org/x/mod v0.25.0/go.mod h1:IXM97Txy2VM4PJ3gI61r1YEk/gAj6zAHN3AdZt6S9Ww= 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-20190620200207-3b0461eec859/go.mod h1:z5CRVTTTmAJ677TzLLGU+0bjPO0LkuOLi4/5GtJWs/s= @@ -435,18 +420,18 @@ 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.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.39.0 h1:ZCu7HMWDxpXpaiKdhzIfaltL9Lp31x/3fCP11bc6/fY= -golang.org/x/net v0.39.0/go.mod h1:X7NRbYVEA+ewNkCNyJ513WmMdQ3BineSwVtN2zD/d+E= -golang.org/x/oauth2 v0.25.0 h1:CY4y7XT9v0cRI9oupztF8AgiIu99L/ksR/Xp/6jrZ70= -golang.org/x/oauth2 v0.25.0/go.mod h1:XYTD2NtWslqkgxebSiOHnXEap4TF09sJSc7H1sXbhtI= +golang.org/x/net v0.41.0 h1:vBTly1HeNPEn3wtREYfy4GZ/NECgw2Cnl+nK6Nz3uvw= +golang.org/x/net v0.41.0/go.mod h1:B/K4NNqkfmg07DQYrbwvSluqCJOOXwUjeb/5lOisjbA= +golang.org/x/oauth2 v0.30.0 h1:dnDm7JmhM45NNpd8FDDeLhK6FwqbOf4MLCM9zb1BOHI= +golang.org/x/oauth2 v0.30.0/go.mod h1:B++QgG3ZKulg6sRPGD/mqlHQs5rB3Ml9erfeDY7xKlU= 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-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-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.13.0 h1:AauUjRAJ9OSnvULf/ARrrVywoJDy0YS2AwQ98I37610= -golang.org/x/sync v0.13.0/go.mod h1:1dzgHSNfp02xaA81J2MS99Qcpr2w7fw1gpm99rleRqA= +golang.org/x/sync v0.15.0 h1:KWH3jNZsfyT6xfAfKiz6MRNmd46ByHDYaZ7KSkCtdW8= +golang.org/x/sync v0.15.0/go.mod h1:1dzgHSNfp02xaA81J2MS99Qcpr2w7fw1gpm99rleRqA= 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-20190222072716-a9d3bda3a223/go.mod h1:STP8DvDyc/dI5b8T5hshtkjS+E42TnysNCUPdjciGhY= @@ -467,8 +452,8 @@ 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.7.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.12.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= -golang.org/x/sys v0.32.0 h1:s77OFDvIQeibCmezSnk/q6iAfkdiQaJi4VzroCFrN20= -golang.org/x/sys v0.32.0/go.mod h1:BJP2sWEmIv4KK5OTEluFJCKSidICx8ciO85XgH3Ak8k= +golang.org/x/sys v0.33.0 h1:q3i8TbbEz+JRD9ywIRlyRAQbM0qF7hu24q3teo2hbuw= +golang.org/x/sys v0.33.0/go.mod h1:BJP2sWEmIv4KK5OTEluFJCKSidICx8ciO85XgH3Ak8k= 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.5.0/go.mod h1:jMB1sMXY+tzblOD4FWmEbocvup2/aLOaQEp7JmGp78k= @@ -481,8 +466,8 @@ 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.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.24.0 h1:dd5Bzh4yt5KYA8f9CJHCP4FB4D51c2c6JvN37xJJkJ0= -golang.org/x/text v0.24.0/go.mod h1:L8rBsPeo2pSS+xqN0d5u2ikmjtmoJbDBT1b7nHvFCdU= +golang.org/x/text v0.26.0 h1:P42AVeLghgTYr4+xUnTRKDMqpar+PtX7KWuNQL21L8M= +golang.org/x/text v0.26.0/go.mod h1:QK15LZJUUQVJxhz7wXgxSy/CJaTFjd0G+YLonydOVQA= 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-20191119224855-298f0cb1881e/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= @@ -491,18 +476,20 @@ 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.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.32.0 h1:Q7N1vhpkQv7ybVzLFtTjvQya2ewbwNDZzUgfXGqtMWU= -golang.org/x/tools v0.32.0/go.mod h1:ZxrU41P/wAbZD8EDa6dDCa6XfpkhJ7HFMjHJXfBDu8s= +golang.org/x/tools v0.33.0 h1:4qz2S3zmRxbGIhDIAgjxvFutSvH5EfnsYrRBj0UI0bc= +golang.org/x/tools v0.33.0/go.mod h1:CIJMaWEY88juyUfo7UbgPqbC8rU2OqfAV1h2Qp0oMYI= 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-20191204190536-9bdfabe68543/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= golang.org/x/xerrors v0.0.0-20200804184101-5ec99f83aff1/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= -google.golang.org/genproto/googleapis/api v0.0.0-20250106144421-5f5ef82da422 h1:GVIKPyP/kLIyVOgOnTwFOrvQaQUzOzGMCxgFUOEmm24= -google.golang.org/genproto/googleapis/api v0.0.0-20250106144421-5f5ef82da422/go.mod h1:b6h1vNKhxaSoEI+5jc3PJUCustfli/mRab7295pY7rw= -google.golang.org/genproto/googleapis/rpc v0.0.0-20250414145226-207652e42e2e h1:ztQaXfzEXTmCBvbtWYRhJxW+0iJcz2qXfd38/e9l7bA= -google.golang.org/genproto/googleapis/rpc v0.0.0-20250414145226-207652e42e2e/go.mod h1:qQ0YXyHHx3XkvlzUtpXDkS29lDSafHMZBAZDc03LQ3A= -google.golang.org/grpc v1.71.1 h1:ffsFWr7ygTUscGPI0KKK6TLrGz0476KUvvsbqWK0rPI= -google.golang.org/grpc v1.71.1/go.mod h1:H0GRtasmQOh9LkFoCPDu3ZrwUtD1YGE+b2vYBYd/8Ec= +gonum.org/v1/gonum v0.16.0 h1:5+ul4Swaf3ESvrOnidPp4GZbzf0mxVQpDCYUQE7OJfk= +gonum.org/v1/gonum v0.16.0/go.mod h1:fef3am4MQ93R2HHpKnLk4/Tbh/s0+wqD5nfa6Pnwy4E= +google.golang.org/genproto/googleapis/api v0.0.0-20250707201910-8d1bb00bc6a7 h1:FiusG7LWj+4byqhbvmB+Q93B/mOxJLN2DTozDuZm4EU= +google.golang.org/genproto/googleapis/api v0.0.0-20250707201910-8d1bb00bc6a7/go.mod h1:kXqgZtrWaf6qS3jZOCnCH7WYfrvFjkC51bM8fz3RsCA= +google.golang.org/genproto/googleapis/rpc v0.0.0-20250707201910-8d1bb00bc6a7 h1:pFyd6EwwL2TqFf8emdthzeX+gZE1ElRq3iM8pui4KBY= +google.golang.org/genproto/googleapis/rpc v0.0.0-20250707201910-8d1bb00bc6a7/go.mod h1:qQ0YXyHHx3XkvlzUtpXDkS29lDSafHMZBAZDc03LQ3A= +google.golang.org/grpc v1.75.1 h1:/ODCNEuf9VghjgO3rqLcfg8fiOP0nSluljWFlDxELLI= +google.golang.org/grpc v1.75.1/go.mod h1:JtPAzKiq4v1xcAB2hydNlWI2RnF85XXcV0mhKXr2ecQ= google.golang.org/protobuf v1.26.0-rc.1/go.mod h1:jlhhOSvTdKEhbULTjvd4ARK9grFBp09yW+WbY/TyQbw= google.golang.org/protobuf v1.27.1/go.mod h1:9q0QmTI4eRPtz6boOQmLYwt+qCgq0jsYwAQnmE0givc= google.golang.org/protobuf v1.36.6 h1:z1NpPI8ku2WgiWnf+t9wTPsn6eP1L7ksHUlkfLvd9xY= diff --git a/handlers/application/beneficiaries.go b/handlers/application/beneficiaries.go index 5fdeab5..7d2d59c 100755 --- a/handlers/application/beneficiaries.go +++ b/handlers/application/beneficiaries.go @@ -382,7 +382,11 @@ func (h *ApplicationHandler) BeneficiaryDisplay(w http.ResponseWriter, r *http.R for i, d := range diag { diagsAny[i] = d } - h.Renderer.BeneficiaryDisplay(w, r, resp.Account.ToStorageType(), bookings, organizations, beneficiaries_file_types, file_types_map, documents, events_list, diagsAny, solidarityTransportStats) + + account := resp.Account.ToStorageType() + walletBalance := h.calculateWalletBalance(account) + + h.Renderer.BeneficiaryDisplay(w, r, account, bookings, organizations, beneficiaries_file_types, file_types_map, documents, events_list, diagsAny, solidarityTransportStats, walletBalance) } func (h *ApplicationHandler) BeneficiaryUpdate(w http.ResponseWriter, r *http.Request) { diff --git a/handlers/application/journeys.go b/handlers/application/journeys.go index d312ec4..ba981c7 100755 --- a/handlers/application/journeys.go +++ b/handlers/application/journeys.go @@ -20,7 +20,7 @@ import ( groupstorage "git.coopgo.io/coopgo-platform/groups-management/storage" mobilityaccounts "git.coopgo.io/coopgo-platform/mobility-accounts/grpcapi" mobilityaccountsstorage "git.coopgo.io/coopgo-platform/mobility-accounts/storage" - "git.coopgo.io/coopgo-platform/multimodal-routing/libs/transit/motis" + "git.coopgo.io/coopgo-platform/multimodal-routing/libs/transit/transitous" "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" @@ -42,7 +42,7 @@ var ( func (h *ApplicationHandler) JourneysSearch(w http.ResponseWriter, r *http.Request) { r.ParseForm() var ( - transit_results []*motis.Itinerary + transit_results []*transitous.Itinerary carpool_results []*geojson.FeatureCollection vehicle_results []fleetsstorage.Vehicle ) @@ -158,13 +158,28 @@ func (h *ApplicationHandler) JourneysSearch(w http.ResponseWriter, r *http.Reque }) } + // Get departure and destination addresses from properties + var departureAddress, destinationAddress string + if departuregeo.Properties != nil { + if label, ok := departuregeo.Properties["label"].(string); ok { + departureAddress = label + } + } + if destinationgeo.Properties != nil { + if label, ok := destinationgeo.Properties["label"].(string); ok { + destinationAddress = label + } + } + // 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), + DepartureLat: departuregeo.Point().Lat(), + DepartureLng: departuregeo.Point().Lon(), + ArrivalLat: destinationgeo.Point().Lat(), + ArrivalLng: destinationgeo.Point().Lon(), + DepartureDate: timestamppb.New(departuredatetime), + DepartureAddress: &departureAddress, + ArrivalAddress: &destinationAddress, }) if err != nil { log.Error().Err(err).Msg("error retrieving organized carpools") @@ -188,23 +203,19 @@ func (h *ApplicationHandler) JourneysSearch(w http.ResponseWriter, r *http.Reque }() // TRANSIT - transitch := make(chan *motis.Itinerary) - go func(transitch chan *motis.Itinerary, departure *geojson.Feature, destination *geojson.Feature, datetime *time.Time) { + transitch := make(chan *transitous.Itinerary) + go func(transitch chan *transitous.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{ + response, err := h.services.TransitRouting.PlanWithResponse(context.Background(), &transitous.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 { - log.Error().Err(err).Msg("error retrieving transit data from MOTIS server") + log.Error().Err(err).Msg("error retrieving transit data from Transitous server") return } - for _, i := range response.JSON200.Itineraries { + for _, i := range response.Itineraries { transitch <- &i } }(transitch, departuregeo, destinationgeo, &departuredatetime) diff --git a/handlers/application/organized-carpool.go b/handlers/application/organized-carpool.go index 5abd226..f38ef46 100644 --- a/handlers/application/organized-carpool.go +++ b/handlers/application/organized-carpool.go @@ -67,7 +67,6 @@ func (h *ApplicationHandler) OrganizedCarpoolOverview(w http.ResponseWriter, r * if err == nil { for _, b := range bookingsproto.Bookings { - // booking, _ := transformers.BookingProtoToType(b) bookings = append(bookings, b) } } @@ -85,6 +84,101 @@ func (h *ApplicationHandler) OrganizedCarpoolOverview(w http.ResponseWriter, r * h.Renderer.OrganizedCarpoolOverview(w, r, accounts, accountsMap, beneficiariesMap, bookings) } +func (h *ApplicationHandler) OrganizedCarpoolBookingDisplay(w http.ResponseWriter, r *http.Request) { + vars := mux.Vars(r) + bookingId := vars["bookingid"] + + resp, err := h.services.GRPC.CarpoolService.GetBooking(context.Background(), &proto.GetCarpoolBookingRequest{ + BookingId: bookingId, + }) + if err != nil { + log.Error().Err(err).Msg("could not get carpool booking") + w.WriteHeader(http.StatusInternalServerError) + return + } + + if resp.Booking == nil { + log.Error().Msg("carpool booking not found") + w.WriteHeader(http.StatusNotFound) + return + } + + driver, err := h.services.GetAccount(resp.Booking.Driver.Id) + if err != nil { + log.Error().Err(err).Msg("driver retrieval issue") + w.WriteHeader(http.StatusInternalServerError) + return + } + + passenger, err := h.services.GetAccount(resp.Booking.Passenger.Id) + if err != nil { + log.Error().Err(err).Msg("passenger retrieval issue") + w.WriteHeader(http.StatusInternalServerError) + return + } + + // Extract driver departure and arrival addresses from DriverRoute GeoJSON + var driverDepartureAddress, driverArrivalAddress string + if resp.Booking.DriverRoute != nil && resp.Booking.DriverRoute.Serialized != "" { + fc, err := geojson.UnmarshalFeatureCollection([]byte(resp.Booking.DriverRoute.Serialized)) + if err != nil { + log.Error().Err(err).Msg("could not unmarshal driver route geojson") + } else { + // Extract departure address (first feature) + if len(fc.Features) > 0 { + if addr, ok := fc.Features[0].Properties["label"]; ok { + if addrStr, ok := addr.(string); ok { + driverDepartureAddress = addrStr + } + } + } + // Extract arrival address (last feature) + if len(fc.Features) > 1 { + if addr, ok := fc.Features[1].Properties["label"]; ok { + if addrStr, ok := addr.(string); ok { + driverArrivalAddress = addrStr + } + } + } + } + } + + h.Renderer.OrganizedCarpoolBookingDisplay(w, r, resp.Booking, driver, passenger, driverDepartureAddress, driverArrivalAddress) +} + +func (h *ApplicationHandler) OrganizedCarpoolBookingStatus(action string) func(w http.ResponseWriter, r *http.Request) { + return func(w http.ResponseWriter, r *http.Request) { + vars := mux.Vars(r) + bookingId := vars["bookingid"] + + var status proto.CarpoolServiceBookingStatus + if action == "confirm" { + status = proto.CarpoolServiceBookingStatus_CONFIRMED + } else if action == "cancel" { + status = proto.CarpoolServiceBookingStatus_CANCELLED + } else if action == "waitconfirmation" { + status = proto.CarpoolServiceBookingStatus_WAITING_DRIVER_CONFIRMATION + } else { + log.Error().Str("action", action).Msg("unknown booking action") + w.WriteHeader(http.StatusBadRequest) + return + } + + _, err := h.services.GRPC.CarpoolService.UpdateBooking(context.Background(), &proto.UpdateCarpoolBookingRequest{ + BookingId: bookingId, + Status: status, + }) + if err != nil { + log.Error().Err(err).Msg("update carpool booking status issue") + w.WriteHeader(http.StatusInternalServerError) + return + } + + // Redirect back to the booking display page + http.Redirect(w, r, fmt.Sprintf("/app/organized-carpool/bookings/%s", bookingId), http.StatusSeeOther) + } +} + func (h *ApplicationHandler) organizedCarpoolDrivers(r *http.Request) ([]mobilityaccountsstorage.Account, error) { accounts := []mobilityaccountsstorage.Account{} @@ -549,48 +643,200 @@ func (h *ApplicationHandler) OrganizedCarpoolJourney(w http.ResponseWriter, r *h var passenger mobilityaccountsstorage.Account passengerId := r.URL.Query().Get("passengerid") - log.Info().Str("journeyid", journeyId).Str("driverid", driverId).Str("passengerid", passengerId).Msg("driver journey") + log.Info().Str("journeyid", journeyId).Str("driverid", driverId).Str("passengerid", passengerId).Msg("organized carpool journey") + // Get the planned trip data 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") + log.Error().Err(err).Msg("could not get carpool 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") + log.Error().Err(err).Msg("could not unmarshal carpool journey") w.WriteHeader(http.StatusNotFound) return } + departureDate := journey.ExtraMembers["departure_date"] + var departureTime *timestamppb.Timestamp + if departureDate != nil { + if dd, ok := departureDate.(string); ok { + dt, _ := time.Parse("2006-01-02 15:04", dd) + departureTime = timestamppb.New(dt) + } + } + + // Extract operator from journey data + var operatorID string + if operator, ok := journey.ExtraMembers["operator"]; ok { + if op, ok := operator.(string); ok { + operatorID = op + } + } + if operatorID == "" { + operatorID = "example.coopgo.fr" // fallback to default + } + + if departureTime == nil { + // Fallback to current time if we can't extract departure time + departureTime = timestamppb.New(time.Now()) + } + if r.Method == "POST" { if passengerId == "" { - log.Error().Err(err).Msg("could not get driver journey") - w.WriteHeader(http.StatusNotFound) + log.Error().Msg("missing passenger ID for carpool booking") + w.WriteHeader(http.StatusBadRequest) 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, - }, + if err := r.ParseForm(); err != nil { + log.Error().Err(err).Msg("could not parse form input") + w.WriteHeader(http.StatusBadRequest) + return + } + + // Extract journey properties from the geojson data + var journeyProps map[string]any + if props, ok := journey.ExtraMembers["properties"]; ok { + if propsMap, ok := props.(map[string]any); ok { + journeyProps = propsMap } - PassengerId: passengerId, - DriverId: driverId, - DriverJourneyId: journeyId, - }); err != nil { - log.Error().Err(err).Msg("cannot create booking") + } + + if journeyProps == nil { + log.Error().Msg("could not extract journey properties") w.WriteHeader(http.StatusInternalServerError) return - }*/ - http.Redirect(w, r, fmt.Sprintf("/app/organized_carpool/"), http.StatusFound) + } + + // Extract departure date from journey ExtraMembers + if depDate, ok := journey.ExtraMembers["departure_date"]; ok { + if depDateStr, ok := depDate.(string); ok { + if parsedTime, err := time.Parse("2006-01-02T15:04:05Z", depDateStr); err == nil { + departureTime = timestamppb.New(parsedTime) + } else if parsedTime, err := time.Parse("2006-01-02", depDateStr); err == nil { + departureTime = timestamppb.New(parsedTime) + } else { + log.Warn().Str("departure_date", depDateStr).Msg("could not parse departure date, using current time") + } + } + } + + // Extract passenger pickup/drop coordinates and addresses from stored passenger data + var pickupLat, pickupLng, dropLat, dropLng float64 + var pickupAddress, dropAddress string + + // Check if we have passenger pickup and drop features in the journey's extra members + if pickupData, ok := journey.ExtraMembers["passenger_pickup"]; ok { + if pickupMap, ok := pickupData.(map[string]interface{}); ok { + if geometry, ok := pickupMap["geometry"].(map[string]interface{}); ok { + if coords, ok := geometry["coordinates"].([]interface{}); ok && len(coords) >= 2 { + if lng, ok := coords[0].(float64); ok { + pickupLng = lng + } + if lat, ok := coords[1].(float64); ok { + pickupLat = lat + } + } + } + if properties, ok := pickupMap["properties"].(map[string]interface{}); ok { + if label, ok := properties["label"].(string); ok { + pickupAddress = label + } + } + } + } + + if dropData, ok := journey.ExtraMembers["passenger_drop"]; ok { + if dropMap, ok := dropData.(map[string]interface{}); ok { + if geometry, ok := dropMap["geometry"].(map[string]interface{}); ok { + if coords, ok := geometry["coordinates"].([]interface{}); ok && len(coords) >= 2 { + if lng, ok := coords[0].(float64); ok { + dropLng = lng + } + if lat, ok := coords[1].(float64); ok { + dropLat = lat + } + } + } + if properties, ok := dropMap["properties"].(map[string]interface{}); ok { + if label, ok := properties["label"].(string); ok { + dropAddress = label + } + } + } + } + + log.Debug().Str("pickup_address", pickupAddress).Str("drop_address", dropAddress).Msg("Extracted addresses") + + // Extract time from schedules if available and no specific departure_date was found + if departureTime.AsTime().Equal(time.Now().Truncate(time.Second)) { + if schedules, ok := journeyProps["schedules"]; ok { + if schedulesList, ok := schedules.([]any); ok && len(schedulesList) > 0 { + if schedule, ok := schedulesList[0].(map[string]any); ok { + if timeOfDay, ok := schedule["time_of_day"].(string); ok { + // Parse time and combine with current date + now := time.Now() + timeStr := fmt.Sprintf("%s %s", now.Format("2006-01-02"), timeOfDay) + if depTime, err := time.Parse("2006-01-02 15:04", timeStr); err == nil { + departureTime = timestamppb.New(depTime) + } + } + } + } + } + } + + motivation := r.PostFormValue("motivation") + + // Create carpool booking using extracted journey data + booking := &proto.CarpoolServiceBooking{ + Id: uuid.NewString(), + Driver: &proto.CarpoolServiceUser{ + Id: driverId, + Operator: operatorID, + }, + Passenger: &proto.CarpoolServiceUser{ + Id: passengerId, + Operator: operatorID, + }, + PassengerPickupDate: departureTime, + PassengerPickupLat: pickupLat, + PassengerPickupLng: pickupLng, + PassengerDropLat: dropLat, + PassengerDropLng: dropLng, + PassengerPickupAddress: &pickupAddress, + PassengerDropAddress: &dropAddress, + Status: proto.CarpoolServiceBookingStatus_WAITING_DRIVER_CONFIRMATION, + DriverJourneyId: journeyId, + } + + bookingRes, err := h.services.GRPC.CarpoolService.CreateBooking(context.Background(), &proto.CreateCarpoolBookingRequest{ + Booking: booking, + }) + if err != nil { + log.Error().Err(err).Msg("cannot create carpool booking") + w.WriteHeader(http.StatusInternalServerError) + return + } + + log.Info().Str("booking_id", bookingRes.Booking.Id).Msg("Carpool booking created successfully") + + // Send SMS notification if requested + message := r.PostFormValue("message") + doNotSend := r.PostFormValue("do_not_send") + if message != "" && doNotSend != "on" { + send_message := strings.ReplaceAll(message, "{booking_id}", bookingRes.Booking.Id) + send_message = strings.ReplaceAll(send_message, "{motivation}", motivation) + log.Debug().Str("message", send_message).Msg("Carpool booking created: sending message") + h.GenerateSMS(driverId, send_message) + } + + http.Redirect(w, r, fmt.Sprintf("/app/organized-carpool/"), http.StatusFound) return } @@ -616,13 +862,6 @@ func (h *ApplicationHandler) OrganizedCarpoolJourney(w http.ResponseWriter, r *h 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) } diff --git a/handlers/application/solidarity-transport-ext.go b/handlers/application/solidarity-transport-ext.go index f45dc72..42e611a 100644 --- a/handlers/application/solidarity-transport-ext.go +++ b/handlers/application/solidarity-transport-ext.go @@ -67,8 +67,13 @@ func (h *ApplicationHandler) SolidarityTransportExternalBookingProposal(w http.R booking.Status = status if status == "VALIDATED" { h.GenerateSMS(passenger.ID, message) + if err := h.creditWallet(driver.ID, booking.Journey.Price.Amount, "Transport solidaire", "Crédit transport solidaire"); err != nil { + log.Error().Err(err).Msg("could not credit driver wallet") + w.WriteHeader(http.StatusInternalServerError) + return + } } else if status == "CANCELLED" { - if err := h.creditWallet(passenger.ID, booking.Journey.Price.Amount); err != nil { + if err := h.creditWallet(passenger.ID, booking.Journey.Price.Amount, "Transport solidaire", "Remboursement annulation transport solidaire"); err != nil { log.Error().Err(err).Msg("could not credit wallet") w.WriteHeader(http.StatusInternalServerError) return diff --git a/handlers/application/solidarity-transport.go b/handlers/application/solidarity-transport.go index c3826bf..1e68aa5 100644 --- a/handlers/application/solidarity-transport.go +++ b/handlers/application/solidarity-transport.go @@ -308,7 +308,9 @@ func (h *ApplicationHandler) SolidarityTransportDriverDisplay(w http.ResponseWri }, } - h.Renderer.SolidarityTransportDriverDisplay(w, r, driver, availabilities, documents, bookings, stats) + walletBalance := h.calculateWalletBalance(driver) + + h.Renderer.SolidarityTransportDriverDisplay(w, r, driver, availabilities, documents, bookings, stats, walletBalance) } func (h *ApplicationHandler) SolidarityTransportAddAvailability(w http.ResponseWriter, r *http.Request) { @@ -724,8 +726,8 @@ func (h *ApplicationHandler) SolidarityTransportDriverJourney(w http.ResponseWri 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") + if err := h.creditWallet(passengerId, float64(-1)*journey.DriverJourney.Price.Amount, "Transport solidaire", "Débit pour réservation transport solidaire"); err != nil { + log.Error().Err(err).Msg("could not credit passenger wallet") w.WriteHeader(http.StatusInternalServerError) return } @@ -756,7 +758,12 @@ func (h *ApplicationHandler) SolidarityTransportDriverJourney(w http.ResponseWri return } - h.Renderer.SolidarityTransportDriverJourney(w, r, driverjourney, driver, passenger, beneficiaries) + passengerWalletBalance := float64(0) + if passenger.Data != nil { + passengerWalletBalance = h.calculateWalletBalance(passenger) + } + + h.Renderer.SolidarityTransportDriverJourney(w, r, driverjourney, driver, passenger, beneficiaries, passengerWalletBalance) } func (h *ApplicationHandler) SolidarityTransportDriverJourneyToggleNoreturn(w http.ResponseWriter, r *http.Request) { @@ -830,7 +837,12 @@ func (h *ApplicationHandler) SolidarityTransportBookingDisplay(w http.ResponseWr return } - h.Renderer.SolidarityTransportBookingDisplay(w, r, booking, driver, passenger) + passengerWalletBalance := float64(0) + if passenger.Data != nil { + passengerWalletBalance = h.calculateWalletBalance(passenger) + } + + h.Renderer.SolidarityTransportBookingDisplay(w, r, booking, driver, passenger, passengerWalletBalance) } func (h *ApplicationHandler) SolidarityTransportBookingStatus(action string) func(w http.ResponseWriter, r *http.Request) { @@ -867,7 +879,7 @@ func (h *ApplicationHandler) SolidarityTransportBookingStatus(action string) fun Id: bookingId, }) if err == nil { - if err := h.creditWallet(booking.Booking.PassengerId, booking.Booking.Journey.Price.Amount); err != nil { + if err := h.creditWallet(booking.Booking.PassengerId, booking.Booking.Journey.Price.Amount, "Transport solidaire", "Remboursement annulation transport solidaire"); err != nil { log.Error().Err(err).Msg("could not credit wallet") w.WriteHeader(http.StatusInternalServerError) return @@ -879,13 +891,25 @@ func (h *ApplicationHandler) SolidarityTransportBookingStatus(action string) fun Id: bookingId, }) if err == nil { - if err := h.creditWallet(booking.Booking.PassengerId, float64(-1)*booking.Booking.Journey.Price.Amount); err != nil { + if err := h.creditWallet(booking.Booking.PassengerId, float64(-1)*booking.Booking.Journey.Price.Amount, "Transport solidaire", "Débit transport solidaire"); err != nil { log.Error().Err(err).Msg("could not credit wallet") w.WriteHeader(http.StatusInternalServerError) return } } } + if status == "VALIDATED" { + booking, err := h.services.GRPC.SolidarityTransport.GetSolidarityTransportBooking(context.Background(), &gen.GetSolidarityTransportBookingRequest{ + Id: bookingId, + }) + if err == nil { + if err := h.creditWallet(booking.Booking.DriverId, booking.Booking.Journey.Price.Amount, "Transport solidaire", "Crédit transport solidaire"); err != nil { + log.Error().Err(err).Msg("could not credit driver wallet") + w.WriteHeader(http.StatusInternalServerError) + return + } + } + } } http.Redirect(w, r, fmt.Sprintf("/app/solidarity-transport/bookings/%s", bookingId), http.StatusFound) } diff --git a/handlers/application/wallets.go b/handlers/application/wallets.go index 5a4ca66..98918b2 100644 --- a/handlers/application/wallets.go +++ b/handlers/application/wallets.go @@ -4,8 +4,10 @@ import ( "context" "net/http" "strconv" + "time" "git.coopgo.io/coopgo-platform/mobility-accounts/grpcapi" + mobilityaccountsstorage "git.coopgo.io/coopgo-platform/mobility-accounts/storage" "github.com/gorilla/mux" "github.com/rs/zerolog/log" ) @@ -22,6 +24,8 @@ func (h ApplicationHandler) CreditWallet(w http.ResponseWriter, r *http.Request) r.ParseForm() amountStr := r.FormValue("amount") + paymentMethod := r.FormValue("payment_method") + description := r.FormValue("description") amount, err := strconv.ParseFloat(amountStr, 64) if err != nil { @@ -30,7 +34,11 @@ func (h ApplicationHandler) CreditWallet(w http.ResponseWriter, r *http.Request) return } - if err := h.creditWallet(userid, amount); err != nil { + if paymentMethod == "" { + paymentMethod = "Paiement en espèce (MMS)" + } + + if err := h.creditWallet(userid, amount, paymentMethod, description); err != nil { log.Error().Err(err).Msg("could not credit wallet") w.WriteHeader(http.StatusInternalServerError) return @@ -39,18 +47,65 @@ func (h ApplicationHandler) CreditWallet(w http.ResponseWriter, r *http.Request) http.Redirect(w, r, r.Referer(), http.StatusFound) } -func (h *ApplicationHandler) creditWallet(userid string, amount float64) error { +func (h *ApplicationHandler) creditWallet(userid string, amount float64, paymentMethod string, description string) error { account, err := h.services.GetAccount(userid) if err != nil { log.Error().Err(err).Msg("could not retrieve account") return err } + // Initialize wallet if it doesn't exist if account.Data["wallet"] == nil { account.Data["wallet"] = float64(0) } - account.Data["wallet"] = account.Data["wallet"].(float64) + amount + // Initialize wallet history if it doesn't exist + if account.Data["wallet_history"] == nil { + account.Data["wallet_history"] = []map[string]interface{}{} + } + + // Determine operation type based on amount sign + operationType := "credit" + if amount < 0 { + operationType = "debit" + } + + // Create wallet operation record + operation := map[string]interface{}{ + "timestamp": time.Now().Format(time.RFC3339), + "amount": amount, + "payment_method": paymentMethod, + "description": description, + "operation_type": operationType, + } + + // Add operation to history + var history []map[string]interface{} + if existingHistory, ok := account.Data["wallet_history"].([]interface{}); ok { + // Convert []interface{} to []map[string]interface{} + for _, item := range existingHistory { + if historyItem, ok := item.(map[string]interface{}); ok { + history = append(history, historyItem) + } + } + } else if existingHistory, ok := account.Data["wallet_history"].([]map[string]interface{}); ok { + history = existingHistory + } + + history = append(history, operation) + account.Data["wallet_history"] = history + + log.Debug(). + Str("userid", userid). + Float64("amount", amount). + Str("paymentMethod", paymentMethod). + Str("description", description). + Int("historyCount", len(history)). + Msg("Adding operation to wallet history") + + // Note: wallet balance is NOT updated here - it remains as initial amount + // Balance is calculated from initial amount + sum of all operations + accountproto, err := grpcapi.AccountFromStorageType(&account) if err != nil { log.Error().Err(err).Msg("account type transformation issue") @@ -61,9 +116,69 @@ func (h *ApplicationHandler) creditWallet(userid string, amount float64) error { Account: accountproto, }) if err != nil { - log.Error().Err(err).Msg("account type transformation issue") + log.Error().Err(err).Msg("account update issue") return err } + log.Info(). + Str("userid", userid). + Float64("amount", amount). + Str("payment_method", paymentMethod). + Str("description", description). + Msg("Wallet credited successfully") + return nil } + +// calculateWalletBalance calculates the current wallet balance from initial amount + all operations +func (h *ApplicationHandler) calculateWalletBalance(account mobilityaccountsstorage.Account) float64 { + // Return 0 if account data is nil + if account.Data == nil { + log.Debug().Msg("calculateWalletBalance: account.Data is nil, returning 0") + return float64(0) + } + + // Get initial wallet amount (default to 0 if not set) + initialAmount := float64(0) + if walletValue, exists := account.Data["wallet"]; exists && walletValue != nil { + if val, ok := walletValue.(float64); ok { + initialAmount = val + } + } + + // Calculate total from all operations + operationsTotal := float64(0) + operationCount := 0 + if historyValue, exists := account.Data["wallet_history"]; exists && historyValue != nil { + var operations []map[string]interface{} + + // Handle both []interface{} and []map[string]interface{} types + if history, ok := historyValue.([]interface{}); ok { + for _, item := range history { + if operation, ok := item.(map[string]interface{}); ok { + operations = append(operations, operation) + } + } + } else if history, ok := historyValue.([]map[string]interface{}); ok { + operations = history + } + + for _, operation := range operations { + if amount, ok := operation["amount"].(float64); ok { + operationsTotal += amount + operationCount++ + } + } + } + + result := initialAmount + operationsTotal + log.Debug(). + Str("accountId", account.ID). + Float64("initialAmount", initialAmount). + Float64("operationsTotal", operationsTotal). + Int("operationCount", operationCount). + Float64("result", result). + Msg("calculateWalletBalance") + + return result +} diff --git a/main.go b/main.go index f77ba07..bb86854 100755 --- a/main.go +++ b/main.go @@ -150,6 +150,10 @@ func main() { 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("/organized-carpool/bookings/{bookingid}", applicationHandler.OrganizedCarpoolBookingDisplay) + application.HandleFunc("/organized-carpool/bookings/{bookingid}/confirm", applicationHandler.OrganizedCarpoolBookingStatus("confirm")) + application.HandleFunc("/organized-carpool/bookings/{bookingid}/cancel", applicationHandler.OrganizedCarpoolBookingStatus("cancel")) + application.HandleFunc("/organized-carpool/bookings/{bookingid}/waitconfirmation", applicationHandler.OrganizedCarpoolBookingStatus("waitconfirmation")) application.HandleFunc("/vehicles/", applicationHandler.VehiclesSearch) application.HandleFunc("/vehicles/bookings/", applicationHandler.VehiclesBookingsList) application.HandleFunc("/vehicles/bookings/{bookingid}", applicationHandler.VehicleBookingDisplay) diff --git a/renderer/beneficiaries.go b/renderer/beneficiaries.go index 086eee9..0aae98e 100755 --- a/renderer/beneficiaries.go +++ b/renderer/beneficiaries.go @@ -58,7 +58,7 @@ type BeneficiariesDisplayState struct { 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, solidarityTransportStats 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, walletBalance float64) { files := renderer.ThemeConfig.GetStringSlice("views.beneficiaries.display.files") profileFields := renderer.GlobalConfig.Get("modules.beneficiaries.profile_optional_fields") @@ -74,6 +74,7 @@ func (renderer *Renderer) BeneficiaryDisplay(w http.ResponseWriter, r *http.Requ "diags": diags, "solidarity_transport_stats": solidarityTransportStats, "profile_optional_fields": profileFields, + "wallet_balance": walletBalance, } renderer.Render("beneficiaries_display", w, r, files, state) } diff --git a/renderer/func-maps.go b/renderer/func-maps.go index c3deabc..eaf87af 100755 --- a/renderer/func-maps.go +++ b/renderer/func-maps.go @@ -152,8 +152,23 @@ func Divide[V int | float64](a, b V) V { return a / b } -func ShortDuration(d time.Duration) string { - s := d.String() +func ShortDuration(d interface{}) string { + var duration time.Duration + + switch v := d.(type) { + case time.Duration: + duration = v + case int: + duration = time.Duration(v) * time.Second + case int64: + duration = time.Duration(v) * time.Second + case float64: + duration = time.Duration(v) * time.Second + default: + return "" + } + + s := duration.String() if strings.HasSuffix(s, "m0s") { s = s[:len(s)-2] } diff --git a/renderer/organized-carpool.go b/renderer/organized-carpool.go index cd423b2..b091fb3 100644 --- a/renderer/organized-carpool.go +++ b/renderer/organized-carpool.go @@ -65,7 +65,22 @@ func (renderer *Renderer) OrganizedCarpoolJourney(w http.ResponseWriter, r *http "passenger": passenger, "beneficiaries": beneficiaries, "journey": journey, + "config": renderer.GlobalConfig, } renderer.Render("organized carpool journey", w, r, files, state) } + +func (renderer *Renderer) OrganizedCarpoolBookingDisplay(w http.ResponseWriter, r *http.Request, booking any, driver any, passenger any, driverDepartureAddress, driverArrivalAddress string) { + files := renderer.ThemeConfig.GetStringSlice("views.organized_carpool.booking_display.files") + state := NewState(r, renderer.ThemeConfig, organizedCarpoolMenu) + state.ViewState = map[string]any{ + "driver": driver, + "passenger": passenger, + "booking": booking, + "driverDepartureAddress": driverDepartureAddress, + "driverArrivalAddress": driverArrivalAddress, + } + + renderer.Render("organized carpool booking display", w, r, files, state) +} diff --git a/renderer/solidarity-transport.go b/renderer/solidarity-transport.go index e14f626..84dea43 100644 --- a/renderer/solidarity-transport.go +++ b/renderer/solidarity-transport.go @@ -27,63 +27,75 @@ func (renderer *Renderer) SolidarityTransportOverview(w http.ResponseWriter, r * func (renderer *Renderer) SolidarityTransportCreateDriver(w http.ResponseWriter, r *http.Request) { files := renderer.ThemeConfig.GetStringSlice("views.solidarity_transport.driver_create.files") + profileFields := renderer.GlobalConfig.Get("modules.solidarity_transport.drivers.profile_optional_fields") + state := NewState(r, renderer.ThemeConfig, solidarityTransportMenu) - state.ViewState = map[string]any{} + state.ViewState = map[string]any{ + "profile_optional_fields": profileFields, + } renderer.Render("solidarity transport driver creation", w, r, files, state) } func (renderer *Renderer) SolidarityTransportUpdateDriver(w http.ResponseWriter, r *http.Request, driver any) { files := renderer.ThemeConfig.GetStringSlice("views.solidarity_transport.driver_update.files") + profileFields := renderer.GlobalConfig.Get("modules.solidarity_transport.drivers.profile_optional_fields") + state := NewState(r, renderer.ThemeConfig, solidarityTransportMenu) state.ViewState = map[string]any{ - "driver": driver, + "driver": driver, + "profile_optional_fields": profileFields, } 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) { +func (renderer *Renderer) SolidarityTransportDriverDisplay(w http.ResponseWriter, r *http.Request, driver mobilityaccountsstorage.Account, availabilities any, documents any, bookings any, stats map[string]any, walletBalance float64) { files := renderer.ThemeConfig.GetStringSlice("views.solidarity_transport.driver_display.files") + profileFields := renderer.GlobalConfig.Get("modules.solidarity_transport.drivers.profile_optional_fields") 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, + "driver": driver, + "availabilities": availabilities, + "bookings": bookings, + "documents": documents, + "drivers_file_types": drivers_file_types, + "file_types_map": file_types_map, + "stats": stats, + "profile_optional_fields": profileFields, + "wallet_balance": walletBalance, } 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) { +func (renderer *Renderer) SolidarityTransportDriverJourney(w http.ResponseWriter, r *http.Request, driverJourney any, driver any, passenger any, beneficiaries any, passengerWalletBalance float64) { 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, + "driver": driver, + "passenger": passenger, + "beneficiaries": beneficiaries, + "driver_journey": driverJourney, + "config": renderer.GlobalConfig, + "passenger_wallet_balance": passengerWalletBalance, } 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) { +func (renderer *Renderer) SolidarityTransportBookingDisplay(w http.ResponseWriter, r *http.Request, booking any, driver any, passenger any, passengerWalletBalance float64) { 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, + "driver": driver, + "passenger": passenger, + "booking": booking, + "passenger_wallet_balance": passengerWalletBalance, } renderer.Render("booking display", w, r, files, state) diff --git a/services/services.go b/services/services.go index 7cab2dd..893d14d 100755 --- a/services/services.go +++ b/services/services.go @@ -9,7 +9,7 @@ import ( groupsmanagement "git.coopgo.io/coopgo-platform/groups-management/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/multimodal-routing/libs/transit/transitous" "git.coopgo.io/coopgo-platform/payments/pricing" "git.coopgo.io/coopgo-platform/routing-service" "git.coopgo.io/coopgo-platform/sms" @@ -22,7 +22,7 @@ type ServicesHandler struct { GRPC GRPCServices InteropCarpool *multimodal.CarpoolRoutingHandler Routing routing.RoutingService - TransitRouting *motis.ClientWithResponses + TransitRouting *transitous.Client SMS *sms.SMSHandler Pricing pricing.PricingService Geography admin.AdminIndex @@ -103,11 +103,7 @@ func NewServicesHandler(cfg *viper.Viper) (*ServicesHandler, error) { 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 - } + transitousRouting := transitous.NewClient(cfg.GetString("multimodal.modes.transit.transitous.server")) pricing_type := cfg.GetString("payments.pricing.type") if pricing_type == "" { @@ -143,7 +139,7 @@ func NewServicesHandler(cfg *viper.Viper) (*ServicesHandler, error) { }, Routing: routing, InteropCarpool: carpoolRouting, - TransitRouting: motisRouting, + TransitRouting: transitousRouting, SMS: smsHandler, Pricing: pricingService, Geography: geography,