diff --git a/pkg/services/move/move_router.go b/pkg/services/move/move_router.go index 9b3ccc44d49..b1012865aa6 100644 --- a/pkg/services/move/move_router.go +++ b/pkg/services/move/move_router.go @@ -212,7 +212,13 @@ func (router moveRouter) sendToServiceCounselor(appCtx appcontext.AppContext, mo move.MTOShipments[i].Status = models.MTOShipmentStatusSubmitted if verrs, err := appCtx.DB().ValidateAndUpdate(&move.MTOShipments[i]); verrs.HasAny() || err != nil { - msg := "failure saving shipment when routing move submission" + msg := "failure saving parent MTO shipment object for boat shipment when routing move submission" + appCtx.Logger().Error(msg, zap.Error(err)) + return apperror.NewInvalidInputError(move.MTOShipments[i].ID, err, verrs, msg) + } + + if verrs, err := appCtx.DB().ValidateAndUpdate(move.MTOShipments[i].BoatShipment); verrs.HasAny() || err != nil { + msg := "failure saving boat shipment when routing move submission" appCtx.Logger().Error(msg, zap.Error(err)) return apperror.NewInvalidInputError(move.MTOShipments[i].ID, err, verrs, msg) } @@ -222,19 +228,24 @@ func (router moveRouter) sendToServiceCounselor(appCtx appcontext.AppContext, mo move.MTOShipments[i].Status = models.MTOShipmentStatusSubmitted if verrs, err := appCtx.DB().ValidateAndUpdate(&move.MTOShipments[i]); verrs.HasAny() || err != nil { - msg := "failure saving shipment when routing move submission" + msg := "failure saving parent MTO shipment object for mobile home shipment when routing move submission" + appCtx.Logger().Error(msg, zap.Error(err)) + return apperror.NewInvalidInputError(move.MTOShipments[i].ID, err, verrs, msg) + } + + if verrs, err := appCtx.DB().ValidateAndUpdate(move.MTOShipments[i].MobileHome); verrs.HasAny() || err != nil { + msg := "failure saving mobile home shipment when routing move submission" appCtx.Logger().Error(msg, zap.Error(err)) return apperror.NewInvalidInputError(move.MTOShipments[i].ID, err, verrs, msg) } } - } - if verrs, err := appCtx.DB().ValidateAndSave(move); verrs.HasAny() || err != nil { - msg := "failure saving move when routing move submission" - appCtx.Logger().Error(msg, zap.Error(err)) - return apperror.NewInvalidInputError(move.ID, err, verrs, msg) + if verrs, err := appCtx.DB().ValidateAndSave(move); verrs.HasAny() || err != nil { + msg := "failure saving move when routing move submission" + appCtx.Logger().Error(msg, zap.Error(err)) + return apperror.NewInvalidInputError(move.ID, err, verrs, msg) + } } - return nil } diff --git a/pkg/services/move/move_router_test.go b/pkg/services/move/move_router_test.go index 945a65d6033..f897d239329 100644 --- a/pkg/services/move/move_router_test.go +++ b/pkg/services/move/move_router_test.go @@ -296,32 +296,6 @@ func (suite *MoveServiceSuite) TestMoveSubmission() { }, }, nil) - boatMTOSHipment := factory.BuildMTOShipmentMinimal(suite.DB(), []factory.Customization{ - { - Model: models.MTOShipment{ - Status: models.MTOShipmentStatusDraft, - ShipmentType: models.MTOShipmentTypeBoatHaulAway, - }, - }, - { - Model: move, - LinkOnly: true, - }, - }, nil) - - mobileHomeMTOShipment := factory.BuildMTOShipmentMinimal(suite.DB(), []factory.Customization{ - { - Model: models.MTOShipment{ - Status: models.MTOShipmentStatusDraft, - ShipmentType: models.MTOShipmentTypeMobileHome, - }, - }, - { - Model: move, - LinkOnly: true, - }, - }, nil) - ppmShipment := factory.BuildPPMShipment(suite.DB(), []factory.Customization{ { Model: models.PPMShipment{ @@ -342,7 +316,7 @@ func (suite *MoveServiceSuite) TestMoveSubmission() { }, }, nil) - move.MTOShipments = models.MTOShipments{shipment, boatMTOSHipment, mobileHomeMTOShipment} + move.MTOShipments = models.MTOShipments{shipment} move.MTOShipments[0].PPMShipment = &ppmShipment move.MTOShipments[0].BoatShipment = &boatShipment move.MTOShipments[0].MobileHome = &mobileHomeShipment @@ -439,6 +413,203 @@ func (suite *MoveServiceSuite) TestMoveSubmission() { suite.Equal(models.PPMShipmentStatusSubmitted, move.MTOShipments[0].PPMShipment.Status, "expected Submitted") }) + suite.Run("returns an error when a Mobile Home Shipment is not formatted correctly", func() { + // Under test: MoveRouter.Submit + // Set up: Submit a move without a mobile home shipment that has a field that will not pass validation + // Expected outcome: Error on DB().ValidateAndUpdate + move := factory.BuildMove(suite.DB(), []factory.Customization{ + { + Model: models.DutyLocation{ + ProvidesServicesCounseling: true, + }, + Type: &factory.DutyLocations.OriginDutyLocation, + }, + }, nil) + hhgShipment := factory.BuildMTOShipmentMinimal(suite.DB(), []factory.Customization{ + { + Model: models.MTOShipment{ + Status: models.MTOShipmentStatusDraft, + ShipmentType: models.MTOShipmentTypeMobileHome, + }, + }, + { + Model: move, + LinkOnly: true, + }, + }, nil) + + year := -10000 + mobileHomeShipment := factory.BuildMobileHomeShipment(suite.DB(), []factory.Customization{ + { + Model: models.MobileHome{}, + }, + }, nil) + mobileHomeShipment.Year = &year + move.MTOShipments = models.MTOShipments{hhgShipment} + move.MTOShipments[0].MobileHome = &mobileHomeShipment + newSignedCertification := factory.BuildSignedCertification(nil, []factory.Customization{ + { + Model: move, + LinkOnly: true, + }, + }, nil) + err := moveRouter.Submit(suite.AppContextForTest(), &move, &newSignedCertification) + + suite.Error(err) + suite.Contains(err.Error(), "failure saving mobile home shipment when routing move submission") + suite.Equal(models.MoveStatusNeedsServiceCounseling, move.Status, "expected move to still be in NEEDS_SERVICE_COUNSELING status when routing has failed") + }) + + suite.Run("returns an error when a Mobile Home Shipment is not formatted correctly", func() { + // Under test: MoveRouter.Submit + // Set up: Submit a move without a mobile home shipment that has a field that will not pass validation + // Expected outcome: Error on DB().ValidateAndUpdate + move := factory.BuildMove(suite.DB(), []factory.Customization{ + { + Model: models.DutyLocation{ + ProvidesServicesCounseling: true, + }, + Type: &factory.DutyLocations.OriginDutyLocation, + }, + }, nil) + hhgShipment := factory.BuildMTOShipmentMinimal(suite.DB(), []factory.Customization{ + { + Model: models.MTOShipment{ + Status: models.MTOShipmentStatusDraft, + ShipmentType: models.MTOShipmentTypeBoatHaulAway, + }, + }, + { + Model: move, + LinkOnly: true, + }, + }, nil) + + year := -10000 + boatShipment := factory.BuildBoatShipment(suite.DB(), []factory.Customization{ + { + Model: models.BoatShipment{}, + }, + }, nil) + boatShipment.Year = &year + move.MTOShipments = models.MTOShipments{hhgShipment} + move.MTOShipments[0].BoatShipment = &boatShipment + newSignedCertification := factory.BuildSignedCertification(nil, []factory.Customization{ + { + Model: move, + LinkOnly: true, + }, + }, nil) + err := moveRouter.Submit(suite.AppContextForTest(), &move, &newSignedCertification) + + suite.Error(err) + suite.Contains(err.Error(), "failure saving boat shipment when routing move submission") + suite.Equal(models.MoveStatusNeedsServiceCounseling, move.Status, "expected move to still be in NEEDS_SERVICE_COUNSELING status when routing has failed") + }) + + suite.Run("returns validation errors when a the parent MTO Shipment object for a Mobile Home Shipment is not formatted correctly", func() { + // Under test: MoveRouter.Submit + // Set up: Submit a move without a mobile home shipment that has a field that will not pass validation + // Expected outcome: Error on DB().ValidateAndUpdate + + sitDaysAllowance := -1 // Invalid value that should cause a validation error on MTOShipment + + expError := "failure saving parent MTO shipment object for mobile home shipment when routing move submission" + + move := factory.BuildMove(suite.DB(), []factory.Customization{ + { + Model: models.DutyLocation{ + ProvidesServicesCounseling: true, + }, + Type: &factory.DutyLocations.OriginDutyLocation, + }, + }, nil) + hhgShipment := factory.BuildMTOShipmentMinimal(suite.DB(), []factory.Customization{ + { + Model: models.MTOShipment{ + Status: models.MTOShipmentStatusDraft, + ShipmentType: models.MTOShipmentTypeMobileHome, + }, + }, + { + Model: move, + LinkOnly: true, + }, + }, nil) + + hhgShipment.SITDaysAllowance = &sitDaysAllowance + + mobileHomeShipment := factory.BuildMobileHomeShipment(suite.DB(), []factory.Customization{ + { + Model: models.MobileHome{}, + }, + }, nil) + move.MTOShipments = models.MTOShipments{hhgShipment} + move.MTOShipments[0].MobileHome = &mobileHomeShipment + newSignedCertification := factory.BuildSignedCertification(nil, []factory.Customization{ + { + Model: move, + LinkOnly: true, + }, + }, nil) + err := moveRouter.Submit(suite.AppContextForTest(), &move, &newSignedCertification) + + suite.Error(err) + suite.Contains(err.Error(), expError) + suite.Equal(models.MoveStatusNeedsServiceCounseling, move.Status, "expected move to still be in NEEDS_SERVICE_COUNSELING status when routing has failed") + }) + + suite.Run("returns validation errors when a the parent MTO Shipment object for a Boat Shipment is not formatted correctly", func() { + // Under test: MoveRouter.Submit + // Set up: Submit a move without a mobile home shipment that has a field that will not pass validation + // Expected outcome: Error on DB().ValidateAndUpdate + + sitDaysAllowance := -1 // Invalid value that should cause a validation error on MTOShipment + + expError := "failure saving parent MTO shipment object for boat shipment when routing move submission" + + move := factory.BuildMove(suite.DB(), []factory.Customization{ + { + Model: models.DutyLocation{ + ProvidesServicesCounseling: true, + }, + Type: &factory.DutyLocations.OriginDutyLocation, + }, + }, nil) + hhgShipment := factory.BuildMTOShipmentMinimal(suite.DB(), []factory.Customization{ + { + Model: models.MTOShipment{ + Status: models.MTOShipmentStatusDraft, + ShipmentType: models.MTOShipmentTypeBoatHaulAway, + }, + }, + { + Model: move, + LinkOnly: true, + }, + }, nil) + + hhgShipment.SITDaysAllowance = &sitDaysAllowance + + boatShipment := factory.BuildBoatShipment(suite.DB(), []factory.Customization{ + { + Model: models.BoatShipment{}, + }, + }, nil) + move.MTOShipments = models.MTOShipments{hhgShipment} + move.MTOShipments[0].BoatShipment = &boatShipment + newSignedCertification := factory.BuildSignedCertification(nil, []factory.Customization{ + { + Model: move, + LinkOnly: true, + }, + }, nil) + err := moveRouter.Submit(suite.AppContextForTest(), &move, &newSignedCertification) + + suite.Error(err) + suite.Contains(err.Error(), expError) + suite.Equal(models.MoveStatusNeedsServiceCounseling, move.Status, "expected move to still be in NEEDS_SERVICE_COUNSELING status when routing has failed") + }) } func (suite *MoveServiceSuite) TestMoveCancellation() {