From d308a38c80a52b9e83e80a583a47b5e24e8a82eb Mon Sep 17 00:00:00 2001 From: Alex Lusk Date: Fri, 20 Dec 2024 15:43:41 +0000 Subject: [PATCH 1/4] 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 6a767151b3bb4b09802b7b3c19fc4286319e537e Mon Sep 17 00:00:00 2001 From: Alex Lusk Date: Tue, 7 Jan 2025 23:12:21 +0000 Subject: [PATCH 2/4] 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 3/4] 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: Fri, 10 Jan 2025 22:53:33 +0000 Subject: [PATCH 4/4] 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']);