Skip to content

Commit

Permalink
Merge pull request #14204 from transcom/B-21393V2-Integration
Browse files Browse the repository at this point in the history
B-21393 Integration Follow Up
  • Loading branch information
ajlusk authored Nov 25, 2024
2 parents 462587b + f72a3a7 commit 56f77b1
Show file tree
Hide file tree
Showing 8 changed files with 238 additions and 160 deletions.
10 changes: 10 additions & 0 deletions pkg/factory/ppm_shipment_factory.go
Original file line number Diff line number Diff line change
Expand Up @@ -572,6 +572,16 @@ func BuildPPMShipmentThatNeedsCloseout(db *pop.Connection, userUploader *uploade

ppmShipment.SignedCertification = &signedCert

if ppmShipment.AllowableWeight == nil {
var allowableWeight = unit.Pound(0)
if len(ppmShipment.WeightTickets) >= 1 {
for _, weightTicket := range ppmShipment.WeightTickets {
allowableWeight += *weightTicket.FullWeight - *weightTicket.EmptyWeight
}
}
ppmShipment.AllowableWeight = &allowableWeight
}

ppmShipment.Status = models.PPMShipmentStatusNeedsCloseout
if ppmShipment.SubmittedAt == nil {
ppmShipment.SubmittedAt = models.TimePointer(time.Now())
Expand Down
14 changes: 7 additions & 7 deletions pkg/handlers/ghcapi/ppm_closeout.go
Original file line number Diff line number Diff line change
Expand Up @@ -69,7 +69,7 @@ type GetPPMActualWeightHandler struct {
ppmShipmentFetcher services.PPMShipmentFetcher
}

// Handle retrieves all calcuations for a PPM closeout
// Handle retrieves actual weight for a PPM pending closeout
func (h GetPPMActualWeightHandler) Handle(params ppmcloseoutops.GetPPMActualWeightParams) middleware.Responder {
return h.AuditableAppContextFromRequestWithErrors(params.HTTPRequest,
func(appCtx appcontext.AppContext) (middleware.Responder, error) {
Expand All @@ -79,23 +79,23 @@ func (h GetPPMActualWeightHandler) Handle(params ppmcloseoutops.GetPPMActualWeig
payload := &ghcmessages.Error{Message: handlers.FmtString(err.Error())}
switch err.(type) {
case apperror.NotFoundError:
return ppmcloseoutops.NewGetPPMCloseoutNotFound().WithPayload(payload), err
return ppmcloseoutops.NewGetPPMActualWeightNotFound().WithPayload(payload), err
case apperror.PPMNotReadyForCloseoutError:
return ppmcloseoutops.NewGetPPMCloseoutNotFound().WithPayload(payload), err
return ppmcloseoutops.NewGetPPMActualWeightNotFound().WithPayload(payload), err
case apperror.ForbiddenError:
return ppmcloseoutops.NewGetPPMCloseoutForbidden().WithPayload(payload), err
return ppmcloseoutops.NewGetPPMActualWeightForbidden().WithPayload(payload), err
case apperror.QueryError:
return ppmcloseoutops.NewGetPPMCloseoutInternalServerError().WithPayload(payload), err
return ppmcloseoutops.NewGetPPMActualWeightInternalServerError().WithPayload(payload), err
default:
return ppmcloseoutops.NewGetPPMCloseoutInternalServerError().WithPayload(payload), err
return ppmcloseoutops.NewGetPPMActualWeightInternalServerError().WithPayload(payload), err
}
}
errInstance := fmt.Sprintf("Instance: %s", h.GetTraceIDFromRequest(params.HTTPRequest))

errPayload := &ghcmessages.Error{Message: &errInstance}

if !appCtx.Session().IsOfficeApp() {
return ppmcloseoutops.NewGetPPMCloseoutForbidden().WithPayload(errPayload), apperror.NewSessionError("Request should come from the office app.")
return ppmcloseoutops.NewGetPPMActualWeightForbidden().WithPayload(errPayload), apperror.NewSessionError("Request should come from the office app.")
}
ppmShipmentID := uuid.FromStringOrNil(params.PpmShipmentID.String())

Expand Down
6 changes: 5 additions & 1 deletion pkg/services/ppm_closeout/ppm_closeout.go
Original file line number Diff line number Diff line change
Expand Up @@ -92,7 +92,7 @@ func (p *ppmCloseoutFetcher) GetPPMCloseout(appCtx appcontext.AppContext, ppmShi

fullWeightGCCShipment := ppmShipment

// Set pro gear werights for the GCC calculation to the max allowed before calculating GCC price
// Set pro gear weights for the GCC calculation to the max allowed before calculating GCC price
fullWeightGCCShipment.ProGearWeight = &proGearCustomerMax
fullWeightGCCShipment.SpouseProGearWeight = &proGearSpouseMax
gcc, _ := p.calculateGCC(appCtx, *fullWeightGCCShipment, fullAllowableWeight)
Expand Down Expand Up @@ -351,6 +351,10 @@ func (p *ppmCloseoutFetcher) getServiceItemPrices(appCtx appcontext.AppContext,
}
}

if ppmShipment.AllowableWeight != nil && *ppmShipment.AllowableWeight < totalWeight {
totalWeight = *ppmShipment.AllowableWeight
}

if totalWeight > 0 {
// Reassign ppm shipment fields to their expected location on the mto shipment for dates, addresses, weights ...
ppmToMtoShipment = ppmshipment.MapPPMShipmentFinalFields(ppmShipment, totalWeight)
Expand Down
89 changes: 89 additions & 0 deletions pkg/services/ppm_closeout/ppm_closeout_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -396,6 +396,39 @@ func (suite *PPMCloseoutSuite) TestPPMShipmentCreator() {
appCtx.Logger().Debug("+%v", zap.Error(err))
suite.IsType(err, apperror.PPMNotReadyForCloseoutError{})
})

suite.Run("Can successfully GET a PPMCloseout Object when the allowable weight is less than the net weight", func() {
// Under test: GetPPMCloseout
// Set up: Established ZIPs, ReServices, and all pricing data
// Expected: PPMCloseout Object successfully retrieved
appCtx := suite.AppContextForTest()

mockedPlanner.On("ZipTransitDistance", mock.AnythingOfType("*appcontext.appContext"),
"50309", "30813").Return(2294, nil)

mockedPaymentRequestHelper.On(
"FetchServiceParamsForServiceItems",
mock.AnythingOfType("*appcontext.appContext"),
mock.AnythingOfType("[]models.MTOServiceItem")).Return(serviceParams, nil)

mockIncentiveValue := unit.Cents(100000)
mockPpmEstimator.On(
"FinalIncentiveWithDefaultChecks",
mock.AnythingOfType("*appcontext.appContext"),
mock.AnythingOfType("models.PPMShipment"),
mock.AnythingOfType("*models.PPMShipment")).Return(&mockIncentiveValue, nil)

ppmShipment := suite.mockPPMShipmentForCloseoutWithAllowableWeightTest()

ppmCloseoutObj, err := ppmCloseoutFetcher.GetPPMCloseout(appCtx, ppmShipment.ID)
if err != nil {
appCtx.Logger().Error("Error getting PPM closeout object: ", zap.Error(err))
}

suite.Nil(err)
suite.NotNil(ppmCloseoutObj)
suite.NotEmpty(ppmCloseoutObj)
})
}

func mockServiceParamsTables() models.ServiceParams {
Expand Down Expand Up @@ -606,3 +639,59 @@ func (suite *PPMCloseoutSuite) mockPPMShipmentForCloseoutTest(buildType ppmBuild

return ppmShipment
}

func (suite *PPMCloseoutSuite) mockPPMShipmentForCloseoutWithAllowableWeightTest() models.PPMShipment {
ppmID, _ := uuid.FromString("00000000-0000-0000-0000-000000000000")
estWeight := unit.Pound(2000)
actualMoveDate := time.Now()
expectedDepartureDate := &actualMoveDate
miles := unit.Miles(200)
emptyWeight1 := unit.Pound(1000)
emptyWeight2 := unit.Pound(1500)
fullWeight1 := unit.Pound(7000)
fullWeight2 := unit.Pound(4500) // Net weight sums to 9000
finalIncentive := unit.Cents(20000)
allowableWeight := unit.Pound(8000)

weightTickets := models.WeightTickets{
models.WeightTicket{
EmptyWeight: &emptyWeight1,
FullWeight: &fullWeight1,
},
models.WeightTicket{
EmptyWeight: &emptyWeight2,
FullWeight: &fullWeight2,
},
}

sitDaysAllowance := 20
sitLocation := models.SITLocationTypeOrigin
date := time.Now()

ppmShipmentCustomization := []factory.Customization{
{
Model: models.MTOShipment{
Distance: &miles,
SITDaysAllowance: &sitDaysAllowance,
},
},
{
Model: models.PPMShipment{
ID: ppmID,
ExpectedDepartureDate: *expectedDepartureDate,
ActualMoveDate: &actualMoveDate,
EstimatedWeight: &estWeight,
WeightTickets: weightTickets,
FinalIncentive: &finalIncentive,
SITLocation: &sitLocation,
SITEstimatedEntryDate: &date,
SITEstimatedDepartureDate: &date,
AllowableWeight: &allowableWeight,
},
},
}

ppmShipment := factory.BuildPPMShipmentThatNeedsCloseout(suite.AppContextForTest().DB(), nil, ppmShipmentCustomization)

return ppmShipment
}
4 changes: 4 additions & 0 deletions pkg/services/ppmshipment/ppm_estimator.go
Original file line number Diff line number Diff line change
Expand Up @@ -258,6 +258,10 @@ func (f *estimatePPM) finalIncentive(appCtx appcontext.AppContext, oldPPMShipmen
}
originalTotalWeight, newTotalWeight := SumWeightTickets(oldPPMShipment, *newPPMShipment)

if newPPMShipment.AllowableWeight != nil && *newPPMShipment.AllowableWeight < newTotalWeight {
newTotalWeight = *newPPMShipment.AllowableWeight
}

isMissingInfo := shouldSetFinalIncentiveToNil(newPPMShipment, newTotalWeight)
var skipCalculateFinalIncentive bool
finalIncentive := oldPPMShipment.FinalIncentive
Expand Down
104 changes: 104 additions & 0 deletions pkg/services/ppmshipment/ppm_estimator_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -674,6 +674,7 @@ func (suite *PPMShipmentSuite) TestPPMEstimator() {

suite.Run("Final Incentive", func() {
actualMoveDate := time.Date(2020, time.March, 14, 0, 0, 0, 0, time.UTC)

suite.Run("Final Incentive - Success", func() {
setupPricerData()
weightOverride := unit.Pound(19500)
Expand Down Expand Up @@ -726,6 +727,109 @@ func (suite *PPMShipmentSuite) TestPPMEstimator() {
suite.Equal(unit.Cents(70064364), *ppmFinal)
})

suite.Run("Final Incentive - Success with allowable weight less than net weight", func() {
setupPricerData()
weightOverride := unit.Pound(19500)
oldPPMShipment := factory.BuildPPMShipment(suite.DB(), []factory.Customization{
{
Model: models.PPMShipment{
ActualPickupPostalCode: models.StringPointer("50309"),
ActualDestinationPostalCode: models.StringPointer("30813"),
ActualMoveDate: models.TimePointer(actualMoveDate),
Status: models.PPMShipmentStatusWaitingOnCustomer,
},
},
}, []factory.Trait{factory.GetTraitApprovedPPMWithActualInfo})

oldPPMShipment.WeightTickets = models.WeightTickets{
factory.BuildWeightTicket(suite.DB(), []factory.Customization{
{
Model: models.WeightTicket{
FullWeight: &weightOverride,
},
},
}, nil),
}

newPPM := oldPPMShipment
updatedMoveDate := time.Date(2020, time.March, 15, 0, 0, 0, 0, time.UTC)
newPPM.ActualMoveDate = models.TimePointer(updatedMoveDate)

mockedPaymentRequestHelper.On(
"FetchServiceParamsForServiceItems",
mock.AnythingOfType("*appcontext.appContext"),
mock.AnythingOfType("[]models.MTOServiceItem")).Return(serviceParams, nil)

// DTOD distance is going to be less than the HHG Rand McNally distance of 2361 miles
mockedPlanner.On("ZipTransitDistance", mock.AnythingOfType("*appcontext.appContext"), "50309", "30813").Return(2294, nil)

ppmFinal, err := ppmEstimator.FinalIncentiveWithDefaultChecks(suite.AppContextForTest(), oldPPMShipment, &newPPM)
suite.NilOrNoVerrs(err)

mockedPlanner.AssertCalled(suite.T(), "ZipTransitDistance", mock.AnythingOfType("*appcontext.appContext"), "50309", "30813")
mockedPaymentRequestHelper.AssertCalled(suite.T(), "FetchServiceParamsForServiceItems", mock.AnythingOfType("*appcontext.appContext"), mock.AnythingOfType("[]models.MTOServiceItem"))

suite.Equal(oldPPMShipment.ActualPickupPostalCode, newPPM.ActualPickupPostalCode)
suite.NotEqual(*oldPPMShipment.ActualMoveDate, newPPM.ActualMoveDate)
originalWeight, newWeight := SumWeightTickets(oldPPMShipment, newPPM)
suite.Equal(unit.Pound(5000), originalWeight)
suite.Equal(unit.Pound(5000), newWeight)
suite.Equal(unit.Cents(70064364), *ppmFinal)

// Repeat the above shipment with an allowable weight less than the net weight
weightOverride = unit.Pound(19500)
allowableWeightOverride := unit.Pound(4000)
oldPPMShipment = factory.BuildPPMShipment(suite.DB(), []factory.Customization{
{
Model: models.PPMShipment{
ActualPickupPostalCode: models.StringPointer("50309"),
ActualDestinationPostalCode: models.StringPointer("30813"),
ActualMoveDate: models.TimePointer(actualMoveDate),
Status: models.PPMShipmentStatusWaitingOnCustomer,
AllowableWeight: &allowableWeightOverride,
},
},
}, []factory.Trait{factory.GetTraitApprovedPPMWithActualInfo})

oldPPMShipment.WeightTickets = models.WeightTickets{
factory.BuildWeightTicket(suite.DB(), []factory.Customization{
{
Model: models.WeightTicket{
FullWeight: &weightOverride,
},
},
}, nil),
}

newPPM = oldPPMShipment
updatedMoveDate = time.Date(2020, time.March, 15, 0, 0, 0, 0, time.UTC)
newPPM.ActualMoveDate = models.TimePointer(updatedMoveDate)

mockedPaymentRequestHelper.On(
"FetchServiceParamsForServiceItems",
mock.AnythingOfType("*appcontext.appContext"),
mock.AnythingOfType("[]models.MTOServiceItem")).Return(serviceParams, nil)

// DTOD distance is going to be less than the HHG Rand McNally distance of 2361 miles
mockedPlanner.On("ZipTransitDistance", mock.AnythingOfType("*appcontext.appContext"),
"50309", "30813").Return(2294, nil)

ppmFinalIncentiveLimitedByAllowableWeight, err := ppmEstimator.FinalIncentiveWithDefaultChecks(suite.AppContextForTest(), oldPPMShipment, &newPPM)
suite.NilOrNoVerrs(err)

mockedPlanner.AssertCalled(suite.T(), "ZipTransitDistance", mock.AnythingOfType("*appcontext.appContext"), "50309", "30813")
mockedPaymentRequestHelper.AssertCalled(suite.T(), "FetchServiceParamsForServiceItems", mock.AnythingOfType("*appcontext.appContext"), mock.AnythingOfType("[]models.MTOServiceItem"))

suite.Equal(oldPPMShipment.ActualPickupPostalCode, newPPM.ActualPickupPostalCode)
suite.NotEqual(*oldPPMShipment.ActualMoveDate, newPPM.ActualMoveDate)
originalWeight, newWeight = SumWeightTickets(oldPPMShipment, newPPM)
suite.Equal(unit.Pound(5000), originalWeight)
suite.Equal(unit.Pound(5000), newWeight)

// Confirm the incentive is less than if all of the weight was allowable
suite.Less(*ppmFinalIncentiveLimitedByAllowableWeight, *ppmFinal)
})

suite.Run("Final Incentive - Success with updated weights", func() {
setupPricerData()
moveDate := time.Date(2020, time.March, 15, 0, 0, 0, 0, time.UTC)
Expand Down
8 changes: 8 additions & 0 deletions pkg/testdatagen/scenario/shared.go
Original file line number Diff line number Diff line change
Expand Up @@ -1366,6 +1366,7 @@ func createApprovedMoveWithPPMCloseoutComplete(appCtx appcontext.AppContext, use
approvedAt := time.Date(2022, 4, 15, 12, 30, 0, 0, time.UTC)
address := factory.BuildAddress(appCtx.DB(), nil, nil)
approvedAdvanceStatus := models.PPMAdvanceStatusApproved
allowableWeight := unit.Pound(4000)

assertions := testdatagen.Assertions{
UserUploader: userUploader,
Expand All @@ -1388,6 +1389,7 @@ func createApprovedMoveWithPPMCloseoutComplete(appCtx appcontext.AppContext, use
HasReceivedAdvance: models.BoolPointer(true),
AdvanceAmountReceived: models.CentPointer(unit.Cents(340000)),
W2Address: &address,
AllowableWeight: &allowableWeight,
},
}

Expand Down Expand Up @@ -1426,6 +1428,7 @@ func createApprovedMoveWithPPMCloseoutCompleteMultipleWeightTickets(appCtx appco
approvedAt := time.Date(2022, 4, 15, 12, 30, 0, 0, time.UTC)
address := factory.BuildAddress(appCtx.DB(), nil, nil)
approvedAdvanceStatus := models.PPMAdvanceStatusApproved
allowableWeight := unit.Pound(8000)

assertions := testdatagen.Assertions{
UserUploader: userUploader,
Expand All @@ -1448,6 +1451,7 @@ func createApprovedMoveWithPPMCloseoutCompleteMultipleWeightTickets(appCtx appco
HasReceivedAdvance: models.BoolPointer(true),
AdvanceAmountReceived: models.CentPointer(unit.Cents(340000)),
W2Address: &address,
AllowableWeight: &allowableWeight,
},
}

Expand Down Expand Up @@ -1504,6 +1508,7 @@ func createApprovedMoveWithPPMCloseoutCompleteWithExpenses(appCtx appcontext.App
approvedAt := time.Date(2022, 4, 15, 12, 30, 0, 0, time.UTC)
address := factory.BuildAddress(appCtx.DB(), nil, nil)
approvedAdvanceStatus := models.PPMAdvanceStatusApproved
allowableWeight := unit.Pound(4000)

assertions := testdatagen.Assertions{
UserUploader: userUploader,
Expand All @@ -1526,6 +1531,7 @@ func createApprovedMoveWithPPMCloseoutCompleteWithExpenses(appCtx appcontext.App
HasReceivedAdvance: models.BoolPointer(true),
AdvanceAmountReceived: models.CentPointer(unit.Cents(340000)),
W2Address: &address,
AllowableWeight: &allowableWeight,
},
}

Expand Down Expand Up @@ -1595,6 +1601,7 @@ func createApprovedMoveWithPPMCloseoutCompleteWithAllDocTypes(appCtx appcontext.
approvedAt := time.Date(2022, 4, 15, 12, 30, 0, 0, time.UTC)
address := factory.BuildAddress(appCtx.DB(), nil, nil)
approvedAdvanceStatus := models.PPMAdvanceStatusApproved
allowableWeight := unit.Pound(4000)

assertions := testdatagen.Assertions{
UserUploader: userUploader,
Expand All @@ -1617,6 +1624,7 @@ func createApprovedMoveWithPPMCloseoutCompleteWithAllDocTypes(appCtx appcontext.
HasReceivedAdvance: models.BoolPointer(true),
AdvanceAmountReceived: models.CentPointer(unit.Cents(340000)),
W2Address: &address,
AllowableWeight: &allowableWeight,
},
}

Expand Down
Loading

0 comments on commit 56f77b1

Please sign in to comment.