improvements
Build and Push Docker Image / build_and_push (push) Failing after 3m6s
Details
Build and Push Docker Image / build_and_push (push) Failing after 3m6s
Details
This commit is contained in:
parent
fc5b33e88c
commit
723c12a657
|
@ -1 +1,2 @@
|
||||||
config.yaml
|
config.yaml
|
||||||
|
solidarity-transport
|
||||||
|
|
8
go.mod
8
go.mod
|
@ -5,16 +5,19 @@ go 1.23.3
|
||||||
//replace git.coopgo.io/coopgo-platform/routing-service => ../../coopgo-platform/routing-service/
|
//replace git.coopgo.io/coopgo-platform/routing-service => ../../coopgo-platform/routing-service/
|
||||||
|
|
||||||
require (
|
require (
|
||||||
|
git.coopgo.io/coopgo-platform/routing-service v0.0.0-20250304234521-faabcc54f536
|
||||||
github.com/google/uuid v1.6.0
|
github.com/google/uuid v1.6.0
|
||||||
|
github.com/paulmach/orb v0.11.1
|
||||||
github.com/rs/zerolog v1.33.0
|
github.com/rs/zerolog v1.33.0
|
||||||
github.com/spf13/viper v1.19.0
|
github.com/spf13/viper v1.19.0
|
||||||
|
github.com/stretchr/testify v1.9.0
|
||||||
go.mongodb.org/mongo-driver/v2 v2.1.0
|
go.mongodb.org/mongo-driver/v2 v2.1.0
|
||||||
google.golang.org/grpc v1.70.0
|
google.golang.org/grpc v1.70.0
|
||||||
google.golang.org/protobuf v1.36.6
|
google.golang.org/protobuf v1.36.6
|
||||||
)
|
)
|
||||||
|
|
||||||
require (
|
require (
|
||||||
git.coopgo.io/coopgo-platform/routing-service v0.0.0-20250304234521-faabcc54f536 // indirect
|
github.com/davecgh/go-spew v1.1.2-0.20180830191138-d8f796af33cc // indirect
|
||||||
github.com/fsnotify/fsnotify v1.7.0 // indirect
|
github.com/fsnotify/fsnotify v1.7.0 // indirect
|
||||||
github.com/golang/snappy v0.0.4 // indirect
|
github.com/golang/snappy v0.0.4 // indirect
|
||||||
github.com/hashicorp/hcl v1.0.0 // indirect
|
github.com/hashicorp/hcl v1.0.0 // indirect
|
||||||
|
@ -23,14 +26,15 @@ require (
|
||||||
github.com/mattn/go-colorable v0.1.13 // indirect
|
github.com/mattn/go-colorable v0.1.13 // indirect
|
||||||
github.com/mattn/go-isatty v0.0.19 // indirect
|
github.com/mattn/go-isatty v0.0.19 // indirect
|
||||||
github.com/mitchellh/mapstructure v1.5.0 // indirect
|
github.com/mitchellh/mapstructure v1.5.0 // indirect
|
||||||
github.com/paulmach/orb v0.11.1 // indirect
|
|
||||||
github.com/pelletier/go-toml/v2 v2.2.2 // indirect
|
github.com/pelletier/go-toml/v2 v2.2.2 // indirect
|
||||||
|
github.com/pmezard/go-difflib v1.0.1-0.20181226105442-5d4384ee4fb2 // indirect
|
||||||
github.com/sagikazarmark/locafero v0.4.0 // indirect
|
github.com/sagikazarmark/locafero v0.4.0 // indirect
|
||||||
github.com/sagikazarmark/slog-shim v0.1.0 // indirect
|
github.com/sagikazarmark/slog-shim v0.1.0 // indirect
|
||||||
github.com/sourcegraph/conc v0.3.0 // indirect
|
github.com/sourcegraph/conc v0.3.0 // indirect
|
||||||
github.com/spf13/afero v1.11.0 // indirect
|
github.com/spf13/afero v1.11.0 // indirect
|
||||||
github.com/spf13/cast v1.6.0 // indirect
|
github.com/spf13/cast v1.6.0 // indirect
|
||||||
github.com/spf13/pflag v1.0.5 // indirect
|
github.com/spf13/pflag v1.0.5 // indirect
|
||||||
|
github.com/stretchr/objx v0.5.2 // indirect
|
||||||
github.com/subosito/gotenv v1.6.0 // indirect
|
github.com/subosito/gotenv v1.6.0 // indirect
|
||||||
github.com/twpayne/go-polyline v1.1.1 // indirect
|
github.com/twpayne/go-polyline v1.1.1 // indirect
|
||||||
github.com/xdg-go/pbkdf2 v1.0.0 // indirect
|
github.com/xdg-go/pbkdf2 v1.0.0 // indirect
|
||||||
|
|
6
go.sum
6
go.sum
|
@ -1,5 +1,3 @@
|
||||||
git.coopgo.io/coopgo-platform/routing-service v0.0.0-20240919052617-d03cd410081c h1:I0pJtlpW7Eloiro+VXVRzdQYJW9AMmjNIczBlROCX9Y=
|
|
||||||
git.coopgo.io/coopgo-platform/routing-service v0.0.0-20240919052617-d03cd410081c/go.mod h1:Nh7o15LlV0OuO9zxvJIs9FlelpeAaLYkXtFdgIkFrgg=
|
|
||||||
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 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/routing-service v0.0.0-20250304234521-faabcc54f536/go.mod h1:Nh7o15LlV0OuO9zxvJIs9FlelpeAaLYkXtFdgIkFrgg=
|
||||||
github.com/coreos/go-systemd/v22 v22.5.0/go.mod h1:Y58oyj3AT4RCenI/lSvhwexgC+NSVTIJ3seZv2GcEnc=
|
github.com/coreos/go-systemd/v22 v22.5.0/go.mod h1:Y58oyj3AT4RCenI/lSvhwexgC+NSVTIJ3seZv2GcEnc=
|
||||||
|
@ -86,6 +84,7 @@ github.com/stretchr/objx v0.1.0/go.mod h1:HFkY916IF+rwdDfMAkV7OtwuqBVzrE8GR6GFx+
|
||||||
github.com/stretchr/objx v0.3.0/go.mod h1:qt09Ya8vawLte6SNmTgCsAVtYtaKzEcn8ATUoHMkEqE=
|
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.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/objx v0.5.2/go.mod h1:FRsXN1f5AsAjCGJKqEizvkpNtU+EGNCLh3NxZ/8L+MA=
|
||||||
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.6.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg=
|
github.com/stretchr/testify v1.6.1/go.mod h1:6Fq8oRcR53rry900zMqJjRRixrwX3KX962/h/Wwjteg=
|
||||||
|
@ -97,6 +96,7 @@ github.com/stretchr/testify v1.9.0 h1:HtqpIVDClZ4nwg75+f6Lvsy/wHu+3BoSGCbBAcpTsT
|
||||||
github.com/stretchr/testify v1.9.0/go.mod h1:r2ic/lqez/lEtzL7wO/rwa5dbSLXVDPFyf8C91i36aY=
|
github.com/stretchr/testify v1.9.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/pretty v1.0.0 h1:HsD+QiTn7sK6flMKIvNmpqz1qrpP3Ps6jOKIKMooyg4=
|
||||||
github.com/tidwall/pretty v1.0.0/go.mod h1:XNkn88O1ChpSDQmQeStsy+sBenx6DDtFZJxhVysOjyk=
|
github.com/tidwall/pretty v1.0.0/go.mod h1:XNkn88O1ChpSDQmQeStsy+sBenx6DDtFZJxhVysOjyk=
|
||||||
github.com/twpayne/go-polyline v1.1.1 h1:/tSF1BR7rN4HWj4XKqvRUNrCiYVMCvywxTFVofvDV0w=
|
github.com/twpayne/go-polyline v1.1.1 h1:/tSF1BR7rN4HWj4XKqvRUNrCiYVMCvywxTFVofvDV0w=
|
||||||
github.com/twpayne/go-polyline v1.1.1/go.mod h1:ybd9IWWivW/rlXPXuuckeKUyF3yrIim+iqA7kSl4NFY=
|
github.com/twpayne/go-polyline v1.1.1/go.mod h1:ybd9IWWivW/rlXPXuuckeKUyF3yrIim+iqA7kSl4NFY=
|
||||||
|
@ -197,8 +197,6 @@ google.golang.org/grpc v1.70.0 h1:pWFv03aZoHzlRKHWicjsZytKAiYCtNS0dHbXnIdq7jQ=
|
||||||
google.golang.org/grpc v1.70.0/go.mod h1:ofIJqVKDXx/JiXrwr2IG4/zwdH9txy3IlF40RmcJSQw=
|
google.golang.org/grpc v1.70.0/go.mod h1:ofIJqVKDXx/JiXrwr2IG4/zwdH9txy3IlF40RmcJSQw=
|
||||||
google.golang.org/protobuf v1.26.0-rc.1/go.mod h1:jlhhOSvTdKEhbULTjvd4ARK9grFBp09yW+WbY/TyQbw=
|
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.27.1/go.mod h1:9q0QmTI4eRPtz6boOQmLYwt+qCgq0jsYwAQnmE0givc=
|
||||||
google.golang.org/protobuf v1.35.2 h1:8Ar7bF+apOIoThw1EdZl0p1oWvMqTHmpA2fRTyZO8io=
|
|
||||||
google.golang.org/protobuf v1.35.2/go.mod h1:9fA7Ob0pmnwhb644+1+CVWFRbNajQ6iRojtC/QF5bRE=
|
|
||||||
google.golang.org/protobuf v1.36.6 h1:z1NpPI8ku2WgiWnf+t9wTPsn6eP1L7ksHUlkfLvd9xY=
|
google.golang.org/protobuf v1.36.6 h1:z1NpPI8ku2WgiWnf+t9wTPsn6eP1L7ksHUlkfLvd9xY=
|
||||||
google.golang.org/protobuf v1.36.6/go.mod h1:jduwjTPXsFjZGTmRluh+L6NjiWu7pchiJ2/5YcXBHnY=
|
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=
|
||||||
|
|
|
@ -9,7 +9,7 @@ import (
|
||||||
"github.com/rs/zerolog/log"
|
"github.com/rs/zerolog/log"
|
||||||
)
|
)
|
||||||
|
|
||||||
func (h Handler) BookDriverJourney(passengerid string, driverid string, journeyid string, returnWaitingDuration time.Duration, priceAmount float64, priceCurrency string, data map[string]any) (*types.Booking, error) {
|
func (h Handler) BookDriverJourney(passengerid string, driverid string, journeyid string, returnWaitingDuration time.Duration, priceAmount float64, priceCurrency string, driverCompensationAmount float64, driverCompensationCurrency string, data map[string]any) (*types.Booking, error) {
|
||||||
journey, err := h.Storage.GetDriverJourney(journeyid)
|
journey, err := h.Storage.GetDriverJourney(journeyid)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
log.Error().Err(err).Msg("could not find driver journey")
|
log.Error().Err(err).Msg("could not find driver journey")
|
||||||
|
@ -26,14 +26,16 @@ func (h Handler) BookDriverJourney(passengerid string, driverid string, journeyi
|
||||||
log.Debug().Float64("Price", priceAmount).Any("journey", journey.Price).Msg("store booking")
|
log.Debug().Float64("Price", priceAmount).Any("journey", journey.Price).Msg("store booking")
|
||||||
|
|
||||||
booking := types.Booking{
|
booking := types.Booking{
|
||||||
Id: uuid.NewString(),
|
Id: uuid.NewString(),
|
||||||
GroupId: uuid.NewString(),
|
GroupId: uuid.NewString(),
|
||||||
Status: "WAITING_CONFIRMATION",
|
Status: "WAITING_CONFIRMATION",
|
||||||
PassengerId: passengerid,
|
PassengerId: passengerid,
|
||||||
DriverId: driverid,
|
DriverId: driverid,
|
||||||
Journey: journey,
|
Journey: journey,
|
||||||
ReturnWaitingDuration: returnWaitingDuration,
|
ReturnWaitingDuration: returnWaitingDuration,
|
||||||
Data: data,
|
Data: data,
|
||||||
|
DriverCompensationAmount: driverCompensationAmount,
|
||||||
|
DriverCompensationCurrency: driverCompensationCurrency,
|
||||||
}
|
}
|
||||||
|
|
||||||
if err := h.Storage.CreateBooking(booking); err != nil {
|
if err := h.Storage.CreateBooking(booking); err != nil {
|
||||||
|
|
|
@ -0,0 +1,335 @@
|
||||||
|
package handler
|
||||||
|
|
||||||
|
import (
|
||||||
|
"testing"
|
||||||
|
"time"
|
||||||
|
|
||||||
|
"git.coopgo.io/coopgo-platform/routing-service"
|
||||||
|
"git.coopgo.io/coopgo-platform/solidarity-transport/storage"
|
||||||
|
"git.coopgo.io/coopgo-platform/solidarity-transport/types"
|
||||||
|
"github.com/google/uuid"
|
||||||
|
"github.com/paulmach/orb"
|
||||||
|
"github.com/paulmach/orb/geojson"
|
||||||
|
"github.com/spf13/viper"
|
||||||
|
"github.com/stretchr/testify/assert"
|
||||||
|
"github.com/stretchr/testify/mock"
|
||||||
|
"github.com/stretchr/testify/require"
|
||||||
|
)
|
||||||
|
|
||||||
|
type MockRoutingService struct {
|
||||||
|
mock.Mock
|
||||||
|
}
|
||||||
|
|
||||||
|
func (m *MockRoutingService) Route(points []orb.Point) (*routing.Route, error) {
|
||||||
|
args := m.Called(points)
|
||||||
|
return args.Get(0).(*routing.Route), args.Error(1)
|
||||||
|
}
|
||||||
|
|
||||||
|
func createTestConfig() *viper.Viper {
|
||||||
|
cfg := viper.New()
|
||||||
|
cfg.Set("storage.db.type", "mock")
|
||||||
|
cfg.Set("parameters.limits.distance.min", 1000)
|
||||||
|
cfg.Set("parameters.limits.distance.max", 50000)
|
||||||
|
return cfg
|
||||||
|
}
|
||||||
|
|
||||||
|
func createTestGeoJSONFeature(lat, lng float64, label string) *geojson.Feature {
|
||||||
|
feature := geojson.NewFeature(orb.Point{lng, lat})
|
||||||
|
feature.Properties = make(map[string]interface{})
|
||||||
|
feature.Properties["label"] = label
|
||||||
|
return feature
|
||||||
|
}
|
||||||
|
|
||||||
|
func createTestRoute() *routing.Route {
|
||||||
|
return createTestRouteWithDistance(6000) // Default route with 6km passenger distance
|
||||||
|
}
|
||||||
|
|
||||||
|
func createTestRouteNoReturn(passengerDistance float64) *routing.Route {
|
||||||
|
// No-return: 3 legs (driver→pickup, pickup→dropoff, dropoff→driver)
|
||||||
|
return &routing.Route{
|
||||||
|
Summary: routing.Summary{
|
||||||
|
Distance: 4000 + passengerDistance,
|
||||||
|
Duration: 15 * time.Minute,
|
||||||
|
Polyline: "test_polyline",
|
||||||
|
},
|
||||||
|
Legs: []routing.RouteLeg{
|
||||||
|
{Summary: routing.Summary{Distance: 2000, Duration: 5 * time.Minute}}, // driver to pickup
|
||||||
|
{Summary: routing.Summary{Distance: passengerDistance, Duration: 8 * time.Minute}}, // pickup to dropoff
|
||||||
|
{Summary: routing.Summary{Distance: 2000, Duration: 5 * time.Minute}}, // dropoff to driver destination
|
||||||
|
},
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func createTestRouteReturn(passengerDistance float64) *routing.Route {
|
||||||
|
// Return: 4+ legs (driver→pickup, pickup→dropoff, dropoff→pickup, pickup→driver)
|
||||||
|
// For return journeys: passenger distance = legs[1] + legs[2]
|
||||||
|
singleLegDistance := passengerDistance / 2
|
||||||
|
|
||||||
|
return &routing.Route{
|
||||||
|
Summary: routing.Summary{
|
||||||
|
Distance: 4000 + passengerDistance,
|
||||||
|
Duration: 18 * time.Minute,
|
||||||
|
Polyline: "test_polyline",
|
||||||
|
},
|
||||||
|
Legs: []routing.RouteLeg{
|
||||||
|
{Summary: routing.Summary{Distance: 2000, Duration: 5 * time.Minute}}, // driver to pickup
|
||||||
|
{Summary: routing.Summary{Distance: singleLegDistance, Duration: 8 * time.Minute}}, // pickup to dropoff
|
||||||
|
{Summary: routing.Summary{Distance: singleLegDistance, Duration: 2 * time.Minute}}, // dropoff to pickup (return)
|
||||||
|
{Summary: routing.Summary{Distance: 2000, Duration: 3 * time.Minute}}, // pickup to driver destination
|
||||||
|
},
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func createTestRouteWithDistance(passengerDistance float64) *routing.Route {
|
||||||
|
// Default to return journey for backward compatibility
|
||||||
|
return createTestRouteReturn(passengerDistance)
|
||||||
|
}
|
||||||
|
|
||||||
|
func createTestAvailability(driverID string, day int, startTime, endTime string) *types.DriverRegularAvailability {
|
||||||
|
address := createTestGeoJSONFeature(45.7640, 4.8357, "Driver Address")
|
||||||
|
return &types.DriverRegularAvailability{
|
||||||
|
ID: uuid.New().String(),
|
||||||
|
DriverId: driverID,
|
||||||
|
Day: day,
|
||||||
|
StartTime: startTime,
|
||||||
|
EndTime: endTime,
|
||||||
|
Address: address,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestHandler_GetDriverJourneys(t *testing.T) {
|
||||||
|
tests := []struct {
|
||||||
|
name string
|
||||||
|
departureDate time.Time
|
||||||
|
noreturn bool
|
||||||
|
availabilities []*types.DriverRegularAvailability
|
||||||
|
routingResponse *routing.Route
|
||||||
|
expectedJourneys int
|
||||||
|
expectedDriverIDs []string
|
||||||
|
description string
|
||||||
|
}{
|
||||||
|
{
|
||||||
|
name: "journey within distance limits",
|
||||||
|
departureDate: time.Date(2024, 1, 15, 8, 0, 0, 0, time.UTC),
|
||||||
|
noreturn: false,
|
||||||
|
availabilities: []*types.DriverRegularAvailability{
|
||||||
|
createTestAvailability("driver-1", 1, "07:00", "09:00"),
|
||||||
|
},
|
||||||
|
routingResponse: createTestRouteWithDistance(6000), // 6km - within limits (1km to 50km)
|
||||||
|
expectedJourneys: 1,
|
||||||
|
expectedDriverIDs: []string{"driver-1"},
|
||||||
|
description: "6km journey should be within distance limits",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "journey too short - below minimum distance",
|
||||||
|
departureDate: time.Date(2024, 1, 15, 8, 0, 0, 0, time.UTC),
|
||||||
|
noreturn: false,
|
||||||
|
availabilities: []*types.DriverRegularAvailability{
|
||||||
|
createTestAvailability("driver-1", 1, "07:00", "09:00"),
|
||||||
|
},
|
||||||
|
routingResponse: createTestRouteWithDistance(500), // 500m - below 1km minimum
|
||||||
|
expectedJourneys: 0,
|
||||||
|
expectedDriverIDs: []string{},
|
||||||
|
description: "500m journey should be rejected (below minimum distance)",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "journey too long - above maximum distance",
|
||||||
|
departureDate: time.Date(2024, 1, 15, 8, 0, 0, 0, time.UTC),
|
||||||
|
noreturn: false,
|
||||||
|
availabilities: []*types.DriverRegularAvailability{
|
||||||
|
createTestAvailability("driver-1", 1, "07:00", "09:00"),
|
||||||
|
},
|
||||||
|
routingResponse: createTestRouteWithDistance(60000), // 60km - above 50km maximum
|
||||||
|
expectedJourneys: 0,
|
||||||
|
expectedDriverIDs: []string{},
|
||||||
|
description: "60km journey should be rejected (above maximum distance)",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "journey at minimum distance boundary",
|
||||||
|
departureDate: time.Date(2024, 1, 15, 8, 0, 0, 0, time.UTC),
|
||||||
|
noreturn: false,
|
||||||
|
availabilities: []*types.DriverRegularAvailability{
|
||||||
|
createTestAvailability("driver-1", 1, "07:00", "09:00"),
|
||||||
|
},
|
||||||
|
routingResponse: createTestRouteWithDistance(1000), // Exactly 1km minimum
|
||||||
|
expectedJourneys: 1,
|
||||||
|
expectedDriverIDs: []string{"driver-1"},
|
||||||
|
description: "1km journey should be accepted (at minimum boundary)",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "journey at maximum distance boundary",
|
||||||
|
departureDate: time.Date(2024, 1, 15, 8, 0, 0, 0, time.UTC),
|
||||||
|
noreturn: false,
|
||||||
|
availabilities: []*types.DriverRegularAvailability{
|
||||||
|
createTestAvailability("driver-1", 1, "07:00", "09:00"),
|
||||||
|
},
|
||||||
|
routingResponse: createTestRouteWithDistance(50000), // Exactly 50km maximum
|
||||||
|
expectedJourneys: 1,
|
||||||
|
expectedDriverIDs: []string{"driver-1"},
|
||||||
|
description: "50km journey should be accepted (at maximum boundary)",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "wrong day no availabilities",
|
||||||
|
departureDate: time.Date(2024, 1, 16, 9, 0, 0, 0, time.UTC),
|
||||||
|
noreturn: false,
|
||||||
|
availabilities: []*types.DriverRegularAvailability{
|
||||||
|
createTestAvailability("driver-1", 1, "08:00", "10:00"),
|
||||||
|
},
|
||||||
|
expectedJourneys: 0,
|
||||||
|
expectedDriverIDs: []string{},
|
||||||
|
description: "Tuesday departure should not match Monday availability",
|
||||||
|
},
|
||||||
|
}
|
||||||
|
|
||||||
|
departure := createTestGeoJSONFeature(45.7578, 4.8320, "Departure")
|
||||||
|
arrival := createTestGeoJSONFeature(45.7485, 4.8467, "Arrival")
|
||||||
|
|
||||||
|
for _, tt := range tests {
|
||||||
|
t.Run(tt.name, func(t *testing.T) {
|
||||||
|
cfg := createTestConfig()
|
||||||
|
mockStorage := storage.NewMockStorage(cfg)
|
||||||
|
mockRouting := &MockRoutingService{}
|
||||||
|
|
||||||
|
for _, availability := range tt.availabilities {
|
||||||
|
err := mockStorage.CreateDriverRegularAvailability(*availability)
|
||||||
|
require.NoError(t, err)
|
||||||
|
}
|
||||||
|
|
||||||
|
routeResponse := tt.routingResponse
|
||||||
|
if routeResponse == nil {
|
||||||
|
routeResponse = createTestRoute() // Default route
|
||||||
|
}
|
||||||
|
mockRouting.On("Route", mock.AnythingOfType("[]orb.Point")).Return(routeResponse, nil)
|
||||||
|
|
||||||
|
handler := &Handler{
|
||||||
|
Config: cfg,
|
||||||
|
Storage: mockStorage,
|
||||||
|
Routing: mockRouting,
|
||||||
|
}
|
||||||
|
|
||||||
|
journeys, err := handler.GetDriverJourneys(departure, arrival, tt.departureDate, tt.noreturn)
|
||||||
|
|
||||||
|
assert.NoError(t, err, tt.description)
|
||||||
|
assert.Len(t, journeys, tt.expectedJourneys, tt.description)
|
||||||
|
|
||||||
|
if tt.expectedJourneys > 0 {
|
||||||
|
actualDriverIDs := make([]string, len(journeys))
|
||||||
|
for i, journey := range journeys {
|
||||||
|
assert.NotEmpty(t, journey.Id)
|
||||||
|
actualDriverIDs[i] = journey.DriverId
|
||||||
|
}
|
||||||
|
assert.ElementsMatch(t, tt.expectedDriverIDs, actualDriverIDs, tt.description)
|
||||||
|
}
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestHandler_GetDriverJourney(t *testing.T) {
|
||||||
|
cfg := createTestConfig()
|
||||||
|
mockStorage := storage.NewMockStorage(cfg)
|
||||||
|
|
||||||
|
testJourney := &types.DriverJourney{
|
||||||
|
Id: uuid.New().String(),
|
||||||
|
DriverId: "driver-1",
|
||||||
|
}
|
||||||
|
err := mockStorage.PushDriverJourneys([]*types.DriverJourney{testJourney})
|
||||||
|
require.NoError(t, err)
|
||||||
|
|
||||||
|
handler := &Handler{
|
||||||
|
Config: cfg,
|
||||||
|
Storage: mockStorage,
|
||||||
|
}
|
||||||
|
|
||||||
|
tests := []struct {
|
||||||
|
name string
|
||||||
|
driverID string
|
||||||
|
journeyID string
|
||||||
|
expectedError bool
|
||||||
|
errorMessage string
|
||||||
|
}{
|
||||||
|
{
|
||||||
|
name: "successful retrieval",
|
||||||
|
driverID: "driver-1",
|
||||||
|
journeyID: testJourney.Id,
|
||||||
|
expectedError: false,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "driver mismatch",
|
||||||
|
driverID: "driver-2",
|
||||||
|
journeyID: testJourney.Id,
|
||||||
|
expectedError: true,
|
||||||
|
errorMessage: "not allowed, driver id mismatch",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
name: "journey not found",
|
||||||
|
driverID: "driver-1",
|
||||||
|
journeyID: "non-existent",
|
||||||
|
expectedError: true,
|
||||||
|
},
|
||||||
|
}
|
||||||
|
|
||||||
|
for _, tt := range tests {
|
||||||
|
t.Run(tt.name, func(t *testing.T) {
|
||||||
|
journey, err := handler.GetDriverJourney(tt.driverID, tt.journeyID)
|
||||||
|
|
||||||
|
if tt.expectedError {
|
||||||
|
assert.Error(t, err)
|
||||||
|
if tt.errorMessage != "" {
|
||||||
|
assert.Contains(t, err.Error(), tt.errorMessage)
|
||||||
|
}
|
||||||
|
assert.Nil(t, journey)
|
||||||
|
} else {
|
||||||
|
assert.NoError(t, err)
|
||||||
|
assert.NotNil(t, journey)
|
||||||
|
assert.Equal(t, tt.journeyID, journey.Id)
|
||||||
|
assert.Equal(t, tt.driverID, journey.DriverId)
|
||||||
|
}
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestHandler_ToggleDriverJourneyNoreturn(t *testing.T) {
|
||||||
|
cfg := createTestConfig()
|
||||||
|
mockStorage := storage.NewMockStorage(cfg)
|
||||||
|
mockRouting := &MockRoutingService{}
|
||||||
|
|
||||||
|
departure := createTestGeoJSONFeature(45.7578, 4.8320, "Departure")
|
||||||
|
arrival := createTestGeoJSONFeature(45.7485, 4.8467, "Arrival")
|
||||||
|
driverAddress := createTestGeoJSONFeature(45.7640, 4.8357, "Driver Address")
|
||||||
|
|
||||||
|
testJourney := &types.DriverJourney{
|
||||||
|
Id: uuid.New().String(),
|
||||||
|
DriverId: "driver-1",
|
||||||
|
PassengerPickup: departure,
|
||||||
|
PassengerDrop: arrival,
|
||||||
|
DriverDeparture: driverAddress,
|
||||||
|
Noreturn: false,
|
||||||
|
}
|
||||||
|
|
||||||
|
err := mockStorage.PushDriverJourneys([]*types.DriverJourney{testJourney})
|
||||||
|
require.NoError(t, err)
|
||||||
|
|
||||||
|
mockRouting.On("Route", mock.AnythingOfType("[]orb.Point")).Return(createTestRoute(), nil)
|
||||||
|
|
||||||
|
handler := &Handler{
|
||||||
|
Config: cfg,
|
||||||
|
Storage: mockStorage,
|
||||||
|
Routing: mockRouting,
|
||||||
|
}
|
||||||
|
|
||||||
|
err = handler.ToggleDriverJourneyNoreturn(testJourney.Id)
|
||||||
|
assert.NoError(t, err)
|
||||||
|
|
||||||
|
updatedJourney, err := mockStorage.GetDriverJourney(testJourney.Id)
|
||||||
|
assert.NoError(t, err)
|
||||||
|
assert.True(t, updatedJourney.Noreturn)
|
||||||
|
|
||||||
|
err = handler.ToggleDriverJourneyNoreturn(testJourney.Id)
|
||||||
|
assert.NoError(t, err)
|
||||||
|
|
||||||
|
updatedJourney, err = mockStorage.GetDriverJourney(testJourney.Id)
|
||||||
|
assert.NoError(t, err)
|
||||||
|
assert.False(t, updatedJourney.Noreturn)
|
||||||
|
|
||||||
|
mockRouting.AssertExpectations(t)
|
||||||
|
}
|
|
@ -396,17 +396,19 @@ func (x *SolidarityTransportPrice) GetCurrency() string {
|
||||||
}
|
}
|
||||||
|
|
||||||
type SolidarityTransportBooking struct {
|
type SolidarityTransportBooking struct {
|
||||||
state protoimpl.MessageState `protogen:"open.v1"`
|
state protoimpl.MessageState `protogen:"open.v1"`
|
||||||
Id string `protobuf:"bytes,1,opt,name=id,proto3" json:"id,omitempty"`
|
Id string `protobuf:"bytes,1,opt,name=id,proto3" json:"id,omitempty"`
|
||||||
GroupId string `protobuf:"bytes,2,opt,name=group_id,json=groupId,proto3" json:"group_id,omitempty"`
|
GroupId string `protobuf:"bytes,2,opt,name=group_id,json=groupId,proto3" json:"group_id,omitempty"`
|
||||||
DriverId string `protobuf:"bytes,3,opt,name=driver_id,json=driverId,proto3" json:"driver_id,omitempty"`
|
DriverId string `protobuf:"bytes,3,opt,name=driver_id,json=driverId,proto3" json:"driver_id,omitempty"`
|
||||||
PassengerId string `protobuf:"bytes,4,opt,name=passenger_id,json=passengerId,proto3" json:"passenger_id,omitempty"`
|
PassengerId string `protobuf:"bytes,4,opt,name=passenger_id,json=passengerId,proto3" json:"passenger_id,omitempty"`
|
||||||
Status string `protobuf:"bytes,5,opt,name=status,proto3" json:"status,omitempty"`
|
Status string `protobuf:"bytes,5,opt,name=status,proto3" json:"status,omitempty"`
|
||||||
ReturnWaitingDuration int64 `protobuf:"varint,6,opt,name=return_waiting_duration,json=returnWaitingDuration,proto3" json:"return_waiting_duration,omitempty"`
|
ReturnWaitingDuration int64 `protobuf:"varint,6,opt,name=return_waiting_duration,json=returnWaitingDuration,proto3" json:"return_waiting_duration,omitempty"`
|
||||||
Data *structpb.Struct `protobuf:"bytes,7,opt,name=data,proto3" json:"data,omitempty"`
|
Data *structpb.Struct `protobuf:"bytes,7,opt,name=data,proto3" json:"data,omitempty"`
|
||||||
Journey *SolidarityTransportDriverJourney `protobuf:"bytes,10,opt,name=journey,proto3" json:"journey,omitempty"`
|
DriverCompensationAmount float64 `protobuf:"fixed64,8,opt,name=driver_compensation_amount,json=driverCompensationAmount,proto3" json:"driver_compensation_amount,omitempty"`
|
||||||
unknownFields protoimpl.UnknownFields
|
DriverCompensationCurrency string `protobuf:"bytes,9,opt,name=driver_compensation_currency,json=driverCompensationCurrency,proto3" json:"driver_compensation_currency,omitempty"`
|
||||||
sizeCache protoimpl.SizeCache
|
Journey *SolidarityTransportDriverJourney `protobuf:"bytes,10,opt,name=journey,proto3" json:"journey,omitempty"`
|
||||||
|
unknownFields protoimpl.UnknownFields
|
||||||
|
sizeCache protoimpl.SizeCache
|
||||||
}
|
}
|
||||||
|
|
||||||
func (x *SolidarityTransportBooking) Reset() {
|
func (x *SolidarityTransportBooking) Reset() {
|
||||||
|
@ -488,6 +490,20 @@ func (x *SolidarityTransportBooking) GetData() *structpb.Struct {
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (x *SolidarityTransportBooking) GetDriverCompensationAmount() float64 {
|
||||||
|
if x != nil {
|
||||||
|
return x.DriverCompensationAmount
|
||||||
|
}
|
||||||
|
return 0
|
||||||
|
}
|
||||||
|
|
||||||
|
func (x *SolidarityTransportBooking) GetDriverCompensationCurrency() string {
|
||||||
|
if x != nil {
|
||||||
|
return x.DriverCompensationCurrency
|
||||||
|
}
|
||||||
|
return ""
|
||||||
|
}
|
||||||
|
|
||||||
func (x *SolidarityTransportBooking) GetJourney() *SolidarityTransportDriverJourney {
|
func (x *SolidarityTransportBooking) GetJourney() *SolidarityTransportDriverJourney {
|
||||||
if x != nil {
|
if x != nil {
|
||||||
return x.Journey
|
return x.Journey
|
||||||
|
@ -537,7 +553,7 @@ const file_solidarity_transport_types_proto_rawDesc = "" +
|
||||||
"\x06_price\"N\n" +
|
"\x06_price\"N\n" +
|
||||||
"\x18SolidarityTransportPrice\x12\x16\n" +
|
"\x18SolidarityTransportPrice\x12\x16\n" +
|
||||||
"\x06amount\x18\x01 \x01(\x01R\x06amount\x12\x1a\n" +
|
"\x06amount\x18\x01 \x01(\x01R\x06amount\x12\x1a\n" +
|
||||||
"\bcurrency\x18\x02 \x01(\tR\bcurrency\"\xc1\x02\n" +
|
"\bcurrency\x18\x02 \x01(\tR\bcurrency\"\xc1\x03\n" +
|
||||||
"\x1aSolidarityTransportBooking\x12\x0e\n" +
|
"\x1aSolidarityTransportBooking\x12\x0e\n" +
|
||||||
"\x02id\x18\x01 \x01(\tR\x02id\x12\x19\n" +
|
"\x02id\x18\x01 \x01(\tR\x02id\x12\x19\n" +
|
||||||
"\bgroup_id\x18\x02 \x01(\tR\agroupId\x12\x1b\n" +
|
"\bgroup_id\x18\x02 \x01(\tR\agroupId\x12\x1b\n" +
|
||||||
|
@ -545,7 +561,9 @@ const file_solidarity_transport_types_proto_rawDesc = "" +
|
||||||
"\fpassenger_id\x18\x04 \x01(\tR\vpassengerId\x12\x16\n" +
|
"\fpassenger_id\x18\x04 \x01(\tR\vpassengerId\x12\x16\n" +
|
||||||
"\x06status\x18\x05 \x01(\tR\x06status\x126\n" +
|
"\x06status\x18\x05 \x01(\tR\x06status\x126\n" +
|
||||||
"\x17return_waiting_duration\x18\x06 \x01(\x03R\x15returnWaitingDuration\x12+\n" +
|
"\x17return_waiting_duration\x18\x06 \x01(\x03R\x15returnWaitingDuration\x12+\n" +
|
||||||
"\x04data\x18\a \x01(\v2\x17.google.protobuf.StructR\x04data\x12;\n" +
|
"\x04data\x18\a \x01(\v2\x17.google.protobuf.StructR\x04data\x12<\n" +
|
||||||
|
"\x1adriver_compensation_amount\x18\b \x01(\x01R\x18driverCompensationAmount\x12@\n" +
|
||||||
|
"\x1cdriver_compensation_currency\x18\t \x01(\tR\x1adriverCompensationCurrency\x12;\n" +
|
||||||
"\ajourney\x18\n" +
|
"\ajourney\x18\n" +
|
||||||
" \x01(\v2!.SolidarityTransportDriverJourneyR\ajourneyBKZIgit.coopgo.io/coopgo-platform/solidarity-transport/servers/grpc/proto/genb\x06proto3"
|
" \x01(\v2!.SolidarityTransportDriverJourneyR\ajourneyBKZIgit.coopgo.io/coopgo-platform/solidarity-transport/servers/grpc/proto/genb\x06proto3"
|
||||||
|
|
||||||
|
|
|
@ -608,16 +608,18 @@ func (x *GetDriverJourneyResponse) GetDriverJourney() *SolidarityTransportDriver
|
||||||
}
|
}
|
||||||
|
|
||||||
type BookDriverJourneyRequest struct {
|
type BookDriverJourneyRequest struct {
|
||||||
state protoimpl.MessageState `protogen:"open.v1"`
|
state protoimpl.MessageState `protogen:"open.v1"`
|
||||||
PassengerId string `protobuf:"bytes,1,opt,name=passenger_id,json=passengerId,proto3" json:"passenger_id,omitempty"`
|
PassengerId string `protobuf:"bytes,1,opt,name=passenger_id,json=passengerId,proto3" json:"passenger_id,omitempty"`
|
||||||
DriverId string `protobuf:"bytes,2,opt,name=driver_id,json=driverId,proto3" json:"driver_id,omitempty"`
|
DriverId string `protobuf:"bytes,2,opt,name=driver_id,json=driverId,proto3" json:"driver_id,omitempty"`
|
||||||
DriverJourneyId string `protobuf:"bytes,3,opt,name=driver_journey_id,json=driverJourneyId,proto3" json:"driver_journey_id,omitempty"`
|
DriverJourneyId string `protobuf:"bytes,3,opt,name=driver_journey_id,json=driverJourneyId,proto3" json:"driver_journey_id,omitempty"`
|
||||||
ReturnWaitingDuration int64 `protobuf:"varint,4,opt,name=return_waiting_duration,json=returnWaitingDuration,proto3" json:"return_waiting_duration,omitempty"`
|
ReturnWaitingDuration int64 `protobuf:"varint,4,opt,name=return_waiting_duration,json=returnWaitingDuration,proto3" json:"return_waiting_duration,omitempty"`
|
||||||
PriceAmount float64 `protobuf:"fixed64,5,opt,name=price_amount,json=priceAmount,proto3" json:"price_amount,omitempty"`
|
PriceAmount float64 `protobuf:"fixed64,5,opt,name=price_amount,json=priceAmount,proto3" json:"price_amount,omitempty"`
|
||||||
PriceCurrency string `protobuf:"bytes,6,opt,name=price_currency,json=priceCurrency,proto3" json:"price_currency,omitempty"`
|
PriceCurrency string `protobuf:"bytes,6,opt,name=price_currency,json=priceCurrency,proto3" json:"price_currency,omitempty"`
|
||||||
Data *structpb.Struct `protobuf:"bytes,7,opt,name=data,proto3" json:"data,omitempty"`
|
Data *structpb.Struct `protobuf:"bytes,7,opt,name=data,proto3" json:"data,omitempty"`
|
||||||
unknownFields protoimpl.UnknownFields
|
DriverCompensationAmount float64 `protobuf:"fixed64,8,opt,name=driver_compensation_amount,json=driverCompensationAmount,proto3" json:"driver_compensation_amount,omitempty"`
|
||||||
sizeCache protoimpl.SizeCache
|
DriverCompensationCurrency string `protobuf:"bytes,9,opt,name=driver_compensation_currency,json=driverCompensationCurrency,proto3" json:"driver_compensation_currency,omitempty"`
|
||||||
|
unknownFields protoimpl.UnknownFields
|
||||||
|
sizeCache protoimpl.SizeCache
|
||||||
}
|
}
|
||||||
|
|
||||||
func (x *BookDriverJourneyRequest) Reset() {
|
func (x *BookDriverJourneyRequest) Reset() {
|
||||||
|
@ -699,6 +701,20 @@ func (x *BookDriverJourneyRequest) GetData() *structpb.Struct {
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (x *BookDriverJourneyRequest) GetDriverCompensationAmount() float64 {
|
||||||
|
if x != nil {
|
||||||
|
return x.DriverCompensationAmount
|
||||||
|
}
|
||||||
|
return 0
|
||||||
|
}
|
||||||
|
|
||||||
|
func (x *BookDriverJourneyRequest) GetDriverCompensationCurrency() string {
|
||||||
|
if x != nil {
|
||||||
|
return x.DriverCompensationCurrency
|
||||||
|
}
|
||||||
|
return ""
|
||||||
|
}
|
||||||
|
|
||||||
type BookDriverJourneyResponse struct {
|
type BookDriverJourneyResponse struct {
|
||||||
state protoimpl.MessageState `protogen:"open.v1"`
|
state protoimpl.MessageState `protogen:"open.v1"`
|
||||||
Booking *SolidarityTransportBooking `protobuf:"bytes,1,opt,name=booking,proto3" json:"booking,omitempty"`
|
Booking *SolidarityTransportBooking `protobuf:"bytes,1,opt,name=booking,proto3" json:"booking,omitempty"`
|
||||||
|
@ -1246,7 +1262,7 @@ const file_solidarity_transport_proto_rawDesc = "" +
|
||||||
"\n" +
|
"\n" +
|
||||||
"journey_id\x18\x02 \x01(\tR\tjourneyId\"d\n" +
|
"journey_id\x18\x02 \x01(\tR\tjourneyId\"d\n" +
|
||||||
"\x18GetDriverJourneyResponse\x12H\n" +
|
"\x18GetDriverJourneyResponse\x12H\n" +
|
||||||
"\x0edriver_journey\x18\x01 \x01(\v2!.SolidarityTransportDriverJourneyR\rdriverJourney\"\xb5\x02\n" +
|
"\x0edriver_journey\x18\x01 \x01(\v2!.SolidarityTransportDriverJourneyR\rdriverJourney\"\xb5\x03\n" +
|
||||||
"\x18BookDriverJourneyRequest\x12!\n" +
|
"\x18BookDriverJourneyRequest\x12!\n" +
|
||||||
"\fpassenger_id\x18\x01 \x01(\tR\vpassengerId\x12\x1b\n" +
|
"\fpassenger_id\x18\x01 \x01(\tR\vpassengerId\x12\x1b\n" +
|
||||||
"\tdriver_id\x18\x02 \x01(\tR\bdriverId\x12*\n" +
|
"\tdriver_id\x18\x02 \x01(\tR\bdriverId\x12*\n" +
|
||||||
|
@ -1254,7 +1270,9 @@ const file_solidarity_transport_proto_rawDesc = "" +
|
||||||
"\x17return_waiting_duration\x18\x04 \x01(\x03R\x15returnWaitingDuration\x12!\n" +
|
"\x17return_waiting_duration\x18\x04 \x01(\x03R\x15returnWaitingDuration\x12!\n" +
|
||||||
"\fprice_amount\x18\x05 \x01(\x01R\vpriceAmount\x12%\n" +
|
"\fprice_amount\x18\x05 \x01(\x01R\vpriceAmount\x12%\n" +
|
||||||
"\x0eprice_currency\x18\x06 \x01(\tR\rpriceCurrency\x12+\n" +
|
"\x0eprice_currency\x18\x06 \x01(\tR\rpriceCurrency\x12+\n" +
|
||||||
"\x04data\x18\a \x01(\v2\x17.google.protobuf.StructR\x04data\"R\n" +
|
"\x04data\x18\a \x01(\v2\x17.google.protobuf.StructR\x04data\x12<\n" +
|
||||||
|
"\x1adriver_compensation_amount\x18\b \x01(\x01R\x18driverCompensationAmount\x12@\n" +
|
||||||
|
"\x1cdriver_compensation_currency\x18\t \x01(\tR\x1adriverCompensationCurrency\"R\n" +
|
||||||
"\x19BookDriverJourneyResponse\x125\n" +
|
"\x19BookDriverJourneyResponse\x125\n" +
|
||||||
"\abooking\x18\x01 \x01(\v2\x1b.SolidarityTransportBookingR\abooking\"\xef\x01\n" +
|
"\abooking\x18\x01 \x01(\v2\x1b.SolidarityTransportBookingR\abooking\"\xef\x01\n" +
|
||||||
"%GetSolidarityTransportBookingsRequest\x129\n" +
|
"%GetSolidarityTransportBookingsRequest\x129\n" +
|
||||||
|
|
|
@ -51,6 +51,8 @@ message SolidarityTransportBooking {
|
||||||
string status = 5;
|
string status = 5;
|
||||||
int64 return_waiting_duration = 6;
|
int64 return_waiting_duration = 6;
|
||||||
google.protobuf.Struct data = 7;
|
google.protobuf.Struct data = 7;
|
||||||
|
double driver_compensation_amount = 8;
|
||||||
|
string driver_compensation_currency = 9;
|
||||||
|
|
||||||
SolidarityTransportDriverJourney journey = 10;
|
SolidarityTransportDriverJourney journey = 10;
|
||||||
}
|
}
|
||||||
|
|
|
@ -88,6 +88,8 @@ message BookDriverJourneyRequest {
|
||||||
double price_amount = 5;
|
double price_amount = 5;
|
||||||
string price_currency = 6;
|
string price_currency = 6;
|
||||||
google.protobuf.Struct data = 7;
|
google.protobuf.Struct data = 7;
|
||||||
|
double driver_compensation_amount = 8;
|
||||||
|
string driver_compensation_currency = 9;
|
||||||
}
|
}
|
||||||
|
|
||||||
message BookDriverJourneyResponse {
|
message BookDriverJourneyResponse {
|
||||||
|
|
|
@ -17,10 +17,12 @@ func (s SolidarityTransportServerImpl) BookDriverJourney(ctx context.Context, re
|
||||||
journeyId := req.DriverJourneyId
|
journeyId := req.DriverJourneyId
|
||||||
priceAmount := req.PriceAmount
|
priceAmount := req.PriceAmount
|
||||||
priceCurrency := req.PriceCurrency
|
priceCurrency := req.PriceCurrency
|
||||||
|
driverCompensationAmount := req.DriverCompensationAmount
|
||||||
|
driverCompensationCurrency := req.DriverCompensationCurrency
|
||||||
returnWaitingDuration := time.Duration(req.ReturnWaitingDuration)
|
returnWaitingDuration := time.Duration(req.ReturnWaitingDuration)
|
||||||
data := req.Data.AsMap()
|
data := req.Data.AsMap()
|
||||||
|
|
||||||
booking, err := s.Handler.BookDriverJourney(passengerId, driverId, journeyId, returnWaitingDuration, priceAmount, priceCurrency, data)
|
booking, err := s.Handler.BookDriverJourney(passengerId, driverId, journeyId, returnWaitingDuration, priceAmount, priceCurrency, driverCompensationAmount, driverCompensationCurrency, data)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
log.Error().Err(err).Msg("issue in BookDriverJourney handler")
|
log.Error().Err(err).Msg("issue in BookDriverJourney handler")
|
||||||
return nil, status.Errorf(codes.Internal, "could not create booking : %v", err)
|
return nil, status.Errorf(codes.Internal, "could not create booking : %v", err)
|
||||||
|
|
|
@ -20,14 +20,16 @@ func BookingTypeToProto(booking *types.Booking) (*gen.SolidarityTransportBooking
|
||||||
}
|
}
|
||||||
|
|
||||||
return &gen.SolidarityTransportBooking{
|
return &gen.SolidarityTransportBooking{
|
||||||
Id: booking.Id,
|
Id: booking.Id,
|
||||||
GroupId: booking.GroupId,
|
GroupId: booking.GroupId,
|
||||||
DriverId: booking.DriverId,
|
DriverId: booking.DriverId,
|
||||||
PassengerId: booking.PassengerId,
|
PassengerId: booking.PassengerId,
|
||||||
Status: booking.Status,
|
Status: booking.Status,
|
||||||
ReturnWaitingDuration: int64(booking.ReturnWaitingDuration),
|
ReturnWaitingDuration: int64(booking.ReturnWaitingDuration),
|
||||||
Journey: journey,
|
Journey: journey,
|
||||||
Data: data,
|
Data: data,
|
||||||
|
DriverCompensationAmount: booking.DriverCompensationAmount,
|
||||||
|
DriverCompensationCurrency: booking.DriverCompensationCurrency,
|
||||||
}, nil
|
}, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -37,13 +39,15 @@ func BookingProtoToType(booking *gen.SolidarityTransportBooking) (*types.Booking
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
return &types.Booking{
|
return &types.Booking{
|
||||||
Id: booking.Id,
|
Id: booking.Id,
|
||||||
GroupId: booking.GroupId,
|
GroupId: booking.GroupId,
|
||||||
DriverId: booking.DriverId,
|
DriverId: booking.DriverId,
|
||||||
PassengerId: booking.PassengerId,
|
PassengerId: booking.PassengerId,
|
||||||
Status: booking.Status,
|
Status: booking.Status,
|
||||||
ReturnWaitingDuration: time.Duration(booking.ReturnWaitingDuration),
|
ReturnWaitingDuration: time.Duration(booking.ReturnWaitingDuration),
|
||||||
Journey: journey,
|
Journey: journey,
|
||||||
Data: booking.Data.AsMap(),
|
Data: booking.Data.AsMap(),
|
||||||
|
DriverCompensationAmount: booking.DriverCompensationAmount,
|
||||||
|
DriverCompensationCurrency: booking.DriverCompensationCurrency,
|
||||||
}, nil
|
}, nil
|
||||||
}
|
}
|
||||||
|
|
|
@ -0,0 +1,279 @@
|
||||||
|
package storage
|
||||||
|
|
||||||
|
import (
|
||||||
|
"fmt"
|
||||||
|
"strings"
|
||||||
|
"sync"
|
||||||
|
|
||||||
|
"git.coopgo.io/coopgo-platform/solidarity-transport/types"
|
||||||
|
"github.com/google/uuid"
|
||||||
|
"github.com/spf13/viper"
|
||||||
|
)
|
||||||
|
|
||||||
|
// MockStorage implements the Storage interface for testing purposes
|
||||||
|
type MockStorage struct {
|
||||||
|
config *viper.Viper
|
||||||
|
mu sync.RWMutex
|
||||||
|
availabilities map[string]*types.DriverRegularAvailability
|
||||||
|
journeys map[string]*types.DriverJourney
|
||||||
|
bookings map[string]*types.Booking
|
||||||
|
availabilitiesByDriver map[string][]*types.DriverRegularAvailability
|
||||||
|
}
|
||||||
|
|
||||||
|
// NewMockStorage creates a new mock storage instance
|
||||||
|
func NewMockStorage(cfg *viper.Viper) Storage {
|
||||||
|
return &MockStorage{
|
||||||
|
config: cfg,
|
||||||
|
availabilities: make(map[string]*types.DriverRegularAvailability),
|
||||||
|
journeys: make(map[string]*types.DriverJourney),
|
||||||
|
bookings: make(map[string]*types.Booking),
|
||||||
|
availabilitiesByDriver: make(map[string][]*types.DriverRegularAvailability),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Driver Regular Availability methods
|
||||||
|
|
||||||
|
func (m *MockStorage) CreateDriverRegularAvailability(availability types.DriverRegularAvailability) error {
|
||||||
|
m.mu.Lock()
|
||||||
|
defer m.mu.Unlock()
|
||||||
|
|
||||||
|
if availability.ID == "" {
|
||||||
|
availability.ID = uuid.New().String()
|
||||||
|
}
|
||||||
|
|
||||||
|
m.availabilities[availability.ID] = &availability
|
||||||
|
|
||||||
|
// Update driver index
|
||||||
|
m.availabilitiesByDriver[availability.DriverId] = append(
|
||||||
|
m.availabilitiesByDriver[availability.DriverId],
|
||||||
|
&availability,
|
||||||
|
)
|
||||||
|
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (m *MockStorage) CreateDriverRegularAvailabilities(availabilities []*types.DriverRegularAvailability) error {
|
||||||
|
for _, availability := range availabilities {
|
||||||
|
if err := m.CreateDriverRegularAvailability(*availability); err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (m *MockStorage) DeleteDriverRegularAvailability(driverid string, availabilityid string) error {
|
||||||
|
m.mu.Lock()
|
||||||
|
defer m.mu.Unlock()
|
||||||
|
|
||||||
|
availability, exists := m.availabilities[availabilityid]
|
||||||
|
if !exists {
|
||||||
|
return fmt.Errorf("availability %s not found", availabilityid)
|
||||||
|
}
|
||||||
|
|
||||||
|
if availability.DriverId != driverid {
|
||||||
|
return fmt.Errorf("availability %s does not belong to driver %s", availabilityid, driverid)
|
||||||
|
}
|
||||||
|
|
||||||
|
delete(m.availabilities, availabilityid)
|
||||||
|
|
||||||
|
// Update driver index
|
||||||
|
driverAvailabilities := m.availabilitiesByDriver[driverid]
|
||||||
|
for i, a := range driverAvailabilities {
|
||||||
|
if a.ID == availabilityid {
|
||||||
|
m.availabilitiesByDriver[driverid] = append(driverAvailabilities[:i], driverAvailabilities[i+1:]...)
|
||||||
|
break
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (m *MockStorage) GetDriverRegularAvailability(driverid string, availabilityid string) (*types.DriverRegularAvailability, error) {
|
||||||
|
m.mu.RLock()
|
||||||
|
defer m.mu.RUnlock()
|
||||||
|
|
||||||
|
availability, exists := m.availabilities[availabilityid]
|
||||||
|
if !exists {
|
||||||
|
return nil, fmt.Errorf("availability %s not found", availabilityid)
|
||||||
|
}
|
||||||
|
|
||||||
|
if availability.DriverId != driverid {
|
||||||
|
return nil, fmt.Errorf("availability %s does not belong to driver %s", availabilityid, driverid)
|
||||||
|
}
|
||||||
|
|
||||||
|
return availability, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (m *MockStorage) GetDriverRegularAvailabilities(driverid string) ([]*types.DriverRegularAvailability, error) {
|
||||||
|
m.mu.RLock()
|
||||||
|
defer m.mu.RUnlock()
|
||||||
|
|
||||||
|
return m.availabilitiesByDriver[driverid], nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (m *MockStorage) GetRegularAvailabilities(day int, timeInDay string) ([]*types.DriverRegularAvailability, error) {
|
||||||
|
m.mu.RLock()
|
||||||
|
defer m.mu.RUnlock()
|
||||||
|
|
||||||
|
var result []*types.DriverRegularAvailability
|
||||||
|
|
||||||
|
for _, availability := range m.availabilities {
|
||||||
|
// Match day
|
||||||
|
if availability.Day != day {
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
|
||||||
|
// For testing, just return all availabilities for the day
|
||||||
|
// Let the handler do the time filtering logic
|
||||||
|
result = append(result, availability)
|
||||||
|
}
|
||||||
|
|
||||||
|
return result, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// timeMatches is a simple time matching function for testing
|
||||||
|
func (m *MockStorage) timeMatches(availabilityTime, requestedTime string) bool {
|
||||||
|
// Simple string matching for testing - real implementation would parse times
|
||||||
|
return strings.HasPrefix(availabilityTime, requestedTime[:2]) // Match hour
|
||||||
|
}
|
||||||
|
|
||||||
|
// Driver Journey methods
|
||||||
|
|
||||||
|
func (m *MockStorage) PushDriverJourneys(journeys []*types.DriverJourney) error {
|
||||||
|
m.mu.Lock()
|
||||||
|
defer m.mu.Unlock()
|
||||||
|
|
||||||
|
for _, journey := range journeys {
|
||||||
|
if journey.Id == "" {
|
||||||
|
journey.Id = uuid.New().String()
|
||||||
|
}
|
||||||
|
m.journeys[journey.Id] = journey
|
||||||
|
}
|
||||||
|
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (m *MockStorage) GetDriverJourney(id string) (*types.DriverJourney, error) {
|
||||||
|
m.mu.RLock()
|
||||||
|
defer m.mu.RUnlock()
|
||||||
|
|
||||||
|
journey, exists := m.journeys[id]
|
||||||
|
if !exists {
|
||||||
|
return nil, fmt.Errorf("journey %s not found", id)
|
||||||
|
}
|
||||||
|
|
||||||
|
return journey, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (m *MockStorage) UpdateDriverJourney(journey types.DriverJourney) error {
|
||||||
|
m.mu.Lock()
|
||||||
|
defer m.mu.Unlock()
|
||||||
|
|
||||||
|
if _, exists := m.journeys[journey.Id]; !exists {
|
||||||
|
return fmt.Errorf("journey %s not found", journey.Id)
|
||||||
|
}
|
||||||
|
|
||||||
|
m.journeys[journey.Id] = &journey
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// Booking methods
|
||||||
|
|
||||||
|
func (m *MockStorage) CreateBooking(booking types.Booking) error {
|
||||||
|
m.mu.Lock()
|
||||||
|
defer m.mu.Unlock()
|
||||||
|
|
||||||
|
if booking.Id == "" {
|
||||||
|
booking.Id = uuid.New().String()
|
||||||
|
}
|
||||||
|
|
||||||
|
m.bookings[booking.Id] = &booking
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (m *MockStorage) GetAllBookings() ([]*types.Booking, error) {
|
||||||
|
m.mu.RLock()
|
||||||
|
defer m.mu.RUnlock()
|
||||||
|
|
||||||
|
var result []*types.Booking
|
||||||
|
for _, booking := range m.bookings {
|
||||||
|
result = append(result, booking)
|
||||||
|
}
|
||||||
|
|
||||||
|
return result, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (m *MockStorage) GetBooking(id string) (*types.Booking, error) {
|
||||||
|
m.mu.RLock()
|
||||||
|
defer m.mu.RUnlock()
|
||||||
|
|
||||||
|
booking, exists := m.bookings[id]
|
||||||
|
if !exists {
|
||||||
|
return nil, fmt.Errorf("booking %s not found", id)
|
||||||
|
}
|
||||||
|
|
||||||
|
return booking, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (m *MockStorage) UpdateBooking(booking types.Booking) error {
|
||||||
|
m.mu.Lock()
|
||||||
|
defer m.mu.Unlock()
|
||||||
|
|
||||||
|
if _, exists := m.bookings[booking.Id]; !exists {
|
||||||
|
return fmt.Errorf("booking %s not found", booking.Id)
|
||||||
|
}
|
||||||
|
|
||||||
|
m.bookings[booking.Id] = &booking
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (m *MockStorage) UpdateBookingStatus(bookingid string, newStatus string, reason string) error {
|
||||||
|
m.mu.Lock()
|
||||||
|
defer m.mu.Unlock()
|
||||||
|
|
||||||
|
booking, exists := m.bookings[bookingid]
|
||||||
|
if !exists {
|
||||||
|
return fmt.Errorf("booking %s not found", bookingid)
|
||||||
|
}
|
||||||
|
|
||||||
|
booking.Status = newStatus
|
||||||
|
// In a real implementation, we might store the reason in a separate field
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// Helper methods for testing
|
||||||
|
|
||||||
|
// Reset clears all data - useful for test setup
|
||||||
|
func (m *MockStorage) Reset() {
|
||||||
|
m.mu.Lock()
|
||||||
|
defer m.mu.Unlock()
|
||||||
|
|
||||||
|
m.availabilities = make(map[string]*types.DriverRegularAvailability)
|
||||||
|
m.journeys = make(map[string]*types.DriverJourney)
|
||||||
|
m.bookings = make(map[string]*types.Booking)
|
||||||
|
m.availabilitiesByDriver = make(map[string][]*types.DriverRegularAvailability)
|
||||||
|
}
|
||||||
|
|
||||||
|
// GetAllJourneys returns all stored journeys - useful for testing
|
||||||
|
func (m *MockStorage) GetAllJourneys() []*types.DriverJourney {
|
||||||
|
m.mu.RLock()
|
||||||
|
defer m.mu.RUnlock()
|
||||||
|
|
||||||
|
var result []*types.DriverJourney
|
||||||
|
for _, journey := range m.journeys {
|
||||||
|
result = append(result, journey)
|
||||||
|
}
|
||||||
|
return result
|
||||||
|
}
|
||||||
|
|
||||||
|
// GetAllAvailabilities returns all stored availabilities - useful for testing
|
||||||
|
func (m *MockStorage) GetAllAvailabilities() []*types.DriverRegularAvailability {
|
||||||
|
m.mu.RLock()
|
||||||
|
defer m.mu.RUnlock()
|
||||||
|
|
||||||
|
var result []*types.DriverRegularAvailability
|
||||||
|
for _, availability := range m.availabilities {
|
||||||
|
result = append(result, availability)
|
||||||
|
}
|
||||||
|
return result
|
||||||
|
}
|
|
@ -35,6 +35,8 @@ func NewStorage(cfg *viper.Viper) (Storage, error) {
|
||||||
return NewMongoDBStorage(cfg)
|
return NewMongoDBStorage(cfg)
|
||||||
case "memory":
|
case "memory":
|
||||||
return NewMemoryStorage(cfg)
|
return NewMemoryStorage(cfg)
|
||||||
|
case "mock":
|
||||||
|
return NewMockStorage(cfg), nil
|
||||||
default:
|
default:
|
||||||
return nil, fmt.Errorf("storage type %v is not supported", storage_type)
|
return nil, fmt.Errorf("storage type %v is not supported", storage_type)
|
||||||
|
|
||||||
|
|
|
@ -3,13 +3,15 @@ package types
|
||||||
import "time"
|
import "time"
|
||||||
|
|
||||||
type Booking struct {
|
type Booking struct {
|
||||||
Id string `json:"id" bson:"_id"`
|
Id string `json:"id" bson:"_id"`
|
||||||
GroupId string `json:"group_id" bson:"group_id"`
|
GroupId string `json:"group_id" bson:"group_id"`
|
||||||
DriverId string `json:"driver_id" bson:"driver_id"`
|
DriverId string `json:"driver_id" bson:"driver_id"`
|
||||||
PassengerId string `json:"passenger_id" bson:"passenger_id"`
|
PassengerId string `json:"passenger_id" bson:"passenger_id"`
|
||||||
Status string `json:"status" bson:"status"`
|
Status string `json:"status" bson:"status"`
|
||||||
ReturnWaitingDuration time.Duration `json:"return_waiting_duration" bson:"return_waiting_duration"`
|
ReturnWaitingDuration time.Duration `json:"return_waiting_duration" bson:"return_waiting_duration"`
|
||||||
Data map[string]any `json:"data" bson:"data"`
|
Data map[string]any `json:"data" bson:"data"`
|
||||||
|
DriverCompensationAmount float64 `json:"driver_compensation_amount" bson:"driver_compensation_amount"`
|
||||||
|
DriverCompensationCurrency string `json:"driver_compensation_currency" bson:"driver_compensation_currency"`
|
||||||
|
|
||||||
Journey *DriverJourney `json:"journey,omitempty" bson:"journey,omitempty"`
|
Journey *DriverJourney `json:"journey,omitempty" bson:"journey,omitempty"`
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in New Issue