Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

MAIN B-22769 #14874

Merged
merged 4 commits into from
Feb 28, 2025
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
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.

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
Loading