diff --git a/pkg/gen/ghcapi/embedded_spec.go b/pkg/gen/ghcapi/embedded_spec.go index ce035d0a324..c6b8f881384 100644 --- a/pkg/gen/ghcapi/embedded_spec.go +++ b/pkg/gen/ghcapi/embedded_spec.go @@ -6059,12 +6059,15 @@ func init() { "AvailableOfficeUser": { "type": "object", "properties": { - "fullName": { + "firstName": { "type": "string" }, "hasSafetyPrivilege": { "type": "boolean" }, + "lastName": { + "type": "string" + }, "officeUserId": { "type": "string", "format": "uuid", @@ -21033,12 +21036,15 @@ func init() { "AvailableOfficeUser": { "type": "object", "properties": { - "fullName": { + "firstName": { "type": "string" }, "hasSafetyPrivilege": { "type": "boolean" }, + "lastName": { + "type": "string" + }, "officeUserId": { "type": "string", "format": "uuid", diff --git a/pkg/gen/ghcmessages/available_office_user.go b/pkg/gen/ghcmessages/available_office_user.go index 6a1e3c1bdea..98f0ce1804f 100644 --- a/pkg/gen/ghcmessages/available_office_user.go +++ b/pkg/gen/ghcmessages/available_office_user.go @@ -19,12 +19,15 @@ import ( // swagger:model AvailableOfficeUser type AvailableOfficeUser struct { - // full name - FullName string `json:"fullName,omitempty"` + // first name + FirstName string `json:"firstName,omitempty"` // has safety privilege HasSafetyPrivilege bool `json:"hasSafetyPrivilege,omitempty"` + // last name + LastName string `json:"lastName,omitempty"` + // office user Id // Example: c56a4180-65aa-42ec-a945-5fd21dec0538 // Format: uuid diff --git a/pkg/handlers/ghcapi/api.go b/pkg/handlers/ghcapi/api.go index ec5006c783a..1b6d7efed25 100644 --- a/pkg/handlers/ghcapi/api.go +++ b/pkg/handlers/ghcapi/api.go @@ -514,7 +514,6 @@ func NewGhcAPIHandler(handlerConfig handlers.HandlerConfig) *ghcops.MymoveAPI { order.NewOrderFetcher(), movelocker.NewMoveUnlocker(), officeusercreator.NewOfficeUserFetcherPop(), - officeusercreator.NewOfficeUserGblocFetcher(), } ghcAPI.QueuesListPrimeMovesHandler = ListPrimeMovesHandler{ @@ -527,7 +526,6 @@ func NewGhcAPIHandler(handlerConfig handlers.HandlerConfig) *ghcops.MymoveAPI { paymentrequest.NewPaymentRequestListFetcher(), movelocker.NewMoveUnlocker(), officeusercreator.NewOfficeUserFetcherPop(), - officeusercreator.NewOfficeUserGblocFetcher(), } ghcAPI.QueuesGetServicesCounselingQueueHandler = GetServicesCounselingQueueHandler{ @@ -535,7 +533,6 @@ func NewGhcAPIHandler(handlerConfig handlers.HandlerConfig) *ghcops.MymoveAPI { order.NewOrderFetcher(), movelocker.NewMoveUnlocker(), officeusercreator.NewOfficeUserFetcherPop(), - officeusercreator.NewOfficeUserGblocFetcher(), } ghcAPI.QueuesGetServicesCounselingOriginListHandler = GetServicesCounselingOriginListHandler{ diff --git a/pkg/handlers/ghcapi/internal/payloads/model_to_payload.go b/pkg/handlers/ghcapi/internal/payloads/model_to_payload.go index 5a5cbc393c4..31d5141b754 100644 --- a/pkg/handlers/ghcapi/internal/payloads/model_to_payload.go +++ b/pkg/handlers/ghcapi/internal/payloads/model_to_payload.go @@ -1883,7 +1883,8 @@ func QueueAvailableOfficeUsers(officeUsers []models.OfficeUser) *ghcmessages.Ava hasSafety := officeUser.User.Privileges.HasPrivilege(models.PrivilegeTypeSafety) availableOfficeUsers[i] = &ghcmessages.AvailableOfficeUser{ - FullName: officeUser.LastName + ", " + officeUser.FirstName, + LastName: officeUser.LastName, + FirstName: officeUser.FirstName, OfficeUserID: *handlers.FmtUUID(officeUser.ID), HasSafetyPrivilege: swag.BoolValue(&hasSafety), } diff --git a/pkg/handlers/ghcapi/queues.go b/pkg/handlers/ghcapi/queues.go index 7ec14e6f42f..f994b55a4eb 100644 --- a/pkg/handlers/ghcapi/queues.go +++ b/pkg/handlers/ghcapi/queues.go @@ -6,6 +6,7 @@ import ( "github.com/go-openapi/runtime/middleware" "github.com/gobuffalo/pop/v6" + "github.com/gofrs/uuid" "go.uber.org/zap" "github.com/transcom/mymove/pkg/appcontext" @@ -17,7 +18,6 @@ import ( "github.com/transcom/mymove/pkg/models" "github.com/transcom/mymove/pkg/models/roles" "github.com/transcom/mymove/pkg/services" - officeuser "github.com/transcom/mymove/pkg/services/office_user" ) // GetMovesQueueHandler returns the moves for the TOO queue user via GET /queues/moves @@ -26,7 +26,6 @@ type GetMovesQueueHandler struct { services.OrderFetcher services.MoveUnlocker services.OfficeUserFetcherPop - services.OfficeUserGblocFetcher } // FilterOption defines the type for the functional arguments used for private functions in OrderFetcher @@ -92,17 +91,19 @@ func (h GetMovesQueueHandler) Handle(params queues.GetMovesQueueParams) middlewa return queues.NewGetMovesQueueInternalServerError(), err } - var gblocErr error - gblocFetcher := officeuser.NewOfficeUserGblocFetcher() - officeUserGbloc, gblocErr := gblocFetcher.FetchGblocForOfficeUser(appCtx, appCtx.Session().OfficeUserID) - if gblocErr != nil { - return queues.NewGetMovesQueueInternalServerError(), gblocErr + var officeUser models.OfficeUser + if appCtx.Session().OfficeUserID != uuid.Nil { + officeUser, err = h.OfficeUserFetcherPop.FetchOfficeUserByID(appCtx, appCtx.Session().OfficeUserID) + if err != nil { + appCtx.Logger().Error("Error retrieving office_user", zap.Error(err)) + return queues.NewGetServicesCounselingQueueInternalServerError(), err + } } - officeUsers, err := h.OfficeUserFetcherPop.FetchOfficeUserByRoleAndGbloc( + officeUsers, err := h.OfficeUserFetcherPop.FetchOfficeUsersByRoleAndOffice( appCtx, roles.RoleTypeTOO, - officeUserGbloc, + officeUser.TransportationOfficeID, ) if err != nil { @@ -204,7 +205,6 @@ type GetPaymentRequestsQueueHandler struct { services.PaymentRequestListFetcher services.MoveUnlocker services.OfficeUserFetcherPop - services.OfficeUserGblocFetcher } // Handle returns the paginated list of payment requests for the TIO user @@ -266,17 +266,19 @@ func (h GetPaymentRequestsQueueHandler) Handle( return queues.NewGetPaymentRequestsQueueInternalServerError(), err } - var gblocErr error - gblocFetcher := officeuser.NewOfficeUserGblocFetcher() - officeUserGbloc, gblocErr := gblocFetcher.FetchGblocForOfficeUser(appCtx, appCtx.Session().OfficeUserID) - if gblocErr != nil { - return queues.NewGetPaymentRequestsQueueInternalServerError(), gblocErr + var officeUser models.OfficeUser + if appCtx.Session().OfficeUserID != uuid.Nil { + officeUser, err = h.OfficeUserFetcherPop.FetchOfficeUserByID(appCtx, appCtx.Session().OfficeUserID) + if err != nil { + appCtx.Logger().Error("Error retrieving office_user", zap.Error(err)) + return queues.NewGetServicesCounselingQueueInternalServerError(), err + } } - officeUsers, err := h.OfficeUserFetcherPop.FetchOfficeUserByRoleAndGbloc( + officeUsers, err := h.OfficeUserFetcherPop.FetchOfficeUsersByRoleAndOffice( appCtx, roles.RoleTypeTIO, - officeUserGbloc, + officeUser.TransportationOfficeID, ) if err != nil { @@ -327,7 +329,6 @@ type GetServicesCounselingQueueHandler struct { services.OrderFetcher services.MoveUnlocker services.OfficeUserFetcherPop - services.OfficeUserGblocFetcher } // Handle returns the paginated list of moves for the services counselor @@ -401,17 +402,19 @@ func (h GetServicesCounselingQueueHandler) Handle( return queues.NewGetServicesCounselingQueueInternalServerError(), err } - var gblocErr error - gblocFetcher := officeuser.NewOfficeUserGblocFetcher() - officeUserGbloc, gblocErr := gblocFetcher.FetchGblocForOfficeUser(appCtx, appCtx.Session().OfficeUserID) - if gblocErr != nil { - return queues.NewGetServicesCounselingQueueInternalServerError(), gblocErr + var officeUser models.OfficeUser + if appCtx.Session().OfficeUserID != uuid.Nil { + officeUser, err = h.OfficeUserFetcherPop.FetchOfficeUserByID(appCtx, appCtx.Session().OfficeUserID) + if err != nil { + appCtx.Logger().Error("Error retrieving office_user", zap.Error(err)) + return queues.NewGetServicesCounselingQueueInternalServerError(), err + } } - officeUsers, err := h.OfficeUserFetcherPop.FetchOfficeUserByRoleAndGbloc( + officeUsers, err := h.OfficeUserFetcherPop.FetchOfficeUsersByRoleAndOffice( appCtx, roles.RoleTypeServicesCounselor, - officeUserGbloc, + officeUser.TransportationOfficeID, ) if err != nil { diff --git a/pkg/handlers/ghcapi/queues_test.go b/pkg/handlers/ghcapi/queues_test.go index 171ce22ee88..f1efe5028fe 100644 --- a/pkg/handlers/ghcapi/queues_test.go +++ b/pkg/handlers/ghcapi/queues_test.go @@ -79,7 +79,6 @@ func (suite *HandlerSuite) TestGetMoveQueuesHandler() { order.NewOrderFetcher(), mockUnlocker, officeusercreator.NewOfficeUserFetcherPop(), - officeusercreator.NewOfficeUserGblocFetcher(), } // Validate incoming payload: no body to validate @@ -208,7 +207,6 @@ func (suite *HandlerSuite) TestGetMoveQueuesHandlerMoveInfo() { &orderFetcher, mockUnlocker, officeusercreator.NewOfficeUserFetcherPop(), - officeusercreator.NewOfficeUserGblocFetcher(), } // Validate incoming payload: no body to validate @@ -283,7 +281,6 @@ func (suite *HandlerSuite) TestGetMoveQueuesBranchFilter() { order.NewOrderFetcher(), mockUnlocker, officeusercreator.NewOfficeUserFetcherPop(), - officeusercreator.NewOfficeUserGblocFetcher(), } // Validate incoming payload: no body to validate @@ -372,7 +369,6 @@ func (suite *HandlerSuite) TestGetMoveQueuesHandlerStatuses() { order.NewOrderFetcher(), mockUnlocker, officeusercreator.NewOfficeUserFetcherPop(), - officeusercreator.NewOfficeUserGblocFetcher(), } // Validate incoming payload: no body to validate @@ -522,7 +518,6 @@ func (suite *HandlerSuite) TestGetMoveQueuesHandlerFilters() { order.NewOrderFetcher(), mockUnlocker, officeusercreator.NewOfficeUserFetcherPop(), - officeusercreator.NewOfficeUserGblocFetcher(), } suite.Run("loads results with all STATUSes selected", func() { @@ -780,7 +775,6 @@ func (suite *HandlerSuite) TestGetMoveQueuesHandlerCustomerInfoFilters() { order.NewOrderFetcher(), mockUnlocker, officeusercreator.NewOfficeUserFetcherPop(), - officeusercreator.NewOfficeUserGblocFetcher(), } suite.Run("returns unfiltered results", func() { @@ -927,7 +921,6 @@ func (suite *HandlerSuite) TestGetMoveQueuesHandlerUnauthorizedRole() { order.NewOrderFetcher(), mockUnlocker, officeusercreator.NewOfficeUserFetcherPop(), - officeusercreator.NewOfficeUserGblocFetcher(), } // Validate incoming payload: no body to validate @@ -959,7 +952,6 @@ func (suite *HandlerSuite) TestGetMoveQueuesHandlerUnauthorizedUser() { order.NewOrderFetcher(), mockUnlocker, officeusercreator.NewOfficeUserFetcherPop(), - officeusercreator.NewOfficeUserGblocFetcher(), } // Validate incoming payload: no body to validate @@ -1012,7 +1004,6 @@ func (suite *HandlerSuite) TestGetMoveQueuesHandlerEmptyResults() { order.NewOrderFetcher(), mockUnlocker, officeusercreator.NewOfficeUserFetcherPop(), - officeusercreator.NewOfficeUserGblocFetcher(), } // Validate incoming payload: no body to validate @@ -1063,7 +1054,6 @@ func (suite *HandlerSuite) TestGetPaymentRequestsQueueHandler() { paymentrequest.NewPaymentRequestListFetcher(), mockUnlocker, officeusercreator.NewOfficeUserFetcherPop(), - officeusercreator.NewOfficeUserGblocFetcher(), } // Validate incoming payload: no body to validate @@ -1142,7 +1132,6 @@ func (suite *HandlerSuite) TestGetPaymentRequestsQueueSubmittedAtFilter() { paymentrequest.NewPaymentRequestListFetcher(), mockUnlocker, officeusercreator.NewOfficeUserFetcherPop(), - officeusercreator.NewOfficeUserGblocFetcher(), } suite.Run("returns unfiltered results", func() { params := queues.GetPaymentRequestsQueueParams{ @@ -1223,7 +1212,6 @@ func (suite *HandlerSuite) TestGetPaymentRequestsQueueHandlerUnauthorizedRole() paymentrequest.NewPaymentRequestListFetcher(), mockUnlocker, officeusercreator.NewOfficeUserFetcherPop(), - officeusercreator.NewOfficeUserGblocFetcher(), } // Validate incoming payload: no body to validate @@ -1260,7 +1248,6 @@ func (suite *HandlerSuite) TestGetPaymentRequestsQueueHandlerServerError() { &paymentRequestListFetcher, mockUnlocker, officeusercreator.NewOfficeUserFetcherPop(), - officeusercreator.NewOfficeUserGblocFetcher(), } // Validate incoming payload: no body to validate @@ -1298,7 +1285,6 @@ func (suite *HandlerSuite) TestGetPaymentRequestsQueueHandlerEmptyResults() { &paymentRequestListFetcher, mockUnlocker, officeusercreator.NewOfficeUserFetcherPop(), - officeusercreator.NewOfficeUserGblocFetcher(), } // Validate incoming payload: no body to validate @@ -1505,7 +1491,6 @@ func (suite *HandlerSuite) makeServicesCounselingSubtestData() (subtestData *ser order.NewOrderFetcher(), mockUnlocker, officeusercreator.NewOfficeUserFetcherPop(), - officeusercreator.NewOfficeUserGblocFetcher(), } return subtestData diff --git a/pkg/services/mocks/OfficeUserFetcherPop.go b/pkg/services/mocks/OfficeUserFetcherPop.go index 6754bc999c6..3b167d49ef0 100644 --- a/pkg/services/mocks/OfficeUserFetcherPop.go +++ b/pkg/services/mocks/OfficeUserFetcherPop.go @@ -42,25 +42,25 @@ func (_m *OfficeUserFetcherPop) FetchOfficeUserByID(appCtx appcontext.AppContext return r0, r1 } -// FetchOfficeUserByRoleAndGbloc provides a mock function with given fields: appCtx, role, gbloc -func (_m *OfficeUserFetcherPop) FetchOfficeUserByRoleAndGbloc(appCtx appcontext.AppContext, role roles.RoleType, gbloc string) ([]models.OfficeUser, error) { - ret := _m.Called(appCtx, role, gbloc) +// FetchOfficeUsersByRoleAndOffice provides a mock function with given fields: appCtx, role, officeID +func (_m *OfficeUserFetcherPop) FetchOfficeUsersByRoleAndOffice(appCtx appcontext.AppContext, role roles.RoleType, officeID uuid.UUID) ([]models.OfficeUser, error) { + ret := _m.Called(appCtx, role, officeID) var r0 []models.OfficeUser var r1 error - if rf, ok := ret.Get(0).(func(appcontext.AppContext, roles.RoleType, string) ([]models.OfficeUser, error)); ok { - return rf(appCtx, role, gbloc) + if rf, ok := ret.Get(0).(func(appcontext.AppContext, roles.RoleType, uuid.UUID) ([]models.OfficeUser, error)); ok { + return rf(appCtx, role, officeID) } - if rf, ok := ret.Get(0).(func(appcontext.AppContext, roles.RoleType, string) []models.OfficeUser); ok { - r0 = rf(appCtx, role, gbloc) + if rf, ok := ret.Get(0).(func(appcontext.AppContext, roles.RoleType, uuid.UUID) []models.OfficeUser); ok { + r0 = rf(appCtx, role, officeID) } else { if ret.Get(0) != nil { r0 = ret.Get(0).([]models.OfficeUser) } } - if rf, ok := ret.Get(1).(func(appcontext.AppContext, roles.RoleType, string) error); ok { - r1 = rf(appCtx, role, gbloc) + if rf, ok := ret.Get(1).(func(appcontext.AppContext, roles.RoleType, uuid.UUID) error); ok { + r1 = rf(appCtx, role, officeID) } else { r1 = ret.Error(1) } diff --git a/pkg/services/office_user.go b/pkg/services/office_user.go index 2e18a01fc9c..9e7a17d6bbe 100644 --- a/pkg/services/office_user.go +++ b/pkg/services/office_user.go @@ -22,7 +22,7 @@ type OfficeUserFetcher interface { //go:generate mockery --name OfficeUserFetcherPop type OfficeUserFetcherPop interface { FetchOfficeUserByID(appCtx appcontext.AppContext, id uuid.UUID) (models.OfficeUser, error) - FetchOfficeUserByRoleAndGbloc(appCtx appcontext.AppContext, role roles.RoleType, gbloc string) ([]models.OfficeUser, error) + FetchOfficeUsersByRoleAndOffice(appCtx appcontext.AppContext, role roles.RoleType, officeID uuid.UUID) ([]models.OfficeUser, error) } // OfficeUserGblocFetcher is the exported interface for fetching the GBLOC of the diff --git a/pkg/services/office_user/office_user_fetcher.go b/pkg/services/office_user/office_user_fetcher.go index d34e9967be4..c5722f58111 100644 --- a/pkg/services/office_user/office_user_fetcher.go +++ b/pkg/services/office_user/office_user_fetcher.go @@ -57,7 +57,7 @@ func (o *officeUserFetcherPop) FetchOfficeUserByID(appCtx appcontext.AppContext, } // Fetch office users of the same role within a gbloc, for assignment purposes -func (o *officeUserFetcherPop) FetchOfficeUserByRoleAndGbloc(appCtx appcontext.AppContext, role roles.RoleType, gbloc string) ([]models.OfficeUser, error) { +func (o *officeUserFetcherPop) FetchOfficeUsersByRoleAndOffice(appCtx appcontext.AppContext, role roles.RoleType, officeID uuid.UUID) ([]models.OfficeUser, error) { var officeUsers []models.OfficeUser err := appCtx.DB().EagerPreload( @@ -70,9 +70,9 @@ func (o *officeUserFetcherPop) FetchOfficeUserByRoleAndGbloc(appCtx appcontext.A Join("users", "users.id = office_users.user_id"). Join("users_roles", "users.id = users_roles.user_id"). Join("roles", "users_roles.role_id = roles.id"). - Join("transportation_offices", "office_users.transportation_office_id = transportation_offices.id"). - Where("gbloc = ?", gbloc). + Where("transportation_office_id = ?", officeID). Where("role_type = ?", role). + Where("users_roles.deleted_at IS NULL"). Where("office_users.active = TRUE"). Order("last_name asc"). All(&officeUsers) diff --git a/pkg/services/office_user/office_user_fetcher_test.go b/pkg/services/office_user/office_user_fetcher_test.go index ef8228a0b5f..5ce6c1aeda4 100644 --- a/pkg/services/office_user/office_user_fetcher_test.go +++ b/pkg/services/office_user/office_user_fetcher_test.go @@ -94,22 +94,23 @@ func (suite *OfficeUserServiceSuite) TestFetchOfficeUserPop() { suite.Equal(officeUser.ID, fetchedUser.ID) }) - suite.Run("returns a set of office users when given a gbloc and role", func() { - // build 2 TOOs - factory.BuildOfficeUserWithRoles(suite.DB(), factory.GetTraitActiveOfficeUser(), []roles.RoleType{roles.RoleTypeTOO}) - factory.BuildOfficeUserWithRoles(suite.DB(), factory.GetTraitActiveOfficeUser(), []roles.RoleType{roles.RoleTypeTOO}) - // build 1 SC an 3 TIOs + suite.Run("returns a set of office users when given a and role", func() { + // build 1 TOO + officeUser := factory.BuildOfficeUserWithRoles(suite.DB(), factory.GetTraitActiveOfficeUser(), []roles.RoleType{roles.RoleTypeTOO}) + // build 2 SCs and 3 TIOs + factory.BuildOfficeUserWithRoles(suite.DB(), factory.GetTraitActiveOfficeUser(), []roles.RoleType{roles.RoleTypeServicesCounselor}) factory.BuildOfficeUserWithRoles(suite.DB(), factory.GetTraitActiveOfficeUser(), []roles.RoleType{roles.RoleTypeServicesCounselor}) factory.BuildOfficeUserWithRoles(suite.DB(), factory.GetTraitActiveOfficeUser(), []roles.RoleType{roles.RoleTypeTIO}) factory.BuildOfficeUserWithRoles(suite.DB(), factory.GetTraitActiveOfficeUser(), []roles.RoleType{roles.RoleTypeTIO}) factory.BuildOfficeUserWithRoles(suite.DB(), factory.GetTraitActiveOfficeUser(), []roles.RoleType{roles.RoleTypeTIO}) fetcher := NewOfficeUserFetcherPop() - fetchedUsers, err := fetcher.FetchOfficeUserByRoleAndGbloc(suite.AppContextForTest(), roles.RoleTypeTOO, "KKFA") + fetchedUsers, err := fetcher.FetchOfficeUsersByRoleAndOffice(suite.AppContextForTest(), roles.RoleTypeTOO, officeUser.TransportationOfficeID) - // ensure length of returned set is 2, corresponding to the TOO role passed to FetchOfficeUserByRoleAndGbloc + // ensure length of returned set is 1, corresponding to the TOO role passed to FetchOfficeUsersByRoleAndOffice + // and not 2 (SC) or 3 (TIO) suite.NoError(err) - suite.Len(fetchedUsers, 2) + suite.Len(fetchedUsers, 1) }) suite.Run("returns zero value office user on error", func() { diff --git a/swagger-def/ghc.yaml b/swagger-def/ghc.yaml index 951f2de93e1..16197a0da97 100644 --- a/swagger-def/ghc.yaml +++ b/swagger-def/ghc.yaml @@ -6338,7 +6338,9 @@ definitions: type: string format: uuid example: c56a4180-65aa-42ec-a945-5fd21dec0538 - fullName: + lastName: + type: string + firstName: type: string hasSafetyPrivilege: type: boolean diff --git a/swagger/ghc.yaml b/swagger/ghc.yaml index e736520de3e..74d64181341 100644 --- a/swagger/ghc.yaml +++ b/swagger/ghc.yaml @@ -6611,7 +6611,9 @@ definitions: type: string format: uuid example: c56a4180-65aa-42ec-a945-5fd21dec0538 - fullName: + lastName: + type: string + firstName: type: string hasSafetyPrivilege: type: boolean