diff --git a/pkg/gen/ghcapi/embedded_spec.go b/pkg/gen/ghcapi/embedded_spec.go
index 51113c85e01..61bd52e4f5c 100644
--- a/pkg/gen/ghcapi/embedded_spec.go
+++ b/pkg/gen/ghcapi/embedded_spec.go
@@ -1911,7 +1911,7 @@ func init() {
},
"/move_task_orders/{moveTaskOrderID}/mto_shipments/{shipmentID}": {
"patch": {
- "description": "Updates a specified MTO shipment.\nRequired fields include:\n* MTO Shipment ID required in path\n* If-Match required in headers\n* No fields required in body\nOptional fields include:\n* New shipment status type\n* Shipment Type\n* Customer requested pick-up date\n* Pick-up Address\n* Delivery Address\n* Secondary Pick-up Address\n* SecondaryDelivery Address\n* Delivery Address Type\n* Customer Remarks\n* Counselor Remarks\n* Releasing / Receiving agents\n* Actual Pro Gear Weight\n* Actual Spouse Pro Gear Weight\n",
+ "description": "Updates a specified MTO shipment.\nRequired fields include:\n* MTO Shipment ID required in path\n* If-Match required in headers\n* No fields required in body\nOptional fields include:\n* New shipment status type\n* Shipment Type\n* Customer requested pick-up date\n* Pick-up Address\n* Delivery Address\n* Secondary Pick-up Address\n* SecondaryDelivery Address\n* Delivery Address Type\n* Customer Remarks\n* Counselor Remarks\n* Releasing / Receiving agents\n* Actual Pro Gear Weight\n* Actual Spouse Pro Gear Weight\n* Location of the POE/POD\n",
"consumes": [
"application/json"
],
@@ -9986,6 +9986,12 @@ func init() {
"x-nullable": true,
"$ref": "#/definitions/Address"
},
+ "podLocation": {
+ "$ref": "#/definitions/Port"
+ },
+ "poeLocation": {
+ "$ref": "#/definitions/Port"
+ },
"ppmShipment": {
"$ref": "#/definitions/PPMShipment"
},
@@ -12569,6 +12575,115 @@ func init() {
"$ref": "#/definitions/PaymentServiceItem"
}
},
+ "Port": {
+ "description": "A port that is used to move an international shipment.",
+ "type": "object",
+ "properties": {
+ "city": {
+ "type": "string",
+ "example": "PORTLAND"
+ },
+ "country": {
+ "description": "Two-letter country code",
+ "type": "string",
+ "pattern": "^[A-Z]{2}$",
+ "example": "US"
+ },
+ "county": {
+ "type": "string",
+ "example": "MULTNOMAH"
+ },
+ "id": {
+ "type": "string",
+ "format": "uuid",
+ "example": "c56a4180-65aa-42ec-a945-5fd21dec0538"
+ },
+ "portCode": {
+ "description": "3 or 4 digit port code",
+ "type": "string",
+ "example": "0431"
+ },
+ "portName": {
+ "description": "Name of the port",
+ "type": "string",
+ "example": "PORTLAND INTL"
+ },
+ "portType": {
+ "description": "Port type A (Air), B (Border Crossing), S (Sea)",
+ "type": "string",
+ "enum": [
+ "A",
+ "B",
+ "S"
+ ]
+ },
+ "state": {
+ "description": "US state",
+ "type": "string",
+ "enum": [
+ "AL",
+ "AK",
+ "AR",
+ "AZ",
+ "CA",
+ "CO",
+ "CT",
+ "DC",
+ "DE",
+ "FL",
+ "GA",
+ "HI",
+ "IA",
+ "ID",
+ "IL",
+ "IN",
+ "KS",
+ "KY",
+ "LA",
+ "MA",
+ "MD",
+ "ME",
+ "MI",
+ "MN",
+ "MO",
+ "MS",
+ "MT",
+ "NC",
+ "ND",
+ "NE",
+ "NH",
+ "NJ",
+ "NM",
+ "NV",
+ "NY",
+ "OH",
+ "OK",
+ "OR",
+ "PA",
+ "RI",
+ "SC",
+ "SD",
+ "TN",
+ "TX",
+ "UT",
+ "VA",
+ "VT",
+ "WA",
+ "WI",
+ "WV",
+ "WY"
+ ],
+ "example": "OR"
+ },
+ "zip": {
+ "type": "string",
+ "format": "zip",
+ "title": "ZIP",
+ "pattern": "^(\\d{5}([\\-]\\d{4})?)$",
+ "example": "99501"
+ }
+ }
+ },
"PostDocumentPayload": {
"type": "object",
"properties": {
@@ -17965,7 +18080,7 @@ func init() {
},
"/move_task_orders/{moveTaskOrderID}/mto_shipments/{shipmentID}": {
"patch": {
- "description": "Updates a specified MTO shipment.\nRequired fields include:\n* MTO Shipment ID required in path\n* If-Match required in headers\n* No fields required in body\nOptional fields include:\n* New shipment status type\n* Shipment Type\n* Customer requested pick-up date\n* Pick-up Address\n* Delivery Address\n* Secondary Pick-up Address\n* SecondaryDelivery Address\n* Delivery Address Type\n* Customer Remarks\n* Counselor Remarks\n* Releasing / Receiving agents\n* Actual Pro Gear Weight\n* Actual Spouse Pro Gear Weight\n",
+ "description": "Updates a specified MTO shipment.\nRequired fields include:\n* MTO Shipment ID required in path\n* If-Match required in headers\n* No fields required in body\nOptional fields include:\n* New shipment status type\n* Shipment Type\n* Customer requested pick-up date\n* Pick-up Address\n* Delivery Address\n* Secondary Pick-up Address\n* SecondaryDelivery Address\n* Delivery Address Type\n* Customer Remarks\n* Counselor Remarks\n* Releasing / Receiving agents\n* Actual Pro Gear Weight\n* Actual Spouse Pro Gear Weight\n* Location of the POE/POD\n",
"consumes": [
"application/json"
],
@@ -27077,6 +27192,12 @@ func init() {
"x-nullable": true,
"$ref": "#/definitions/Address"
},
+ "podLocation": {
+ "$ref": "#/definitions/Port"
+ },
+ "poeLocation": {
+ "$ref": "#/definitions/Port"
+ },
"ppmShipment": {
"$ref": "#/definitions/PPMShipment"
},
@@ -29734,6 +29855,115 @@ func init() {
"$ref": "#/definitions/PaymentServiceItem"
}
},
+ "Port": {
+ "description": "A port that is used to move an international shipment.",
+ "type": "object",
+ "properties": {
+ "city": {
+ "type": "string",
+ "example": "PORTLAND"
+ },
+ "country": {
+ "description": "Two-letter country code",
+ "type": "string",
+ "pattern": "^[A-Z]{2}$",
+ "example": "US"
+ },
+ "county": {
+ "type": "string",
+ "example": "MULTNOMAH"
+ },
+ "id": {
+ "type": "string",
+ "format": "uuid",
+ "example": "c56a4180-65aa-42ec-a945-5fd21dec0538"
+ },
+ "portCode": {
+ "description": "3 or 4 digit port code",
+ "type": "string",
+ "example": "0431"
+ },
+ "portName": {
+ "description": "Name of the port",
+ "type": "string",
+ "example": "PORTLAND INTL"
+ },
+ "portType": {
+ "description": "Port type A (Air), B (Border Crossing), S (Sea)",
+ "type": "string",
+ "enum": [
+ "A",
+ "B",
+ "S"
+ ]
+ },
+ "state": {
+ "description": "US state",
+ "type": "string",
+ "enum": [
+ "AL",
+ "AK",
+ "AR",
+ "AZ",
+ "CA",
+ "CO",
+ "CT",
+ "DC",
+ "DE",
+ "FL",
+ "GA",
+ "HI",
+ "IA",
+ "ID",
+ "IL",
+ "IN",
+ "KS",
+ "KY",
+ "LA",
+ "MA",
+ "MD",
+ "ME",
+ "MI",
+ "MN",
+ "MO",
+ "MS",
+ "MT",
+ "NC",
+ "ND",
+ "NE",
+ "NH",
+ "NJ",
+ "NM",
+ "NV",
+ "NY",
+ "OH",
+ "OK",
+ "OR",
+ "PA",
+ "RI",
+ "SC",
+ "SD",
+ "TN",
+ "TX",
+ "UT",
+ "VA",
+ "VT",
+ "WA",
+ "WI",
+ "WV",
+ "WY"
+ ],
+ "example": "OR"
+ },
+ "zip": {
+ "type": "string",
+ "format": "zip",
+ "title": "ZIP",
+ "pattern": "^(\\d{5}([\\-]\\d{4})?)$",
+ "example": "99501"
+ }
+ }
+ },
"PostDocumentPayload": {
"type": "object",
"properties": {
diff --git a/pkg/gen/ghcapi/ghcoperations/mto_shipment/update_m_t_o_shipment.go b/pkg/gen/ghcapi/ghcoperations/mto_shipment/update_m_t_o_shipment.go
index eb0db5e29ab..2ad855d4d8b 100644
--- a/pkg/gen/ghcapi/ghcoperations/mto_shipment/update_m_t_o_shipment.go
+++ b/pkg/gen/ghcapi/ghcoperations/mto_shipment/update_m_t_o_shipment.go
@@ -53,6 +53,7 @@ Optional fields include:
* Releasing / Receiving agents
* Actual Pro Gear Weight
* Actual Spouse Pro Gear Weight
+* Location of the POE/POD
*/
type UpdateMTOShipment struct {
Context *middleware.Context
diff --git a/pkg/gen/ghcmessages/m_t_o_shipment.go b/pkg/gen/ghcmessages/m_t_o_shipment.go
index 78a6420cee4..793859afdfc 100644
--- a/pkg/gen/ghcmessages/m_t_o_shipment.go
+++ b/pkg/gen/ghcmessages/m_t_o_shipment.go
@@ -151,6 +151,12 @@ type MTOShipment struct {
// pickup address
PickupAddress *Address `json:"pickupAddress,omitempty"`
+ // pod location
+ PodLocation *Port `json:"podLocation,omitempty"`
+
+ // poe location
+ PoeLocation *Port `json:"poeLocation,omitempty"`
+
// ppm shipment
PpmShipment *PPMShipment `json:"ppmShipment,omitempty"`
@@ -318,6 +324,14 @@ func (m *MTOShipment) Validate(formats strfmt.Registry) error {
res = append(res, err)
}
+ if err := m.validatePodLocation(formats); err != nil {
+ res = append(res, err)
+ }
+
+ if err := m.validatePoeLocation(formats); err != nil {
+ res = append(res, err)
+ }
+
if err := m.validatePpmShipment(formats); err != nil {
res = append(res, err)
}
@@ -698,6 +712,44 @@ func (m *MTOShipment) validatePickupAddress(formats strfmt.Registry) error {
return nil
}
+func (m *MTOShipment) validatePodLocation(formats strfmt.Registry) error {
+ if swag.IsZero(m.PodLocation) { // not required
+ return nil
+ }
+
+ if m.PodLocation != nil {
+ if err := m.PodLocation.Validate(formats); err != nil {
+ if ve, ok := err.(*errors.Validation); ok {
+ return ve.ValidateName("podLocation")
+ } else if ce, ok := err.(*errors.CompositeError); ok {
+ return ce.ValidateName("podLocation")
+ }
+ return err
+ }
+ }
+
+ return nil
+}
+
+func (m *MTOShipment) validatePoeLocation(formats strfmt.Registry) error {
+ if swag.IsZero(m.PoeLocation) { // not required
+ return nil
+ }
+
+ if m.PoeLocation != nil {
+ if err := m.PoeLocation.Validate(formats); err != nil {
+ if ve, ok := err.(*errors.Validation); ok {
+ return ve.ValidateName("poeLocation")
+ } else if ce, ok := err.(*errors.CompositeError); ok {
+ return ce.ValidateName("poeLocation")
+ }
+ return err
+ }
+ }
+
+ return nil
+}
+
func (m *MTOShipment) validatePpmShipment(formats strfmt.Registry) error {
if swag.IsZero(m.PpmShipment) { // not required
return nil
@@ -1051,6 +1103,14 @@ func (m *MTOShipment) ContextValidate(ctx context.Context, formats strfmt.Regist
res = append(res, err)
}
+ if err := m.contextValidatePodLocation(ctx, formats); err != nil {
+ res = append(res, err)
+ }
+
+ if err := m.contextValidatePoeLocation(ctx, formats); err != nil {
+ res = append(res, err)
+ }
+
if err := m.contextValidatePpmShipment(ctx, formats); err != nil {
res = append(res, err)
}
@@ -1276,6 +1336,48 @@ func (m *MTOShipment) contextValidatePickupAddress(ctx context.Context, formats
return nil
}
+func (m *MTOShipment) contextValidatePodLocation(ctx context.Context, formats strfmt.Registry) error {
+
+ if m.PodLocation != nil {
+
+ if swag.IsZero(m.PodLocation) { // not required
+ return nil
+ }
+
+ if err := m.PodLocation.ContextValidate(ctx, formats); err != nil {
+ if ve, ok := err.(*errors.Validation); ok {
+ return ve.ValidateName("podLocation")
+ } else if ce, ok := err.(*errors.CompositeError); ok {
+ return ce.ValidateName("podLocation")
+ }
+ return err
+ }
+ }
+
+ return nil
+}
+
+func (m *MTOShipment) contextValidatePoeLocation(ctx context.Context, formats strfmt.Registry) error {
+
+ if m.PoeLocation != nil {
+
+ if swag.IsZero(m.PoeLocation) { // not required
+ return nil
+ }
+
+ if err := m.PoeLocation.ContextValidate(ctx, formats); err != nil {
+ if ve, ok := err.(*errors.Validation); ok {
+ return ve.ValidateName("poeLocation")
+ } else if ce, ok := err.(*errors.CompositeError); ok {
+ return ce.ValidateName("poeLocation")
+ }
+ return err
+ }
+ }
+
+ return nil
+}
+
func (m *MTOShipment) contextValidatePpmShipment(ctx context.Context, formats strfmt.Registry) error {
if m.PpmShipment != nil {
diff --git a/pkg/gen/ghcmessages/port.go b/pkg/gen/ghcmessages/port.go
new file mode 100644
index 00000000000..5ffb0256db8
--- /dev/null
+++ b/pkg/gen/ghcmessages/port.go
@@ -0,0 +1,385 @@
+// Code generated by go-swagger; DO NOT EDIT.
+
+package ghcmessages
+
+// This file was generated by the swagger tool.
+// Editing this file might prove futile when you re-run the swagger generate command
+
+import (
+ "context"
+ "encoding/json"
+
+ "github.com/go-openapi/errors"
+ "github.com/go-openapi/strfmt"
+ "github.com/go-openapi/swag"
+ "github.com/go-openapi/validate"
+)
+
+// Port A port that is used to move an international shipment.
+//
+// swagger:model Port
+type Port struct {
+
+ // city
+ // Example: PORTLAND
+ City string `json:"city,omitempty"`
+
+ // Two-letter country code
+ // Example: US
+ // Pattern: ^[A-Z]{2}$
+ Country string `json:"country,omitempty"`
+
+ // county
+ // Example: MULTNOMAH
+ County string `json:"county,omitempty"`
+
+ // id
+ // Example: c56a4180-65aa-42ec-a945-5fd21dec0538
+ // Format: uuid
+ ID strfmt.UUID `json:"id,omitempty"`
+
+ // 3 or 4 digit port code
+ // Example: 0431
+ PortCode string `json:"portCode,omitempty"`
+
+ // Name of the port
+ // Example: PORTLAND INTL
+ PortName string `json:"portName,omitempty"`
+
+ // Port type A (Air), B (Border Crossing), S (Sea)
+ // Enum: [A B S]
+ PortType string `json:"portType,omitempty"`
+
+ // US state
+ // Example: OR
+ // Enum: [AL AK AR AZ CA CO CT DC DE FL GA HI IA ID IL IN KS KY LA MA MD ME MI MN MO MS MT NC ND NE NH NJ NM NV NY OH OK OR PA RI SC SD TN TX UT VA VT WA WI WV WY]
+ State string `json:"state,omitempty"`
+
+ // ZIP
+ // Example: 99501
+ // Pattern: ^(\d{5}([\-]\d{4})?)$
+ Zip string `json:"zip,omitempty"`
+}
+
+// Validate validates this port
+func (m *Port) Validate(formats strfmt.Registry) error {
+ var res []error
+
+ if err := m.validateCountry(formats); err != nil {
+ res = append(res, err)
+ }
+
+ if err := m.validateID(formats); err != nil {
+ res = append(res, err)
+ }
+
+ if err := m.validatePortType(formats); err != nil {
+ res = append(res, err)
+ }
+
+ if err := m.validateState(formats); err != nil {
+ res = append(res, err)
+ }
+
+ if err := m.validateZip(formats); err != nil {
+ res = append(res, err)
+ }
+
+ if len(res) > 0 {
+ return errors.CompositeValidationError(res...)
+ }
+ return nil
+}
+
+func (m *Port) validateCountry(formats strfmt.Registry) error {
+ if swag.IsZero(m.Country) { // not required
+ return nil
+ }
+
+ if err := validate.Pattern("country", "body", m.Country, `^[A-Z]{2}$`); err != nil {
+ return err
+ }
+
+ return nil
+}
+
+func (m *Port) validateID(formats strfmt.Registry) error {
+ if swag.IsZero(m.ID) { // not required
+ return nil
+ }
+
+ if err := validate.FormatOf("id", "body", "uuid", m.ID.String(), formats); err != nil {
+ return err
+ }
+
+ return nil
+}
+
+var portTypePortTypePropEnum []interface{}
+
+func init() {
+ var res []string
+ if err := json.Unmarshal([]byte(`["A","B","S"]`), &res); err != nil {
+ panic(err)
+ }
+ for _, v := range res {
+ portTypePortTypePropEnum = append(portTypePortTypePropEnum, v)
+ }
+}
+
+const (
+
+ // PortPortTypeA captures enum value "A"
+ PortPortTypeA string = "A"
+
+ // PortPortTypeB captures enum value "B"
+ PortPortTypeB string = "B"
+
+ // PortPortTypeS captures enum value "S"
+ PortPortTypeS string = "S"
+)
+
+// prop value enum
+func (m *Port) validatePortTypeEnum(path, location string, value string) error {
+ if err := validate.EnumCase(path, location, value, portTypePortTypePropEnum, true); err != nil {
+ return err
+ }
+ return nil
+}
+
+func (m *Port) validatePortType(formats strfmt.Registry) error {
+ if swag.IsZero(m.PortType) { // not required
+ return nil
+ }
+
+ // value enum
+ if err := m.validatePortTypeEnum("portType", "body", m.PortType); err != nil {
+ return err
+ }
+
+ return nil
+}
+
+var portTypeStatePropEnum []interface{}
+
+func init() {
+ var res []string
+ if err := json.Unmarshal([]byte(`["AL","AK","AR","AZ","CA","CO","CT","DC","DE","FL","GA","HI","IA","ID","IL","IN","KS","KY","LA","MA","MD","ME","MI","MN","MO","MS","MT","NC","ND","NE","NH","NJ","NM","NV","NY","OH","OK","OR","PA","RI","SC","SD","TN","TX","UT","VA","VT","WA","WI","WV","WY"]`), &res); err != nil {
+ panic(err)
+ }
+ for _, v := range res {
+ portTypeStatePropEnum = append(portTypeStatePropEnum, v)
+ }
+}
+
+const (
+
+ // PortStateAL captures enum value "AL"
+ PortStateAL string = "AL"
+
+ // PortStateAK captures enum value "AK"
+ PortStateAK string = "AK"
+
+ // PortStateAR captures enum value "AR"
+ PortStateAR string = "AR"
+
+ // PortStateAZ captures enum value "AZ"
+ PortStateAZ string = "AZ"
+
+ // PortStateCA captures enum value "CA"
+ PortStateCA string = "CA"
+
+ // PortStateCO captures enum value "CO"
+ PortStateCO string = "CO"
+
+ // PortStateCT captures enum value "CT"
+ PortStateCT string = "CT"
+
+ // PortStateDC captures enum value "DC"
+ PortStateDC string = "DC"
+
+ // PortStateDE captures enum value "DE"
+ PortStateDE string = "DE"
+
+ // PortStateFL captures enum value "FL"
+ PortStateFL string = "FL"
+
+ // PortStateGA captures enum value "GA"
+ PortStateGA string = "GA"
+
+ // PortStateHI captures enum value "HI"
+ PortStateHI string = "HI"
+
+ // PortStateIA captures enum value "IA"
+ PortStateIA string = "IA"
+
+ // PortStateID captures enum value "ID"
+ PortStateID string = "ID"
+
+ // PortStateIL captures enum value "IL"
+ PortStateIL string = "IL"
+
+ // PortStateIN captures enum value "IN"
+ PortStateIN string = "IN"
+
+ // PortStateKS captures enum value "KS"
+ PortStateKS string = "KS"
+
+ // PortStateKY captures enum value "KY"
+ PortStateKY string = "KY"
+
+ // PortStateLA captures enum value "LA"
+ PortStateLA string = "LA"
+
+ // PortStateMA captures enum value "MA"
+ PortStateMA string = "MA"
+
+ // PortStateMD captures enum value "MD"
+ PortStateMD string = "MD"
+
+ // PortStateME captures enum value "ME"
+ PortStateME string = "ME"
+
+ // PortStateMI captures enum value "MI"
+ PortStateMI string = "MI"
+
+ // PortStateMN captures enum value "MN"
+ PortStateMN string = "MN"
+
+ // PortStateMO captures enum value "MO"
+ PortStateMO string = "MO"
+
+ // PortStateMS captures enum value "MS"
+ PortStateMS string = "MS"
+
+ // PortStateMT captures enum value "MT"
+ PortStateMT string = "MT"
+
+ // PortStateNC captures enum value "NC"
+ PortStateNC string = "NC"
+
+ // PortStateND captures enum value "ND"
+ PortStateND string = "ND"
+
+ // PortStateNE captures enum value "NE"
+ PortStateNE string = "NE"
+
+ // PortStateNH captures enum value "NH"
+ PortStateNH string = "NH"
+
+ // PortStateNJ captures enum value "NJ"
+ PortStateNJ string = "NJ"
+
+ // PortStateNM captures enum value "NM"
+ PortStateNM string = "NM"
+
+ // PortStateNV captures enum value "NV"
+ PortStateNV string = "NV"
+
+ // PortStateNY captures enum value "NY"
+ PortStateNY string = "NY"
+
+ // PortStateOH captures enum value "OH"
+ PortStateOH string = "OH"
+
+ // PortStateOK captures enum value "OK"
+ PortStateOK string = "OK"
+
+ // PortStateOR captures enum value "OR"
+ PortStateOR string = "OR"
+
+ // PortStatePA captures enum value "PA"
+ PortStatePA string = "PA"
+
+ // PortStateRI captures enum value "RI"
+ PortStateRI string = "RI"
+
+ // PortStateSC captures enum value "SC"
+ PortStateSC string = "SC"
+
+ // PortStateSD captures enum value "SD"
+ PortStateSD string = "SD"
+
+ // PortStateTN captures enum value "TN"
+ PortStateTN string = "TN"
+
+ // PortStateTX captures enum value "TX"
+ PortStateTX string = "TX"
+
+ // PortStateUT captures enum value "UT"
+ PortStateUT string = "UT"
+
+ // PortStateVA captures enum value "VA"
+ PortStateVA string = "VA"
+
+ // PortStateVT captures enum value "VT"
+ PortStateVT string = "VT"
+
+ // PortStateWA captures enum value "WA"
+ PortStateWA string = "WA"
+
+ // PortStateWI captures enum value "WI"
+ PortStateWI string = "WI"
+
+ // PortStateWV captures enum value "WV"
+ PortStateWV string = "WV"
+
+ // PortStateWY captures enum value "WY"
+ PortStateWY string = "WY"
+)
+
+// prop value enum
+func (m *Port) validateStateEnum(path, location string, value string) error {
+ if err := validate.EnumCase(path, location, value, portTypeStatePropEnum, true); err != nil {
+ return err
+ }
+ return nil
+}
+
+func (m *Port) validateState(formats strfmt.Registry) error {
+ if swag.IsZero(m.State) { // not required
+ return nil
+ }
+
+ // value enum
+ if err := m.validateStateEnum("state", "body", m.State); err != nil {
+ return err
+ }
+
+ return nil
+}
+
+func (m *Port) validateZip(formats strfmt.Registry) error {
+ if swag.IsZero(m.Zip) { // not required
+ return nil
+ }
+
+ if err := validate.Pattern("zip", "body", m.Zip, `^(\d{5}([\-]\d{4})?)$`); err != nil {
+ return err
+ }
+
+ return nil
+}
+
+// ContextValidate validates this port based on context it is used
+func (m *Port) ContextValidate(ctx context.Context, formats strfmt.Registry) error {
+ return nil
+}
+
+// MarshalBinary interface implementation
+func (m *Port) MarshalBinary() ([]byte, error) {
+ if m == nil {
+ return nil, nil
+ }
+ return swag.WriteJSON(m)
+}
+
+// UnmarshalBinary interface implementation
+func (m *Port) UnmarshalBinary(b []byte) error {
+ var res Port
+ if err := swag.ReadJSON(b, &res); err != nil {
+ return err
+ }
+ *m = res
+ return nil
+}
diff --git a/pkg/handlers/ghcapi/internal/payloads/model_to_payload.go b/pkg/handlers/ghcapi/internal/payloads/model_to_payload.go
index 20be502ac48..e2c02f30c06 100644
--- a/pkg/handlers/ghcapi/internal/payloads/model_to_payload.go
+++ b/pkg/handlers/ghcapi/internal/payloads/model_to_payload.go
@@ -1523,6 +1523,8 @@ func MTOShipment(storer storage.FileStorer, mtoShipment *models.MTOShipment, sit
DeliveryAddressUpdate: ShipmentAddressUpdate(mtoShipment.DeliveryAddressUpdate),
ShipmentLocator: handlers.FmtStringPtr(mtoShipment.ShipmentLocator),
MarketCode: MarketCode(&mtoShipment.MarketCode),
+ PoeLocation: Port(mtoShipment.MTOServiceItems, "POE"),
+ PodLocation: Port(mtoShipment.MTOServiceItems, "POD"),
}
if mtoShipment.Distance != nil {
@@ -2734,3 +2736,33 @@ func VLocations(vLocations models.VLocations) ghcmessages.VLocations {
}
return payload
}
+
+func Port(mtoServiceItems models.MTOServiceItems, portType string) *ghcmessages.Port {
+ if mtoServiceItems == nil {
+ return nil
+ }
+
+ for _, mtoServiceItem := range mtoServiceItems {
+ var portLocation *models.PortLocation
+ if portType == "POE" && mtoServiceItem.POELocation != nil {
+ portLocation = mtoServiceItem.POELocation
+ } else if portType == "POD" && mtoServiceItem.PODLocation != nil {
+ portLocation = mtoServiceItem.PODLocation
+ }
+
+ if portLocation != nil {
+ return &ghcmessages.Port{
+ ID: strfmt.UUID(portLocation.ID.String()),
+ PortType: portLocation.Port.PortType.String(),
+ PortCode: portLocation.Port.PortCode,
+ PortName: portLocation.Port.PortName,
+ City: portLocation.City.CityName,
+ County: portLocation.UsPostRegionCity.UsprcCountyNm,
+ State: portLocation.UsPostRegionCity.UsPostRegion.State.StateName,
+ Zip: portLocation.UsPostRegionCity.UsprZipID,
+ Country: portLocation.Country.CountryName,
+ }
+ }
+ }
+ return nil
+}
diff --git a/pkg/handlers/ghcapi/internal/payloads/model_to_payload_test.go b/pkg/handlers/ghcapi/internal/payloads/model_to_payload_test.go
index e170710f29f..fe164e85723 100644
--- a/pkg/handlers/ghcapi/internal/payloads/model_to_payload_test.go
+++ b/pkg/handlers/ghcapi/internal/payloads/model_to_payload_test.go
@@ -905,16 +905,16 @@ func (suite *PayloadsSuite) TestReServiceItems() {
marketCodeInternational := models.MarketCodeInternational
marketCodeDomestic := models.MarketCodeDomestic
poefscReServiceCode := models.ReServiceCodePOEFSC
- poedscReServiceCode := models.ReServiceCodePODFSC
+ podfscReServiceCode := models.ReServiceCodePODFSC
poefscServiceName := "International POE Fuel Surcharge"
- poedscServiceName := "International POD Fuel Surcharge"
+ podfscServiceName := "International POD Fuel Surcharge"
poefscService := models.ReService{
Code: poefscReServiceCode,
Name: poefscServiceName,
}
podfscService := models.ReService{
- Code: poedscReServiceCode,
- Name: poedscServiceName,
+ Code: podfscReServiceCode,
+ Name: podfscServiceName,
}
hhgShipmentType := models.MTOShipmentTypeHHG
ubShipmentType := models.MTOShipmentTypeUnaccompaniedBaggage
@@ -1218,3 +1218,138 @@ func (suite *PayloadsSuite) TestMTOServiceItemModel() {
suite.Equal(handlers.FmtString(models.MarketOconus.FullString()), result.Market, "Expected Market to be OCONUS")
})
}
+
+func (suite *PayloadsSuite) TestPort() {
+
+ suite.Run("returns nil when PortLocation is nil", func() {
+ var mtoServiceItems models.MTOServiceItems = nil
+ result := Port(mtoServiceItems, "POE")
+ suite.Nil(result, "Expected result to be nil when Port Location is nil")
+ })
+
+ suite.Run("Success - Maps PortLocation to Port payload", func() {
+ // Use the factory to create a port location
+ portLocation := factory.FetchPortLocation(suite.DB(), []factory.Customization{
+ {
+ Model: models.Port{
+ PortCode: "PDX",
+ },
+ },
+ }, nil)
+
+ mtoServiceItem := factory.BuildMTOServiceItem(nil, []factory.Customization{
+ {
+ Model: models.ReService{
+ Code: models.ReServiceCodePOEFSC,
+ },
+ },
+ {
+ Model: portLocation,
+ LinkOnly: true,
+ Type: &factory.PortLocations.PortOfEmbarkation,
+ },
+ }, nil)
+
+ // Actual
+ mtoServiceItems := models.MTOServiceItems{mtoServiceItem}
+ result := Port(mtoServiceItems, "POE")
+
+ // Assert
+ suite.IsType(&ghcmessages.Port{}, result)
+ suite.Equal(strfmt.UUID(portLocation.ID.String()), result.ID)
+ suite.Equal(portLocation.Port.PortType.String(), result.PortType)
+ suite.Equal(portLocation.Port.PortCode, result.PortCode)
+ suite.Equal(portLocation.Port.PortName, result.PortName)
+ suite.Equal(portLocation.City.CityName, result.City)
+ suite.Equal(portLocation.UsPostRegionCity.UsprcCountyNm, result.County)
+ suite.Equal(portLocation.UsPostRegionCity.UsPostRegion.State.StateName, result.State)
+ suite.Equal(portLocation.UsPostRegionCity.UsprZipID, result.Zip)
+ suite.Equal(portLocation.Country.CountryName, result.Country)
+ })
+}
+
+func (suite *PayloadsSuite) TestMTOShipment_POE_POD_Locations() {
+ suite.Run("Only POE Location is set", func() {
+ // Create mock data for MTOServiceItems with POE and POD
+ poePortLocation := factory.FetchPortLocation(suite.DB(), []factory.Customization{
+ {
+ Model: models.Port{
+ PortCode: "PDX",
+ },
+ },
+ }, nil)
+
+ poefscServiceItem := factory.BuildMTOServiceItem(nil, []factory.Customization{
+ {
+ Model: models.ReService{
+ Code: models.ReServiceCodePOEFSC,
+ Priority: 1,
+ },
+ },
+ {
+ Model: poePortLocation,
+ LinkOnly: true,
+ Type: &factory.PortLocations.PortOfEmbarkation,
+ },
+ }, nil)
+
+ mtoShipment := factory.BuildMTOShipment(suite.DB(), []factory.Customization{
+ {
+ Model: models.MTOShipment{
+ MTOServiceItems: models.MTOServiceItems{poefscServiceItem},
+ },
+ },
+ }, nil)
+
+ payload := MTOShipment(nil, &mtoShipment, nil)
+
+ // Assertions
+ suite.NotNil(payload, "Expected payload to not be nil")
+ suite.NotNil(payload.PoeLocation, "Expected POELocation to not be nil")
+ suite.Equal("PDX", payload.PoeLocation.PortCode, "Expected POE Port Code to match")
+ suite.Equal("PORTLAND INTL", payload.PoeLocation.PortName, "Expected POE Port Name to match")
+ suite.Nil(payload.PodLocation, "Expected PODLocation to be nil when POELocation is set")
+ })
+
+ suite.Run("Only POD Location is set", func() {
+ // Create mock data for MTOServiceItems with POE and POD
+ podPortLocation := factory.FetchPortLocation(suite.DB(), []factory.Customization{
+ {
+ Model: models.Port{
+ PortCode: "PDX",
+ },
+ },
+ }, nil)
+
+ podfscServiceItem := factory.BuildMTOServiceItem(nil, []factory.Customization{
+ {
+ Model: models.ReService{
+ Code: models.ReServiceCodePODFSC,
+ Priority: 1,
+ },
+ },
+ {
+ Model: podPortLocation,
+ LinkOnly: true,
+ Type: &factory.PortLocations.PortOfDebarkation,
+ },
+ }, nil)
+
+ mtoShipment := factory.BuildMTOShipment(suite.DB(), []factory.Customization{
+ {
+ Model: models.MTOShipment{
+ MTOServiceItems: models.MTOServiceItems{podfscServiceItem},
+ },
+ },
+ }, nil)
+
+ payload := MTOShipment(nil, &mtoShipment, nil)
+
+ // Assertions
+ suite.NotNil(payload, "Expected payload to not be nil")
+ suite.NotNil(payload.PodLocation, "Expected PODLocation to not be nil")
+ suite.Equal("PDX", payload.PodLocation.PortCode, "Expected POD Port Code to match")
+ suite.Equal("PORTLAND INTL", payload.PodLocation.PortName, "Expected POD Port Name to match")
+ suite.Nil(payload.PoeLocation, "Expected PODLocation to be nil when PODLocation is set")
+ })
+}
diff --git a/pkg/services/mto_shipment/mto_shipment_fetcher.go b/pkg/services/mto_shipment/mto_shipment_fetcher.go
index 6796fec5b30..01a19c9fbdb 100644
--- a/pkg/services/mto_shipment/mto_shipment_fetcher.go
+++ b/pkg/services/mto_shipment/mto_shipment_fetcher.go
@@ -53,6 +53,8 @@ func (f mtoShipmentFetcher) ListMTOShipments(appCtx appcontext.AppContext, moveI
"SecondaryDeliveryAddress.Country",
"TertiaryDeliveryAddress.Country",
"MTOServiceItems.Dimensions",
+ "MTOServiceItems.PODLocation.Port",
+ "MTOServiceItems.POELocation.Port",
"BoatShipment",
"MobileHome",
"PPMShipment.W2Address",
@@ -146,6 +148,22 @@ func (f mtoShipmentFetcher) ListMTOShipments(appCtx appcontext.AppContext, moveI
return nil, err
}
shipments[i].MTOAgents = agents
+
+ //Pull the port location info back
+ for _, serviceItem := range shipments[i].MTOServiceItems {
+ if serviceItem.PODLocation != nil {
+ loadErr := appCtx.DB().Load(serviceItem.PODLocation, "City", "Country", "UsPostRegionCity.UsPostRegion.State")
+ if loadErr != nil {
+ return nil, loadErr
+ }
+ }
+ if serviceItem.POELocation != nil {
+ loadErr := appCtx.DB().Load(serviceItem.POELocation, "City", "Country", "UsPostRegionCity.UsPostRegion.State")
+ if loadErr != nil {
+ return nil, loadErr
+ }
+ }
+ }
}
return shipments, nil
diff --git a/src/components/Office/ShipmentAddresses/ShipmentAddresses.jsx b/src/components/Office/ShipmentAddresses/ShipmentAddresses.jsx
index 34b8f0c791d..876aca3a848 100644
--- a/src/components/Office/ShipmentAddresses/ShipmentAddresses.jsx
+++ b/src/components/Office/ShipmentAddresses/ShipmentAddresses.jsx
@@ -5,7 +5,7 @@ import { FontAwesomeIcon } from '@fortawesome/react-fontawesome';
import { Button } from '@trussworks/react-uswds';
import { AddressShape } from '../../../types/address';
-import { formatAddress, formatCityStateAndPostalCode } from '../../../utils/shipmentDisplay';
+import { formatAddress, formatCityStateAndPostalCode, formatPortInfo } from '../../../utils/shipmentDisplay';
import DataTableWrapper from '../../DataTableWrapper/index';
import DataTable from '../../DataTable/index';
@@ -25,6 +25,8 @@ const ShipmentAddresses = ({
handleShowDiversionModal,
shipmentInfo,
isMoveLocked,
+ poeLocation,
+ podLocation,
}) => {
let pickupHeader;
let destinationHeader;
@@ -85,6 +87,10 @@ const ShipmentAddresses = ({
icon={}
data-testid="pickupDestinationAddress"
/>
+
);
};
diff --git a/src/components/Office/ShipmentAddresses/ShipmentAddresses.test.jsx b/src/components/Office/ShipmentAddresses/ShipmentAddresses.test.jsx
index 9153061aafa..9521d67fbbb 100644
--- a/src/components/Office/ShipmentAddresses/ShipmentAddresses.test.jsx
+++ b/src/components/Office/ShipmentAddresses/ShipmentAddresses.test.jsx
@@ -42,6 +42,8 @@ const testProps = {
shipmentLocator: 'ABCDEF-01',
},
diversionReason: '',
+ poeLocation: null,
+ podLocation: null,
};
const ppmShipment = {
@@ -184,6 +186,8 @@ describe('ShipmentAddresses', () => {
it('shows correct headings for HHG', () => {
render();
expect(screen.getByText("Customer's addresses")).toBeInTheDocument();
+ expect(screen.getByText('Port of Embarkation')).toBeInTheDocument();
+ expect(screen.getByText('Port of Debarkation')).toBeInTheDocument();
});
it('shows correct headings for NTS', () => {
diff --git a/src/components/Office/ShipmentDetails/ShipmentDetailsMain.jsx b/src/components/Office/ShipmentDetails/ShipmentDetailsMain.jsx
index 430d0808f60..c1914d2f9c1 100644
--- a/src/components/Office/ShipmentDetails/ShipmentDetailsMain.jsx
+++ b/src/components/Office/ShipmentDetails/ShipmentDetailsMain.jsx
@@ -67,6 +67,8 @@ const ShipmentDetailsMain = ({
storageInTransit,
shipmentType,
storageFacility,
+ poeLocation,
+ podLocation,
} = shipment;
const { originDutyLocationAddress, destinationDutyLocationAddress } = dutyLocationAddresses;
@@ -135,6 +137,8 @@ const ShipmentDetailsMain = ({
let pickupActualDate;
let plannedMoveDate;
let actualMoveDate;
+ let displayPoeLocation;
+ let displayPodLocation;
switch (shipmentType) {
case SHIPMENT_OPTIONS.HHG:
@@ -144,6 +148,8 @@ const ShipmentDetailsMain = ({
weightResult = primeEstimatedWeight;
displayedPickupAddress = pickupAddress;
displayedDeliveryAddress = destinationAddress || destinationDutyLocationAddress;
+ displayPoeLocation = poeLocation;
+ displayPodLocation = podLocation;
break;
case SHIPMENT_OPTIONS.NTS:
pickupRequestedDate = requestedPickupDate;
@@ -175,6 +181,8 @@ const ShipmentDetailsMain = ({
weightResult = primeEstimatedWeight;
displayedPickupAddress = pickupAddress;
displayedDeliveryAddress = destinationAddress || destinationDutyLocationAddress;
+ displayPoeLocation = poeLocation;
+ displayPodLocation = podLocation;
break;
}
@@ -260,6 +268,8 @@ const ShipmentDetailsMain = ({
}}
handleShowDiversionModal={handleShowDiversionModal}
isMoveLocked={isMoveLocked}
+ poeLocation={displayPoeLocation}
+ podLocation={displayPodLocation}
/>
{
expect(shipmentType).toEqual(shipmentModificationTypes.DIVERSION);
});
});
+
+ describe('formatPortInfo', () => {
+ it('formats port information correctly when all fields are provided', () => {
+ const port = {
+ portCode: 'PDX',
+ portName: 'PORTLAND INTL',
+ city: 'PORTLAND',
+ state: 'OREGON',
+ zip: '97220',
+ };
+ const formattedPortInfo = formatPortInfo(port);
+ expect(formattedPortInfo).toEqual('PDX - PORTLAND INTL\nPORTLAND, OREGON 97220');
+ });
+
+ it('returns a dash when no port is provided', () => {
+ const formattedPortInfo = formatPortInfo(null);
+ expect(formattedPortInfo).toEqual('-');
+ });
+ });
});
diff --git a/swagger-def/definitions/MTOShipment.yaml b/swagger-def/definitions/MTOShipment.yaml
index 2e3f55c6fbc..d11a9ec4023 100644
--- a/swagger-def/definitions/MTOShipment.yaml
+++ b/swagger-def/definitions/MTOShipment.yaml
@@ -217,3 +217,7 @@ properties:
- 'i'
example: 'd'
description: 'Single-letter designator for domestic (d) or international (i) shipments'
+ podLocation:
+ $ref: 'Port.yaml'
+ poeLocation:
+ $ref: 'Port.yaml'
diff --git a/swagger-def/ghc.yaml b/swagger-def/ghc.yaml
index 01d005b1ae6..e95349bcc3c 100644
--- a/swagger-def/ghc.yaml
+++ b/swagger-def/ghc.yaml
@@ -1062,6 +1062,7 @@ paths:
* Releasing / Receiving agents
* Actual Pro Gear Weight
* Actual Spouse Pro Gear Weight
+ * Location of the POE/POD
consumes:
- application/json
produces:
diff --git a/swagger/ghc.yaml b/swagger/ghc.yaml
index d8247650b54..23c28fdb556 100644
--- a/swagger/ghc.yaml
+++ b/swagger/ghc.yaml
@@ -1113,6 +1113,7 @@ paths:
* Releasing / Receiving agents
* Actual Pro Gear Weight
* Actual Spouse Pro Gear Weight
+ * Location of the POE/POD
consumes:
- application/json
produces:
@@ -10628,6 +10629,102 @@ definitions:
- originalAddress
- newAddress
- contractorRemarks
+ Port:
+ description: A port that is used to move an international shipment.
+ type: object
+ properties:
+ id:
+ type: string
+ format: uuid
+ example: c56a4180-65aa-42ec-a945-5fd21dec0538
+ portType:
+ type: string
+ description: Port type A (Air), B (Border Crossing), S (Sea)
+ enum:
+ - A
+ - B
+ - S
+ portCode:
+ type: string
+ description: 3 or 4 digit port code
+ example: '0431'
+ portName:
+ type: string
+ description: Name of the port
+ example: PORTLAND INTL
+ city:
+ type: string
+ example: PORTLAND
+ county:
+ type: string
+ example: MULTNOMAH
+ state:
+ type: string
+ description: US state
+ example: OR
+ enum:
+ - AL
+ - AK
+ - AR
+ - AZ
+ - CA
+ - CO
+ - CT
+ - DC
+ - DE
+ - FL
+ - GA
+ - HI
+ - IA
+ - ID
+ - IL
+ - IN
+ - KS
+ - KY
+ - LA
+ - MA
+ - MD
+ - ME
+ - MI
+ - MN
+ - MO
+ - MS
+ - MT
+ - NC
+ - ND
+ - NE
+ - NH
+ - NJ
+ - NM
+ - NV
+ - NY
+ - OH
+ - OK
+ - OR
+ - PA
+ - RI
+ - SC
+ - SD
+ - TN
+ - TX
+ - UT
+ - VA
+ - VT
+ - WA
+ - WI
+ - WV
+ - WY
+ zip:
+ type: string
+ format: zip
+ title: ZIP
+ example: '99501'
+ pattern: ^(\d{5}([\-]\d{4})?)$
+ country:
+ type: string
+ example: US
+ pattern: ^[A-Z]{2}$
+ description: Two-letter country code
MTOShipment:
properties:
moveTaskOrderID:
@@ -10858,6 +10955,10 @@ definitions:
description: >-
Single-letter designator for domestic (d) or international (i)
shipments
+ podLocation:
+ $ref: '#/definitions/Port'
+ poeLocation:
+ $ref: '#/definitions/Port'
LOATypeNullable:
description: The Line of accounting (TAC/SAC) type that will be used for the shipment
type: string