From 09d3cfa67968eb61e20e3ee4c34ce0cc984cec28 Mon Sep 17 00:00:00 2001 From: Alex Lusk Date: Wed, 18 Dec 2024 00:04:44 +0000 Subject: [PATCH 01/20] 21977 functioning - Services counselor can select counseling office when creating a move --- pkg/gen/ghcapi/configure_mymove.go | 5 + pkg/gen/ghcapi/embedded_spec.go | 132 +++++++++++++++++- pkg/gen/ghcapi/ghcoperations/mymove_api.go | 12 ++ ...sportation_offices_g_b_l_o_cs_responses.go | 2 +- .../show_counseling_offices.go | 58 ++++++++ .../show_counseling_offices_parameters.go | 91 ++++++++++++ .../show_counseling_offices_responses.go | 87 ++++++++++++ .../show_counseling_offices_urlbuilder.go | 101 ++++++++++++++ pkg/gen/ghcmessages/counseling_office.go | 95 +++++++++++++ pkg/gen/ghcmessages/counseling_offices.go | 78 +++++++++++ pkg/gen/ghcmessages/create_orders.go | 21 +++ pkg/handlers/ghcapi/api.go | 5 + .../internal/payloads/model_to_payload.go | 12 ++ pkg/handlers/ghcapi/orders.go | 12 +- pkg/handlers/ghcapi/tranportation_offices.go | 24 ++++ .../Office/AddOrdersForm/AddOrdersForm.jsx | 41 +++++- src/services/ghcApi.js | 4 + swagger-def/ghc.yaml | 47 ++++++- swagger/ghc.yaml | 49 ++++++- 19 files changed, 863 insertions(+), 13 deletions(-) create mode 100644 pkg/gen/ghcapi/ghcoperations/transportation_office/show_counseling_offices.go create mode 100644 pkg/gen/ghcapi/ghcoperations/transportation_office/show_counseling_offices_parameters.go create mode 100644 pkg/gen/ghcapi/ghcoperations/transportation_office/show_counseling_offices_responses.go create mode 100644 pkg/gen/ghcapi/ghcoperations/transportation_office/show_counseling_offices_urlbuilder.go create mode 100644 pkg/gen/ghcmessages/counseling_office.go create mode 100644 pkg/gen/ghcmessages/counseling_offices.go diff --git a/pkg/gen/ghcapi/configure_mymove.go b/pkg/gen/ghcapi/configure_mymove.go index 4ca4c62707f..5dc14161927 100644 --- a/pkg/gen/ghcapi/configure_mymove.go +++ b/pkg/gen/ghcapi/configure_mymove.go @@ -456,6 +456,11 @@ func configureAPI(api *ghcoperations.MymoveAPI) http.Handler { return middleware.NotImplemented("operation ppm.ShowAOAPacket has not yet been implemented") }) } + if api.TransportationOfficeShowCounselingOfficesHandler == nil { + api.TransportationOfficeShowCounselingOfficesHandler = transportation_office.ShowCounselingOfficesHandlerFunc(func(params transportation_office.ShowCounselingOfficesParams) middleware.Responder { + return middleware.NotImplemented("operation transportation_office.ShowCounselingOffices has not yet been implemented") + }) + } if api.PpmShowPaymentPacketHandler == nil { api.PpmShowPaymentPacketHandler = ppm.ShowPaymentPacketHandlerFunc(func(params ppm.ShowPaymentPacketParams) middleware.Responder { return middleware.NotImplemented("operation ppm.ShowPaymentPacket has not yet been implemented") diff --git a/pkg/gen/ghcapi/embedded_spec.go b/pkg/gen/ghcapi/embedded_spec.go index 005d774877f..39b6a4f900a 100644 --- a/pkg/gen/ghcapi/embedded_spec.go +++ b/pkg/gen/ghcapi/embedded_spec.go @@ -6109,7 +6109,7 @@ func init() { "operationId": "getTransportationOfficesGBLOCs", "responses": { "200": { - "description": "Successfully retrieved transportation offices", + "description": "Successfully retrieved GBLOCs", "schema": { "$ref": "#/definitions/GBLOCs" } @@ -6132,6 +6132,40 @@ func init() { } } }, + "/transportation_offices/{dutyLocationId}/counseling_offices": { + "get": { + "description": "Returns the counseling locations matching the GBLOC from the selected duty location", + "produces": [ + "application/json" + ], + "tags": [ + "transportationOffice" + ], + "summary": "Returns the counseling locations in the GBLOC matching the duty location", + "operationId": "showCounselingOffices", + "parameters": [ + { + "type": "string", + "format": "uuid", + "description": "UUID of the duty location", + "name": "dutyLocationId", + "in": "path", + "required": true + } + ], + "responses": { + "200": { + "description": "Successfully retrieved counseling offices", + "schema": { + "$ref": "#/definitions/CounselingOffices" + } + }, + "500": { + "description": "internal server error" + } + } + } + }, "/uploads": { "post": { "description": "Uploads represent a single digital file, such as a JPEG or PDF. Currently, office application uploads are only for Services Counselors to upload files for orders, but this may be expanded in the future.", @@ -6810,6 +6844,30 @@ func init() { } } }, + "CounselingOffice": { + "type": "object", + "required": [ + "id", + "name" + ], + "properties": { + "id": { + "type": "string", + "format": "uuid", + "example": "c56a4180-65aa-42ec-a945-5fd21dec0538" + }, + "name": { + "type": "string", + "example": "Fort Bragg North Station" + } + } + }, + "CounselingOffices": { + "type": "array", + "items": { + "$ref": "#/definitions/CounselingOffice" + } + }, "CounselingUpdateAllowancePayload": { "type": "object", "properties": { @@ -7411,6 +7469,12 @@ func init() { "x-nullable": true, "example": true }, + "counseling_office_id": { + "type": "string", + "format": "uuid", + "x-nullable": true, + "example": "cf1addea-a4f9-4173-8506-2bb82a064cb7" + }, "departmentIndicator": { "$ref": "#/definitions/DeptIndicator" }, @@ -22610,7 +22674,7 @@ func init() { "operationId": "getTransportationOfficesGBLOCs", "responses": { "200": { - "description": "Successfully retrieved transportation offices", + "description": "Successfully retrieved GBLOCs", "schema": { "$ref": "#/definitions/GBLOCs" } @@ -22648,6 +22712,40 @@ func init() { } } }, + "/transportation_offices/{dutyLocationId}/counseling_offices": { + "get": { + "description": "Returns the counseling locations matching the GBLOC from the selected duty location", + "produces": [ + "application/json" + ], + "tags": [ + "transportationOffice" + ], + "summary": "Returns the counseling locations in the GBLOC matching the duty location", + "operationId": "showCounselingOffices", + "parameters": [ + { + "type": "string", + "format": "uuid", + "description": "UUID of the duty location", + "name": "dutyLocationId", + "in": "path", + "required": true + } + ], + "responses": { + "200": { + "description": "Successfully retrieved counseling offices", + "schema": { + "$ref": "#/definitions/CounselingOffices" + } + }, + "500": { + "description": "internal server error" + } + } + } + }, "/uploads": { "post": { "description": "Uploads represent a single digital file, such as a JPEG or PDF. Currently, office application uploads are only for Services Counselors to upload files for orders, but this may be expanded in the future.", @@ -23342,6 +23440,30 @@ func init() { } } }, + "CounselingOffice": { + "type": "object", + "required": [ + "id", + "name" + ], + "properties": { + "id": { + "type": "string", + "format": "uuid", + "example": "c56a4180-65aa-42ec-a945-5fd21dec0538" + }, + "name": { + "type": "string", + "example": "Fort Bragg North Station" + } + } + }, + "CounselingOffices": { + "type": "array", + "items": { + "$ref": "#/definitions/CounselingOffice" + } + }, "CounselingUpdateAllowancePayload": { "type": "object", "properties": { @@ -23947,6 +24069,12 @@ func init() { "x-nullable": true, "example": true }, + "counseling_office_id": { + "type": "string", + "format": "uuid", + "x-nullable": true, + "example": "cf1addea-a4f9-4173-8506-2bb82a064cb7" + }, "departmentIndicator": { "$ref": "#/definitions/DeptIndicator" }, diff --git a/pkg/gen/ghcapi/ghcoperations/mymove_api.go b/pkg/gen/ghcapi/ghcoperations/mymove_api.go index 0809cb3b701..b7b59bf7947 100644 --- a/pkg/gen/ghcapi/ghcoperations/mymove_api.go +++ b/pkg/gen/ghcapi/ghcoperations/mymove_api.go @@ -301,6 +301,9 @@ func NewMymoveAPI(spec *loads.Document) *MymoveAPI { PpmShowAOAPacketHandler: ppm.ShowAOAPacketHandlerFunc(func(params ppm.ShowAOAPacketParams) middleware.Responder { return middleware.NotImplemented("operation ppm.ShowAOAPacket has not yet been implemented") }), + TransportationOfficeShowCounselingOfficesHandler: transportation_office.ShowCounselingOfficesHandlerFunc(func(params transportation_office.ShowCounselingOfficesParams) middleware.Responder { + return middleware.NotImplemented("operation transportation_office.ShowCounselingOffices has not yet been implemented") + }), PpmShowPaymentPacketHandler: ppm.ShowPaymentPacketHandlerFunc(func(params ppm.ShowPaymentPacketParams) middleware.Responder { return middleware.NotImplemented("operation ppm.ShowPaymentPacket has not yet been implemented") }), @@ -585,6 +588,8 @@ type MymoveAPI struct { MoveSetFinancialReviewFlagHandler move.SetFinancialReviewFlagHandler // PpmShowAOAPacketHandler sets the operation handler for the show a o a packet operation PpmShowAOAPacketHandler ppm.ShowAOAPacketHandler + // TransportationOfficeShowCounselingOfficesHandler sets the operation handler for the show counseling offices operation + TransportationOfficeShowCounselingOfficesHandler transportation_office.ShowCounselingOfficesHandler // PpmShowPaymentPacketHandler sets the operation handler for the show payment packet operation PpmShowPaymentPacketHandler ppm.ShowPaymentPacketHandler // EvaluationReportsSubmitEvaluationReportHandler sets the operation handler for the submit evaluation report operation @@ -955,6 +960,9 @@ func (o *MymoveAPI) Validate() error { if o.PpmShowAOAPacketHandler == nil { unregistered = append(unregistered, "ppm.ShowAOAPacketHandler") } + if o.TransportationOfficeShowCounselingOfficesHandler == nil { + unregistered = append(unregistered, "transportation_office.ShowCounselingOfficesHandler") + } if o.PpmShowPaymentPacketHandler == nil { unregistered = append(unregistered, "ppm.ShowPaymentPacketHandler") } @@ -1442,6 +1450,10 @@ func (o *MymoveAPI) initHandlerCache() { if o.handlers["GET"] == nil { o.handlers["GET"] = make(map[string]http.Handler) } + o.handlers["GET"]["/transportation_offices/{dutyLocationId}/counseling_offices"] = transportation_office.NewShowCounselingOffices(o.context, o.TransportationOfficeShowCounselingOfficesHandler) + if o.handlers["GET"] == nil { + o.handlers["GET"] = make(map[string]http.Handler) + } o.handlers["GET"]["/ppm-shipments/{ppmShipmentId}/payment-packet"] = ppm.NewShowPaymentPacket(o.context, o.PpmShowPaymentPacketHandler) if o.handlers["POST"] == nil { o.handlers["POST"] = make(map[string]http.Handler) diff --git a/pkg/gen/ghcapi/ghcoperations/transportation_office/get_transportation_offices_g_b_l_o_cs_responses.go b/pkg/gen/ghcapi/ghcoperations/transportation_office/get_transportation_offices_g_b_l_o_cs_responses.go index 309de84d0fa..c630be03fd6 100644 --- a/pkg/gen/ghcapi/ghcoperations/transportation_office/get_transportation_offices_g_b_l_o_cs_responses.go +++ b/pkg/gen/ghcapi/ghcoperations/transportation_office/get_transportation_offices_g_b_l_o_cs_responses.go @@ -17,7 +17,7 @@ import ( const GetTransportationOfficesGBLOCsOKCode int = 200 /* -GetTransportationOfficesGBLOCsOK Successfully retrieved transportation offices +GetTransportationOfficesGBLOCsOK Successfully retrieved GBLOCs swagger:response getTransportationOfficesGBLOCsOK */ diff --git a/pkg/gen/ghcapi/ghcoperations/transportation_office/show_counseling_offices.go b/pkg/gen/ghcapi/ghcoperations/transportation_office/show_counseling_offices.go new file mode 100644 index 00000000000..5b4c1967e43 --- /dev/null +++ b/pkg/gen/ghcapi/ghcoperations/transportation_office/show_counseling_offices.go @@ -0,0 +1,58 @@ +// Code generated by go-swagger; DO NOT EDIT. + +package transportation_office + +// This file was generated by the swagger tool. +// Editing this file might prove futile when you re-run the generate command + +import ( + "net/http" + + "github.com/go-openapi/runtime/middleware" +) + +// ShowCounselingOfficesHandlerFunc turns a function with the right signature into a show counseling offices handler +type ShowCounselingOfficesHandlerFunc func(ShowCounselingOfficesParams) middleware.Responder + +// Handle executing the request and returning a response +func (fn ShowCounselingOfficesHandlerFunc) Handle(params ShowCounselingOfficesParams) middleware.Responder { + return fn(params) +} + +// ShowCounselingOfficesHandler interface for that can handle valid show counseling offices params +type ShowCounselingOfficesHandler interface { + Handle(ShowCounselingOfficesParams) middleware.Responder +} + +// NewShowCounselingOffices creates a new http.Handler for the show counseling offices operation +func NewShowCounselingOffices(ctx *middleware.Context, handler ShowCounselingOfficesHandler) *ShowCounselingOffices { + return &ShowCounselingOffices{Context: ctx, Handler: handler} +} + +/* + ShowCounselingOffices swagger:route GET /transportation_offices/{dutyLocationId}/counseling_offices transportationOffice showCounselingOffices + +# Returns the counseling locations in the GBLOC matching the duty location + +Returns the counseling locations matching the GBLOC from the selected duty location +*/ +type ShowCounselingOffices struct { + Context *middleware.Context + Handler ShowCounselingOfficesHandler +} + +func (o *ShowCounselingOffices) ServeHTTP(rw http.ResponseWriter, r *http.Request) { + route, rCtx, _ := o.Context.RouteInfo(r) + if rCtx != nil { + *r = *rCtx + } + var Params = NewShowCounselingOfficesParams() + if err := o.Context.BindValidRequest(r, route, &Params); err != nil { // bind params + o.Context.Respond(rw, r, route.Produces, route, err) + return + } + + res := o.Handler.Handle(Params) // actually handle the request + o.Context.Respond(rw, r, route.Produces, route, res) + +} diff --git a/pkg/gen/ghcapi/ghcoperations/transportation_office/show_counseling_offices_parameters.go b/pkg/gen/ghcapi/ghcoperations/transportation_office/show_counseling_offices_parameters.go new file mode 100644 index 00000000000..24f4c585bfd --- /dev/null +++ b/pkg/gen/ghcapi/ghcoperations/transportation_office/show_counseling_offices_parameters.go @@ -0,0 +1,91 @@ +// Code generated by go-swagger; DO NOT EDIT. + +package transportation_office + +// This file was generated by the swagger tool. +// Editing this file might prove futile when you re-run the swagger generate command + +import ( + "net/http" + + "github.com/go-openapi/errors" + "github.com/go-openapi/runtime/middleware" + "github.com/go-openapi/strfmt" + "github.com/go-openapi/validate" +) + +// NewShowCounselingOfficesParams creates a new ShowCounselingOfficesParams object +// +// There are no default values defined in the spec. +func NewShowCounselingOfficesParams() ShowCounselingOfficesParams { + + return ShowCounselingOfficesParams{} +} + +// ShowCounselingOfficesParams contains all the bound params for the show counseling offices operation +// typically these are obtained from a http.Request +// +// swagger:parameters showCounselingOffices +type ShowCounselingOfficesParams struct { + + // HTTP Request Object + HTTPRequest *http.Request `json:"-"` + + /*UUID of the duty location + Required: true + In: path + */ + DutyLocationID strfmt.UUID +} + +// BindRequest both binds and validates a request, it assumes that complex things implement a Validatable(strfmt.Registry) error interface +// for simple values it will use straight method calls. +// +// To ensure default values, the struct must have been initialized with NewShowCounselingOfficesParams() beforehand. +func (o *ShowCounselingOfficesParams) BindRequest(r *http.Request, route *middleware.MatchedRoute) error { + var res []error + + o.HTTPRequest = r + + rDutyLocationID, rhkDutyLocationID, _ := route.Params.GetOK("dutyLocationId") + if err := o.bindDutyLocationID(rDutyLocationID, rhkDutyLocationID, route.Formats); err != nil { + res = append(res, err) + } + if len(res) > 0 { + return errors.CompositeValidationError(res...) + } + return nil +} + +// bindDutyLocationID binds and validates parameter DutyLocationID from path. +func (o *ShowCounselingOfficesParams) bindDutyLocationID(rawData []string, hasKey bool, formats strfmt.Registry) error { + var raw string + if len(rawData) > 0 { + raw = rawData[len(rawData)-1] + } + + // Required: true + // Parameter is provided by construction from the route + + // Format: uuid + value, err := formats.Parse("uuid", raw) + if err != nil { + return errors.InvalidType("dutyLocationId", "path", "strfmt.UUID", raw) + } + o.DutyLocationID = *(value.(*strfmt.UUID)) + + if err := o.validateDutyLocationID(formats); err != nil { + return err + } + + return nil +} + +// validateDutyLocationID carries on validations for parameter DutyLocationID +func (o *ShowCounselingOfficesParams) validateDutyLocationID(formats strfmt.Registry) error { + + if err := validate.FormatOf("dutyLocationId", "path", "uuid", o.DutyLocationID.String(), formats); err != nil { + return err + } + return nil +} diff --git a/pkg/gen/ghcapi/ghcoperations/transportation_office/show_counseling_offices_responses.go b/pkg/gen/ghcapi/ghcoperations/transportation_office/show_counseling_offices_responses.go new file mode 100644 index 00000000000..73793566c47 --- /dev/null +++ b/pkg/gen/ghcapi/ghcoperations/transportation_office/show_counseling_offices_responses.go @@ -0,0 +1,87 @@ +// Code generated by go-swagger; DO NOT EDIT. + +package transportation_office + +// This file was generated by the swagger tool. +// Editing this file might prove futile when you re-run the swagger generate command + +import ( + "net/http" + + "github.com/go-openapi/runtime" + + "github.com/transcom/mymove/pkg/gen/ghcmessages" +) + +// ShowCounselingOfficesOKCode is the HTTP code returned for type ShowCounselingOfficesOK +const ShowCounselingOfficesOKCode int = 200 + +/* +ShowCounselingOfficesOK Successfully retrieved counseling offices + +swagger:response showCounselingOfficesOK +*/ +type ShowCounselingOfficesOK struct { + + /* + In: Body + */ + Payload ghcmessages.CounselingOffices `json:"body,omitempty"` +} + +// NewShowCounselingOfficesOK creates ShowCounselingOfficesOK with default headers values +func NewShowCounselingOfficesOK() *ShowCounselingOfficesOK { + + return &ShowCounselingOfficesOK{} +} + +// WithPayload adds the payload to the show counseling offices o k response +func (o *ShowCounselingOfficesOK) WithPayload(payload ghcmessages.CounselingOffices) *ShowCounselingOfficesOK { + o.Payload = payload + return o +} + +// SetPayload sets the payload to the show counseling offices o k response +func (o *ShowCounselingOfficesOK) SetPayload(payload ghcmessages.CounselingOffices) { + o.Payload = payload +} + +// WriteResponse to the client +func (o *ShowCounselingOfficesOK) WriteResponse(rw http.ResponseWriter, producer runtime.Producer) { + + rw.WriteHeader(200) + payload := o.Payload + if payload == nil { + // return empty array + payload = ghcmessages.CounselingOffices{} + } + + if err := producer.Produce(rw, payload); err != nil { + panic(err) // let the recovery middleware deal with this + } +} + +// ShowCounselingOfficesInternalServerErrorCode is the HTTP code returned for type ShowCounselingOfficesInternalServerError +const ShowCounselingOfficesInternalServerErrorCode int = 500 + +/* +ShowCounselingOfficesInternalServerError internal server error + +swagger:response showCounselingOfficesInternalServerError +*/ +type ShowCounselingOfficesInternalServerError struct { +} + +// NewShowCounselingOfficesInternalServerError creates ShowCounselingOfficesInternalServerError with default headers values +func NewShowCounselingOfficesInternalServerError() *ShowCounselingOfficesInternalServerError { + + return &ShowCounselingOfficesInternalServerError{} +} + +// WriteResponse to the client +func (o *ShowCounselingOfficesInternalServerError) WriteResponse(rw http.ResponseWriter, producer runtime.Producer) { + + rw.Header().Del(runtime.HeaderContentType) //Remove Content-Type on empty responses + + rw.WriteHeader(500) +} diff --git a/pkg/gen/ghcapi/ghcoperations/transportation_office/show_counseling_offices_urlbuilder.go b/pkg/gen/ghcapi/ghcoperations/transportation_office/show_counseling_offices_urlbuilder.go new file mode 100644 index 00000000000..1f0e360afa7 --- /dev/null +++ b/pkg/gen/ghcapi/ghcoperations/transportation_office/show_counseling_offices_urlbuilder.go @@ -0,0 +1,101 @@ +// Code generated by go-swagger; DO NOT EDIT. + +package transportation_office + +// This file was generated by the swagger tool. +// Editing this file might prove futile when you re-run the generate command + +import ( + "errors" + "net/url" + golangswaggerpaths "path" + "strings" + + "github.com/go-openapi/strfmt" +) + +// ShowCounselingOfficesURL generates an URL for the show counseling offices operation +type ShowCounselingOfficesURL struct { + DutyLocationID strfmt.UUID + + _basePath string + // avoid unkeyed usage + _ struct{} +} + +// WithBasePath sets the base path for this url builder, only required when it's different from the +// base path specified in the swagger spec. +// When the value of the base path is an empty string +func (o *ShowCounselingOfficesURL) WithBasePath(bp string) *ShowCounselingOfficesURL { + o.SetBasePath(bp) + return o +} + +// SetBasePath sets the base path for this url builder, only required when it's different from the +// base path specified in the swagger spec. +// When the value of the base path is an empty string +func (o *ShowCounselingOfficesURL) SetBasePath(bp string) { + o._basePath = bp +} + +// Build a url path and query string +func (o *ShowCounselingOfficesURL) Build() (*url.URL, error) { + var _result url.URL + + var _path = "/transportation_offices/{dutyLocationId}/counseling_offices" + + dutyLocationID := o.DutyLocationID.String() + if dutyLocationID != "" { + _path = strings.Replace(_path, "{dutyLocationId}", dutyLocationID, -1) + } else { + return nil, errors.New("dutyLocationId is required on ShowCounselingOfficesURL") + } + + _basePath := o._basePath + if _basePath == "" { + _basePath = "/ghc/v1" + } + _result.Path = golangswaggerpaths.Join(_basePath, _path) + + return &_result, nil +} + +// Must is a helper function to panic when the url builder returns an error +func (o *ShowCounselingOfficesURL) Must(u *url.URL, err error) *url.URL { + if err != nil { + panic(err) + } + if u == nil { + panic("url can't be nil") + } + return u +} + +// String returns the string representation of the path with query string +func (o *ShowCounselingOfficesURL) String() string { + return o.Must(o.Build()).String() +} + +// BuildFull builds a full url with scheme, host, path and query string +func (o *ShowCounselingOfficesURL) BuildFull(scheme, host string) (*url.URL, error) { + if scheme == "" { + return nil, errors.New("scheme is required for a full url on ShowCounselingOfficesURL") + } + if host == "" { + return nil, errors.New("host is required for a full url on ShowCounselingOfficesURL") + } + + base, err := o.Build() + if err != nil { + return nil, err + } + + base.Scheme = scheme + base.Host = host + return base, nil +} + +// StringFull returns the string representation of a complete url +func (o *ShowCounselingOfficesURL) StringFull(scheme, host string) string { + return o.Must(o.BuildFull(scheme, host)).String() +} diff --git a/pkg/gen/ghcmessages/counseling_office.go b/pkg/gen/ghcmessages/counseling_office.go new file mode 100644 index 00000000000..b3bf2fea949 --- /dev/null +++ b/pkg/gen/ghcmessages/counseling_office.go @@ -0,0 +1,95 @@ +// 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" + + "github.com/go-openapi/errors" + "github.com/go-openapi/strfmt" + "github.com/go-openapi/swag" + "github.com/go-openapi/validate" +) + +// CounselingOffice counseling office +// +// swagger:model CounselingOffice +type CounselingOffice struct { + + // id + // Example: c56a4180-65aa-42ec-a945-5fd21dec0538 + // Required: true + // Format: uuid + ID *strfmt.UUID `json:"id"` + + // name + // Example: Fort Bragg North Station + // Required: true + Name *string `json:"name"` +} + +// Validate validates this counseling office +func (m *CounselingOffice) Validate(formats strfmt.Registry) error { + var res []error + + if err := m.validateID(formats); err != nil { + res = append(res, err) + } + + if err := m.validateName(formats); err != nil { + res = append(res, err) + } + + if len(res) > 0 { + return errors.CompositeValidationError(res...) + } + return nil +} + +func (m *CounselingOffice) validateID(formats strfmt.Registry) error { + + if err := validate.Required("id", "body", m.ID); err != nil { + return err + } + + if err := validate.FormatOf("id", "body", "uuid", m.ID.String(), formats); err != nil { + return err + } + + return nil +} + +func (m *CounselingOffice) validateName(formats strfmt.Registry) error { + + if err := validate.Required("name", "body", m.Name); err != nil { + return err + } + + return nil +} + +// ContextValidate validates this counseling office based on context it is used +func (m *CounselingOffice) ContextValidate(ctx context.Context, formats strfmt.Registry) error { + return nil +} + +// MarshalBinary interface implementation +func (m *CounselingOffice) MarshalBinary() ([]byte, error) { + if m == nil { + return nil, nil + } + return swag.WriteJSON(m) +} + +// UnmarshalBinary interface implementation +func (m *CounselingOffice) UnmarshalBinary(b []byte) error { + var res CounselingOffice + if err := swag.ReadJSON(b, &res); err != nil { + return err + } + *m = res + return nil +} diff --git a/pkg/gen/ghcmessages/counseling_offices.go b/pkg/gen/ghcmessages/counseling_offices.go new file mode 100644 index 00000000000..28a6d79e3b3 --- /dev/null +++ b/pkg/gen/ghcmessages/counseling_offices.go @@ -0,0 +1,78 @@ +// 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" + "strconv" + + "github.com/go-openapi/errors" + "github.com/go-openapi/strfmt" + "github.com/go-openapi/swag" +) + +// CounselingOffices counseling offices +// +// swagger:model CounselingOffices +type CounselingOffices []*CounselingOffice + +// Validate validates this counseling offices +func (m CounselingOffices) Validate(formats strfmt.Registry) error { + var res []error + + for i := 0; i < len(m); i++ { + if swag.IsZero(m[i]) { // not required + continue + } + + if m[i] != nil { + if err := m[i].Validate(formats); err != nil { + if ve, ok := err.(*errors.Validation); ok { + return ve.ValidateName(strconv.Itoa(i)) + } else if ce, ok := err.(*errors.CompositeError); ok { + return ce.ValidateName(strconv.Itoa(i)) + } + return err + } + } + + } + + if len(res) > 0 { + return errors.CompositeValidationError(res...) + } + return nil +} + +// ContextValidate validate this counseling offices based on the context it is used +func (m CounselingOffices) ContextValidate(ctx context.Context, formats strfmt.Registry) error { + var res []error + + for i := 0; i < len(m); i++ { + + if m[i] != nil { + + if swag.IsZero(m[i]) { // not required + return nil + } + + if err := m[i].ContextValidate(ctx, formats); err != nil { + if ve, ok := err.(*errors.Validation); ok { + return ve.ValidateName(strconv.Itoa(i)) + } else if ce, ok := err.(*errors.CompositeError); ok { + return ce.ValidateName(strconv.Itoa(i)) + } + return err + } + } + + } + + if len(res) > 0 { + return errors.CompositeValidationError(res...) + } + return nil +} diff --git a/pkg/gen/ghcmessages/create_orders.go b/pkg/gen/ghcmessages/create_orders.go index 25f77f42c15..d253d74c0aa 100644 --- a/pkg/gen/ghcmessages/create_orders.go +++ b/pkg/gen/ghcmessages/create_orders.go @@ -23,6 +23,11 @@ type CreateOrders struct { // Example: true AccompaniedTour *bool `json:"accompaniedTour,omitempty"` + // counseling office id + // Example: cf1addea-a4f9-4173-8506-2bb82a064cb7 + // Format: uuid + CounselingOfficeID *strfmt.UUID `json:"counseling_office_id,omitempty"` + // department indicator DepartmentIndicator *DeptIndicator `json:"departmentIndicator,omitempty"` @@ -100,6 +105,10 @@ type CreateOrders struct { func (m *CreateOrders) Validate(formats strfmt.Registry) error { var res []error + if err := m.validateCounselingOfficeID(formats); err != nil { + res = append(res, err) + } + if err := m.validateDepartmentIndicator(formats); err != nil { res = append(res, err) } @@ -150,6 +159,18 @@ func (m *CreateOrders) Validate(formats strfmt.Registry) error { return nil } +func (m *CreateOrders) validateCounselingOfficeID(formats strfmt.Registry) error { + if swag.IsZero(m.CounselingOfficeID) { // not required + return nil + } + + if err := validate.FormatOf("counseling_office_id", "body", "uuid", m.CounselingOfficeID.String(), formats); err != nil { + return err + } + + return nil +} + func (m *CreateOrders) validateDepartmentIndicator(formats strfmt.Registry) error { if swag.IsZero(m.DepartmentIndicator) { // not required return nil diff --git a/pkg/handlers/ghcapi/api.go b/pkg/handlers/ghcapi/api.go index 5edc3f7e3ee..b97cd843244 100644 --- a/pkg/handlers/ghcapi/api.go +++ b/pkg/handlers/ghcapi/api.go @@ -641,6 +641,11 @@ func NewGhcAPIHandler(handlerConfig handlers.HandlerConfig) *ghcops.MymoveAPI { transportationOfficeFetcher, } + ghcAPI.TransportationOfficeShowCounselingOfficesHandler = ShowCounselingOfficesHandler{ + handlerConfig, + transportationOfficeFetcher, + } + ghcAPI.MoveUpdateCloseoutOfficeHandler = UpdateMoveCloseoutOfficeHandler{ handlerConfig, closeoutOfficeUpdater, diff --git a/pkg/handlers/ghcapi/internal/payloads/model_to_payload.go b/pkg/handlers/ghcapi/internal/payloads/model_to_payload.go index ebfbf27c303..41951384931 100644 --- a/pkg/handlers/ghcapi/internal/payloads/model_to_payload.go +++ b/pkg/handlers/ghcapi/internal/payloads/model_to_payload.go @@ -435,6 +435,18 @@ func GBLOCs(gblocs []string) ghcmessages.GBLOCs { return payload } +func CounselingOffices(counselingOffices models.TransportationOffices) ghcmessages.CounselingOffices { + payload := make(ghcmessages.CounselingOffices, len(counselingOffices)) + + for i, counselingOffice := range counselingOffices { + payload[i] = &ghcmessages.CounselingOffice{ + ID: handlers.FmtUUID(counselingOffice.ID), + Name: models.StringPointer(counselingOffice.Name), + } + } + return payload +} + // MoveHistory payload func MoveHistory(logger *zap.Logger, moveHistory *models.MoveHistory) *ghcmessages.MoveHistory { payload := &ghcmessages.MoveHistory{ diff --git a/pkg/handlers/ghcapi/orders.go b/pkg/handlers/ghcapi/orders.go index 9f0ce28404a..8488bf64db4 100644 --- a/pkg/handlers/ghcapi/orders.go +++ b/pkg/handlers/ghcapi/orders.go @@ -330,15 +330,13 @@ func (h CreateOrderHandler) Handle(params orderop.CreateOrderParams) middleware. Show: models.BoolPointer(true), Status: &status, } - if !appCtx.Session().OfficeUserID.IsNil() { - officeUser, err := models.FetchOfficeUserByID(appCtx.DB(), appCtx.Session().OfficeUserID) + + if payload.CounselingOfficeID != nil { + counselingOffice, err := uuid.FromString(payload.CounselingOfficeID.String()) if err != nil { - err = apperror.NewBadDataError("Unable to fetch office user.") - appCtx.Logger().Error(err.Error()) - return orderop.NewCreateOrderUnprocessableEntity(), err - } else { - moveOptions.CounselingOfficeID = &officeUser.TransportationOfficeID + return handlers.ResponseForError(appCtx.Logger(), err), err } + moveOptions.CounselingOfficeID = &counselingOffice } if newOrder.OrdersType == "SAFETY" { diff --git a/pkg/handlers/ghcapi/tranportation_offices.go b/pkg/handlers/ghcapi/tranportation_offices.go index 405580923bb..6c0dcacc1b6 100644 --- a/pkg/handlers/ghcapi/tranportation_offices.go +++ b/pkg/handlers/ghcapi/tranportation_offices.go @@ -2,6 +2,7 @@ package ghcapi import ( "github.com/go-openapi/runtime/middleware" + "github.com/gofrs/uuid" "go.uber.org/zap" "github.com/transcom/mymove/pkg/appcontext" @@ -73,3 +74,26 @@ func (h GetTransportationOfficesGBLOCsHandler) Handle(params transportationoffic return transportationofficeop.NewGetTransportationOfficesGBLOCsOK().WithPayload(returnPayload), nil }) } + +// ShowCounselingOfficesHandler returns the counseling offices for a duty location ID +type ShowCounselingOfficesHandler struct { + handlers.HandlerConfig + services.TransportationOfficesFetcher +} + +// Handle retrieves the counseling offices in the system for a given duty location ID +func (h ShowCounselingOfficesHandler) Handle(params transportationofficeop.ShowCounselingOfficesParams) middleware.Responder { + return h.AuditableAppContextFromRequestWithErrors(params.HTTPRequest, + func(appCtx appcontext.AppContext) (middleware.Responder, error) { + dutyLocationID := uuid.FromStringOrNil(params.DutyLocationID.String()) + + counselingOffices, err := h.TransportationOfficesFetcher.GetCounselingOffices(appCtx, dutyLocationID) + if err != nil { + appCtx.Logger().Error("Error searching for Counseling Offices: ", zap.Error(err)) + return transportationofficeop.NewShowCounselingOfficesInternalServerError(), err + } + + returnPayload := payloads.CounselingOffices(*counselingOffices) + return transportationofficeop.NewShowCounselingOfficesOK().WithPayload(returnPayload), nil + }) +} diff --git a/src/components/Office/AddOrdersForm/AddOrdersForm.jsx b/src/components/Office/AddOrdersForm/AddOrdersForm.jsx index 07949b46c2e..dfc7929d597 100644 --- a/src/components/Office/AddOrdersForm/AddOrdersForm.jsx +++ b/src/components/Office/AddOrdersForm/AddOrdersForm.jsx @@ -20,11 +20,13 @@ import Callout from 'components/Callout'; import MaskedTextField from 'components/form/fields/MaskedTextField/MaskedTextField'; import formStyles from 'styles/form.module.scss'; import ConnectedFlashMessage from 'containers/FlashMessage/FlashMessage'; +import { showCounselingOffices } from 'services/ghcApi'; let originMeta; let newDutyMeta = ''; const AddOrdersForm = ({ onSubmit, ordersTypeOptions, initialValues, onBack, isSafetyMoveSelected }) => { const payGradeOptions = dropdownInputOptions(ORDERS_PAY_GRADE_OPTIONS); + const [counselingOfficeOptions, setCounselingOfficeOptions] = useState(null); const [currentDutyLocation, setCurrentDutyLocation] = useState(''); const [newDutyLocation, setNewDutyLocation] = useState(''); const [showAccompaniedTourField, setShowAccompaniedTourField] = useState(false); @@ -69,6 +71,17 @@ const AddOrdersForm = ({ onSubmit, ordersTypeOptions, initialValues, onBack, isS }, []); useEffect(() => { + if (currentDutyLocation?.id) { + showCounselingOffices(currentDutyLocation.id).then((fetchedData) => { + if (fetchedData.body) { + const counselingOffices = fetchedData.body.map((item) => ({ + key: item.id, + value: item.name, + })); + setCounselingOfficeOptions(counselingOffices); + } + }); + } // Check if either currentDutyLocation or newDutyLocation is OCONUS if (currentDutyLocation?.address?.isOconus || newDutyLocation?.address?.isOconus) { setIsOconusMove(true); @@ -90,11 +103,19 @@ const AddOrdersForm = ({ onSubmit, ordersTypeOptions, initialValues, onBack, isS return ( - {({ values, isValid, isSubmitting, handleSubmit, touched, setFieldValue }) => { + {({ values, isValid, isSubmitting, handleSubmit, touched, setFieldValue, setValues }) => { const isRetirementOrSeparation = ['RETIREMENT', 'SEPARATION'].includes(values.ordersType); if (!values.origin_duty_location && touched.origin_duty_location) originMeta = 'Required'; else originMeta = null; + const handleCounselingOfficeChange = () => { + setValues({ + ...values, + counseling_office_id: null, + }); + setCounselingOfficeOptions(null); + }; + if (!values.newDutyLocation && touched.newDutyLocation) newDutyMeta = 'Required'; else newDutyMeta = null; const handleHasDependentsChange = (e) => { @@ -133,10 +154,28 @@ const AddOrdersForm = ({ onSubmit, ordersTypeOptions, initialValues, onBack, isS id="originDutyLocation" onDutyLocationChange={(e) => { setCurrentDutyLocation(e); + handleCounselingOfficeChange(); }} metaOverride={originMeta} required /> + {currentDutyLocation.provides_services_counseling && ( +
+ + +
+ )} {isRetirementOrSeparation ? ( <> diff --git a/src/services/ghcApi.js b/src/services/ghcApi.js index de5d1ea9092..043616613b5 100644 --- a/src/services/ghcApi.js +++ b/src/services/ghcApi.js @@ -754,6 +754,10 @@ export async function getGBLOCs() { return makeGHCRequest(operationPath, {}, { normalize: false }); } +export async function showCounselingOffices(dutyLocationId) { + return makeGHCRequestRaw('transportationOffice.showCounselingOffices', { dutyLocationId }); +} + export const reviewShipmentAddressUpdate = async ({ shipmentID, ifMatchETag, body }) => { const operationPath = 'shipment.reviewShipmentAddressUpdate'; const schemaKey = 'ShipmentAddressUpdate'; diff --git a/swagger-def/ghc.yaml b/swagger-def/ghc.yaml index b3889e88eab..c9abaf62e5c 100644 --- a/swagger-def/ghc.yaml +++ b/swagger-def/ghc.yaml @@ -4012,7 +4012,7 @@ paths: - transportationOffice responses: '200': - description: Successfully retrieved transportation offices + description: Successfully retrieved GBLOCs schema: $ref: '#/definitions/GBLOCs' '400': @@ -4025,6 +4025,29 @@ paths: $ref: '#/responses/NotFound' '500': $ref: '#/responses/ServerError' + /transportation_offices/{dutyLocationId}/counseling_offices: + get: + summary: Returns the counseling locations in the GBLOC matching the duty location + description: Returns the counseling locations matching the GBLOC from the selected duty location + operationId: showCounselingOffices + tags: + - transportationOffice + parameters: + - in: path + name: dutyLocationId + format: uuid + type: string + required: true + description: UUID of the duty location + produces: + - application/json + responses: + '200': + description: Successfully retrieved counseling offices + schema: + $ref: '#/definitions/CounselingOffices' + '500': + description: internal server error /uploads: post: summary: Create a new upload @@ -5541,6 +5564,11 @@ definitions: type: string format: uuid example: c56a4180-65aa-42ec-a945-5fd21dec0538 + counseling_office_id: + type: string + format: uuid + example: cf1addea-a4f9-4173-8506-2bb82a064cb7 + x-nullable: true ordersNumber: type: string title: Orders Number @@ -7638,6 +7666,23 @@ definitions: type: array items: type: string + CounselingOffices: + type: array + items: + $ref: '#/definitions/CounselingOffice' + CounselingOffice: + type: object + properties: + id: + type: string + format: uuid + example: c56a4180-65aa-42ec-a945-5fd21dec0538 + name: + type: string + example: Fort Bragg North Station + required: + - id + - name MovePayload: type: object properties: diff --git a/swagger/ghc.yaml b/swagger/ghc.yaml index f37c686f7b8..426b1a3b421 100644 --- a/swagger/ghc.yaml +++ b/swagger/ghc.yaml @@ -4208,7 +4208,7 @@ paths: - transportationOffice responses: '200': - description: Successfully retrieved transportation offices + description: Successfully retrieved GBLOCs schema: $ref: '#/definitions/GBLOCs' '400': @@ -4221,6 +4221,31 @@ paths: $ref: '#/responses/NotFound' '500': $ref: '#/responses/ServerError' + /transportation_offices/{dutyLocationId}/counseling_offices: + get: + summary: Returns the counseling locations in the GBLOC matching the duty location + description: >- + Returns the counseling locations matching the GBLOC from the selected + duty location + operationId: showCounselingOffices + tags: + - transportationOffice + parameters: + - in: path + name: dutyLocationId + format: uuid + type: string + required: true + description: UUID of the duty location + produces: + - application/json + responses: + '200': + description: Successfully retrieved counseling offices + schema: + $ref: '#/definitions/CounselingOffices' + '500': + description: internal server error /uploads: post: summary: Create a new upload @@ -5785,6 +5810,11 @@ definitions: type: string format: uuid example: c56a4180-65aa-42ec-a945-5fd21dec0538 + counselingOfficeId: + type: string + format: uuid + example: cf1addea-a4f9-4173-8506-2bb82a064cb7 + x-nullable: true ordersNumber: type: string title: Orders Number @@ -7982,6 +8012,23 @@ definitions: type: array items: type: string + CounselingOffices: + type: array + items: + $ref: '#/definitions/CounselingOffice' + CounselingOffice: + type: object + properties: + id: + type: string + format: uuid + example: c56a4180-65aa-42ec-a945-5fd21dec0538 + name: + type: string + example: Fort Bragg North Station + required: + - id + - name MovePayload: type: object properties: From c61301b553d54c901cdea68ae26577f800212593 Mon Sep 17 00:00:00 2001 From: Alex Lusk Date: Wed, 18 Dec 2024 00:41:54 +0000 Subject: [PATCH 02/20] tests for 21997 --- pkg/handlers/ghcapi/orders_test.go | 1 + .../ghcapi/transportation_offices_test.go | 57 ++++++++++++++++ .../AddOrdersForm/AddOrdersForm.test.jsx | 66 +++++++++++++++++++ 3 files changed, 124 insertions(+) diff --git a/pkg/handlers/ghcapi/orders_test.go b/pkg/handlers/ghcapi/orders_test.go index 93fdc901600..3ace83328be 100644 --- a/pkg/handlers/ghcapi/orders_test.go +++ b/pkg/handlers/ghcapi/orders_test.go @@ -73,6 +73,7 @@ func (suite *HandlerSuite) TestCreateOrder() { Sac: handlers.FmtString("SacNumber"), DepartmentIndicator: ghcmessages.NewDeptIndicator(deptIndicator), Grade: ghcmessages.GradeE1.Pointer(), + CounselingOfficeID: handlers.FmtUUID(*dutyLocation.TransportationOfficeID), } params := orderop.CreateOrderParams{ diff --git a/pkg/handlers/ghcapi/transportation_offices_test.go b/pkg/handlers/ghcapi/transportation_offices_test.go index 92ac98f630b..ef61e931c71 100644 --- a/pkg/handlers/ghcapi/transportation_offices_test.go +++ b/pkg/handlers/ghcapi/transportation_offices_test.go @@ -1,13 +1,16 @@ package ghcapi import ( + "fmt" "net/http/httptest" "github.com/go-openapi/strfmt" "github.com/transcom/mymove/pkg/factory" transportationofficeop "github.com/transcom/mymove/pkg/gen/ghcapi/ghcoperations/transportation_office" + "github.com/transcom/mymove/pkg/handlers" "github.com/transcom/mymove/pkg/models" + "github.com/transcom/mymove/pkg/services/address" transportationofficeservice "github.com/transcom/mymove/pkg/services/transportation_office" ) @@ -145,3 +148,57 @@ func (suite *HandlerSuite) TestGetTransportationOfficesGBLOCsHandler() { suite.Equal(transportationOffice1.Gbloc, responsePayload.Payload[0]) suite.Equal(transportationOffice2.Gbloc, responsePayload.Payload[1]) } + +func (suite *HandlerSuite) TestShowCounselingOfficesHandler() { + user := factory.BuildDefaultUser(suite.DB()) + + fetcher := transportationofficeservice.NewTransportationOfficesFetcher() + + newAddress := models.Address{ + StreetAddress1: "some address", + City: "city", + State: "CA", + PostalCode: "59801", + County: "County", + } + addressCreator := address.NewAddressCreator() + createdAddress, err := addressCreator.CreateAddress(suite.AppContextForTest(), &newAddress) + suite.NoError(err) + + origDutyLocation := factory.BuildDutyLocation(suite.DB(), []factory.Customization{ + { + Model: models.DutyLocation{ + AddressID: createdAddress.ID, + ProvidesServicesCounseling: true, + }, + }, + { + Model: models.TransportationOffice{ + Name: "PPPO Travis AFB - USAF", + Gbloc: "KKFA", + ProvidesCloseout: true, + }, + }, + }, nil) + suite.MustSave(&origDutyLocation) + + path := fmt.Sprintf("/transportation_offices/%v/counseling_offices", origDutyLocation.ID.String()) + req := httptest.NewRequest("GET", path, nil) + req = suite.AuthenticateUserRequest(req, user) + params := transportationofficeop.ShowCounselingOfficesParams{ + HTTPRequest: req, + DutyLocationID: *handlers.FmtUUID(origDutyLocation.ID), + } + + handler := ShowCounselingOfficesHandler{ + HandlerConfig: suite.HandlerConfig(), + TransportationOfficesFetcher: fetcher} + + response := handler.Handle(params) + suite.Assertions.IsType(&transportationofficeop.ShowCounselingOfficesOK{}, response) + responsePayload := response.(*transportationofficeop.ShowCounselingOfficesOK) + + // Validate outgoing payload + suite.NoError(responsePayload.Payload.Validate(strfmt.Default)) + +} diff --git a/src/components/Office/AddOrdersForm/AddOrdersForm.test.jsx b/src/components/Office/AddOrdersForm/AddOrdersForm.test.jsx index f6c4f04e22f..f09c075ea29 100644 --- a/src/components/Office/AddOrdersForm/AddOrdersForm.test.jsx +++ b/src/components/Office/AddOrdersForm/AddOrdersForm.test.jsx @@ -75,10 +75,44 @@ jest.mock('components/LocationSearchBox/api', () => ({ name: 'Luke AFB', updated_at: '2021-02-11T16:48:04.117Z', }, + { + address: { + city: '', + id: '25be4d12-fe93-47f1-bbec-1db386dfa67e', + postalCode: '', + state: '', + streetAddress1: '', + }, + address_id: '4334640b-c35e-4293-a2f1-36c7b629f904', + affiliation: 'AIR_FORCE', + created_at: '2021-02-11T16:48:04.117Z', + id: '22f0755f-6f35-478b-9a75-35a69211da1d', + name: 'Scott AFB', + updated_at: '2021-02-11T16:48:04.117Z', + provides_services_counseling: true, + }, ]), ), })); +jest.mock('services/ghcApi', () => ({ + ...jest.requireActual('services/ghcApi'), + showCounselingOffices: jest.fn().mockImplementation(() => + Promise.resolve({ + body: [ + { + id: '3e937c1f-5539-4919-954d-017989130584', + name: 'Albuquerque AFB', + }, + { + id: 'fa51dab0-4553-4732-b843-1f33407f77bc', + name: 'Glendale Luke AFB', + }, + ], + }), + ), +})); + jest.mock('utils/featureFlags', () => ({ ...jest.requireActual('utils/featureFlags'), isBooleanFlagEnabled: jest.fn().mockImplementation(() => Promise.resolve(false)), @@ -96,6 +130,7 @@ const initialValues = { accompaniedTour: '', dependentsUnderTwelve: '', dependentsTwelveAndOver: '', + counselingOfficeId: '', }; const testProps = { initialValues, @@ -194,3 +229,34 @@ describe('AddOrdersForm - OCONUS and Accompanied Tour Test', () => { }); }); }); + +describe('AddOrdersForm - With Counseling Office', () => { + it('displays the counseling office dropdown', async () => { + isBooleanFlagEnabled.mockImplementation(() => Promise.resolve(true)); + render( + + + , + ); + + await userEvent.selectOptions(await screen.findByLabelText(/Orders type/), 'PERMANENT_CHANGE_OF_STATION'); + await userEvent.type(screen.getByLabelText(/Orders date/), '08 Nov 2020'); + await userEvent.type(screen.getByLabelText(/Report by date/), '26 Nov 2020'); + await userEvent.click(screen.getByLabelText('No')); + await userEvent.selectOptions(screen.getByLabelText(/Pay grade/), ['E_5']); + + // Test Current Duty Location Search Box interaction + await userEvent.type(screen.getByLabelText(/Current duty location/), 'AFB', { delay: 100 }); + const selectedOptionCurrent = await screen.findByText(/Scott/); + await userEvent.click(selectedOptionCurrent); + + // Test New Duty Location Search Box interaction + await userEvent.type(screen.getByLabelText(/New duty location/), 'AFB', { delay: 100 }); + const selectedOptionNew = await screen.findByText(/Luke/); + await userEvent.click(selectedOptionNew); + + await waitFor(() => { + expect(screen.getByLabelText(/Counseling office/)); + }); + }); +}); From fdb8347bcddc31b77030a4e8820f7f53894c03bc Mon Sep 17 00:00:00 2001 From: Alex Lusk Date: Wed, 18 Dec 2024 15:50:38 +0000 Subject: [PATCH 03/20] expand 21997 tests --- pkg/gen/ghcapi/embedded_spec.go | 4 +- pkg/gen/ghcmessages/create_orders.go | 6 +-- .../Office/AddOrdersForm/AddOrdersForm.jsx | 3 +- .../ServicesCounselingAddOrders.test.jsx | 45 +++++++++++++++++++ swagger-def/ghc.yaml | 2 +- 5 files changed, 53 insertions(+), 7 deletions(-) diff --git a/pkg/gen/ghcapi/embedded_spec.go b/pkg/gen/ghcapi/embedded_spec.go index 39b6a4f900a..cbe49f80e17 100644 --- a/pkg/gen/ghcapi/embedded_spec.go +++ b/pkg/gen/ghcapi/embedded_spec.go @@ -7469,7 +7469,7 @@ func init() { "x-nullable": true, "example": true }, - "counseling_office_id": { + "counselingOfficeId": { "type": "string", "format": "uuid", "x-nullable": true, @@ -24069,7 +24069,7 @@ func init() { "x-nullable": true, "example": true }, - "counseling_office_id": { + "counselingOfficeId": { "type": "string", "format": "uuid", "x-nullable": true, diff --git a/pkg/gen/ghcmessages/create_orders.go b/pkg/gen/ghcmessages/create_orders.go index d253d74c0aa..a71a85a4d74 100644 --- a/pkg/gen/ghcmessages/create_orders.go +++ b/pkg/gen/ghcmessages/create_orders.go @@ -23,10 +23,10 @@ type CreateOrders struct { // Example: true AccompaniedTour *bool `json:"accompaniedTour,omitempty"` - // counseling office id + // counseling office Id // Example: cf1addea-a4f9-4173-8506-2bb82a064cb7 // Format: uuid - CounselingOfficeID *strfmt.UUID `json:"counseling_office_id,omitempty"` + CounselingOfficeID *strfmt.UUID `json:"counselingOfficeId,omitempty"` // department indicator DepartmentIndicator *DeptIndicator `json:"departmentIndicator,omitempty"` @@ -164,7 +164,7 @@ func (m *CreateOrders) validateCounselingOfficeID(formats strfmt.Registry) error return nil } - if err := validate.FormatOf("counseling_office_id", "body", "uuid", m.CounselingOfficeID.String(), formats); err != nil { + if err := validate.FormatOf("counselingOfficeId", "body", "uuid", m.CounselingOfficeID.String(), formats); err != nil { return err } diff --git a/src/components/Office/AddOrdersForm/AddOrdersForm.jsx b/src/components/Office/AddOrdersForm/AddOrdersForm.jsx index dfc7929d597..c16b00fc1d6 100644 --- a/src/components/Office/AddOrdersForm/AddOrdersForm.jsx +++ b/src/components/Office/AddOrdersForm/AddOrdersForm.jsx @@ -111,7 +111,7 @@ const AddOrdersForm = ({ onSubmit, ordersTypeOptions, initialValues, onBack, isS const handleCounselingOfficeChange = () => { setValues({ ...values, - counseling_office_id: null, + counselingOfficeId: null, }); setCounselingOfficeOptions(null); }; @@ -170,6 +170,7 @@ const AddOrdersForm = ({ onSubmit, ordersTypeOptions, initialValues, onBack, isS label="Counseling office" name="counselingOfficeId" id="counselingOfficeId" + data-testid="counselingOfficeSelect" hint="Required" required options={counselingOfficeOptions} diff --git a/src/pages/Office/ServicesCounselingAddOrders/ServicesCounselingAddOrders.test.jsx b/src/pages/Office/ServicesCounselingAddOrders/ServicesCounselingAddOrders.test.jsx index eb57eefb665..7677573f6c2 100644 --- a/src/pages/Office/ServicesCounselingAddOrders/ServicesCounselingAddOrders.test.jsx +++ b/src/pages/Office/ServicesCounselingAddOrders/ServicesCounselingAddOrders.test.jsx @@ -1,6 +1,7 @@ import React from 'react'; import { render, screen, waitFor } from '@testing-library/react'; import userEvent from '@testing-library/user-event'; +import { debug } from 'jest-preview'; import ServicesCounselingAddOrders from './ServicesCounselingAddOrders'; @@ -23,6 +24,20 @@ jest.mock('utils/featureFlags', () => ({ jest.mock('services/ghcApi', () => ({ ...jest.requireActual('services/ghcApi'), counselingCreateOrder: jest.fn().mockImplementation(() => Promise.resolve()), + showCounselingOffices: jest.fn().mockImplementation(() => + Promise.resolve({ + body: [ + { + id: '3e937c1f-5539-4919-954d-017989130584', + name: 'Albuquerque AFB', + }, + { + id: 'fa51dab0-4553-4732-b843-1f33407f77bc', + name: 'Glendale Luke AFB', + }, + ], + }), + ), })); jest.mock('services/internalApi', () => ({ @@ -79,6 +94,7 @@ jest.mock('components/LocationSearchBox/api', () => ({ id: '7d123884-7c1b-4611-92ae-e8d43ca03ad9', name: 'Hill AFB', updated_at: '2021-02-11T16:48:04.117Z', + provides_services_counseling: true, }, { address: { @@ -362,6 +378,7 @@ describe('ServicesCounselingAddOrders component', () => { expect(nextBtn).toBeEnabled(); }); + // debug(); await userEvent.click(nextBtn); await waitFor(() => { @@ -370,6 +387,34 @@ describe('ServicesCounselingAddOrders component', () => { }); }); + it('Displays the counseling office dropdown', async () => { + renderWithMocks(); + + counselingCreateOrder.mockImplementation(() => Promise.resolve(fakeResponse)); + + const user = userEvent.setup(); + + await user.selectOptions(screen.getByLabelText('Orders type'), 'PERMANENT_CHANGE_OF_STATION'); + await user.type(screen.getByLabelText('Orders date'), '08 Nov 2020'); + await user.type(screen.getByLabelText('Report by date'), '29 Nov 2020'); + await user.click(screen.getByLabelText('No')); + await user.selectOptions(screen.getByLabelText('Pay grade'), ['E-5']); + + // Test Current Duty Location Search Box interaction + await user.type(screen.getByLabelText('Current duty location'), 'AFB', { delay: 500 }); + const selectedOptionCurrent = await screen.findByText(/Hill/); + await user.click(selectedOptionCurrent); + + await waitFor(async () => { + expect(screen.getByLabelText(/Counseling office/)); + }); + + await user.type(screen.getByLabelText('New duty location'), 'AFB', { delay: 500 }); + const selectedOptionNew = await screen.findByText(/Luke/); + await user.click(selectedOptionNew); + debug(); + }); + it('routes to the move details page when the next button is clicked for OCONUS orders', async () => { isBooleanFlagEnabled.mockImplementation(() => Promise.resolve(true)); renderWithMocks(); diff --git a/swagger-def/ghc.yaml b/swagger-def/ghc.yaml index c9abaf62e5c..5c60482d05e 100644 --- a/swagger-def/ghc.yaml +++ b/swagger-def/ghc.yaml @@ -5564,7 +5564,7 @@ definitions: type: string format: uuid example: c56a4180-65aa-42ec-a945-5fd21dec0538 - counseling_office_id: + counselingOfficeId: type: string format: uuid example: cf1addea-a4f9-4173-8506-2bb82a064cb7 From 4c9b0ca61b19bf02d78ad46a46e32dad0a00018e Mon Sep 17 00:00:00 2001 From: Alex Lusk Date: Thu, 19 Dec 2024 15:18:57 +0000 Subject: [PATCH 04/20] removed jest debugs and added no counseling office test case --- .../Office/AddOrdersForm/AddOrdersForm.test.jsx | 8 +++++--- .../ServicesCounselingAddOrders.test.jsx | 11 +++++------ 2 files changed, 10 insertions(+), 9 deletions(-) diff --git a/src/components/Office/AddOrdersForm/AddOrdersForm.test.jsx b/src/components/Office/AddOrdersForm/AddOrdersForm.test.jsx index f09c075ea29..ed9a856cdfa 100644 --- a/src/components/Office/AddOrdersForm/AddOrdersForm.test.jsx +++ b/src/components/Office/AddOrdersForm/AddOrdersForm.test.jsx @@ -208,6 +208,9 @@ describe('AddOrdersForm - OCONUS and Accompanied Tour Test', () => { const selectedOptionCurrent = await screen.findByText(/Elmendorf/); await userEvent.click(selectedOptionCurrent); + const counselingOfficeLabel = await screen.queryByText(/Counseling office/); + expect(counselingOfficeLabel).toBeFalsy(); + // Test New Duty Location Search Box interaction await userEvent.type(screen.getByLabelText(/New duty location/), 'AFB', { delay: 100 }); const selectedOptionNew = await screen.findByText(/Luke/); @@ -255,8 +258,7 @@ describe('AddOrdersForm - With Counseling Office', () => { const selectedOptionNew = await screen.findByText(/Luke/); await userEvent.click(selectedOptionNew); - await waitFor(() => { - expect(screen.getByLabelText(/Counseling office/)); - }); + const counselingOfficeLabel = await screen.queryByText(/Counseling office/); + expect(counselingOfficeLabel).toBeTruthy(); }); }); diff --git a/src/pages/Office/ServicesCounselingAddOrders/ServicesCounselingAddOrders.test.jsx b/src/pages/Office/ServicesCounselingAddOrders/ServicesCounselingAddOrders.test.jsx index 7677573f6c2..497ebcbe081 100644 --- a/src/pages/Office/ServicesCounselingAddOrders/ServicesCounselingAddOrders.test.jsx +++ b/src/pages/Office/ServicesCounselingAddOrders/ServicesCounselingAddOrders.test.jsx @@ -1,7 +1,6 @@ import React from 'react'; import { render, screen, waitFor } from '@testing-library/react'; import userEvent from '@testing-library/user-event'; -import { debug } from 'jest-preview'; import ServicesCounselingAddOrders from './ServicesCounselingAddOrders'; @@ -369,6 +368,9 @@ describe('ServicesCounselingAddOrders component', () => { const selectedOptionCurrent = await screen.findByText(/Altus/); await user.click(selectedOptionCurrent); + const counselingOfficeLabel = await screen.queryByText(/Counseling office/); + expect(counselingOfficeLabel).toBeFalsy(); + await user.type(screen.getByLabelText('New duty location'), 'AFB', { delay: 500 }); const selectedOptionNew = await screen.findByText(/Luke/); await user.click(selectedOptionNew); @@ -378,7 +380,6 @@ describe('ServicesCounselingAddOrders component', () => { expect(nextBtn).toBeEnabled(); }); - // debug(); await userEvent.click(nextBtn); await waitFor(() => { @@ -405,14 +406,12 @@ describe('ServicesCounselingAddOrders component', () => { const selectedOptionCurrent = await screen.findByText(/Hill/); await user.click(selectedOptionCurrent); - await waitFor(async () => { - expect(screen.getByLabelText(/Counseling office/)); - }); + const counselingOfficeLabel = await screen.queryByText(/Counseling office/); + expect(counselingOfficeLabel).toBeTruthy(); await user.type(screen.getByLabelText('New duty location'), 'AFB', { delay: 500 }); const selectedOptionNew = await screen.findByText(/Luke/); await user.click(selectedOptionNew); - debug(); }); it('routes to the move details page when the next button is clicked for OCONUS orders', async () => { From d308a38c80a52b9e83e80a583a47b5e24e8a82eb Mon Sep 17 00:00:00 2001 From: Alex Lusk Date: Fri, 20 Dec 2024 15:43:41 +0000 Subject: [PATCH 05/20] Added counseling office to move payload --- pkg/gen/ghcapi/embedded_spec.go | 18 +++++ pkg/gen/ghcmessages/move.go | 71 +++++++++++++++++++ .../internal/payloads/model_to_payload.go | 2 + pkg/services/move/move_fetcher.go | 2 +- swagger-def/ghc.yaml | 7 ++ swagger/ghc.yaml | 9 +++ 6 files changed, 108 insertions(+), 1 deletion(-) diff --git a/pkg/gen/ghcapi/embedded_spec.go b/pkg/gen/ghcapi/embedded_spec.go index cbe49f80e17..183609a41ca 100644 --- a/pkg/gen/ghcapi/embedded_spec.go +++ b/pkg/gen/ghcapi/embedded_spec.go @@ -9980,6 +9980,15 @@ func init() { "format": "uuid", "x-nullable": true }, + "counselingOffice": { + "$ref": "#/definitions/TransportationOffice" + }, + "counselingOfficeId": { + "description": "The transportation office that will handle services counseling for this move", + "type": "string", + "format": "uuid", + "x-nullable": true + }, "createdAt": { "type": "string", "format": "date-time" @@ -26580,6 +26589,15 @@ func init() { "format": "uuid", "x-nullable": true }, + "counselingOffice": { + "$ref": "#/definitions/TransportationOffice" + }, + "counselingOfficeId": { + "description": "The transportation office that will handle services counseling for this move", + "type": "string", + "format": "uuid", + "x-nullable": true + }, "createdAt": { "type": "string", "format": "date-time" diff --git a/pkg/gen/ghcmessages/move.go b/pkg/gen/ghcmessages/move.go index bb67e748b11..c647b3c7764 100644 --- a/pkg/gen/ghcmessages/move.go +++ b/pkg/gen/ghcmessages/move.go @@ -61,6 +61,13 @@ type Move struct { // Format: uuid ContractorID *strfmt.UUID `json:"contractorId,omitempty"` + // counseling office + CounselingOffice *TransportationOffice `json:"counselingOffice,omitempty"` + + // The transportation office that will handle services counseling for this move + // Format: uuid + CounselingOfficeID *strfmt.UUID `json:"counselingOfficeId,omitempty"` + // created at // Format: date-time CreatedAt strfmt.DateTime `json:"createdAt,omitempty"` @@ -193,6 +200,14 @@ func (m *Move) Validate(formats strfmt.Registry) error { res = append(res, err) } + if err := m.validateCounselingOffice(formats); err != nil { + res = append(res, err) + } + + if err := m.validateCounselingOfficeID(formats); err != nil { + res = append(res, err) + } + if err := m.validateCreatedAt(formats); err != nil { res = append(res, err) } @@ -441,6 +456,37 @@ func (m *Move) validateContractorID(formats strfmt.Registry) error { return nil } +func (m *Move) validateCounselingOffice(formats strfmt.Registry) error { + if swag.IsZero(m.CounselingOffice) { // not required + return nil + } + + if m.CounselingOffice != nil { + if err := m.CounselingOffice.Validate(formats); err != nil { + if ve, ok := err.(*errors.Validation); ok { + return ve.ValidateName("counselingOffice") + } else if ce, ok := err.(*errors.CompositeError); ok { + return ce.ValidateName("counselingOffice") + } + return err + } + } + + return nil +} + +func (m *Move) validateCounselingOfficeID(formats strfmt.Registry) error { + if swag.IsZero(m.CounselingOfficeID) { // not required + return nil + } + + if err := validate.FormatOf("counselingOfficeId", "body", "uuid", m.CounselingOfficeID.String(), formats); err != nil { + return err + } + + return nil +} + func (m *Move) validateCreatedAt(formats strfmt.Registry) error { if swag.IsZero(m.CreatedAt) { // not required return nil @@ -661,6 +707,10 @@ func (m *Move) ContextValidate(ctx context.Context, formats strfmt.Registry) err res = append(res, err) } + if err := m.contextValidateCounselingOffice(ctx, formats); err != nil { + res = append(res, err) + } + if err := m.contextValidateFinancialReviewFlag(ctx, formats); err != nil { res = append(res, err) } @@ -817,6 +867,27 @@ func (m *Move) contextValidateContractor(ctx context.Context, formats strfmt.Reg return nil } +func (m *Move) contextValidateCounselingOffice(ctx context.Context, formats strfmt.Registry) error { + + if m.CounselingOffice != nil { + + if swag.IsZero(m.CounselingOffice) { // not required + return nil + } + + if err := m.CounselingOffice.ContextValidate(ctx, formats); err != nil { + if ve, ok := err.(*errors.Validation); ok { + return ve.ValidateName("counselingOffice") + } else if ce, ok := err.(*errors.CompositeError); ok { + return ce.ValidateName("counselingOffice") + } + return err + } + } + + return nil +} + func (m *Move) contextValidateFinancialReviewFlag(ctx context.Context, formats strfmt.Registry) error { if err := validate.ReadOnly(ctx, "financialReviewFlag", "body", bool(m.FinancialReviewFlag)); err != nil { diff --git a/pkg/handlers/ghcapi/internal/payloads/model_to_payload.go b/pkg/handlers/ghcapi/internal/payloads/model_to_payload.go index 6d1dd799115..c15657f6966 100644 --- a/pkg/handlers/ghcapi/internal/payloads/model_to_payload.go +++ b/pkg/handlers/ghcapi/internal/payloads/model_to_payload.go @@ -120,6 +120,8 @@ func Move(move *models.Move, storer storage.FileStorer) (*ghcmessages.Move, erro SCAssignedUser: AssignedOfficeUser(move.SCAssignedUser), TOOAssignedUser: AssignedOfficeUser(move.TOOAssignedUser), TIOAssignedUser: AssignedOfficeUser(move.TIOAssignedUser), + CounselingOfficeID: handlers.FmtUUIDPtr(move.CounselingOfficeID), + CounselingOffice: TransportationOffice(move.CounselingOffice), } return payload, nil diff --git a/pkg/services/move/move_fetcher.go b/pkg/services/move/move_fetcher.go index 470f4ca78a4..a75cf4ece2a 100644 --- a/pkg/services/move/move_fetcher.go +++ b/pkg/services/move/move_fetcher.go @@ -25,7 +25,7 @@ func (f moveFetcher) FetchMove(appCtx appcontext.AppContext, locator string, sea move := &models.Move{} query := appCtx.DB(). EagerPreload("CloseoutOffice.Address", "Contractor", "ShipmentGBLOC", "LockedByOfficeUser", "LockedByOfficeUser.TransportationOffice", "AdditionalDocuments", - "AdditionalDocuments.UserUploads"). + "AdditionalDocuments.UserUploads", "CounselingOffice"). LeftJoin("move_to_gbloc", "move_to_gbloc.move_id = moves.id"). LeftJoin("office_users", "office_users.id = moves.locked_by"). Where("locator = $1", locator) diff --git a/swagger-def/ghc.yaml b/swagger-def/ghc.yaml index 5c60482d05e..2bf80c888f8 100644 --- a/swagger-def/ghc.yaml +++ b/swagger-def/ghc.yaml @@ -5147,6 +5147,13 @@ definitions: format: uuid description: The transportation office that will handle reviewing PPM Closeout documentation for Army and Air Force service members x-nullable: true + counselingOffice: + $ref: 'definitions/TransportationOffice.yaml' + counselingOfficeId: + type: string + format: uuid + description: The transportation office that will handle services counseling for this move + x-nullable: true approvalsRequestedAt: type: string format: date-time diff --git a/swagger/ghc.yaml b/swagger/ghc.yaml index 426b1a3b421..c4b0c22900d 100644 --- a/swagger/ghc.yaml +++ b/swagger/ghc.yaml @@ -5379,6 +5379,15 @@ definitions: The transportation office that will handle reviewing PPM Closeout documentation for Army and Air Force service members x-nullable: true + counselingOffice: + $ref: '#/definitions/TransportationOffice' + counselingOfficeId: + type: string + format: uuid + description: >- + The transportation office that will handle services counseling for + this move + x-nullable: true approvalsRequestedAt: type: string format: date-time From b35066b5844555b9a2d0df72c857f7b247f26101 Mon Sep 17 00:00:00 2001 From: Alex Lusk Date: Fri, 20 Dec 2024 17:23:33 +0000 Subject: [PATCH 06/20] update counseling office selction instructions --- src/components/Office/AddOrdersForm/AddOrdersForm.jsx | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/src/components/Office/AddOrdersForm/AddOrdersForm.jsx b/src/components/Office/AddOrdersForm/AddOrdersForm.jsx index c16b00fc1d6..87ef797e81c 100644 --- a/src/components/Office/AddOrdersForm/AddOrdersForm.jsx +++ b/src/components/Office/AddOrdersForm/AddOrdersForm.jsx @@ -162,9 +162,9 @@ const AddOrdersForm = ({ onSubmit, ordersTypeOptions, initialValues, onBack, isS {currentDutyLocation.provides_services_counseling && (
Date: Tue, 7 Jan 2025 23:12:21 +0000 Subject: [PATCH 07/20] Add counseling office to orders list component --- .../Office/DefinitionLists/OrdersList.jsx | 10 +++++-- .../DefinitionLists/OrdersList.stories.jsx | 18 +++++++++++ .../DefinitionLists/OrdersList.test.jsx | 9 +++++- src/pages/Office/MoveDetails/MoveDetails.jsx | 2 +- .../ServicesCounselingMoveDetails.jsx | 2 +- src/setupProxy.js | 30 +++++++++---------- 6 files changed, 51 insertions(+), 20 deletions(-) diff --git a/src/components/Office/DefinitionLists/OrdersList.jsx b/src/components/Office/DefinitionLists/OrdersList.jsx index 46ec027d40e..f915abc480c 100644 --- a/src/components/Office/DefinitionLists/OrdersList.jsx +++ b/src/components/Office/DefinitionLists/OrdersList.jsx @@ -15,7 +15,7 @@ import { ordersTypeDetailReadable, } from 'utils/formatters'; -const OrdersList = ({ ordersInfo, showMissingWarnings }) => { +const OrdersList = ({ ordersInfo, moveInfo, showMissingWarnings }) => { const { ordersType } = ordersInfo; const isRetiree = ordersType === 'RETIREMENT'; const isSeparatee = ordersType === 'SEPARATION'; @@ -57,6 +57,12 @@ const OrdersList = ({ ordersInfo, showMissingWarnings }) => {
Current duty location
{ordersInfo.currentDutyLocation?.name}
+
+
Counseling office
+
+ {moveInfo.counselingOffice?.name ? moveInfo.counselingOffice?.name : '—'} +
+
{ {isRetiree || isSeparatee ? 'HOR, HOS, or PLEAD' : 'New duty location'}
- {ordersInfo.newDutyLocation?.name ? ordersInfo.newDutyLocation?.name : '-'} + {ordersInfo.newDutyLocation?.name ? ordersInfo.newDutyLocation?.name : '—'}
( NTStac: text('ordersInfo.NTStac', '9999'), payGrade: text('ordersInfo.payGrade', 'E_5'), }} + moveInfo={{ + name: 'PPPO Los Angeles SFB - USAF', + }} />
); @@ -81,6 +84,9 @@ export const AsServiceCounselor = () => ( NTStac: '', payGrade: text('ordersInfo.payGrade', 'E_5'), }} + moveInfo={{ + name: 'PPPO Los Angeles SFB - USAF', + }} /> ); @@ -105,6 +111,9 @@ export const AsServiceCounselorProcessingRetirement = () => ( NTStac: '', payGrade: text('ordersInfo.payGrade', 'E_5'), }} + moveInfo={{ + name: 'PPPO Los Angeles SFB - USAF', + }} /> ); @@ -129,6 +138,9 @@ export const AsServiceCounselorProcessingSeparation = () => ( NTStac: '', payGrade: text('ordersInfo.payGrade', 'E_5'), }} + moveInfo={{ + name: 'PPPO Los Angeles SFB - USAF', + }} /> ); @@ -166,6 +178,9 @@ export const AsTOO = () => ( NTStac: '', payGrade: text('ordersInfo.payGrade', 'E_5'), }} + moveInfo={{ + name: 'PPPO Los Angeles SFB - USAF', + }} /> ); @@ -212,6 +227,9 @@ export const AsTOOProcessingSeparation = () => ( NTStac: '', payGrade: text('ordersInfo.payGrade', 'E_5'), }} + moveInfo={{ + name: 'PPPO Los Angeles SFB - USAF', + }} /> ); diff --git a/src/components/Office/DefinitionLists/OrdersList.test.jsx b/src/components/Office/DefinitionLists/OrdersList.test.jsx index 586c0d1bfab..107463b7a1c 100644 --- a/src/components/Office/DefinitionLists/OrdersList.test.jsx +++ b/src/components/Office/DefinitionLists/OrdersList.test.jsx @@ -32,9 +32,16 @@ const ordersInfo = { payGrade: 'E_7', }; +const moveInfo = { + counselingOffice: { + name: 'PPPO Los Angeles SFB - USAF', + }, +}; + // what ordersInfo from above should be rendered as const expectedRenderedOrdersInfo = { currentDutyLocation: 'JBSA Lackland', + counselingOffice: 'PPPO Los Angeles SFB - USAF', newDutyLocation: 'JB Lewis-McChord', issuedDate: '08 Mar 2020', reportByDate: '01 Apr 2020', @@ -65,7 +72,7 @@ const ordersInfoMissing = { describe('OrdersList', () => { it('renders formatted orders info', () => { - render(); + render(); Object.keys(expectedRenderedOrdersInfo).forEach((key) => { expect(screen.getByText(expectedRenderedOrdersInfo[key])).toBeInTheDocument(); }); diff --git a/src/pages/Office/MoveDetails/MoveDetails.jsx b/src/pages/Office/MoveDetails/MoveDetails.jsx index d47156e3dc0..3ee4c4d3dcf 100644 --- a/src/pages/Office/MoveDetails/MoveDetails.jsx +++ b/src/pages/Office/MoveDetails/MoveDetails.jsx @@ -638,7 +638,7 @@ const MoveDetails = ({ } shipmentsInfoNonPpm={shipmentsInfoNonPPM} > - +
diff --git a/src/pages/Office/ServicesCounselingMoveDetails/ServicesCounselingMoveDetails.jsx b/src/pages/Office/ServicesCounselingMoveDetails/ServicesCounselingMoveDetails.jsx index 82e50380a2f..2c6bc7cef99 100644 --- a/src/pages/Office/ServicesCounselingMoveDetails/ServicesCounselingMoveDetails.jsx +++ b/src/pages/Office/ServicesCounselingMoveDetails/ServicesCounselingMoveDetails.jsx @@ -878,7 +878,7 @@ const ServicesCounselingMoveDetails = ({ } ppmShipmentInfoNeedsApproval={ppmShipmentsInfoNeedsApproval} > - +
diff --git a/src/setupProxy.js b/src/setupProxy.js index 3a6b0f36484..7d92e2f9aea 100644 --- a/src/setupProxy.js +++ b/src/setupProxy.js @@ -1,19 +1,19 @@ const { createProxyMiddleware } = require('http-proxy-middleware'); module.exports = (app) => { - app.use(createProxyMiddleware('/api', { target: 'http://milmovelocal:8080/' })); - app.use(createProxyMiddleware('/internal', { target: 'http://milmovelocal:8080/' })); - app.use(createProxyMiddleware('/admin', { target: 'http://milmovelocal:8080/' })); - app.use(createProxyMiddleware('/ghc', { target: 'http://milmovelocal:8080/' })); - app.use(createProxyMiddleware('/prime', { target: 'http://milmovelocal:8080/' })); - app.use(createProxyMiddleware('/pptas', { target: 'http://milmovelocal:8080/' })); - app.use(createProxyMiddleware('/support', { target: 'http://milmovelocal:8080/' })); - app.use(createProxyMiddleware('/testharness', { target: 'http://milmovelocal:8080/' })); - app.use(createProxyMiddleware('/storage', { target: 'http://milmovelocal:8080/' })); - app.use(createProxyMiddleware('/devlocal-auth', { target: 'http://milmovelocal:8080/' })); - app.use(createProxyMiddleware('/auth/**', { target: 'http://milmovelocal:8080/' })); - app.use(createProxyMiddleware('/logout', { target: 'http://milmovelocal:8080/' })); - app.use(createProxyMiddleware('/downloads', { target: 'http://milmovelocal:8080/' })); - app.use(createProxyMiddleware('/debug/**', { target: 'http://milmovelocal:8080/' })); - app.use(createProxyMiddleware('/client/**', { target: 'http://milmovelocal:8080/' })); + app.use('/api', createProxyMiddleware({ target: 'http://milmovelocal:8080/api' })); + app.use('/internal', createProxyMiddleware({ target: 'http://milmovelocal:8080/internal' })); + app.use('/admin', createProxyMiddleware({ target: 'http://milmovelocal:8080/admin' })); + app.use('/ghc', createProxyMiddleware({ target: 'http://milmovelocal:8080/ghc' })); + app.use('/prime', createProxyMiddleware({ target: 'http://milmovelocal:8080/prime' })); + app.use('/pptas', createProxyMiddleware({ target: 'http://milmovelocal:8080/pptas' })); + app.use('/support', createProxyMiddleware({ target: 'http://milmovelocal:8080/support' })); + app.use('/testharness', createProxyMiddleware({ target: 'http://milmovelocal:8080/testharness' })); + app.use('/storage', createProxyMiddleware({ target: 'http://milmovelocal:8080/storage' })); + app.use('/devlocal-auth', createProxyMiddleware({ target: 'http://milmovelocal:8080/devlocal-auth' })); + app.use('/auth', createProxyMiddleware({ target: 'http://milmovelocal:8080/auth' })); + app.use('/logout', createProxyMiddleware({ target: 'http://milmovelocal:8080/logout' })); + app.use('/downloads', createProxyMiddleware({ target: 'http://milmovelocal:8080/downloads' })); + app.use('/debug', createProxyMiddleware({ target: 'http://milmovelocal:8080/debug' })); + app.use('/client', createProxyMiddleware({ target: 'http://milmovelocal:8080/client' })); }; From 9dfc76ce90e3cc1bf31eb04641c45c0f304c0340 Mon Sep 17 00:00:00 2001 From: Alex Lusk Date: Wed, 8 Jan 2025 16:00:43 +0000 Subject: [PATCH 08/20] counseling office in orders card test fix --- src/components/Office/DefinitionLists/OrdersList.jsx | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/components/Office/DefinitionLists/OrdersList.jsx b/src/components/Office/DefinitionLists/OrdersList.jsx index f915abc480c..27de47eb1fc 100644 --- a/src/components/Office/DefinitionLists/OrdersList.jsx +++ b/src/components/Office/DefinitionLists/OrdersList.jsx @@ -60,7 +60,7 @@ const OrdersList = ({ ordersInfo, moveInfo, showMissingWarnings }) => {
Counseling office
- {moveInfo.counselingOffice?.name ? moveInfo.counselingOffice?.name : '—'} + {moveInfo?.counselingOffice?.name ? moveInfo.counselingOffice.name : '—'}
Date: Wed, 8 Jan 2025 21:19:00 +0000 Subject: [PATCH 09/20] extend counselor add orders with counseling offices tests --- pkg/handlers/ghcapi/transportation_offices_test.go | 10 ++++++++-- .../Office/AddOrdersForm/AddOrdersForm.test.jsx | 5 +++++ .../ServicesCounselingAddOrders.test.jsx | 7 +++++++ 3 files changed, 20 insertions(+), 2 deletions(-) diff --git a/pkg/handlers/ghcapi/transportation_offices_test.go b/pkg/handlers/ghcapi/transportation_offices_test.go index 10c0a51ddd2..087c5c2d243 100644 --- a/pkg/handlers/ghcapi/transportation_offices_test.go +++ b/pkg/handlers/ghcapi/transportation_offices_test.go @@ -174,7 +174,7 @@ func (suite *HandlerSuite) TestShowCounselingOfficesHandler() { }, { Model: models.TransportationOffice{ - Name: "PPPO Travis AFB - USAF", + Name: "New PPPO Travis AFB - USAF", Gbloc: "KKFA", ProvidesCloseout: true, }, @@ -200,5 +200,11 @@ func (suite *HandlerSuite) TestShowCounselingOfficesHandler() { // Validate outgoing payload suite.NoError(responsePayload.Payload.Validate(strfmt.Default)) - + var i int + for index, office := range responsePayload.Payload { + if *office.Name == "New PPPO Travis AFB - USAF" { + i = index + } + } + suite.NotNil(i) } diff --git a/src/components/Office/AddOrdersForm/AddOrdersForm.test.jsx b/src/components/Office/AddOrdersForm/AddOrdersForm.test.jsx index ed9a856cdfa..804c6f71642 100644 --- a/src/components/Office/AddOrdersForm/AddOrdersForm.test.jsx +++ b/src/components/Office/AddOrdersForm/AddOrdersForm.test.jsx @@ -260,5 +260,10 @@ describe('AddOrdersForm - With Counseling Office', () => { const counselingOfficeLabel = await screen.queryByText(/Counseling office/); expect(counselingOfficeLabel).toBeTruthy(); + + await userEvent.selectOptions(screen.getByLabelText(/Counseling office/), ['Albuquerque AFB']); + + const nextBtn = screen.getByRole('button', { name: 'Next' }); + expect(nextBtn.getAttribute('disabled')).toBeFalsy(); }); }); diff --git a/src/pages/Office/ServicesCounselingAddOrders/ServicesCounselingAddOrders.test.jsx b/src/pages/Office/ServicesCounselingAddOrders/ServicesCounselingAddOrders.test.jsx index 497ebcbe081..a0accc4b2db 100644 --- a/src/pages/Office/ServicesCounselingAddOrders/ServicesCounselingAddOrders.test.jsx +++ b/src/pages/Office/ServicesCounselingAddOrders/ServicesCounselingAddOrders.test.jsx @@ -409,9 +409,16 @@ describe('ServicesCounselingAddOrders component', () => { const counselingOfficeLabel = await screen.queryByText(/Counseling office/); expect(counselingOfficeLabel).toBeTruthy(); + await userEvent.selectOptions(screen.getByLabelText(/Counseling office/), ['Glendale Luke AFB']); + await user.type(screen.getByLabelText('New duty location'), 'AFB', { delay: 500 }); const selectedOptionNew = await screen.findByText(/Luke/); await user.click(selectedOptionNew); + + const nextBtn = await screen.findByRole('button', { name: 'Next' }); + await waitFor(() => { + expect(nextBtn.getAttribute('disabled')).toBeFalsy(); + }); }); it('routes to the move details page when the next button is clicked for OCONUS orders', async () => { From a0131278d4e90a595eb6b3f75562ea850d7a2ab6 Mon Sep 17 00:00:00 2001 From: Alex Lusk Date: Thu, 9 Jan 2025 20:57:50 +0000 Subject: [PATCH 10/20] increase test coverage of counseling offices model to payload per review request --- .../payloads/model_to_payload_test.go | 31 ++++++++++++++++++ .../payloads/model_to_payload_test.go | 32 +++++++++++++++++++ 2 files changed, 63 insertions(+) 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 ec3072d2ca0..e1aa18da846 100644 --- a/pkg/handlers/ghcapi/internal/payloads/model_to_payload_test.go +++ b/pkg/handlers/ghcapi/internal/payloads/model_to_payload_test.go @@ -950,3 +950,34 @@ func (suite *PayloadsSuite) TestMTOServiceItemModel() { suite.Equal(handlers.FmtString(models.MarketOconus.FullString()), result.Market, "Expected Market to be OCONUS") }) } + +func (suite *PayloadsSuite) TestCounselingOffices() { + suite.Run("correctly maps transportaion offices to counseling offices payload", func() { + office1 := factory.BuildTransportationOffice(nil, []factory.Customization{ + { + Model: models.TransportationOffice{ + ID: uuid.Must(uuid.NewV4()), + Name: "PPPO Fort Liberty", + }, + }, + }, nil) + + office2 := factory.BuildTransportationOffice(nil, []factory.Customization{ + { + Model: models.TransportationOffice{ + ID: uuid.Must(uuid.NewV4()), + Name: "PPPO Fort Walker", + }, + }, + }, nil) + + offices := models.TransportationOffices{office1, office2} + + payload := CounselingOffices(offices) + + suite.IsType(payload, ghcmessages.CounselingOffices{}) + suite.Equal(2, len(payload)) + suite.Equal(office1.ID.String(), payload[0].ID.String()) + suite.Equal(office2.ID.String(), payload[1].ID.String()) + }) +} diff --git a/pkg/handlers/internalapi/internal/payloads/model_to_payload_test.go b/pkg/handlers/internalapi/internal/payloads/model_to_payload_test.go index c88ec3b12ff..c91a8073807 100644 --- a/pkg/handlers/internalapi/internal/payloads/model_to_payload_test.go +++ b/pkg/handlers/internalapi/internal/payloads/model_to_payload_test.go @@ -3,6 +3,7 @@ package payloads import ( "github.com/gofrs/uuid" + "github.com/transcom/mymove/pkg/factory" "github.com/transcom/mymove/pkg/gen/internalmessages" "github.com/transcom/mymove/pkg/handlers" "github.com/transcom/mymove/pkg/models" @@ -115,3 +116,34 @@ func (suite *PayloadsSuite) TestVLocation() { suite.Equal(county, *(payload.County), "Expected County to match") }) } + +func (suite *PayloadsSuite) TestCounselingOffices() { + suite.Run("correctly maps transportaion offices to counseling offices payload", func() { + office1 := factory.BuildTransportationOffice(nil, []factory.Customization{ + { + Model: models.TransportationOffice{ + ID: uuid.Must(uuid.NewV4()), + Name: "PPPO Fort Liberty", + }, + }, + }, nil) + + office2 := factory.BuildTransportationOffice(nil, []factory.Customization{ + { + Model: models.TransportationOffice{ + ID: uuid.Must(uuid.NewV4()), + Name: "PPPO Fort Walker", + }, + }, + }, nil) + + offices := models.TransportationOffices{office1, office2} + + payload := CounselingOffices(offices) + + suite.IsType(payload, internalmessages.CounselingOffices{}) + suite.Equal(2, len(payload)) + suite.Equal(office1.ID.String(), payload[0].ID.String()) + suite.Equal(office2.ID.String(), payload[1].ID.String()) + }) +} From 3123707db761e438f9190ff2cb804c54fab67671 Mon Sep 17 00:00:00 2001 From: Alex Lusk Date: Fri, 10 Jan 2025 22:53:33 +0000 Subject: [PATCH 11/20] peer review suggestions --- pkg/handlers/ghcapi/transportation_offices_test.go | 1 - pkg/handlers/internalapi/transportation_offices_test.go | 1 - src/components/Office/AddOrdersForm/AddOrdersForm.test.jsx | 4 ++-- 3 files changed, 2 insertions(+), 4 deletions(-) diff --git a/pkg/handlers/ghcapi/transportation_offices_test.go b/pkg/handlers/ghcapi/transportation_offices_test.go index 087c5c2d243..3be2ce21b3d 100644 --- a/pkg/handlers/ghcapi/transportation_offices_test.go +++ b/pkg/handlers/ghcapi/transportation_offices_test.go @@ -180,7 +180,6 @@ func (suite *HandlerSuite) TestShowCounselingOfficesHandler() { }, }, }, nil) - suite.MustSave(&origDutyLocation) path := fmt.Sprintf("/transportation_offices/%v/counseling_offices", origDutyLocation.ID.String()) req := httptest.NewRequest("GET", path, nil) diff --git a/pkg/handlers/internalapi/transportation_offices_test.go b/pkg/handlers/internalapi/transportation_offices_test.go index b41c5aff7bf..83f875335a4 100644 --- a/pkg/handlers/internalapi/transportation_offices_test.go +++ b/pkg/handlers/internalapi/transportation_offices_test.go @@ -153,7 +153,6 @@ func (suite *HandlerSuite) TestShowCounselingOfficesHandler() { }, }, }, nil) - suite.MustSave(&origDutyLocation) path := fmt.Sprintf("/transportation_offices/%v/counseling_offices", origDutyLocation.ID.String()) req := httptest.NewRequest("GET", path, nil) diff --git a/src/components/Office/AddOrdersForm/AddOrdersForm.test.jsx b/src/components/Office/AddOrdersForm/AddOrdersForm.test.jsx index 18495b24036..55813f517fb 100644 --- a/src/components/Office/AddOrdersForm/AddOrdersForm.test.jsx +++ b/src/components/Office/AddOrdersForm/AddOrdersForm.test.jsx @@ -263,8 +263,8 @@ describe('AddOrdersForm - With Counseling Office', () => { ); await userEvent.selectOptions(await screen.findByLabelText(/Orders type/), 'PERMANENT_CHANGE_OF_STATION'); - await userEvent.type(screen.getByLabelText(/Orders date/), '08 Nov 2020'); - await userEvent.type(screen.getByLabelText(/Report by date/), '26 Nov 2020'); + await userEvent.paste(screen.getByLabelText(/Orders date/), '08 Nov 2020'); + await userEvent.paste(screen.getByLabelText(/Report by date/), '26 Nov 2020'); await userEvent.click(screen.getByLabelText('No')); await userEvent.selectOptions(screen.getByLabelText(/Pay grade/), ['E_5']); From 9254ad2477c915a3db5c4bf6364d88876ad03ef4 Mon Sep 17 00:00:00 2001 From: Alex Lusk Date: Thu, 16 Jan 2025 21:26:46 +0000 Subject: [PATCH 12/20] fix office user selecting counseling office validation --- .../Office/AddOrdersForm/AddOrdersForm.jsx | 3 ++ .../AddOrdersForm/AddOrdersForm.test.jsx | 32 +++++++++++++++++++ 2 files changed, 35 insertions(+) diff --git a/src/components/Office/AddOrdersForm/AddOrdersForm.jsx b/src/components/Office/AddOrdersForm/AddOrdersForm.jsx index beecfa6373e..07d984952ce 100644 --- a/src/components/Office/AddOrdersForm/AddOrdersForm.jsx +++ b/src/components/Office/AddOrdersForm/AddOrdersForm.jsx @@ -54,6 +54,9 @@ const AddOrdersForm = ({ .required('Required'), hasDependents: Yup.mixed().oneOf(['yes', 'no']).required('Required'), originDutyLocation: Yup.object().nullable().required('Required'), + counselingOfficeId: currentDutyLocation.provides_services_counseling + ? Yup.string().required('Required') + : Yup.string().notRequired(), newDutyLocation: Yup.object().nullable().required('Required'), grade: Yup.mixed().oneOf(Object.keys(ORDERS_PAY_GRADE_OPTIONS)).required('Required'), accompaniedTour: showAccompaniedTourField diff --git a/src/components/Office/AddOrdersForm/AddOrdersForm.test.jsx b/src/components/Office/AddOrdersForm/AddOrdersForm.test.jsx index 18495b24036..c14c9bf1c21 100644 --- a/src/components/Office/AddOrdersForm/AddOrdersForm.test.jsx +++ b/src/components/Office/AddOrdersForm/AddOrdersForm.test.jsx @@ -286,4 +286,36 @@ describe('AddOrdersForm - With Counseling Office', () => { const nextBtn = screen.getByRole('button', { name: 'Next' }); expect(nextBtn.getAttribute('disabled')).toBeFalsy(); }); + + it('disabled submit if counseling office is required and blank', async () => { + isBooleanFlagEnabled.mockImplementation(() => Promise.resolve(true)); + render( + + + , + ); + + await userEvent.selectOptions(await screen.findByLabelText(/Orders type/), 'PERMANENT_CHANGE_OF_STATION'); + await userEvent.type(screen.getByLabelText(/Orders date/), '08 Nov 2024'); + await userEvent.type(screen.getByLabelText(/Report by date/), '26 Nov 2024'); + await userEvent.click(screen.getByLabelText('No')); + await userEvent.selectOptions(screen.getByLabelText(/Pay grade/), ['E_5']); + + // Test Current Duty Location Search Box interaction + await userEvent.type(screen.getByLabelText(/Current duty location/), 'AFB', { delay: 100 }); + const selectedOptionCurrent = await screen.findByText(/Scott/); + await userEvent.click(selectedOptionCurrent); + + // Test New Duty Location Search Box interaction + await userEvent.type(screen.getByLabelText(/New duty location/), 'AFB', { delay: 100 }); + const selectedOptionNew = await screen.findByText(/Luke/); + await userEvent.click(selectedOptionNew); + screen.getByLabelText(/New duty location/).blurElement(); + + const counselingOfficeLabel = await screen.queryByText(/Counseling office/); + expect(counselingOfficeLabel).toBeTruthy(); // If the field is visible then it it required + + const nextBtn = await screen.getByRole('button', { name: 'Next' }); + expect(nextBtn.getAttribute('disabled')).toBeTruthy(); + }); }); From 224a40bb96ba111893ff5a82314f956eaab0fe03 Mon Sep 17 00:00:00 2001 From: Alex Lusk Date: Thu, 16 Jan 2025 22:23:09 +0000 Subject: [PATCH 13/20] fix AddOrdersForm test --- .../Office/AddOrdersForm/AddOrdersForm.test.jsx | 10 +++++----- 1 file changed, 5 insertions(+), 5 deletions(-) diff --git a/src/components/Office/AddOrdersForm/AddOrdersForm.test.jsx b/src/components/Office/AddOrdersForm/AddOrdersForm.test.jsx index c14c9bf1c21..d1169ac92fe 100644 --- a/src/components/Office/AddOrdersForm/AddOrdersForm.test.jsx +++ b/src/components/Office/AddOrdersForm/AddOrdersForm.test.jsx @@ -298,8 +298,6 @@ describe('AddOrdersForm - With Counseling Office', () => { await userEvent.selectOptions(await screen.findByLabelText(/Orders type/), 'PERMANENT_CHANGE_OF_STATION'); await userEvent.type(screen.getByLabelText(/Orders date/), '08 Nov 2024'); await userEvent.type(screen.getByLabelText(/Report by date/), '26 Nov 2024'); - await userEvent.click(screen.getByLabelText('No')); - await userEvent.selectOptions(screen.getByLabelText(/Pay grade/), ['E_5']); // Test Current Duty Location Search Box interaction await userEvent.type(screen.getByLabelText(/Current duty location/), 'AFB', { delay: 100 }); @@ -310,12 +308,14 @@ describe('AddOrdersForm - With Counseling Office', () => { await userEvent.type(screen.getByLabelText(/New duty location/), 'AFB', { delay: 100 }); const selectedOptionNew = await screen.findByText(/Luke/); await userEvent.click(selectedOptionNew); - screen.getByLabelText(/New duty location/).blurElement(); const counselingOfficeLabel = await screen.queryByText(/Counseling office/); expect(counselingOfficeLabel).toBeTruthy(); // If the field is visible then it it required - const nextBtn = await screen.getByRole('button', { name: 'Next' }); - expect(nextBtn.getAttribute('disabled')).toBeTruthy(); + await userEvent.selectOptions(screen.getByLabelText(/Pay grade/), ['E_5']); + await userEvent.click(screen.getByLabelText('No')); + + const nextBtn = await screen.getByRole('button', { name: 'Next' }, { delay: 100 }); + expect(nextBtn).toBeDisabled(); }); }); From cb4cfaa7bd3060e986d1629d87b174915586d0f4 Mon Sep 17 00:00:00 2001 From: Alex Lusk Date: Fri, 17 Jan 2025 19:28:44 +0000 Subject: [PATCH 14/20] consistent required hints on AddOrdersForm.jsx --- .../Office/AddOrdersForm/AddOrdersForm.jsx | 21 ++++++++++++++----- 1 file changed, 16 insertions(+), 5 deletions(-) diff --git a/src/components/Office/AddOrdersForm/AddOrdersForm.jsx b/src/components/Office/AddOrdersForm/AddOrdersForm.jsx index 07d984952ce..147d45626cc 100644 --- a/src/components/Office/AddOrdersForm/AddOrdersForm.jsx +++ b/src/components/Office/AddOrdersForm/AddOrdersForm.jsx @@ -154,9 +154,10 @@ const AddOrdersForm = ({ options={ordersTypeOptions} required isDisabled={isSafetyMoveSelected || isBluebarkMoveSelected} + hint="Required" /> - - + + {currentDutyLocation.provides_services_counseling && (
@@ -217,6 +219,7 @@ const AddOrdersForm = ({ displayAddress={false} placeholder="Enter a city or ZIP" metaOverride={newDutyMeta} + hint="Required" onDutyLocationChange={(e) => { setNewDutyLocation(e); }} @@ -227,6 +230,7 @@ const AddOrdersForm = ({ name="newDutyLocation" label="New duty location" required + hint="Required" metaOverride={newDutyMeta} onDutyLocationChange={(e) => { setNewDutyLocation(e); @@ -235,7 +239,7 @@ const AddOrdersForm = ({ )} - +
- +
)} - +
From cf53cfaaf675816c3e810dfd07c86caeb09a8412 Mon Sep 17 00:00:00 2001 From: Alex Lusk Date: Fri, 17 Jan 2025 20:13:52 +0000 Subject: [PATCH 15/20] test fixes for 21977 --- .../AddOrdersForm/AddOrdersForm.test.jsx | 30 ++++++++-------- .../ServicesCounselingAddOrders.test.jsx | 36 +++++++++---------- 2 files changed, 33 insertions(+), 33 deletions(-) diff --git a/src/components/Office/AddOrdersForm/AddOrdersForm.test.jsx b/src/components/Office/AddOrdersForm/AddOrdersForm.test.jsx index d1169ac92fe..81da5f5baf3 100644 --- a/src/components/Office/AddOrdersForm/AddOrdersForm.test.jsx +++ b/src/components/Office/AddOrdersForm/AddOrdersForm.test.jsx @@ -149,15 +149,15 @@ describe('CreateMoveCustomerInfo Component', () => { await waitFor(() => { expect(screen.getByText('Tell us about the orders')).toBeInTheDocument(); - expect(screen.getByLabelText('Orders type')).toBeInTheDocument(); - expect(screen.getByLabelText('Orders date')).toBeInTheDocument(); - expect(screen.getByLabelText('Report by date')).toBeInTheDocument(); - expect(screen.getByText('Are dependents included in the orders?')).toBeInTheDocument(); + expect(screen.getByLabelText(/Orders type/)).toBeInTheDocument(); + expect(screen.getByLabelText(/Orders date/)).toBeInTheDocument(); + expect(screen.getByLabelText(/Report by date/)).toBeInTheDocument(); + expect(screen.getByText(/Are dependents included in the orders?/)).toBeInTheDocument(); expect(screen.getByTestId('hasDependentsYes')).toBeInTheDocument(); expect(screen.getByTestId('hasDependentsNo')).toBeInTheDocument(); - expect(screen.getByLabelText('Current duty location')).toBeInTheDocument(); - expect(screen.getByLabelText('New duty location')).toBeInTheDocument(); - expect(screen.getByLabelText('Pay grade')).toBeInTheDocument(); + expect(screen.getByLabelText(/Current duty location/)).toBeInTheDocument(); + expect(screen.getByLabelText(/New duty location/)).toBeInTheDocument(); + expect(screen.getByLabelText(/Pay grade/)).toBeInTheDocument(); }); }); @@ -167,12 +167,12 @@ describe('CreateMoveCustomerInfo Component', () => { , ); - await userEvent.click(getByLabelText('Orders type')); - await userEvent.click(getByLabelText('Orders date')); - await userEvent.click(getByLabelText('Report by date')); - await userEvent.click(getByLabelText('Current duty location')); - await userEvent.click(getByLabelText('New duty location')); - await userEvent.click(getByLabelText('Pay grade')); + await userEvent.click(getByLabelText(/Orders type/)); + await userEvent.click(getByLabelText(/Orders date/)); + await userEvent.click(getByLabelText(/Report by date/)); + await userEvent.click(getByLabelText(/Current duty location/)); + await userEvent.click(getByLabelText(/New duty location/)); + await userEvent.click(getByLabelText(/Pay grade/)); const submitBtn = getByRole('button', { name: 'Next' }); await userEvent.click(submitBtn); @@ -240,7 +240,7 @@ describe('AddOrdersForm - Edge Cases and Additional Scenarios', () => { , ); - expect(screen.getByLabelText('Orders type')).toBeDisabled(); + expect(screen.getByLabelText(/Orders type/)).toBeDisabled(); }); it('disables orders type when bluebark move is selected', async () => { @@ -249,7 +249,7 @@ describe('AddOrdersForm - Edge Cases and Additional Scenarios', () => { , ); - expect(screen.getByLabelText('Orders type')).toBeDisabled(); + expect(screen.getByLabelText(/Orders type/)).toBeDisabled(); }); }); diff --git a/src/pages/Office/ServicesCounselingAddOrders/ServicesCounselingAddOrders.test.jsx b/src/pages/Office/ServicesCounselingAddOrders/ServicesCounselingAddOrders.test.jsx index a0accc4b2db..8d2cc7a2fb8 100644 --- a/src/pages/Office/ServicesCounselingAddOrders/ServicesCounselingAddOrders.test.jsx +++ b/src/pages/Office/ServicesCounselingAddOrders/ServicesCounselingAddOrders.test.jsx @@ -357,21 +357,21 @@ describe('ServicesCounselingAddOrders component', () => { const user = userEvent.setup(); - await user.selectOptions(screen.getByLabelText('Orders type'), 'PERMANENT_CHANGE_OF_STATION'); - await user.type(screen.getByLabelText('Orders date'), '08 Nov 2020'); - await user.type(screen.getByLabelText('Report by date'), '26 Nov 2020'); + await user.selectOptions(screen.getByLabelText(/Orders type/), 'PERMANENT_CHANGE_OF_STATION'); + await user.type(screen.getByLabelText(/Orders date/), '08 Nov 2020'); + await user.type(screen.getByLabelText(/Report by date/), '26 Nov 2020'); await user.click(screen.getByLabelText('No')); - await user.selectOptions(screen.getByLabelText('Pay grade'), ['E-5']); + await user.selectOptions(screen.getByLabelText(/Pay grade/), ['E-5']); // Test Current Duty Location Search Box interaction - await user.type(screen.getByLabelText('Current duty location'), 'AFB', { delay: 500 }); + await user.type(screen.getByLabelText(/Current duty location/), 'AFB', { delay: 500 }); const selectedOptionCurrent = await screen.findByText(/Altus/); await user.click(selectedOptionCurrent); const counselingOfficeLabel = await screen.queryByText(/Counseling office/); expect(counselingOfficeLabel).toBeFalsy(); - await user.type(screen.getByLabelText('New duty location'), 'AFB', { delay: 500 }); + await user.type(screen.getByLabelText(/New duty location/), 'AFB', { delay: 500 }); const selectedOptionNew = await screen.findByText(/Luke/); await user.click(selectedOptionNew); @@ -395,14 +395,14 @@ describe('ServicesCounselingAddOrders component', () => { const user = userEvent.setup(); - await user.selectOptions(screen.getByLabelText('Orders type'), 'PERMANENT_CHANGE_OF_STATION'); - await user.type(screen.getByLabelText('Orders date'), '08 Nov 2020'); - await user.type(screen.getByLabelText('Report by date'), '29 Nov 2020'); + await user.selectOptions(screen.getByLabelText(/Orders type/), 'PERMANENT_CHANGE_OF_STATION'); + await user.type(screen.getByLabelText(/Orders date/), '08 Nov 2020'); + await user.type(screen.getByLabelText(/Report by date/), '29 Nov 2020'); await user.click(screen.getByLabelText('No')); - await user.selectOptions(screen.getByLabelText('Pay grade'), ['E-5']); + await user.selectOptions(screen.getByLabelText(/Pay grade/), ['E-5']); // Test Current Duty Location Search Box interaction - await user.type(screen.getByLabelText('Current duty location'), 'AFB', { delay: 500 }); + await user.type(screen.getByLabelText(/Current duty location/), 'AFB', { delay: 500 }); const selectedOptionCurrent = await screen.findByText(/Hill/); await user.click(selectedOptionCurrent); @@ -411,7 +411,7 @@ describe('ServicesCounselingAddOrders component', () => { await userEvent.selectOptions(screen.getByLabelText(/Counseling office/), ['Glendale Luke AFB']); - await user.type(screen.getByLabelText('New duty location'), 'AFB', { delay: 500 }); + await user.type(screen.getByLabelText(/New duty location/), 'AFB', { delay: 500 }); const selectedOptionNew = await screen.findByText(/Luke/); await user.click(selectedOptionNew); @@ -429,17 +429,17 @@ describe('ServicesCounselingAddOrders component', () => { const user = userEvent.setup(); - await user.selectOptions(screen.getByLabelText('Orders type'), 'PERMANENT_CHANGE_OF_STATION'); - await user.type(screen.getByLabelText('Orders date'), '08 Nov 2020'); - await user.type(screen.getByLabelText('Report by date'), '26 Nov 2020'); + await user.selectOptions(screen.getByLabelText(/Orders type/), 'PERMANENT_CHANGE_OF_STATION'); + await user.type(screen.getByLabelText(/Orders date/), '08 Nov 2020'); + await user.type(screen.getByLabelText(/Report by date/), '26 Nov 2020'); await user.click(screen.getByLabelText('No')); - await user.selectOptions(screen.getByLabelText('Pay grade'), ['E-5']); + await user.selectOptions(screen.getByLabelText(/Pay grade/), ['E-5']); - await user.type(screen.getByLabelText('Current duty location'), 'AFB', { delay: 500 }); + await user.type(screen.getByLabelText(/Current duty location/), 'AFB', { delay: 500 }); const selectedOptionCurrent = await screen.findByText(/Altus/); await user.click(selectedOptionCurrent); - await user.type(screen.getByLabelText('New duty location'), 'AFB', { delay: 500 }); + await user.type(screen.getByLabelText(/New duty location/), 'AFB', { delay: 500 }); const selectedOptionNew = await screen.findByText(/Outta This World/); await user.click(selectedOptionNew); From 5b30fcdd738f7db3278c63e27710f2aa320aa3a9 Mon Sep 17 00:00:00 2001 From: Alex Lusk Date: Fri, 17 Jan 2025 22:38:56 +0000 Subject: [PATCH 16/20] test updates for 21977 --- .../AddOrdersForm/AddOrdersForm.test.jsx | 18 +++++++++--------- 1 file changed, 9 insertions(+), 9 deletions(-) diff --git a/src/components/Office/AddOrdersForm/AddOrdersForm.test.jsx b/src/components/Office/AddOrdersForm/AddOrdersForm.test.jsx index 91357ff5db9..639d617de43 100644 --- a/src/components/Office/AddOrdersForm/AddOrdersForm.test.jsx +++ b/src/components/Office/AddOrdersForm/AddOrdersForm.test.jsx @@ -170,7 +170,7 @@ describe('CreateMoveCustomerInfo Component', () => { , ); - const ordersTypeDropdown = getByLabelText('Orders type'); + const ordersTypeDropdown = getByLabelText(/Orders type/); expect(ordersTypeDropdown).toBeInstanceOf(HTMLSelectElement); await userEvent.selectOptions(ordersTypeDropdown, ORDERS_TYPE.PERMANENT_CHANGE_OF_STATION); @@ -277,7 +277,7 @@ describe('AddOrdersForm - Student Travel, Early Return of Dependents Test', () = , ); - await userEvent.selectOptions(screen.getByLabelText('Orders type'), ORDERS_TYPE.STUDENT_TRAVEL); + await userEvent.selectOptions(screen.getByLabelText(/Orders type/), ORDERS_TYPE.STUDENT_TRAVEL); const hasDependentsYes = screen.getByLabelText('Yes'); const hasDependentsNo = screen.getByLabelText('No'); @@ -298,7 +298,7 @@ describe('AddOrdersForm - Student Travel, Early Return of Dependents Test', () = , ); - await userEvent.selectOptions(screen.getByLabelText('Orders type'), ORDERS_TYPE.EARLY_RETURN_OF_DEPENDENTS); + await userEvent.selectOptions(screen.getByLabelText(/Orders type/), ORDERS_TYPE.EARLY_RETURN_OF_DEPENDENTS); const hasDependentsYes = screen.getByLabelText('Yes'); const hasDependentsNo = screen.getByLabelText('No'); @@ -318,7 +318,7 @@ describe('AddOrdersForm - Student Travel, Early Return of Dependents Test', () = , ); - await userEvent.selectOptions(screen.getByLabelText('Orders type'), ORDERS_TYPE.PERMANENT_CHANGE_OF_STATION); + await userEvent.selectOptions(screen.getByLabelText(/Orders type/), ORDERS_TYPE.PERMANENT_CHANGE_OF_STATION); const hasDependentsYesPermChg = screen.getByLabelText('Yes'); const hasDependentsNoPermChg = screen.getByLabelText('No'); @@ -331,7 +331,7 @@ describe('AddOrdersForm - Student Travel, Early Return of Dependents Test', () = }); // set order type to value that disables and defaults "has dependents" - await userEvent.selectOptions(screen.getByLabelText('Orders type'), ORDERS_TYPE.STUDENT_TRAVEL); + await userEvent.selectOptions(screen.getByLabelText(/Orders type/), ORDERS_TYPE.STUDENT_TRAVEL); const hasDependentsYesStudent = screen.getByLabelText('Yes'); const hasDependentsNoStudent = screen.getByLabelText('No'); @@ -343,7 +343,7 @@ describe('AddOrdersForm - Student Travel, Early Return of Dependents Test', () = }); // set order type to value the re-enables "has dependents" - await userEvent.selectOptions(screen.getByLabelText('Orders type'), ORDERS_TYPE.LOCAL_MOVE); + await userEvent.selectOptions(screen.getByLabelText(/Orders type/), ORDERS_TYPE.LOCAL_MOVE); const hasDependentsYesLocalMove = screen.getByLabelText('Yes'); const hasDependentsNoLocalMove = screen.getByLabelText('No'); @@ -365,7 +365,7 @@ describe('AddOrdersForm - Student Travel, Early Return of Dependents Test', () = , ); - await userEvent.selectOptions(screen.getByLabelText('Orders type'), ORDERS_TYPE.PERMANENT_CHANGE_OF_STATION); + await userEvent.selectOptions(screen.getByLabelText(/Orders type/), ORDERS_TYPE.PERMANENT_CHANGE_OF_STATION); const hasDependentsYesPermChg = screen.getByLabelText('Yes'); const hasDependentsNoPermChg = screen.getByLabelText('No'); @@ -378,7 +378,7 @@ describe('AddOrdersForm - Student Travel, Early Return of Dependents Test', () = }); // set order type to value that disables and defaults "has dependents" - await userEvent.selectOptions(screen.getByLabelText('Orders type'), ORDERS_TYPE.EARLY_RETURN_OF_DEPENDENTS); + await userEvent.selectOptions(screen.getByLabelText(/Orders type/), ORDERS_TYPE.EARLY_RETURN_OF_DEPENDENTS); const hasDependentsYesEarly = screen.getByLabelText('Yes'); const hasDependentsNoEarly = screen.getByLabelText('No'); @@ -390,7 +390,7 @@ describe('AddOrdersForm - Student Travel, Early Return of Dependents Test', () = }); // set order type to value the re-enables "has dependents" - await userEvent.selectOptions(screen.getByLabelText('Orders type'), ORDERS_TYPE.LOCAL_MOVE); + await userEvent.selectOptions(screen.getByLabelText(/Orders type/), ORDERS_TYPE.LOCAL_MOVE); const hasDependentsYesLocalMove = screen.getByLabelText('Yes'); const hasDependentsNoLocalMove = screen.getByLabelText('No'); From 9038658aff5c46cddc9e553f6b421c2fd19f4d18 Mon Sep 17 00:00:00 2001 From: Alex Lusk Date: Mon, 27 Jan 2025 18:47:33 +0000 Subject: [PATCH 17/20] pass serviceMemberId to office app's get counseling offices handler and pass it to service --- pkg/gen/ghcapi/embedded_spec.go | 47 +++++- pkg/gen/ghcapi/ghcoperations/mymove_api.go | 2 +- .../show_counseling_offices.go | 2 +- .../show_counseling_offices_parameters.go | 43 ++++++ .../show_counseling_offices_responses.go | 135 ++++++++++++++++++ .../show_counseling_offices_urlbuilder.go | 12 +- pkg/handlers/ghcapi/tranportation_offices.go | 3 +- .../internalapi/transportation_offices.go | 2 +- .../mocks/TransportationOfficesFetcher.go | 18 +-- pkg/services/transportation_office.go | 2 +- .../transportation_office_fetcher.go | 13 +- .../transportation_office_fetcher_test.go | 29 ++-- .../Office/AddOrdersForm/AddOrdersForm.jsx | 8 +- src/services/ghcApi.js | 4 +- swagger-def/ghc.yaml | 14 +- swagger/ghc.yaml | 16 ++- 16 files changed, 309 insertions(+), 41 deletions(-) diff --git a/pkg/gen/ghcapi/embedded_spec.go b/pkg/gen/ghcapi/embedded_spec.go index 9beed88f2e7..a882cd98800 100644 --- a/pkg/gen/ghcapi/embedded_spec.go +++ b/pkg/gen/ghcapi/embedded_spec.go @@ -6275,7 +6275,7 @@ func init() { } } }, - "/transportation_offices/{dutyLocationId}/counseling_offices": { + "/transportation_offices/{dutyLocationId}/counseling_offices/{serviceMemberId}": { "get": { "description": "Returns the counseling locations matching the GBLOC from the selected duty location", "produces": [ @@ -6294,6 +6294,14 @@ func init() { "name": "dutyLocationId", "in": "path", "required": true + }, + { + "type": "string", + "format": "uuid", + "description": "UUID of the service member, some counseling offices are branch specific", + "name": "serviceMemberId", + "in": "path", + "required": true } ], "responses": { @@ -6303,6 +6311,15 @@ func init() { "$ref": "#/definitions/CounselingOffices" } }, + "400": { + "$ref": "#/responses/InvalidRequest" + }, + "403": { + "$ref": "#/responses/PermissionDenied" + }, + "404": { + "$ref": "#/responses/NotFound" + }, "500": { "description": "internal server error" } @@ -23365,7 +23382,7 @@ func init() { } } }, - "/transportation_offices/{dutyLocationId}/counseling_offices": { + "/transportation_offices/{dutyLocationId}/counseling_offices/{serviceMemberId}": { "get": { "description": "Returns the counseling locations matching the GBLOC from the selected duty location", "produces": [ @@ -23384,6 +23401,14 @@ func init() { "name": "dutyLocationId", "in": "path", "required": true + }, + { + "type": "string", + "format": "uuid", + "description": "UUID of the service member, some counseling offices are branch specific", + "name": "serviceMemberId", + "in": "path", + "required": true } ], "responses": { @@ -23393,6 +23418,24 @@ func init() { "$ref": "#/definitions/CounselingOffices" } }, + "400": { + "description": "The request payload is invalid", + "schema": { + "$ref": "#/definitions/Error" + } + }, + "403": { + "description": "The request was denied", + "schema": { + "$ref": "#/definitions/Error" + } + }, + "404": { + "description": "The requested resource wasn't found", + "schema": { + "$ref": "#/definitions/Error" + } + }, "500": { "description": "internal server error" } diff --git a/pkg/gen/ghcapi/ghcoperations/mymove_api.go b/pkg/gen/ghcapi/ghcoperations/mymove_api.go index 49432fc71b9..7d9bb87acf6 100644 --- a/pkg/gen/ghcapi/ghcoperations/mymove_api.go +++ b/pkg/gen/ghcapi/ghcoperations/mymove_api.go @@ -1487,7 +1487,7 @@ func (o *MymoveAPI) initHandlerCache() { if o.handlers["GET"] == nil { o.handlers["GET"] = make(map[string]http.Handler) } - o.handlers["GET"]["/transportation_offices/{dutyLocationId}/counseling_offices"] = transportation_office.NewShowCounselingOffices(o.context, o.TransportationOfficeShowCounselingOfficesHandler) + o.handlers["GET"]["/transportation_offices/{dutyLocationId}/counseling_offices/{serviceMemberId}"] = transportation_office.NewShowCounselingOffices(o.context, o.TransportationOfficeShowCounselingOfficesHandler) if o.handlers["GET"] == nil { o.handlers["GET"] = make(map[string]http.Handler) } diff --git a/pkg/gen/ghcapi/ghcoperations/transportation_office/show_counseling_offices.go b/pkg/gen/ghcapi/ghcoperations/transportation_office/show_counseling_offices.go index 5b4c1967e43..b0cb58981df 100644 --- a/pkg/gen/ghcapi/ghcoperations/transportation_office/show_counseling_offices.go +++ b/pkg/gen/ghcapi/ghcoperations/transportation_office/show_counseling_offices.go @@ -30,7 +30,7 @@ func NewShowCounselingOffices(ctx *middleware.Context, handler ShowCounselingOff } /* - ShowCounselingOffices swagger:route GET /transportation_offices/{dutyLocationId}/counseling_offices transportationOffice showCounselingOffices + ShowCounselingOffices swagger:route GET /transportation_offices/{dutyLocationId}/counseling_offices/{serviceMemberId} transportationOffice showCounselingOffices # Returns the counseling locations in the GBLOC matching the duty location diff --git a/pkg/gen/ghcapi/ghcoperations/transportation_office/show_counseling_offices_parameters.go b/pkg/gen/ghcapi/ghcoperations/transportation_office/show_counseling_offices_parameters.go index 24f4c585bfd..91d0a12238c 100644 --- a/pkg/gen/ghcapi/ghcoperations/transportation_office/show_counseling_offices_parameters.go +++ b/pkg/gen/ghcapi/ghcoperations/transportation_office/show_counseling_offices_parameters.go @@ -36,6 +36,11 @@ type ShowCounselingOfficesParams struct { In: path */ DutyLocationID strfmt.UUID + /*UUID of the service member, some counseling offices are branch specific + Required: true + In: path + */ + ServiceMemberID strfmt.UUID } // BindRequest both binds and validates a request, it assumes that complex things implement a Validatable(strfmt.Registry) error interface @@ -51,6 +56,11 @@ func (o *ShowCounselingOfficesParams) BindRequest(r *http.Request, route *middle if err := o.bindDutyLocationID(rDutyLocationID, rhkDutyLocationID, route.Formats); err != nil { res = append(res, err) } + + rServiceMemberID, rhkServiceMemberID, _ := route.Params.GetOK("serviceMemberId") + if err := o.bindServiceMemberID(rServiceMemberID, rhkServiceMemberID, route.Formats); err != nil { + res = append(res, err) + } if len(res) > 0 { return errors.CompositeValidationError(res...) } @@ -89,3 +99,36 @@ func (o *ShowCounselingOfficesParams) validateDutyLocationID(formats strfmt.Regi } return nil } + +// bindServiceMemberID binds and validates parameter ServiceMemberID from path. +func (o *ShowCounselingOfficesParams) bindServiceMemberID(rawData []string, hasKey bool, formats strfmt.Registry) error { + var raw string + if len(rawData) > 0 { + raw = rawData[len(rawData)-1] + } + + // Required: true + // Parameter is provided by construction from the route + + // Format: uuid + value, err := formats.Parse("uuid", raw) + if err != nil { + return errors.InvalidType("serviceMemberId", "path", "strfmt.UUID", raw) + } + o.ServiceMemberID = *(value.(*strfmt.UUID)) + + if err := o.validateServiceMemberID(formats); err != nil { + return err + } + + return nil +} + +// validateServiceMemberID carries on validations for parameter ServiceMemberID +func (o *ShowCounselingOfficesParams) validateServiceMemberID(formats strfmt.Registry) error { + + if err := validate.FormatOf("serviceMemberId", "path", "uuid", o.ServiceMemberID.String(), formats); err != nil { + return err + } + return nil +} diff --git a/pkg/gen/ghcapi/ghcoperations/transportation_office/show_counseling_offices_responses.go b/pkg/gen/ghcapi/ghcoperations/transportation_office/show_counseling_offices_responses.go index 73793566c47..0e38c7ca905 100644 --- a/pkg/gen/ghcapi/ghcoperations/transportation_office/show_counseling_offices_responses.go +++ b/pkg/gen/ghcapi/ghcoperations/transportation_office/show_counseling_offices_responses.go @@ -61,6 +61,141 @@ func (o *ShowCounselingOfficesOK) WriteResponse(rw http.ResponseWriter, producer } } +// ShowCounselingOfficesBadRequestCode is the HTTP code returned for type ShowCounselingOfficesBadRequest +const ShowCounselingOfficesBadRequestCode int = 400 + +/* +ShowCounselingOfficesBadRequest The request payload is invalid + +swagger:response showCounselingOfficesBadRequest +*/ +type ShowCounselingOfficesBadRequest struct { + + /* + In: Body + */ + Payload *ghcmessages.Error `json:"body,omitempty"` +} + +// NewShowCounselingOfficesBadRequest creates ShowCounselingOfficesBadRequest with default headers values +func NewShowCounselingOfficesBadRequest() *ShowCounselingOfficesBadRequest { + + return &ShowCounselingOfficesBadRequest{} +} + +// WithPayload adds the payload to the show counseling offices bad request response +func (o *ShowCounselingOfficesBadRequest) WithPayload(payload *ghcmessages.Error) *ShowCounselingOfficesBadRequest { + o.Payload = payload + return o +} + +// SetPayload sets the payload to the show counseling offices bad request response +func (o *ShowCounselingOfficesBadRequest) SetPayload(payload *ghcmessages.Error) { + o.Payload = payload +} + +// WriteResponse to the client +func (o *ShowCounselingOfficesBadRequest) WriteResponse(rw http.ResponseWriter, producer runtime.Producer) { + + rw.WriteHeader(400) + if o.Payload != nil { + payload := o.Payload + if err := producer.Produce(rw, payload); err != nil { + panic(err) // let the recovery middleware deal with this + } + } +} + +// ShowCounselingOfficesForbiddenCode is the HTTP code returned for type ShowCounselingOfficesForbidden +const ShowCounselingOfficesForbiddenCode int = 403 + +/* +ShowCounselingOfficesForbidden The request was denied + +swagger:response showCounselingOfficesForbidden +*/ +type ShowCounselingOfficesForbidden struct { + + /* + In: Body + */ + Payload *ghcmessages.Error `json:"body,omitempty"` +} + +// NewShowCounselingOfficesForbidden creates ShowCounselingOfficesForbidden with default headers values +func NewShowCounselingOfficesForbidden() *ShowCounselingOfficesForbidden { + + return &ShowCounselingOfficesForbidden{} +} + +// WithPayload adds the payload to the show counseling offices forbidden response +func (o *ShowCounselingOfficesForbidden) WithPayload(payload *ghcmessages.Error) *ShowCounselingOfficesForbidden { + o.Payload = payload + return o +} + +// SetPayload sets the payload to the show counseling offices forbidden response +func (o *ShowCounselingOfficesForbidden) SetPayload(payload *ghcmessages.Error) { + o.Payload = payload +} + +// WriteResponse to the client +func (o *ShowCounselingOfficesForbidden) WriteResponse(rw http.ResponseWriter, producer runtime.Producer) { + + rw.WriteHeader(403) + if o.Payload != nil { + payload := o.Payload + if err := producer.Produce(rw, payload); err != nil { + panic(err) // let the recovery middleware deal with this + } + } +} + +// ShowCounselingOfficesNotFoundCode is the HTTP code returned for type ShowCounselingOfficesNotFound +const ShowCounselingOfficesNotFoundCode int = 404 + +/* +ShowCounselingOfficesNotFound The requested resource wasn't found + +swagger:response showCounselingOfficesNotFound +*/ +type ShowCounselingOfficesNotFound struct { + + /* + In: Body + */ + Payload *ghcmessages.Error `json:"body,omitempty"` +} + +// NewShowCounselingOfficesNotFound creates ShowCounselingOfficesNotFound with default headers values +func NewShowCounselingOfficesNotFound() *ShowCounselingOfficesNotFound { + + return &ShowCounselingOfficesNotFound{} +} + +// WithPayload adds the payload to the show counseling offices not found response +func (o *ShowCounselingOfficesNotFound) WithPayload(payload *ghcmessages.Error) *ShowCounselingOfficesNotFound { + o.Payload = payload + return o +} + +// SetPayload sets the payload to the show counseling offices not found response +func (o *ShowCounselingOfficesNotFound) SetPayload(payload *ghcmessages.Error) { + o.Payload = payload +} + +// WriteResponse to the client +func (o *ShowCounselingOfficesNotFound) WriteResponse(rw http.ResponseWriter, producer runtime.Producer) { + + rw.WriteHeader(404) + if o.Payload != nil { + payload := o.Payload + if err := producer.Produce(rw, payload); err != nil { + panic(err) // let the recovery middleware deal with this + } + } +} + // ShowCounselingOfficesInternalServerErrorCode is the HTTP code returned for type ShowCounselingOfficesInternalServerError const ShowCounselingOfficesInternalServerErrorCode int = 500 diff --git a/pkg/gen/ghcapi/ghcoperations/transportation_office/show_counseling_offices_urlbuilder.go b/pkg/gen/ghcapi/ghcoperations/transportation_office/show_counseling_offices_urlbuilder.go index 1f0e360afa7..269dfc8874e 100644 --- a/pkg/gen/ghcapi/ghcoperations/transportation_office/show_counseling_offices_urlbuilder.go +++ b/pkg/gen/ghcapi/ghcoperations/transportation_office/show_counseling_offices_urlbuilder.go @@ -16,7 +16,8 @@ import ( // ShowCounselingOfficesURL generates an URL for the show counseling offices operation type ShowCounselingOfficesURL struct { - DutyLocationID strfmt.UUID + DutyLocationID strfmt.UUID + ServiceMemberID strfmt.UUID _basePath string // avoid unkeyed usage @@ -42,7 +43,7 @@ func (o *ShowCounselingOfficesURL) SetBasePath(bp string) { func (o *ShowCounselingOfficesURL) Build() (*url.URL, error) { var _result url.URL - var _path = "/transportation_offices/{dutyLocationId}/counseling_offices" + var _path = "/transportation_offices/{dutyLocationId}/counseling_offices/{serviceMemberId}" dutyLocationID := o.DutyLocationID.String() if dutyLocationID != "" { @@ -51,6 +52,13 @@ func (o *ShowCounselingOfficesURL) Build() (*url.URL, error) { return nil, errors.New("dutyLocationId is required on ShowCounselingOfficesURL") } + serviceMemberID := o.ServiceMemberID.String() + if serviceMemberID != "" { + _path = strings.Replace(_path, "{serviceMemberId}", serviceMemberID, -1) + } else { + return nil, errors.New("serviceMemberId is required on ShowCounselingOfficesURL") + } + _basePath := o._basePath if _basePath == "" { _basePath = "/ghc/v1" diff --git a/pkg/handlers/ghcapi/tranportation_offices.go b/pkg/handlers/ghcapi/tranportation_offices.go index 6c0dcacc1b6..5df15bb6aaa 100644 --- a/pkg/handlers/ghcapi/tranportation_offices.go +++ b/pkg/handlers/ghcapi/tranportation_offices.go @@ -86,8 +86,9 @@ func (h ShowCounselingOfficesHandler) Handle(params transportationofficeop.ShowC return h.AuditableAppContextFromRequestWithErrors(params.HTTPRequest, func(appCtx appcontext.AppContext) (middleware.Responder, error) { dutyLocationID := uuid.FromStringOrNil(params.DutyLocationID.String()) + serviceMemberID := uuid.FromStringOrNil(params.ServiceMemberID.String()) - counselingOffices, err := h.TransportationOfficesFetcher.GetCounselingOffices(appCtx, dutyLocationID) + counselingOffices, err := h.TransportationOfficesFetcher.GetCounselingOffices(appCtx, dutyLocationID, serviceMemberID) if err != nil { appCtx.Logger().Error("Error searching for Counseling Offices: ", zap.Error(err)) return transportationofficeop.NewShowCounselingOfficesInternalServerError(), err diff --git a/pkg/handlers/internalapi/transportation_offices.go b/pkg/handlers/internalapi/transportation_offices.go index 6b535fd9ba9..f1f7eb706eb 100644 --- a/pkg/handlers/internalapi/transportation_offices.go +++ b/pkg/handlers/internalapi/transportation_offices.go @@ -74,7 +74,7 @@ func (h ShowCounselingOfficesHandler) Handle(params transportationofficeop.ShowC func(appCtx appcontext.AppContext) (middleware.Responder, error) { dutyLocationID := uuid.FromStringOrNil(params.DutyLocationID.String()) - counselingOffices, err := h.TransportationOfficesFetcher.GetCounselingOffices(appCtx, dutyLocationID) + counselingOffices, err := h.TransportationOfficesFetcher.GetCounselingOffices(appCtx, dutyLocationID, appCtx.Session().ServiceMemberID) if err != nil { appCtx.Logger().Error("Error searching for Counseling Offices: ", zap.Error(err)) return transportationofficeop.NewShowCounselingOfficesInternalServerError(), err diff --git a/pkg/services/mocks/TransportationOfficesFetcher.go b/pkg/services/mocks/TransportationOfficesFetcher.go index eed32753594..ad777d72b0a 100644 --- a/pkg/services/mocks/TransportationOfficesFetcher.go +++ b/pkg/services/mocks/TransportationOfficesFetcher.go @@ -46,9 +46,9 @@ func (_m *TransportationOfficesFetcher) GetAllGBLOCs(appCtx appcontext.AppContex return r0, r1 } -// GetCounselingOffices provides a mock function with given fields: appCtx, dutyLocationID -func (_m *TransportationOfficesFetcher) GetCounselingOffices(appCtx appcontext.AppContext, dutyLocationID uuid.UUID) (*models.TransportationOffices, error) { - ret := _m.Called(appCtx, dutyLocationID) +// GetCounselingOffices provides a mock function with given fields: appCtx, dutyLocationID, serviceMemberID +func (_m *TransportationOfficesFetcher) GetCounselingOffices(appCtx appcontext.AppContext, dutyLocationID uuid.UUID, serviceMemberID uuid.UUID) (*models.TransportationOffices, error) { + ret := _m.Called(appCtx, dutyLocationID, serviceMemberID) if len(ret) == 0 { panic("no return value specified for GetCounselingOffices") @@ -56,19 +56,19 @@ func (_m *TransportationOfficesFetcher) GetCounselingOffices(appCtx appcontext.A var r0 *models.TransportationOffices var r1 error - if rf, ok := ret.Get(0).(func(appcontext.AppContext, uuid.UUID) (*models.TransportationOffices, error)); ok { - return rf(appCtx, dutyLocationID) + if rf, ok := ret.Get(0).(func(appcontext.AppContext, uuid.UUID, uuid.UUID) (*models.TransportationOffices, error)); ok { + return rf(appCtx, dutyLocationID, serviceMemberID) } - if rf, ok := ret.Get(0).(func(appcontext.AppContext, uuid.UUID) *models.TransportationOffices); ok { - r0 = rf(appCtx, dutyLocationID) + if rf, ok := ret.Get(0).(func(appcontext.AppContext, uuid.UUID, uuid.UUID) *models.TransportationOffices); ok { + r0 = rf(appCtx, dutyLocationID, serviceMemberID) } else { if ret.Get(0) != nil { r0 = ret.Get(0).(*models.TransportationOffices) } } - if rf, ok := ret.Get(1).(func(appcontext.AppContext, uuid.UUID) error); ok { - r1 = rf(appCtx, dutyLocationID) + if rf, ok := ret.Get(1).(func(appcontext.AppContext, uuid.UUID, uuid.UUID) error); ok { + r1 = rf(appCtx, dutyLocationID, serviceMemberID) } else { r1 = ret.Error(1) } diff --git a/pkg/services/transportation_office.go b/pkg/services/transportation_office.go index 307f0d0fef5..9ec90364ba0 100644 --- a/pkg/services/transportation_office.go +++ b/pkg/services/transportation_office.go @@ -12,5 +12,5 @@ type TransportationOfficesFetcher interface { GetTransportationOffices(appCtx appcontext.AppContext, search string, forPpm bool) (*models.TransportationOffices, error) GetTransportationOffice(appCtx appcontext.AppContext, transportationOfficeID uuid.UUID, includeOnlyPPMCloseoutOffices bool) (*models.TransportationOffice, error) GetAllGBLOCs(appCtx appcontext.AppContext) (*models.GBLOCs, error) - GetCounselingOffices(appCtx appcontext.AppContext, dutyLocationID uuid.UUID) (*models.TransportationOffices, error) + GetCounselingOffices(appCtx appcontext.AppContext, dutyLocationID uuid.UUID, serviceMemberID uuid.UUID) (*models.TransportationOffices, error) } diff --git a/pkg/services/transportation_office/transportation_office_fetcher.go b/pkg/services/transportation_office/transportation_office_fetcher.go index be942890c75..8ccd09694f3 100644 --- a/pkg/services/transportation_office/transportation_office_fetcher.go +++ b/pkg/services/transportation_office/transportation_office_fetcher.go @@ -127,8 +127,8 @@ func ListDistinctGBLOCs(appCtx appcontext.AppContext) (models.GBLOCs, error) { return gblocList, err } -func (o transportationOfficesFetcher) GetCounselingOffices(appCtx appcontext.AppContext, dutyLocationID uuid.UUID) (*models.TransportationOffices, error) { - officeList, err := findCounselingOffice(appCtx, dutyLocationID) +func (o transportationOfficesFetcher) GetCounselingOffices(appCtx appcontext.AppContext, dutyLocationID uuid.UUID, serviceMemberID uuid.UUID) (*models.TransportationOffices, error) { + officeList, err := findCounselingOffice(appCtx, dutyLocationID, serviceMemberID) if err != nil { switch err { @@ -143,7 +143,8 @@ func (o transportationOfficesFetcher) GetCounselingOffices(appCtx appcontext.App } // return all the transportation offices in the GBLOC of the given duty location where provides_services_counseling = true -func findCounselingOffice(appCtx appcontext.AppContext, dutyLocationID uuid.UUID) (models.TransportationOffices, error) { +// serviceMemberID is only provided when this function is called by the office handler +func findCounselingOffice(appCtx appcontext.AppContext, dutyLocationID uuid.UUID, serviceMemberID uuid.UUID) (models.TransportationOffices, error) { var officeList []models.TransportationOffice duty_location, err := models.FetchDutyLocation(appCtx.DB(), dutyLocationID) @@ -157,7 +158,7 @@ func findCounselingOffice(appCtx appcontext.AppContext, dutyLocationID uuid.UUID // Find for oconus duty location // ******************************** if *duty_location.Address.IsOconus { - gblocDepartmentIndicator, err := findOconusGblocDepartmentIndicator(appCtx, duty_location) + gblocDepartmentIndicator, err := findOconusGblocDepartmentIndicator(appCtx, duty_location, serviceMemberID) if err != nil { return officeList, err } @@ -238,8 +239,8 @@ func findCounselingOffice(appCtx appcontext.AppContext, dutyLocationID uuid.UUID return officeList, nil } -func findOconusGblocDepartmentIndicator(appCtx appcontext.AppContext, dutyLocation models.DutyLocation) (*oconusGblocDepartmentIndicator, error) { - serviceMember, err := models.FetchServiceMember(appCtx.DB(), appCtx.Session().ServiceMemberID) +func findOconusGblocDepartmentIndicator(appCtx appcontext.AppContext, dutyLocation models.DutyLocation, serviceMemberID uuid.UUID) (*oconusGblocDepartmentIndicator, error) { + serviceMember, err := models.FetchServiceMember(appCtx.DB(), serviceMemberID) if err != nil { return nil, err } diff --git a/pkg/services/transportation_office/transportation_office_fetcher_test.go b/pkg/services/transportation_office/transportation_office_fetcher_test.go index 9ce5bab765c..7514868e12a 100644 --- a/pkg/services/transportation_office/transportation_office_fetcher_test.go +++ b/pkg/services/transportation_office/transportation_office_fetcher_test.go @@ -181,7 +181,16 @@ func (suite *TransportationOfficeServiceSuite) Test_FindCounselingOffices() { }, }, nil) - offices, err := findCounselingOffice(suite.AppContextForTest(), origDutyLocation.ID) + armyAffliation := models.AffiliationARMY + serviceMember := factory.BuildServiceMember(suite.DB(), []factory.Customization{ + { + Model: models.ServiceMember{ + Affiliation: &armyAffliation, + }, + }, + }, nil) + + offices, err := findCounselingOffice(suite.AppContextForTest(), origDutyLocation.ID, serviceMember.ID) suite.NoError(err) suite.Len(offices, 2) @@ -368,7 +377,7 @@ func (suite *TransportationOfficeServiceSuite) Test_Oconus_AK_FindCounselingOffi ServiceMemberID: serviceMember.ID, }) suite.Nil(err) - departmentIndictor, err := findOconusGblocDepartmentIndicator(appCtx, dutylocation) + departmentIndictor, err := findOconusGblocDepartmentIndicator(appCtx, dutylocation, uuid.Nil) suite.NotNil(departmentIndictor) suite.Nil(err) suite.Nil(departmentIndictor.DepartmentIndicator) @@ -427,7 +436,7 @@ func (suite *TransportationOfficeServiceSuite) Test_Oconus_AK_FindCounselingOffi ServiceMemberID: serviceMember.ID, }) suite.Nil(err) - departmentIndictor, err := findOconusGblocDepartmentIndicator(appCtx, dutylocation) + departmentIndictor, err := findOconusGblocDepartmentIndicator(appCtx, dutylocation, appCtx.Session().ServiceMemberID) suite.NotNil(departmentIndictor) suite.Nil(err) suite.NotNil(departmentIndictor.DepartmentIndicator) @@ -455,7 +464,7 @@ func (suite *TransportationOfficeServiceSuite) Test_Oconus_AK_FindCounselingOffi ServiceMemberID: serviceMember.ID, }) suite.Nil(err) - departmentIndictor, err := findOconusGblocDepartmentIndicator(appCtx, dutylocation) + departmentIndictor, err := findOconusGblocDepartmentIndicator(appCtx, dutylocation, appCtx.Session().ServiceMemberID) suite.Nil(departmentIndictor) suite.NotNil(err) }) @@ -473,7 +482,7 @@ func (suite *TransportationOfficeServiceSuite) Test_Oconus_AK_FindCounselingOffi }) suite.Nil(err) - departmentIndictor, err := findOconusGblocDepartmentIndicator(appCtx, dutylocation) + departmentIndictor, err := findOconusGblocDepartmentIndicator(appCtx, dutylocation, appCtx.Session().ServiceMemberID) suite.Nil(departmentIndictor) suite.NotNil(err) }) @@ -483,7 +492,7 @@ func (suite *TransportationOfficeServiceSuite) Test_Oconus_AK_FindCounselingOffi ServiceMemberID: uuid.Must(uuid.NewV4()), }) unknown_duty_location_id := uuid.Must(uuid.NewV4()) - offices, err := findCounselingOffice(appCtx, unknown_duty_location_id) + offices, err := findCounselingOffice(appCtx, unknown_duty_location_id, appCtx.Session().ServiceMemberID) suite.Nil(offices) suite.NotNil(err) }) @@ -523,7 +532,7 @@ func (suite *TransportationOfficeServiceSuite) Test_Oconus_AK_FindCounselingOffi }) suite.Nil(err) - offices, err := findCounselingOffice(appCtx, dutylocation.ID) + offices, err := findCounselingOffice(appCtx, dutylocation.ID, appCtx.Session().ServiceMemberID) suite.NotNil(offices) suite.Nil(err) suite.Equal(1, len(offices)) @@ -539,7 +548,7 @@ func (suite *TransportationOfficeServiceSuite) Test_Oconus_AK_FindCounselingOffi }, }, }, nil) - offices, err = findCounselingOffice(appCtx, dutylocation.ID) + offices, err = findCounselingOffice(appCtx, dutylocation.ID, appCtx.Session().ServiceMemberID) suite.NotNil(offices) suite.Nil(err) suite.Equal(2, len(offices)) @@ -618,7 +627,7 @@ func (suite *TransportationOfficeServiceSuite) Test_Oconus_AK_FindCounselingOffi appCtx := suite.AppContextWithSessionForTest(&auth.Session{ ServiceMemberID: serviceMember.ID, }) - offices, err := findCounselingOffice(appCtx, dutylocation.ID) + offices, err := findCounselingOffice(appCtx, dutylocation.ID, appCtx.Session().ServiceMemberID) suite.NotNil(offices) suite.Nil(err) suite.Equal(1, len(offices)) @@ -629,7 +638,7 @@ func (suite *TransportationOfficeServiceSuite) Test_Oconus_AK_FindCounselingOffi appCtx := suite.AppContextWithSessionForTest(&auth.Session{ ServiceMemberID: serviceMember.ID, }) - offices, err := findCounselingOffice(appCtx, dutylocation.ID) + offices, err := findCounselingOffice(appCtx, dutylocation.ID, uuid.Nil) suite.NotNil(offices) suite.Nil(err) suite.Equal(1, len(offices)) diff --git a/src/components/Office/AddOrdersForm/AddOrdersForm.jsx b/src/components/Office/AddOrdersForm/AddOrdersForm.jsx index 9adc7e94e43..a2c6be4ff4d 100644 --- a/src/components/Office/AddOrdersForm/AddOrdersForm.jsx +++ b/src/components/Office/AddOrdersForm/AddOrdersForm.jsx @@ -1,4 +1,5 @@ import React, { useState, useEffect } from 'react'; +import { useParams } from 'react-router-dom'; import { Field, Formik } from 'formik'; import * as Yup from 'yup'; import { FormGroup, Label, Radio, Link as USWDSLink } from '@trussworks/react-uswds'; @@ -44,6 +45,7 @@ const AddOrdersForm = ({ const [isHasDependentsDisabled, setHasDependentsDisabled] = useState(false); const [prevOrderType, setPrevOrderType] = useState(''); const [filteredOrderTypeOptions, setFilteredOrderTypeOptions] = useState(ordersTypeOptions); + const { customerId: serviceMemberId } = useParams(); const validationSchema = Yup.object().shape({ ordersType: Yup.mixed() @@ -84,8 +86,8 @@ const AddOrdersForm = ({ }, []); useEffect(() => { - if (currentDutyLocation?.id) { - showCounselingOffices(currentDutyLocation.id).then((fetchedData) => { + if (currentDutyLocation?.id && serviceMemberId) { + showCounselingOffices(currentDutyLocation.id, serviceMemberId).then((fetchedData) => { if (fetchedData.body) { const counselingOffices = fetchedData.body.map((item) => ({ key: item.id, @@ -112,7 +114,7 @@ const AddOrdersForm = ({ setShowDependentAgeFields(false); } } - }, [currentDutyLocation, newDutyLocation, isOconusMove, hasDependents, enableUB]); + }, [currentDutyLocation, newDutyLocation, isOconusMove, hasDependents, enableUB, serviceMemberId]); useEffect(() => { const fetchData = async () => { diff --git a/src/services/ghcApi.js b/src/services/ghcApi.js index ccb69d56275..65218c1d9e3 100644 --- a/src/services/ghcApi.js +++ b/src/services/ghcApi.js @@ -763,8 +763,8 @@ export async function getGBLOCs() { return makeGHCRequest(operationPath, {}, { normalize: false }); } -export async function showCounselingOffices(dutyLocationId) { - return makeGHCRequestRaw('transportationOffice.showCounselingOffices', { dutyLocationId }); +export async function showCounselingOffices(dutyLocationId, serviceMemberId) { + return makeGHCRequestRaw('transportationOffice.showCounselingOffices', { dutyLocationId, serviceMemberId }); } export const reviewShipmentAddressUpdate = async ({ shipmentID, ifMatchETag, body }) => { diff --git a/swagger-def/ghc.yaml b/swagger-def/ghc.yaml index ce83f5c37dd..4cee2b29b33 100644 --- a/swagger-def/ghc.yaml +++ b/swagger-def/ghc.yaml @@ -4124,7 +4124,7 @@ paths: $ref: '#/responses/NotFound' '500': $ref: '#/responses/ServerError' - /transportation_offices/{dutyLocationId}/counseling_offices: + /transportation_offices/{dutyLocationId}/counseling_offices/{serviceMemberId}: get: summary: Returns the counseling locations in the GBLOC matching the duty location description: Returns the counseling locations matching the GBLOC from the selected duty location @@ -4138,6 +4138,12 @@ paths: type: string required: true description: UUID of the duty location + - in: path + name: serviceMemberId + format: uuid + type: string + required: true + description: UUID of the service member, some counseling offices are branch specific produces: - application/json responses: @@ -4145,6 +4151,12 @@ paths: description: Successfully retrieved counseling offices schema: $ref: '#/definitions/CounselingOffices' + '400': + $ref: '#/responses/InvalidRequest' + '403': + $ref: '#/responses/PermissionDenied' + '404': + $ref: '#/responses/NotFound' '500': description: internal server error /uploads: diff --git a/swagger/ghc.yaml b/swagger/ghc.yaml index 4d6b137b868..9b53612328b 100644 --- a/swagger/ghc.yaml +++ b/swagger/ghc.yaml @@ -4332,7 +4332,7 @@ paths: $ref: '#/responses/NotFound' '500': $ref: '#/responses/ServerError' - /transportation_offices/{dutyLocationId}/counseling_offices: + /transportation_offices/{dutyLocationId}/counseling_offices/{serviceMemberId}: get: summary: Returns the counseling locations in the GBLOC matching the duty location description: >- @@ -4348,6 +4348,14 @@ paths: type: string required: true description: UUID of the duty location + - in: path + name: serviceMemberId + format: uuid + type: string + required: true + description: >- + UUID of the service member, some counseling offices are branch + specific produces: - application/json responses: @@ -4355,6 +4363,12 @@ paths: description: Successfully retrieved counseling offices schema: $ref: '#/definitions/CounselingOffices' + '400': + $ref: '#/responses/InvalidRequest' + '403': + $ref: '#/responses/PermissionDenied' + '404': + $ref: '#/responses/NotFound' '500': description: internal server error /uploads: From a47a09671674164944a6e597239c4a194f01841a Mon Sep 17 00:00:00 2001 From: Alex Lusk Date: Mon, 27 Jan 2025 18:52:21 +0000 Subject: [PATCH 18/20] slightly expand tests for counseling offices handlers --- pkg/handlers/ghcapi/transportation_offices_test.go | 3 ++- pkg/handlers/internalapi/transportation_offices_test.go | 9 +++++++++ 2 files changed, 11 insertions(+), 1 deletion(-) diff --git a/pkg/handlers/ghcapi/transportation_offices_test.go b/pkg/handlers/ghcapi/transportation_offices_test.go index 087c5c2d243..deef04cac31 100644 --- a/pkg/handlers/ghcapi/transportation_offices_test.go +++ b/pkg/handlers/ghcapi/transportation_offices_test.go @@ -151,6 +151,7 @@ func (suite *HandlerSuite) TestGetTransportationOfficesGBLOCsHandler() { func (suite *HandlerSuite) TestShowCounselingOfficesHandler() { user := factory.BuildDefaultUser(suite.DB()) + serviceMember := factory.BuildServiceMember(suite.DB(), nil, nil) fetcher := transportationofficeservice.NewTransportationOfficesFetcher() @@ -182,7 +183,7 @@ func (suite *HandlerSuite) TestShowCounselingOfficesHandler() { }, nil) suite.MustSave(&origDutyLocation) - path := fmt.Sprintf("/transportation_offices/%v/counseling_offices", origDutyLocation.ID.String()) + path := fmt.Sprintf("/transportation_offices/%v/counseling_offices/%v", origDutyLocation.ID.String(), serviceMember.ID.String()) req := httptest.NewRequest("GET", path, nil) req = suite.AuthenticateUserRequest(req, user) params := transportationofficeop.ShowCounselingOfficesParams{ diff --git a/pkg/handlers/internalapi/transportation_offices_test.go b/pkg/handlers/internalapi/transportation_offices_test.go index b41c5aff7bf..ec7bf6ff858 100644 --- a/pkg/handlers/internalapi/transportation_offices_test.go +++ b/pkg/handlers/internalapi/transportation_offices_test.go @@ -174,4 +174,13 @@ func (suite *HandlerSuite) TestShowCounselingOfficesHandler() { // Validate outgoing payload suite.NoError(responsePayload.Payload.Validate(strfmt.Default)) + // Validate outgoing payload + suite.NoError(responsePayload.Payload.Validate(strfmt.Default)) + var i int + for index, office := range responsePayload.Payload { + if *office.Name == "New PPPO Travis AFB - USAF" { + i = index + } + } + suite.NotNil(i) } From 8255fdbce8d0595900d645bf3128ecd12320b6e8 Mon Sep 17 00:00:00 2001 From: Alex Lusk Date: Tue, 28 Jan 2025 10:37:59 -0500 Subject: [PATCH 19/20] add path and params to clients tests for AddOrdersForm which now uses useParams --- .../Office/AddOrdersForm/AddOrdersForm.test.jsx | 14 +++++++++----- .../ServicesCounselingAddOrders.test.jsx | 6 +++++- 2 files changed, 14 insertions(+), 6 deletions(-) diff --git a/src/components/Office/AddOrdersForm/AddOrdersForm.test.jsx b/src/components/Office/AddOrdersForm/AddOrdersForm.test.jsx index 639d617de43..9110d400626 100644 --- a/src/components/Office/AddOrdersForm/AddOrdersForm.test.jsx +++ b/src/components/Office/AddOrdersForm/AddOrdersForm.test.jsx @@ -5,10 +5,12 @@ import { Provider } from 'react-redux'; import AddOrdersForm from './AddOrdersForm'; +import { MockProviders } from 'testUtils'; import { dropdownInputOptions } from 'utils/formatters'; import { ORDERS_TYPE, ORDERS_TYPE_OPTIONS } from 'constants/orders'; import { configureStore } from 'shared/store'; import { isBooleanFlagEnabled } from 'utils/featureFlags'; +import { servicesCounselingRoutes } from 'constants/routes'; jest.setTimeout(60000); @@ -138,6 +140,8 @@ const testProps = { onSubmit: jest.fn(), onBack: jest.fn(), }; +const mockParams = { customerId: 'ea51dab0-4553-4732-b843-1f33407f77bd' }; +const mockPath = servicesCounselingRoutes.BASE_CUSTOMERS_ORDERS_ADD_PATH; describe('CreateMoveCustomerInfo Component', () => { it('renders the form inputs', async () => { @@ -226,7 +230,7 @@ describe('AddOrdersForm - OCONUS and Accompanied Tour Test', () => { it('submits the form with OCONUS values and accompanied tour selection', async () => { isBooleanFlagEnabled.mockImplementation(() => Promise.resolve(true)); render( - + , ); @@ -429,9 +433,9 @@ describe('AddOrdersForm - With Counseling Office', () => { it('displays the counseling office dropdown', async () => { isBooleanFlagEnabled.mockImplementation(() => Promise.resolve(true)); render( - + - , + , ); await userEvent.selectOptions(await screen.findByLabelText(/Orders type/), 'PERMANENT_CHANGE_OF_STATION'); @@ -462,9 +466,9 @@ describe('AddOrdersForm - With Counseling Office', () => { it('disabled submit if counseling office is required and blank', async () => { isBooleanFlagEnabled.mockImplementation(() => Promise.resolve(true)); render( - + - , + , ); await userEvent.selectOptions(await screen.findByLabelText(/Orders type/), 'PERMANENT_CHANGE_OF_STATION'); diff --git a/src/pages/Office/ServicesCounselingAddOrders/ServicesCounselingAddOrders.test.jsx b/src/pages/Office/ServicesCounselingAddOrders/ServicesCounselingAddOrders.test.jsx index 8d2cc7a2fb8..972b01d05ce 100644 --- a/src/pages/Office/ServicesCounselingAddOrders/ServicesCounselingAddOrders.test.jsx +++ b/src/pages/Office/ServicesCounselingAddOrders/ServicesCounselingAddOrders.test.jsx @@ -8,6 +8,7 @@ import { MockProviders } from 'testUtils'; import { counselingCreateOrder } from 'services/ghcApi'; import { setCanAddOrders } from 'store/general/actions'; import { isBooleanFlagEnabled } from 'utils/featureFlags'; +import { servicesCounselingRoutes } from 'constants/routes'; const mockNavigate = jest.fn(); jest.mock('react-router-dom', () => ({ @@ -331,10 +332,13 @@ const fakeResponse = { }, }; +const mockParams = { customerId: 'ea51dab0-4553-4732-b843-1f33407f77bd' }; +const mockPath = servicesCounselingRoutes.BASE_CUSTOMERS_ORDERS_ADD_PATH; + const renderWithMocks = () => { const testProps = { customer, setCanAddOrders: jest.fn() }; render( - + , ); From e4fc97c0288d658b1f3e96b4b6ca26b87e967380 Mon Sep 17 00:00:00 2001 From: Alex Lusk Date: Tue, 4 Feb 2025 15:31:10 +0000 Subject: [PATCH 20/20] test fix due to weird merge --- .../transportation_office_fetcher_test.go | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/pkg/services/transportation_office/transportation_office_fetcher_test.go b/pkg/services/transportation_office/transportation_office_fetcher_test.go index 7514868e12a..9c91710989c 100644 --- a/pkg/services/transportation_office/transportation_office_fetcher_test.go +++ b/pkg/services/transportation_office/transportation_office_fetcher_test.go @@ -343,7 +343,7 @@ func (suite *TransportationOfficeServiceSuite) Test_Oconus_AK_FindCounselingOffi return rateArea, oconusRateArea, *usprc, found_duty_location } - suite.Run("success - findOconusGblocDepartmentIndicator - returns default GLOC for departmentAffiliation if no specific departmentAffilation mapping is defined", func() { + suite.Run("success - findOconusGblocDepartmentIndicator - returns default GBLOC for departmentAffiliation if no specific departmentAffilation mapping is defined", func() { contract, err := createContract(suite.AppContextForTest(), testContractCode, testContractName) suite.NotNil(contract) suite.FatalNoError(err) @@ -377,7 +377,7 @@ func (suite *TransportationOfficeServiceSuite) Test_Oconus_AK_FindCounselingOffi ServiceMemberID: serviceMember.ID, }) suite.Nil(err) - departmentIndictor, err := findOconusGblocDepartmentIndicator(appCtx, dutylocation, uuid.Nil) + departmentIndictor, err := findOconusGblocDepartmentIndicator(appCtx, dutylocation, serviceMember.ID) suite.NotNil(departmentIndictor) suite.Nil(err) suite.Nil(departmentIndictor.DepartmentIndicator) @@ -638,7 +638,7 @@ func (suite *TransportationOfficeServiceSuite) Test_Oconus_AK_FindCounselingOffi appCtx := suite.AppContextWithSessionForTest(&auth.Session{ ServiceMemberID: serviceMember.ID, }) - offices, err := findCounselingOffice(appCtx, dutylocation.ID, uuid.Nil) + offices, err := findCounselingOffice(appCtx, dutylocation.ID, serviceMember.ID) suite.NotNil(offices) suite.Nil(err) suite.Equal(1, len(offices))