diff --git a/pkg/gen/primev3api/embedded_spec.go b/pkg/gen/primev3api/embedded_spec.go index 6ea3004f846..0cb5f3e7eaa 100644 --- a/pkg/gen/primev3api/embedded_spec.go +++ b/pkg/gen/primev3api/embedded_spec.go @@ -3267,6 +3267,22 @@ func init() { "$ref": "#/definitions/StorageFacility" } ] + }, + "tertiaryDeliveryAddress": { + "description": "A third delivery address for this shipment, if the customer entered one. An optional field.", + "allOf": [ + { + "$ref": "#/definitions/Address" + } + ] + }, + "tertiaryPickupAddress": { + "description": "A third pickup address for this shipment, if the customer entered one. An optional field.", + "allOf": [ + { + "$ref": "#/definitions/Address" + } + ] } } }, @@ -3321,6 +3337,16 @@ func init() { "x-nullable": true, "x-omitempty": false }, + "hasTertiaryDestinationAddress": { + "type": "boolean", + "x-nullable": true, + "x-omitempty": false + }, + "hasTertiaryPickupAddress": { + "type": "boolean", + "x-nullable": true, + "x-omitempty": false + }, "pickupAddress": { "description": "The address of the origin location where goods are being moved from.\n", "allOf": [ @@ -3387,6 +3413,22 @@ func init() { "description": "The estimated weight of the pro-gear being moved belonging to a spouse.", "type": "integer", "x-nullable": true + }, + "tertiaryDestinationAddress": { + "description": "An optional third address near the destination where goods will be dropped off.\n", + "allOf": [ + { + "$ref": "#/definitions/Address" + } + ] + }, + "tertiaryPickupAddress": { + "description": "An optional third pickup location near the origin where additional goods exist.\n", + "allOf": [ + { + "$ref": "#/definitions/Address" + } + ] } } }, @@ -6878,6 +6920,22 @@ func init() { "$ref": "#/definitions/StorageFacility" } ] + }, + "tertiaryDeliveryAddress": { + "description": "A third delivery address for this shipment, if the customer entered one. An optional field.", + "allOf": [ + { + "$ref": "#/definitions/Address" + } + ] + }, + "tertiaryPickupAddress": { + "description": "A third pickup address for this shipment, if the customer entered one. An optional field.", + "allOf": [ + { + "$ref": "#/definitions/Address" + } + ] } } }, @@ -6932,6 +6990,16 @@ func init() { "x-nullable": true, "x-omitempty": false }, + "hasTertiaryDestinationAddress": { + "type": "boolean", + "x-nullable": true, + "x-omitempty": false + }, + "hasTertiaryPickupAddress": { + "type": "boolean", + "x-nullable": true, + "x-omitempty": false + }, "pickupAddress": { "description": "The address of the origin location where goods are being moved from.\n", "allOf": [ @@ -6998,6 +7066,22 @@ func init() { "description": "The estimated weight of the pro-gear being moved belonging to a spouse.", "type": "integer", "x-nullable": true + }, + "tertiaryDestinationAddress": { + "description": "An optional third address near the destination where goods will be dropped off.\n", + "allOf": [ + { + "$ref": "#/definitions/Address" + } + ] + }, + "tertiaryPickupAddress": { + "description": "An optional third pickup location near the origin where additional goods exist.\n", + "allOf": [ + { + "$ref": "#/definitions/Address" + } + ] } } }, diff --git a/pkg/gen/primev3messages/update_m_t_o_shipment.go b/pkg/gen/primev3messages/update_m_t_o_shipment.go index 037dbf4557f..df0c18d8763 100644 --- a/pkg/gen/primev3messages/update_m_t_o_shipment.go +++ b/pkg/gen/primev3messages/update_m_t_o_shipment.go @@ -112,6 +112,16 @@ type UpdateMTOShipment struct { // storage facility StorageFacility *StorageFacility `json:"storageFacility,omitempty"` + + // A third delivery address for this shipment, if the customer entered one. An optional field. + TertiaryDeliveryAddress struct { + Address + } `json:"tertiaryDeliveryAddress,omitempty"` + + // A third pickup address for this shipment, if the customer entered one. An optional field. + TertiaryPickupAddress struct { + Address + } `json:"tertiaryPickupAddress,omitempty"` } // Validate validates this update m t o shipment @@ -178,6 +188,14 @@ func (m *UpdateMTOShipment) Validate(formats strfmt.Registry) error { res = append(res, err) } + if err := m.validateTertiaryDeliveryAddress(formats); err != nil { + res = append(res, err) + } + + if err := m.validateTertiaryPickupAddress(formats); err != nil { + res = append(res, err) + } + if len(res) > 0 { return errors.CompositeValidationError(res...) } @@ -374,6 +392,22 @@ func (m *UpdateMTOShipment) validateStorageFacility(formats strfmt.Registry) err return nil } +func (m *UpdateMTOShipment) validateTertiaryDeliveryAddress(formats strfmt.Registry) error { + if swag.IsZero(m.TertiaryDeliveryAddress) { // not required + return nil + } + + return nil +} + +func (m *UpdateMTOShipment) validateTertiaryPickupAddress(formats strfmt.Registry) error { + if swag.IsZero(m.TertiaryPickupAddress) { // not required + return nil + } + + return nil +} + // ContextValidate validate this update m t o shipment based on the context it is used func (m *UpdateMTOShipment) ContextValidate(ctx context.Context, formats strfmt.Registry) error { var res []error @@ -410,6 +444,14 @@ func (m *UpdateMTOShipment) ContextValidate(ctx context.Context, formats strfmt. res = append(res, err) } + if err := m.contextValidateTertiaryDeliveryAddress(ctx, formats); err != nil { + res = append(res, err) + } + + if err := m.contextValidateTertiaryPickupAddress(ctx, formats); err != nil { + res = append(res, err) + } + if len(res) > 0 { return errors.CompositeValidationError(res...) } @@ -517,6 +559,16 @@ func (m *UpdateMTOShipment) contextValidateStorageFacility(ctx context.Context, return nil } +func (m *UpdateMTOShipment) contextValidateTertiaryDeliveryAddress(ctx context.Context, formats strfmt.Registry) error { + + return nil +} + +func (m *UpdateMTOShipment) contextValidateTertiaryPickupAddress(ctx context.Context, formats strfmt.Registry) error { + + return nil +} + // MarshalBinary interface implementation func (m *UpdateMTOShipment) MarshalBinary() ([]byte, error) { if m == nil { diff --git a/pkg/gen/primev3messages/update_p_p_m_shipment.go b/pkg/gen/primev3messages/update_p_p_m_shipment.go index 6778ab0cb05..ead98493601 100644 --- a/pkg/gen/primev3messages/update_p_p_m_shipment.go +++ b/pkg/gen/primev3messages/update_p_p_m_shipment.go @@ -44,6 +44,12 @@ type UpdatePPMShipment struct { // has secondary pickup address HasSecondaryPickupAddress *bool `json:"hasSecondaryPickupAddress"` + // has tertiary destination address + HasTertiaryDestinationAddress *bool `json:"hasTertiaryDestinationAddress"` + + // has tertiary pickup address + HasTertiaryPickupAddress *bool `json:"hasTertiaryPickupAddress"` + // The address of the origin location where goods are being moved from. // PickupAddress struct { @@ -88,6 +94,18 @@ type UpdatePPMShipment struct { // The estimated weight of the pro-gear being moved belonging to a spouse. SpouseProGearWeight *int64 `json:"spouseProGearWeight,omitempty"` + + // An optional third address near the destination where goods will be dropped off. + // + TertiaryDestinationAddress struct { + Address + } `json:"tertiaryDestinationAddress,omitempty"` + + // An optional third pickup location near the origin where additional goods exist. + // + TertiaryPickupAddress struct { + Address + } `json:"tertiaryPickupAddress,omitempty"` } // Validate validates this update p p m shipment @@ -126,6 +144,14 @@ func (m *UpdatePPMShipment) Validate(formats strfmt.Registry) error { res = append(res, err) } + if err := m.validateTertiaryDestinationAddress(formats); err != nil { + res = append(res, err) + } + + if err := m.validateTertiaryPickupAddress(formats); err != nil { + res = append(res, err) + } + if len(res) > 0 { return errors.CompositeValidationError(res...) } @@ -219,6 +245,22 @@ func (m *UpdatePPMShipment) validateSitLocation(formats strfmt.Registry) error { return nil } +func (m *UpdatePPMShipment) validateTertiaryDestinationAddress(formats strfmt.Registry) error { + if swag.IsZero(m.TertiaryDestinationAddress) { // not required + return nil + } + + return nil +} + +func (m *UpdatePPMShipment) validateTertiaryPickupAddress(formats strfmt.Registry) error { + if swag.IsZero(m.TertiaryPickupAddress) { // not required + return nil + } + + return nil +} + // ContextValidate validate this update p p m shipment based on the context it is used func (m *UpdatePPMShipment) ContextValidate(ctx context.Context, formats strfmt.Registry) error { var res []error @@ -243,6 +285,14 @@ func (m *UpdatePPMShipment) ContextValidate(ctx context.Context, formats strfmt. res = append(res, err) } + if err := m.contextValidateTertiaryDestinationAddress(ctx, formats); err != nil { + res = append(res, err) + } + + if err := m.contextValidateTertiaryPickupAddress(ctx, formats); err != nil { + res = append(res, err) + } + if len(res) > 0 { return errors.CompositeValidationError(res...) } @@ -290,6 +340,16 @@ func (m *UpdatePPMShipment) contextValidateSitLocation(ctx context.Context, form return nil } +func (m *UpdatePPMShipment) contextValidateTertiaryDestinationAddress(ctx context.Context, formats strfmt.Registry) error { + + return nil +} + +func (m *UpdatePPMShipment) contextValidateTertiaryPickupAddress(ctx context.Context, formats strfmt.Registry) error { + + return nil +} + // MarshalBinary interface implementation func (m *UpdatePPMShipment) MarshalBinary() ([]byte, error) { if m == nil { diff --git a/pkg/handlers/primeapiv3/payloads/payload_to_model.go b/pkg/handlers/primeapiv3/payloads/payload_to_model.go index 1efd15bcb6f..8b0aff08a3d 100644 --- a/pkg/handlers/primeapiv3/payloads/payload_to_model.go +++ b/pkg/handlers/primeapiv3/payloads/payload_to_model.go @@ -386,6 +386,14 @@ func MTOShipmentModelFromUpdate(mtoShipment *primev3messages.UpdateMTOShipment, model.HasSecondaryPickupAddress = handlers.FmtBool(true) } + addressModel = AddressModel(&mtoShipment.TertiaryPickupAddress.Address) + if addressModel != nil { + model.TertiaryPickupAddress = addressModel + tertiaryPickupAddressID := uuid.FromStringOrNil(addressModel.ID.String()) + model.TertiaryPickupAddressID = &tertiaryPickupAddressID + model.HasTertiaryPickupAddress = handlers.FmtBool(true) + } + addressModel = AddressModel(&mtoShipment.SecondaryDeliveryAddress.Address) if addressModel != nil { model.SecondaryDeliveryAddress = addressModel @@ -394,6 +402,14 @@ func MTOShipmentModelFromUpdate(mtoShipment *primev3messages.UpdateMTOShipment, model.HasSecondaryDeliveryAddress = handlers.FmtBool(true) } + addressModel = AddressModel(&mtoShipment.TertiaryDeliveryAddress.Address) + if addressModel != nil { + model.TertiaryDeliveryAddress = addressModel + tertiaryDeliveryAddressID := uuid.FromStringOrNil(addressModel.ID.String()) + model.TertiaryDeliveryAddressID = &tertiaryDeliveryAddressID + model.HasTertiaryDeliveryAddress = handlers.FmtBool(true) + } + if mtoShipment.PpmShipment != nil { model.PPMShipment = PPMShipmentModelFromUpdate(mtoShipment.PpmShipment) model.PPMShipment.Shipment = *model @@ -436,6 +452,15 @@ func PPMShipmentModelFromUpdate(ppmShipment *primev3messages.UpdatePPMShipment) } } + if ppmShipment.HasTertiaryPickupAddress != nil && *ppmShipment.HasTertiaryPickupAddress { + addressModel = AddressModel(&ppmShipment.TertiaryPickupAddress.Address) + if addressModel != nil { + model.TertiaryPickupAddress = addressModel + tertiaryPickupAddressID := uuid.FromStringOrNil(addressModel.ID.String()) + model.TertiaryPickupAddressID = &tertiaryPickupAddressID + } + } + addressModel = AddressModel(&ppmShipment.DestinationAddress.Address) if addressModel != nil { model.DestinationAddress = addressModel @@ -451,6 +476,15 @@ func PPMShipmentModelFromUpdate(ppmShipment *primev3messages.UpdatePPMShipment) } } + if ppmShipment.HasTertiaryDestinationAddress != nil && *ppmShipment.HasTertiaryDestinationAddress { + addressModel = AddressModel(&ppmShipment.TertiaryDestinationAddress.Address) + if addressModel != nil { + model.TertiaryDestinationAddress = addressModel + tertiaryDestinationAddressID := uuid.FromStringOrNil(addressModel.ID.String()) + model.TertiaryDestinationAddressID = &tertiaryDestinationAddressID + } + } + expectedDepartureDate := handlers.FmtDatePtrToPopPtr(ppmShipment.ExpectedDepartureDate) if expectedDepartureDate != nil && !expectedDepartureDate.IsZero() { model.ExpectedDepartureDate = *expectedDepartureDate diff --git a/playwright/tests/office/primesimulator/primeSimulatorFlows.spec.js b/playwright/tests/office/primesimulator/primeSimulatorFlows.spec.js index 5b6f56fbb57..a6cc84e9f04 100644 --- a/playwright/tests/office/primesimulator/primeSimulatorFlows.spec.js +++ b/playwright/tests/office/primesimulator/primeSimulatorFlows.spec.js @@ -148,7 +148,7 @@ test.describe('Prime simulator user', () => { await page.locator('input[name="destinationAddress.city"]').fill('Joshua Tree'); await page.locator('select[name="destinationAddress.state"]').selectOption({ label: 'CA' }); await page.locator('input[name="destinationAddress.postalCode"]').fill('92252'); - await page.getByTestId('dropdown').nth(1).selectOption('Home of record (HOR)'); + await page.getByTestId('dropdown').nth(5).selectOption('Home of record (HOR)'); await page.getByText('Save').click(); await expect(page.getByText('Successfully updated shipment')).toHaveCount(1); diff --git a/src/pages/PrimeUI/Shipment/PrimeUIShipmentUpdate.jsx b/src/pages/PrimeUI/Shipment/PrimeUIShipmentUpdate.jsx index 699700e7ee8..bb408d21f55 100644 --- a/src/pages/PrimeUI/Shipment/PrimeUIShipmentUpdate.jsx +++ b/src/pages/PrimeUI/Shipment/PrimeUIShipmentUpdate.jsx @@ -20,7 +20,12 @@ import formStyles from 'styles/form.module.scss'; import WizardNavigation from 'components/Customer/WizardNavigation/WizardNavigation'; import { requiredAddressSchema, addressSchema } from 'utils/validation'; import { isEmpty, isValidWeight } from 'shared/utils'; -import { formatAddressForPrimeAPI, formatSwaggerDate, fromPrimeAPIAddressFormat } from 'utils/formatters'; +import { + formatAddressForPrimeAPI, + formatExtraAddressForPrimeAPI, + formatSwaggerDate, + fromPrimeAPIAddressFormat, +} from 'utils/formatters'; import PrimeUIShipmentUpdateForm from 'pages/PrimeUI/Shipment/PrimeUIShipmentUpdateForm'; import PrimeUIShipmentUpdatePPMForm from 'pages/PrimeUI/Shipment/PrimeUIShipmentUpdatePPMForm'; import { setFlashMessage as setFlashMessageAction } from 'store/flash/actions'; @@ -128,7 +133,11 @@ const PrimeUIShipmentUpdate = ({ setFlashMessage }) => { const reformatPrimeApiSecondaryDeliveryAddress = fromPrimeAPIAddressFormat(shipment.secondaryDeliveryAddress); const reformatPrimeApiTertiaryDeliveryAddress = fromPrimeAPIAddressFormat(shipment.tertiaryDeliveryAddress); const editablePickupAddress = isEmpty(reformatPrimeApiPickupAddress); + const editableSecondaryPickupAddress = isEmpty(reformatPrimeApiSecondaryPickupAddress); + const editableTertiaryPickupAddress = isEmpty(reformatPrimeApiTertiaryPickupAddress); const editableDestinationAddress = isEmpty(reformatPrimeApiDestinationAddress); + const editableSecondaryDeliveryAddress = isEmpty(reformatPrimeApiSecondaryDeliveryAddress); + const editableTertiaryDeliveryAddress = isEmpty(reformatPrimeApiTertiaryDeliveryAddress); const onCancelShipmentClick = () => { mutateMTOShipmentStatus({ mtoShipmentID: shipmentId, ifMatchETag: shipment.eTag }).then(() => { @@ -144,8 +153,10 @@ const PrimeUIShipmentUpdate = ({ setFlashMessage }) => { expectedDepartureDate, pickupAddress, secondaryPickupAddress, + tertiaryPickupAddress, destinationAddress, secondaryDestinationAddress, + tertiaryDestinationAddress, sitExpected, sitLocation, sitEstimatedWeight, @@ -156,7 +167,9 @@ const PrimeUIShipmentUpdate = ({ setFlashMessage }) => { proGearWeight, spouseProGearWeight, hasSecondaryPickupAddress, + hasTertiaryPickupAddress, hasSecondaryDestinationAddress, + hasTertiaryDestinationAddress, }, counselorRemarks, } = values; @@ -167,10 +180,16 @@ const PrimeUIShipmentUpdate = ({ setFlashMessage }) => { secondaryPickupAddress: isEmpty(secondaryPickupAddress) ? emptyAddress : formatAddressForPrimeAPI(secondaryPickupAddress), + tertiaryPickupAddress: isEmpty(tertiaryPickupAddress) + ? emptyAddress + : formatAddressForPrimeAPI(tertiaryPickupAddress), destinationAddress: isEmpty(destinationAddress) ? null : formatAddressForPrimeAPI(destinationAddress), secondaryDestinationAddress: isEmpty(secondaryDestinationAddress) ? emptyAddress : formatAddressForPrimeAPI(secondaryDestinationAddress), + tertiaryDestinationAddress: isEmpty(tertiaryDestinationAddress) + ? emptyAddress + : formatAddressForPrimeAPI(tertiaryDestinationAddress), sitExpected, ...(sitExpected && { sitLocation: sitLocation || null, @@ -185,7 +204,9 @@ const PrimeUIShipmentUpdate = ({ setFlashMessage }) => { spouseProGearWeight: spouseProGearWeight ? parseInt(spouseProGearWeight, 10) : null, }), hasSecondaryPickupAddress: hasSecondaryPickupAddress === 'true', + hasTertiaryPickupAddress: hasTertiaryPickupAddress === 'true', hasSecondaryDestinationAddress: hasSecondaryDestinationAddress === 'true', + hasTertiaryDestinationAddress: hasTertiaryDestinationAddress === 'true', }, counselorRemarks: counselorRemarks || null, }; @@ -200,7 +221,11 @@ const PrimeUIShipmentUpdate = ({ setFlashMessage }) => { actualDeliveryDate, scheduledDeliveryDate, pickupAddress, + secondaryPickupAddress, + tertiaryPickupAddress, destinationAddress, + secondaryDeliveryAddress, + tertiaryDeliveryAddress, destinationType, diversion, } = values; @@ -215,7 +240,19 @@ const PrimeUIShipmentUpdate = ({ setFlashMessage }) => { scheduledDeliveryDate: scheduledDeliveryDate ? formatSwaggerDate(scheduledDeliveryDate) : null, actualDeliveryDate: actualDeliveryDate ? formatSwaggerDate(actualDeliveryDate) : null, pickupAddress: editablePickupAddress ? formatAddressForPrimeAPI(pickupAddress) : null, + secondaryPickupAddress: editableSecondaryPickupAddress + ? formatExtraAddressForPrimeAPI(secondaryPickupAddress) + : null, + tertiaryPickupAddress: editableTertiaryPickupAddress + ? formatExtraAddressForPrimeAPI(tertiaryPickupAddress) + : null, destinationAddress: editableDestinationAddress ? formatAddressForPrimeAPI(destinationAddress) : null, + secondaryDeliveryAddress: editableSecondaryDeliveryAddress + ? formatExtraAddressForPrimeAPI(secondaryDeliveryAddress) + : null, + tertiaryDeliveryAddress: editableTertiaryDeliveryAddress + ? formatExtraAddressForPrimeAPI(tertiaryDeliveryAddress) + : null, destinationType, diversion, }; @@ -237,12 +274,18 @@ const PrimeUIShipmentUpdate = ({ setFlashMessage }) => { secondaryPickupAddress: shipment.ppmShipment.secondaryPickupAddress ? formatAddressForPrimeAPI(shipment.ppmShipment.secondaryPickupAddress) : emptyAddress, + tertiaryPickupAddress: shipment.ppmShipment.tertiaryPickupAddress + ? formatAddressForPrimeAPI(shipment.ppmShipment.tertiaryPickupAddress) + : emptyAddress, destinationAddress: shipment.ppmShipment.destinationAddress ? formatAddressForPrimeAPI(shipment.ppmShipment.destinationAddress) : emptyAddress, secondaryDestinationAddress: shipment.ppmShipment.secondaryDestinationAddress ? formatAddressForPrimeAPI(shipment.ppmShipment.secondaryDestinationAddress) : emptyAddress, + tertiaryDestinationAddress: shipment.ppmShipment.tertiaryDestinationAddress + ? formatAddressForPrimeAPI(shipment.ppmShipment.tertiaryDestinationAddress) + : emptyAddress, sitExpected: shipment.ppmShipment.sitExpected, sitLocation: shipment.ppmShipment.sitLocation, sitEstimatedWeight: shipment.ppmShipment.sitEstimatedWeight?.toString(), @@ -254,7 +297,9 @@ const PrimeUIShipmentUpdate = ({ setFlashMessage }) => { proGearWeight: shipment.ppmShipment.proGearWeight?.toString(), spouseProGearWeight: shipment.ppmShipment.spouseProGearWeight?.toString(), hasSecondaryPickupAddress: shipment.ppmShipment.hasSecondaryPickupAddress ? 'true' : 'false', + hasTertiaryPickupAddress: shipment.ppmShipment.hasTertiaryPickupAddress ? 'true' : 'false', hasSecondaryDestinationAddress: shipment.ppmShipment.hasSecondaryDestinationAddress ? 'true' : 'false', + hasTertiaryDestinationAddress: shipment.ppmShipment.hasTertiaryDestinationAddress ? 'true' : 'false', }, counselorRemarks: shipment.counselorRemarks || '', }; @@ -265,8 +310,10 @@ const PrimeUIShipmentUpdate = ({ setFlashMessage }) => { .typeError('Invalid date. Must be in the format: DD MMM YYYY'), pickupAddress: requiredAddressSchema.required('Required'), secondaryPickupAddress: OptionalAddressSchema, + tertiaryPickupAddress: OptionalAddressSchema, destinationAddress: requiredAddressSchema.required('Required'), secondaryDestinationAddress: OptionalAddressSchema, + tertiaryDestinationAddress: OptionalAddressSchema, sitExpected: Yup.boolean().required('Required'), sitLocation: Yup.string().when('sitExpected', { is: true, @@ -313,11 +360,13 @@ const PrimeUIShipmentUpdate = ({ setFlashMessage }) => { scheduledDeliveryDate: shipment.scheduledDeliveryDate, actualDeliveryDate: shipment.actualDeliveryDate, pickupAddress: editablePickupAddress ? emptyAddress : reformatPrimeApiPickupAddress, - secondaryPickupAddress: reformatPrimeApiSecondaryPickupAddress, - tertiaryPickupAddress: reformatPrimeApiTertiaryPickupAddress, + secondaryPickupAddress: editableSecondaryPickupAddress ? emptyAddress : reformatPrimeApiSecondaryPickupAddress, + tertiaryPickupAddress: editableTertiaryPickupAddress ? emptyAddress : reformatPrimeApiTertiaryPickupAddress, destinationAddress: editableDestinationAddress ? emptyAddress : reformatPrimeApiDestinationAddress, - secondaryDeliveryAddress: reformatPrimeApiSecondaryDeliveryAddress, - tertiaryDeliveryAddress: reformatPrimeApiTertiaryDeliveryAddress, + secondaryDeliveryAddress: editableSecondaryDeliveryAddress + ? emptyAddress + : reformatPrimeApiSecondaryDeliveryAddress, + tertiaryDeliveryAddress: editableTertiaryDeliveryAddress ? emptyAddress : reformatPrimeApiTertiaryDeliveryAddress, destinationType: shipment.destinationType, diversion: shipment.diversion, }; @@ -365,7 +414,11 @@ const PrimeUIShipmentUpdate = ({ setFlashMessage }) => { editableProGearWeightActualField={editableProGearWeightActualField} editableSpouseProGearWeightActualField={editableSpouseProGearWeightActualField} editablePickupAddress={editablePickupAddress} + editableSecondaryPickupAddress={editableSecondaryPickupAddress} + editableTertiaryPickupAddress={editableTertiaryPickupAddress} editableDestinationAddress={editableDestinationAddress} + editableSecondaryDeliveryAddress={editableSecondaryDeliveryAddress} + editableTertiaryDeliveryAddress={editableTertiaryDeliveryAddress} estimatedWeight={initialValues.estimatedWeight} actualWeight={initialValues.actualWeight} actualProGearWeight={initialValues.actualProGearWeight} @@ -378,6 +431,7 @@ const PrimeUIShipmentUpdate = ({ setFlashMessage }) => { secondaryDeliveryAddress={initialValues.secondaryDeliveryAddress} tertiaryDeliveryAddress={initialValues.tertiaryDeliveryAddress} diversion={initialValues.diversion} + shipmentType={shipment.shipmentType} /> )}
diff --git a/src/pages/PrimeUI/Shipment/PrimeUIShipmentUpdateForm.jsx b/src/pages/PrimeUI/Shipment/PrimeUIShipmentUpdateForm.jsx index 50d8bdb2a57..795e6caf525 100644 --- a/src/pages/PrimeUI/Shipment/PrimeUIShipmentUpdateForm.jsx +++ b/src/pages/PrimeUI/Shipment/PrimeUIShipmentUpdateForm.jsx @@ -11,6 +11,7 @@ import { AddressFields } from 'components/form/AddressFields/AddressFields'; import SectionWrapper from 'components/Customer/SectionWrapper'; import formStyles from 'styles/form.module.scss'; import { shipmentDestinationTypes } from 'constants/shipments'; +import { SHIPMENT_OPTIONS } from 'shared/constants'; const emptyAddressShape = { streetAddress1: '', @@ -28,7 +29,11 @@ const PrimeUIShipmentUpdateForm = ({ editableProGearWeightActualField, editableSpouseProGearWeightActualField, editablePickupAddress, + editableSecondaryPickupAddress, + editableTertiaryPickupAddress, editableDestinationAddress, + editableSecondaryDeliveryAddress, + editableTertiaryDeliveryAddress, requestedPickupDate, estimatedWeight, actualWeight, @@ -40,7 +45,10 @@ const PrimeUIShipmentUpdateForm = ({ destinationAddress, secondaryDeliveryAddress, tertiaryDeliveryAddress, + shipmentType, }) => { + const isNTS = shipmentType === SHIPMENT_OPTIONS.NTS; + const isNTSR = shipmentType === SHIPMENT_OPTIONS.NTSR; return (

Shipment Dates

@@ -146,17 +154,29 @@ const PrimeUIShipmentUpdateForm = ({
Pickup Address
{editablePickupAddress && } {!editablePickupAddress && formatAddress(pickupAddress)} -
Second Pickup Address
- {formatAddress(secondaryPickupAddress)} -
Third Pickup Address
- {formatAddress(tertiaryPickupAddress)} + {!isNTSR && ( + <> +
Second Pickup Address
+ {editableSecondaryPickupAddress && } + {!editableSecondaryPickupAddress && formatAddress(secondaryPickupAddress)} +
Third Pickup Address
+ {editableTertiaryPickupAddress && } + {!editableTertiaryPickupAddress && formatAddress(tertiaryPickupAddress)} + + )}
Destination Address
{editableDestinationAddress && } {!editableDestinationAddress && formatAddress(destinationAddress)} -
Second Destination Address
- {formatAddress(secondaryDeliveryAddress)} -
Third Destination Address
- {formatAddress(tertiaryDeliveryAddress)} + {!isNTS && ( + <> +
Second Delivery Address
+ {editableSecondaryDeliveryAddress && } + {!editableSecondaryDeliveryAddress && formatAddress(secondaryDeliveryAddress)} +
Third Delivery Address
+ {editableTertiaryDeliveryAddress && } + {!editableTertiaryDeliveryAddress && formatAddress(tertiaryDeliveryAddress)} + + )} { const { values } = useFormikContext(); - const { sitExpected, hasProGear, hasSecondaryPickupAddress, hasSecondaryDestinationAddress } = values.ppmShipment; + const { + sitExpected, + hasProGear, + hasSecondaryPickupAddress, + hasTertiaryPickupAddress, + hasSecondaryDestinationAddress, + hasTertiaryDestinationAddress, + } = values.ppmShipment; return ( @@ -62,7 +69,41 @@ const PrimeUIShipmentUpdatePPMForm = () => { />
- {hasSecondaryPickupAddress === 'true' && } + {hasSecondaryPickupAddress === 'true' && ( + <> + +

Third pickup location

+ +

+ Will the movers pick up any belongings from a third address? (Must be near the pickup address. + Subject to approval.) +

+
+ + +
+
+ {hasTertiaryPickupAddress === 'true' && } + + )} )} /> @@ -103,7 +144,41 @@ const PrimeUIShipmentUpdatePPMForm = () => { {hasSecondaryDestinationAddress === 'true' && ( - + <> + +

Third destination location

+ +

+ Will the movers pick up any belongings from a third address? (Must be near the Destination address. + Subject to approval.) +

+
+ + +
+
+ {hasTertiaryDestinationAddress === 'true' && ( + + )} + )} )} diff --git a/src/pages/PrimeUI/Shipment/PrimeUIShipmentUpdatePPMForm.test.jsx b/src/pages/PrimeUI/Shipment/PrimeUIShipmentUpdatePPMForm.test.jsx index e6ca000f04a..be3ea189cd7 100644 --- a/src/pages/PrimeUI/Shipment/PrimeUIShipmentUpdatePPMForm.test.jsx +++ b/src/pages/PrimeUI/Shipment/PrimeUIShipmentUpdatePPMForm.test.jsx @@ -69,6 +69,14 @@ const shipment = { state: 'KY', postalCode: '42702', }, + tertiaryPickupAddress: { + streetAddress1: '123 Test Lane', + streetAddress2: '234 Test Lane', + streetAddress3: 'Test Woman', + city: 'Missoula', + state: 'MT', + postalCode: '59801', + }, destinationAddress: { streetAddress1: '222 Test Street', streetAddress2: '333 Test Street', @@ -85,8 +93,18 @@ const shipment = { state: 'KY', postalCode: '42701', }, + tertiaryDestinationAddress: { + streetAddress1: '321 Test Lane', + streetAddress2: '432 Test Lane', + streetAddress3: 'Test Woman', + city: 'Silver Spring', + state: 'MD', + postalCode: '20906', + }, hasSecondaryPickupAddress: 'true', hasSecondaryDestinationAddress: 'true', + hasTertiaryPickupAddress: 'true', + hasTertiaryDestinationAddress: 'true', submittedAt: '2022-07-01T13:41:33.252Z', updatedAt: '2022-07-01T14:23:19.780Z', }, @@ -106,6 +124,18 @@ const shipment = { state: null, streetAddress1: null, }, + tertiaryDeliveryAddress: { + city: null, + postalCode: null, + state: null, + streetAddress1: null, + }, + tertiaryPickupAddress: { + city: null, + postalCode: null, + state: null, + streetAddress1: null, + }, shipmentType: 'PPM', status: 'APPROVED', updatedAt: '2022-07-01T14:23:19.738Z', @@ -173,33 +203,63 @@ describe('PrimeUIShipmentUpdatePPMForm', () => { ); expect(await screen.getAllByLabelText('Address 1')[2]).toHaveValue( - initialValues.ppmShipment.destinationAddress.streetAddress1, + initialValues.ppmShipment.tertiaryPickupAddress.streetAddress1, ); expect(await screen.getAllByLabelText(/Address 2/)[2]).toHaveValue( - initialValues.ppmShipment.destinationAddress.streetAddress2, + initialValues.ppmShipment.tertiaryPickupAddress.streetAddress2, + ); + expect(await screen.getAllByLabelText('City')[2]).toHaveValue(initialValues.ppmShipment.tertiaryPickupAddress.city); + expect(await screen.getAllByLabelText('State')[2]).toHaveValue( + initialValues.ppmShipment.tertiaryPickupAddress.state, ); - expect(await screen.getAllByLabelText('City')[2]).toHaveValue(initialValues.ppmShipment.destinationAddress.city); - expect(await screen.getAllByLabelText('State')[2]).toHaveValue(initialValues.ppmShipment.destinationAddress.state); expect(await screen.getAllByLabelText('ZIP')[2]).toHaveValue( - initialValues.ppmShipment.destinationAddress.postalCode, + initialValues.ppmShipment.tertiaryPickupAddress.postalCode, ); expect(await screen.getAllByLabelText('Address 1')[3]).toHaveValue( - initialValues.ppmShipment.secondaryDestinationAddress.streetAddress1, + initialValues.ppmShipment.destinationAddress.streetAddress1, ); expect(await screen.getAllByLabelText(/Address 2/)[3]).toHaveValue( + initialValues.ppmShipment.destinationAddress.streetAddress2, + ); + expect(await screen.getAllByLabelText('City')[3]).toHaveValue(initialValues.ppmShipment.destinationAddress.city); + expect(await screen.getAllByLabelText('State')[3]).toHaveValue(initialValues.ppmShipment.destinationAddress.state); + expect(await screen.getAllByLabelText('ZIP')[3]).toHaveValue( + initialValues.ppmShipment.destinationAddress.postalCode, + ); + + expect(await screen.getAllByLabelText('Address 1')[4]).toHaveValue( + initialValues.ppmShipment.secondaryDestinationAddress.streetAddress1, + ); + expect(await screen.getAllByLabelText(/Address 2/)[4]).toHaveValue( initialValues.ppmShipment.secondaryDestinationAddress.streetAddress2, ); - expect(await screen.getAllByLabelText('City')[3]).toHaveValue( + expect(await screen.getAllByLabelText('City')[4]).toHaveValue( initialValues.ppmShipment.secondaryDestinationAddress.city, ); - expect(await screen.getAllByLabelText('State')[3]).toHaveValue( + expect(await screen.getAllByLabelText('State')[4]).toHaveValue( initialValues.ppmShipment.secondaryDestinationAddress.state, ); - expect(await screen.getAllByLabelText('ZIP')[3]).toHaveValue( + expect(await screen.getAllByLabelText('ZIP')[4]).toHaveValue( initialValues.ppmShipment.secondaryDestinationAddress.postalCode, ); + expect(await screen.getAllByLabelText('Address 1')[5]).toHaveValue( + initialValues.ppmShipment.tertiaryDestinationAddress.streetAddress1, + ); + expect(await screen.getAllByLabelText(/Address 2/)[5]).toHaveValue( + initialValues.ppmShipment.tertiaryDestinationAddress.streetAddress2, + ); + expect(await screen.getAllByLabelText('City')[5]).toHaveValue( + initialValues.ppmShipment.tertiaryDestinationAddress.city, + ); + expect(await screen.getAllByLabelText('State')[5]).toHaveValue( + initialValues.ppmShipment.tertiaryDestinationAddress.state, + ); + expect(await screen.getAllByLabelText('ZIP')[5]).toHaveValue( + initialValues.ppmShipment.tertiaryDestinationAddress.postalCode, + ); + expect(await screen.findByText('Storage In Transit (SIT)')).toBeInTheDocument(); expect(await screen.findByLabelText('SIT Expected')).toBeChecked(); expect(await screen.findByLabelText('SIT Location')).toHaveValue(initialValues.ppmShipment.sitLocation); diff --git a/src/utils/formatters.js b/src/utils/formatters.js index 139ef5b179f..50b54459236 100644 --- a/src/utils/formatters.js +++ b/src/utils/formatters.js @@ -406,6 +406,19 @@ export const formatAddressForPrimeAPI = (address) => { }; }; +export const formatExtraAddressForPrimeAPI = (address) => { + const { streetAddress1, city, state, postalCode } = address; + if (streetAddress1 === '' || city === '' || state === '' || postalCode === '') return null; + return { + streetAddress1: address.streetAddress1, + streetAddress2: address.streetAddress2, + streetAddress3: address.streetAddress3, + city: address.city, + state: address.state, + postalCode: address.postalCode, + }; +}; + const emptyAddress = { streetAddress1: '', streetAddress2: '', diff --git a/swagger-def/prime_v3.yaml b/swagger-def/prime_v3.yaml index 7981ffce54f..6ada3f13596 100644 --- a/swagger-def/prime_v3.yaml +++ b/swagger-def/prime_v3.yaml @@ -621,6 +621,15 @@ definitions: An optional secondary pickup location near the origin where additional goods exist. allOf: - $ref: 'definitions/Address.yaml' + hasTertiaryPickupAddress: + type: boolean + x-omitempty: false + x-nullable: true + tertiaryPickupAddress: + description: > + An optional third pickup location near the origin where additional goods exist. + allOf: + - $ref: 'definitions/Address.yaml' destinationAddress: description: > The address of the destination location where goods are being delivered to. @@ -635,6 +644,15 @@ definitions: An optional secondary address near the destination where goods will be dropped off. allOf: - $ref: 'definitions/Address.yaml' + hasTertiaryDestinationAddress: + type: boolean + x-omitempty: false + x-nullable: true + tertiaryDestinationAddress: + description: > + An optional third address near the destination where goods will be dropped off. + allOf: + - $ref: 'definitions/Address.yaml' sitExpected: description: | Captures whether some or all of the PPM shipment will require temporary storage at the origin or destination. @@ -769,6 +787,14 @@ definitions: description: A second delivery address for this shipment, if the customer entered one. An optional field. allOf: - $ref: 'definitions/Address.yaml' + tertiaryPickupAddress: + description: A third pickup address for this shipment, if the customer entered one. An optional field. + allOf: + - $ref: 'definitions/Address.yaml' + tertiaryDeliveryAddress: + description: A third delivery address for this shipment, if the customer entered one. An optional field. + allOf: + - $ref: 'definitions/Address.yaml' storageFacility: allOf: - x-nullable: true diff --git a/swagger/prime_v3.yaml b/swagger/prime_v3.yaml index 41ae3c1afb2..2f59100a3e6 100644 --- a/swagger/prime_v3.yaml +++ b/swagger/prime_v3.yaml @@ -923,6 +923,16 @@ definitions: goods exist. allOf: - $ref: '#/definitions/Address' + hasTertiaryPickupAddress: + type: boolean + x-omitempty: false + x-nullable: true + tertiaryPickupAddress: + description: > + An optional third pickup location near the origin where additional + goods exist. + allOf: + - $ref: '#/definitions/Address' destinationAddress: description: > The address of the destination location where goods are being @@ -939,6 +949,16 @@ definitions: dropped off. allOf: - $ref: '#/definitions/Address' + hasTertiaryDestinationAddress: + type: boolean + x-omitempty: false + x-nullable: true + tertiaryDestinationAddress: + description: > + An optional third address near the destination where goods will be + dropped off. + allOf: + - $ref: '#/definitions/Address' sitExpected: description: > Captures whether some or all of the PPM shipment will require @@ -1106,6 +1126,18 @@ definitions: one. An optional field. allOf: - $ref: '#/definitions/Address' + tertiaryPickupAddress: + description: >- + A third pickup address for this shipment, if the customer entered one. + An optional field. + allOf: + - $ref: '#/definitions/Address' + tertiaryDeliveryAddress: + description: >- + A third delivery address for this shipment, if the customer entered + one. An optional field. + allOf: + - $ref: '#/definitions/Address' storageFacility: allOf: - x-nullable: true