366 lines
11 KiB
Go
366 lines
11 KiB
Go
package pricing
|
|
|
|
import (
|
|
"testing"
|
|
|
|
"github.com/stretchr/testify/assert"
|
|
)
|
|
|
|
func TestMMS43Prices(t *testing.T) {
|
|
testCases := []struct {
|
|
name string
|
|
params PricingParams
|
|
expectedPrices map[string]Price
|
|
expectedError bool
|
|
}{
|
|
{
|
|
name: "Solidarity transport - First trip - should be free for passenger",
|
|
params: PricingParams{
|
|
MobilityType: "solidarity_transport",
|
|
Beneficiary: BeneficiaryParams{
|
|
History: 0, // First trip
|
|
Priority: false,
|
|
},
|
|
SharedMobility: SharedMobilityParams{
|
|
PassengerDistance: 10, // 10km in meters
|
|
DriverDistance: 15, // 15km in meters
|
|
},
|
|
},
|
|
expectedPrices: map[string]Price{
|
|
"passenger": {Amount: 0.0, Currency: "EUR"}, // Free for first trip
|
|
"driver": {Amount: 4.5, Currency: "EUR"}, // 15km * 0.30€/km (driver distance)
|
|
},
|
|
expectedError: false,
|
|
},
|
|
{
|
|
name: "Organized carpool - First trip - should be free for passenger",
|
|
params: PricingParams{
|
|
MobilityType: "organized_carpool",
|
|
Beneficiary: BeneficiaryParams{
|
|
History: 0, // First trip
|
|
Priority: false,
|
|
},
|
|
SharedMobility: SharedMobilityParams{
|
|
PassengerDistance: 10, // 10km in meters
|
|
DriverDistance: 15, // 15km in meters
|
|
},
|
|
},
|
|
expectedPrices: map[string]Price{
|
|
"passenger": {Amount: 0.0, Currency: "EUR"}, // Free for first trip
|
|
"driver": {Amount: 3.0, Currency: "EUR"}, // 10km * 0.30€/km (passenger distance)
|
|
},
|
|
expectedError: false,
|
|
},
|
|
{
|
|
name: "Solidarity transport - Second trip - should be free for passenger",
|
|
params: PricingParams{
|
|
MobilityType: "solidarity_transport",
|
|
Beneficiary: BeneficiaryParams{
|
|
History: 1, // Second trip
|
|
Priority: false,
|
|
},
|
|
SharedMobility: SharedMobilityParams{
|
|
PassengerDistance: 20, // 20km in meters
|
|
DriverDistance: 25, // 25km in meters
|
|
},
|
|
},
|
|
expectedPrices: map[string]Price{
|
|
"passenger": {Amount: 0.0, Currency: "EUR"}, // Free for second trip
|
|
"driver": {Amount: 7.5, Currency: "EUR"}, // 25km * 0.30€/km (driver distance)
|
|
},
|
|
expectedError: false,
|
|
},
|
|
{
|
|
name: "Organized carpool - Second trip - should be free for passenger",
|
|
params: PricingParams{
|
|
MobilityType: "organized_carpool",
|
|
Beneficiary: BeneficiaryParams{
|
|
History: 1, // Second trip
|
|
Priority: false,
|
|
},
|
|
SharedMobility: SharedMobilityParams{
|
|
PassengerDistance: 20, // 20km in meters
|
|
DriverDistance: 25, // 25km in meters
|
|
},
|
|
},
|
|
expectedPrices: map[string]Price{
|
|
"passenger": {Amount: 0.0, Currency: "EUR"}, // Free for second trip
|
|
"driver": {Amount: 6.0, Currency: "EUR"}, // 20km * 0.30€/km (passenger distance)
|
|
},
|
|
expectedError: false,
|
|
},
|
|
{
|
|
name: "Solidarity transport - Third trip - passenger should pay",
|
|
params: PricingParams{
|
|
MobilityType: "solidarity_transport",
|
|
Beneficiary: BeneficiaryParams{
|
|
History: 2, // Third trip
|
|
Priority: false,
|
|
},
|
|
SharedMobility: SharedMobilityParams{
|
|
PassengerDistance: 10, // 10km in meters
|
|
DriverDistance: 12, // 12km in meters
|
|
},
|
|
},
|
|
expectedPrices: map[string]Price{
|
|
"passenger": {Amount: 1.8, Currency: "EUR"}, // 12km * 0.15€/km (driver distance)
|
|
"driver": {Amount: 3.6, Currency: "EUR"}, // 12km * 0.30€/km (driver distance)
|
|
},
|
|
expectedError: false,
|
|
},
|
|
{
|
|
name: "Organized carpool - Third trip - passenger should pay",
|
|
params: PricingParams{
|
|
MobilityType: "organized_carpool",
|
|
Beneficiary: BeneficiaryParams{
|
|
History: 2, // Third trip
|
|
Priority: false,
|
|
},
|
|
SharedMobility: SharedMobilityParams{
|
|
PassengerDistance: 10, // 10km in meters
|
|
DriverDistance: 12, // 12km in meters
|
|
},
|
|
},
|
|
expectedPrices: map[string]Price{
|
|
"passenger": {Amount: 1.5, Currency: "EUR"}, // 10km * 0.15€/km (passenger distance)
|
|
"driver": {Amount: 3.0, Currency: "EUR"}, // 10km * 0.30€/km (passenger distance)
|
|
},
|
|
expectedError: false,
|
|
},
|
|
{
|
|
name: "Solidarity transport - Multiple trips - passenger pays normal rate",
|
|
params: PricingParams{
|
|
MobilityType: "solidarity_transport",
|
|
Beneficiary: BeneficiaryParams{
|
|
History: 5, // Multiple trips
|
|
Priority: false,
|
|
},
|
|
SharedMobility: SharedMobilityParams{
|
|
PassengerDistance: 30, // 30km in meters
|
|
DriverDistance: 35, // 35km in meters
|
|
},
|
|
},
|
|
expectedPrices: map[string]Price{
|
|
"passenger": {Amount: 5.25, Currency: "EUR"}, // 35km * 0.15€/km (driver distance)
|
|
"driver": {Amount: 10.5, Currency: "EUR"}, // 35km * 0.30€/km (driver distance)
|
|
},
|
|
expectedError: false,
|
|
},
|
|
{
|
|
name: "Organized carpool - Multiple trips - passenger pays normal rate",
|
|
params: PricingParams{
|
|
MobilityType: "organized_carpool",
|
|
Beneficiary: BeneficiaryParams{
|
|
History: 5, // Multiple trips
|
|
Priority: false,
|
|
},
|
|
SharedMobility: SharedMobilityParams{
|
|
PassengerDistance: 30, // 30km in meters
|
|
DriverDistance: 35, // 35km in meters
|
|
},
|
|
},
|
|
expectedPrices: map[string]Price{
|
|
"passenger": {Amount: 4.5, Currency: "EUR"}, // 30km * 0.15€/km (passenger distance)
|
|
"driver": {Amount: 9.0, Currency: "EUR"}, // 30km * 0.30€/km (passenger distance)
|
|
},
|
|
expectedError: false,
|
|
},
|
|
{
|
|
name: "Solidarity transport - Zero distance - should return zero amounts",
|
|
params: PricingParams{
|
|
MobilityType: "solidarity_transport",
|
|
Beneficiary: BeneficiaryParams{
|
|
History: 3,
|
|
Priority: false,
|
|
},
|
|
SharedMobility: SharedMobilityParams{
|
|
PassengerDistance: 0,
|
|
DriverDistance: 0,
|
|
},
|
|
},
|
|
expectedPrices: map[string]Price{
|
|
"passenger": {Amount: 0.0, Currency: "EUR"},
|
|
"driver": {Amount: 0.0, Currency: "EUR"},
|
|
},
|
|
expectedError: false,
|
|
},
|
|
{
|
|
name: "Solidarity transport - Large distances - check calculation accuracy",
|
|
params: PricingParams{
|
|
MobilityType: "solidarity_transport",
|
|
Beneficiary: BeneficiaryParams{
|
|
History: 10,
|
|
Priority: false,
|
|
},
|
|
SharedMobility: SharedMobilityParams{
|
|
PassengerDistance: 100, // 100km in meters
|
|
DriverDistance: 120, // 120km in meters
|
|
},
|
|
},
|
|
expectedPrices: map[string]Price{
|
|
"passenger": {Amount: 18.0, Currency: "EUR"}, // 120km * 0.15€/km (driver distance)
|
|
"driver": {Amount: 36.0, Currency: "EUR"}, // 120km * 0.30€/km (driver distance)
|
|
},
|
|
expectedError: false,
|
|
},
|
|
{
|
|
name: "Organized carpool - Large distances - check calculation accuracy",
|
|
params: PricingParams{
|
|
MobilityType: "organized_carpool",
|
|
Beneficiary: BeneficiaryParams{
|
|
History: 10,
|
|
Priority: false,
|
|
},
|
|
SharedMobility: SharedMobilityParams{
|
|
PassengerDistance: 100, // 100km in meters
|
|
DriverDistance: 120, // 120km in meters
|
|
},
|
|
},
|
|
expectedPrices: map[string]Price{
|
|
"passenger": {Amount: 15.0, Currency: "EUR"}, // 100km * 0.15€/km (passenger distance)
|
|
"driver": {Amount: 30.0, Currency: "EUR"}, // 100km * 0.30€/km (passenger distance)
|
|
},
|
|
expectedError: false,
|
|
},
|
|
{
|
|
name: "Solidarity transport - Edge case - exactly 2 trips history (3rd trip)",
|
|
params: PricingParams{
|
|
MobilityType: "solidarity_transport",
|
|
Beneficiary: BeneficiaryParams{
|
|
History: 2, // Exactly at the limit
|
|
Priority: false,
|
|
},
|
|
SharedMobility: SharedMobilityParams{
|
|
PassengerDistance: 4, // 4km in meters
|
|
DriverDistance: 5, // 5km in meters
|
|
},
|
|
},
|
|
expectedPrices: map[string]Price{
|
|
"passenger": {Amount: 0.75, Currency: "EUR"}, // 5km * 0.15€/km (first paid trip, driver distance)
|
|
"driver": {Amount: 1.5, Currency: "EUR"}, // 5km * 0.30€/km (driver distance)
|
|
},
|
|
expectedError: false,
|
|
},
|
|
{
|
|
name: "Solidarity transport - Small distances with fractions",
|
|
params: PricingParams{
|
|
MobilityType: "solidarity_transport",
|
|
Beneficiary: BeneficiaryParams{
|
|
History: 3,
|
|
Priority: false,
|
|
},
|
|
SharedMobility: SharedMobilityParams{
|
|
PassengerDistance: 2, // 2km in meters
|
|
DriverDistance: 3, // 3km in meters
|
|
},
|
|
},
|
|
expectedPrices: map[string]Price{
|
|
"passenger": {Amount: 0.45, Currency: "EUR"}, // 3km * 0.15€/km (driver distance)
|
|
"driver": {Amount: 0.9, Currency: "EUR"}, // 3km * 0.30€/km (driver distance)
|
|
},
|
|
expectedError: false,
|
|
},
|
|
}
|
|
|
|
for _, tc := range testCases {
|
|
t.Run(tc.name, func(t *testing.T) {
|
|
pricingService, err := NewMMS43PricingService()
|
|
assert.NoError(t, err)
|
|
|
|
prices, err := pricingService.Prices(tc.params)
|
|
if tc.expectedError {
|
|
assert.Error(t, err)
|
|
} else {
|
|
assert.NoError(t, err)
|
|
// Use InDelta for floating-point comparisons to handle precision issues
|
|
assert.InDelta(t, tc.expectedPrices["passenger"].Amount, prices["passenger"].Amount, 0.001)
|
|
assert.Equal(t, tc.expectedPrices["passenger"].Currency, prices["passenger"].Currency)
|
|
assert.InDelta(t, tc.expectedPrices["driver"].Amount, prices["driver"].Amount, 0.001)
|
|
assert.Equal(t, tc.expectedPrices["driver"].Currency, prices["driver"].Currency)
|
|
}
|
|
})
|
|
}
|
|
}
|
|
|
|
func TestMMS43PricingEdgeCases(t *testing.T) {
|
|
pricingService, err := NewMMS43PricingService()
|
|
assert.NoError(t, err)
|
|
|
|
t.Run("Solidarity transport - Negative history should still work", func(t *testing.T) {
|
|
params := PricingParams{
|
|
MobilityType: "solidarity_transport",
|
|
Beneficiary: BeneficiaryParams{
|
|
History: -1, // Edge case: negative history
|
|
},
|
|
SharedMobility: SharedMobilityParams{
|
|
PassengerDistance: 10,
|
|
DriverDistance: 10,
|
|
},
|
|
}
|
|
|
|
prices, err := pricingService.Prices(params)
|
|
assert.NoError(t, err)
|
|
// Should still be free (2 - (-1) = 3 > 0)
|
|
assert.InDelta(t, 0.0, prices["passenger"].Amount, 0.001)
|
|
assert.InDelta(t, 3.0, prices["driver"].Amount, 0.001)
|
|
})
|
|
|
|
t.Run("Organized carpool - Negative history should still work", func(t *testing.T) {
|
|
params := PricingParams{
|
|
MobilityType: "organized_carpool",
|
|
Beneficiary: BeneficiaryParams{
|
|
History: -1, // Edge case: negative history
|
|
},
|
|
SharedMobility: SharedMobilityParams{
|
|
PassengerDistance: 10,
|
|
DriverDistance: 12,
|
|
},
|
|
}
|
|
|
|
prices, err := pricingService.Prices(params)
|
|
assert.NoError(t, err)
|
|
// Should still be free (2 - (-1) = 3 > 0)
|
|
assert.InDelta(t, 0.0, prices["passenger"].Amount, 0.001)
|
|
assert.InDelta(t, 3.0, prices["driver"].Amount, 0.001) // Uses passenger distance
|
|
})
|
|
|
|
t.Run("Solidarity transport - Very high history", func(t *testing.T) {
|
|
params := PricingParams{
|
|
MobilityType: "solidarity_transport",
|
|
Beneficiary: BeneficiaryParams{
|
|
History: 100,
|
|
},
|
|
SharedMobility: SharedMobilityParams{
|
|
PassengerDistance: 10,
|
|
DriverDistance: 10,
|
|
},
|
|
}
|
|
|
|
prices, err := pricingService.Prices(params)
|
|
assert.NoError(t, err)
|
|
// Should charge normal rate
|
|
assert.InDelta(t, 1.5, prices["passenger"].Amount, 0.001)
|
|
assert.InDelta(t, 3.0, prices["driver"].Amount, 0.001)
|
|
})
|
|
|
|
t.Run("Organized carpool - Very high history", func(t *testing.T) {
|
|
params := PricingParams{
|
|
MobilityType: "organized_carpool",
|
|
Beneficiary: BeneficiaryParams{
|
|
History: 100,
|
|
},
|
|
SharedMobility: SharedMobilityParams{
|
|
PassengerDistance: 10,
|
|
DriverDistance: 12,
|
|
},
|
|
}
|
|
|
|
prices, err := pricingService.Prices(params)
|
|
assert.NoError(t, err)
|
|
// Should charge normal rate based on passenger distance
|
|
assert.InDelta(t, 1.5, prices["passenger"].Amount, 0.001) // 10km * 0.15
|
|
assert.InDelta(t, 3.0, prices["driver"].Amount, 0.001) // 10km * 0.30
|
|
})
|
|
}
|
|
|