From 75d0288d2d4f2607bbd98d8e633835919a9d33dd Mon Sep 17 00:00:00 2001 From: Arnaud Delcasse Date: Mon, 13 Oct 2025 19:57:12 +0200 Subject: [PATCH] fix MMS43 pricing --- pricing/pricing_mms43.go | 19 +++- pricing/pricing_mms43_test.go | 189 +++++++++++++++++++++++++++++----- 2 files changed, 181 insertions(+), 27 deletions(-) diff --git a/pricing/pricing_mms43.go b/pricing/pricing_mms43.go index b2b339d..501f8ab 100644 --- a/pricing/pricing_mms43.go +++ b/pricing/pricing_mms43.go @@ -7,6 +7,17 @@ func NewMMS43PricingService() (*MMS43PricingService, error) { } func (s *MMS43PricingService) Prices(params PricingParams) (map[string]Price, error) { + // Determine which distance to use based on mobility type + // For solidarity transport: use driver distance + // For organized carpool: use passenger distance + var distanceForPricing int64 + if params.MobilityType == "solidarity_transport" { + distanceForPricing = params.SharedMobility.DriverDistance + } else { + // organized_carpool or default + distanceForPricing = params.SharedMobility.PassengerDistance + } + // Calculate passenger price var passengerAmount float64 @@ -16,12 +27,12 @@ func (s *MMS43PricingService) Prices(params PricingParams) (map[string]Price, er // Trip is free passengerAmount = 0.0 } else { - // Price is 0.15€/km for passenger distance - passengerAmount = 0.15 * float64(params.SharedMobility.PassengerDistance) + // Price is 0.15€/km based on mobility type distance + passengerAmount = 0.15 * float64(distanceForPricing) } - // Driver indemnification is always 0.30€/km for driver distance - driverAmount := 0.30 * float64(params.SharedMobility.DriverDistance) + // Driver indemnification is always 0.30€/km based on mobility type distance + driverAmount := 0.30 * float64(distanceForPricing) return map[string]Price{ "passenger": { diff --git a/pricing/pricing_mms43_test.go b/pricing/pricing_mms43_test.go index bcc1d4d..05d6ec7 100644 --- a/pricing/pricing_mms43_test.go +++ b/pricing/pricing_mms43_test.go @@ -14,8 +14,9 @@ func TestMMS43Prices(t *testing.T) { expectedError bool }{ { - name: "First trip - should be free for passenger", + name: "Solidarity transport - First trip - should be free for passenger", params: PricingParams{ + MobilityType: "solidarity_transport", Beneficiary: BeneficiaryParams{ History: 0, // First trip Priority: false, @@ -27,13 +28,33 @@ func TestMMS43Prices(t *testing.T) { }, 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": {Amount: 4.5, Currency: "EUR"}, // 15km * 0.30€/km (driver distance) }, expectedError: false, }, { - name: "Second trip - should be free for passenger", + 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, @@ -45,31 +66,71 @@ func TestMMS43Prices(t *testing.T) { }, 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": {Amount: 7.5, Currency: "EUR"}, // 25km * 0.30€/km (driver distance) }, expectedError: false, }, { - name: "Third trip - passenger should pay", + 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: 10, // 10km in meters + DriverDistance: 12, // 12km in meters }, }, expectedPrices: map[string]Price{ - "passenger": {Amount: 1.5, Currency: "EUR"}, // 10km * 0.15€/km - "driver": {Amount: 3.0, Currency: "EUR"}, // 10km * 0.30€/km + "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: "Multiple trips - passenger pays normal rate", + 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, @@ -80,14 +141,34 @@ func TestMMS43Prices(t *testing.T) { }, }, expectedPrices: map[string]Price{ - "passenger": {Amount: 4.5, Currency: "EUR"}, // 30km * 0.15€/km - "driver": {Amount: 10.5, Currency: "EUR"}, // 35km * 0.30€/km + "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: "Zero distance - should return zero amounts", + 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, @@ -104,8 +185,9 @@ func TestMMS43Prices(t *testing.T) { expectedError: false, }, { - name: "Large distances - check calculation accuracy", + name: "Solidarity transport - Large distances - check calculation accuracy", params: PricingParams{ + MobilityType: "solidarity_transport", Beneficiary: BeneficiaryParams{ History: 10, Priority: false, @@ -116,14 +198,34 @@ func TestMMS43Prices(t *testing.T) { }, }, expectedPrices: map[string]Price{ - "passenger": {Amount: 15.0, Currency: "EUR"}, // 100km * 0.15€/km - "driver": {Amount: 36.0, Currency: "EUR"}, // 120km * 0.30€/km + "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: "Edge case - exactly 2 trips history (3rd trip)", + 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, @@ -134,14 +236,15 @@ func TestMMS43Prices(t *testing.T) { }, }, expectedPrices: map[string]Price{ - "passenger": {Amount: 0.6, Currency: "EUR"}, // 4km * 0.15€/km (first paid trip) - "driver": {Amount: 1.5, Currency: "EUR"}, // 5km * 0.30€/km + "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: "Small distances with fractions", + name: "Solidarity transport - Small distances with fractions", params: PricingParams{ + MobilityType: "solidarity_transport", Beneficiary: BeneficiaryParams{ History: 3, Priority: false, @@ -152,8 +255,8 @@ func TestMMS43Prices(t *testing.T) { }, }, expectedPrices: map[string]Price{ - "passenger": {Amount: 0.3, Currency: "EUR"}, // 2km * 0.15€/km - "driver": {Amount: 0.9, Currency: "EUR"}, // 3km * 0.30€/km + "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, }, @@ -183,8 +286,9 @@ func TestMMS43PricingEdgeCases(t *testing.T) { pricingService, err := NewMMS43PricingService() assert.NoError(t, err) - t.Run("Negative history should still work", func(t *testing.T) { + 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 }, @@ -201,8 +305,28 @@ func TestMMS43PricingEdgeCases(t *testing.T) { assert.InDelta(t, 3.0, prices["driver"].Amount, 0.001) }) - t.Run("Very high history", func(t *testing.T) { + 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, }, @@ -218,5 +342,24 @@ func TestMMS43PricingEdgeCases(t *testing.T) { 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 + }) }