diff --git a/pkg/handlers/primeapiv3/mto_shipment.go b/pkg/handlers/primeapiv3/mto_shipment.go index 5201f11f9ee..cddeeaab45b 100644 --- a/pkg/handlers/primeapiv3/mto_shipment.go +++ b/pkg/handlers/primeapiv3/mto_shipment.go @@ -109,7 +109,7 @@ func (h CreateMTOShipmentHandler) Handle(params mtoshipmentops.CreateMTOShipment appCtx.Logger().Error("Error validating mto shipment object: ", zap.Error(verrs)) return mtoshipmentops.NewCreateMTOShipmentUnprocessableEntity().WithPayload(payloads.ValidationError( - "The MTO shipment object is invalid.", h.GetTraceIDFromRequest(params.HTTPRequest), nil)), verrs + "The MTO shipment object is invalid. "+verrs.Error(), h.GetTraceIDFromRequest(params.HTTPRequest), nil)), verrs } mtoShipment.Status = models.MTOShipmentStatusSubmitted diff --git a/pkg/handlers/primeapiv3/mto_shipment_test.go b/pkg/handlers/primeapiv3/mto_shipment_test.go index c0443c77eb2..44c8f229e0d 100644 --- a/pkg/handlers/primeapiv3/mto_shipment_test.go +++ b/pkg/handlers/primeapiv3/mto_shipment_test.go @@ -1479,8 +1479,7 @@ func (suite *HandlerSuite) TestCreateMTOShipmentHandler() { suite.IsType(&mtoshipmentops.CreateMTOShipmentUnprocessableEntity{}, response) errResponse := response.(*mtoshipmentops.CreateMTOShipmentUnprocessableEntity) - suite.Contains(*errResponse.Payload.Detail, "Invalid input found while validating the PPM shipment.") - suite.Contains(errResponse.Payload.InvalidFields["error validating ppm shipment"][0], "Shipment cannot have a third address without a second address present") + suite.Contains(*errResponse.Payload.Detail, "The MTO shipment object is invalid. Shipment cannot have a third pickup address without a second pickup address present") }) suite.Run("POST failure - Error creating mto shipment containing a ppm shipment contains tertiary destination address no secondary destination address.", func() { @@ -1538,8 +1537,7 @@ func (suite *HandlerSuite) TestCreateMTOShipmentHandler() { suite.IsType(&mtoshipmentops.CreateMTOShipmentUnprocessableEntity{}, response) errResponse := response.(*mtoshipmentops.CreateMTOShipmentUnprocessableEntity) - suite.Contains(*errResponse.Payload.Detail, "Invalid input found while validating the PPM shipment.") - suite.Contains(errResponse.Payload.InvalidFields["error validating ppm shipment"][0], "Shipment cannot have a third address without a second address present") + suite.Contains(*errResponse.Payload.Detail, "The MTO shipment object is invalid. Shipment cannot have a third destination address without a second destination address present") }) suite.Run("PATCH failure - Error updating an mto shipment contains tertiary pickup address no secondary pickup address.", func() { // Under Test: UpdateMTOShipmentHandler diff --git a/pkg/handlers/primeapiv3/payloads/payload_to_model.go b/pkg/handlers/primeapiv3/payloads/payload_to_model.go index 7eb48d87ad7..aaa2a1a671e 100644 --- a/pkg/handlers/primeapiv3/payloads/payload_to_model.go +++ b/pkg/handlers/primeapiv3/payloads/payload_to_model.go @@ -262,8 +262,14 @@ func MTOShipmentModelFromCreate(mtoShipment *primev3messages.CreateMTOShipment) } if mtoShipment.PpmShipment != nil { - model.PPMShipment = PPMShipmentModelFromCreate(mtoShipment.PpmShipment) - model.PPMShipment.Shipment = *model + ppmShipment, err := PPMShipmentModelFromCreate(mtoShipment.PpmShipment) + if err != nil { + verrs.Add("mtoShipment", err.Error()) + return nil, verrs + } else { + model.PPMShipment = ppmShipment + model.PPMShipment.Shipment = *model + } } if mtoShipment.BoatShipment != nil { @@ -306,9 +312,10 @@ func ShipmentAddressUpdateModel(nonSITAddressUpdate *primev3messages.UpdateShipm } // PPMShipmentModelFromCreate model -func PPMShipmentModelFromCreate(ppmShipment *primev3messages.CreatePPMShipment) *models.PPMShipment { +func PPMShipmentModelFromCreate(ppmShipment *primev3messages.CreatePPMShipment) (*models.PPMShipment, *validate.Errors) { + verrs := validate.NewErrors() if ppmShipment == nil { - return nil + return nil, nil } model := &models.PPMShipment{ @@ -339,6 +346,10 @@ func PPMShipmentModelFromCreate(ppmShipment *primev3messages.CreatePPMShipment) addressModel = AddressModel(&ppmShipment.TertiaryPickupAddress.Address) if addressModel != nil { + if AddressModel(&ppmShipment.SecondaryPickupAddress.Address) == nil { + verrs.Add("ppmShipment", "Shipment cannot have a third pickup address without a second pickup address present") + return nil, verrs + } model.TertiaryPickupAddress = addressModel model.HasTertiaryPickupAddress = handlers.FmtBool(true) } @@ -356,6 +367,10 @@ func PPMShipmentModelFromCreate(ppmShipment *primev3messages.CreatePPMShipment) addressModel = AddressModel(&ppmShipment.TertiaryDestinationAddress.Address) if addressModel != nil { + if AddressModel(&ppmShipment.SecondaryDestinationAddress.Address) == nil { + verrs.Add("ppmShipment", "Shipment cannot have a third destination address without a second destination address present") + return nil, verrs + } model.TertiaryDestinationAddress = addressModel model.HasTertiaryDestinationAddress = handlers.FmtBool(true) } @@ -387,7 +402,7 @@ func PPMShipmentModelFromCreate(ppmShipment *primev3messages.CreatePPMShipment) model.IsActualExpenseReimbursement = ppmShipment.IsActualExpenseReimbursement } - return model + return model, nil } // BoatShipmentModelFromCreate model diff --git a/pkg/handlers/primeapiv3/payloads/payload_to_model_test.go b/pkg/handlers/primeapiv3/payloads/payload_to_model_test.go index 7d3ffd37cf1..9d9ff85041f 100644 --- a/pkg/handlers/primeapiv3/payloads/payload_to_model_test.go +++ b/pkg/handlers/primeapiv3/payloads/payload_to_model_test.go @@ -762,7 +762,7 @@ func (suite *PayloadsSuite) TestPPMShipmentModelFromCreate() { IsActualExpenseReimbursement: models.BoolPointer(true), } - model := PPMShipmentModelFromCreate(&ppmShipment) + model, _ := PPMShipmentModelFromCreate(&ppmShipment) suite.NotNil(model) suite.Equal(models.PPMShipmentStatusSubmitted, model.Status) @@ -1326,3 +1326,58 @@ func (suite *PayloadsSuite) TestPPMShipmentModelWithOptionalDestinationStreet1Fr model3 := PPMShipmentModelFromUpdate(&ppmShipmentValidDestinatonStreet1) suite.Equal(model3.DestinationAddress.StreetAddress1, streetAddress1) } + +func (suite *PayloadsSuite) TestPPMShipmentModelWithThirdDestinationWithoutSecond() { + time := time.Now() + expectedDepartureDate := handlers.FmtDatePtr(&time) + + address := models.Address{ + StreetAddress1: "some address", + City: "city", + State: "state", + PostalCode: "12345", + } + + var pickupAddress primev3messages.Address + var destinationAddress primev3messages.PPMDestinationAddress + var thirdDestinationAddress primev3messages.Address + + pickupAddress = primev3messages.Address{ + City: &address.City, + PostalCode: &address.PostalCode, + State: &address.State, + StreetAddress1: &address.StreetAddress1, + StreetAddress2: address.StreetAddress2, + StreetAddress3: address.StreetAddress3, + } + destinationAddress = primev3messages.PPMDestinationAddress{ + City: &address.City, + PostalCode: &address.PostalCode, + State: &address.State, + StreetAddress1: models.StringPointer(""), // empty string + StreetAddress2: address.StreetAddress2, + StreetAddress3: address.StreetAddress3, + } + thirdDestinationAddress = primev3messages.Address{ + City: &address.City, + PostalCode: &address.PostalCode, + State: &address.State, + StreetAddress1: models.StringPointer(""), // empty string + StreetAddress2: address.StreetAddress2, + StreetAddress3: address.StreetAddress3, + } + + ppmShipment := primev3messages.CreatePPMShipment{ + ExpectedDepartureDate: expectedDepartureDate, + PickupAddress: struct{ primev3messages.Address }{pickupAddress}, + DestinationAddress: struct { + primev3messages.PPMDestinationAddress + }{destinationAddress}, + TertiaryDestinationAddress: struct{ primev3messages.Address }{thirdDestinationAddress}, + } + + model, err := PPMShipmentModelFromCreate(&ppmShipment) + + suite.Error(err) + suite.Nil(model) +} diff --git a/src/components/Office/RequestedShipments/ApprovedRequestedShipments.jsx b/src/components/Office/RequestedShipments/ApprovedRequestedShipments.jsx index 236f4821ea1..1739daf26ac 100644 --- a/src/components/Office/RequestedShipments/ApprovedRequestedShipments.jsx +++ b/src/components/Office/RequestedShipments/ApprovedRequestedShipments.jsx @@ -89,6 +89,8 @@ const ApprovedRequestedShipments = ({ const [enableBoat, setEnableBoat] = useState(false); const [enableMobileHome, setEnableMobileHome] = useState(false); const [enableUB, setEnableUB] = useState(false); + const [enableNTS, setEnableNTS] = useState(false); + const [enableNTSR, setEnableNTSR] = useState(false); const [isOconusMove, setIsOconusMove] = useState(false); useEffect(() => { @@ -96,6 +98,8 @@ const ApprovedRequestedShipments = ({ setEnableBoat(await isBooleanFlagEnabled(FEATURE_FLAG_KEYS.BOAT)); setEnableMobileHome(await isBooleanFlagEnabled(FEATURE_FLAG_KEYS.MOBILE_HOME)); setEnableUB(await isBooleanFlagEnabled(FEATURE_FLAG_KEYS.UNACCOMPANIED_BAGGAGE)); + setEnableNTS(await isBooleanFlagEnabled(FEATURE_FLAG_KEYS.NTS)); + setEnableNTSR(await isBooleanFlagEnabled(FEATURE_FLAG_KEYS.NTSR)); }; fetchData(); }, []); @@ -117,8 +121,8 @@ const ApprovedRequestedShipments = ({ HHG - - + {enableNTS && } + {enableNTSR && } {enableBoat && } {enableMobileHome && } {enableUB && isOconusMove && } diff --git a/src/components/Office/RequestedShipments/SubmittedRequestedShipments.jsx b/src/components/Office/RequestedShipments/SubmittedRequestedShipments.jsx index 75a9702e25e..cb35c161286 100644 --- a/src/components/Office/RequestedShipments/SubmittedRequestedShipments.jsx +++ b/src/components/Office/RequestedShipments/SubmittedRequestedShipments.jsx @@ -66,6 +66,8 @@ const SubmittedRequestedShipments = ({ const [enableBoat, setEnableBoat] = useState(false); const [enableMobileHome, setEnableMobileHome] = useState(false); const [enableUB, setEnableUB] = useState(false); + const [enableNTS, setEnableNTS] = useState(false); + const [enableNTSR, setEnableNTSR] = useState(false); const [isOconusMove, setIsOconusMove] = useState(false); useEffect(() => { @@ -73,6 +75,8 @@ const SubmittedRequestedShipments = ({ setEnableBoat(await isBooleanFlagEnabled(FEATURE_FLAG_KEYS.BOAT)); setEnableMobileHome(await isBooleanFlagEnabled(FEATURE_FLAG_KEYS.MOBILE_HOME)); setEnableUB(await isBooleanFlagEnabled(FEATURE_FLAG_KEYS.UNACCOMPANIED_BAGGAGE)); + setEnableNTS(await isBooleanFlagEnabled(FEATURE_FLAG_KEYS.NTS)); + setEnableNTSR(await isBooleanFlagEnabled(FEATURE_FLAG_KEYS.NTSR)); }; fetchData(); }, []); @@ -136,8 +140,8 @@ const SubmittedRequestedShipments = ({ HHG - - + {enableNTS && } + {enableNTSR && } {enableBoat && } {enableMobileHome && } {enableUB && isOconusMove && } diff --git a/src/pages/Office/ServicesCounselingMoveDetails/ServicesCounselingMoveDetails.jsx b/src/pages/Office/ServicesCounselingMoveDetails/ServicesCounselingMoveDetails.jsx index 04e34ec3499..82e50380a2f 100644 --- a/src/pages/Office/ServicesCounselingMoveDetails/ServicesCounselingMoveDetails.jsx +++ b/src/pages/Office/ServicesCounselingMoveDetails/ServicesCounselingMoveDetails.jsx @@ -77,6 +77,8 @@ const ServicesCounselingMoveDetails = ({ const [enableBoat, setEnableBoat] = useState(false); const [enableMobileHome, setEnableMobileHome] = useState(false); const [enableUB, setEnableUB] = useState(false); + const [enableNTS, setEnableNTS] = useState(false); + const [enableNTSR, setEnableNTSR] = useState(false); const [isOconusMove, setIsOconusMove] = useState(false); const [errorMessage, setErrorMessage] = useState(null); @@ -166,6 +168,8 @@ const ServicesCounselingMoveDetails = ({ setEnableBoat(await isBooleanFlagEnabled(FEATURE_FLAG_KEYS.BOAT)); setEnableMobileHome(await isBooleanFlagEnabled(FEATURE_FLAG_KEYS.MOBILE_HOME)); setEnableUB(await isBooleanFlagEnabled(FEATURE_FLAG_KEYS.UNACCOMPANIED_BAGGAGE)); + setEnableNTS(await isBooleanFlagEnabled(FEATURE_FLAG_KEYS.NTS)); + setEnableNTSR(await isBooleanFlagEnabled(FEATURE_FLAG_KEYS.NTSR)); }; fetchData(); }, []); @@ -632,8 +636,8 @@ const ServicesCounselingMoveDetails = ({ HHG - - + {enableNTS && } + {enableNTSR && } {enableBoat && } {enableMobileHome && } {enableUB && isOconusMove && }