Skip to content

Commit

Permalink
Merge pull request #14874 from transcom/MAIN-B-22769
Browse files Browse the repository at this point in the history
MAIN B-22769
  • Loading branch information
deandreJones authored Feb 28, 2025
2 parents e6e80e5 + 069057c commit df502ed
Show file tree
Hide file tree
Showing 7 changed files with 75 additions and 25 deletions.
2 changes: 1 addition & 1 deletion pkg/services/ghc_rate_engine.go
Original file line number Diff line number Diff line change
Expand Up @@ -57,7 +57,7 @@ type DomesticLinehaulPricer interface {
//
//go:generate mockery --name DomesticShorthaulPricer
type DomesticShorthaulPricer interface {
Price(appCtx appcontext.AppContext, contractCode string, requestedPickupDate time.Time, distance unit.Miles, weight unit.Pound, serviceArea string) (unit.Cents, PricingDisplayParams, error)
Price(appCtx appcontext.AppContext, contractCode string, requestedPickupDate time.Time, distance unit.Miles, weight unit.Pound, serviceArea string, isPPM bool) (unit.Cents, PricingDisplayParams, error)
ParamsPricer
}

Expand Down
15 changes: 12 additions & 3 deletions pkg/services/ghcrateengine/domestic_shorthaul_pricer.go
Original file line number Diff line number Diff line change
Expand Up @@ -28,15 +28,16 @@ func (p domesticShorthaulPricer) Price(appCtx appcontext.AppContext, contractCod
referenceDate time.Time,
distance unit.Miles,
weight unit.Pound,
serviceArea string) (totalCost unit.Cents, params services.PricingDisplayParams, err error) {
serviceArea string,
isPPM bool) (totalCost unit.Cents, params services.PricingDisplayParams, err error) {
// Validate parameters
if len(contractCode) == 0 {
return 0, nil, errors.New("ContractCode is required")
}
if referenceDate.IsZero() {
return 0, nil, errors.New("ReferenceDate is required")
}
if weight < minDomesticWeight {
if !isPPM && weight < minDomesticWeight {
return 0, nil, fmt.Errorf("Weight must be a minimum of %d", minDomesticWeight)
}
if distance <= 0 {
Expand Down Expand Up @@ -110,5 +111,13 @@ func (p domesticShorthaulPricer) PriceUsingParams(appCtx appcontext.AppContext,
return unit.Cents(0), nil, err
}

return p.Price(appCtx, contractCode, referenceDate, unit.Miles(distanceZip), unit.Pound(weightBilled), serviceAreaOrigin)
var isPPM = false
if params[0].PaymentServiceItem.MTOServiceItem.MTOShipment.ShipmentType == models.MTOShipmentTypePPM {
// PPMs do not require minimums for a shipment's weight or distance
// this flag is passed into the Price function to ensure the weight and distance mins
// are not enforced for PPMs
isPPM = true
}

return p.Price(appCtx, contractCode, referenceDate, unit.Miles(distanceZip), unit.Pound(weightBilled), serviceAreaOrigin, isPPM)
}
36 changes: 31 additions & 5 deletions pkg/services/ghcrateengine/domestic_shorthaul_pricer_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,8 @@ const (
dshTestMileage = 1200
)

var dshRequestedPickupDate = time.Date(testdatagen.TestYear, time.June, 5, 7, 33, 11, 456, time.UTC)

func (suite *GHCRateEngineServiceSuite) TestPriceDomesticShorthaulWithServiceItemParamsBadData() {
requestedPickup := time.Date(testdatagen.TestYear, peakStart.month, peakStart.day, 0, 0, 0, 0, time.UTC).Format(DateParamFormat)
pricer := NewDomesticShorthaulPricer()
Expand Down Expand Up @@ -120,6 +122,7 @@ func (suite *GHCRateEngineServiceSuite) TestPriceDomesticShorthaulWithServiceIte
}

func (suite *GHCRateEngineServiceSuite) TestPriceDomesticShorthaul() {
isPPM := false
suite.Run("success shorthaul cost within peak period", func() {
requestedPickup := time.Date(testdatagen.TestYear, peakStart.month, peakStart.day, 0, 0, 0, 0, time.UTC).Format(DateParamFormat)
suite.setUpDomesticShorthaulData()
Expand All @@ -135,6 +138,7 @@ func (suite *GHCRateEngineServiceSuite) TestPriceDomesticShorthaul() {
dshTestMileage,
dshTestWeight,
dshTestServiceArea,
isPPM,
)
expectedCost := unit.Cents(6566400)
suite.NoError(err)
Expand All @@ -158,6 +162,7 @@ func (suite *GHCRateEngineServiceSuite) TestPriceDomesticShorthaul() {
dshTestMileage,
dshTestWeight,
dshTestServiceArea,
isPPM,
)
expectedCost := unit.Cents(5702400)
suite.NoError(err)
Expand All @@ -176,6 +181,7 @@ func (suite *GHCRateEngineServiceSuite) TestPriceDomesticShorthaul() {
dshTestMileage,
dshTestWeight,
dshTestServiceArea,
isPPM,
)

suite.Error(err)
Expand All @@ -194,6 +200,7 @@ func (suite *GHCRateEngineServiceSuite) TestPriceDomesticShorthaul() {
dshTestMileage,
dshTestWeight,
dshTestServiceArea,
isPPM,
)

suite.Error(err)
Expand All @@ -212,45 +219,64 @@ func (suite *GHCRateEngineServiceSuite) TestPriceDomesticShorthaul() {
dshTestMileage,
unit.Pound(499),
dshTestServiceArea,
isPPM,
)
suite.Equal(unit.Cents(0), cost)
suite.Error(err)
suite.Equal("Weight must be a minimum of 500", err.Error())
suite.Nil(rateEngineParams)
})

suite.Run("successfully finds shorthaul price for ppm with weight < 500 lbs with Price method", func() {
suite.setUpDomesticShorthaulData()
pricer := NewDomesticShorthaulPricer()
isPPM = true
// the PPM price for weights < 500 should be prorated from a base of 500
basePriceCents, _, err := pricer.Price(suite.AppContextForTest(), testdatagen.DefaultContractCode, dshRequestedPickupDate, dshTestMileage, unit.Pound(500), dshTestServiceArea, isPPM)
suite.NoError(err)

halfPriceCents, _, err := pricer.Price(suite.AppContextForTest(), testdatagen.DefaultContractCode, dshRequestedPickupDate, dshTestMileage, unit.Pound(250), dshTestServiceArea, isPPM)
suite.NoError(err)
suite.Equal(basePriceCents/2, halfPriceCents)

fifthPriceCents, _, err := pricer.Price(suite.AppContextForTest(), testdatagen.DefaultContractCode, dshRequestedPickupDate, dshTestMileage, unit.Pound(100), dshTestServiceArea, isPPM)
suite.NoError(err)
suite.Equal(basePriceCents/5, fifthPriceCents)
isPPM = false
})

suite.Run("validation errors", func() {
suite.setUpDomesticShorthaulData()
pricer := NewDomesticShorthaulPricer()

requestedPickupDate := time.Date(testdatagen.TestYear, time.July, 4, 0, 0, 0, 0, time.UTC)

// No contract code
_, rateEngineParams, err := pricer.Price(suite.AppContextForTest(), "", requestedPickupDate, dshTestMileage, dshTestWeight, dshTestServiceArea)
_, rateEngineParams, err := pricer.Price(suite.AppContextForTest(), "", requestedPickupDate, dshTestMileage, dshTestWeight, dshTestServiceArea, isPPM)
suite.Error(err)
suite.Equal("ContractCode is required", err.Error())
suite.Nil(rateEngineParams)

// No reference date
_, rateEngineParams, err = pricer.Price(suite.AppContextForTest(), testdatagen.DefaultContractCode, time.Time{}, dshTestMileage, dshTestWeight, dshTestServiceArea)
_, rateEngineParams, err = pricer.Price(suite.AppContextForTest(), testdatagen.DefaultContractCode, time.Time{}, dshTestMileage, dshTestWeight, dshTestServiceArea, isPPM)
suite.Error(err)
suite.Equal("ReferenceDate is required", err.Error())
suite.Nil(rateEngineParams)

// No distance
_, rateEngineParams, err = pricer.Price(suite.AppContextForTest(), testdatagen.DefaultContractCode, requestedPickupDate, 0, dshTestWeight, dshTestServiceArea)
_, rateEngineParams, err = pricer.Price(suite.AppContextForTest(), testdatagen.DefaultContractCode, requestedPickupDate, 0, dshTestWeight, dshTestServiceArea, isPPM)
suite.Error(err)
suite.Equal("Distance must be greater than 0", err.Error())
suite.Nil(rateEngineParams)

// No weight
_, rateEngineParams, err = pricer.Price(suite.AppContextForTest(), testdatagen.DefaultContractCode, requestedPickupDate, dshTestMileage, 0, dshTestServiceArea)
_, rateEngineParams, err = pricer.Price(suite.AppContextForTest(), testdatagen.DefaultContractCode, requestedPickupDate, dshTestMileage, 0, dshTestServiceArea, isPPM)
suite.Error(err)
suite.Equal("Weight must be a minimum of 500", err.Error())
suite.Nil(rateEngineParams)

// No service area
_, rateEngineParams, err = pricer.Price(suite.AppContextForTest(), testdatagen.DefaultContractCode, requestedPickupDate, dshTestMileage, dshTestWeight, "")
_, rateEngineParams, err = pricer.Price(suite.AppContextForTest(), testdatagen.DefaultContractCode, requestedPickupDate, dshTestMileage, dshTestWeight, "", isPPM)
suite.Error(err)
suite.Equal("ServiceArea is required", err.Error())
suite.Nil(rateEngineParams)
Expand Down
3 changes: 2 additions & 1 deletion pkg/services/ghcrateengine/pricer_helpers.go
Original file line number Diff line number Diff line change
Expand Up @@ -267,7 +267,8 @@ func priceDomesticPickupDeliverySIT(appCtx appcontext.AppContext, pickupDelivery
if zip3Original == zip3Actual {
// Do a normal shorthaul calculation
shorthaulPricer := NewDomesticShorthaulPricer()
totalPriceCents, displayParams, err := shorthaulPricer.Price(appCtx, contractCode, referenceDate, distance, weight, serviceArea)
isPPM := false
totalPriceCents, displayParams, err := shorthaulPricer.Price(appCtx, contractCode, referenceDate, distance, weight, serviceArea, isPPM)
if err != nil {
return unit.Cents(0), nil, fmt.Errorf("could not price shorthaul: %w", err)
}
Expand Down
22 changes: 11 additions & 11 deletions pkg/services/mocks/DomesticShorthaulPricer.go

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

2 changes: 1 addition & 1 deletion pkg/services/mto_service_item/mto_service_item_creator.go
Original file line number Diff line number Diff line change
Expand Up @@ -152,7 +152,7 @@ func (o *mtoServiceItemCreator) FindEstimatedPrice(appCtx appcontext.AppContext,
return 0, err
}
}
price, _, err = o.shorthaulPricer.Price(appCtx, contractCode, requestedPickupDate, unit.Miles(distance), *adjustedWeight, domesticServiceArea.ServiceArea)
price, _, err = o.shorthaulPricer.Price(appCtx, contractCode, requestedPickupDate, unit.Miles(distance), *adjustedWeight, domesticServiceArea.ServiceArea, isPPM)
if err != nil {
return 0, err
}
Expand Down
20 changes: 17 additions & 3 deletions pkg/services/ppmshipment/ppm_estimator.go
Original file line number Diff line number Diff line change
Expand Up @@ -489,8 +489,16 @@ func (f estimatePPM) calculatePrice(appCtx appcontext.AppContext, ppmShipment *m
}
}

if pickupPostal[0:3] == destPostal[0:3] {
serviceItemsToPrice[0] = models.MTOServiceItem{ReService: models.ReService{Code: models.ReServiceCodeDSH}, MTOShipmentID: &ppmShipment.ShipmentID}
// if the ZIPs are the same, we need to replace the DLH service item with DSH
if len(pickupPostal) >= 3 && len(destPostal) >= 3 && pickupPostal[:3] == destPostal[:3] {
if pickupPostal[0:3] == destPostal[0:3] {
for i, serviceItem := range serviceItemsToPrice {
if serviceItem.ReService.Code == models.ReServiceCodeDLH {
serviceItemsToPrice[i] = models.MTOServiceItem{ReService: models.ReService{Code: models.ReServiceCodeDSH}, MTOShipmentID: &ppmShipment.ShipmentID}
break
}
}
}
}

// Get a list of all the pricing params needed to calculate the price for each service item
Expand Down Expand Up @@ -630,9 +638,15 @@ func (f estimatePPM) priceBreakdown(appCtx appcontext.AppContext, ppmShipment *m
destPostal = ppmShipment.DestinationAddress.PostalCode
}

// if the ZIPs are the same, we need to replace the DLH service item with DSH
if len(pickupPostal) >= 3 && len(destPostal) >= 3 && pickupPostal[:3] == destPostal[:3] {
if pickupPostal[0:3] == destPostal[0:3] {
serviceItemsToPrice[0] = models.MTOServiceItem{ReService: models.ReService{Code: models.ReServiceCodeDSH}, MTOShipmentID: &ppmShipment.ShipmentID}
for i, serviceItem := range serviceItemsToPrice {
if serviceItem.ReService.Code == models.ReServiceCodeDLH {
serviceItemsToPrice[i] = models.MTOServiceItem{ReService: models.ReService{Code: models.ReServiceCodeDSH}, MTOShipmentID: &ppmShipment.ShipmentID}
break
}
}
}
}

Expand Down

0 comments on commit df502ed

Please sign in to comment.