From ba3cfeef2b944780501fa581e19d42f713045b3b Mon Sep 17 00:00:00 2001 From: KonstanceH Date: Fri, 24 Jan 2025 15:41:10 +0000 Subject: [PATCH 01/37] added cols to table/swagger and generated files. --- migrations/app/migrations_manifest.txt | 1 + ..._deleted_cols_to_admin_office_users.up.sql | 8 + .../adminapi/adminoperations/mymove_api.go | 25 ++ .../get_rejected_office_user.go | 58 ++++ .../get_rejected_office_user_parameters.go | 91 +++++++ .../get_rejected_office_user_responses.go | 159 +++++++++++ .../get_rejected_office_user_urlbuilder.go | 101 +++++++ .../index_rejected_office_users.go | 59 +++++ .../index_rejected_office_users_parameters.go | 201 ++++++++++++++ .../index_rejected_office_users_responses.go | 184 +++++++++++++ .../index_rejected_office_users_urlbuilder.go | 141 ++++++++++ pkg/gen/adminapi/configure_mymove.go | 11 + pkg/gen/adminapi/embedded_spec.go | 250 ++++++++++++++++++ pkg/gen/adminmessages/office_user.go | 68 +++++ pkg/models/office_user.go | 2 + swagger-def/admin.yaml | 83 ++++++ swagger/admin.yaml | 89 +++++++ 17 files changed, 1531 insertions(+) create mode 100644 migrations/app/schema/20250124140959_add_rejected_and_deleted_cols_to_admin_office_users.up.sql create mode 100644 pkg/gen/adminapi/adminoperations/rejected_office_users/get_rejected_office_user.go create mode 100644 pkg/gen/adminapi/adminoperations/rejected_office_users/get_rejected_office_user_parameters.go create mode 100644 pkg/gen/adminapi/adminoperations/rejected_office_users/get_rejected_office_user_responses.go create mode 100644 pkg/gen/adminapi/adminoperations/rejected_office_users/get_rejected_office_user_urlbuilder.go create mode 100644 pkg/gen/adminapi/adminoperations/rejected_office_users/index_rejected_office_users.go create mode 100644 pkg/gen/adminapi/adminoperations/rejected_office_users/index_rejected_office_users_parameters.go create mode 100644 pkg/gen/adminapi/adminoperations/rejected_office_users/index_rejected_office_users_responses.go create mode 100644 pkg/gen/adminapi/adminoperations/rejected_office_users/index_rejected_office_users_urlbuilder.go diff --git a/migrations/app/migrations_manifest.txt b/migrations/app/migrations_manifest.txt index 564ae241e40..cc76b6bfbff 100644 --- a/migrations/app/migrations_manifest.txt +++ b/migrations/app/migrations_manifest.txt @@ -1073,3 +1073,4 @@ 20250110153428_add_shipment_address_updates_to_move_history.up.sql 20250110214012_homesafeconnect_cert.up.sql 20250116200912_disable_homesafe_stg_cert.up.sql +20250124140959_add_rejected_and_deleted_cols_to_admin_office_users.up.sql diff --git a/migrations/app/schema/20250124140959_add_rejected_and_deleted_cols_to_admin_office_users.up.sql b/migrations/app/schema/20250124140959_add_rejected_and_deleted_cols_to_admin_office_users.up.sql new file mode 100644 index 00000000000..f52420e6fdb --- /dev/null +++ b/migrations/app/schema/20250124140959_add_rejected_and_deleted_cols_to_admin_office_users.up.sql @@ -0,0 +1,8 @@ +-- Adds new columns to office_users table +ALTER TABLE public.office_users +ADD COLUMN IF NOT EXISTS rejected_on timestamptz, +ADD COLUMN IF NOT EXISTS deleted_on timestamptz; + +-- Comments on new columns +COMMENT on COLUMN office_users.rejected_on IS 'Date requested office users were rejected.'; +COMMENT on COLUMN office_users.deleted_on IS 'Date office users were deleted.'; diff --git a/pkg/gen/adminapi/adminoperations/mymove_api.go b/pkg/gen/adminapi/adminoperations/mymove_api.go index e2ed2892e29..62eb894bda6 100644 --- a/pkg/gen/adminapi/adminoperations/mymove_api.go +++ b/pkg/gen/adminapi/adminoperations/mymove_api.go @@ -28,6 +28,7 @@ import ( "github.com/transcom/mymove/pkg/gen/adminapi/adminoperations/organizations" "github.com/transcom/mymove/pkg/gen/adminapi/adminoperations/payment_request_syncada_file" "github.com/transcom/mymove/pkg/gen/adminapi/adminoperations/payment_request_syncada_files" + "github.com/transcom/mymove/pkg/gen/adminapi/adminoperations/rejected_office_users" "github.com/transcom/mymove/pkg/gen/adminapi/adminoperations/requested_office_users" "github.com/transcom/mymove/pkg/gen/adminapi/adminoperations/transportation_offices" "github.com/transcom/mymove/pkg/gen/adminapi/adminoperations/uploads" @@ -91,6 +92,9 @@ func NewMymoveAPI(spec *loads.Document) *MymoveAPI { OfficeUsersGetOfficeUserHandler: office_users.GetOfficeUserHandlerFunc(func(params office_users.GetOfficeUserParams) middleware.Responder { return middleware.NotImplemented("operation office_users.GetOfficeUser has not yet been implemented") }), + RejectedOfficeUsersGetRejectedOfficeUserHandler: rejected_office_users.GetRejectedOfficeUserHandlerFunc(func(params rejected_office_users.GetRejectedOfficeUserParams) middleware.Responder { + return middleware.NotImplemented("operation rejected_office_users.GetRejectedOfficeUser has not yet been implemented") + }), RequestedOfficeUsersGetRequestedOfficeUserHandler: requested_office_users.GetRequestedOfficeUserHandlerFunc(func(params requested_office_users.GetRequestedOfficeUserParams) middleware.Responder { return middleware.NotImplemented("operation requested_office_users.GetRequestedOfficeUser has not yet been implemented") }), @@ -130,6 +134,9 @@ func NewMymoveAPI(spec *loads.Document) *MymoveAPI { PaymentRequestSyncadaFilesIndexPaymentRequestSyncadaFilesHandler: payment_request_syncada_files.IndexPaymentRequestSyncadaFilesHandlerFunc(func(params payment_request_syncada_files.IndexPaymentRequestSyncadaFilesParams) middleware.Responder { return middleware.NotImplemented("operation payment_request_syncada_files.IndexPaymentRequestSyncadaFiles has not yet been implemented") }), + RejectedOfficeUsersIndexRejectedOfficeUsersHandler: rejected_office_users.IndexRejectedOfficeUsersHandlerFunc(func(params rejected_office_users.IndexRejectedOfficeUsersParams) middleware.Responder { + return middleware.NotImplemented("operation rejected_office_users.IndexRejectedOfficeUsers has not yet been implemented") + }), RequestedOfficeUsersIndexRequestedOfficeUsersHandler: requested_office_users.IndexRequestedOfficeUsersHandlerFunc(func(params requested_office_users.IndexRequestedOfficeUsersParams) middleware.Responder { return middleware.NotImplemented("operation requested_office_users.IndexRequestedOfficeUsers has not yet been implemented") }), @@ -228,6 +235,8 @@ type MymoveAPI struct { TransportationOfficesGetOfficeByIDHandler transportation_offices.GetOfficeByIDHandler // OfficeUsersGetOfficeUserHandler sets the operation handler for the get office user operation OfficeUsersGetOfficeUserHandler office_users.GetOfficeUserHandler + // RejectedOfficeUsersGetRejectedOfficeUserHandler sets the operation handler for the get rejected office user operation + RejectedOfficeUsersGetRejectedOfficeUserHandler rejected_office_users.GetRejectedOfficeUserHandler // RequestedOfficeUsersGetRequestedOfficeUserHandler sets the operation handler for the get requested office user operation RequestedOfficeUsersGetRequestedOfficeUserHandler requested_office_users.GetRequestedOfficeUserHandler // UploadsGetUploadHandler sets the operation handler for the get upload operation @@ -254,6 +263,8 @@ type MymoveAPI struct { OrganizationsIndexOrganizationsHandler organizations.IndexOrganizationsHandler // PaymentRequestSyncadaFilesIndexPaymentRequestSyncadaFilesHandler sets the operation handler for the index payment request syncada files operation PaymentRequestSyncadaFilesIndexPaymentRequestSyncadaFilesHandler payment_request_syncada_files.IndexPaymentRequestSyncadaFilesHandler + // RejectedOfficeUsersIndexRejectedOfficeUsersHandler sets the operation handler for the index rejected office users operation + RejectedOfficeUsersIndexRejectedOfficeUsersHandler rejected_office_users.IndexRejectedOfficeUsersHandler // RequestedOfficeUsersIndexRequestedOfficeUsersHandler sets the operation handler for the index requested office users operation RequestedOfficeUsersIndexRequestedOfficeUsersHandler requested_office_users.IndexRequestedOfficeUsersHandler // UsersIndexUsersHandler sets the operation handler for the index users operation @@ -388,6 +399,9 @@ func (o *MymoveAPI) Validate() error { if o.OfficeUsersGetOfficeUserHandler == nil { unregistered = append(unregistered, "office_users.GetOfficeUserHandler") } + if o.RejectedOfficeUsersGetRejectedOfficeUserHandler == nil { + unregistered = append(unregistered, "rejected_office_users.GetRejectedOfficeUserHandler") + } if o.RequestedOfficeUsersGetRequestedOfficeUserHandler == nil { unregistered = append(unregistered, "requested_office_users.GetRequestedOfficeUserHandler") } @@ -427,6 +441,9 @@ func (o *MymoveAPI) Validate() error { if o.PaymentRequestSyncadaFilesIndexPaymentRequestSyncadaFilesHandler == nil { unregistered = append(unregistered, "payment_request_syncada_files.IndexPaymentRequestSyncadaFilesHandler") } + if o.RejectedOfficeUsersIndexRejectedOfficeUsersHandler == nil { + unregistered = append(unregistered, "rejected_office_users.IndexRejectedOfficeUsersHandler") + } if o.RequestedOfficeUsersIndexRequestedOfficeUsersHandler == nil { unregistered = append(unregistered, "requested_office_users.IndexRequestedOfficeUsersHandler") } @@ -598,6 +615,10 @@ func (o *MymoveAPI) initHandlerCache() { if o.handlers["GET"] == nil { o.handlers["GET"] = make(map[string]http.Handler) } + o.handlers["GET"]["/rejected-office-users/{officeUserId}"] = rejected_office_users.NewGetRejectedOfficeUser(o.context, o.RejectedOfficeUsersGetRejectedOfficeUserHandler) + if o.handlers["GET"] == nil { + o.handlers["GET"] = make(map[string]http.Handler) + } o.handlers["GET"]["/requested-office-users/{officeUserId}"] = requested_office_users.NewGetRequestedOfficeUser(o.context, o.RequestedOfficeUsersGetRequestedOfficeUserHandler) if o.handlers["GET"] == nil { o.handlers["GET"] = make(map[string]http.Handler) @@ -650,6 +671,10 @@ func (o *MymoveAPI) initHandlerCache() { if o.handlers["GET"] == nil { o.handlers["GET"] = make(map[string]http.Handler) } + o.handlers["GET"]["/rejected-office-users"] = rejected_office_users.NewIndexRejectedOfficeUsers(o.context, o.RejectedOfficeUsersIndexRejectedOfficeUsersHandler) + if o.handlers["GET"] == nil { + o.handlers["GET"] = make(map[string]http.Handler) + } o.handlers["GET"]["/requested-office-users"] = requested_office_users.NewIndexRequestedOfficeUsers(o.context, o.RequestedOfficeUsersIndexRequestedOfficeUsersHandler) if o.handlers["GET"] == nil { o.handlers["GET"] = make(map[string]http.Handler) diff --git a/pkg/gen/adminapi/adminoperations/rejected_office_users/get_rejected_office_user.go b/pkg/gen/adminapi/adminoperations/rejected_office_users/get_rejected_office_user.go new file mode 100644 index 00000000000..d7664e97399 --- /dev/null +++ b/pkg/gen/adminapi/adminoperations/rejected_office_users/get_rejected_office_user.go @@ -0,0 +1,58 @@ +// Code generated by go-swagger; DO NOT EDIT. + +package rejected_office_users + +// 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" +) + +// GetRejectedOfficeUserHandlerFunc turns a function with the right signature into a get rejected office user handler +type GetRejectedOfficeUserHandlerFunc func(GetRejectedOfficeUserParams) middleware.Responder + +// Handle executing the request and returning a response +func (fn GetRejectedOfficeUserHandlerFunc) Handle(params GetRejectedOfficeUserParams) middleware.Responder { + return fn(params) +} + +// GetRejectedOfficeUserHandler interface for that can handle valid get rejected office user params +type GetRejectedOfficeUserHandler interface { + Handle(GetRejectedOfficeUserParams) middleware.Responder +} + +// NewGetRejectedOfficeUser creates a new http.Handler for the get rejected office user operation +func NewGetRejectedOfficeUser(ctx *middleware.Context, handler GetRejectedOfficeUserHandler) *GetRejectedOfficeUser { + return &GetRejectedOfficeUser{Context: ctx, Handler: handler} +} + +/* + GetRejectedOfficeUser swagger:route GET /rejected-office-users/{officeUserId} Rejected office users getRejectedOfficeUser + +# Get a Rejected Office User + +Retrieving a single office user in any status. This endpoint is used in the Admin UI that will allow the admin user to view the user's relevant data. +*/ +type GetRejectedOfficeUser struct { + Context *middleware.Context + Handler GetRejectedOfficeUserHandler +} + +func (o *GetRejectedOfficeUser) ServeHTTP(rw http.ResponseWriter, r *http.Request) { + route, rCtx, _ := o.Context.RouteInfo(r) + if rCtx != nil { + *r = *rCtx + } + var Params = NewGetRejectedOfficeUserParams() + 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/adminapi/adminoperations/rejected_office_users/get_rejected_office_user_parameters.go b/pkg/gen/adminapi/adminoperations/rejected_office_users/get_rejected_office_user_parameters.go new file mode 100644 index 00000000000..46f91bf217a --- /dev/null +++ b/pkg/gen/adminapi/adminoperations/rejected_office_users/get_rejected_office_user_parameters.go @@ -0,0 +1,91 @@ +// Code generated by go-swagger; DO NOT EDIT. + +package rejected_office_users + +// 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" +) + +// NewGetRejectedOfficeUserParams creates a new GetRejectedOfficeUserParams object +// +// There are no default values defined in the spec. +func NewGetRejectedOfficeUserParams() GetRejectedOfficeUserParams { + + return GetRejectedOfficeUserParams{} +} + +// GetRejectedOfficeUserParams contains all the bound params for the get rejected office user operation +// typically these are obtained from a http.Request +// +// swagger:parameters getRejectedOfficeUser +type GetRejectedOfficeUserParams struct { + + // HTTP Request Object + HTTPRequest *http.Request `json:"-"` + + /* + Required: true + In: path + */ + OfficeUserID 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 NewGetRejectedOfficeUserParams() beforehand. +func (o *GetRejectedOfficeUserParams) BindRequest(r *http.Request, route *middleware.MatchedRoute) error { + var res []error + + o.HTTPRequest = r + + rOfficeUserID, rhkOfficeUserID, _ := route.Params.GetOK("officeUserId") + if err := o.bindOfficeUserID(rOfficeUserID, rhkOfficeUserID, route.Formats); err != nil { + res = append(res, err) + } + if len(res) > 0 { + return errors.CompositeValidationError(res...) + } + return nil +} + +// bindOfficeUserID binds and validates parameter OfficeUserID from path. +func (o *GetRejectedOfficeUserParams) bindOfficeUserID(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("officeUserId", "path", "strfmt.UUID", raw) + } + o.OfficeUserID = *(value.(*strfmt.UUID)) + + if err := o.validateOfficeUserID(formats); err != nil { + return err + } + + return nil +} + +// validateOfficeUserID carries on validations for parameter OfficeUserID +func (o *GetRejectedOfficeUserParams) validateOfficeUserID(formats strfmt.Registry) error { + + if err := validate.FormatOf("officeUserId", "path", "uuid", o.OfficeUserID.String(), formats); err != nil { + return err + } + return nil +} diff --git a/pkg/gen/adminapi/adminoperations/rejected_office_users/get_rejected_office_user_responses.go b/pkg/gen/adminapi/adminoperations/rejected_office_users/get_rejected_office_user_responses.go new file mode 100644 index 00000000000..a67fcb04e3f --- /dev/null +++ b/pkg/gen/adminapi/adminoperations/rejected_office_users/get_rejected_office_user_responses.go @@ -0,0 +1,159 @@ +// Code generated by go-swagger; DO NOT EDIT. + +package rejected_office_users + +// 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/adminmessages" +) + +// GetRejectedOfficeUserOKCode is the HTTP code returned for type GetRejectedOfficeUserOK +const GetRejectedOfficeUserOKCode int = 200 + +/* +GetRejectedOfficeUserOK success + +swagger:response getRejectedOfficeUserOK +*/ +type GetRejectedOfficeUserOK struct { + + /* + In: Body + */ + Payload *adminmessages.OfficeUser `json:"body,omitempty"` +} + +// NewGetRejectedOfficeUserOK creates GetRejectedOfficeUserOK with default headers values +func NewGetRejectedOfficeUserOK() *GetRejectedOfficeUserOK { + + return &GetRejectedOfficeUserOK{} +} + +// WithPayload adds the payload to the get rejected office user o k response +func (o *GetRejectedOfficeUserOK) WithPayload(payload *adminmessages.OfficeUser) *GetRejectedOfficeUserOK { + o.Payload = payload + return o +} + +// SetPayload sets the payload to the get rejected office user o k response +func (o *GetRejectedOfficeUserOK) SetPayload(payload *adminmessages.OfficeUser) { + o.Payload = payload +} + +// WriteResponse to the client +func (o *GetRejectedOfficeUserOK) WriteResponse(rw http.ResponseWriter, producer runtime.Producer) { + + rw.WriteHeader(200) + if o.Payload != nil { + payload := o.Payload + if err := producer.Produce(rw, payload); err != nil { + panic(err) // let the recovery middleware deal with this + } + } +} + +// GetRejectedOfficeUserBadRequestCode is the HTTP code returned for type GetRejectedOfficeUserBadRequest +const GetRejectedOfficeUserBadRequestCode int = 400 + +/* +GetRejectedOfficeUserBadRequest invalid request + +swagger:response getRejectedOfficeUserBadRequest +*/ +type GetRejectedOfficeUserBadRequest struct { +} + +// NewGetRejectedOfficeUserBadRequest creates GetRejectedOfficeUserBadRequest with default headers values +func NewGetRejectedOfficeUserBadRequest() *GetRejectedOfficeUserBadRequest { + + return &GetRejectedOfficeUserBadRequest{} +} + +// WriteResponse to the client +func (o *GetRejectedOfficeUserBadRequest) WriteResponse(rw http.ResponseWriter, producer runtime.Producer) { + + rw.Header().Del(runtime.HeaderContentType) //Remove Content-Type on empty responses + + rw.WriteHeader(400) +} + +// GetRejectedOfficeUserUnauthorizedCode is the HTTP code returned for type GetRejectedOfficeUserUnauthorized +const GetRejectedOfficeUserUnauthorizedCode int = 401 + +/* +GetRejectedOfficeUserUnauthorized request requires user authentication + +swagger:response getRejectedOfficeUserUnauthorized +*/ +type GetRejectedOfficeUserUnauthorized struct { +} + +// NewGetRejectedOfficeUserUnauthorized creates GetRejectedOfficeUserUnauthorized with default headers values +func NewGetRejectedOfficeUserUnauthorized() *GetRejectedOfficeUserUnauthorized { + + return &GetRejectedOfficeUserUnauthorized{} +} + +// WriteResponse to the client +func (o *GetRejectedOfficeUserUnauthorized) WriteResponse(rw http.ResponseWriter, producer runtime.Producer) { + + rw.Header().Del(runtime.HeaderContentType) //Remove Content-Type on empty responses + + rw.WriteHeader(401) +} + +// GetRejectedOfficeUserNotFoundCode is the HTTP code returned for type GetRejectedOfficeUserNotFound +const GetRejectedOfficeUserNotFoundCode int = 404 + +/* +GetRejectedOfficeUserNotFound Office User not found + +swagger:response getRejectedOfficeUserNotFound +*/ +type GetRejectedOfficeUserNotFound struct { +} + +// NewGetRejectedOfficeUserNotFound creates GetRejectedOfficeUserNotFound with default headers values +func NewGetRejectedOfficeUserNotFound() *GetRejectedOfficeUserNotFound { + + return &GetRejectedOfficeUserNotFound{} +} + +// WriteResponse to the client +func (o *GetRejectedOfficeUserNotFound) WriteResponse(rw http.ResponseWriter, producer runtime.Producer) { + + rw.Header().Del(runtime.HeaderContentType) //Remove Content-Type on empty responses + + rw.WriteHeader(404) +} + +// GetRejectedOfficeUserInternalServerErrorCode is the HTTP code returned for type GetRejectedOfficeUserInternalServerError +const GetRejectedOfficeUserInternalServerErrorCode int = 500 + +/* +GetRejectedOfficeUserInternalServerError server error + +swagger:response getRejectedOfficeUserInternalServerError +*/ +type GetRejectedOfficeUserInternalServerError struct { +} + +// NewGetRejectedOfficeUserInternalServerError creates GetRejectedOfficeUserInternalServerError with default headers values +func NewGetRejectedOfficeUserInternalServerError() *GetRejectedOfficeUserInternalServerError { + + return &GetRejectedOfficeUserInternalServerError{} +} + +// WriteResponse to the client +func (o *GetRejectedOfficeUserInternalServerError) 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/adminapi/adminoperations/rejected_office_users/get_rejected_office_user_urlbuilder.go b/pkg/gen/adminapi/adminoperations/rejected_office_users/get_rejected_office_user_urlbuilder.go new file mode 100644 index 00000000000..090820d35f5 --- /dev/null +++ b/pkg/gen/adminapi/adminoperations/rejected_office_users/get_rejected_office_user_urlbuilder.go @@ -0,0 +1,101 @@ +// Code generated by go-swagger; DO NOT EDIT. + +package rejected_office_users + +// 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" +) + +// GetRejectedOfficeUserURL generates an URL for the get rejected office user operation +type GetRejectedOfficeUserURL struct { + OfficeUserID 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 *GetRejectedOfficeUserURL) WithBasePath(bp string) *GetRejectedOfficeUserURL { + 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 *GetRejectedOfficeUserURL) SetBasePath(bp string) { + o._basePath = bp +} + +// Build a url path and query string +func (o *GetRejectedOfficeUserURL) Build() (*url.URL, error) { + var _result url.URL + + var _path = "/rejected-office-users/{officeUserId}" + + officeUserID := o.OfficeUserID.String() + if officeUserID != "" { + _path = strings.Replace(_path, "{officeUserId}", officeUserID, -1) + } else { + return nil, errors.New("officeUserId is required on GetRejectedOfficeUserURL") + } + + _basePath := o._basePath + if _basePath == "" { + _basePath = "/admin/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 *GetRejectedOfficeUserURL) 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 *GetRejectedOfficeUserURL) String() string { + return o.Must(o.Build()).String() +} + +// BuildFull builds a full url with scheme, host, path and query string +func (o *GetRejectedOfficeUserURL) BuildFull(scheme, host string) (*url.URL, error) { + if scheme == "" { + return nil, errors.New("scheme is required for a full url on GetRejectedOfficeUserURL") + } + if host == "" { + return nil, errors.New("host is required for a full url on GetRejectedOfficeUserURL") + } + + 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 *GetRejectedOfficeUserURL) StringFull(scheme, host string) string { + return o.Must(o.BuildFull(scheme, host)).String() +} diff --git a/pkg/gen/adminapi/adminoperations/rejected_office_users/index_rejected_office_users.go b/pkg/gen/adminapi/adminoperations/rejected_office_users/index_rejected_office_users.go new file mode 100644 index 00000000000..bb1a98ebe4d --- /dev/null +++ b/pkg/gen/adminapi/adminoperations/rejected_office_users/index_rejected_office_users.go @@ -0,0 +1,59 @@ +// Code generated by go-swagger; DO NOT EDIT. + +package rejected_office_users + +// 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" +) + +// IndexRejectedOfficeUsersHandlerFunc turns a function with the right signature into a index rejected office users handler +type IndexRejectedOfficeUsersHandlerFunc func(IndexRejectedOfficeUsersParams) middleware.Responder + +// Handle executing the request and returning a response +func (fn IndexRejectedOfficeUsersHandlerFunc) Handle(params IndexRejectedOfficeUsersParams) middleware.Responder { + return fn(params) +} + +// IndexRejectedOfficeUsersHandler interface for that can handle valid index rejected office users params +type IndexRejectedOfficeUsersHandler interface { + Handle(IndexRejectedOfficeUsersParams) middleware.Responder +} + +// NewIndexRejectedOfficeUsers creates a new http.Handler for the index rejected office users operation +func NewIndexRejectedOfficeUsers(ctx *middleware.Context, handler IndexRejectedOfficeUsersHandler) *IndexRejectedOfficeUsers { + return &IndexRejectedOfficeUsers{Context: ctx, Handler: handler} +} + +/* + IndexRejectedOfficeUsers swagger:route GET /rejected-office-users Rejected office users indexRejectedOfficeUsers + +# List of Office Rejected Requesting Office Users Accounts + +This endpoint returns a list of Office Users. Do not use this endpoint directly +as it is meant to be used with the Admin UI exclusively. +*/ +type IndexRejectedOfficeUsers struct { + Context *middleware.Context + Handler IndexRejectedOfficeUsersHandler +} + +func (o *IndexRejectedOfficeUsers) ServeHTTP(rw http.ResponseWriter, r *http.Request) { + route, rCtx, _ := o.Context.RouteInfo(r) + if rCtx != nil { + *r = *rCtx + } + var Params = NewIndexRejectedOfficeUsersParams() + 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/adminapi/adminoperations/rejected_office_users/index_rejected_office_users_parameters.go b/pkg/gen/adminapi/adminoperations/rejected_office_users/index_rejected_office_users_parameters.go new file mode 100644 index 00000000000..1557c7990e1 --- /dev/null +++ b/pkg/gen/adminapi/adminoperations/rejected_office_users/index_rejected_office_users_parameters.go @@ -0,0 +1,201 @@ +// Code generated by go-swagger; DO NOT EDIT. + +package rejected_office_users + +// 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" + "github.com/go-openapi/runtime/middleware" + "github.com/go-openapi/strfmt" + "github.com/go-openapi/swag" +) + +// NewIndexRejectedOfficeUsersParams creates a new IndexRejectedOfficeUsersParams object +// +// There are no default values defined in the spec. +func NewIndexRejectedOfficeUsersParams() IndexRejectedOfficeUsersParams { + + return IndexRejectedOfficeUsersParams{} +} + +// IndexRejectedOfficeUsersParams contains all the bound params for the index rejected office users operation +// typically these are obtained from a http.Request +// +// swagger:parameters indexRejectedOfficeUsers +type IndexRejectedOfficeUsersParams struct { + + // HTTP Request Object + HTTPRequest *http.Request `json:"-"` + + /* + In: query + */ + Filter *string + /* + In: query + */ + Order *bool + /* + In: query + */ + Page *int64 + /* + In: query + */ + PerPage *int64 + /* + In: query + */ + Sort *string +} + +// 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 NewIndexRejectedOfficeUsersParams() beforehand. +func (o *IndexRejectedOfficeUsersParams) BindRequest(r *http.Request, route *middleware.MatchedRoute) error { + var res []error + + o.HTTPRequest = r + + qs := runtime.Values(r.URL.Query()) + + qFilter, qhkFilter, _ := qs.GetOK("filter") + if err := o.bindFilter(qFilter, qhkFilter, route.Formats); err != nil { + res = append(res, err) + } + + qOrder, qhkOrder, _ := qs.GetOK("order") + if err := o.bindOrder(qOrder, qhkOrder, route.Formats); err != nil { + res = append(res, err) + } + + qPage, qhkPage, _ := qs.GetOK("page") + if err := o.bindPage(qPage, qhkPage, route.Formats); err != nil { + res = append(res, err) + } + + qPerPage, qhkPerPage, _ := qs.GetOK("perPage") + if err := o.bindPerPage(qPerPage, qhkPerPage, route.Formats); err != nil { + res = append(res, err) + } + + qSort, qhkSort, _ := qs.GetOK("sort") + if err := o.bindSort(qSort, qhkSort, route.Formats); err != nil { + res = append(res, err) + } + if len(res) > 0 { + return errors.CompositeValidationError(res...) + } + return nil +} + +// bindFilter binds and validates parameter Filter from query. +func (o *IndexRejectedOfficeUsersParams) bindFilter(rawData []string, hasKey bool, formats strfmt.Registry) error { + var raw string + if len(rawData) > 0 { + raw = rawData[len(rawData)-1] + } + + // Required: false + // AllowEmptyValue: false + + if raw == "" { // empty values pass all other validations + return nil + } + o.Filter = &raw + + return nil +} + +// bindOrder binds and validates parameter Order from query. +func (o *IndexRejectedOfficeUsersParams) bindOrder(rawData []string, hasKey bool, formats strfmt.Registry) error { + var raw string + if len(rawData) > 0 { + raw = rawData[len(rawData)-1] + } + + // Required: false + // AllowEmptyValue: false + + if raw == "" { // empty values pass all other validations + return nil + } + + value, err := swag.ConvertBool(raw) + if err != nil { + return errors.InvalidType("order", "query", "bool", raw) + } + o.Order = &value + + return nil +} + +// bindPage binds and validates parameter Page from query. +func (o *IndexRejectedOfficeUsersParams) bindPage(rawData []string, hasKey bool, formats strfmt.Registry) error { + var raw string + if len(rawData) > 0 { + raw = rawData[len(rawData)-1] + } + + // Required: false + // AllowEmptyValue: false + + if raw == "" { // empty values pass all other validations + return nil + } + + value, err := swag.ConvertInt64(raw) + if err != nil { + return errors.InvalidType("page", "query", "int64", raw) + } + o.Page = &value + + return nil +} + +// bindPerPage binds and validates parameter PerPage from query. +func (o *IndexRejectedOfficeUsersParams) bindPerPage(rawData []string, hasKey bool, formats strfmt.Registry) error { + var raw string + if len(rawData) > 0 { + raw = rawData[len(rawData)-1] + } + + // Required: false + // AllowEmptyValue: false + + if raw == "" { // empty values pass all other validations + return nil + } + + value, err := swag.ConvertInt64(raw) + if err != nil { + return errors.InvalidType("perPage", "query", "int64", raw) + } + o.PerPage = &value + + return nil +} + +// bindSort binds and validates parameter Sort from query. +func (o *IndexRejectedOfficeUsersParams) bindSort(rawData []string, hasKey bool, formats strfmt.Registry) error { + var raw string + if len(rawData) > 0 { + raw = rawData[len(rawData)-1] + } + + // Required: false + // AllowEmptyValue: false + + if raw == "" { // empty values pass all other validations + return nil + } + o.Sort = &raw + + return nil +} diff --git a/pkg/gen/adminapi/adminoperations/rejected_office_users/index_rejected_office_users_responses.go b/pkg/gen/adminapi/adminoperations/rejected_office_users/index_rejected_office_users_responses.go new file mode 100644 index 00000000000..a434819b1c7 --- /dev/null +++ b/pkg/gen/adminapi/adminoperations/rejected_office_users/index_rejected_office_users_responses.go @@ -0,0 +1,184 @@ +// Code generated by go-swagger; DO NOT EDIT. + +package rejected_office_users + +// 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/adminmessages" +) + +// IndexRejectedOfficeUsersOKCode is the HTTP code returned for type IndexRejectedOfficeUsersOK +const IndexRejectedOfficeUsersOKCode int = 200 + +/* +IndexRejectedOfficeUsersOK success + +swagger:response indexRejectedOfficeUsersOK +*/ +type IndexRejectedOfficeUsersOK struct { + /*Used for pagination + + */ + ContentRange string `json:"Content-Range"` + + /* + In: Body + */ + Payload adminmessages.OfficeUsers `json:"body,omitempty"` +} + +// NewIndexRejectedOfficeUsersOK creates IndexRejectedOfficeUsersOK with default headers values +func NewIndexRejectedOfficeUsersOK() *IndexRejectedOfficeUsersOK { + + return &IndexRejectedOfficeUsersOK{} +} + +// WithContentRange adds the contentRange to the index rejected office users o k response +func (o *IndexRejectedOfficeUsersOK) WithContentRange(contentRange string) *IndexRejectedOfficeUsersOK { + o.ContentRange = contentRange + return o +} + +// SetContentRange sets the contentRange to the index rejected office users o k response +func (o *IndexRejectedOfficeUsersOK) SetContentRange(contentRange string) { + o.ContentRange = contentRange +} + +// WithPayload adds the payload to the index rejected office users o k response +func (o *IndexRejectedOfficeUsersOK) WithPayload(payload adminmessages.OfficeUsers) *IndexRejectedOfficeUsersOK { + o.Payload = payload + return o +} + +// SetPayload sets the payload to the index rejected office users o k response +func (o *IndexRejectedOfficeUsersOK) SetPayload(payload adminmessages.OfficeUsers) { + o.Payload = payload +} + +// WriteResponse to the client +func (o *IndexRejectedOfficeUsersOK) WriteResponse(rw http.ResponseWriter, producer runtime.Producer) { + + // response header Content-Range + + contentRange := o.ContentRange + if contentRange != "" { + rw.Header().Set("Content-Range", contentRange) + } + + rw.WriteHeader(200) + payload := o.Payload + if payload == nil { + // return empty array + payload = adminmessages.OfficeUsers{} + } + + if err := producer.Produce(rw, payload); err != nil { + panic(err) // let the recovery middleware deal with this + } +} + +// IndexRejectedOfficeUsersBadRequestCode is the HTTP code returned for type IndexRejectedOfficeUsersBadRequest +const IndexRejectedOfficeUsersBadRequestCode int = 400 + +/* +IndexRejectedOfficeUsersBadRequest invalid request + +swagger:response indexRejectedOfficeUsersBadRequest +*/ +type IndexRejectedOfficeUsersBadRequest struct { +} + +// NewIndexRejectedOfficeUsersBadRequest creates IndexRejectedOfficeUsersBadRequest with default headers values +func NewIndexRejectedOfficeUsersBadRequest() *IndexRejectedOfficeUsersBadRequest { + + return &IndexRejectedOfficeUsersBadRequest{} +} + +// WriteResponse to the client +func (o *IndexRejectedOfficeUsersBadRequest) WriteResponse(rw http.ResponseWriter, producer runtime.Producer) { + + rw.Header().Del(runtime.HeaderContentType) //Remove Content-Type on empty responses + + rw.WriteHeader(400) +} + +// IndexRejectedOfficeUsersUnauthorizedCode is the HTTP code returned for type IndexRejectedOfficeUsersUnauthorized +const IndexRejectedOfficeUsersUnauthorizedCode int = 401 + +/* +IndexRejectedOfficeUsersUnauthorized request requires user authentication + +swagger:response indexRejectedOfficeUsersUnauthorized +*/ +type IndexRejectedOfficeUsersUnauthorized struct { +} + +// NewIndexRejectedOfficeUsersUnauthorized creates IndexRejectedOfficeUsersUnauthorized with default headers values +func NewIndexRejectedOfficeUsersUnauthorized() *IndexRejectedOfficeUsersUnauthorized { + + return &IndexRejectedOfficeUsersUnauthorized{} +} + +// WriteResponse to the client +func (o *IndexRejectedOfficeUsersUnauthorized) WriteResponse(rw http.ResponseWriter, producer runtime.Producer) { + + rw.Header().Del(runtime.HeaderContentType) //Remove Content-Type on empty responses + + rw.WriteHeader(401) +} + +// IndexRejectedOfficeUsersNotFoundCode is the HTTP code returned for type IndexRejectedOfficeUsersNotFound +const IndexRejectedOfficeUsersNotFoundCode int = 404 + +/* +IndexRejectedOfficeUsersNotFound Office User not found + +swagger:response indexRejectedOfficeUsersNotFound +*/ +type IndexRejectedOfficeUsersNotFound struct { +} + +// NewIndexRejectedOfficeUsersNotFound creates IndexRejectedOfficeUsersNotFound with default headers values +func NewIndexRejectedOfficeUsersNotFound() *IndexRejectedOfficeUsersNotFound { + + return &IndexRejectedOfficeUsersNotFound{} +} + +// WriteResponse to the client +func (o *IndexRejectedOfficeUsersNotFound) WriteResponse(rw http.ResponseWriter, producer runtime.Producer) { + + rw.Header().Del(runtime.HeaderContentType) //Remove Content-Type on empty responses + + rw.WriteHeader(404) +} + +// IndexRejectedOfficeUsersInternalServerErrorCode is the HTTP code returned for type IndexRejectedOfficeUsersInternalServerError +const IndexRejectedOfficeUsersInternalServerErrorCode int = 500 + +/* +IndexRejectedOfficeUsersInternalServerError server error + +swagger:response indexRejectedOfficeUsersInternalServerError +*/ +type IndexRejectedOfficeUsersInternalServerError struct { +} + +// NewIndexRejectedOfficeUsersInternalServerError creates IndexRejectedOfficeUsersInternalServerError with default headers values +func NewIndexRejectedOfficeUsersInternalServerError() *IndexRejectedOfficeUsersInternalServerError { + + return &IndexRejectedOfficeUsersInternalServerError{} +} + +// WriteResponse to the client +func (o *IndexRejectedOfficeUsersInternalServerError) 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/adminapi/adminoperations/rejected_office_users/index_rejected_office_users_urlbuilder.go b/pkg/gen/adminapi/adminoperations/rejected_office_users/index_rejected_office_users_urlbuilder.go new file mode 100644 index 00000000000..2585e80458f --- /dev/null +++ b/pkg/gen/adminapi/adminoperations/rejected_office_users/index_rejected_office_users_urlbuilder.go @@ -0,0 +1,141 @@ +// Code generated by go-swagger; DO NOT EDIT. + +package rejected_office_users + +// 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" + + "github.com/go-openapi/swag" +) + +// IndexRejectedOfficeUsersURL generates an URL for the index rejected office users operation +type IndexRejectedOfficeUsersURL struct { + Filter *string + Order *bool + Page *int64 + PerPage *int64 + Sort *string + + _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 *IndexRejectedOfficeUsersURL) WithBasePath(bp string) *IndexRejectedOfficeUsersURL { + 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 *IndexRejectedOfficeUsersURL) SetBasePath(bp string) { + o._basePath = bp +} + +// Build a url path and query string +func (o *IndexRejectedOfficeUsersURL) Build() (*url.URL, error) { + var _result url.URL + + var _path = "/rejected-office-users" + + _basePath := o._basePath + if _basePath == "" { + _basePath = "/admin/v1" + } + _result.Path = golangswaggerpaths.Join(_basePath, _path) + + qs := make(url.Values) + + var filterQ string + if o.Filter != nil { + filterQ = *o.Filter + } + if filterQ != "" { + qs.Set("filter", filterQ) + } + + var orderQ string + if o.Order != nil { + orderQ = swag.FormatBool(*o.Order) + } + if orderQ != "" { + qs.Set("order", orderQ) + } + + var pageQ string + if o.Page != nil { + pageQ = swag.FormatInt64(*o.Page) + } + if pageQ != "" { + qs.Set("page", pageQ) + } + + var perPageQ string + if o.PerPage != nil { + perPageQ = swag.FormatInt64(*o.PerPage) + } + if perPageQ != "" { + qs.Set("perPage", perPageQ) + } + + var sortQ string + if o.Sort != nil { + sortQ = *o.Sort + } + if sortQ != "" { + qs.Set("sort", sortQ) + } + + _result.RawQuery = qs.Encode() + + return &_result, nil +} + +// Must is a helper function to panic when the url builder returns an error +func (o *IndexRejectedOfficeUsersURL) 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 *IndexRejectedOfficeUsersURL) String() string { + return o.Must(o.Build()).String() +} + +// BuildFull builds a full url with scheme, host, path and query string +func (o *IndexRejectedOfficeUsersURL) BuildFull(scheme, host string) (*url.URL, error) { + if scheme == "" { + return nil, errors.New("scheme is required for a full url on IndexRejectedOfficeUsersURL") + } + if host == "" { + return nil, errors.New("host is required for a full url on IndexRejectedOfficeUsersURL") + } + + 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 *IndexRejectedOfficeUsersURL) StringFull(scheme, host string) string { + return o.Must(o.BuildFull(scheme, host)).String() +} diff --git a/pkg/gen/adminapi/configure_mymove.go b/pkg/gen/adminapi/configure_mymove.go index 1e8322fbfe9..a872c2d579c 100644 --- a/pkg/gen/adminapi/configure_mymove.go +++ b/pkg/gen/adminapi/configure_mymove.go @@ -20,6 +20,7 @@ import ( "github.com/transcom/mymove/pkg/gen/adminapi/adminoperations/organizations" "github.com/transcom/mymove/pkg/gen/adminapi/adminoperations/payment_request_syncada_file" "github.com/transcom/mymove/pkg/gen/adminapi/adminoperations/payment_request_syncada_files" + "github.com/transcom/mymove/pkg/gen/adminapi/adminoperations/rejected_office_users" "github.com/transcom/mymove/pkg/gen/adminapi/adminoperations/requested_office_users" "github.com/transcom/mymove/pkg/gen/adminapi/adminoperations/transportation_offices" "github.com/transcom/mymove/pkg/gen/adminapi/adminoperations/uploads" @@ -107,6 +108,11 @@ func configureAPI(api *adminoperations.MymoveAPI) http.Handler { return middleware.NotImplemented("operation office_users.GetOfficeUser has not yet been implemented") }) } + if api.RejectedOfficeUsersGetRejectedOfficeUserHandler == nil { + api.RejectedOfficeUsersGetRejectedOfficeUserHandler = rejected_office_users.GetRejectedOfficeUserHandlerFunc(func(params rejected_office_users.GetRejectedOfficeUserParams) middleware.Responder { + return middleware.NotImplemented("operation rejected_office_users.GetRejectedOfficeUser has not yet been implemented") + }) + } if api.RequestedOfficeUsersGetRequestedOfficeUserHandler == nil { api.RequestedOfficeUsersGetRequestedOfficeUserHandler = requested_office_users.GetRequestedOfficeUserHandlerFunc(func(params requested_office_users.GetRequestedOfficeUserParams) middleware.Responder { return middleware.NotImplemented("operation requested_office_users.GetRequestedOfficeUser has not yet been implemented") @@ -172,6 +178,11 @@ func configureAPI(api *adminoperations.MymoveAPI) http.Handler { return middleware.NotImplemented("operation payment_request_syncada_files.IndexPaymentRequestSyncadaFiles has not yet been implemented") }) } + if api.RejectedOfficeUsersIndexRejectedOfficeUsersHandler == nil { + api.RejectedOfficeUsersIndexRejectedOfficeUsersHandler = rejected_office_users.IndexRejectedOfficeUsersHandlerFunc(func(params rejected_office_users.IndexRejectedOfficeUsersParams) middleware.Responder { + return middleware.NotImplemented("operation rejected_office_users.IndexRejectedOfficeUsers has not yet been implemented") + }) + } if api.RequestedOfficeUsersIndexRequestedOfficeUsersHandler == nil { api.RequestedOfficeUsersIndexRequestedOfficeUsersHandler = requested_office_users.IndexRequestedOfficeUsersHandlerFunc(func(params requested_office_users.IndexRequestedOfficeUsersParams) middleware.Responder { return middleware.NotImplemented("operation requested_office_users.IndexRequestedOfficeUsers has not yet been implemented") diff --git a/pkg/gen/adminapi/embedded_spec.go b/pkg/gen/adminapi/embedded_spec.go index c92c3d50045..9cc2deaab02 100644 --- a/pkg/gen/adminapi/embedded_spec.go +++ b/pkg/gen/adminapi/embedded_spec.go @@ -1365,6 +1365,114 @@ func init() { } } }, + "/rejected-office-users": { + "get": { + "description": "This endpoint returns a list of Office Users. Do not use this endpoint directly\nas it is meant to be used with the Admin UI exclusively.\n", + "produces": [ + "application/json" + ], + "tags": [ + "Rejected office users" + ], + "summary": "List of Office Rejected Requesting Office Users Accounts", + "operationId": "indexRejectedOfficeUsers", + "parameters": [ + { + "type": "string", + "name": "filter", + "in": "query" + }, + { + "type": "integer", + "name": "page", + "in": "query" + }, + { + "type": "integer", + "name": "perPage", + "in": "query" + }, + { + "type": "string", + "name": "sort", + "in": "query" + }, + { + "type": "boolean", + "name": "order", + "in": "query" + } + ], + "responses": { + "200": { + "description": "success", + "schema": { + "$ref": "#/definitions/OfficeUsers" + }, + "headers": { + "Content-Range": { + "type": "string", + "description": "Used for pagination" + } + } + }, + "400": { + "description": "invalid request" + }, + "401": { + "description": "request requires user authentication" + }, + "404": { + "description": "Office User not found" + }, + "500": { + "description": "server error" + } + } + } + }, + "/rejected-office-users/{officeUserId}": { + "get": { + "description": "Retrieving a single office user in any status. This endpoint is used in the Admin UI that will allow the admin user to view the user's relevant data.", + "produces": [ + "application/json" + ], + "tags": [ + "Rejected office users" + ], + "summary": "Get a Rejected Office User", + "operationId": "getRejectedOfficeUser", + "parameters": [ + { + "type": "string", + "format": "uuid", + "name": "officeUserId", + "in": "path", + "required": true + } + ], + "responses": { + "200": { + "description": "success", + "schema": { + "$ref": "#/definitions/OfficeUser" + } + }, + "400": { + "description": "invalid request" + }, + "401": { + "description": "request requires user authentication" + }, + "404": { + "description": "Office User not found" + }, + "500": { + "description": "server error" + } + } + } + }, "/requested-office-users": { "get": { "description": "This endpoint returns a list of Office Users. Do not use this endpoint directly\nas it is meant to be used with the Admin UI exclusively.\n", @@ -2747,6 +2855,11 @@ func init() { "format": "date-time", "readOnly": true }, + "deletedOn": { + "type": "string", + "format": "date-time", + "readOnly": true + }, "edipi": { "type": "string" }, @@ -2778,6 +2891,11 @@ func init() { "$ref": "#/definitions/Privilege" } }, + "rejectedOn": { + "type": "string", + "format": "date-time", + "readOnly": true + }, "rejectionReason": { "type": "string" }, @@ -3658,6 +3776,13 @@ func init() { "url": "https://transcom.github.io/mymove-docs/docs/api" } }, + { + "description": "Information about rejected office users", + "name": "Rejected office users", + "externalDocs": { + "url": "https://transcom.github.io/mymove-docs/docs/api" + } + }, { "description": "Information about users", "name": "Users", @@ -5022,6 +5147,114 @@ func init() { } } }, + "/rejected-office-users": { + "get": { + "description": "This endpoint returns a list of Office Users. Do not use this endpoint directly\nas it is meant to be used with the Admin UI exclusively.\n", + "produces": [ + "application/json" + ], + "tags": [ + "Rejected office users" + ], + "summary": "List of Office Rejected Requesting Office Users Accounts", + "operationId": "indexRejectedOfficeUsers", + "parameters": [ + { + "type": "string", + "name": "filter", + "in": "query" + }, + { + "type": "integer", + "name": "page", + "in": "query" + }, + { + "type": "integer", + "name": "perPage", + "in": "query" + }, + { + "type": "string", + "name": "sort", + "in": "query" + }, + { + "type": "boolean", + "name": "order", + "in": "query" + } + ], + "responses": { + "200": { + "description": "success", + "schema": { + "$ref": "#/definitions/OfficeUsers" + }, + "headers": { + "Content-Range": { + "type": "string", + "description": "Used for pagination" + } + } + }, + "400": { + "description": "invalid request" + }, + "401": { + "description": "request requires user authentication" + }, + "404": { + "description": "Office User not found" + }, + "500": { + "description": "server error" + } + } + } + }, + "/rejected-office-users/{officeUserId}": { + "get": { + "description": "Retrieving a single office user in any status. This endpoint is used in the Admin UI that will allow the admin user to view the user's relevant data.", + "produces": [ + "application/json" + ], + "tags": [ + "Rejected office users" + ], + "summary": "Get a Rejected Office User", + "operationId": "getRejectedOfficeUser", + "parameters": [ + { + "type": "string", + "format": "uuid", + "name": "officeUserId", + "in": "path", + "required": true + } + ], + "responses": { + "200": { + "description": "success", + "schema": { + "$ref": "#/definitions/OfficeUser" + } + }, + "400": { + "description": "invalid request" + }, + "401": { + "description": "request requires user authentication" + }, + "404": { + "description": "Office User not found" + }, + "500": { + "description": "server error" + } + } + } + }, "/requested-office-users": { "get": { "description": "This endpoint returns a list of Office Users. Do not use this endpoint directly\nas it is meant to be used with the Admin UI exclusively.\n", @@ -6405,6 +6638,11 @@ func init() { "format": "date-time", "readOnly": true }, + "deletedOn": { + "type": "string", + "format": "date-time", + "readOnly": true + }, "edipi": { "type": "string" }, @@ -6436,6 +6674,11 @@ func init() { "$ref": "#/definitions/Privilege" } }, + "rejectedOn": { + "type": "string", + "format": "date-time", + "readOnly": true + }, "rejectionReason": { "type": "string" }, @@ -7320,6 +7563,13 @@ func init() { "url": "https://transcom.github.io/mymove-docs/docs/api" } }, + { + "description": "Information about rejected office users", + "name": "Rejected office users", + "externalDocs": { + "url": "https://transcom.github.io/mymove-docs/docs/api" + } + }, { "description": "Information about users", "name": "Users", diff --git a/pkg/gen/adminmessages/office_user.go b/pkg/gen/adminmessages/office_user.go index 0a58b7a0861..378a6165e4d 100644 --- a/pkg/gen/adminmessages/office_user.go +++ b/pkg/gen/adminmessages/office_user.go @@ -31,6 +31,11 @@ type OfficeUser struct { // Format: date-time CreatedAt strfmt.DateTime `json:"createdAt"` + // deleted on + // Read Only: true + // Format: date-time + DeletedOn strfmt.DateTime `json:"deletedOn,omitempty"` + // edipi // Required: true Edipi *string `json:"edipi"` @@ -65,6 +70,11 @@ type OfficeUser struct { // privileges Privileges []*Privilege `json:"privileges"` + // rejected on + // Read Only: true + // Format: date-time + RejectedOn strfmt.DateTime `json:"rejectedOn,omitempty"` + // rejection reason // Required: true RejectionReason *string `json:"rejectionReason"` @@ -115,6 +125,10 @@ func (m *OfficeUser) Validate(formats strfmt.Registry) error { res = append(res, err) } + if err := m.validateDeletedOn(formats); err != nil { + res = append(res, err) + } + if err := m.validateEdipi(formats); err != nil { res = append(res, err) } @@ -147,6 +161,10 @@ func (m *OfficeUser) Validate(formats strfmt.Registry) error { res = append(res, err) } + if err := m.validateRejectedOn(formats); err != nil { + res = append(res, err) + } + if err := m.validateRejectionReason(formats); err != nil { res = append(res, err) } @@ -207,6 +225,18 @@ func (m *OfficeUser) validateCreatedAt(formats strfmt.Registry) error { return nil } +func (m *OfficeUser) validateDeletedOn(formats strfmt.Registry) error { + if swag.IsZero(m.DeletedOn) { // not required + return nil + } + + if err := validate.FormatOf("deletedOn", "body", "date-time", m.DeletedOn.String(), formats); err != nil { + return err + } + + return nil +} + func (m *OfficeUser) validateEdipi(formats strfmt.Registry) error { if err := validate.Required("edipi", "body", m.Edipi); err != nil { @@ -304,6 +334,18 @@ func (m *OfficeUser) validatePrivileges(formats strfmt.Registry) error { return nil } +func (m *OfficeUser) validateRejectedOn(formats strfmt.Registry) error { + if swag.IsZero(m.RejectedOn) { // not required + return nil + } + + if err := validate.FormatOf("rejectedOn", "body", "date-time", m.RejectedOn.String(), formats); err != nil { + return err + } + + return nil +} + func (m *OfficeUser) validateRejectionReason(formats strfmt.Registry) error { if err := validate.Required("rejectionReason", "body", m.RejectionReason); err != nil { @@ -472,10 +514,18 @@ func (m *OfficeUser) ContextValidate(ctx context.Context, formats strfmt.Registr res = append(res, err) } + if err := m.contextValidateDeletedOn(ctx, formats); err != nil { + res = append(res, err) + } + if err := m.contextValidatePrivileges(ctx, formats); err != nil { res = append(res, err) } + if err := m.contextValidateRejectedOn(ctx, formats); err != nil { + res = append(res, err) + } + if err := m.contextValidateRoles(ctx, formats); err != nil { res = append(res, err) } @@ -503,6 +553,15 @@ func (m *OfficeUser) contextValidateCreatedAt(ctx context.Context, formats strfm return nil } +func (m *OfficeUser) contextValidateDeletedOn(ctx context.Context, formats strfmt.Registry) error { + + if err := validate.ReadOnly(ctx, "deletedOn", "body", strfmt.DateTime(m.DeletedOn)); err != nil { + return err + } + + return nil +} + func (m *OfficeUser) contextValidatePrivileges(ctx context.Context, formats strfmt.Registry) error { for i := 0; i < len(m.Privileges); i++ { @@ -528,6 +587,15 @@ func (m *OfficeUser) contextValidatePrivileges(ctx context.Context, formats strf return nil } +func (m *OfficeUser) contextValidateRejectedOn(ctx context.Context, formats strfmt.Registry) error { + + if err := validate.ReadOnly(ctx, "rejectedOn", "body", strfmt.DateTime(m.RejectedOn)); err != nil { + return err + } + + return nil +} + func (m *OfficeUser) contextValidateRoles(ctx context.Context, formats strfmt.Registry) error { for i := 0; i < len(m.Roles); i++ { diff --git a/pkg/models/office_user.go b/pkg/models/office_user.go index 5386b80e90b..e07fda465a4 100644 --- a/pkg/models/office_user.go +++ b/pkg/models/office_user.go @@ -42,6 +42,8 @@ type OfficeUser struct { EDIPI *string `json:"edipi" db:"edipi"` OtherUniqueID *string `json:"other_unique_id" db:"other_unique_id"` RejectionReason *string `json:"rejection_reason" db:"rejection_reason"` + RejectedOn *string `json:"rejected_on" db:"rejected_on"` + DeletedOn *string `json:"deleted_on" db:"deleted_on"` } type OfficeUserWithWorkload struct { diff --git a/swagger-def/admin.yaml b/swagger-def/admin.yaml index a7c7dc058e0..1c17d22af79 100644 --- a/swagger-def/admin.yaml +++ b/swagger-def/admin.yaml @@ -57,6 +57,10 @@ tags: description: Information about requested office users externalDocs: url: https://transcom.github.io/mymove-docs/docs/api + - name: Rejected office users + description: Information about rejected office users + externalDocs: + url: https://transcom.github.io/mymove-docs/docs/api - name: Users description: Information about users externalDocs: @@ -711,6 +715,14 @@ definitions: type: string format: date-time readOnly: true + rejectedOn: + type: string + format: date-time + readOnly: true + deletedOn: + type: string + format: date-time + readOnly: true required: - id - firstName @@ -1416,6 +1428,77 @@ paths: description: Office User not found "500": description: server error + /rejected-office-users: + get: + produces: + - application/json + summary: List of Office Rejected Requesting Office Users Accounts + description: + $ref: paths/office-users/get/description.md + operationId: indexRejectedOfficeUsers + tags: + - Rejected office users + parameters: + - in: query + name: filter + type: string + - in: query + name: page + type: integer + - in: query + name: perPage + type: integer + - in: query + name: sort + type: string + - in: query + name: order + type: boolean + responses: + "200": + description: success + headers: + Content-Range: + type: string + description: Used for pagination + schema: + $ref: "#/definitions/OfficeUsers" + "400": + description: invalid request + "401": + description: request requires user authentication + "404": + description: Office User not found + "500": + description: server error + /rejected-office-users/{officeUserId}: + get: + produces: + - application/json + summary: Get a Rejected Office User + description: Retrieving a single office user in any status. This endpoint is used in the Admin UI that will allow the admin user to view the user's relevant data. + operationId: getRejectedOfficeUser + tags: + - Rejected office users + parameters: + - in: path + name: officeUserId + type: string + format: uuid + required: true + responses: + "200": + description: success + schema: + $ref: "#/definitions/OfficeUser" + "400": + description: invalid request + "401": + description: request requires user authentication + "404": + description: Office User not found + "500": + description: server error /office-users: get: produces: diff --git a/swagger/admin.yaml b/swagger/admin.yaml index 4fcc51bd46d..992823f128f 100644 --- a/swagger/admin.yaml +++ b/swagger/admin.yaml @@ -61,6 +61,10 @@ tags: description: Information about requested office users externalDocs: url: https://transcom.github.io/mymove-docs/docs/api + - name: Rejected office users + description: Information about rejected office users + externalDocs: + url: https://transcom.github.io/mymove-docs/docs/api - name: Users description: Information about users externalDocs: @@ -718,6 +722,14 @@ definitions: type: string format: date-time readOnly: true + rejectedOn: + type: string + format: date-time + readOnly: true + deletedOn: + type: string + format: date-time + readOnly: true required: - id - firstName @@ -1432,6 +1444,83 @@ paths: $ref: '#/definitions/ValidationError' '500': description: server error + /rejected-office-users: + get: + produces: + - application/json + summary: List of Office Rejected Requesting Office Users Accounts + description: > + This endpoint returns a list of Office Users. Do not use this endpoint + directly + + as it is meant to be used with the Admin UI exclusively. + operationId: indexRejectedOfficeUsers + tags: + - Rejected office users + parameters: + - in: query + name: filter + type: string + - in: query + name: page + type: integer + - in: query + name: perPage + type: integer + - in: query + name: sort + type: string + - in: query + name: order + type: boolean + responses: + '200': + description: success + headers: + Content-Range: + type: string + description: Used for pagination + schema: + $ref: '#/definitions/OfficeUsers' + '400': + description: invalid request + '401': + description: request requires user authentication + '404': + description: Office User not found + '500': + description: server error + /rejected-office-users/{officeUserId}: + get: + produces: + - application/json + summary: Get a Rejected Office User + description: >- + Retrieving a single office user in any status. This endpoint is used in + the Admin UI that will allow the admin user to view the user's relevant + data. + operationId: getRejectedOfficeUser + tags: + - Rejected office users + parameters: + - in: path + name: officeUserId + type: string + format: uuid + required: true + responses: + '200': + description: success + schema: + $ref: '#/definitions/OfficeUser' + '400': + description: invalid request + '401': + description: request requires user authentication + '404': + description: Office User not found + '500': + description: server error /office-users: get: produces: From 8aff5143d0228d51428e0719e26a8b2310cd9b23 Mon Sep 17 00:00:00 2001 From: KonstanceH Date: Mon, 27 Jan 2025 21:10:53 +0000 Subject: [PATCH 02/37] added testharness fir requested/rejected office users --- pkg/testdatagen/testharness/dispatch.go | 6 ++ .../testharness/make_office_user.go | 90 +++++++++++++++++++ playwright/tests/utils/testharness.js | 14 +++ 3 files changed, 110 insertions(+) diff --git a/pkg/testdatagen/testharness/dispatch.go b/pkg/testdatagen/testharness/dispatch.go index 0ed11caf74a..15946d4c978 100644 --- a/pkg/testdatagen/testharness/dispatch.go +++ b/pkg/testdatagen/testharness/dispatch.go @@ -224,6 +224,12 @@ var actionDispatcher = map[string]actionFunc{ "OfficeUserWithTOOAndTIO": func(appCtx appcontext.AppContext) testHarnessResponse { return MakeOfficeUserWithTOOAndTIO(appCtx) }, + "RequestedOfficeUser": func(appCtx appcontext.AppContext) testHarnessResponse { + return MakeRequestedOfficeUserWithTOO(appCtx) + }, + "RejectedOfficeUser": func(appCtx appcontext.AppContext) testHarnessResponse { + return MakeRejectedOfficeUserWithTOO(appCtx) + }, "WebhookSubscription": func(appCtx appcontext.AppContext) testHarnessResponse { return testdatagen.MakeWebhookSubscription(appCtx.DB(), testdatagen.Assertions{}) }, diff --git a/pkg/testdatagen/testharness/make_office_user.go b/pkg/testdatagen/testharness/make_office_user.go index 64001d91b65..7f8230c5b23 100644 --- a/pkg/testdatagen/testharness/make_office_user.go +++ b/pkg/testdatagen/testharness/make_office_user.go @@ -12,6 +12,96 @@ import ( "github.com/transcom/mymove/pkg/testdatagen" ) +func MakeRejectedOfficeUserWithTOO(appCtx appcontext.AppContext) models.User { + tooRole := roles.Role{} + err := appCtx.DB().Where("role_type = $1", roles.RoleTypeTOO).First(&tooRole) + if err != nil { + log.Panic(fmt.Errorf("failed to find RoleTypeTOO in the DB: %w", err)) + } + + email := strings.ToLower(fmt.Sprintf("fred_office_%s@example.com", + testdatagen.MakeRandomString(5))) + + user := factory.BuildUser(appCtx.DB(), []factory.Customization{ + { + Model: models.User{ + OktaEmail: email, + Active: true, + Roles: []roles.Role{tooRole}, + }, + }, + }, nil) + rejectedStatus := models.OfficeUserStatusREJECTED + factory.BuildOfficeUserWithRoles(appCtx.DB(), []factory.Customization{ + { + Model: models.OfficeUser{ + Email: email, + Active: true, + UserID: &user.ID, + Status: &rejectedStatus, + }, + }, + { + Model: user, + LinkOnly: true, + }, + }, []roles.RoleType{roles.RoleTypeTOO, roles.RoleTypeTIO}) + + factory.BuildServiceMember(appCtx.DB(), []factory.Customization{ + { + Model: user, + LinkOnly: true, + }, + }, nil) + + return user +} + +func MakeRequestedOfficeUserWithTOO(appCtx appcontext.AppContext) models.User { + tooRole := roles.Role{} + err := appCtx.DB().Where("role_type = $1", roles.RoleTypeTOO).First(&tooRole) + if err != nil { + log.Panic(fmt.Errorf("failed to find RoleTypeTOO in the DB: %w", err)) + } + + email := strings.ToLower(fmt.Sprintf("fred_office_%s@example.com", + testdatagen.MakeRandomString(5))) + + user := factory.BuildUser(appCtx.DB(), []factory.Customization{ + { + Model: models.User{ + OktaEmail: email, + Active: true, + Roles: []roles.Role{tooRole}, + }, + }, + }, nil) + requestedStatus := models.OfficeUserStatusREQUESTED + factory.BuildOfficeUserWithRoles(appCtx.DB(), []factory.Customization{ + { + Model: models.OfficeUser{ + Email: email, + Active: true, + UserID: &user.ID, + Status: &requestedStatus, + }, + }, + { + Model: user, + LinkOnly: true, + }, + }, []roles.RoleType{roles.RoleTypeTOO, roles.RoleTypeTIO}) + + factory.BuildServiceMember(appCtx.DB(), []factory.Customization{ + { + Model: user, + LinkOnly: true, + }, + }, nil) + + return user +} + func MakeOfficeUserWithTOOAndTIO(appCtx appcontext.AppContext) models.User { tooRole := roles.Role{} err := appCtx.DB().Where("role_type = $1", roles.RoleTypeTOO).First(&tooRole) diff --git a/playwright/tests/utils/testharness.js b/playwright/tests/utils/testharness.js index cc84f4c61f9..d1732381488 100644 --- a/playwright/tests/utils/testharness.js +++ b/playwright/tests/utils/testharness.js @@ -93,6 +93,20 @@ export class TestHarness { return this.buildDefault('SuperAdminUser'); } + /** + * @returns {Promise} + */ + async buildRequestedOfficeUser() { + return this.buildDefault('RequestedOfficeUser'); + } + + /** + * @returns {Promise} + */ + async buildRejectedOfficeUser() { + return this.buildDefault('RejectedOfficeUser'); + } + /** * build office user with TOO and TIO roles * @returns {Promise} From 6cb024b3ef1b4062537e8dce894b223bcc5afb07 Mon Sep 17 00:00:00 2001 From: KonstanceH Date: Tue, 28 Jan 2025 20:29:20 +0000 Subject: [PATCH 03/37] adding services/tests/api. working on how rejected is added in test harness and add ui. --- pkg/factory/office_user_factory.go | 12 ++ pkg/handlers/adminapi/api.go | 15 ++ .../adminapi/rejected_office_users.go | 150 +++++++++++++++ .../adminapi/rejected_office_users_test.go | 180 ++++++++++++++++++ pkg/models/office_user.go | 4 +- .../mocks/RejectedOfficeUserFetcher.go | 59 ++++++ .../mocks/RejectedOfficeUserFetcherPop.go | 59 ++++++ .../mocks/RejectedOfficeUserListFetcher.go | 89 +++++++++ pkg/services/rejected_office_users.go | 30 +++ .../rejected_office_user_fetcher.go | 58 ++++++ .../rejected_office_user_fetcher_test.go | 90 +++++++++ .../rejected_office_user_service_test.go | 22 +++ .../rejected_office_users_list_fetcher.go | 35 ++++ ...rejected_office_users_list_fetcher_test.go | 82 ++++++++ 14 files changed, 883 insertions(+), 2 deletions(-) create mode 100644 pkg/handlers/adminapi/rejected_office_users.go create mode 100644 pkg/handlers/adminapi/rejected_office_users_test.go create mode 100644 pkg/services/mocks/RejectedOfficeUserFetcher.go create mode 100644 pkg/services/mocks/RejectedOfficeUserFetcherPop.go create mode 100644 pkg/services/mocks/RejectedOfficeUserListFetcher.go create mode 100644 pkg/services/rejected_office_users.go create mode 100644 pkg/services/rejected_office_users/rejected_office_user_fetcher.go create mode 100644 pkg/services/rejected_office_users/rejected_office_user_fetcher_test.go create mode 100644 pkg/services/rejected_office_users/rejected_office_user_service_test.go create mode 100644 pkg/services/rejected_office_users/rejected_office_users_list_fetcher.go create mode 100644 pkg/services/rejected_office_users/rejected_office_users_list_fetcher_test.go diff --git a/pkg/factory/office_user_factory.go b/pkg/factory/office_user_factory.go index 09b8bb0b154..9304ad228f8 100644 --- a/pkg/factory/office_user_factory.go +++ b/pkg/factory/office_user_factory.go @@ -340,3 +340,15 @@ func GetTraitRequestedOfficeUser() []Customization { }, } } + +// GetTraitRejectedOfficeUser sets the OfficeUser in an REJECTED status +func GetTraitRejectedOfficeUser() []Customization { + rejectedStatus := models.OfficeUserStatusREJECTED + return []Customization{ + { + Model: models.OfficeUser{ + Status: &rejectedStatus, + }, + }, + } +} diff --git a/pkg/handlers/adminapi/api.go b/pkg/handlers/adminapi/api.go index 34d6729a0f2..d45e131bc54 100644 --- a/pkg/handlers/adminapi/api.go +++ b/pkg/handlers/adminapi/api.go @@ -24,6 +24,7 @@ import ( prsff "github.com/transcom/mymove/pkg/services/payment_request" "github.com/transcom/mymove/pkg/services/ppmshipment" "github.com/transcom/mymove/pkg/services/query" + rejectedofficeusers "github.com/transcom/mymove/pkg/services/rejected_office_users" requestedofficeusers "github.com/transcom/mymove/pkg/services/requested_office_users" "github.com/transcom/mymove/pkg/services/roles" signedcertification "github.com/transcom/mymove/pkg/services/signed_certification" @@ -77,6 +78,20 @@ func NewAdminAPI(handlerConfig handlers.HandlerConfig) *adminops.MymoveAPI { newRolesFetcher, } + adminAPI.RejectedOfficeUsersIndexRejectedOfficeUsersHandler = IndexRejectedOfficeUsersHandler{ + handlerConfig, + rejectedofficeusers.NewRejectedOfficeUsersListFetcher(queryBuilder), + query.NewQueryFilter, + pagination.NewPagination, + } + + adminAPI.RejectedOfficeUsersGetRejectedOfficeUserHandler = GetRejectedOfficeUserHandler{ + handlerConfig, + rejectedofficeusers.NewRejectedOfficeUserFetcher(queryBuilder), + newRolesFetcher, + query.NewQueryFilter, + } + adminAPI.OfficeUsersIndexOfficeUsersHandler = IndexOfficeUsersHandler{ handlerConfig, fetch.NewListFetcher(queryBuilder), diff --git a/pkg/handlers/adminapi/rejected_office_users.go b/pkg/handlers/adminapi/rejected_office_users.go new file mode 100644 index 00000000000..9d28596cf3c --- /dev/null +++ b/pkg/handlers/adminapi/rejected_office_users.go @@ -0,0 +1,150 @@ +package adminapi + +import ( + "fmt" + + "github.com/go-openapi/runtime/middleware" + "go.uber.org/zap" + + "github.com/transcom/mymove/pkg/appcontext" + "github.com/transcom/mymove/pkg/gen/adminapi/adminoperations/rejected_office_users" + "github.com/transcom/mymove/pkg/gen/adminmessages" + "github.com/transcom/mymove/pkg/handlers" + "github.com/transcom/mymove/pkg/models" + "github.com/transcom/mymove/pkg/services" + "github.com/transcom/mymove/pkg/services/query" +) + +func payloadForRejectedOfficeUserModel(o models.OfficeUser) *adminmessages.OfficeUser { + var user models.User + if o.UserID != nil { + user = o.User + } + + payload := &adminmessages.OfficeUser{ + ID: handlers.FmtUUID(o.ID), + FirstName: handlers.FmtString(o.FirstName), + MiddleInitials: handlers.FmtStringPtr(o.MiddleInitials), + LastName: handlers.FmtString(o.LastName), + Telephone: handlers.FmtString(o.Telephone), + Email: handlers.FmtString(o.Email), + TransportationOfficeID: handlers.FmtUUID(o.TransportationOfficeID), + Active: handlers.FmtBool(o.Active), + Status: (*string)(o.Status), + Edipi: handlers.FmtStringPtr(o.EDIPI), + OtherUniqueID: handlers.FmtStringPtr(o.OtherUniqueID), + RejectionReason: handlers.FmtStringPtr(o.RejectionReason), + CreatedAt: *handlers.FmtDateTime(o.CreatedAt), + UpdatedAt: *handlers.FmtDateTime(o.UpdatedAt), + RejectedOn: *handlers.FmtDateTime(o.RejectedOn), + DeletedOn: *handlers.FmtDateTime(o.DeletedOn), + } + + if o.UserID != nil { + userIDFmt := handlers.FmtUUID(*o.UserID) + if userIDFmt != nil { + payload.UserID = *userIDFmt + } + } + for _, role := range user.Roles { + payload.Roles = append(payload.Roles, payloadForRole(role)) + } + return payload +} + +// IndexRejectedOfficeUsersHandler returns a list of rejected office users via GET /rejected_office_users +type IndexRejectedOfficeUsersHandler struct { + handlers.HandlerConfig + services.RejectedOfficeUserListFetcher + services.NewQueryFilter + services.NewPagination +} + +var rejectedOfficeUserFilterConverters = map[string]func(string) []services.QueryFilter{ + "search": func(content string) []services.QueryFilter { + nameSearch := fmt.Sprintf("%s%%", content) + return []services.QueryFilter{ + query.NewQueryFilter("email", "ILIKE", fmt.Sprintf("%%%s%%", content)), + query.NewQueryFilter("first_name", "ILIKE", nameSearch), + query.NewQueryFilter("last_name", "ILIKE", nameSearch), + } + }, +} + +// Handle retrieves a list of rejected office users +func (h IndexRejectedOfficeUsersHandler) Handle(params rejected_office_users.IndexRejectedOfficeUsersParams) middleware.Responder { + return h.AuditableAppContextFromRequestWithErrors(params.HTTPRequest, + func(appCtx appcontext.AppContext) (middleware.Responder, error) { + + // adding in filters for when a search or filtering is done + queryFilters := generateQueryFilters(appCtx.Logger(), params.Filter, rejectedOfficeUserFilterConverters) + + // We only want users that are in a REJECTED status + queryFilters = append(queryFilters, query.NewQueryFilter("status", "=", "REJECTED")) + + // adding in pagination for the UI + pagination := h.NewPagination(params.Page, params.PerPage) + ordering := query.NewQueryOrder(params.Sort, params.Order) + + // need to also get the user's roles + queryAssociations := query.NewQueryAssociationsPreload([]services.QueryAssociation{ + query.NewQueryAssociation("User.Roles"), + }) + + officeUsers, err := h.RejectedOfficeUserListFetcher.FetchRejectedOfficeUsersList(appCtx, queryFilters, queryAssociations, pagination, ordering) + if err != nil { + return handlers.ResponseForError(appCtx.Logger(), err), err + } + + totalOfficeUsersCount, err := h.RejectedOfficeUserListFetcher.FetchRejectedOfficeUsersCount(appCtx, queryFilters) + if err != nil { + return handlers.ResponseForError(appCtx.Logger(), err), err + } + + queriedOfficeUsersCount := len(officeUsers) + + payload := make(adminmessages.OfficeUsers, queriedOfficeUsersCount) + + for i, s := range officeUsers { + payload[i] = payloadForRejectedOfficeUserModel(s) + } + + return rejected_office_users.NewIndexRejectedOfficeUsersOK().WithContentRange(fmt.Sprintf("rejected office users %d-%d/%d", pagination.Offset(), pagination.Offset()+queriedOfficeUsersCount, totalOfficeUsersCount)).WithPayload(payload), nil + }) +} + +// GetRejectedOfficeUserHandler returns a list of office users via GET /rejected_office_users/{officeUserId} +type GetRejectedOfficeUserHandler struct { + handlers.HandlerConfig + services.RejectedOfficeUserFetcher + services.RoleAssociater + services.NewQueryFilter +} + +// Handle retrieves a single rejected office user +func (h GetRejectedOfficeUserHandler) Handle(params rejected_office_users.GetRejectedOfficeUserParams) middleware.Responder { + return h.AuditableAppContextFromRequestWithErrors(params.HTTPRequest, + func(appCtx appcontext.AppContext) (middleware.Responder, error) { + + rejectedOfficeUserID := params.OfficeUserID + + queryFilters := []services.QueryFilter{query.NewQueryFilter("id", "=", rejectedOfficeUserID)} + rejectedOfficeUser, err := h.RejectedOfficeUserFetcher.FetchRejectedOfficeUser(appCtx, queryFilters) + + if err != nil { + return handlers.ResponseForError(appCtx.Logger(), err), err + } + + roles, err := h.RoleAssociater.FetchRolesForUser(appCtx, *rejectedOfficeUser.UserID) + if err != nil { + appCtx.Logger().Error("Error fetching user roles", zap.Error(err)) + return rejected_office_users.NewGetRejectedOfficeUserBadRequest(), err + } + + rejectedOfficeUser.User.Roles = roles + + payload := payloadForRejectedOfficeUserModel(rejectedOfficeUser) + + return rejected_office_users.NewGetRejectedOfficeUserOK().WithPayload(payload), nil + }) +} diff --git a/pkg/handlers/adminapi/rejected_office_users_test.go b/pkg/handlers/adminapi/rejected_office_users_test.go new file mode 100644 index 00000000000..d215ef6d7d7 --- /dev/null +++ b/pkg/handlers/adminapi/rejected_office_users_test.go @@ -0,0 +1,180 @@ +package adminapi + +import ( + "fmt" + "net/http" + "time" + + "github.com/go-openapi/strfmt" + "github.com/gofrs/uuid" + "github.com/stretchr/testify/mock" + + "github.com/transcom/mymove/pkg/factory" + rejectedofficeuserop "github.com/transcom/mymove/pkg/gen/adminapi/adminoperations/rejected_office_users" + "github.com/transcom/mymove/pkg/handlers" + "github.com/transcom/mymove/pkg/models" + "github.com/transcom/mymove/pkg/models/roles" + "github.com/transcom/mymove/pkg/services/mocks" + "github.com/transcom/mymove/pkg/services/pagination" + "github.com/transcom/mymove/pkg/services/query" + rejectedofficeusers "github.com/transcom/mymove/pkg/services/rejected_office_users" +) + +func (suite *HandlerSuite) TestIndexRejectedOfficeUsersHandler() { + // test that everything is wired up + suite.Run("rejected users result in ok response", func() { + // building two office user with rejected status + rejectedOfficeUsers := models.OfficeUsers{ + factory.BuildOfficeUserWithRoles(suite.DB(), factory.GetTraitRejectedOfficeUser(), []roles.RoleType{roles.RoleTypeQae}), + factory.BuildOfficeUserWithRoles(suite.DB(), factory.GetTraitRejectedOfficeUser(), []roles.RoleType{roles.RoleTypeQae})} + params := rejectedofficeuserop.IndexRejectedOfficeUsersParams{ + HTTPRequest: suite.setupAuthenticatedRequest("GET", "/rejected_office_users"), + } + + queryBuilder := query.NewQueryBuilder() + handler := IndexRejectedOfficeUsersHandler{ + HandlerConfig: suite.HandlerConfig(), + NewQueryFilter: query.NewQueryFilter, + RejectedOfficeUserListFetcher: rejectedofficeusers.NewRejectedOfficeUsersListFetcher(queryBuilder), + NewPagination: pagination.NewPagination, + } + + response := handler.Handle(params) + + // should get an ok response + suite.IsType(&rejectedofficeuserop.IndexRejectedOfficeUsersOK{}, response) + okResponse := response.(*rejectedofficeuserop.IndexRejectedOfficeUsersOK) + suite.Len(okResponse.Payload, 2) + suite.Equal(rejectedOfficeUsers[0].ID.String(), okResponse.Payload[0].ID.String()) + }) +} + +func (suite *HandlerSuite) TestGetRejectedOfficeUserHandler() { + // test that everything is wired up + suite.Run("integration test ok response", func() { + rejectedOfficeUser := factory.BuildOfficeUserWithRoles(suite.DB(), factory.GetTraitRejectedOfficeUser(), []roles.RoleType{roles.RoleTypeQae}) + params := rejectedofficeuserop.GetRejectedOfficeUserParams{ + HTTPRequest: suite.setupAuthenticatedRequest("GET", fmt.Sprintf("/rejected_office_users/%s", rejectedOfficeUser.ID)), + OfficeUserID: strfmt.UUID(rejectedOfficeUser.ID.String()), + } + + mockRoleAssociator := &mocks.RoleAssociater{} + mockRoles := roles.Roles{ + roles.Role{ + ID: uuid.Must(uuid.NewV4()), + RoleType: roles.RoleTypeTOO, + RoleName: "Task Ordering Officer", + CreatedAt: time.Now(), + UpdatedAt: time.Now(), + }, + } + mockRoleAssociator.On( + "FetchRolesForUser", + mock.AnythingOfType("*appcontext.appContext"), + mock.Anything, + ).Return(mockRoles, nil) + + queryBuilder := query.NewQueryBuilder() + handler := GetRejectedOfficeUserHandler{ + suite.HandlerConfig(), + rejectedofficeusers.NewRejectedOfficeUserFetcher(queryBuilder), + mockRoleAssociator, + query.NewQueryFilter, + } + + response := handler.Handle(params) + + suite.IsType(&rejectedofficeuserop.GetRejectedOfficeUserOK{}, response) + okResponse := response.(*rejectedofficeuserop.GetRejectedOfficeUserOK) + suite.Equal(rejectedOfficeUser.ID.String(), okResponse.Payload.ID.String()) + }) + + suite.Run("successful response", func() { + rejectedOfficeUser := factory.BuildOfficeUserWithRoles(suite.DB(), factory.GetTraitRejectedOfficeUser(), []roles.RoleType{roles.RoleTypeQae}) + params := rejectedofficeuserop.GetRejectedOfficeUserParams{ + HTTPRequest: suite.setupAuthenticatedRequest("GET", fmt.Sprintf("/rejected_office_users/%s", rejectedOfficeUser.ID)), + OfficeUserID: strfmt.UUID(rejectedOfficeUser.ID.String()), + } + + rejectedOfficeUserFetcher := &mocks.RejectedOfficeUserFetcher{} + rejectedOfficeUserFetcher.On("FetchRejectedOfficeUser", + mock.AnythingOfType("*appcontext.appContext"), + mock.Anything, + ).Return(rejectedOfficeUser, nil).Once() + + mockRoleAssociator := &mocks.RoleAssociater{} + mockRoles := roles.Roles{ + roles.Role{ + ID: uuid.Must(uuid.NewV4()), + RoleType: roles.RoleTypeTOO, + RoleName: "Task Ordering Officer", + CreatedAt: time.Now(), + UpdatedAt: time.Now(), + }, + } + mockRoleAssociator.On( + "FetchRolesForUser", + mock.AnythingOfType("*appcontext.appContext"), + mock.Anything, + ).Return(mockRoles, nil) + + handler := GetRejectedOfficeUserHandler{ + suite.HandlerConfig(), + rejectedOfficeUserFetcher, + mockRoleAssociator, + newMockQueryFilterBuilder(&mocks.QueryFilter{}), + } + + response := handler.Handle(params) + + suite.IsType(&rejectedofficeuserop.GetRejectedOfficeUserOK{}, response) + okResponse := response.(*rejectedofficeuserop.GetRejectedOfficeUserOK) + suite.Equal(rejectedOfficeUser.ID.String(), okResponse.Payload.ID.String()) + }) + + suite.Run("unsuccessful response when fetch fails", func() { + rejectedOfficeUser := factory.BuildOfficeUserWithRoles(suite.DB(), factory.GetTraitRejectedOfficeUser(), []roles.RoleType{roles.RoleTypeQae}) + params := rejectedofficeuserop.GetRejectedOfficeUserParams{ + HTTPRequest: suite.setupAuthenticatedRequest("GET", fmt.Sprintf("/rejected_office_users/%s", rejectedOfficeUser.ID)), + OfficeUserID: strfmt.UUID(rejectedOfficeUser.ID.String()), + } + + expectedError := models.ErrFetchNotFound + rejectedOfficeUserFetcher := &mocks.RejectedOfficeUserFetcher{} + rejectedOfficeUserFetcher.On("FetchRejectedOfficeUser", + mock.AnythingOfType("*appcontext.appContext"), + mock.Anything, + ).Return(models.OfficeUser{}, expectedError).Once() + + mockRoleAssociator := &mocks.RoleAssociater{} + mockRoles := roles.Roles{ + roles.Role{ + ID: uuid.Must(uuid.NewV4()), + RoleType: roles.RoleTypeTOO, + RoleName: "Task Ordering Officer", + CreatedAt: time.Now(), + UpdatedAt: time.Now(), + }, + } + mockRoleAssociator.On( + "FetchRolesForUser", + mock.AnythingOfType("*appcontext.appContext"), + mock.Anything, + ).Return(mockRoles, nil) + + handler := GetRejectedOfficeUserHandler{ + suite.HandlerConfig(), + rejectedOfficeUserFetcher, + mockRoleAssociator, + newMockQueryFilterBuilder(&mocks.QueryFilter{}), + } + + response := handler.Handle(params) + + expectedResponse := &handlers.ErrResponse{ + Code: http.StatusNotFound, + Err: expectedError, + } + suite.Equal(expectedResponse, response) + }) +} diff --git a/pkg/models/office_user.go b/pkg/models/office_user.go index e07fda465a4..9bf9ed9bea2 100644 --- a/pkg/models/office_user.go +++ b/pkg/models/office_user.go @@ -42,8 +42,8 @@ type OfficeUser struct { EDIPI *string `json:"edipi" db:"edipi"` OtherUniqueID *string `json:"other_unique_id" db:"other_unique_id"` RejectionReason *string `json:"rejection_reason" db:"rejection_reason"` - RejectedOn *string `json:"rejected_on" db:"rejected_on"` - DeletedOn *string `json:"deleted_on" db:"deleted_on"` + RejectedOn time.Time `json:"rejected_on" db:"rejected_on"` + DeletedOn time.Time `json:"deleted_on" db:"deleted_on"` } type OfficeUserWithWorkload struct { diff --git a/pkg/services/mocks/RejectedOfficeUserFetcher.go b/pkg/services/mocks/RejectedOfficeUserFetcher.go new file mode 100644 index 00000000000..72a869d5e0e --- /dev/null +++ b/pkg/services/mocks/RejectedOfficeUserFetcher.go @@ -0,0 +1,59 @@ +// Code generated by mockery. DO NOT EDIT. + +package mocks + +import ( + mock "github.com/stretchr/testify/mock" + appcontext "github.com/transcom/mymove/pkg/appcontext" + + models "github.com/transcom/mymove/pkg/models" + + services "github.com/transcom/mymove/pkg/services" +) + +// RejectedOfficeUserFetcher is an autogenerated mock type for the RejectedOfficeUserFetcher type +type RejectedOfficeUserFetcher struct { + mock.Mock +} + +// FetchRejectedOfficeUser provides a mock function with given fields: appCtx, filters +func (_m *RejectedOfficeUserFetcher) FetchRejectedOfficeUser(appCtx appcontext.AppContext, filters []services.QueryFilter) (models.OfficeUser, error) { + ret := _m.Called(appCtx, filters) + + if len(ret) == 0 { + panic("no return value specified for FetchRejectedOfficeUser") + } + + var r0 models.OfficeUser + var r1 error + if rf, ok := ret.Get(0).(func(appcontext.AppContext, []services.QueryFilter) (models.OfficeUser, error)); ok { + return rf(appCtx, filters) + } + if rf, ok := ret.Get(0).(func(appcontext.AppContext, []services.QueryFilter) models.OfficeUser); ok { + r0 = rf(appCtx, filters) + } else { + r0 = ret.Get(0).(models.OfficeUser) + } + + if rf, ok := ret.Get(1).(func(appcontext.AppContext, []services.QueryFilter) error); ok { + r1 = rf(appCtx, filters) + } else { + r1 = ret.Error(1) + } + + return r0, r1 +} + +// NewRejectedOfficeUserFetcher creates a new instance of RejectedOfficeUserFetcher. It also registers a testing interface on the mock and a cleanup function to assert the mocks expectations. +// The first argument is typically a *testing.T value. +func NewRejectedOfficeUserFetcher(t interface { + mock.TestingT + Cleanup(func()) +}) *RejectedOfficeUserFetcher { + mock := &RejectedOfficeUserFetcher{} + mock.Mock.Test(t) + + t.Cleanup(func() { mock.AssertExpectations(t) }) + + return mock +} diff --git a/pkg/services/mocks/RejectedOfficeUserFetcherPop.go b/pkg/services/mocks/RejectedOfficeUserFetcherPop.go new file mode 100644 index 00000000000..1a413118434 --- /dev/null +++ b/pkg/services/mocks/RejectedOfficeUserFetcherPop.go @@ -0,0 +1,59 @@ +// Code generated by mockery. DO NOT EDIT. + +package mocks + +import ( + mock "github.com/stretchr/testify/mock" + appcontext "github.com/transcom/mymove/pkg/appcontext" + + models "github.com/transcom/mymove/pkg/models" + + uuid "github.com/gofrs/uuid" +) + +// RejectedOfficeUserFetcherPop is an autogenerated mock type for the RejectedOfficeUserFetcherPop type +type RejectedOfficeUserFetcherPop struct { + mock.Mock +} + +// FetchRejectedOfficeUserByID provides a mock function with given fields: appCtx, id +func (_m *RejectedOfficeUserFetcherPop) FetchRejectedOfficeUserByID(appCtx appcontext.AppContext, id uuid.UUID) (models.OfficeUser, error) { + ret := _m.Called(appCtx, id) + + if len(ret) == 0 { + panic("no return value specified for FetchRejectedOfficeUserByID") + } + + var r0 models.OfficeUser + var r1 error + if rf, ok := ret.Get(0).(func(appcontext.AppContext, uuid.UUID) (models.OfficeUser, error)); ok { + return rf(appCtx, id) + } + if rf, ok := ret.Get(0).(func(appcontext.AppContext, uuid.UUID) models.OfficeUser); ok { + r0 = rf(appCtx, id) + } else { + r0 = ret.Get(0).(models.OfficeUser) + } + + if rf, ok := ret.Get(1).(func(appcontext.AppContext, uuid.UUID) error); ok { + r1 = rf(appCtx, id) + } else { + r1 = ret.Error(1) + } + + return r0, r1 +} + +// NewRejectedOfficeUserFetcherPop creates a new instance of RejectedOfficeUserFetcherPop. It also registers a testing interface on the mock and a cleanup function to assert the mocks expectations. +// The first argument is typically a *testing.T value. +func NewRejectedOfficeUserFetcherPop(t interface { + mock.TestingT + Cleanup(func()) +}) *RejectedOfficeUserFetcherPop { + mock := &RejectedOfficeUserFetcherPop{} + mock.Mock.Test(t) + + t.Cleanup(func() { mock.AssertExpectations(t) }) + + return mock +} diff --git a/pkg/services/mocks/RejectedOfficeUserListFetcher.go b/pkg/services/mocks/RejectedOfficeUserListFetcher.go new file mode 100644 index 00000000000..6c998167d98 --- /dev/null +++ b/pkg/services/mocks/RejectedOfficeUserListFetcher.go @@ -0,0 +1,89 @@ +// Code generated by mockery. DO NOT EDIT. + +package mocks + +import ( + mock "github.com/stretchr/testify/mock" + appcontext "github.com/transcom/mymove/pkg/appcontext" + + models "github.com/transcom/mymove/pkg/models" + + services "github.com/transcom/mymove/pkg/services" +) + +// RejectedOfficeUserListFetcher is an autogenerated mock type for the RejectedOfficeUserListFetcher type +type RejectedOfficeUserListFetcher struct { + mock.Mock +} + +// FetchRejectedOfficeUsersCount provides a mock function with given fields: appCtx, filters +func (_m *RejectedOfficeUserListFetcher) FetchRejectedOfficeUsersCount(appCtx appcontext.AppContext, filters []services.QueryFilter) (int, error) { + ret := _m.Called(appCtx, filters) + + if len(ret) == 0 { + panic("no return value specified for FetchRejectedOfficeUsersCount") + } + + var r0 int + var r1 error + if rf, ok := ret.Get(0).(func(appcontext.AppContext, []services.QueryFilter) (int, error)); ok { + return rf(appCtx, filters) + } + if rf, ok := ret.Get(0).(func(appcontext.AppContext, []services.QueryFilter) int); ok { + r0 = rf(appCtx, filters) + } else { + r0 = ret.Get(0).(int) + } + + if rf, ok := ret.Get(1).(func(appcontext.AppContext, []services.QueryFilter) error); ok { + r1 = rf(appCtx, filters) + } else { + r1 = ret.Error(1) + } + + return r0, r1 +} + +// FetchRejectedOfficeUsersList provides a mock function with given fields: appCtx, filters, associations, pagination, ordering +func (_m *RejectedOfficeUserListFetcher) FetchRejectedOfficeUsersList(appCtx appcontext.AppContext, filters []services.QueryFilter, associations services.QueryAssociations, pagination services.Pagination, ordering services.QueryOrder) (models.OfficeUsers, error) { + ret := _m.Called(appCtx, filters, associations, pagination, ordering) + + if len(ret) == 0 { + panic("no return value specified for FetchRejectedOfficeUsersList") + } + + var r0 models.OfficeUsers + var r1 error + if rf, ok := ret.Get(0).(func(appcontext.AppContext, []services.QueryFilter, services.QueryAssociations, services.Pagination, services.QueryOrder) (models.OfficeUsers, error)); ok { + return rf(appCtx, filters, associations, pagination, ordering) + } + if rf, ok := ret.Get(0).(func(appcontext.AppContext, []services.QueryFilter, services.QueryAssociations, services.Pagination, services.QueryOrder) models.OfficeUsers); ok { + r0 = rf(appCtx, filters, associations, pagination, ordering) + } else { + if ret.Get(0) != nil { + r0 = ret.Get(0).(models.OfficeUsers) + } + } + + if rf, ok := ret.Get(1).(func(appcontext.AppContext, []services.QueryFilter, services.QueryAssociations, services.Pagination, services.QueryOrder) error); ok { + r1 = rf(appCtx, filters, associations, pagination, ordering) + } else { + r1 = ret.Error(1) + } + + return r0, r1 +} + +// NewRejectedOfficeUserListFetcher creates a new instance of RejectedOfficeUserListFetcher. It also registers a testing interface on the mock and a cleanup function to assert the mocks expectations. +// The first argument is typically a *testing.T value. +func NewRejectedOfficeUserListFetcher(t interface { + mock.TestingT + Cleanup(func()) +}) *RejectedOfficeUserListFetcher { + mock := &RejectedOfficeUserListFetcher{} + mock.Mock.Test(t) + + t.Cleanup(func() { mock.AssertExpectations(t) }) + + return mock +} diff --git a/pkg/services/rejected_office_users.go b/pkg/services/rejected_office_users.go new file mode 100644 index 00000000000..fe1ba485a0b --- /dev/null +++ b/pkg/services/rejected_office_users.go @@ -0,0 +1,30 @@ +package services + +import ( + "github.com/gofrs/uuid" + + "github.com/transcom/mymove/pkg/appcontext" + "github.com/transcom/mymove/pkg/models" +) + +// RejectedOfficeUserListFetcher is the exported interface for fetching multiple rejected rejected office users +// +//go:generate mockery --name RejectedOfficeUserListFetcher +type RejectedOfficeUserListFetcher interface { + FetchRejectedOfficeUsersList(appCtx appcontext.AppContext, filters []QueryFilter, associations QueryAssociations, pagination Pagination, ordering QueryOrder) (models.OfficeUsers, error) + FetchRejectedOfficeUsersCount(appCtx appcontext.AppContext, filters []QueryFilter) (int, error) +} + +// RejectedOfficeUserFetcher is the exported interface for fetching a single rejected rejected office user +// +//go:generate mockery --name RejectedOfficeUserFetcher +type RejectedOfficeUserFetcher interface { + FetchRejectedOfficeUser(appCtx appcontext.AppContext, filters []QueryFilter) (models.OfficeUser, error) +} + +// RejectedOfficeUserFetcherPop is the exported interface for fetching a single office user +// +//go:generate mockery --name RejectedOfficeUserFetcherPop +type RejectedOfficeUserFetcherPop interface { + FetchRejectedOfficeUserByID(appCtx appcontext.AppContext, id uuid.UUID) (models.OfficeUser, error) +} diff --git a/pkg/services/rejected_office_users/rejected_office_user_fetcher.go b/pkg/services/rejected_office_users/rejected_office_user_fetcher.go new file mode 100644 index 00000000000..ca24b44d5b1 --- /dev/null +++ b/pkg/services/rejected_office_users/rejected_office_user_fetcher.go @@ -0,0 +1,58 @@ +package adminuser + +import ( + "database/sql" + + "github.com/gobuffalo/validate/v3" + "github.com/gofrs/uuid" + + "github.com/transcom/mymove/pkg/appcontext" + "github.com/transcom/mymove/pkg/apperror" + "github.com/transcom/mymove/pkg/models" + "github.com/transcom/mymove/pkg/services" +) + +type rejectedOfficeUserQueryBuilder interface { + FetchOne(appCtx appcontext.AppContext, model interface{}, filters []services.QueryFilter) error + UpdateOne(appCtx appcontext.AppContext, model interface{}, eTag *string) (*validate.Errors, error) +} + +type rejectedOfficeUserFetcher struct { + builder rejectedOfficeUserQueryBuilder +} + +// FetchRejectedOfficeUser fetches an office user given a slice of filters +func (o *rejectedOfficeUserFetcher) FetchRejectedOfficeUser(appCtx appcontext.AppContext, filters []services.QueryFilter) (models.OfficeUser, error) { + var rejectedOfficeUser models.OfficeUser + err := o.builder.FetchOne(appCtx, &rejectedOfficeUser, filters) + return rejectedOfficeUser, err +} + +// NewAdminUserFetcher return an implementation of the AdminUserFetcher interface +func NewRejectedOfficeUserFetcher(builder rejectedOfficeUserQueryBuilder) services.RejectedOfficeUserFetcher { + return &rejectedOfficeUserFetcher{builder} +} + +type rejectedOfficeUserFetcherPop struct { +} + +// FetchOfficeUserByID fetches an office user given an ID +func (o *rejectedOfficeUserFetcherPop) FetchRejectedOfficeUserByID(appCtx appcontext.AppContext, id uuid.UUID) (models.OfficeUser, error) { + var officeUser models.OfficeUser + err := appCtx.DB().Eager("TransportationOffice").Find(&officeUser, id) + if err != nil { + switch err { + case sql.ErrNoRows: + return models.OfficeUser{}, apperror.NewNotFoundError(id, "looking for OfficeUser") + default: + return models.OfficeUser{}, apperror.NewQueryError("OfficeUser", err, "") + } + } + + return officeUser, err +} + +// NewOfficeUserFetcherPop return an implementation of the OfficeUserFetcherPop interface +func NewRejectedOfficeUserFetcherPop() services.RejectedOfficeUserFetcherPop { + return &rejectedOfficeUserFetcherPop{} +} diff --git a/pkg/services/rejected_office_users/rejected_office_user_fetcher_test.go b/pkg/services/rejected_office_users/rejected_office_user_fetcher_test.go new file mode 100644 index 00000000000..5ac38aae67f --- /dev/null +++ b/pkg/services/rejected_office_users/rejected_office_user_fetcher_test.go @@ -0,0 +1,90 @@ +package adminuser + +import ( + "errors" + "reflect" + + "github.com/gobuffalo/validate/v3" + "github.com/gofrs/uuid" + + "github.com/transcom/mymove/pkg/appcontext" + "github.com/transcom/mymove/pkg/apperror" + "github.com/transcom/mymove/pkg/factory" + "github.com/transcom/mymove/pkg/models" + "github.com/transcom/mymove/pkg/models/roles" + "github.com/transcom/mymove/pkg/services" + "github.com/transcom/mymove/pkg/services/query" +) + +type testRejectedOfficeUsersQueryBuilder struct { + fakeFetchOne func(appConfig appcontext.AppContext, model interface{}) error +} + +func (t *testRejectedOfficeUsersQueryBuilder) FetchOne(appConfig appcontext.AppContext, model interface{}, _ []services.QueryFilter) error { + m := t.fakeFetchOne(appConfig, model) + return m +} + +func (t *testRejectedOfficeUsersQueryBuilder) UpdateOne(_ appcontext.AppContext, _ interface{}, _ *string) (*validate.Errors, error) { + return nil, nil +} + +func (suite *RejectedOfficeUsersServiceSuite) TestFetchRejectedOfficeUser() { + suite.Run("if the rejected office user is fetched, it should be returned", func() { + id, err := uuid.NewV4() + suite.NoError(err) + fakeFetchOne := func(_ appcontext.AppContext, model interface{}) error { + reflect.ValueOf(model).Elem().FieldByName("ID").Set(reflect.ValueOf(id)) + return nil + } + + builder := &testRejectedOfficeUsersQueryBuilder{ + fakeFetchOne: fakeFetchOne, + } + + fetcher := NewRejectedOfficeUserFetcher(builder) + filters := []services.QueryFilter{query.NewQueryFilter("id", "=", id.String())} + + rejectedOfficeUser, err := fetcher.FetchRejectedOfficeUser(suite.AppContextForTest(), filters) + + suite.NoError(err) + suite.Equal(id, rejectedOfficeUser.ID) + }) + + suite.Run("if there is an error, we get it with zero admin user", func() { + fakeFetchOne := func(_ appcontext.AppContext, _ interface{}) error { + return errors.New("Fetch error") + } + builder := &testRejectedOfficeUsersQueryBuilder{ + fakeFetchOne: fakeFetchOne, + } + fetcher := NewRejectedOfficeUserFetcher(builder) + + rejectedOfficeUser, err := fetcher.FetchRejectedOfficeUser(suite.AppContextForTest(), []services.QueryFilter{}) + + suite.Error(err) + suite.Equal(err.Error(), "Fetch error") + suite.Equal(models.OfficeUser{}, rejectedOfficeUser) + }) +} + +func (suite *RejectedOfficeUsersServiceSuite) TestFetchRejectedOfficeUserPop() { + suite.Run("returns office user on success", func() { + officeUser := factory.BuildOfficeUserWithRoles(suite.DB(), nil, []roles.RoleType{roles.RoleTypeTOO}) + fetcher := NewRejectedOfficeUserFetcherPop() + + fetchedUser, err := fetcher.FetchRejectedOfficeUserByID(suite.AppContextForTest(), officeUser.ID) + + suite.NoError(err) + suite.Equal(officeUser.ID, fetchedUser.ID) + }) + + suite.Run("returns zero value office user on error", func() { + fetcher := NewRejectedOfficeUserFetcherPop() + officeUser, err := fetcher.FetchRejectedOfficeUserByID(suite.AppContextForTest(), uuid.Nil) + + suite.Error(err) + suite.IsType(apperror.NotFoundError{}, err) + suite.Equal(uuid.Nil, officeUser.ID) + }) +} diff --git a/pkg/services/rejected_office_users/rejected_office_user_service_test.go b/pkg/services/rejected_office_users/rejected_office_user_service_test.go new file mode 100644 index 00000000000..f474a2d6af9 --- /dev/null +++ b/pkg/services/rejected_office_users/rejected_office_user_service_test.go @@ -0,0 +1,22 @@ +package adminuser + +import ( + "testing" + + "github.com/stretchr/testify/suite" + + "github.com/transcom/mymove/pkg/testingsuite" +) + +type RejectedOfficeUsersServiceSuite struct { + *testingsuite.PopTestSuite +} + +func TestUserSuite(t *testing.T) { + + ts := &RejectedOfficeUsersServiceSuite{ + PopTestSuite: testingsuite.NewPopTestSuite(testingsuite.CurrentPackage(), testingsuite.WithPerTestTransaction()), + } + suite.Run(t, ts) + ts.PopTestSuite.TearDown() +} diff --git a/pkg/services/rejected_office_users/rejected_office_users_list_fetcher.go b/pkg/services/rejected_office_users/rejected_office_users_list_fetcher.go new file mode 100644 index 00000000000..9445ebbd0b3 --- /dev/null +++ b/pkg/services/rejected_office_users/rejected_office_users_list_fetcher.go @@ -0,0 +1,35 @@ +package adminuser + +import ( + "github.com/transcom/mymove/pkg/appcontext" + "github.com/transcom/mymove/pkg/models" + "github.com/transcom/mymove/pkg/services" +) + +type rejectedOfficeUsersListQueryBuilder interface { + FetchMany(appCtx appcontext.AppContext, model interface{}, filters []services.QueryFilter, associations services.QueryAssociations, pagination services.Pagination, ordering services.QueryOrder) error + Count(appCtx appcontext.AppContext, model interface{}, filters []services.QueryFilter) (int, error) +} + +type rejectedOfficeUserListFetcher struct { + builder rejectedOfficeUsersListQueryBuilder +} + +// FetchAdminUserList uses the passed query builder to fetch a list of office users +func (o *rejectedOfficeUserListFetcher) FetchRejectedOfficeUsersList(appCtx appcontext.AppContext, filters []services.QueryFilter, associations services.QueryAssociations, pagination services.Pagination, ordering services.QueryOrder) (models.OfficeUsers, error) { + var rejectedUsers models.OfficeUsers + err := o.builder.FetchMany(appCtx, &rejectedUsers, filters, associations, pagination, ordering) + return rejectedUsers, err +} + +// FetchAdminUserList uses the passed query builder to fetch a list of office users +func (o *rejectedOfficeUserListFetcher) FetchRejectedOfficeUsersCount(appCtx appcontext.AppContext, filters []services.QueryFilter) (int, error) { + var rejectedUsers models.OfficeUsers + count, err := o.builder.Count(appCtx, &rejectedUsers, filters) + return count, err +} + +// NewAdminUserListFetcher returns an implementation of AdminUserListFetcher +func NewRejectedOfficeUsersListFetcher(builder rejectedOfficeUsersListQueryBuilder) services.RejectedOfficeUserListFetcher { + return &rejectedOfficeUserListFetcher{builder} +} diff --git a/pkg/services/rejected_office_users/rejected_office_users_list_fetcher_test.go b/pkg/services/rejected_office_users/rejected_office_users_list_fetcher_test.go new file mode 100644 index 00000000000..ace816aeeb1 --- /dev/null +++ b/pkg/services/rejected_office_users/rejected_office_users_list_fetcher_test.go @@ -0,0 +1,82 @@ +package adminuser + +import ( + "errors" + "reflect" + + "github.com/gofrs/uuid" + + "github.com/transcom/mymove/pkg/appcontext" + "github.com/transcom/mymove/pkg/models" + "github.com/transcom/mymove/pkg/services" + "github.com/transcom/mymove/pkg/services/pagination" + "github.com/transcom/mymove/pkg/services/query" +) + +type testRejectedOfficeUsersListQueryBuilder struct { + fakeFetchMany func(appCtx appcontext.AppContext, model interface{}) error + fakeCount func(appCtx appcontext.AppContext, model interface{}) (int, error) +} + +func (t *testRejectedOfficeUsersListQueryBuilder) FetchMany(appCtx appcontext.AppContext, model interface{}, _ []services.QueryFilter, _ services.QueryAssociations, _ services.Pagination, _ services.QueryOrder) error { + m := t.fakeFetchMany(appCtx, model) + return m +} + +func (t *testRejectedOfficeUsersListQueryBuilder) Count(appCtx appcontext.AppContext, model interface{}, _ []services.QueryFilter) (int, error) { + count, m := t.fakeCount(appCtx, model) + return count, m +} + +func defaultPagination() services.Pagination { + page, perPage := pagination.DefaultPage(), pagination.DefaultPerPage() + return pagination.NewPagination(&page, &perPage) +} + +func defaultAssociations() services.QueryAssociations { + return query.NewQueryAssociations([]services.QueryAssociation{}) +} + +func defaultOrdering() services.QueryOrder { + return query.NewQueryOrder(nil, nil) +} + +func (suite *RejectedOfficeUsersServiceSuite) TestFetchRejectedOfficeUserList() { + suite.Run("if the users are successfully fetched, they should be returned", func() { + id, err := uuid.NewV4() + suite.NoError(err) + fakeFetchMany := func(_ appcontext.AppContext, model interface{}) error { + value := reflect.ValueOf(model).Elem() + rejectedStatus := models.OfficeUserStatusREJECTED + value.Set(reflect.Append(value, reflect.ValueOf(models.OfficeUser{ID: id, Status: &rejectedStatus}))) + return nil + } + builder := &testRejectedOfficeUsersListQueryBuilder{ + fakeFetchMany: fakeFetchMany, + } + + fetcher := NewRejectedOfficeUsersListFetcher(builder) + + rejectedOfficeUsers, err := fetcher.FetchRejectedOfficeUsersList(suite.AppContextForTest(), nil, defaultAssociations(), defaultPagination(), defaultOrdering()) + + suite.NoError(err) + suite.Equal(id, rejectedOfficeUsers[0].ID) + }) + + suite.Run("if there is an error, we get it with no rejected office users", func() { + fakeFetchMany := func(_ appcontext.AppContext, _ interface{}) error { + return errors.New("Fetch error") + } + builder := &testRejectedOfficeUsersListQueryBuilder{ + fakeFetchMany: fakeFetchMany, + } + + fetcher := NewRejectedOfficeUsersListFetcher(builder) + + rejectedOfficeUsers, err := fetcher.FetchRejectedOfficeUsersList(suite.AppContextForTest(), []services.QueryFilter{}, defaultAssociations(), defaultPagination(), defaultOrdering()) + + suite.Error(err) + suite.Equal(err.Error(), "Fetch error") + suite.Equal(models.OfficeUsers(nil), rejectedOfficeUsers) + }) +} From 3d188de8e25d8c43b5203b76a6233545a8f07337 Mon Sep 17 00:00:00 2001 From: KonstanceH Date: Tue, 28 Jan 2025 21:08:03 +0000 Subject: [PATCH 04/37] pause on frontend --- .../RejectedOfficeUserList.jsx | 43 +++++++++++++++++++ src/scenes/SystemAdmin/Home.jsx | 6 +++ 2 files changed, 49 insertions(+) create mode 100644 src/pages/Admin/RejectedOfficeUsers/RejectedOfficeUserList.jsx diff --git a/src/pages/Admin/RejectedOfficeUsers/RejectedOfficeUserList.jsx b/src/pages/Admin/RejectedOfficeUsers/RejectedOfficeUserList.jsx new file mode 100644 index 00000000000..c3b5426536b --- /dev/null +++ b/src/pages/Admin/RejectedOfficeUsers/RejectedOfficeUserList.jsx @@ -0,0 +1,43 @@ +import React from 'react'; +import { Datagrid, DateField, Filter, List, ReferenceField, TextField, TextInput, TopToolbar } from 'react-admin'; + +import AdminPagination from 'scenes/SystemAdmin/shared/AdminPagination'; + +// Overriding the default toolbar +const ListActions = () => { + return ; +}; + +const RejectedOfficeUserListFilter = () => ( + + + +); + +const defaultSort = { field: 'createdAt', order: 'DESC' }; + +const RejectedOfficeUserList = () => ( + } + perPage={25} + sort={defaultSort} + filters={} + actions={} + > + + + + + + + + + + + + + + +); + +export default RejectedOfficeUserList; diff --git a/src/scenes/SystemAdmin/Home.jsx b/src/scenes/SystemAdmin/Home.jsx index 09f1ca509d9..f5d774f5c35 100644 --- a/src/scenes/SystemAdmin/Home.jsx +++ b/src/scenes/SystemAdmin/Home.jsx @@ -42,6 +42,7 @@ import WebhookSubscriptionCreate from 'pages/Admin/WebhookSubscriptions/WebhookS import RequestedOfficeUserList from 'pages/Admin/RequestedOfficeUsers/RequestedOfficeUserList'; import RequestedOfficeUserShow from 'pages/Admin/RequestedOfficeUsers/RequestedOfficeUserShow'; import RequestedOfficeUserEdit from 'pages/Admin/RequestedOfficeUsers/RequestedOfficeUserEdit'; +import RejectedOfficeUserList from 'pages/Admin/RejectedOfficeUsers/RejectedOfficeUserList'; import PaymentRequest858List from 'pages/Admin/PaymentRequests/PaymentRequest858List'; import PaymentRequest858Show from 'pages/Admin/PaymentRequests/PaymentRequest858Show'; @@ -79,6 +80,11 @@ const Home = () => ( show={RequestedOfficeUserShow} edit={RequestedOfficeUserEdit} /> + Date: Wed, 29 Jan 2025 07:16:42 +0000 Subject: [PATCH 05/37] can see listed from ui. Need to fix data column and index test --- .../adminapi/rejected_office_users.go | 1 - pkg/models/office_user.go | 1 - .../requested_office_user_updater.go | 3 + .../RejectedOfficeUserList.jsx | 20 +++- .../RejectedOfficeUserShow.jsx | 98 +++++++++++++++++++ .../RejectedOfficeUserShow.module.scss | 53 ++++++++++ src/scenes/SystemAdmin/Home.jsx | 2 + 7 files changed, 173 insertions(+), 5 deletions(-) create mode 100644 src/pages/Admin/RejectedOfficeUsers/RejectedOfficeUserShow.jsx create mode 100644 src/pages/Admin/RejectedOfficeUsers/RejectedOfficeUserShow.module.scss diff --git a/pkg/handlers/adminapi/rejected_office_users.go b/pkg/handlers/adminapi/rejected_office_users.go index 9d28596cf3c..1c37338b5fd 100644 --- a/pkg/handlers/adminapi/rejected_office_users.go +++ b/pkg/handlers/adminapi/rejected_office_users.go @@ -37,7 +37,6 @@ func payloadForRejectedOfficeUserModel(o models.OfficeUser) *adminmessages.Offic CreatedAt: *handlers.FmtDateTime(o.CreatedAt), UpdatedAt: *handlers.FmtDateTime(o.UpdatedAt), RejectedOn: *handlers.FmtDateTime(o.RejectedOn), - DeletedOn: *handlers.FmtDateTime(o.DeletedOn), } if o.UserID != nil { diff --git a/pkg/models/office_user.go b/pkg/models/office_user.go index 9bf9ed9bea2..83988d15db0 100644 --- a/pkg/models/office_user.go +++ b/pkg/models/office_user.go @@ -43,7 +43,6 @@ type OfficeUser struct { OtherUniqueID *string `json:"other_unique_id" db:"other_unique_id"` RejectionReason *string `json:"rejection_reason" db:"rejection_reason"` RejectedOn time.Time `json:"rejected_on" db:"rejected_on"` - DeletedOn time.Time `json:"deleted_on" db:"deleted_on"` } type OfficeUserWithWorkload struct { diff --git a/pkg/services/requested_office_users/requested_office_user_updater.go b/pkg/services/requested_office_users/requested_office_user_updater.go index 4a3363290b8..2d950c8c5c5 100644 --- a/pkg/services/requested_office_users/requested_office_user_updater.go +++ b/pkg/services/requested_office_users/requested_office_user_updater.go @@ -1,6 +1,8 @@ package adminuser import ( + "time" + "github.com/gobuffalo/validate/v3" "github.com/gofrs/uuid" @@ -66,6 +68,7 @@ func (o *requestedOfficeUserUpdater) UpdateRequestedOfficeUser(appCtx appcontext if payload.RejectionReason != "" { officeUser.RejectionReason = &payload.RejectionReason + officeUser.RejectedOn = time.Now() } if payload.Status != "" { diff --git a/src/pages/Admin/RejectedOfficeUsers/RejectedOfficeUserList.jsx b/src/pages/Admin/RejectedOfficeUsers/RejectedOfficeUserList.jsx index c3b5426536b..4555bf2af91 100644 --- a/src/pages/Admin/RejectedOfficeUsers/RejectedOfficeUserList.jsx +++ b/src/pages/Admin/RejectedOfficeUsers/RejectedOfficeUserList.jsx @@ -1,5 +1,15 @@ import React from 'react'; -import { Datagrid, DateField, Filter, List, ReferenceField, TextField, TextInput, TopToolbar } from 'react-admin'; +import { + ArrayField, + Datagrid, + DateField, + Filter, + List, + ReferenceField, + TextField, + TextInput, + TopToolbar, +} from 'react-admin'; import AdminPagination from 'scenes/SystemAdmin/shared/AdminPagination'; @@ -33,9 +43,13 @@ const RejectedOfficeUserList = () => ( - - + + + + + + ); diff --git a/src/pages/Admin/RejectedOfficeUsers/RejectedOfficeUserShow.jsx b/src/pages/Admin/RejectedOfficeUsers/RejectedOfficeUserShow.jsx new file mode 100644 index 00000000000..54adb2c8099 --- /dev/null +++ b/src/pages/Admin/RejectedOfficeUsers/RejectedOfficeUserShow.jsx @@ -0,0 +1,98 @@ +import { Alert, Label, TextInput } from '@trussworks/react-uswds'; +import React, { useState } from 'react'; +import { + ArrayField, + Datagrid, + DateField, + ReferenceField, + Show, + SimpleShowLayout, + TextField, + useRecordContext, +} from 'react-admin'; + +import styles from './RejectedOfficeUserShow.module.scss'; + +const RejectedOfficeUserShowTitle = () => { + const record = useRecordContext(); + + return {`${record?.firstName} ${record?.lastName}`}; +}; + +const RejectedOfficeUserShowRoles = () => { + const record = useRecordContext(); + if (!record?.roles) return

This user has not rejected any roles.

; + + return ( + + Rejected roles: + + + + + ); +}; + +// renders server and rej reason alerts +// renders approve/reject/edit buttons +// handles logic of approving/rejecting user +const RejectedOfficeUserActionButtons = () => { + const [serverError] = useState(''); + const [rejectionReason, setRejectionReason] = useState(''); + const [rejectionReasonCheck, setRejectionReasonCheck] = useState(''); + + return ( + <> + {serverError && ( + + {serverError} + + )} + {rejectionReasonCheck && ( + + {rejectionReasonCheck} + + )} +
+ + { + setRejectionReason(e.target.value); + // removing error banner if text is entered + setRejectionReasonCheck(''); + }} + /> +
+ + ); +}; + +const RejectedOfficeUserShow = () => { + return ( + }> + + + + + + + + + + + + + + + + + + + + ); +}; + +export default RejectedOfficeUserShow; diff --git a/src/pages/Admin/RejectedOfficeUsers/RejectedOfficeUserShow.module.scss b/src/pages/Admin/RejectedOfficeUsers/RejectedOfficeUserShow.module.scss new file mode 100644 index 00000000000..b37e5801e46 --- /dev/null +++ b/src/pages/Admin/RejectedOfficeUsers/RejectedOfficeUserShow.module.scss @@ -0,0 +1,53 @@ +@import 'shared/styles/colors.scss'; + +.btnContainer { + display: flex; + justify-content: flex-start; + align-self: center; + gap: 10px; + + .approveBtn { + width: 125px; + margin-left: 15px; + background-color: $primary; + + &:active, + &:hover, + &:focus { + background-color: $primary; + opacity: 80%; + } + } + + .rejectBtn { + width: 125px; + background-color: $error; + + &:active, + &:hover, + &:focus { + background-color: $error; + opacity: 80%; + } + } +} + +.rejectionInput { + margin-left: 15px; + margin-bottom: 10px; +} + +.error { + width: auto; + background-color: $error; + margin-left: 15px; + margin-right: 15px; +} + +.rejErrorEdit { + width: auto; + background-color: $error; + margin-left: 15px; + margin-right: 15px; + margin-bottom: 10px; +} \ No newline at end of file diff --git a/src/scenes/SystemAdmin/Home.jsx b/src/scenes/SystemAdmin/Home.jsx index f5d774f5c35..b825c2656a6 100644 --- a/src/scenes/SystemAdmin/Home.jsx +++ b/src/scenes/SystemAdmin/Home.jsx @@ -43,6 +43,7 @@ import RequestedOfficeUserList from 'pages/Admin/RequestedOfficeUsers/RequestedO import RequestedOfficeUserShow from 'pages/Admin/RequestedOfficeUsers/RequestedOfficeUserShow'; import RequestedOfficeUserEdit from 'pages/Admin/RequestedOfficeUsers/RequestedOfficeUserEdit'; import RejectedOfficeUserList from 'pages/Admin/RejectedOfficeUsers/RejectedOfficeUserList'; +import RejectedOfficeUserShow from 'pages/Admin/RejectedOfficeUsers/RejectedOfficeUserShow'; import PaymentRequest858List from 'pages/Admin/PaymentRequests/PaymentRequest858List'; import PaymentRequest858Show from 'pages/Admin/PaymentRequests/PaymentRequest858Show'; @@ -84,6 +85,7 @@ const Home = () => ( name="rejected-office-users" options={{ label: 'Rejected Office Users' }} list={RejectedOfficeUserList} + show={RejectedOfficeUserShow} /> Date: Wed, 29 Jan 2025 15:46:54 +0000 Subject: [PATCH 06/37] fixed index test --- pkg/factory/office_user_factory.go | 4 +++- pkg/handlers/adminapi/rejected_office_users_test.go | 1 + 2 files changed, 4 insertions(+), 1 deletion(-) diff --git a/pkg/factory/office_user_factory.go b/pkg/factory/office_user_factory.go index 9304ad228f8..84828064330 100644 --- a/pkg/factory/office_user_factory.go +++ b/pkg/factory/office_user_factory.go @@ -3,6 +3,7 @@ package factory import ( "fmt" "strings" + "time" "github.com/gobuffalo/pop/v6" "github.com/gofrs/uuid" @@ -347,7 +348,8 @@ func GetTraitRejectedOfficeUser() []Customization { return []Customization{ { Model: models.OfficeUser{ - Status: &rejectedStatus, + Status: &rejectedStatus, + RejectedOn: time.Now(), }, }, } diff --git a/pkg/handlers/adminapi/rejected_office_users_test.go b/pkg/handlers/adminapi/rejected_office_users_test.go index d215ef6d7d7..40d11eefb2b 100644 --- a/pkg/handlers/adminapi/rejected_office_users_test.go +++ b/pkg/handlers/adminapi/rejected_office_users_test.go @@ -27,6 +27,7 @@ func (suite *HandlerSuite) TestIndexRejectedOfficeUsersHandler() { rejectedOfficeUsers := models.OfficeUsers{ factory.BuildOfficeUserWithRoles(suite.DB(), factory.GetTraitRejectedOfficeUser(), []roles.RoleType{roles.RoleTypeQae}), factory.BuildOfficeUserWithRoles(suite.DB(), factory.GetTraitRejectedOfficeUser(), []roles.RoleType{roles.RoleTypeQae})} + params := rejectedofficeuserop.IndexRejectedOfficeUsersParams{ HTTPRequest: suite.setupAuthenticatedRequest("GET", "/rejected_office_users"), } From c5b624e2e8bb2a834ee29e5763481b3ca2efac8d Mon Sep 17 00:00:00 2001 From: KonstanceH Date: Wed, 29 Jan 2025 17:11:57 +0000 Subject: [PATCH 07/37] fixed pull in also dont need roles on main page just show page --- pkg/factory/office_user_factory.go | 3 ++- pkg/handlers/adminapi/rejected_office_users.go | 2 +- pkg/models/office_user.go | 2 +- .../requested_office_user_updater.go | 3 ++- .../RejectedOfficeUserList.jsx | 17 +---------------- 5 files changed, 7 insertions(+), 20 deletions(-) diff --git a/pkg/factory/office_user_factory.go b/pkg/factory/office_user_factory.go index 84828064330..0ab45f121c4 100644 --- a/pkg/factory/office_user_factory.go +++ b/pkg/factory/office_user_factory.go @@ -345,11 +345,12 @@ func GetTraitRequestedOfficeUser() []Customization { // GetTraitRejectedOfficeUser sets the OfficeUser in an REJECTED status func GetTraitRejectedOfficeUser() []Customization { rejectedStatus := models.OfficeUserStatusREJECTED + rejectedOn := time.Now() return []Customization{ { Model: models.OfficeUser{ Status: &rejectedStatus, - RejectedOn: time.Now(), + RejectedOn: &rejectedOn, }, }, } diff --git a/pkg/handlers/adminapi/rejected_office_users.go b/pkg/handlers/adminapi/rejected_office_users.go index 1c37338b5fd..86d23f415d1 100644 --- a/pkg/handlers/adminapi/rejected_office_users.go +++ b/pkg/handlers/adminapi/rejected_office_users.go @@ -36,7 +36,7 @@ func payloadForRejectedOfficeUserModel(o models.OfficeUser) *adminmessages.Offic RejectionReason: handlers.FmtStringPtr(o.RejectionReason), CreatedAt: *handlers.FmtDateTime(o.CreatedAt), UpdatedAt: *handlers.FmtDateTime(o.UpdatedAt), - RejectedOn: *handlers.FmtDateTime(o.RejectedOn), + RejectedOn: *handlers.FmtDateTime(*o.RejectedOn), } if o.UserID != nil { diff --git a/pkg/models/office_user.go b/pkg/models/office_user.go index 83988d15db0..9f95575e77f 100644 --- a/pkg/models/office_user.go +++ b/pkg/models/office_user.go @@ -42,7 +42,7 @@ type OfficeUser struct { EDIPI *string `json:"edipi" db:"edipi"` OtherUniqueID *string `json:"other_unique_id" db:"other_unique_id"` RejectionReason *string `json:"rejection_reason" db:"rejection_reason"` - RejectedOn time.Time `json:"rejected_on" db:"rejected_on"` + RejectedOn *time.Time `json:"rejected_on" db:"rejected_on"` } type OfficeUserWithWorkload struct { diff --git a/pkg/services/requested_office_users/requested_office_user_updater.go b/pkg/services/requested_office_users/requested_office_user_updater.go index 2d950c8c5c5..f48d84a895d 100644 --- a/pkg/services/requested_office_users/requested_office_user_updater.go +++ b/pkg/services/requested_office_users/requested_office_user_updater.go @@ -66,9 +66,10 @@ func (o *requestedOfficeUserUpdater) UpdateRequestedOfficeUser(appCtx appcontext officeUser.OtherUniqueID = &payload.OtherUniqueID } + rejectedOn := time.Now() if payload.RejectionReason != "" { officeUser.RejectionReason = &payload.RejectionReason - officeUser.RejectedOn = time.Now() + officeUser.RejectedOn = &rejectedOn } if payload.Status != "" { diff --git a/src/pages/Admin/RejectedOfficeUsers/RejectedOfficeUserList.jsx b/src/pages/Admin/RejectedOfficeUsers/RejectedOfficeUserList.jsx index 4555bf2af91..369af3ffef8 100644 --- a/src/pages/Admin/RejectedOfficeUsers/RejectedOfficeUserList.jsx +++ b/src/pages/Admin/RejectedOfficeUsers/RejectedOfficeUserList.jsx @@ -1,15 +1,5 @@ import React from 'react'; -import { - ArrayField, - Datagrid, - DateField, - Filter, - List, - ReferenceField, - TextField, - TextInput, - TopToolbar, -} from 'react-admin'; +import { Datagrid, DateField, Filter, List, ReferenceField, TextField, TextInput, TopToolbar } from 'react-admin'; import AdminPagination from 'scenes/SystemAdmin/shared/AdminPagination'; @@ -45,11 +35,6 @@ const RejectedOfficeUserList = () => ( - - - - - ); From bfecadeacc65f5a9b39c255c73cdaa6325cfc248 Mon Sep 17 00:00:00 2001 From: KonstanceH Date: Thu, 30 Jan 2025 05:31:31 +0000 Subject: [PATCH 08/37] update show page added roles sep by , --- .../RejectedOfficeUserList.jsx | 28 +++++++++++- .../RejectedOfficeUserShow.jsx | 43 +------------------ 2 files changed, 28 insertions(+), 43 deletions(-) diff --git a/src/pages/Admin/RejectedOfficeUsers/RejectedOfficeUserList.jsx b/src/pages/Admin/RejectedOfficeUsers/RejectedOfficeUserList.jsx index 369af3ffef8..63332ce19a2 100644 --- a/src/pages/Admin/RejectedOfficeUsers/RejectedOfficeUserList.jsx +++ b/src/pages/Admin/RejectedOfficeUsers/RejectedOfficeUserList.jsx @@ -1,8 +1,33 @@ import React from 'react'; -import { Datagrid, DateField, Filter, List, ReferenceField, TextField, TextInput, TopToolbar } from 'react-admin'; +import { + Datagrid, + DateField, + Filter, + List, + ReferenceField, + TextField, + TextInput, + TopToolbar, + useRecordContext, +} from 'react-admin'; import AdminPagination from 'scenes/SystemAdmin/shared/AdminPagination'; +const RejectedOfficeUserShowRoles = () => { + const officeUser = useRecordContext(); + if (!officeUser?.roles) return

This user has not rejected any roles.

; + + const uniqueRoleNamesList = []; + const rejectedRoles = officeUser.roles; + for (let i = 0; i < rejectedRoles.length; i += 1) { + if (!uniqueRoleNamesList.includes(rejectedRoles[i].roleName)) { + uniqueRoleNamesList.push(rejectedRoles[i].roleName); + } + } + + return

{uniqueRoleNamesList.join(', ')}

; +}; + // Overriding the default toolbar const ListActions = () => { return ; @@ -35,6 +60,7 @@ const RejectedOfficeUserList = () => ( + ); diff --git a/src/pages/Admin/RejectedOfficeUsers/RejectedOfficeUserShow.jsx b/src/pages/Admin/RejectedOfficeUsers/RejectedOfficeUserShow.jsx index 54adb2c8099..30b286d2a12 100644 --- a/src/pages/Admin/RejectedOfficeUsers/RejectedOfficeUserShow.jsx +++ b/src/pages/Admin/RejectedOfficeUsers/RejectedOfficeUserShow.jsx @@ -1,5 +1,4 @@ -import { Alert, Label, TextInput } from '@trussworks/react-uswds'; -import React, { useState } from 'react'; +import React from 'react'; import { ArrayField, Datagrid, @@ -11,8 +10,6 @@ import { useRecordContext, } from 'react-admin'; -import styles from './RejectedOfficeUserShow.module.scss'; - const RejectedOfficeUserShowTitle = () => { const record = useRecordContext(); @@ -33,43 +30,6 @@ const RejectedOfficeUserShowRoles = () => { ); }; -// renders server and rej reason alerts -// renders approve/reject/edit buttons -// handles logic of approving/rejecting user -const RejectedOfficeUserActionButtons = () => { - const [serverError] = useState(''); - const [rejectionReason, setRejectionReason] = useState(''); - const [rejectionReasonCheck, setRejectionReasonCheck] = useState(''); - - return ( - <> - {serverError && ( - - {serverError} - - )} - {rejectionReasonCheck && ( - - {rejectionReasonCheck} - - )} -
- - { - setRejectionReason(e.target.value); - // removing error banner if text is entered - setRejectionReasonCheck(''); - }} - /> -
- - ); -}; - const RejectedOfficeUserShow = () => { return ( }> @@ -90,7 +50,6 @@ const RejectedOfficeUserShow = () => { - ); }; From 2818a105c06c275bd5095baa4bdbc73f161122b0 Mon Sep 17 00:00:00 2001 From: KonstanceH Date: Thu, 30 Jan 2025 06:19:03 +0000 Subject: [PATCH 09/37] trying to get test coverage up --- .../RejectedOfficeUser.test.jsx | 69 +++++++++++++++++++ 1 file changed, 69 insertions(+) create mode 100644 src/pages/Admin/RejectedOfficeUsers/RejectedOfficeUser.test.jsx diff --git a/src/pages/Admin/RejectedOfficeUsers/RejectedOfficeUser.test.jsx b/src/pages/Admin/RejectedOfficeUsers/RejectedOfficeUser.test.jsx new file mode 100644 index 00000000000..b05e6b4106f --- /dev/null +++ b/src/pages/Admin/RejectedOfficeUsers/RejectedOfficeUser.test.jsx @@ -0,0 +1,69 @@ +import React from 'react'; +import { AdminContext, Resource } from 'react-admin'; +import { render } from '@testing-library/react'; + +import RejectedOfficeUserList from './RejectedOfficeUserList'; +import RejectedOfficeUserShow from './RejectedOfficeUserShow'; + +const RejectedOfficeUser = { + active: true, + createdAt: '2024-10-25T20:04:29.658Z', + edipi: null, + email: 'Siobhan@example.com', + firstName: 'Siobhan', + id: '49136521-a02a-43dd-8884-9b8fcca198d3', + lastName: "O'Testoghue", + middleInitials: null, + otherUniqueId: null, + privileges: null, + rejectionReason: 'Testing rejection reason', + roles: [ + { + createdAt: '2024-10-25T19:55:13.204Z', + id: '2458e82f-b1ab-4eca-84a6-f39666b778fd', + roleName: 'Task Ordering Officer', + roleType: 'task_ordering_officer', + updatedAt: '2024-10-25T19:55:13.204Z', + }, + ], + status: 'REJECTED', + telephone: '787-787-7878', + transportationOfficeAssignments: [ + { + createdAt: '2024-10-25T20:04:29.670Z', + officeUserId: '49136521-a02a-43dd-8884-9b8fcca198d3', + primaryOffice: true, + transportationOfficeId: '171b54fa-4c89-45d8-8111-a2d65818ff8c', + updatedAt: '2024-10-25T20:04:29.670Z', + }, + ], + transportationOfficeId: '171b54fa-4c89-45d8-8111-a2d65818ff8c', + updatedAt: '2024-10-25T20:04:29.658Z', + userId: '465a47b2-8ce1-46d8-86b5-bdf6639ced22', + rejectedOn: '2025-10-25T20:04:29.658Z', +}; + +const dataProvider = { + getOne: () => Promise.resolve({ data: RejectedOfficeUser }), + getList: () => Promise.resolve({ data: [RejectedOfficeUser], total: 1 }), +}; + +describe('RejectedOfficeUserList page', () => { + it('renders without crashing', async () => { + render( + + + , + ); + }); +}); + +describe('RejectedOfficeUserShow page', () => { + it('renders without crashing', async () => { + render( + + + , + ); + }); +}); From a69d87b55d0718b6f2910c0cf0320872e9a1bfb1 Mon Sep 17 00:00:00 2001 From: KonstanceH Date: Thu, 30 Jan 2025 07:36:48 +0000 Subject: [PATCH 10/37] fix rejected testharness --- pkg/testdatagen/testharness/make_office_user.go | 13 +++++++++---- 1 file changed, 9 insertions(+), 4 deletions(-) diff --git a/pkg/testdatagen/testharness/make_office_user.go b/pkg/testdatagen/testharness/make_office_user.go index 7f8230c5b23..a8a20915e76 100644 --- a/pkg/testdatagen/testharness/make_office_user.go +++ b/pkg/testdatagen/testharness/make_office_user.go @@ -4,6 +4,7 @@ import ( "fmt" "log" "strings" + "time" "github.com/transcom/mymove/pkg/appcontext" "github.com/transcom/mymove/pkg/factory" @@ -32,13 +33,17 @@ func MakeRejectedOfficeUserWithTOO(appCtx appcontext.AppContext) models.User { }, }, nil) rejectedStatus := models.OfficeUserStatusREJECTED + rejectionReason := "testing" + rejectedOn := time.Now() factory.BuildOfficeUserWithRoles(appCtx.DB(), []factory.Customization{ { Model: models.OfficeUser{ - Email: email, - Active: true, - UserID: &user.ID, - Status: &rejectedStatus, + Email: email, + Active: true, + UserID: &user.ID, + Status: &rejectedStatus, + RejectedOn: &rejectedOn, + RejectionReason: &rejectionReason, }, }, { From e0c7d0e0679d4ea3b8c4c0956e289d574b5e7053 Mon Sep 17 00:00:00 2001 From: KonstanceH Date: Thu, 30 Jan 2025 07:39:09 +0000 Subject: [PATCH 11/37] fix rejected testharness --- pkg/testdatagen/testharness/make_office_user.go | 13 +++++++++---- 1 file changed, 9 insertions(+), 4 deletions(-) diff --git a/pkg/testdatagen/testharness/make_office_user.go b/pkg/testdatagen/testharness/make_office_user.go index 7f8230c5b23..a8a20915e76 100644 --- a/pkg/testdatagen/testharness/make_office_user.go +++ b/pkg/testdatagen/testharness/make_office_user.go @@ -4,6 +4,7 @@ import ( "fmt" "log" "strings" + "time" "github.com/transcom/mymove/pkg/appcontext" "github.com/transcom/mymove/pkg/factory" @@ -32,13 +33,17 @@ func MakeRejectedOfficeUserWithTOO(appCtx appcontext.AppContext) models.User { }, }, nil) rejectedStatus := models.OfficeUserStatusREJECTED + rejectionReason := "testing" + rejectedOn := time.Now() factory.BuildOfficeUserWithRoles(appCtx.DB(), []factory.Customization{ { Model: models.OfficeUser{ - Email: email, - Active: true, - UserID: &user.ID, - Status: &rejectedStatus, + Email: email, + Active: true, + UserID: &user.ID, + Status: &rejectedStatus, + RejectedOn: &rejectedOn, + RejectionReason: &rejectionReason, }, }, { From b79b241ea170dc447f8d01346e57c31b5f9f5bdb Mon Sep 17 00:00:00 2001 From: KonstanceH Date: Fri, 31 Jan 2025 21:01:45 +0000 Subject: [PATCH 12/37] removing deleted columns and adding new migration --- migrations/app/migrations_manifest.txt | 2 +- ...38_add_rejected_col_to_admin_users.up.sql} | 4 +-- pkg/gen/adminapi/embedded_spec.go | 10 ------ pkg/gen/adminmessages/office_user.go | 34 ------------------- swagger-def/admin.yaml | 4 --- swagger/admin.yaml | 4 --- 6 files changed, 2 insertions(+), 56 deletions(-) rename migrations/app/schema/{20250124140959_add_rejected_and_deleted_cols_to_admin_office_users.up.sql => 20250131205338_add_rejected_col_to_admin_users.up.sql} (52%) diff --git a/migrations/app/migrations_manifest.txt b/migrations/app/migrations_manifest.txt index 8c9340621c5..7254a8c53b0 100644 --- a/migrations/app/migrations_manifest.txt +++ b/migrations/app/migrations_manifest.txt @@ -1078,4 +1078,4 @@ 20250113201232_update_estimated_pricing_procs_add_is_peak_func.up.sql 20250116200912_disable_homesafe_stg_cert.up.sql 20250120144247_update_pricing_proc_to_use_110_percent_weight.up.sql -20250124140959_add_rejected_and_deleted_cols_to_admin_office_users.up.sql +20250131205338_add_rejected_col_to_admin_users.up.sql diff --git a/migrations/app/schema/20250124140959_add_rejected_and_deleted_cols_to_admin_office_users.up.sql b/migrations/app/schema/20250131205338_add_rejected_col_to_admin_users.up.sql similarity index 52% rename from migrations/app/schema/20250124140959_add_rejected_and_deleted_cols_to_admin_office_users.up.sql rename to migrations/app/schema/20250131205338_add_rejected_col_to_admin_users.up.sql index f52420e6fdb..14b367ab6a6 100644 --- a/migrations/app/schema/20250124140959_add_rejected_and_deleted_cols_to_admin_office_users.up.sql +++ b/migrations/app/schema/20250131205338_add_rejected_col_to_admin_users.up.sql @@ -1,8 +1,6 @@ -- Adds new columns to office_users table ALTER TABLE public.office_users -ADD COLUMN IF NOT EXISTS rejected_on timestamptz, -ADD COLUMN IF NOT EXISTS deleted_on timestamptz; +ADD COLUMN IF NOT EXISTS rejected_on timestamptz; -- Comments on new columns COMMENT on COLUMN office_users.rejected_on IS 'Date requested office users were rejected.'; -COMMENT on COLUMN office_users.deleted_on IS 'Date office users were deleted.'; diff --git a/pkg/gen/adminapi/embedded_spec.go b/pkg/gen/adminapi/embedded_spec.go index 30af223a212..5aa58228261 100644 --- a/pkg/gen/adminapi/embedded_spec.go +++ b/pkg/gen/adminapi/embedded_spec.go @@ -2889,11 +2889,6 @@ func init() { "format": "date-time", "readOnly": true }, - "deletedOn": { - "type": "string", - "format": "date-time", - "readOnly": true - }, "edipi": { "type": "string" }, @@ -6706,11 +6701,6 @@ func init() { "format": "date-time", "readOnly": true }, - "deletedOn": { - "type": "string", - "format": "date-time", - "readOnly": true - }, "edipi": { "type": "string" }, diff --git a/pkg/gen/adminmessages/office_user.go b/pkg/gen/adminmessages/office_user.go index 378a6165e4d..782d93ca590 100644 --- a/pkg/gen/adminmessages/office_user.go +++ b/pkg/gen/adminmessages/office_user.go @@ -31,11 +31,6 @@ type OfficeUser struct { // Format: date-time CreatedAt strfmt.DateTime `json:"createdAt"` - // deleted on - // Read Only: true - // Format: date-time - DeletedOn strfmt.DateTime `json:"deletedOn,omitempty"` - // edipi // Required: true Edipi *string `json:"edipi"` @@ -125,10 +120,6 @@ func (m *OfficeUser) Validate(formats strfmt.Registry) error { res = append(res, err) } - if err := m.validateDeletedOn(formats); err != nil { - res = append(res, err) - } - if err := m.validateEdipi(formats); err != nil { res = append(res, err) } @@ -225,18 +216,6 @@ func (m *OfficeUser) validateCreatedAt(formats strfmt.Registry) error { return nil } -func (m *OfficeUser) validateDeletedOn(formats strfmt.Registry) error { - if swag.IsZero(m.DeletedOn) { // not required - return nil - } - - if err := validate.FormatOf("deletedOn", "body", "date-time", m.DeletedOn.String(), formats); err != nil { - return err - } - - return nil -} - func (m *OfficeUser) validateEdipi(formats strfmt.Registry) error { if err := validate.Required("edipi", "body", m.Edipi); err != nil { @@ -514,10 +493,6 @@ func (m *OfficeUser) ContextValidate(ctx context.Context, formats strfmt.Registr res = append(res, err) } - if err := m.contextValidateDeletedOn(ctx, formats); err != nil { - res = append(res, err) - } - if err := m.contextValidatePrivileges(ctx, formats); err != nil { res = append(res, err) } @@ -553,15 +528,6 @@ func (m *OfficeUser) contextValidateCreatedAt(ctx context.Context, formats strfm return nil } -func (m *OfficeUser) contextValidateDeletedOn(ctx context.Context, formats strfmt.Registry) error { - - if err := validate.ReadOnly(ctx, "deletedOn", "body", strfmt.DateTime(m.DeletedOn)); err != nil { - return err - } - - return nil -} - func (m *OfficeUser) contextValidatePrivileges(ctx context.Context, formats strfmt.Registry) error { for i := 0; i < len(m.Privileges); i++ { diff --git a/swagger-def/admin.yaml b/swagger-def/admin.yaml index e82846f0058..22f82591ae2 100644 --- a/swagger-def/admin.yaml +++ b/swagger-def/admin.yaml @@ -719,10 +719,6 @@ definitions: type: string format: date-time readOnly: true - deletedOn: - type: string - format: date-time - readOnly: true required: - id - firstName diff --git a/swagger/admin.yaml b/swagger/admin.yaml index af215def851..05ff4d37e2d 100644 --- a/swagger/admin.yaml +++ b/swagger/admin.yaml @@ -726,10 +726,6 @@ definitions: type: string format: date-time readOnly: true - deletedOn: - type: string - format: date-time - readOnly: true required: - id - firstName From 69db5dcb57cb376b3ddc123e8e6c119520cb3162 Mon Sep 17 00:00:00 2001 From: KonstanceH Date: Tue, 4 Feb 2025 19:54:12 +0000 Subject: [PATCH 13/37] remove unused and fix font --- pkg/handlers/adminapi/api.go | 7 - .../adminapi/rejected_office_users_test.go | 140 ------------------ pkg/services/rejected_office_users.go | 9 -- .../rejected_office_user_fetcher.go | 58 -------- .../rejected_office_user_fetcher_test.go | 90 ----------- .../RejectedOfficeUserList.jsx | 2 +- 6 files changed, 1 insertion(+), 305 deletions(-) delete mode 100644 pkg/services/rejected_office_users/rejected_office_user_fetcher.go delete mode 100644 pkg/services/rejected_office_users/rejected_office_user_fetcher_test.go diff --git a/pkg/handlers/adminapi/api.go b/pkg/handlers/adminapi/api.go index 3ae1c4c8bc6..a4050632ee2 100644 --- a/pkg/handlers/adminapi/api.go +++ b/pkg/handlers/adminapi/api.go @@ -85,13 +85,6 @@ func NewAdminAPI(handlerConfig handlers.HandlerConfig) *adminops.MymoveAPI { pagination.NewPagination, } - adminAPI.RejectedOfficeUsersGetRejectedOfficeUserHandler = GetRejectedOfficeUserHandler{ - handlerConfig, - rejectedofficeusers.NewRejectedOfficeUserFetcher(queryBuilder), - newRolesFetcher, - query.NewQueryFilter, - } - adminAPI.OfficeUsersIndexOfficeUsersHandler = IndexOfficeUsersHandler{ handlerConfig, fetch.NewListFetcher(queryBuilder), diff --git a/pkg/handlers/adminapi/rejected_office_users_test.go b/pkg/handlers/adminapi/rejected_office_users_test.go index 40d11eefb2b..5ed2d09aa09 100644 --- a/pkg/handlers/adminapi/rejected_office_users_test.go +++ b/pkg/handlers/adminapi/rejected_office_users_test.go @@ -1,20 +1,10 @@ package adminapi import ( - "fmt" - "net/http" - "time" - - "github.com/go-openapi/strfmt" - "github.com/gofrs/uuid" - "github.com/stretchr/testify/mock" - "github.com/transcom/mymove/pkg/factory" rejectedofficeuserop "github.com/transcom/mymove/pkg/gen/adminapi/adminoperations/rejected_office_users" - "github.com/transcom/mymove/pkg/handlers" "github.com/transcom/mymove/pkg/models" "github.com/transcom/mymove/pkg/models/roles" - "github.com/transcom/mymove/pkg/services/mocks" "github.com/transcom/mymove/pkg/services/pagination" "github.com/transcom/mymove/pkg/services/query" rejectedofficeusers "github.com/transcom/mymove/pkg/services/rejected_office_users" @@ -49,133 +39,3 @@ func (suite *HandlerSuite) TestIndexRejectedOfficeUsersHandler() { suite.Equal(rejectedOfficeUsers[0].ID.String(), okResponse.Payload[0].ID.String()) }) } - -func (suite *HandlerSuite) TestGetRejectedOfficeUserHandler() { - // test that everything is wired up - suite.Run("integration test ok response", func() { - rejectedOfficeUser := factory.BuildOfficeUserWithRoles(suite.DB(), factory.GetTraitRejectedOfficeUser(), []roles.RoleType{roles.RoleTypeQae}) - params := rejectedofficeuserop.GetRejectedOfficeUserParams{ - HTTPRequest: suite.setupAuthenticatedRequest("GET", fmt.Sprintf("/rejected_office_users/%s", rejectedOfficeUser.ID)), - OfficeUserID: strfmt.UUID(rejectedOfficeUser.ID.String()), - } - - mockRoleAssociator := &mocks.RoleAssociater{} - mockRoles := roles.Roles{ - roles.Role{ - ID: uuid.Must(uuid.NewV4()), - RoleType: roles.RoleTypeTOO, - RoleName: "Task Ordering Officer", - CreatedAt: time.Now(), - UpdatedAt: time.Now(), - }, - } - mockRoleAssociator.On( - "FetchRolesForUser", - mock.AnythingOfType("*appcontext.appContext"), - mock.Anything, - ).Return(mockRoles, nil) - - queryBuilder := query.NewQueryBuilder() - handler := GetRejectedOfficeUserHandler{ - suite.HandlerConfig(), - rejectedofficeusers.NewRejectedOfficeUserFetcher(queryBuilder), - mockRoleAssociator, - query.NewQueryFilter, - } - - response := handler.Handle(params) - - suite.IsType(&rejectedofficeuserop.GetRejectedOfficeUserOK{}, response) - okResponse := response.(*rejectedofficeuserop.GetRejectedOfficeUserOK) - suite.Equal(rejectedOfficeUser.ID.String(), okResponse.Payload.ID.String()) - }) - - suite.Run("successful response", func() { - rejectedOfficeUser := factory.BuildOfficeUserWithRoles(suite.DB(), factory.GetTraitRejectedOfficeUser(), []roles.RoleType{roles.RoleTypeQae}) - params := rejectedofficeuserop.GetRejectedOfficeUserParams{ - HTTPRequest: suite.setupAuthenticatedRequest("GET", fmt.Sprintf("/rejected_office_users/%s", rejectedOfficeUser.ID)), - OfficeUserID: strfmt.UUID(rejectedOfficeUser.ID.String()), - } - - rejectedOfficeUserFetcher := &mocks.RejectedOfficeUserFetcher{} - rejectedOfficeUserFetcher.On("FetchRejectedOfficeUser", - mock.AnythingOfType("*appcontext.appContext"), - mock.Anything, - ).Return(rejectedOfficeUser, nil).Once() - - mockRoleAssociator := &mocks.RoleAssociater{} - mockRoles := roles.Roles{ - roles.Role{ - ID: uuid.Must(uuid.NewV4()), - RoleType: roles.RoleTypeTOO, - RoleName: "Task Ordering Officer", - CreatedAt: time.Now(), - UpdatedAt: time.Now(), - }, - } - mockRoleAssociator.On( - "FetchRolesForUser", - mock.AnythingOfType("*appcontext.appContext"), - mock.Anything, - ).Return(mockRoles, nil) - - handler := GetRejectedOfficeUserHandler{ - suite.HandlerConfig(), - rejectedOfficeUserFetcher, - mockRoleAssociator, - newMockQueryFilterBuilder(&mocks.QueryFilter{}), - } - - response := handler.Handle(params) - - suite.IsType(&rejectedofficeuserop.GetRejectedOfficeUserOK{}, response) - okResponse := response.(*rejectedofficeuserop.GetRejectedOfficeUserOK) - suite.Equal(rejectedOfficeUser.ID.String(), okResponse.Payload.ID.String()) - }) - - suite.Run("unsuccessful response when fetch fails", func() { - rejectedOfficeUser := factory.BuildOfficeUserWithRoles(suite.DB(), factory.GetTraitRejectedOfficeUser(), []roles.RoleType{roles.RoleTypeQae}) - params := rejectedofficeuserop.GetRejectedOfficeUserParams{ - HTTPRequest: suite.setupAuthenticatedRequest("GET", fmt.Sprintf("/rejected_office_users/%s", rejectedOfficeUser.ID)), - OfficeUserID: strfmt.UUID(rejectedOfficeUser.ID.String()), - } - - expectedError := models.ErrFetchNotFound - rejectedOfficeUserFetcher := &mocks.RejectedOfficeUserFetcher{} - rejectedOfficeUserFetcher.On("FetchRejectedOfficeUser", - mock.AnythingOfType("*appcontext.appContext"), - mock.Anything, - ).Return(models.OfficeUser{}, expectedError).Once() - - mockRoleAssociator := &mocks.RoleAssociater{} - mockRoles := roles.Roles{ - roles.Role{ - ID: uuid.Must(uuid.NewV4()), - RoleType: roles.RoleTypeTOO, - RoleName: "Task Ordering Officer", - CreatedAt: time.Now(), - UpdatedAt: time.Now(), - }, - } - mockRoleAssociator.On( - "FetchRolesForUser", - mock.AnythingOfType("*appcontext.appContext"), - mock.Anything, - ).Return(mockRoles, nil) - - handler := GetRejectedOfficeUserHandler{ - suite.HandlerConfig(), - rejectedOfficeUserFetcher, - mockRoleAssociator, - newMockQueryFilterBuilder(&mocks.QueryFilter{}), - } - - response := handler.Handle(params) - - expectedResponse := &handlers.ErrResponse{ - Code: http.StatusNotFound, - Err: expectedError, - } - suite.Equal(expectedResponse, response) - }) -} diff --git a/pkg/services/rejected_office_users.go b/pkg/services/rejected_office_users.go index fe1ba485a0b..1a7d57990f4 100644 --- a/pkg/services/rejected_office_users.go +++ b/pkg/services/rejected_office_users.go @@ -1,8 +1,6 @@ package services import ( - "github.com/gofrs/uuid" - "github.com/transcom/mymove/pkg/appcontext" "github.com/transcom/mymove/pkg/models" ) @@ -21,10 +19,3 @@ type RejectedOfficeUserListFetcher interface { type RejectedOfficeUserFetcher interface { FetchRejectedOfficeUser(appCtx appcontext.AppContext, filters []QueryFilter) (models.OfficeUser, error) } - -// RejectedOfficeUserFetcherPop is the exported interface for fetching a single office user -// -//go:generate mockery --name RejectedOfficeUserFetcherPop -type RejectedOfficeUserFetcherPop interface { - FetchRejectedOfficeUserByID(appCtx appcontext.AppContext, id uuid.UUID) (models.OfficeUser, error) -} diff --git a/pkg/services/rejected_office_users/rejected_office_user_fetcher.go b/pkg/services/rejected_office_users/rejected_office_user_fetcher.go deleted file mode 100644 index ca24b44d5b1..00000000000 --- a/pkg/services/rejected_office_users/rejected_office_user_fetcher.go +++ /dev/null @@ -1,58 +0,0 @@ -package adminuser - -import ( - "database/sql" - - "github.com/gobuffalo/validate/v3" - "github.com/gofrs/uuid" - - "github.com/transcom/mymove/pkg/appcontext" - "github.com/transcom/mymove/pkg/apperror" - "github.com/transcom/mymove/pkg/models" - "github.com/transcom/mymove/pkg/services" -) - -type rejectedOfficeUserQueryBuilder interface { - FetchOne(appCtx appcontext.AppContext, model interface{}, filters []services.QueryFilter) error - UpdateOne(appCtx appcontext.AppContext, model interface{}, eTag *string) (*validate.Errors, error) -} - -type rejectedOfficeUserFetcher struct { - builder rejectedOfficeUserQueryBuilder -} - -// FetchRejectedOfficeUser fetches an office user given a slice of filters -func (o *rejectedOfficeUserFetcher) FetchRejectedOfficeUser(appCtx appcontext.AppContext, filters []services.QueryFilter) (models.OfficeUser, error) { - var rejectedOfficeUser models.OfficeUser - err := o.builder.FetchOne(appCtx, &rejectedOfficeUser, filters) - return rejectedOfficeUser, err -} - -// NewAdminUserFetcher return an implementation of the AdminUserFetcher interface -func NewRejectedOfficeUserFetcher(builder rejectedOfficeUserQueryBuilder) services.RejectedOfficeUserFetcher { - return &rejectedOfficeUserFetcher{builder} -} - -type rejectedOfficeUserFetcherPop struct { -} - -// FetchOfficeUserByID fetches an office user given an ID -func (o *rejectedOfficeUserFetcherPop) FetchRejectedOfficeUserByID(appCtx appcontext.AppContext, id uuid.UUID) (models.OfficeUser, error) { - var officeUser models.OfficeUser - err := appCtx.DB().Eager("TransportationOffice").Find(&officeUser, id) - if err != nil { - switch err { - case sql.ErrNoRows: - return models.OfficeUser{}, apperror.NewNotFoundError(id, "looking for OfficeUser") - default: - return models.OfficeUser{}, apperror.NewQueryError("OfficeUser", err, "") - } - } - - return officeUser, err -} - -// NewOfficeUserFetcherPop return an implementation of the OfficeUserFetcherPop interface -func NewRejectedOfficeUserFetcherPop() services.RejectedOfficeUserFetcherPop { - return &rejectedOfficeUserFetcherPop{} -} diff --git a/pkg/services/rejected_office_users/rejected_office_user_fetcher_test.go b/pkg/services/rejected_office_users/rejected_office_user_fetcher_test.go deleted file mode 100644 index 5ac38aae67f..00000000000 --- a/pkg/services/rejected_office_users/rejected_office_user_fetcher_test.go +++ /dev/null @@ -1,90 +0,0 @@ -package adminuser - -import ( - "errors" - "reflect" - - "github.com/gobuffalo/validate/v3" - "github.com/gofrs/uuid" - - "github.com/transcom/mymove/pkg/appcontext" - "github.com/transcom/mymove/pkg/apperror" - "github.com/transcom/mymove/pkg/factory" - "github.com/transcom/mymove/pkg/models" - "github.com/transcom/mymove/pkg/models/roles" - "github.com/transcom/mymove/pkg/services" - "github.com/transcom/mymove/pkg/services/query" -) - -type testRejectedOfficeUsersQueryBuilder struct { - fakeFetchOne func(appConfig appcontext.AppContext, model interface{}) error -} - -func (t *testRejectedOfficeUsersQueryBuilder) FetchOne(appConfig appcontext.AppContext, model interface{}, _ []services.QueryFilter) error { - m := t.fakeFetchOne(appConfig, model) - return m -} - -func (t *testRejectedOfficeUsersQueryBuilder) UpdateOne(_ appcontext.AppContext, _ interface{}, _ *string) (*validate.Errors, error) { - return nil, nil -} - -func (suite *RejectedOfficeUsersServiceSuite) TestFetchRejectedOfficeUser() { - suite.Run("if the rejected office user is fetched, it should be returned", func() { - id, err := uuid.NewV4() - suite.NoError(err) - fakeFetchOne := func(_ appcontext.AppContext, model interface{}) error { - reflect.ValueOf(model).Elem().FieldByName("ID").Set(reflect.ValueOf(id)) - return nil - } - - builder := &testRejectedOfficeUsersQueryBuilder{ - fakeFetchOne: fakeFetchOne, - } - - fetcher := NewRejectedOfficeUserFetcher(builder) - filters := []services.QueryFilter{query.NewQueryFilter("id", "=", id.String())} - - rejectedOfficeUser, err := fetcher.FetchRejectedOfficeUser(suite.AppContextForTest(), filters) - - suite.NoError(err) - suite.Equal(id, rejectedOfficeUser.ID) - }) - - suite.Run("if there is an error, we get it with zero admin user", func() { - fakeFetchOne := func(_ appcontext.AppContext, _ interface{}) error { - return errors.New("Fetch error") - } - builder := &testRejectedOfficeUsersQueryBuilder{ - fakeFetchOne: fakeFetchOne, - } - fetcher := NewRejectedOfficeUserFetcher(builder) - - rejectedOfficeUser, err := fetcher.FetchRejectedOfficeUser(suite.AppContextForTest(), []services.QueryFilter{}) - - suite.Error(err) - suite.Equal(err.Error(), "Fetch error") - suite.Equal(models.OfficeUser{}, rejectedOfficeUser) - }) -} - -func (suite *RejectedOfficeUsersServiceSuite) TestFetchRejectedOfficeUserPop() { - suite.Run("returns office user on success", func() { - officeUser := factory.BuildOfficeUserWithRoles(suite.DB(), nil, []roles.RoleType{roles.RoleTypeTOO}) - fetcher := NewRejectedOfficeUserFetcherPop() - - fetchedUser, err := fetcher.FetchRejectedOfficeUserByID(suite.AppContextForTest(), officeUser.ID) - - suite.NoError(err) - suite.Equal(officeUser.ID, fetchedUser.ID) - }) - - suite.Run("returns zero value office user on error", func() { - fetcher := NewRejectedOfficeUserFetcherPop() - officeUser, err := fetcher.FetchRejectedOfficeUserByID(suite.AppContextForTest(), uuid.Nil) - - suite.Error(err) - suite.IsType(apperror.NotFoundError{}, err) - suite.Equal(uuid.Nil, officeUser.ID) - }) -} diff --git a/src/pages/Admin/RejectedOfficeUsers/RejectedOfficeUserList.jsx b/src/pages/Admin/RejectedOfficeUsers/RejectedOfficeUserList.jsx index 63332ce19a2..d0278bc2e77 100644 --- a/src/pages/Admin/RejectedOfficeUsers/RejectedOfficeUserList.jsx +++ b/src/pages/Admin/RejectedOfficeUsers/RejectedOfficeUserList.jsx @@ -25,7 +25,7 @@ const RejectedOfficeUserShowRoles = () => { } } - return

{uniqueRoleNamesList.join(', ')}

; + return {uniqueRoleNamesList.join(', ')}; }; // Overriding the default toolbar From 9051446db313a19978c21dc01cf72bd220f71b7a Mon Sep 17 00:00:00 2001 From: KonstanceH Date: Tue, 4 Feb 2025 21:45:59 +0000 Subject: [PATCH 14/37] remove from swagger --- .../adminapi/adminoperations/mymove_api.go | 12 -- .../get_rejected_office_user.go | 58 ------- .../get_rejected_office_user_parameters.go | 91 ---------- .../get_rejected_office_user_responses.go | 159 ------------------ .../get_rejected_office_user_urlbuilder.go | 101 ----------- pkg/gen/adminapi/configure_mymove.go | 5 - pkg/gen/adminapi/embedded_spec.go | 84 --------- .../adminapi/rejected_office_users.go | 37 ---- pkg/services/mocks/WeightAllotmentFetcher.go | 117 +++++++++++++ pkg/services/mocks/WeightRestrictor.go | 89 ++++++++++ swagger-def/admin.yaml | 28 --- swagger/admin.yaml | 31 ---- 12 files changed, 206 insertions(+), 606 deletions(-) delete mode 100644 pkg/gen/adminapi/adminoperations/rejected_office_users/get_rejected_office_user.go delete mode 100644 pkg/gen/adminapi/adminoperations/rejected_office_users/get_rejected_office_user_parameters.go delete mode 100644 pkg/gen/adminapi/adminoperations/rejected_office_users/get_rejected_office_user_responses.go delete mode 100644 pkg/gen/adminapi/adminoperations/rejected_office_users/get_rejected_office_user_urlbuilder.go create mode 100644 pkg/services/mocks/WeightAllotmentFetcher.go create mode 100644 pkg/services/mocks/WeightRestrictor.go diff --git a/pkg/gen/adminapi/adminoperations/mymove_api.go b/pkg/gen/adminapi/adminoperations/mymove_api.go index 64953dade88..a3877cb338e 100644 --- a/pkg/gen/adminapi/adminoperations/mymove_api.go +++ b/pkg/gen/adminapi/adminoperations/mymove_api.go @@ -95,9 +95,6 @@ func NewMymoveAPI(spec *loads.Document) *MymoveAPI { OfficeUsersGetOfficeUserHandler: office_users.GetOfficeUserHandlerFunc(func(params office_users.GetOfficeUserParams) middleware.Responder { return middleware.NotImplemented("operation office_users.GetOfficeUser has not yet been implemented") }), - RejectedOfficeUsersGetRejectedOfficeUserHandler: rejected_office_users.GetRejectedOfficeUserHandlerFunc(func(params rejected_office_users.GetRejectedOfficeUserParams) middleware.Responder { - return middleware.NotImplemented("operation rejected_office_users.GetRejectedOfficeUser has not yet been implemented") - }), RequestedOfficeUsersGetRequestedOfficeUserHandler: requested_office_users.GetRequestedOfficeUserHandlerFunc(func(params requested_office_users.GetRequestedOfficeUserParams) middleware.Responder { return middleware.NotImplemented("operation requested_office_users.GetRequestedOfficeUser has not yet been implemented") }), @@ -240,8 +237,6 @@ type MymoveAPI struct { TransportationOfficesGetOfficeByIDHandler transportation_offices.GetOfficeByIDHandler // OfficeUsersGetOfficeUserHandler sets the operation handler for the get office user operation OfficeUsersGetOfficeUserHandler office_users.GetOfficeUserHandler - // RejectedOfficeUsersGetRejectedOfficeUserHandler sets the operation handler for the get rejected office user operation - RejectedOfficeUsersGetRejectedOfficeUserHandler rejected_office_users.GetRejectedOfficeUserHandler // RequestedOfficeUsersGetRequestedOfficeUserHandler sets the operation handler for the get requested office user operation RequestedOfficeUsersGetRequestedOfficeUserHandler requested_office_users.GetRequestedOfficeUserHandler // UploadsGetUploadHandler sets the operation handler for the get upload operation @@ -407,9 +402,6 @@ func (o *MymoveAPI) Validate() error { if o.OfficeUsersGetOfficeUserHandler == nil { unregistered = append(unregistered, "office_users.GetOfficeUserHandler") } - if o.RejectedOfficeUsersGetRejectedOfficeUserHandler == nil { - unregistered = append(unregistered, "rejected_office_users.GetRejectedOfficeUserHandler") - } if o.RequestedOfficeUsersGetRequestedOfficeUserHandler == nil { unregistered = append(unregistered, "requested_office_users.GetRequestedOfficeUserHandler") } @@ -627,10 +619,6 @@ func (o *MymoveAPI) initHandlerCache() { if o.handlers["GET"] == nil { o.handlers["GET"] = make(map[string]http.Handler) } - o.handlers["GET"]["/rejected-office-users/{officeUserId}"] = rejected_office_users.NewGetRejectedOfficeUser(o.context, o.RejectedOfficeUsersGetRejectedOfficeUserHandler) - if o.handlers["GET"] == nil { - o.handlers["GET"] = make(map[string]http.Handler) - } o.handlers["GET"]["/requested-office-users/{officeUserId}"] = requested_office_users.NewGetRequestedOfficeUser(o.context, o.RequestedOfficeUsersGetRequestedOfficeUserHandler) if o.handlers["GET"] == nil { o.handlers["GET"] = make(map[string]http.Handler) diff --git a/pkg/gen/adminapi/adminoperations/rejected_office_users/get_rejected_office_user.go b/pkg/gen/adminapi/adminoperations/rejected_office_users/get_rejected_office_user.go deleted file mode 100644 index d7664e97399..00000000000 --- a/pkg/gen/adminapi/adminoperations/rejected_office_users/get_rejected_office_user.go +++ /dev/null @@ -1,58 +0,0 @@ -// Code generated by go-swagger; DO NOT EDIT. - -package rejected_office_users - -// 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" -) - -// GetRejectedOfficeUserHandlerFunc turns a function with the right signature into a get rejected office user handler -type GetRejectedOfficeUserHandlerFunc func(GetRejectedOfficeUserParams) middleware.Responder - -// Handle executing the request and returning a response -func (fn GetRejectedOfficeUserHandlerFunc) Handle(params GetRejectedOfficeUserParams) middleware.Responder { - return fn(params) -} - -// GetRejectedOfficeUserHandler interface for that can handle valid get rejected office user params -type GetRejectedOfficeUserHandler interface { - Handle(GetRejectedOfficeUserParams) middleware.Responder -} - -// NewGetRejectedOfficeUser creates a new http.Handler for the get rejected office user operation -func NewGetRejectedOfficeUser(ctx *middleware.Context, handler GetRejectedOfficeUserHandler) *GetRejectedOfficeUser { - return &GetRejectedOfficeUser{Context: ctx, Handler: handler} -} - -/* - GetRejectedOfficeUser swagger:route GET /rejected-office-users/{officeUserId} Rejected office users getRejectedOfficeUser - -# Get a Rejected Office User - -Retrieving a single office user in any status. This endpoint is used in the Admin UI that will allow the admin user to view the user's relevant data. -*/ -type GetRejectedOfficeUser struct { - Context *middleware.Context - Handler GetRejectedOfficeUserHandler -} - -func (o *GetRejectedOfficeUser) ServeHTTP(rw http.ResponseWriter, r *http.Request) { - route, rCtx, _ := o.Context.RouteInfo(r) - if rCtx != nil { - *r = *rCtx - } - var Params = NewGetRejectedOfficeUserParams() - 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/adminapi/adminoperations/rejected_office_users/get_rejected_office_user_parameters.go b/pkg/gen/adminapi/adminoperations/rejected_office_users/get_rejected_office_user_parameters.go deleted file mode 100644 index 46f91bf217a..00000000000 --- a/pkg/gen/adminapi/adminoperations/rejected_office_users/get_rejected_office_user_parameters.go +++ /dev/null @@ -1,91 +0,0 @@ -// Code generated by go-swagger; DO NOT EDIT. - -package rejected_office_users - -// 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" -) - -// NewGetRejectedOfficeUserParams creates a new GetRejectedOfficeUserParams object -// -// There are no default values defined in the spec. -func NewGetRejectedOfficeUserParams() GetRejectedOfficeUserParams { - - return GetRejectedOfficeUserParams{} -} - -// GetRejectedOfficeUserParams contains all the bound params for the get rejected office user operation -// typically these are obtained from a http.Request -// -// swagger:parameters getRejectedOfficeUser -type GetRejectedOfficeUserParams struct { - - // HTTP Request Object - HTTPRequest *http.Request `json:"-"` - - /* - Required: true - In: path - */ - OfficeUserID 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 NewGetRejectedOfficeUserParams() beforehand. -func (o *GetRejectedOfficeUserParams) BindRequest(r *http.Request, route *middleware.MatchedRoute) error { - var res []error - - o.HTTPRequest = r - - rOfficeUserID, rhkOfficeUserID, _ := route.Params.GetOK("officeUserId") - if err := o.bindOfficeUserID(rOfficeUserID, rhkOfficeUserID, route.Formats); err != nil { - res = append(res, err) - } - if len(res) > 0 { - return errors.CompositeValidationError(res...) - } - return nil -} - -// bindOfficeUserID binds and validates parameter OfficeUserID from path. -func (o *GetRejectedOfficeUserParams) bindOfficeUserID(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("officeUserId", "path", "strfmt.UUID", raw) - } - o.OfficeUserID = *(value.(*strfmt.UUID)) - - if err := o.validateOfficeUserID(formats); err != nil { - return err - } - - return nil -} - -// validateOfficeUserID carries on validations for parameter OfficeUserID -func (o *GetRejectedOfficeUserParams) validateOfficeUserID(formats strfmt.Registry) error { - - if err := validate.FormatOf("officeUserId", "path", "uuid", o.OfficeUserID.String(), formats); err != nil { - return err - } - return nil -} diff --git a/pkg/gen/adminapi/adminoperations/rejected_office_users/get_rejected_office_user_responses.go b/pkg/gen/adminapi/adminoperations/rejected_office_users/get_rejected_office_user_responses.go deleted file mode 100644 index a67fcb04e3f..00000000000 --- a/pkg/gen/adminapi/adminoperations/rejected_office_users/get_rejected_office_user_responses.go +++ /dev/null @@ -1,159 +0,0 @@ -// Code generated by go-swagger; DO NOT EDIT. - -package rejected_office_users - -// 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/adminmessages" -) - -// GetRejectedOfficeUserOKCode is the HTTP code returned for type GetRejectedOfficeUserOK -const GetRejectedOfficeUserOKCode int = 200 - -/* -GetRejectedOfficeUserOK success - -swagger:response getRejectedOfficeUserOK -*/ -type GetRejectedOfficeUserOK struct { - - /* - In: Body - */ - Payload *adminmessages.OfficeUser `json:"body,omitempty"` -} - -// NewGetRejectedOfficeUserOK creates GetRejectedOfficeUserOK with default headers values -func NewGetRejectedOfficeUserOK() *GetRejectedOfficeUserOK { - - return &GetRejectedOfficeUserOK{} -} - -// WithPayload adds the payload to the get rejected office user o k response -func (o *GetRejectedOfficeUserOK) WithPayload(payload *adminmessages.OfficeUser) *GetRejectedOfficeUserOK { - o.Payload = payload - return o -} - -// SetPayload sets the payload to the get rejected office user o k response -func (o *GetRejectedOfficeUserOK) SetPayload(payload *adminmessages.OfficeUser) { - o.Payload = payload -} - -// WriteResponse to the client -func (o *GetRejectedOfficeUserOK) WriteResponse(rw http.ResponseWriter, producer runtime.Producer) { - - rw.WriteHeader(200) - if o.Payload != nil { - payload := o.Payload - if err := producer.Produce(rw, payload); err != nil { - panic(err) // let the recovery middleware deal with this - } - } -} - -// GetRejectedOfficeUserBadRequestCode is the HTTP code returned for type GetRejectedOfficeUserBadRequest -const GetRejectedOfficeUserBadRequestCode int = 400 - -/* -GetRejectedOfficeUserBadRequest invalid request - -swagger:response getRejectedOfficeUserBadRequest -*/ -type GetRejectedOfficeUserBadRequest struct { -} - -// NewGetRejectedOfficeUserBadRequest creates GetRejectedOfficeUserBadRequest with default headers values -func NewGetRejectedOfficeUserBadRequest() *GetRejectedOfficeUserBadRequest { - - return &GetRejectedOfficeUserBadRequest{} -} - -// WriteResponse to the client -func (o *GetRejectedOfficeUserBadRequest) WriteResponse(rw http.ResponseWriter, producer runtime.Producer) { - - rw.Header().Del(runtime.HeaderContentType) //Remove Content-Type on empty responses - - rw.WriteHeader(400) -} - -// GetRejectedOfficeUserUnauthorizedCode is the HTTP code returned for type GetRejectedOfficeUserUnauthorized -const GetRejectedOfficeUserUnauthorizedCode int = 401 - -/* -GetRejectedOfficeUserUnauthorized request requires user authentication - -swagger:response getRejectedOfficeUserUnauthorized -*/ -type GetRejectedOfficeUserUnauthorized struct { -} - -// NewGetRejectedOfficeUserUnauthorized creates GetRejectedOfficeUserUnauthorized with default headers values -func NewGetRejectedOfficeUserUnauthorized() *GetRejectedOfficeUserUnauthorized { - - return &GetRejectedOfficeUserUnauthorized{} -} - -// WriteResponse to the client -func (o *GetRejectedOfficeUserUnauthorized) WriteResponse(rw http.ResponseWriter, producer runtime.Producer) { - - rw.Header().Del(runtime.HeaderContentType) //Remove Content-Type on empty responses - - rw.WriteHeader(401) -} - -// GetRejectedOfficeUserNotFoundCode is the HTTP code returned for type GetRejectedOfficeUserNotFound -const GetRejectedOfficeUserNotFoundCode int = 404 - -/* -GetRejectedOfficeUserNotFound Office User not found - -swagger:response getRejectedOfficeUserNotFound -*/ -type GetRejectedOfficeUserNotFound struct { -} - -// NewGetRejectedOfficeUserNotFound creates GetRejectedOfficeUserNotFound with default headers values -func NewGetRejectedOfficeUserNotFound() *GetRejectedOfficeUserNotFound { - - return &GetRejectedOfficeUserNotFound{} -} - -// WriteResponse to the client -func (o *GetRejectedOfficeUserNotFound) WriteResponse(rw http.ResponseWriter, producer runtime.Producer) { - - rw.Header().Del(runtime.HeaderContentType) //Remove Content-Type on empty responses - - rw.WriteHeader(404) -} - -// GetRejectedOfficeUserInternalServerErrorCode is the HTTP code returned for type GetRejectedOfficeUserInternalServerError -const GetRejectedOfficeUserInternalServerErrorCode int = 500 - -/* -GetRejectedOfficeUserInternalServerError server error - -swagger:response getRejectedOfficeUserInternalServerError -*/ -type GetRejectedOfficeUserInternalServerError struct { -} - -// NewGetRejectedOfficeUserInternalServerError creates GetRejectedOfficeUserInternalServerError with default headers values -func NewGetRejectedOfficeUserInternalServerError() *GetRejectedOfficeUserInternalServerError { - - return &GetRejectedOfficeUserInternalServerError{} -} - -// WriteResponse to the client -func (o *GetRejectedOfficeUserInternalServerError) 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/adminapi/adminoperations/rejected_office_users/get_rejected_office_user_urlbuilder.go b/pkg/gen/adminapi/adminoperations/rejected_office_users/get_rejected_office_user_urlbuilder.go deleted file mode 100644 index 090820d35f5..00000000000 --- a/pkg/gen/adminapi/adminoperations/rejected_office_users/get_rejected_office_user_urlbuilder.go +++ /dev/null @@ -1,101 +0,0 @@ -// Code generated by go-swagger; DO NOT EDIT. - -package rejected_office_users - -// 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" -) - -// GetRejectedOfficeUserURL generates an URL for the get rejected office user operation -type GetRejectedOfficeUserURL struct { - OfficeUserID 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 *GetRejectedOfficeUserURL) WithBasePath(bp string) *GetRejectedOfficeUserURL { - 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 *GetRejectedOfficeUserURL) SetBasePath(bp string) { - o._basePath = bp -} - -// Build a url path and query string -func (o *GetRejectedOfficeUserURL) Build() (*url.URL, error) { - var _result url.URL - - var _path = "/rejected-office-users/{officeUserId}" - - officeUserID := o.OfficeUserID.String() - if officeUserID != "" { - _path = strings.Replace(_path, "{officeUserId}", officeUserID, -1) - } else { - return nil, errors.New("officeUserId is required on GetRejectedOfficeUserURL") - } - - _basePath := o._basePath - if _basePath == "" { - _basePath = "/admin/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 *GetRejectedOfficeUserURL) 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 *GetRejectedOfficeUserURL) String() string { - return o.Must(o.Build()).String() -} - -// BuildFull builds a full url with scheme, host, path and query string -func (o *GetRejectedOfficeUserURL) BuildFull(scheme, host string) (*url.URL, error) { - if scheme == "" { - return nil, errors.New("scheme is required for a full url on GetRejectedOfficeUserURL") - } - if host == "" { - return nil, errors.New("host is required for a full url on GetRejectedOfficeUserURL") - } - - 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 *GetRejectedOfficeUserURL) StringFull(scheme, host string) string { - return o.Must(o.BuildFull(scheme, host)).String() -} diff --git a/pkg/gen/adminapi/configure_mymove.go b/pkg/gen/adminapi/configure_mymove.go index a6809ba55be..4548f47231a 100644 --- a/pkg/gen/adminapi/configure_mymove.go +++ b/pkg/gen/adminapi/configure_mymove.go @@ -113,11 +113,6 @@ func configureAPI(api *adminoperations.MymoveAPI) http.Handler { return middleware.NotImplemented("operation office_users.GetOfficeUser has not yet been implemented") }) } - if api.RejectedOfficeUsersGetRejectedOfficeUserHandler == nil { - api.RejectedOfficeUsersGetRejectedOfficeUserHandler = rejected_office_users.GetRejectedOfficeUserHandlerFunc(func(params rejected_office_users.GetRejectedOfficeUserParams) middleware.Responder { - return middleware.NotImplemented("operation rejected_office_users.GetRejectedOfficeUser has not yet been implemented") - }) - } if api.RequestedOfficeUsersGetRequestedOfficeUserHandler == nil { api.RequestedOfficeUsersGetRequestedOfficeUserHandler = requested_office_users.GetRequestedOfficeUserHandlerFunc(func(params requested_office_users.GetRequestedOfficeUserParams) middleware.Responder { return middleware.NotImplemented("operation requested_office_users.GetRequestedOfficeUser has not yet been implemented") diff --git a/pkg/gen/adminapi/embedded_spec.go b/pkg/gen/adminapi/embedded_spec.go index 5aa58228261..71e67bc6696 100644 --- a/pkg/gen/adminapi/embedded_spec.go +++ b/pkg/gen/adminapi/embedded_spec.go @@ -1465,48 +1465,6 @@ func init() { } } }, - "/rejected-office-users/{officeUserId}": { - "get": { - "description": "Retrieving a single office user in any status. This endpoint is used in the Admin UI that will allow the admin user to view the user's relevant data.", - "produces": [ - "application/json" - ], - "tags": [ - "Rejected office users" - ], - "summary": "Get a Rejected Office User", - "operationId": "getRejectedOfficeUser", - "parameters": [ - { - "type": "string", - "format": "uuid", - "name": "officeUserId", - "in": "path", - "required": true - } - ], - "responses": { - "200": { - "description": "success", - "schema": { - "$ref": "#/definitions/OfficeUser" - } - }, - "400": { - "description": "invalid request" - }, - "401": { - "description": "request requires user authentication" - }, - "404": { - "description": "Office User not found" - }, - "500": { - "description": "server error" - } - } - } - }, "/requested-office-users": { "get": { "description": "This endpoint returns a list of Office Users. Do not use this endpoint directly\nas it is meant to be used with the Admin UI exclusively.\n", @@ -5276,48 +5234,6 @@ func init() { } } }, - "/rejected-office-users/{officeUserId}": { - "get": { - "description": "Retrieving a single office user in any status. This endpoint is used in the Admin UI that will allow the admin user to view the user's relevant data.", - "produces": [ - "application/json" - ], - "tags": [ - "Rejected office users" - ], - "summary": "Get a Rejected Office User", - "operationId": "getRejectedOfficeUser", - "parameters": [ - { - "type": "string", - "format": "uuid", - "name": "officeUserId", - "in": "path", - "required": true - } - ], - "responses": { - "200": { - "description": "success", - "schema": { - "$ref": "#/definitions/OfficeUser" - } - }, - "400": { - "description": "invalid request" - }, - "401": { - "description": "request requires user authentication" - }, - "404": { - "description": "Office User not found" - }, - "500": { - "description": "server error" - } - } - } - }, "/requested-office-users": { "get": { "description": "This endpoint returns a list of Office Users. Do not use this endpoint directly\nas it is meant to be used with the Admin UI exclusively.\n", diff --git a/pkg/handlers/adminapi/rejected_office_users.go b/pkg/handlers/adminapi/rejected_office_users.go index 86d23f415d1..eb7015a78d9 100644 --- a/pkg/handlers/adminapi/rejected_office_users.go +++ b/pkg/handlers/adminapi/rejected_office_users.go @@ -4,7 +4,6 @@ import ( "fmt" "github.com/go-openapi/runtime/middleware" - "go.uber.org/zap" "github.com/transcom/mymove/pkg/appcontext" "github.com/transcom/mymove/pkg/gen/adminapi/adminoperations/rejected_office_users" @@ -111,39 +110,3 @@ func (h IndexRejectedOfficeUsersHandler) Handle(params rejected_office_users.Ind return rejected_office_users.NewIndexRejectedOfficeUsersOK().WithContentRange(fmt.Sprintf("rejected office users %d-%d/%d", pagination.Offset(), pagination.Offset()+queriedOfficeUsersCount, totalOfficeUsersCount)).WithPayload(payload), nil }) } - -// GetRejectedOfficeUserHandler returns a list of office users via GET /rejected_office_users/{officeUserId} -type GetRejectedOfficeUserHandler struct { - handlers.HandlerConfig - services.RejectedOfficeUserFetcher - services.RoleAssociater - services.NewQueryFilter -} - -// Handle retrieves a single rejected office user -func (h GetRejectedOfficeUserHandler) Handle(params rejected_office_users.GetRejectedOfficeUserParams) middleware.Responder { - return h.AuditableAppContextFromRequestWithErrors(params.HTTPRequest, - func(appCtx appcontext.AppContext) (middleware.Responder, error) { - - rejectedOfficeUserID := params.OfficeUserID - - queryFilters := []services.QueryFilter{query.NewQueryFilter("id", "=", rejectedOfficeUserID)} - rejectedOfficeUser, err := h.RejectedOfficeUserFetcher.FetchRejectedOfficeUser(appCtx, queryFilters) - - if err != nil { - return handlers.ResponseForError(appCtx.Logger(), err), err - } - - roles, err := h.RoleAssociater.FetchRolesForUser(appCtx, *rejectedOfficeUser.UserID) - if err != nil { - appCtx.Logger().Error("Error fetching user roles", zap.Error(err)) - return rejected_office_users.NewGetRejectedOfficeUserBadRequest(), err - } - - rejectedOfficeUser.User.Roles = roles - - payload := payloadForRejectedOfficeUserModel(rejectedOfficeUser) - - return rejected_office_users.NewGetRejectedOfficeUserOK().WithPayload(payload), nil - }) -} diff --git a/pkg/services/mocks/WeightAllotmentFetcher.go b/pkg/services/mocks/WeightAllotmentFetcher.go new file mode 100644 index 00000000000..fa36bfbee2e --- /dev/null +++ b/pkg/services/mocks/WeightAllotmentFetcher.go @@ -0,0 +1,117 @@ +// Code generated by mockery. DO NOT EDIT. + +package mocks + +import ( + appcontext "github.com/transcom/mymove/pkg/appcontext" + internalmessages "github.com/transcom/mymove/pkg/gen/internalmessages" + + mock "github.com/stretchr/testify/mock" + + models "github.com/transcom/mymove/pkg/models" +) + +// WeightAllotmentFetcher is an autogenerated mock type for the WeightAllotmentFetcher type +type WeightAllotmentFetcher struct { + mock.Mock +} + +// GetAllWeightAllotments provides a mock function with given fields: appCtx +func (_m *WeightAllotmentFetcher) GetAllWeightAllotments(appCtx appcontext.AppContext) (map[internalmessages.OrderPayGrade]models.WeightAllotment, error) { + ret := _m.Called(appCtx) + + if len(ret) == 0 { + panic("no return value specified for GetAllWeightAllotments") + } + + var r0 map[internalmessages.OrderPayGrade]models.WeightAllotment + var r1 error + if rf, ok := ret.Get(0).(func(appcontext.AppContext) (map[internalmessages.OrderPayGrade]models.WeightAllotment, error)); ok { + return rf(appCtx) + } + if rf, ok := ret.Get(0).(func(appcontext.AppContext) map[internalmessages.OrderPayGrade]models.WeightAllotment); ok { + r0 = rf(appCtx) + } else { + if ret.Get(0) != nil { + r0 = ret.Get(0).(map[internalmessages.OrderPayGrade]models.WeightAllotment) + } + } + + if rf, ok := ret.Get(1).(func(appcontext.AppContext) error); ok { + r1 = rf(appCtx) + } else { + r1 = ret.Error(1) + } + + return r0, r1 +} + +// GetWeightAllotment provides a mock function with given fields: appCtx, grade, ordersType +func (_m *WeightAllotmentFetcher) GetWeightAllotment(appCtx appcontext.AppContext, grade string, ordersType internalmessages.OrdersType) (models.WeightAllotment, error) { + ret := _m.Called(appCtx, grade, ordersType) + + if len(ret) == 0 { + panic("no return value specified for GetWeightAllotment") + } + + var r0 models.WeightAllotment + var r1 error + if rf, ok := ret.Get(0).(func(appcontext.AppContext, string, internalmessages.OrdersType) (models.WeightAllotment, error)); ok { + return rf(appCtx, grade, ordersType) + } + if rf, ok := ret.Get(0).(func(appcontext.AppContext, string, internalmessages.OrdersType) models.WeightAllotment); ok { + r0 = rf(appCtx, grade, ordersType) + } else { + r0 = ret.Get(0).(models.WeightAllotment) + } + + if rf, ok := ret.Get(1).(func(appcontext.AppContext, string, internalmessages.OrdersType) error); ok { + r1 = rf(appCtx, grade, ordersType) + } else { + r1 = ret.Error(1) + } + + return r0, r1 +} + +// GetWeightAllotmentByOrdersType provides a mock function with given fields: appCtx, ordersType +func (_m *WeightAllotmentFetcher) GetWeightAllotmentByOrdersType(appCtx appcontext.AppContext, ordersType internalmessages.OrdersType) (models.WeightAllotment, error) { + ret := _m.Called(appCtx, ordersType) + + if len(ret) == 0 { + panic("no return value specified for GetWeightAllotmentByOrdersType") + } + + var r0 models.WeightAllotment + var r1 error + if rf, ok := ret.Get(0).(func(appcontext.AppContext, internalmessages.OrdersType) (models.WeightAllotment, error)); ok { + return rf(appCtx, ordersType) + } + if rf, ok := ret.Get(0).(func(appcontext.AppContext, internalmessages.OrdersType) models.WeightAllotment); ok { + r0 = rf(appCtx, ordersType) + } else { + r0 = ret.Get(0).(models.WeightAllotment) + } + + if rf, ok := ret.Get(1).(func(appcontext.AppContext, internalmessages.OrdersType) error); ok { + r1 = rf(appCtx, ordersType) + } else { + r1 = ret.Error(1) + } + + return r0, r1 +} + +// NewWeightAllotmentFetcher creates a new instance of WeightAllotmentFetcher. It also registers a testing interface on the mock and a cleanup function to assert the mocks expectations. +// The first argument is typically a *testing.T value. +func NewWeightAllotmentFetcher(t interface { + mock.TestingT + Cleanup(func()) +}) *WeightAllotmentFetcher { + mock := &WeightAllotmentFetcher{} + mock.Mock.Test(t) + + t.Cleanup(func() { mock.AssertExpectations(t) }) + + return mock +} diff --git a/pkg/services/mocks/WeightRestrictor.go b/pkg/services/mocks/WeightRestrictor.go new file mode 100644 index 00000000000..6f7ad72bae4 --- /dev/null +++ b/pkg/services/mocks/WeightRestrictor.go @@ -0,0 +1,89 @@ +// Code generated by mockery. DO NOT EDIT. + +package mocks + +import ( + mock "github.com/stretchr/testify/mock" + appcontext "github.com/transcom/mymove/pkg/appcontext" + + models "github.com/transcom/mymove/pkg/models" +) + +// WeightRestrictor is an autogenerated mock type for the WeightRestrictor type +type WeightRestrictor struct { + mock.Mock +} + +// ApplyWeightRestrictionToEntitlement provides a mock function with given fields: appCtx, entitlement, weightRestriction, eTag +func (_m *WeightRestrictor) ApplyWeightRestrictionToEntitlement(appCtx appcontext.AppContext, entitlement models.Entitlement, weightRestriction int, eTag string) (*models.Entitlement, error) { + ret := _m.Called(appCtx, entitlement, weightRestriction, eTag) + + if len(ret) == 0 { + panic("no return value specified for ApplyWeightRestrictionToEntitlement") + } + + var r0 *models.Entitlement + var r1 error + if rf, ok := ret.Get(0).(func(appcontext.AppContext, models.Entitlement, int, string) (*models.Entitlement, error)); ok { + return rf(appCtx, entitlement, weightRestriction, eTag) + } + if rf, ok := ret.Get(0).(func(appcontext.AppContext, models.Entitlement, int, string) *models.Entitlement); ok { + r0 = rf(appCtx, entitlement, weightRestriction, eTag) + } else { + if ret.Get(0) != nil { + r0 = ret.Get(0).(*models.Entitlement) + } + } + + if rf, ok := ret.Get(1).(func(appcontext.AppContext, models.Entitlement, int, string) error); ok { + r1 = rf(appCtx, entitlement, weightRestriction, eTag) + } else { + r1 = ret.Error(1) + } + + return r0, r1 +} + +// RemoveWeightRestrictionFromEntitlement provides a mock function with given fields: appCtx, entitlement, eTag +func (_m *WeightRestrictor) RemoveWeightRestrictionFromEntitlement(appCtx appcontext.AppContext, entitlement models.Entitlement, eTag string) (*models.Entitlement, error) { + ret := _m.Called(appCtx, entitlement, eTag) + + if len(ret) == 0 { + panic("no return value specified for RemoveWeightRestrictionFromEntitlement") + } + + var r0 *models.Entitlement + var r1 error + if rf, ok := ret.Get(0).(func(appcontext.AppContext, models.Entitlement, string) (*models.Entitlement, error)); ok { + return rf(appCtx, entitlement, eTag) + } + if rf, ok := ret.Get(0).(func(appcontext.AppContext, models.Entitlement, string) *models.Entitlement); ok { + r0 = rf(appCtx, entitlement, eTag) + } else { + if ret.Get(0) != nil { + r0 = ret.Get(0).(*models.Entitlement) + } + } + + if rf, ok := ret.Get(1).(func(appcontext.AppContext, models.Entitlement, string) error); ok { + r1 = rf(appCtx, entitlement, eTag) + } else { + r1 = ret.Error(1) + } + + return r0, r1 +} + +// NewWeightRestrictor creates a new instance of WeightRestrictor. It also registers a testing interface on the mock and a cleanup function to assert the mocks expectations. +// The first argument is typically a *testing.T value. +func NewWeightRestrictor(t interface { + mock.TestingT + Cleanup(func()) +}) *WeightRestrictor { + mock := &WeightRestrictor{} + mock.Mock.Test(t) + + t.Cleanup(func() { mock.AssertExpectations(t) }) + + return mock +} diff --git a/swagger-def/admin.yaml b/swagger-def/admin.yaml index 22f82591ae2..0612515b63e 100644 --- a/swagger-def/admin.yaml +++ b/swagger-def/admin.yaml @@ -1467,34 +1467,6 @@ paths: description: Office User not found "500": description: server error - /rejected-office-users/{officeUserId}: - get: - produces: - - application/json - summary: Get a Rejected Office User - description: Retrieving a single office user in any status. This endpoint is used in the Admin UI that will allow the admin user to view the user's relevant data. - operationId: getRejectedOfficeUser - tags: - - Rejected office users - parameters: - - in: path - name: officeUserId - type: string - format: uuid - required: true - responses: - "200": - description: success - schema: - $ref: "#/definitions/OfficeUser" - "400": - description: invalid request - "401": - description: request requires user authentication - "404": - description: Office User not found - "500": - description: server error /office-users: get: produces: diff --git a/swagger/admin.yaml b/swagger/admin.yaml index 05ff4d37e2d..b9c42f2c98c 100644 --- a/swagger/admin.yaml +++ b/swagger/admin.yaml @@ -1486,37 +1486,6 @@ paths: description: Office User not found '500': description: server error - /rejected-office-users/{officeUserId}: - get: - produces: - - application/json - summary: Get a Rejected Office User - description: >- - Retrieving a single office user in any status. This endpoint is used in - the Admin UI that will allow the admin user to view the user's relevant - data. - operationId: getRejectedOfficeUser - tags: - - Rejected office users - parameters: - - in: path - name: officeUserId - type: string - format: uuid - required: true - responses: - '200': - description: success - schema: - $ref: '#/definitions/OfficeUser' - '400': - description: invalid request - '401': - description: request requires user authentication - '404': - description: Office User not found - '500': - description: server error /office-users: get: produces: From 159699fa3c8a1ed32f58cff8a3d41d1b4ad598d3 Mon Sep 17 00:00:00 2001 From: Konstance Haffaney Date: Tue, 11 Feb 2025 19:12:20 +0000 Subject: [PATCH 15/37] testing string --- pkg/models/models.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pkg/models/models.go b/pkg/models/models.go index 32e9338d23c..61a1b43610b 100644 --- a/pkg/models/models.go +++ b/pkg/models/models.go @@ -11,7 +11,7 @@ import ( // EagerAssociations are a collection of named associations type EagerAssociations []string -// StringPointer allows you to take the address of a string literal. +// testing comment StringPointer allows you to take the address of a string literal. // It is useful for initializing string pointer fields in model construction func StringPointer(s string) *string { return &s From 8c70f48d350000a509d7de47713a79b6e95d6ab1 Mon Sep 17 00:00:00 2001 From: Konstance Haffaney Date: Tue, 11 Feb 2025 19:40:59 +0000 Subject: [PATCH 16/37] removing unused --- pkg/handlers/adminapi/api.go | 7 - .../adminapi/rejected_office_users_test.go | 142 +----------------- .../mocks/RejectedOfficeUserFetcherPop.go | 14 -- pkg/services/rejected_office_users.go | 9 -- .../rejected_office_user_fetcher.go | 58 ------- .../rejected_office_user_fetcher_test.go | 90 ----------- 6 files changed, 1 insertion(+), 319 deletions(-) delete mode 100644 pkg/services/rejected_office_users/rejected_office_user_fetcher.go delete mode 100644 pkg/services/rejected_office_users/rejected_office_user_fetcher_test.go diff --git a/pkg/handlers/adminapi/api.go b/pkg/handlers/adminapi/api.go index 3263cc482f7..ffce154f4cc 100644 --- a/pkg/handlers/adminapi/api.go +++ b/pkg/handlers/adminapi/api.go @@ -88,13 +88,6 @@ func NewAdminAPI(handlerConfig handlers.HandlerConfig) *adminops.MymoveAPI { pagination.NewPagination, } - adminAPI.RejectedOfficeUsersGetRejectedOfficeUserHandler = GetRejectedOfficeUserHandler{ - handlerConfig, - rejectedofficeusers.NewRejectedOfficeUserFetcher(queryBuilder), - newRolesFetcher, - query.NewQueryFilter, - } - adminAPI.OfficeUsersIndexOfficeUsersHandler = IndexOfficeUsersHandler{ handlerConfig, fetch.NewListFetcher(queryBuilder), diff --git a/pkg/handlers/adminapi/rejected_office_users_test.go b/pkg/handlers/adminapi/rejected_office_users_test.go index 40d11eefb2b..f59cb13ef84 100644 --- a/pkg/handlers/adminapi/rejected_office_users_test.go +++ b/pkg/handlers/adminapi/rejected_office_users_test.go @@ -1,20 +1,10 @@ package adminapi import ( - "fmt" - "net/http" - "time" - - "github.com/go-openapi/strfmt" - "github.com/gofrs/uuid" - "github.com/stretchr/testify/mock" - "github.com/transcom/mymove/pkg/factory" rejectedofficeuserop "github.com/transcom/mymove/pkg/gen/adminapi/adminoperations/rejected_office_users" - "github.com/transcom/mymove/pkg/handlers" "github.com/transcom/mymove/pkg/models" "github.com/transcom/mymove/pkg/models/roles" - "github.com/transcom/mymove/pkg/services/mocks" "github.com/transcom/mymove/pkg/services/pagination" "github.com/transcom/mymove/pkg/services/query" rejectedofficeusers "github.com/transcom/mymove/pkg/services/rejected_office_users" @@ -48,134 +38,4 @@ func (suite *HandlerSuite) TestIndexRejectedOfficeUsersHandler() { suite.Len(okResponse.Payload, 2) suite.Equal(rejectedOfficeUsers[0].ID.String(), okResponse.Payload[0].ID.String()) }) -} - -func (suite *HandlerSuite) TestGetRejectedOfficeUserHandler() { - // test that everything is wired up - suite.Run("integration test ok response", func() { - rejectedOfficeUser := factory.BuildOfficeUserWithRoles(suite.DB(), factory.GetTraitRejectedOfficeUser(), []roles.RoleType{roles.RoleTypeQae}) - params := rejectedofficeuserop.GetRejectedOfficeUserParams{ - HTTPRequest: suite.setupAuthenticatedRequest("GET", fmt.Sprintf("/rejected_office_users/%s", rejectedOfficeUser.ID)), - OfficeUserID: strfmt.UUID(rejectedOfficeUser.ID.String()), - } - - mockRoleAssociator := &mocks.RoleAssociater{} - mockRoles := roles.Roles{ - roles.Role{ - ID: uuid.Must(uuid.NewV4()), - RoleType: roles.RoleTypeTOO, - RoleName: "Task Ordering Officer", - CreatedAt: time.Now(), - UpdatedAt: time.Now(), - }, - } - mockRoleAssociator.On( - "FetchRolesForUser", - mock.AnythingOfType("*appcontext.appContext"), - mock.Anything, - ).Return(mockRoles, nil) - - queryBuilder := query.NewQueryBuilder() - handler := GetRejectedOfficeUserHandler{ - suite.HandlerConfig(), - rejectedofficeusers.NewRejectedOfficeUserFetcher(queryBuilder), - mockRoleAssociator, - query.NewQueryFilter, - } - - response := handler.Handle(params) - - suite.IsType(&rejectedofficeuserop.GetRejectedOfficeUserOK{}, response) - okResponse := response.(*rejectedofficeuserop.GetRejectedOfficeUserOK) - suite.Equal(rejectedOfficeUser.ID.String(), okResponse.Payload.ID.String()) - }) - - suite.Run("successful response", func() { - rejectedOfficeUser := factory.BuildOfficeUserWithRoles(suite.DB(), factory.GetTraitRejectedOfficeUser(), []roles.RoleType{roles.RoleTypeQae}) - params := rejectedofficeuserop.GetRejectedOfficeUserParams{ - HTTPRequest: suite.setupAuthenticatedRequest("GET", fmt.Sprintf("/rejected_office_users/%s", rejectedOfficeUser.ID)), - OfficeUserID: strfmt.UUID(rejectedOfficeUser.ID.String()), - } - - rejectedOfficeUserFetcher := &mocks.RejectedOfficeUserFetcher{} - rejectedOfficeUserFetcher.On("FetchRejectedOfficeUser", - mock.AnythingOfType("*appcontext.appContext"), - mock.Anything, - ).Return(rejectedOfficeUser, nil).Once() - - mockRoleAssociator := &mocks.RoleAssociater{} - mockRoles := roles.Roles{ - roles.Role{ - ID: uuid.Must(uuid.NewV4()), - RoleType: roles.RoleTypeTOO, - RoleName: "Task Ordering Officer", - CreatedAt: time.Now(), - UpdatedAt: time.Now(), - }, - } - mockRoleAssociator.On( - "FetchRolesForUser", - mock.AnythingOfType("*appcontext.appContext"), - mock.Anything, - ).Return(mockRoles, nil) - - handler := GetRejectedOfficeUserHandler{ - suite.HandlerConfig(), - rejectedOfficeUserFetcher, - mockRoleAssociator, - newMockQueryFilterBuilder(&mocks.QueryFilter{}), - } - - response := handler.Handle(params) - - suite.IsType(&rejectedofficeuserop.GetRejectedOfficeUserOK{}, response) - okResponse := response.(*rejectedofficeuserop.GetRejectedOfficeUserOK) - suite.Equal(rejectedOfficeUser.ID.String(), okResponse.Payload.ID.String()) - }) - - suite.Run("unsuccessful response when fetch fails", func() { - rejectedOfficeUser := factory.BuildOfficeUserWithRoles(suite.DB(), factory.GetTraitRejectedOfficeUser(), []roles.RoleType{roles.RoleTypeQae}) - params := rejectedofficeuserop.GetRejectedOfficeUserParams{ - HTTPRequest: suite.setupAuthenticatedRequest("GET", fmt.Sprintf("/rejected_office_users/%s", rejectedOfficeUser.ID)), - OfficeUserID: strfmt.UUID(rejectedOfficeUser.ID.String()), - } - - expectedError := models.ErrFetchNotFound - rejectedOfficeUserFetcher := &mocks.RejectedOfficeUserFetcher{} - rejectedOfficeUserFetcher.On("FetchRejectedOfficeUser", - mock.AnythingOfType("*appcontext.appContext"), - mock.Anything, - ).Return(models.OfficeUser{}, expectedError).Once() - - mockRoleAssociator := &mocks.RoleAssociater{} - mockRoles := roles.Roles{ - roles.Role{ - ID: uuid.Must(uuid.NewV4()), - RoleType: roles.RoleTypeTOO, - RoleName: "Task Ordering Officer", - CreatedAt: time.Now(), - UpdatedAt: time.Now(), - }, - } - mockRoleAssociator.On( - "FetchRolesForUser", - mock.AnythingOfType("*appcontext.appContext"), - mock.Anything, - ).Return(mockRoles, nil) - - handler := GetRejectedOfficeUserHandler{ - suite.HandlerConfig(), - rejectedOfficeUserFetcher, - mockRoleAssociator, - newMockQueryFilterBuilder(&mocks.QueryFilter{}), - } - - response := handler.Handle(params) - - expectedResponse := &handlers.ErrResponse{ - Code: http.StatusNotFound, - Err: expectedError, - } - suite.Equal(expectedResponse, response) - }) -} +} \ No newline at end of file diff --git a/pkg/services/mocks/RejectedOfficeUserFetcherPop.go b/pkg/services/mocks/RejectedOfficeUserFetcherPop.go index 1a413118434..c6a7083afb2 100644 --- a/pkg/services/mocks/RejectedOfficeUserFetcherPop.go +++ b/pkg/services/mocks/RejectedOfficeUserFetcherPop.go @@ -43,17 +43,3 @@ func (_m *RejectedOfficeUserFetcherPop) FetchRejectedOfficeUserByID(appCtx appco return r0, r1 } - -// NewRejectedOfficeUserFetcherPop creates a new instance of RejectedOfficeUserFetcherPop. It also registers a testing interface on the mock and a cleanup function to assert the mocks expectations. -// The first argument is typically a *testing.T value. -func NewRejectedOfficeUserFetcherPop(t interface { - mock.TestingT - Cleanup(func()) -}) *RejectedOfficeUserFetcherPop { - mock := &RejectedOfficeUserFetcherPop{} - mock.Mock.Test(t) - - t.Cleanup(func() { mock.AssertExpectations(t) }) - - return mock -} diff --git a/pkg/services/rejected_office_users.go b/pkg/services/rejected_office_users.go index fe1ba485a0b..1a7d57990f4 100644 --- a/pkg/services/rejected_office_users.go +++ b/pkg/services/rejected_office_users.go @@ -1,8 +1,6 @@ package services import ( - "github.com/gofrs/uuid" - "github.com/transcom/mymove/pkg/appcontext" "github.com/transcom/mymove/pkg/models" ) @@ -21,10 +19,3 @@ type RejectedOfficeUserListFetcher interface { type RejectedOfficeUserFetcher interface { FetchRejectedOfficeUser(appCtx appcontext.AppContext, filters []QueryFilter) (models.OfficeUser, error) } - -// RejectedOfficeUserFetcherPop is the exported interface for fetching a single office user -// -//go:generate mockery --name RejectedOfficeUserFetcherPop -type RejectedOfficeUserFetcherPop interface { - FetchRejectedOfficeUserByID(appCtx appcontext.AppContext, id uuid.UUID) (models.OfficeUser, error) -} diff --git a/pkg/services/rejected_office_users/rejected_office_user_fetcher.go b/pkg/services/rejected_office_users/rejected_office_user_fetcher.go deleted file mode 100644 index ca24b44d5b1..00000000000 --- a/pkg/services/rejected_office_users/rejected_office_user_fetcher.go +++ /dev/null @@ -1,58 +0,0 @@ -package adminuser - -import ( - "database/sql" - - "github.com/gobuffalo/validate/v3" - "github.com/gofrs/uuid" - - "github.com/transcom/mymove/pkg/appcontext" - "github.com/transcom/mymove/pkg/apperror" - "github.com/transcom/mymove/pkg/models" - "github.com/transcom/mymove/pkg/services" -) - -type rejectedOfficeUserQueryBuilder interface { - FetchOne(appCtx appcontext.AppContext, model interface{}, filters []services.QueryFilter) error - UpdateOne(appCtx appcontext.AppContext, model interface{}, eTag *string) (*validate.Errors, error) -} - -type rejectedOfficeUserFetcher struct { - builder rejectedOfficeUserQueryBuilder -} - -// FetchRejectedOfficeUser fetches an office user given a slice of filters -func (o *rejectedOfficeUserFetcher) FetchRejectedOfficeUser(appCtx appcontext.AppContext, filters []services.QueryFilter) (models.OfficeUser, error) { - var rejectedOfficeUser models.OfficeUser - err := o.builder.FetchOne(appCtx, &rejectedOfficeUser, filters) - return rejectedOfficeUser, err -} - -// NewAdminUserFetcher return an implementation of the AdminUserFetcher interface -func NewRejectedOfficeUserFetcher(builder rejectedOfficeUserQueryBuilder) services.RejectedOfficeUserFetcher { - return &rejectedOfficeUserFetcher{builder} -} - -type rejectedOfficeUserFetcherPop struct { -} - -// FetchOfficeUserByID fetches an office user given an ID -func (o *rejectedOfficeUserFetcherPop) FetchRejectedOfficeUserByID(appCtx appcontext.AppContext, id uuid.UUID) (models.OfficeUser, error) { - var officeUser models.OfficeUser - err := appCtx.DB().Eager("TransportationOffice").Find(&officeUser, id) - if err != nil { - switch err { - case sql.ErrNoRows: - return models.OfficeUser{}, apperror.NewNotFoundError(id, "looking for OfficeUser") - default: - return models.OfficeUser{}, apperror.NewQueryError("OfficeUser", err, "") - } - } - - return officeUser, err -} - -// NewOfficeUserFetcherPop return an implementation of the OfficeUserFetcherPop interface -func NewRejectedOfficeUserFetcherPop() services.RejectedOfficeUserFetcherPop { - return &rejectedOfficeUserFetcherPop{} -} diff --git a/pkg/services/rejected_office_users/rejected_office_user_fetcher_test.go b/pkg/services/rejected_office_users/rejected_office_user_fetcher_test.go deleted file mode 100644 index 5ac38aae67f..00000000000 --- a/pkg/services/rejected_office_users/rejected_office_user_fetcher_test.go +++ /dev/null @@ -1,90 +0,0 @@ -package adminuser - -import ( - "errors" - "reflect" - - "github.com/gobuffalo/validate/v3" - "github.com/gofrs/uuid" - - "github.com/transcom/mymove/pkg/appcontext" - "github.com/transcom/mymove/pkg/apperror" - "github.com/transcom/mymove/pkg/factory" - "github.com/transcom/mymove/pkg/models" - "github.com/transcom/mymove/pkg/models/roles" - "github.com/transcom/mymove/pkg/services" - "github.com/transcom/mymove/pkg/services/query" -) - -type testRejectedOfficeUsersQueryBuilder struct { - fakeFetchOne func(appConfig appcontext.AppContext, model interface{}) error -} - -func (t *testRejectedOfficeUsersQueryBuilder) FetchOne(appConfig appcontext.AppContext, model interface{}, _ []services.QueryFilter) error { - m := t.fakeFetchOne(appConfig, model) - return m -} - -func (t *testRejectedOfficeUsersQueryBuilder) UpdateOne(_ appcontext.AppContext, _ interface{}, _ *string) (*validate.Errors, error) { - return nil, nil -} - -func (suite *RejectedOfficeUsersServiceSuite) TestFetchRejectedOfficeUser() { - suite.Run("if the rejected office user is fetched, it should be returned", func() { - id, err := uuid.NewV4() - suite.NoError(err) - fakeFetchOne := func(_ appcontext.AppContext, model interface{}) error { - reflect.ValueOf(model).Elem().FieldByName("ID").Set(reflect.ValueOf(id)) - return nil - } - - builder := &testRejectedOfficeUsersQueryBuilder{ - fakeFetchOne: fakeFetchOne, - } - - fetcher := NewRejectedOfficeUserFetcher(builder) - filters := []services.QueryFilter{query.NewQueryFilter("id", "=", id.String())} - - rejectedOfficeUser, err := fetcher.FetchRejectedOfficeUser(suite.AppContextForTest(), filters) - - suite.NoError(err) - suite.Equal(id, rejectedOfficeUser.ID) - }) - - suite.Run("if there is an error, we get it with zero admin user", func() { - fakeFetchOne := func(_ appcontext.AppContext, _ interface{}) error { - return errors.New("Fetch error") - } - builder := &testRejectedOfficeUsersQueryBuilder{ - fakeFetchOne: fakeFetchOne, - } - fetcher := NewRejectedOfficeUserFetcher(builder) - - rejectedOfficeUser, err := fetcher.FetchRejectedOfficeUser(suite.AppContextForTest(), []services.QueryFilter{}) - - suite.Error(err) - suite.Equal(err.Error(), "Fetch error") - suite.Equal(models.OfficeUser{}, rejectedOfficeUser) - }) -} - -func (suite *RejectedOfficeUsersServiceSuite) TestFetchRejectedOfficeUserPop() { - suite.Run("returns office user on success", func() { - officeUser := factory.BuildOfficeUserWithRoles(suite.DB(), nil, []roles.RoleType{roles.RoleTypeTOO}) - fetcher := NewRejectedOfficeUserFetcherPop() - - fetchedUser, err := fetcher.FetchRejectedOfficeUserByID(suite.AppContextForTest(), officeUser.ID) - - suite.NoError(err) - suite.Equal(officeUser.ID, fetchedUser.ID) - }) - - suite.Run("returns zero value office user on error", func() { - fetcher := NewRejectedOfficeUserFetcherPop() - officeUser, err := fetcher.FetchRejectedOfficeUserByID(suite.AppContextForTest(), uuid.Nil) - - suite.Error(err) - suite.IsType(apperror.NotFoundError{}, err) - suite.Equal(uuid.Nil, officeUser.ID) - }) -} From 6258e2c209d5cfb8b692447a31524007f6b64b92 Mon Sep 17 00:00:00 2001 From: Konstance Haffaney Date: Tue, 11 Feb 2025 19:45:37 +0000 Subject: [PATCH 17/37] fix font --- src/pages/Admin/RejectedOfficeUsers/RejectedOfficeUserList.jsx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/pages/Admin/RejectedOfficeUsers/RejectedOfficeUserList.jsx b/src/pages/Admin/RejectedOfficeUsers/RejectedOfficeUserList.jsx index 63332ce19a2..d0278bc2e77 100644 --- a/src/pages/Admin/RejectedOfficeUsers/RejectedOfficeUserList.jsx +++ b/src/pages/Admin/RejectedOfficeUsers/RejectedOfficeUserList.jsx @@ -25,7 +25,7 @@ const RejectedOfficeUserShowRoles = () => { } } - return

{uniqueRoleNamesList.join(', ')}

; + return {uniqueRoleNamesList.join(', ')}; }; // Overriding the default toolbar From d17c7b3d53716908bfa85a68326b91bcca358179 Mon Sep 17 00:00:00 2001 From: Konstance Haffaney Date: Tue, 11 Feb 2025 20:25:09 +0000 Subject: [PATCH 18/37] adding generated files --- pkg/gen/ghcapi/embedded_spec.go | 6 +- pkg/services/mocks/IntlCratingPricer.go | 109 +++++++++++++++++++++ pkg/services/mocks/IntlUncratingPricer.go | 109 +++++++++++++++++++++ swagger/ghc.yaml | 112 ++++++++++++++++++++++ 4 files changed, 334 insertions(+), 2 deletions(-) create mode 100644 pkg/services/mocks/IntlCratingPricer.go create mode 100644 pkg/services/mocks/IntlUncratingPricer.go diff --git a/pkg/gen/ghcapi/embedded_spec.go b/pkg/gen/ghcapi/embedded_spec.go index 9470b809e63..ec08bd3f508 100644 --- a/pkg/gen/ghcapi/embedded_spec.go +++ b/pkg/gen/ghcapi/embedded_spec.go @@ -6001,7 +6001,8 @@ func init() { "application/json" ], "tags": [ - "shipment" + "shipment", + "shipment_address_updates" ], "summary": "Allows TOO to review a shipment address update", "operationId": "reviewShipmentAddressUpdate", @@ -23358,7 +23359,8 @@ func init() { "application/json" ], "tags": [ - "shipment" + "shipment", + "shipment_address_updates" ], "summary": "Allows TOO to review a shipment address update", "operationId": "reviewShipmentAddressUpdate", diff --git a/pkg/services/mocks/IntlCratingPricer.go b/pkg/services/mocks/IntlCratingPricer.go new file mode 100644 index 00000000000..0ada84deb77 --- /dev/null +++ b/pkg/services/mocks/IntlCratingPricer.go @@ -0,0 +1,109 @@ +// Code generated by mockery. DO NOT EDIT. + +package mocks + +import ( + mock "github.com/stretchr/testify/mock" + appcontext "github.com/transcom/mymove/pkg/appcontext" + + models "github.com/transcom/mymove/pkg/models" + + services "github.com/transcom/mymove/pkg/services" + + time "time" + + unit "github.com/transcom/mymove/pkg/unit" +) + +// IntlCratingPricer is an autogenerated mock type for the IntlCratingPricer type +type IntlCratingPricer struct { + mock.Mock +} + +// Price provides a mock function with given fields: appCtx, contractCode, requestedPickupDate, billedCubicFeet, standaloneCrate, standaloneCrateCap, externalCrate, market +func (_m *IntlCratingPricer) Price(appCtx appcontext.AppContext, contractCode string, requestedPickupDate time.Time, billedCubicFeet unit.CubicFeet, standaloneCrate bool, standaloneCrateCap unit.Cents, externalCrate bool, market models.Market) (unit.Cents, services.PricingDisplayParams, error) { + ret := _m.Called(appCtx, contractCode, requestedPickupDate, billedCubicFeet, standaloneCrate, standaloneCrateCap, externalCrate, market) + + if len(ret) == 0 { + panic("no return value specified for Price") + } + + var r0 unit.Cents + var r1 services.PricingDisplayParams + var r2 error + if rf, ok := ret.Get(0).(func(appcontext.AppContext, string, time.Time, unit.CubicFeet, bool, unit.Cents, bool, models.Market) (unit.Cents, services.PricingDisplayParams, error)); ok { + return rf(appCtx, contractCode, requestedPickupDate, billedCubicFeet, standaloneCrate, standaloneCrateCap, externalCrate, market) + } + if rf, ok := ret.Get(0).(func(appcontext.AppContext, string, time.Time, unit.CubicFeet, bool, unit.Cents, bool, models.Market) unit.Cents); ok { + r0 = rf(appCtx, contractCode, requestedPickupDate, billedCubicFeet, standaloneCrate, standaloneCrateCap, externalCrate, market) + } else { + r0 = ret.Get(0).(unit.Cents) + } + + if rf, ok := ret.Get(1).(func(appcontext.AppContext, string, time.Time, unit.CubicFeet, bool, unit.Cents, bool, models.Market) services.PricingDisplayParams); ok { + r1 = rf(appCtx, contractCode, requestedPickupDate, billedCubicFeet, standaloneCrate, standaloneCrateCap, externalCrate, market) + } else { + if ret.Get(1) != nil { + r1 = ret.Get(1).(services.PricingDisplayParams) + } + } + + if rf, ok := ret.Get(2).(func(appcontext.AppContext, string, time.Time, unit.CubicFeet, bool, unit.Cents, bool, models.Market) error); ok { + r2 = rf(appCtx, contractCode, requestedPickupDate, billedCubicFeet, standaloneCrate, standaloneCrateCap, externalCrate, market) + } else { + r2 = ret.Error(2) + } + + return r0, r1, r2 +} + +// PriceUsingParams provides a mock function with given fields: appCtx, params +func (_m *IntlCratingPricer) PriceUsingParams(appCtx appcontext.AppContext, params models.PaymentServiceItemParams) (unit.Cents, services.PricingDisplayParams, error) { + ret := _m.Called(appCtx, params) + + if len(ret) == 0 { + panic("no return value specified for PriceUsingParams") + } + + var r0 unit.Cents + var r1 services.PricingDisplayParams + var r2 error + if rf, ok := ret.Get(0).(func(appcontext.AppContext, models.PaymentServiceItemParams) (unit.Cents, services.PricingDisplayParams, error)); ok { + return rf(appCtx, params) + } + if rf, ok := ret.Get(0).(func(appcontext.AppContext, models.PaymentServiceItemParams) unit.Cents); ok { + r0 = rf(appCtx, params) + } else { + r0 = ret.Get(0).(unit.Cents) + } + + if rf, ok := ret.Get(1).(func(appcontext.AppContext, models.PaymentServiceItemParams) services.PricingDisplayParams); ok { + r1 = rf(appCtx, params) + } else { + if ret.Get(1) != nil { + r1 = ret.Get(1).(services.PricingDisplayParams) + } + } + + if rf, ok := ret.Get(2).(func(appcontext.AppContext, models.PaymentServiceItemParams) error); ok { + r2 = rf(appCtx, params) + } else { + r2 = ret.Error(2) + } + + return r0, r1, r2 +} + +// NewIntlCratingPricer creates a new instance of IntlCratingPricer. It also registers a testing interface on the mock and a cleanup function to assert the mocks expectations. +// The first argument is typically a *testing.T value. +func NewIntlCratingPricer(t interface { + mock.TestingT + Cleanup(func()) +}) *IntlCratingPricer { + mock := &IntlCratingPricer{} + mock.Mock.Test(t) + + t.Cleanup(func() { mock.AssertExpectations(t) }) + + return mock +} diff --git a/pkg/services/mocks/IntlUncratingPricer.go b/pkg/services/mocks/IntlUncratingPricer.go new file mode 100644 index 00000000000..c54879fbce8 --- /dev/null +++ b/pkg/services/mocks/IntlUncratingPricer.go @@ -0,0 +1,109 @@ +// Code generated by mockery. DO NOT EDIT. + +package mocks + +import ( + mock "github.com/stretchr/testify/mock" + appcontext "github.com/transcom/mymove/pkg/appcontext" + + models "github.com/transcom/mymove/pkg/models" + + services "github.com/transcom/mymove/pkg/services" + + time "time" + + unit "github.com/transcom/mymove/pkg/unit" +) + +// IntlUncratingPricer is an autogenerated mock type for the IntlUncratingPricer type +type IntlUncratingPricer struct { + mock.Mock +} + +// Price provides a mock function with given fields: appCtx, contractCode, requestedPickupDate, billedCubicFeet, market +func (_m *IntlUncratingPricer) Price(appCtx appcontext.AppContext, contractCode string, requestedPickupDate time.Time, billedCubicFeet unit.CubicFeet, market models.Market) (unit.Cents, services.PricingDisplayParams, error) { + ret := _m.Called(appCtx, contractCode, requestedPickupDate, billedCubicFeet, market) + + if len(ret) == 0 { + panic("no return value specified for Price") + } + + var r0 unit.Cents + var r1 services.PricingDisplayParams + var r2 error + if rf, ok := ret.Get(0).(func(appcontext.AppContext, string, time.Time, unit.CubicFeet, models.Market) (unit.Cents, services.PricingDisplayParams, error)); ok { + return rf(appCtx, contractCode, requestedPickupDate, billedCubicFeet, market) + } + if rf, ok := ret.Get(0).(func(appcontext.AppContext, string, time.Time, unit.CubicFeet, models.Market) unit.Cents); ok { + r0 = rf(appCtx, contractCode, requestedPickupDate, billedCubicFeet, market) + } else { + r0 = ret.Get(0).(unit.Cents) + } + + if rf, ok := ret.Get(1).(func(appcontext.AppContext, string, time.Time, unit.CubicFeet, models.Market) services.PricingDisplayParams); ok { + r1 = rf(appCtx, contractCode, requestedPickupDate, billedCubicFeet, market) + } else { + if ret.Get(1) != nil { + r1 = ret.Get(1).(services.PricingDisplayParams) + } + } + + if rf, ok := ret.Get(2).(func(appcontext.AppContext, string, time.Time, unit.CubicFeet, models.Market) error); ok { + r2 = rf(appCtx, contractCode, requestedPickupDate, billedCubicFeet, market) + } else { + r2 = ret.Error(2) + } + + return r0, r1, r2 +} + +// PriceUsingParams provides a mock function with given fields: appCtx, params +func (_m *IntlUncratingPricer) PriceUsingParams(appCtx appcontext.AppContext, params models.PaymentServiceItemParams) (unit.Cents, services.PricingDisplayParams, error) { + ret := _m.Called(appCtx, params) + + if len(ret) == 0 { + panic("no return value specified for PriceUsingParams") + } + + var r0 unit.Cents + var r1 services.PricingDisplayParams + var r2 error + if rf, ok := ret.Get(0).(func(appcontext.AppContext, models.PaymentServiceItemParams) (unit.Cents, services.PricingDisplayParams, error)); ok { + return rf(appCtx, params) + } + if rf, ok := ret.Get(0).(func(appcontext.AppContext, models.PaymentServiceItemParams) unit.Cents); ok { + r0 = rf(appCtx, params) + } else { + r0 = ret.Get(0).(unit.Cents) + } + + if rf, ok := ret.Get(1).(func(appcontext.AppContext, models.PaymentServiceItemParams) services.PricingDisplayParams); ok { + r1 = rf(appCtx, params) + } else { + if ret.Get(1) != nil { + r1 = ret.Get(1).(services.PricingDisplayParams) + } + } + + if rf, ok := ret.Get(2).(func(appcontext.AppContext, models.PaymentServiceItemParams) error); ok { + r2 = rf(appCtx, params) + } else { + r2 = ret.Error(2) + } + + return r0, r1, r2 +} + +// NewIntlUncratingPricer creates a new instance of IntlUncratingPricer. It also registers a testing interface on the mock and a cleanup function to assert the mocks expectations. +// The first argument is typically a *testing.T value. +func NewIntlUncratingPricer(t interface { + mock.TestingT + Cleanup(func()) +}) *IntlUncratingPricer { + mock := &IntlUncratingPricer{} + mock.Mock.Test(t) + + t.Cleanup(func() { mock.AssertExpectations(t) }) + + return mock +} diff --git a/swagger/ghc.yaml b/swagger/ghc.yaml index b00c002f3d5..84f6e9a65e0 100644 --- a/swagger/ghc.yaml +++ b/swagger/ghc.yaml @@ -1512,6 +1512,7 @@ paths: $ref: '#/responses/ServerError' tags: - shipment + - shipment_address_updates description: >- This endpoint is used to approve a address update request. Office remarks are required. Approving the address update will update the @@ -3946,6 +3947,117 @@ paths: $ref: '#/responses/PermissionDenied' '500': $ref: '#/responses/ServerError' + /queues/destination-requests: + get: + produces: + - application/json + summary: >- + Gets queued list of all customer moves by GBLOC that have both CONUS & + OCONUS destination requests (destination SIT, destination shuttle, + address requests) + description: > + A TOO will view this queue when they have destination requests tied to + their GBLOC. This includes unapproved destination SIT service items, + destination shuttle service items and destination address requests that + are not yet approved by the TOO. + operationId: getDestinationRequestsQueue + tags: + - queues + parameters: + - in: query + name: page + type: integer + description: requested page of results + - in: query + name: perPage + type: integer + description: results per page + - in: query + name: sort + type: string + enum: + - customerName + - edipi + - emplid + - branch + - locator + - status + - originDutyLocation + - destinationDutyLocation + - requestedMoveDate + - appearedInTooAt + - assignedTo + - counselingOffice + description: field that results should be sorted by + - in: query + name: order + type: string + enum: + - asc + - desc + description: direction of sort order if applied + - in: query + name: branch + type: string + - in: query + name: locator + type: string + - in: query + name: customerName + type: string + - in: query + name: edipi + type: string + - in: query + name: emplid + type: string + - in: query + name: originDutyLocation + type: array + uniqueItems: true + collectionFormat: multi + items: + type: string + - in: query + name: destinationDutyLocation + type: string + - in: query + name: appearedInTooAt + type: string + format: date-time + - in: query + name: requestedMoveDate + type: string + description: filters the requested pickup date of a shipment on the move + - in: query + name: status + type: array + description: Filtering for the status. + uniqueItems: true + items: + type: string + enum: + - SUBMITTED + - SERVICE COUNSELING COMPLETED + - APPROVALS REQUESTED + - in: query + name: assignedTo + type: string + description: | + Used to illustrate which user is assigned to this move. + - in: query + name: counselingOffice + type: string + description: filters using a counselingOffice name of the move + responses: + '200': + description: Successfully returned all moves matching the criteria + schema: + $ref: '#/definitions/QueueMovesResult' + '403': + $ref: '#/responses/PermissionDenied' + '500': + $ref: '#/responses/ServerError' /queues/payment-requests: get: produces: From 3b13637797ac7dca2070935dd53f1efae6071aa5 Mon Sep 17 00:00:00 2001 From: Konstance Haffaney Date: Tue, 11 Feb 2025 21:51:32 +0000 Subject: [PATCH 19/37] remove tester comment --- pkg/models/models.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pkg/models/models.go b/pkg/models/models.go index 61a1b43610b..32e9338d23c 100644 --- a/pkg/models/models.go +++ b/pkg/models/models.go @@ -11,7 +11,7 @@ import ( // EagerAssociations are a collection of named associations type EagerAssociations []string -// testing comment StringPointer allows you to take the address of a string literal. +// StringPointer allows you to take the address of a string literal. // It is useful for initializing string pointer fields in model construction func StringPointer(s string) *string { return &s From d51827eb784a9c65a836ecc8c4bc04377c386f4e Mon Sep 17 00:00:00 2001 From: Konstance Haffaney Date: Wed, 12 Feb 2025 02:50:06 +0000 Subject: [PATCH 20/37] made roles column sortable and changed to rejected on --- .../Admin/RejectedOfficeUsers/RejectedOfficeUserList.jsx | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-) diff --git a/src/pages/Admin/RejectedOfficeUsers/RejectedOfficeUserList.jsx b/src/pages/Admin/RejectedOfficeUsers/RejectedOfficeUserList.jsx index d0278bc2e77..f2a58ae4df4 100644 --- a/src/pages/Admin/RejectedOfficeUsers/RejectedOfficeUserList.jsx +++ b/src/pages/Admin/RejectedOfficeUsers/RejectedOfficeUserList.jsx @@ -59,8 +59,10 @@ const RejectedOfficeUserList = () => ( - - + + + + ); From 6fbf29a2341ebe47cfa81786320cc86e0e2758e7 Mon Sep 17 00:00:00 2001 From: Konstance Haffaney Date: Wed, 12 Feb 2025 03:06:22 +0000 Subject: [PATCH 21/37] adding missing files --- .../adminapi/adminoperations/mymove_api.go | 12 ++ .../get_rejected_office_user.go | 58 +++++++ .../get_rejected_office_user_parameters.go | 91 ++++++++++ .../get_rejected_office_user_responses.go | 159 ++++++++++++++++++ .../get_rejected_office_user_urlbuilder.go | 101 +++++++++++ pkg/gen/adminapi/configure_mymove.go | 5 + pkg/gen/adminapi/embedded_spec.go | 84 +++++++++ pkg/gen/ghcapi/embedded_spec.go | 4 +- .../adminapi/rejected_office_users.go | 37 ++++ .../RejectedOfficeUserList.jsx | 6 +- swagger-def/admin.yaml | 28 +++ swagger/admin.yaml | 31 ++++ 12 files changed, 612 insertions(+), 4 deletions(-) create mode 100644 pkg/gen/adminapi/adminoperations/rejected_office_users/get_rejected_office_user.go create mode 100644 pkg/gen/adminapi/adminoperations/rejected_office_users/get_rejected_office_user_parameters.go create mode 100644 pkg/gen/adminapi/adminoperations/rejected_office_users/get_rejected_office_user_responses.go create mode 100644 pkg/gen/adminapi/adminoperations/rejected_office_users/get_rejected_office_user_urlbuilder.go diff --git a/pkg/gen/adminapi/adminoperations/mymove_api.go b/pkg/gen/adminapi/adminoperations/mymove_api.go index a3877cb338e..64953dade88 100644 --- a/pkg/gen/adminapi/adminoperations/mymove_api.go +++ b/pkg/gen/adminapi/adminoperations/mymove_api.go @@ -95,6 +95,9 @@ func NewMymoveAPI(spec *loads.Document) *MymoveAPI { OfficeUsersGetOfficeUserHandler: office_users.GetOfficeUserHandlerFunc(func(params office_users.GetOfficeUserParams) middleware.Responder { return middleware.NotImplemented("operation office_users.GetOfficeUser has not yet been implemented") }), + RejectedOfficeUsersGetRejectedOfficeUserHandler: rejected_office_users.GetRejectedOfficeUserHandlerFunc(func(params rejected_office_users.GetRejectedOfficeUserParams) middleware.Responder { + return middleware.NotImplemented("operation rejected_office_users.GetRejectedOfficeUser has not yet been implemented") + }), RequestedOfficeUsersGetRequestedOfficeUserHandler: requested_office_users.GetRequestedOfficeUserHandlerFunc(func(params requested_office_users.GetRequestedOfficeUserParams) middleware.Responder { return middleware.NotImplemented("operation requested_office_users.GetRequestedOfficeUser has not yet been implemented") }), @@ -237,6 +240,8 @@ type MymoveAPI struct { TransportationOfficesGetOfficeByIDHandler transportation_offices.GetOfficeByIDHandler // OfficeUsersGetOfficeUserHandler sets the operation handler for the get office user operation OfficeUsersGetOfficeUserHandler office_users.GetOfficeUserHandler + // RejectedOfficeUsersGetRejectedOfficeUserHandler sets the operation handler for the get rejected office user operation + RejectedOfficeUsersGetRejectedOfficeUserHandler rejected_office_users.GetRejectedOfficeUserHandler // RequestedOfficeUsersGetRequestedOfficeUserHandler sets the operation handler for the get requested office user operation RequestedOfficeUsersGetRequestedOfficeUserHandler requested_office_users.GetRequestedOfficeUserHandler // UploadsGetUploadHandler sets the operation handler for the get upload operation @@ -402,6 +407,9 @@ func (o *MymoveAPI) Validate() error { if o.OfficeUsersGetOfficeUserHandler == nil { unregistered = append(unregistered, "office_users.GetOfficeUserHandler") } + if o.RejectedOfficeUsersGetRejectedOfficeUserHandler == nil { + unregistered = append(unregistered, "rejected_office_users.GetRejectedOfficeUserHandler") + } if o.RequestedOfficeUsersGetRequestedOfficeUserHandler == nil { unregistered = append(unregistered, "requested_office_users.GetRequestedOfficeUserHandler") } @@ -619,6 +627,10 @@ func (o *MymoveAPI) initHandlerCache() { if o.handlers["GET"] == nil { o.handlers["GET"] = make(map[string]http.Handler) } + o.handlers["GET"]["/rejected-office-users/{officeUserId}"] = rejected_office_users.NewGetRejectedOfficeUser(o.context, o.RejectedOfficeUsersGetRejectedOfficeUserHandler) + if o.handlers["GET"] == nil { + o.handlers["GET"] = make(map[string]http.Handler) + } o.handlers["GET"]["/requested-office-users/{officeUserId}"] = requested_office_users.NewGetRequestedOfficeUser(o.context, o.RequestedOfficeUsersGetRequestedOfficeUserHandler) if o.handlers["GET"] == nil { o.handlers["GET"] = make(map[string]http.Handler) diff --git a/pkg/gen/adminapi/adminoperations/rejected_office_users/get_rejected_office_user.go b/pkg/gen/adminapi/adminoperations/rejected_office_users/get_rejected_office_user.go new file mode 100644 index 00000000000..d7664e97399 --- /dev/null +++ b/pkg/gen/adminapi/adminoperations/rejected_office_users/get_rejected_office_user.go @@ -0,0 +1,58 @@ +// Code generated by go-swagger; DO NOT EDIT. + +package rejected_office_users + +// 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" +) + +// GetRejectedOfficeUserHandlerFunc turns a function with the right signature into a get rejected office user handler +type GetRejectedOfficeUserHandlerFunc func(GetRejectedOfficeUserParams) middleware.Responder + +// Handle executing the request and returning a response +func (fn GetRejectedOfficeUserHandlerFunc) Handle(params GetRejectedOfficeUserParams) middleware.Responder { + return fn(params) +} + +// GetRejectedOfficeUserHandler interface for that can handle valid get rejected office user params +type GetRejectedOfficeUserHandler interface { + Handle(GetRejectedOfficeUserParams) middleware.Responder +} + +// NewGetRejectedOfficeUser creates a new http.Handler for the get rejected office user operation +func NewGetRejectedOfficeUser(ctx *middleware.Context, handler GetRejectedOfficeUserHandler) *GetRejectedOfficeUser { + return &GetRejectedOfficeUser{Context: ctx, Handler: handler} +} + +/* + GetRejectedOfficeUser swagger:route GET /rejected-office-users/{officeUserId} Rejected office users getRejectedOfficeUser + +# Get a Rejected Office User + +Retrieving a single office user in any status. This endpoint is used in the Admin UI that will allow the admin user to view the user's relevant data. +*/ +type GetRejectedOfficeUser struct { + Context *middleware.Context + Handler GetRejectedOfficeUserHandler +} + +func (o *GetRejectedOfficeUser) ServeHTTP(rw http.ResponseWriter, r *http.Request) { + route, rCtx, _ := o.Context.RouteInfo(r) + if rCtx != nil { + *r = *rCtx + } + var Params = NewGetRejectedOfficeUserParams() + 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/adminapi/adminoperations/rejected_office_users/get_rejected_office_user_parameters.go b/pkg/gen/adminapi/adminoperations/rejected_office_users/get_rejected_office_user_parameters.go new file mode 100644 index 00000000000..46f91bf217a --- /dev/null +++ b/pkg/gen/adminapi/adminoperations/rejected_office_users/get_rejected_office_user_parameters.go @@ -0,0 +1,91 @@ +// Code generated by go-swagger; DO NOT EDIT. + +package rejected_office_users + +// 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" +) + +// NewGetRejectedOfficeUserParams creates a new GetRejectedOfficeUserParams object +// +// There are no default values defined in the spec. +func NewGetRejectedOfficeUserParams() GetRejectedOfficeUserParams { + + return GetRejectedOfficeUserParams{} +} + +// GetRejectedOfficeUserParams contains all the bound params for the get rejected office user operation +// typically these are obtained from a http.Request +// +// swagger:parameters getRejectedOfficeUser +type GetRejectedOfficeUserParams struct { + + // HTTP Request Object + HTTPRequest *http.Request `json:"-"` + + /* + Required: true + In: path + */ + OfficeUserID 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 NewGetRejectedOfficeUserParams() beforehand. +func (o *GetRejectedOfficeUserParams) BindRequest(r *http.Request, route *middleware.MatchedRoute) error { + var res []error + + o.HTTPRequest = r + + rOfficeUserID, rhkOfficeUserID, _ := route.Params.GetOK("officeUserId") + if err := o.bindOfficeUserID(rOfficeUserID, rhkOfficeUserID, route.Formats); err != nil { + res = append(res, err) + } + if len(res) > 0 { + return errors.CompositeValidationError(res...) + } + return nil +} + +// bindOfficeUserID binds and validates parameter OfficeUserID from path. +func (o *GetRejectedOfficeUserParams) bindOfficeUserID(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("officeUserId", "path", "strfmt.UUID", raw) + } + o.OfficeUserID = *(value.(*strfmt.UUID)) + + if err := o.validateOfficeUserID(formats); err != nil { + return err + } + + return nil +} + +// validateOfficeUserID carries on validations for parameter OfficeUserID +func (o *GetRejectedOfficeUserParams) validateOfficeUserID(formats strfmt.Registry) error { + + if err := validate.FormatOf("officeUserId", "path", "uuid", o.OfficeUserID.String(), formats); err != nil { + return err + } + return nil +} diff --git a/pkg/gen/adminapi/adminoperations/rejected_office_users/get_rejected_office_user_responses.go b/pkg/gen/adminapi/adminoperations/rejected_office_users/get_rejected_office_user_responses.go new file mode 100644 index 00000000000..a67fcb04e3f --- /dev/null +++ b/pkg/gen/adminapi/adminoperations/rejected_office_users/get_rejected_office_user_responses.go @@ -0,0 +1,159 @@ +// Code generated by go-swagger; DO NOT EDIT. + +package rejected_office_users + +// 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/adminmessages" +) + +// GetRejectedOfficeUserOKCode is the HTTP code returned for type GetRejectedOfficeUserOK +const GetRejectedOfficeUserOKCode int = 200 + +/* +GetRejectedOfficeUserOK success + +swagger:response getRejectedOfficeUserOK +*/ +type GetRejectedOfficeUserOK struct { + + /* + In: Body + */ + Payload *adminmessages.OfficeUser `json:"body,omitempty"` +} + +// NewGetRejectedOfficeUserOK creates GetRejectedOfficeUserOK with default headers values +func NewGetRejectedOfficeUserOK() *GetRejectedOfficeUserOK { + + return &GetRejectedOfficeUserOK{} +} + +// WithPayload adds the payload to the get rejected office user o k response +func (o *GetRejectedOfficeUserOK) WithPayload(payload *adminmessages.OfficeUser) *GetRejectedOfficeUserOK { + o.Payload = payload + return o +} + +// SetPayload sets the payload to the get rejected office user o k response +func (o *GetRejectedOfficeUserOK) SetPayload(payload *adminmessages.OfficeUser) { + o.Payload = payload +} + +// WriteResponse to the client +func (o *GetRejectedOfficeUserOK) WriteResponse(rw http.ResponseWriter, producer runtime.Producer) { + + rw.WriteHeader(200) + if o.Payload != nil { + payload := o.Payload + if err := producer.Produce(rw, payload); err != nil { + panic(err) // let the recovery middleware deal with this + } + } +} + +// GetRejectedOfficeUserBadRequestCode is the HTTP code returned for type GetRejectedOfficeUserBadRequest +const GetRejectedOfficeUserBadRequestCode int = 400 + +/* +GetRejectedOfficeUserBadRequest invalid request + +swagger:response getRejectedOfficeUserBadRequest +*/ +type GetRejectedOfficeUserBadRequest struct { +} + +// NewGetRejectedOfficeUserBadRequest creates GetRejectedOfficeUserBadRequest with default headers values +func NewGetRejectedOfficeUserBadRequest() *GetRejectedOfficeUserBadRequest { + + return &GetRejectedOfficeUserBadRequest{} +} + +// WriteResponse to the client +func (o *GetRejectedOfficeUserBadRequest) WriteResponse(rw http.ResponseWriter, producer runtime.Producer) { + + rw.Header().Del(runtime.HeaderContentType) //Remove Content-Type on empty responses + + rw.WriteHeader(400) +} + +// GetRejectedOfficeUserUnauthorizedCode is the HTTP code returned for type GetRejectedOfficeUserUnauthorized +const GetRejectedOfficeUserUnauthorizedCode int = 401 + +/* +GetRejectedOfficeUserUnauthorized request requires user authentication + +swagger:response getRejectedOfficeUserUnauthorized +*/ +type GetRejectedOfficeUserUnauthorized struct { +} + +// NewGetRejectedOfficeUserUnauthorized creates GetRejectedOfficeUserUnauthorized with default headers values +func NewGetRejectedOfficeUserUnauthorized() *GetRejectedOfficeUserUnauthorized { + + return &GetRejectedOfficeUserUnauthorized{} +} + +// WriteResponse to the client +func (o *GetRejectedOfficeUserUnauthorized) WriteResponse(rw http.ResponseWriter, producer runtime.Producer) { + + rw.Header().Del(runtime.HeaderContentType) //Remove Content-Type on empty responses + + rw.WriteHeader(401) +} + +// GetRejectedOfficeUserNotFoundCode is the HTTP code returned for type GetRejectedOfficeUserNotFound +const GetRejectedOfficeUserNotFoundCode int = 404 + +/* +GetRejectedOfficeUserNotFound Office User not found + +swagger:response getRejectedOfficeUserNotFound +*/ +type GetRejectedOfficeUserNotFound struct { +} + +// NewGetRejectedOfficeUserNotFound creates GetRejectedOfficeUserNotFound with default headers values +func NewGetRejectedOfficeUserNotFound() *GetRejectedOfficeUserNotFound { + + return &GetRejectedOfficeUserNotFound{} +} + +// WriteResponse to the client +func (o *GetRejectedOfficeUserNotFound) WriteResponse(rw http.ResponseWriter, producer runtime.Producer) { + + rw.Header().Del(runtime.HeaderContentType) //Remove Content-Type on empty responses + + rw.WriteHeader(404) +} + +// GetRejectedOfficeUserInternalServerErrorCode is the HTTP code returned for type GetRejectedOfficeUserInternalServerError +const GetRejectedOfficeUserInternalServerErrorCode int = 500 + +/* +GetRejectedOfficeUserInternalServerError server error + +swagger:response getRejectedOfficeUserInternalServerError +*/ +type GetRejectedOfficeUserInternalServerError struct { +} + +// NewGetRejectedOfficeUserInternalServerError creates GetRejectedOfficeUserInternalServerError with default headers values +func NewGetRejectedOfficeUserInternalServerError() *GetRejectedOfficeUserInternalServerError { + + return &GetRejectedOfficeUserInternalServerError{} +} + +// WriteResponse to the client +func (o *GetRejectedOfficeUserInternalServerError) 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/adminapi/adminoperations/rejected_office_users/get_rejected_office_user_urlbuilder.go b/pkg/gen/adminapi/adminoperations/rejected_office_users/get_rejected_office_user_urlbuilder.go new file mode 100644 index 00000000000..090820d35f5 --- /dev/null +++ b/pkg/gen/adminapi/adminoperations/rejected_office_users/get_rejected_office_user_urlbuilder.go @@ -0,0 +1,101 @@ +// Code generated by go-swagger; DO NOT EDIT. + +package rejected_office_users + +// 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" +) + +// GetRejectedOfficeUserURL generates an URL for the get rejected office user operation +type GetRejectedOfficeUserURL struct { + OfficeUserID 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 *GetRejectedOfficeUserURL) WithBasePath(bp string) *GetRejectedOfficeUserURL { + 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 *GetRejectedOfficeUserURL) SetBasePath(bp string) { + o._basePath = bp +} + +// Build a url path and query string +func (o *GetRejectedOfficeUserURL) Build() (*url.URL, error) { + var _result url.URL + + var _path = "/rejected-office-users/{officeUserId}" + + officeUserID := o.OfficeUserID.String() + if officeUserID != "" { + _path = strings.Replace(_path, "{officeUserId}", officeUserID, -1) + } else { + return nil, errors.New("officeUserId is required on GetRejectedOfficeUserURL") + } + + _basePath := o._basePath + if _basePath == "" { + _basePath = "/admin/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 *GetRejectedOfficeUserURL) 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 *GetRejectedOfficeUserURL) String() string { + return o.Must(o.Build()).String() +} + +// BuildFull builds a full url with scheme, host, path and query string +func (o *GetRejectedOfficeUserURL) BuildFull(scheme, host string) (*url.URL, error) { + if scheme == "" { + return nil, errors.New("scheme is required for a full url on GetRejectedOfficeUserURL") + } + if host == "" { + return nil, errors.New("host is required for a full url on GetRejectedOfficeUserURL") + } + + 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 *GetRejectedOfficeUserURL) StringFull(scheme, host string) string { + return o.Must(o.BuildFull(scheme, host)).String() +} diff --git a/pkg/gen/adminapi/configure_mymove.go b/pkg/gen/adminapi/configure_mymove.go index 4548f47231a..a6809ba55be 100644 --- a/pkg/gen/adminapi/configure_mymove.go +++ b/pkg/gen/adminapi/configure_mymove.go @@ -113,6 +113,11 @@ func configureAPI(api *adminoperations.MymoveAPI) http.Handler { return middleware.NotImplemented("operation office_users.GetOfficeUser has not yet been implemented") }) } + if api.RejectedOfficeUsersGetRejectedOfficeUserHandler == nil { + api.RejectedOfficeUsersGetRejectedOfficeUserHandler = rejected_office_users.GetRejectedOfficeUserHandlerFunc(func(params rejected_office_users.GetRejectedOfficeUserParams) middleware.Responder { + return middleware.NotImplemented("operation rejected_office_users.GetRejectedOfficeUser has not yet been implemented") + }) + } if api.RequestedOfficeUsersGetRequestedOfficeUserHandler == nil { api.RequestedOfficeUsersGetRequestedOfficeUserHandler = requested_office_users.GetRequestedOfficeUserHandlerFunc(func(params requested_office_users.GetRequestedOfficeUserParams) middleware.Responder { return middleware.NotImplemented("operation requested_office_users.GetRequestedOfficeUser has not yet been implemented") diff --git a/pkg/gen/adminapi/embedded_spec.go b/pkg/gen/adminapi/embedded_spec.go index 71e67bc6696..5aa58228261 100644 --- a/pkg/gen/adminapi/embedded_spec.go +++ b/pkg/gen/adminapi/embedded_spec.go @@ -1465,6 +1465,48 @@ func init() { } } }, + "/rejected-office-users/{officeUserId}": { + "get": { + "description": "Retrieving a single office user in any status. This endpoint is used in the Admin UI that will allow the admin user to view the user's relevant data.", + "produces": [ + "application/json" + ], + "tags": [ + "Rejected office users" + ], + "summary": "Get a Rejected Office User", + "operationId": "getRejectedOfficeUser", + "parameters": [ + { + "type": "string", + "format": "uuid", + "name": "officeUserId", + "in": "path", + "required": true + } + ], + "responses": { + "200": { + "description": "success", + "schema": { + "$ref": "#/definitions/OfficeUser" + } + }, + "400": { + "description": "invalid request" + }, + "401": { + "description": "request requires user authentication" + }, + "404": { + "description": "Office User not found" + }, + "500": { + "description": "server error" + } + } + } + }, "/requested-office-users": { "get": { "description": "This endpoint returns a list of Office Users. Do not use this endpoint directly\nas it is meant to be used with the Admin UI exclusively.\n", @@ -5234,6 +5276,48 @@ func init() { } } }, + "/rejected-office-users/{officeUserId}": { + "get": { + "description": "Retrieving a single office user in any status. This endpoint is used in the Admin UI that will allow the admin user to view the user's relevant data.", + "produces": [ + "application/json" + ], + "tags": [ + "Rejected office users" + ], + "summary": "Get a Rejected Office User", + "operationId": "getRejectedOfficeUser", + "parameters": [ + { + "type": "string", + "format": "uuid", + "name": "officeUserId", + "in": "path", + "required": true + } + ], + "responses": { + "200": { + "description": "success", + "schema": { + "$ref": "#/definitions/OfficeUser" + } + }, + "400": { + "description": "invalid request" + }, + "401": { + "description": "request requires user authentication" + }, + "404": { + "description": "Office User not found" + }, + "500": { + "description": "server error" + } + } + } + }, "/requested-office-users": { "get": { "description": "This endpoint returns a list of Office Users. Do not use this endpoint directly\nas it is meant to be used with the Admin UI exclusively.\n", diff --git a/pkg/gen/ghcapi/embedded_spec.go b/pkg/gen/ghcapi/embedded_spec.go index d84b59fe148..a6d319c8a4d 100644 --- a/pkg/gen/ghcapi/embedded_spec.go +++ b/pkg/gen/ghcapi/embedded_spec.go @@ -1516,7 +1516,7 @@ func init() { }, "/move-task-orders/{moveTaskOrderID}/status": { "patch": { - "description": "Changes move task order status to make it available to prime", + "description": "Changes move task order status", "consumes": [ "application/json" ], @@ -1526,7 +1526,7 @@ func init() { "tags": [ "moveTaskOrder" ], - "summary": "Change the status of a move task order to make it available to prime", + "summary": "Change the status of a move task order", "operationId": "updateMoveTaskOrderStatus", "parameters": [ { diff --git a/pkg/handlers/adminapi/rejected_office_users.go b/pkg/handlers/adminapi/rejected_office_users.go index eb7015a78d9..86d23f415d1 100644 --- a/pkg/handlers/adminapi/rejected_office_users.go +++ b/pkg/handlers/adminapi/rejected_office_users.go @@ -4,6 +4,7 @@ import ( "fmt" "github.com/go-openapi/runtime/middleware" + "go.uber.org/zap" "github.com/transcom/mymove/pkg/appcontext" "github.com/transcom/mymove/pkg/gen/adminapi/adminoperations/rejected_office_users" @@ -110,3 +111,39 @@ func (h IndexRejectedOfficeUsersHandler) Handle(params rejected_office_users.Ind return rejected_office_users.NewIndexRejectedOfficeUsersOK().WithContentRange(fmt.Sprintf("rejected office users %d-%d/%d", pagination.Offset(), pagination.Offset()+queriedOfficeUsersCount, totalOfficeUsersCount)).WithPayload(payload), nil }) } + +// GetRejectedOfficeUserHandler returns a list of office users via GET /rejected_office_users/{officeUserId} +type GetRejectedOfficeUserHandler struct { + handlers.HandlerConfig + services.RejectedOfficeUserFetcher + services.RoleAssociater + services.NewQueryFilter +} + +// Handle retrieves a single rejected office user +func (h GetRejectedOfficeUserHandler) Handle(params rejected_office_users.GetRejectedOfficeUserParams) middleware.Responder { + return h.AuditableAppContextFromRequestWithErrors(params.HTTPRequest, + func(appCtx appcontext.AppContext) (middleware.Responder, error) { + + rejectedOfficeUserID := params.OfficeUserID + + queryFilters := []services.QueryFilter{query.NewQueryFilter("id", "=", rejectedOfficeUserID)} + rejectedOfficeUser, err := h.RejectedOfficeUserFetcher.FetchRejectedOfficeUser(appCtx, queryFilters) + + if err != nil { + return handlers.ResponseForError(appCtx.Logger(), err), err + } + + roles, err := h.RoleAssociater.FetchRolesForUser(appCtx, *rejectedOfficeUser.UserID) + if err != nil { + appCtx.Logger().Error("Error fetching user roles", zap.Error(err)) + return rejected_office_users.NewGetRejectedOfficeUserBadRequest(), err + } + + rejectedOfficeUser.User.Roles = roles + + payload := payloadForRejectedOfficeUserModel(rejectedOfficeUser) + + return rejected_office_users.NewGetRejectedOfficeUserOK().WithPayload(payload), nil + }) +} diff --git a/src/pages/Admin/RejectedOfficeUsers/RejectedOfficeUserList.jsx b/src/pages/Admin/RejectedOfficeUsers/RejectedOfficeUserList.jsx index d0278bc2e77..f2a58ae4df4 100644 --- a/src/pages/Admin/RejectedOfficeUsers/RejectedOfficeUserList.jsx +++ b/src/pages/Admin/RejectedOfficeUsers/RejectedOfficeUserList.jsx @@ -59,8 +59,10 @@ const RejectedOfficeUserList = () => ( - - + + + + ); diff --git a/swagger-def/admin.yaml b/swagger-def/admin.yaml index 0612515b63e..22f82591ae2 100644 --- a/swagger-def/admin.yaml +++ b/swagger-def/admin.yaml @@ -1467,6 +1467,34 @@ paths: description: Office User not found "500": description: server error + /rejected-office-users/{officeUserId}: + get: + produces: + - application/json + summary: Get a Rejected Office User + description: Retrieving a single office user in any status. This endpoint is used in the Admin UI that will allow the admin user to view the user's relevant data. + operationId: getRejectedOfficeUser + tags: + - Rejected office users + parameters: + - in: path + name: officeUserId + type: string + format: uuid + required: true + responses: + "200": + description: success + schema: + $ref: "#/definitions/OfficeUser" + "400": + description: invalid request + "401": + description: request requires user authentication + "404": + description: Office User not found + "500": + description: server error /office-users: get: produces: diff --git a/swagger/admin.yaml b/swagger/admin.yaml index b9c42f2c98c..05ff4d37e2d 100644 --- a/swagger/admin.yaml +++ b/swagger/admin.yaml @@ -1486,6 +1486,37 @@ paths: description: Office User not found '500': description: server error + /rejected-office-users/{officeUserId}: + get: + produces: + - application/json + summary: Get a Rejected Office User + description: >- + Retrieving a single office user in any status. This endpoint is used in + the Admin UI that will allow the admin user to view the user's relevant + data. + operationId: getRejectedOfficeUser + tags: + - Rejected office users + parameters: + - in: path + name: officeUserId + type: string + format: uuid + required: true + responses: + '200': + description: success + schema: + $ref: '#/definitions/OfficeUser' + '400': + description: invalid request + '401': + description: request requires user authentication + '404': + description: Office User not found + '500': + description: server error /office-users: get: produces: From 71ab962432b1aa5c260a20b5cb91aa39b2927ec6 Mon Sep 17 00:00:00 2001 From: Konstance Haffaney Date: Wed, 12 Feb 2025 03:19:08 +0000 Subject: [PATCH 22/37] more missing stuff --- .../adminapi/rejected_office_users.go | 2 +- .../rejected_office_user_service_test.go | 2 +- .../RejectedOfficeUserShow.module.scss | 52 +++++++++---------- 3 files changed, 28 insertions(+), 28 deletions(-) diff --git a/pkg/handlers/adminapi/rejected_office_users.go b/pkg/handlers/adminapi/rejected_office_users.go index 86d23f415d1..80b94fdb033 100644 --- a/pkg/handlers/adminapi/rejected_office_users.go +++ b/pkg/handlers/adminapi/rejected_office_users.go @@ -146,4 +146,4 @@ func (h GetRejectedOfficeUserHandler) Handle(params rejected_office_users.GetRej return rejected_office_users.NewGetRejectedOfficeUserOK().WithPayload(payload), nil }) -} +} \ No newline at end of file diff --git a/pkg/services/rejected_office_users/rejected_office_user_service_test.go b/pkg/services/rejected_office_users/rejected_office_user_service_test.go index f474a2d6af9..0c2d2380f0e 100644 --- a/pkg/services/rejected_office_users/rejected_office_user_service_test.go +++ b/pkg/services/rejected_office_users/rejected_office_user_service_test.go @@ -19,4 +19,4 @@ func TestUserSuite(t *testing.T) { } suite.Run(t, ts) ts.PopTestSuite.TearDown() -} +} \ No newline at end of file diff --git a/src/pages/Admin/RejectedOfficeUsers/RejectedOfficeUserShow.module.scss b/src/pages/Admin/RejectedOfficeUsers/RejectedOfficeUserShow.module.scss index b37e5801e46..2e8c5d470b7 100644 --- a/src/pages/Admin/RejectedOfficeUsers/RejectedOfficeUserShow.module.scss +++ b/src/pages/Admin/RejectedOfficeUsers/RejectedOfficeUserShow.module.scss @@ -1,35 +1,35 @@ @import 'shared/styles/colors.scss'; .btnContainer { - display: flex; - justify-content: flex-start; - align-self: center; - gap: 10px; - - .approveBtn { - width: 125px; - margin-left: 15px; - background-color: $primary; - - &:active, - &:hover, - &:focus { - background-color: $primary; - opacity: 80%; - } + display: flex; + justify-content: flex-start; + align-self: center; + gap: 10px; + + .approveBtn { + width: 125px; + margin-left: 15px; + background-color: $primary; + + &:active, + &:hover, + &:focus { + background-color: $primary; + opacity: 80%; } + } - .rejectBtn { - width: 125px; - background-color: $error; + .rejectBtn { + width: 125px; + background-color: $error; - &:active, - &:hover, - &:focus { - background-color: $error; - opacity: 80%; - } + &:active, + &:hover, + &:focus { + background-color: $error; + opacity: 80%; } + } } .rejectionInput { @@ -50,4 +50,4 @@ margin-left: 15px; margin-right: 15px; margin-bottom: 10px; -} \ No newline at end of file +} From 8c1401c49cdb224dfcd700941bcb2829d7bdd694 Mon Sep 17 00:00:00 2001 From: Konstance Haffaney Date: Wed, 12 Feb 2025 03:41:48 +0000 Subject: [PATCH 23/37] change headers and comments --- .../20250131205338_add_rejected_col_to_admin_users.up.sql | 1 - .../rejected_office_users_list_fetcher.go | 6 +++--- .../Admin/RejectedOfficeUsers/RejectedOfficeUserList.jsx | 4 ++-- .../Admin/RejectedOfficeUsers/RejectedOfficeUserShow.jsx | 2 +- 4 files changed, 6 insertions(+), 7 deletions(-) diff --git a/migrations/app/schema/20250131205338_add_rejected_col_to_admin_users.up.sql b/migrations/app/schema/20250131205338_add_rejected_col_to_admin_users.up.sql index 14b367ab6a6..eeb44ef451b 100644 --- a/migrations/app/schema/20250131205338_add_rejected_col_to_admin_users.up.sql +++ b/migrations/app/schema/20250131205338_add_rejected_col_to_admin_users.up.sql @@ -2,5 +2,4 @@ ALTER TABLE public.office_users ADD COLUMN IF NOT EXISTS rejected_on timestamptz; --- Comments on new columns COMMENT on COLUMN office_users.rejected_on IS 'Date requested office users were rejected.'; diff --git a/pkg/services/rejected_office_users/rejected_office_users_list_fetcher.go b/pkg/services/rejected_office_users/rejected_office_users_list_fetcher.go index 9445ebbd0b3..2a753020d70 100644 --- a/pkg/services/rejected_office_users/rejected_office_users_list_fetcher.go +++ b/pkg/services/rejected_office_users/rejected_office_users_list_fetcher.go @@ -15,21 +15,21 @@ type rejectedOfficeUserListFetcher struct { builder rejectedOfficeUsersListQueryBuilder } -// FetchAdminUserList uses the passed query builder to fetch a list of office users +// FetchRejectedUserList uses the passed query builder to fetch a list of office users func (o *rejectedOfficeUserListFetcher) FetchRejectedOfficeUsersList(appCtx appcontext.AppContext, filters []services.QueryFilter, associations services.QueryAssociations, pagination services.Pagination, ordering services.QueryOrder) (models.OfficeUsers, error) { var rejectedUsers models.OfficeUsers err := o.builder.FetchMany(appCtx, &rejectedUsers, filters, associations, pagination, ordering) return rejectedUsers, err } -// FetchAdminUserList uses the passed query builder to fetch a list of office users +// FetchRejectedUserList uses the passed query builder to fetch a list of office users func (o *rejectedOfficeUserListFetcher) FetchRejectedOfficeUsersCount(appCtx appcontext.AppContext, filters []services.QueryFilter) (int, error) { var rejectedUsers models.OfficeUsers count, err := o.builder.Count(appCtx, &rejectedUsers, filters) return count, err } -// NewAdminUserListFetcher returns an implementation of AdminUserListFetcher +// NewRejectedUserListFetcher returns an implementation of RejectedUserListFetcher func NewRejectedOfficeUsersListFetcher(builder rejectedOfficeUsersListQueryBuilder) services.RejectedOfficeUserListFetcher { return &rejectedOfficeUserListFetcher{builder} } diff --git a/src/pages/Admin/RejectedOfficeUsers/RejectedOfficeUserList.jsx b/src/pages/Admin/RejectedOfficeUsers/RejectedOfficeUserList.jsx index f2a58ae4df4..c014cf485bc 100644 --- a/src/pages/Admin/RejectedOfficeUsers/RejectedOfficeUserList.jsx +++ b/src/pages/Admin/RejectedOfficeUsers/RejectedOfficeUserList.jsx @@ -60,8 +60,8 @@ const RejectedOfficeUserList = () => ( - - + + diff --git a/src/pages/Admin/RejectedOfficeUsers/RejectedOfficeUserShow.jsx b/src/pages/Admin/RejectedOfficeUsers/RejectedOfficeUserShow.jsx index 30b286d2a12..c5493f53f5c 100644 --- a/src/pages/Admin/RejectedOfficeUsers/RejectedOfficeUserShow.jsx +++ b/src/pages/Admin/RejectedOfficeUsers/RejectedOfficeUserShow.jsx @@ -22,7 +22,7 @@ const RejectedOfficeUserShowRoles = () => { return ( - Rejected roles: + Roles Requested: From f77ff7c6c9afbdf28a229093f405623379423a7d Mon Sep 17 00:00:00 2001 From: Konstance Haffaney Date: Wed, 12 Feb 2025 04:00:41 +0000 Subject: [PATCH 24/37] update migration comment --- .../20250131205338_add_rejected_col_to_admin_users.up.sql | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/migrations/app/schema/20250131205338_add_rejected_col_to_admin_users.up.sql b/migrations/app/schema/20250131205338_add_rejected_col_to_admin_users.up.sql index eeb44ef451b..a68cfad4a1e 100644 --- a/migrations/app/schema/20250131205338_add_rejected_col_to_admin_users.up.sql +++ b/migrations/app/schema/20250131205338_add_rejected_col_to_admin_users.up.sql @@ -1,4 +1,4 @@ --- Adds new columns to office_users table +-- Adds new column to office_users table ALTER TABLE public.office_users ADD COLUMN IF NOT EXISTS rejected_on timestamptz; From 280e887046b3149581bfad67f5b4ceba0b18ae84 Mon Sep 17 00:00:00 2001 From: Konstance Haffaney Date: Wed, 12 Feb 2025 04:01:17 +0000 Subject: [PATCH 25/37] update migration comment --- .../20250131205338_add_rejected_col_to_admin_users.up.sql | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/migrations/app/schema/20250131205338_add_rejected_col_to_admin_users.up.sql b/migrations/app/schema/20250131205338_add_rejected_col_to_admin_users.up.sql index eeb44ef451b..a68cfad4a1e 100644 --- a/migrations/app/schema/20250131205338_add_rejected_col_to_admin_users.up.sql +++ b/migrations/app/schema/20250131205338_add_rejected_col_to_admin_users.up.sql @@ -1,4 +1,4 @@ --- Adds new columns to office_users table +-- Adds new column to office_users table ALTER TABLE public.office_users ADD COLUMN IF NOT EXISTS rejected_on timestamptz; From 55e07543b14ba85e92b9893442dfccde2e2eedd0 Mon Sep 17 00:00:00 2001 From: Konstance Haffaney Date: Fri, 14 Feb 2025 03:43:54 +0000 Subject: [PATCH 26/37] deleted needed stuff lol --- pkg/handlers/adminapi/api.go | 7 ++ .../rejected_office_user_fetcher.go | 30 +++++++++ .../rejected_office_user_fetcher_test.go | 66 +++++++++++++++++++ 3 files changed, 103 insertions(+) create mode 100644 pkg/services/rejected_office_users/rejected_office_user_fetcher.go create mode 100644 pkg/services/rejected_office_users/rejected_office_user_fetcher_test.go diff --git a/pkg/handlers/adminapi/api.go b/pkg/handlers/adminapi/api.go index ffce154f4cc..913ed915f9b 100644 --- a/pkg/handlers/adminapi/api.go +++ b/pkg/handlers/adminapi/api.go @@ -88,6 +88,13 @@ func NewAdminAPI(handlerConfig handlers.HandlerConfig) *adminops.MymoveAPI { pagination.NewPagination, } + adminAPI.RejectedOfficeUsersGetRejectedOfficeUserHandler = GetRejectedOfficeUserHandler{ + handlerConfig, + rejectedofficeusers.NewRejectedOfficeUserFetcher(queryBuilder), + newRolesFetcher, + query.NewQueryFilter, + } + adminAPI.OfficeUsersIndexOfficeUsersHandler = IndexOfficeUsersHandler{ handlerConfig, fetch.NewListFetcher(queryBuilder), diff --git a/pkg/services/rejected_office_users/rejected_office_user_fetcher.go b/pkg/services/rejected_office_users/rejected_office_user_fetcher.go new file mode 100644 index 00000000000..5c6b85bd413 --- /dev/null +++ b/pkg/services/rejected_office_users/rejected_office_user_fetcher.go @@ -0,0 +1,30 @@ +package adminuser + +import ( + "github.com/gobuffalo/validate/v3" + + "github.com/transcom/mymove/pkg/appcontext" + "github.com/transcom/mymove/pkg/models" + "github.com/transcom/mymove/pkg/services" +) + +type rejectedOfficeUserQueryBuilder interface { + FetchOne(appCtx appcontext.AppContext, model interface{}, filters []services.QueryFilter) error + UpdateOne(appCtx appcontext.AppContext, model interface{}, eTag *string) (*validate.Errors, error) +} + +type rejectedOfficeUserFetcher struct { + builder rejectedOfficeUserQueryBuilder +} + +// FetchRejectedOfficeUser fetches an office user given a slice of filters +func (o *rejectedOfficeUserFetcher) FetchRejectedOfficeUser(appCtx appcontext.AppContext, filters []services.QueryFilter) (models.OfficeUser, error) { + var rejectedOfficeUser models.OfficeUser + err := o.builder.FetchOne(appCtx, &rejectedOfficeUser, filters) + return rejectedOfficeUser, err +} + +// NewAdminUserFetcher return an implementation of the AdminUserFetcher interface +func NewRejectedOfficeUserFetcher(builder rejectedOfficeUserQueryBuilder) services.RejectedOfficeUserFetcher { + return &rejectedOfficeUserFetcher{builder} +} diff --git a/pkg/services/rejected_office_users/rejected_office_user_fetcher_test.go b/pkg/services/rejected_office_users/rejected_office_user_fetcher_test.go new file mode 100644 index 00000000000..82dea63c812 --- /dev/null +++ b/pkg/services/rejected_office_users/rejected_office_user_fetcher_test.go @@ -0,0 +1,66 @@ +package adminuser + +import ( + "errors" + "reflect" + + "github.com/gobuffalo/validate/v3" + "github.com/gofrs/uuid" + + "github.com/transcom/mymove/pkg/appcontext" + "github.com/transcom/mymove/pkg/models" + "github.com/transcom/mymove/pkg/services" + "github.com/transcom/mymove/pkg/services/query" +) + +type testRejectedOfficeUsersQueryBuilder struct { + fakeFetchOne func(appConfig appcontext.AppContext, model interface{}) error +} + +func (t *testRejectedOfficeUsersQueryBuilder) FetchOne(appConfig appcontext.AppContext, model interface{}, _ []services.QueryFilter) error { + m := t.fakeFetchOne(appConfig, model) + return m +} + +func (t *testRejectedOfficeUsersQueryBuilder) UpdateOne(_ appcontext.AppContext, _ interface{}, _ *string) (*validate.Errors, error) { + return nil, nil +} + +func (suite *RejectedOfficeUsersServiceSuite) TestFetchRejectedOfficeUser() { + suite.Run("if the rejected office user is fetched, it should be returned", func() { + id, err := uuid.NewV4() + suite.NoError(err) + fakeFetchOne := func(_ appcontext.AppContext, model interface{}) error { + reflect.ValueOf(model).Elem().FieldByName("ID").Set(reflect.ValueOf(id)) + return nil + } + + builder := &testRejectedOfficeUsersQueryBuilder{ + fakeFetchOne: fakeFetchOne, + } + + fetcher := NewRejectedOfficeUserFetcher(builder) + filters := []services.QueryFilter{query.NewQueryFilter("id", "=", id.String())} + + rejectedOfficeUser, err := fetcher.FetchRejectedOfficeUser(suite.AppContextForTest(), filters) + + suite.NoError(err) + suite.Equal(id, rejectedOfficeUser.ID) + }) + + suite.Run("if there is an error, we get it with zero admin user", func() { + fakeFetchOne := func(_ appcontext.AppContext, _ interface{}) error { + return errors.New("Fetch error") + } + builder := &testRejectedOfficeUsersQueryBuilder{ + fakeFetchOne: fakeFetchOne, + } + fetcher := NewRejectedOfficeUserFetcher(builder) + + rejectedOfficeUser, err := fetcher.FetchRejectedOfficeUser(suite.AppContextForTest(), []services.QueryFilter{}) + + suite.Error(err) + suite.Equal(err.Error(), "Fetch error") + suite.Equal(models.OfficeUser{}, rejectedOfficeUser) + }) +} From 75f99f64cae3e51f8f20b33a2df2a9c8a7aae24d Mon Sep 17 00:00:00 2001 From: Konstance Haffaney Date: Fri, 14 Feb 2025 05:39:14 +0000 Subject: [PATCH 27/37] fixed search bar and updated tests --- .../adminapi/rejected_office_users.go | 47 +++--- .../adminapi/rejected_office_users_test.go | 11 +- pkg/services/rejected_office_users.go | 8 +- .../rejected_office_users_list_fetcher.go | 65 ++++++++- ...rejected_office_users_list_fetcher_test.go | 137 +++++++++++++----- 5 files changed, 194 insertions(+), 74 deletions(-) diff --git a/pkg/handlers/adminapi/rejected_office_users.go b/pkg/handlers/adminapi/rejected_office_users.go index 80b94fdb033..485e3444eac 100644 --- a/pkg/handlers/adminapi/rejected_office_users.go +++ b/pkg/handlers/adminapi/rejected_office_users.go @@ -1,9 +1,12 @@ package adminapi import ( + "encoding/json" + "errors" "fmt" "github.com/go-openapi/runtime/middleware" + "github.com/gobuffalo/pop/v6" "go.uber.org/zap" "github.com/transcom/mymove/pkg/appcontext" @@ -59,13 +62,11 @@ type IndexRejectedOfficeUsersHandler struct { services.NewPagination } -var rejectedOfficeUserFilterConverters = map[string]func(string) []services.QueryFilter{ - "search": func(content string) []services.QueryFilter { - nameSearch := fmt.Sprintf("%s%%", content) - return []services.QueryFilter{ - query.NewQueryFilter("email", "ILIKE", fmt.Sprintf("%%%s%%", content)), - query.NewQueryFilter("first_name", "ILIKE", nameSearch), - query.NewQueryFilter("last_name", "ILIKE", nameSearch), +var rejectedOfficeUserFilterConverters = map[string]func(string) func(*pop.Query){ + "search": func(content string) func(*pop.Query) { + return func(query *pop.Query) { + nameSearch := fmt.Sprintf("%%%s%%", content) + query.Where("roles.role_name ILIKE ? AND office_users.status = 'REJECTED' OR transportation_offices.name ILIKE ? AND office_users.status = 'REJECTED' OR office_users.email ILIKE ? AND office_users.status = 'REJECTED' OR office_users.first_name ILIKE ? AND office_users.status = 'REJECTED' OR office_users.last_name ILIKE ? AND office_users.status = 'REJECTED'", nameSearch, nameSearch, nameSearch, nameSearch, nameSearch) } }, } @@ -75,27 +76,25 @@ func (h IndexRejectedOfficeUsersHandler) Handle(params rejected_office_users.Ind return h.AuditableAppContextFromRequestWithErrors(params.HTTPRequest, func(appCtx appcontext.AppContext) (middleware.Responder, error) { - // adding in filters for when a search or filtering is done - queryFilters := generateQueryFilters(appCtx.Logger(), params.Filter, rejectedOfficeUserFilterConverters) + var filtersMap map[string]string + if params.Filter != nil && *params.Filter != "" { + err := json.Unmarshal([]byte(*params.Filter), &filtersMap) + if err != nil { + return handlers.ResponseForError(appCtx.Logger(), errors.New("invalid filter format")), err + } + } - // We only want users that are in a REJECTED status - queryFilters = append(queryFilters, query.NewQueryFilter("status", "=", "REJECTED")) + var filterFuncs []func(*pop.Query) + for key, filterFunc := range rejectedOfficeUserFilterConverters { + if filterValue, exists := filtersMap[key]; exists { + filterFuncs = append(filterFuncs, filterFunc(filterValue)) + } + } - // adding in pagination for the UI pagination := h.NewPagination(params.Page, params.PerPage) ordering := query.NewQueryOrder(params.Sort, params.Order) - // need to also get the user's roles - queryAssociations := query.NewQueryAssociationsPreload([]services.QueryAssociation{ - query.NewQueryAssociation("User.Roles"), - }) - - officeUsers, err := h.RejectedOfficeUserListFetcher.FetchRejectedOfficeUsersList(appCtx, queryFilters, queryAssociations, pagination, ordering) - if err != nil { - return handlers.ResponseForError(appCtx.Logger(), err), err - } - - totalOfficeUsersCount, err := h.RejectedOfficeUserListFetcher.FetchRejectedOfficeUsersCount(appCtx, queryFilters) + officeUsers, count, err := h.RejectedOfficeUserListFetcher.FetchRejectedOfficeUsersList(appCtx, filterFuncs, pagination, ordering) if err != nil { return handlers.ResponseForError(appCtx.Logger(), err), err } @@ -108,7 +107,7 @@ func (h IndexRejectedOfficeUsersHandler) Handle(params rejected_office_users.Ind payload[i] = payloadForRejectedOfficeUserModel(s) } - return rejected_office_users.NewIndexRejectedOfficeUsersOK().WithContentRange(fmt.Sprintf("rejected office users %d-%d/%d", pagination.Offset(), pagination.Offset()+queriedOfficeUsersCount, totalOfficeUsersCount)).WithPayload(payload), nil + return rejected_office_users.NewIndexRejectedOfficeUsersOK().WithContentRange(fmt.Sprintf("rejected office users %d-%d/%d", pagination.Offset(), pagination.Offset()+queriedOfficeUsersCount, count)).WithPayload(payload), nil }) } diff --git a/pkg/handlers/adminapi/rejected_office_users_test.go b/pkg/handlers/adminapi/rejected_office_users_test.go index 5ed2d09aa09..e55397e1c9a 100644 --- a/pkg/handlers/adminapi/rejected_office_users_test.go +++ b/pkg/handlers/adminapi/rejected_office_users_test.go @@ -1,6 +1,8 @@ package adminapi import ( + "slices" + "github.com/transcom/mymove/pkg/factory" rejectedofficeuserop "github.com/transcom/mymove/pkg/gen/adminapi/adminoperations/rejected_office_users" "github.com/transcom/mymove/pkg/models" @@ -35,7 +37,12 @@ func (suite *HandlerSuite) TestIndexRejectedOfficeUsersHandler() { // should get an ok response suite.IsType(&rejectedofficeuserop.IndexRejectedOfficeUsersOK{}, response) okResponse := response.(*rejectedofficeuserop.IndexRejectedOfficeUsersOK) - suite.Len(okResponse.Payload, 2) - suite.Equal(rejectedOfficeUsers[0].ID.String(), okResponse.Payload[0].ID.String()) + suite.Equal(len(okResponse.Payload), len(rejectedOfficeUsers)) + + actualID := []string{okResponse.Payload[0].ID.String(), okResponse.Payload[1].ID.String()} + expected := []string{rejectedOfficeUsers[0].ID.String(), rejectedOfficeUsers[1].ID.String()} + for _, expectedID := range expected { + suite.True(slices.Contains(actualID, expectedID)) + } }) } diff --git a/pkg/services/rejected_office_users.go b/pkg/services/rejected_office_users.go index 1a7d57990f4..4fc962f491b 100644 --- a/pkg/services/rejected_office_users.go +++ b/pkg/services/rejected_office_users.go @@ -1,19 +1,21 @@ package services import ( + "github.com/gobuffalo/pop/v6" + "github.com/transcom/mymove/pkg/appcontext" "github.com/transcom/mymove/pkg/models" ) -// RejectedOfficeUserListFetcher is the exported interface for fetching multiple rejected rejected office users +// RejectedOfficeUserListFetcher is the exported interface for fetching multiple rejected office users // //go:generate mockery --name RejectedOfficeUserListFetcher type RejectedOfficeUserListFetcher interface { - FetchRejectedOfficeUsersList(appCtx appcontext.AppContext, filters []QueryFilter, associations QueryAssociations, pagination Pagination, ordering QueryOrder) (models.OfficeUsers, error) + FetchRejectedOfficeUsersList(appCtx appcontext.AppContext, filterFuncs []func(*pop.Query), pagination Pagination, ordering QueryOrder) (models.OfficeUsers, int, error) FetchRejectedOfficeUsersCount(appCtx appcontext.AppContext, filters []QueryFilter) (int, error) } -// RejectedOfficeUserFetcher is the exported interface for fetching a single rejected rejected office user +// RejectedOfficeUserFetcher is the exported interface for fetching a single rejected office user // //go:generate mockery --name RejectedOfficeUserFetcher type RejectedOfficeUserFetcher interface { diff --git a/pkg/services/rejected_office_users/rejected_office_users_list_fetcher.go b/pkg/services/rejected_office_users/rejected_office_users_list_fetcher.go index 2a753020d70..111afc36689 100644 --- a/pkg/services/rejected_office_users/rejected_office_users_list_fetcher.go +++ b/pkg/services/rejected_office_users/rejected_office_users_list_fetcher.go @@ -1,13 +1,17 @@ package adminuser import ( + "fmt" + "sort" + + "github.com/gobuffalo/pop/v6" + "github.com/transcom/mymove/pkg/appcontext" "github.com/transcom/mymove/pkg/models" "github.com/transcom/mymove/pkg/services" ) type rejectedOfficeUsersListQueryBuilder interface { - FetchMany(appCtx appcontext.AppContext, model interface{}, filters []services.QueryFilter, associations services.QueryAssociations, pagination services.Pagination, ordering services.QueryOrder) error Count(appCtx appcontext.AppContext, model interface{}, filters []services.QueryFilter) (int, error) } @@ -15,21 +19,68 @@ type rejectedOfficeUserListFetcher struct { builder rejectedOfficeUsersListQueryBuilder } -// FetchRejectedUserList uses the passed query builder to fetch a list of office users -func (o *rejectedOfficeUserListFetcher) FetchRejectedOfficeUsersList(appCtx appcontext.AppContext, filters []services.QueryFilter, associations services.QueryAssociations, pagination services.Pagination, ordering services.QueryOrder) (models.OfficeUsers, error) { +// FetchAdminUserList uses the passed query builder to fetch a list of office users +func (o *rejectedOfficeUserListFetcher) FetchRejectedOfficeUsersList(appCtx appcontext.AppContext, filterFuncs []func(*pop.Query), pagination services.Pagination, ordering services.QueryOrder) (models.OfficeUsers, int, error) { + var query *pop.Query var rejectedUsers models.OfficeUsers - err := o.builder.FetchMany(appCtx, &rejectedUsers, filters, associations, pagination, ordering) - return rejectedUsers, err + + query = appCtx.DB().Q().EagerPreload( + "User.Roles", + "TransportationOffice"). + 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") + + for _, filterFunc := range filterFuncs { + filterFunc(query) + } + + query = query.Where("status = ?", models.OfficeUserStatusREJECTED) + query.GroupBy("office_users.id") + + var order = "desc" + if ordering.SortOrder() != nil && *ordering.SortOrder() { + order = "asc" + } + + var orderTerm = "id" + if ordering.Column() != nil { + orderTerm = *ordering.Column() + } + + query.Order(fmt.Sprintf("%s %s", orderTerm, order)) + query.Select("office_users.*") + + err := query.Paginate(pagination.Page(), pagination.PerPage()).All(&rejectedUsers) + if err != nil { + return nil, 0, err + } + + if orderTerm == "transportation_office_id" { + if order == "desc" { + sort.Slice(rejectedUsers, func(i, j int) bool { + return rejectedUsers[i].TransportationOffice.Name > rejectedUsers[j].TransportationOffice.Name + }) + } else { + sort.Slice(rejectedUsers, func(i, j int) bool { + return rejectedUsers[i].TransportationOffice.Name < rejectedUsers[j].TransportationOffice.Name + }) + } + } + + count := query.Paginator.TotalEntriesSize + return rejectedUsers, count, nil } -// FetchRejectedUserList uses the passed query builder to fetch a list of office users +// FetchAdminUserList uses the passed query builder to fetch a list of office users func (o *rejectedOfficeUserListFetcher) FetchRejectedOfficeUsersCount(appCtx appcontext.AppContext, filters []services.QueryFilter) (int, error) { var rejectedUsers models.OfficeUsers count, err := o.builder.Count(appCtx, &rejectedUsers, filters) return count, err } -// NewRejectedUserListFetcher returns an implementation of RejectedUserListFetcher +// NewAdminUserListFetcher returns an implementation of AdminUserListFetcher func NewRejectedOfficeUsersListFetcher(builder rejectedOfficeUsersListQueryBuilder) services.RejectedOfficeUserListFetcher { return &rejectedOfficeUserListFetcher{builder} } diff --git a/pkg/services/rejected_office_users/rejected_office_users_list_fetcher_test.go b/pkg/services/rejected_office_users/rejected_office_users_list_fetcher_test.go index ace816aeeb1..16a0aefa66d 100644 --- a/pkg/services/rejected_office_users/rejected_office_users_list_fetcher_test.go +++ b/pkg/services/rejected_office_users/rejected_office_users_list_fetcher_test.go @@ -1,26 +1,17 @@ package adminuser import ( - "errors" - "reflect" - - "github.com/gofrs/uuid" - "github.com/transcom/mymove/pkg/appcontext" + "github.com/transcom/mymove/pkg/factory" "github.com/transcom/mymove/pkg/models" + "github.com/transcom/mymove/pkg/models/roles" "github.com/transcom/mymove/pkg/services" "github.com/transcom/mymove/pkg/services/pagination" "github.com/transcom/mymove/pkg/services/query" ) type testRejectedOfficeUsersListQueryBuilder struct { - fakeFetchMany func(appCtx appcontext.AppContext, model interface{}) error - fakeCount func(appCtx appcontext.AppContext, model interface{}) (int, error) -} - -func (t *testRejectedOfficeUsersListQueryBuilder) FetchMany(appCtx appcontext.AppContext, model interface{}, _ []services.QueryFilter, _ services.QueryAssociations, _ services.Pagination, _ services.QueryOrder) error { - m := t.fakeFetchMany(appCtx, model) - return m + fakeCount func(appCtx appcontext.AppContext, model interface{}) (int, error) } func (t *testRejectedOfficeUsersListQueryBuilder) Count(appCtx appcontext.AppContext, model interface{}, _ []services.QueryFilter) (int, error) { @@ -33,50 +24,120 @@ func defaultPagination() services.Pagination { return pagination.NewPagination(&page, &perPage) } -func defaultAssociations() services.QueryAssociations { - return query.NewQueryAssociations([]services.QueryAssociation{}) -} - func defaultOrdering() services.QueryOrder { return query.NewQueryOrder(nil, nil) } func (suite *RejectedOfficeUsersServiceSuite) TestFetchRejectedOfficeUserList() { suite.Run("if the users are successfully fetched, they should be returned", func() { - id, err := uuid.NewV4() + rejectedStatus := models.OfficeUserStatusREJECTED + officeUser1 := factory.BuildOfficeUserWithRoles(suite.DB(), []factory.Customization{ + { + Model: models.OfficeUser{ + Status: &rejectedStatus, + }, + }, + }, []roles.RoleType{roles.RoleTypeTOO}) + builder := &testRejectedOfficeUsersListQueryBuilder{} + + fetcher := NewRejectedOfficeUsersListFetcher(builder) + + rejectedOfficeUsers, _, err := fetcher.FetchRejectedOfficeUsersList(suite.AppContextForTest(), nil, defaultPagination(), defaultOrdering()) + suite.NoError(err) - fakeFetchMany := func(_ appcontext.AppContext, model interface{}) error { - value := reflect.ValueOf(model).Elem() - rejectedStatus := models.OfficeUserStatusREJECTED - value.Set(reflect.Append(value, reflect.ValueOf(models.OfficeUser{ID: id, Status: &rejectedStatus}))) - return nil - } - builder := &testRejectedOfficeUsersListQueryBuilder{ - fakeFetchMany: fakeFetchMany, - } + suite.Equal(officeUser1.ID, rejectedOfficeUsers[0].ID) + }) + + suite.Run("if there are no rejected office users, we don't receive any rejected office users", func() { + builder := &testRejectedOfficeUsersListQueryBuilder{} fetcher := NewRejectedOfficeUsersListFetcher(builder) - rejectedOfficeUsers, err := fetcher.FetchRejectedOfficeUsersList(suite.AppContextForTest(), nil, defaultAssociations(), defaultPagination(), defaultOrdering()) + rejectedOfficeUsers, _, err := fetcher.FetchRejectedOfficeUsersList(suite.AppContextForTest(), nil, defaultPagination(), defaultOrdering()) suite.NoError(err) - suite.Equal(id, rejectedOfficeUsers[0].ID) + suite.Equal(models.OfficeUsers(nil), rejectedOfficeUsers) }) - suite.Run("if there is an error, we get it with no rejected office users", func() { - fakeFetchMany := func(_ appcontext.AppContext, _ interface{}) error { - return errors.New("Fetch error") - } - builder := &testRejectedOfficeUsersListQueryBuilder{ - fakeFetchMany: fakeFetchMany, - } + suite.Run("should sort and order rejected office users", func() { + rejectedStatus := models.OfficeUserStatusREJECTED + officeUser1 := factory.BuildOfficeUserWithRoles(suite.DB(), []factory.Customization{ + { + Model: models.OfficeUser{ + FirstName: "Angelina", + LastName: "Jolie", + Email: "laraCroft@mail.mil", + Status: &rejectedStatus, + }, + }, + { + Model: models.TransportationOffice{ + Name: "PPPO Kirtland AFB - USAF", + }, + }, + }, []roles.RoleType{roles.RoleTypeTOO}) + officeUser2 := factory.BuildOfficeUserWithRoles(suite.DB(), []factory.Customization{ + { + Model: models.OfficeUser{ + FirstName: "Billy", + LastName: "Bob", + Email: "bigBob@mail.mil", + Status: &rejectedStatus, + }, + }, + { + Model: models.TransportationOffice{ + Name: "PPPO Fort Knox - USA", + }, + }, + }, []roles.RoleType{roles.RoleTypeTIO}) + officeUser3 := factory.BuildOfficeUserWithRoles(suite.DB(), []factory.Customization{ + { + Model: models.OfficeUser{ + FirstName: "Nick", + LastName: "Cage", + Email: "conAirKilluh@mail.mil", + Status: &rejectedStatus, + }, + }, + { + Model: models.TransportationOffice{ + Name: "PPPO Detroit Arsenal - USA", + }, + }, + }, []roles.RoleType{roles.RoleTypeServicesCounselor}) + + + builder := &testRejectedOfficeUsersListQueryBuilder{} fetcher := NewRejectedOfficeUsersListFetcher(builder) - rejectedOfficeUsers, err := fetcher.FetchRejectedOfficeUsersList(suite.AppContextForTest(), []services.QueryFilter{}, defaultAssociations(), defaultPagination(), defaultOrdering()) + column := "transportation_office_id" + ordering := query.NewQueryOrder(&column, models.BoolPointer(true)) + + rejectedOfficeUsers, _, err := fetcher.FetchRejectedOfficeUsersList(suite.AppContextForTest(), nil, defaultPagination(), ordering) + + suite.NoError(err) + suite.Len(rejectedOfficeUsers, 3) + suite.Equal(officeUser3.ID.String(), rejectedOfficeUsers[0].ID.String()) + suite.Equal(officeUser2.ID.String(), rejectedOfficeUsers[1].ID.String()) + suite.Equal(officeUser1.ID.String(), rejectedOfficeUsers[2].ID.String()) + + ordering = query.NewQueryOrder(&column, models.BoolPointer(false)) + + rejectedOfficeUsers, _, err = fetcher.FetchRejectedOfficeUsersList(suite.AppContextForTest(), nil, defaultPagination(), ordering) + + suite.NoError(err) + suite.Len(rejectedOfficeUsers, 3) + suite.Equal(officeUser1.ID.String(), rejectedOfficeUsers[0].ID.String()) + suite.Equal(officeUser2.ID.String(), rejectedOfficeUsers[1].ID.String()) + suite.Equal(officeUser3.ID.String(), rejectedOfficeUsers[2].ID.String()) + + column = "unknown_column" + + rejectedOfficeUsers, _, err = fetcher.FetchRejectedOfficeUsersList(suite.AppContextForTest(), nil, defaultPagination(), ordering) suite.Error(err) - suite.Equal(err.Error(), "Fetch error") - suite.Equal(models.OfficeUsers(nil), rejectedOfficeUsers) + suite.Len(rejectedOfficeUsers, 0) }) } From b5328364022e8376e5254dcea41bcbf75e993524 Mon Sep 17 00:00:00 2001 From: Konstance Haffaney Date: Tue, 18 Feb 2025 17:00:38 +0000 Subject: [PATCH 28/37] sort roles list and update comments --- .../rejected_office_users_list_fetcher.go | 4 ++-- .../Admin/RejectedOfficeUsers/RejectedOfficeUserList.jsx | 1 + 2 files changed, 3 insertions(+), 2 deletions(-) diff --git a/pkg/services/rejected_office_users/rejected_office_users_list_fetcher.go b/pkg/services/rejected_office_users/rejected_office_users_list_fetcher.go index 111afc36689..a00fe861e5c 100644 --- a/pkg/services/rejected_office_users/rejected_office_users_list_fetcher.go +++ b/pkg/services/rejected_office_users/rejected_office_users_list_fetcher.go @@ -19,7 +19,7 @@ type rejectedOfficeUserListFetcher struct { builder rejectedOfficeUsersListQueryBuilder } -// FetchAdminUserList uses the passed query builder to fetch a list of office users +// FetchRejectedUserList uses the passed query builder to fetch a list of office users func (o *rejectedOfficeUserListFetcher) FetchRejectedOfficeUsersList(appCtx appcontext.AppContext, filterFuncs []func(*pop.Query), pagination services.Pagination, ordering services.QueryOrder) (models.OfficeUsers, int, error) { var query *pop.Query var rejectedUsers models.OfficeUsers @@ -73,7 +73,7 @@ func (o *rejectedOfficeUserListFetcher) FetchRejectedOfficeUsersList(appCtx appc return rejectedUsers, count, nil } -// FetchAdminUserList uses the passed query builder to fetch a list of office users +// FetchRejectedUserList uses the passed query builder to fetch a list of office users func (o *rejectedOfficeUserListFetcher) FetchRejectedOfficeUsersCount(appCtx appcontext.AppContext, filters []services.QueryFilter) (int, error) { var rejectedUsers models.OfficeUsers count, err := o.builder.Count(appCtx, &rejectedUsers, filters) diff --git a/src/pages/Admin/RejectedOfficeUsers/RejectedOfficeUserList.jsx b/src/pages/Admin/RejectedOfficeUsers/RejectedOfficeUserList.jsx index c014cf485bc..029e5a6643e 100644 --- a/src/pages/Admin/RejectedOfficeUsers/RejectedOfficeUserList.jsx +++ b/src/pages/Admin/RejectedOfficeUsers/RejectedOfficeUserList.jsx @@ -25,6 +25,7 @@ const RejectedOfficeUserShowRoles = () => { } } + uniqueRoleNamesList.sort(); return {uniqueRoleNamesList.join(', ')}; }; From 8729194cadfbf4e96e1d6454f16ba4b97e2c54d5 Mon Sep 17 00:00:00 2001 From: Konstance Haffaney Date: Wed, 19 Feb 2025 17:53:06 +0000 Subject: [PATCH 29/37] remove front list sort add backend sortby roles --- .../rejected_office_users_list_fetcher.go | 17 ++++++++++++++++- .../RejectedOfficeUserList.jsx | 3 +-- 2 files changed, 17 insertions(+), 3 deletions(-) diff --git a/pkg/services/rejected_office_users/rejected_office_users_list_fetcher.go b/pkg/services/rejected_office_users/rejected_office_users_list_fetcher.go index a00fe861e5c..9529d62ca77 100644 --- a/pkg/services/rejected_office_users/rejected_office_users_list_fetcher.go +++ b/pkg/services/rejected_office_users/rejected_office_users_list_fetcher.go @@ -49,7 +49,16 @@ func (o *rejectedOfficeUserListFetcher) FetchRejectedOfficeUsersList(appCtx appc orderTerm = *ordering.Column() } - query.Order(fmt.Sprintf("%s %s", orderTerm, order)) + if orderTerm == "role" { + if order == "asc" { + query = query.Order("MIN(roles.role_name) ASC") + } else { + query = query.Order("MIN(roles.role_name) DESC") + } + } else { + query = query.Order(fmt.Sprintf("%s %s", orderTerm, order)) + } + query.Select("office_users.*") err := query.Paginate(pagination.Page(), pagination.PerPage()).All(&rejectedUsers) @@ -57,6 +66,12 @@ func (o *rejectedOfficeUserListFetcher) FetchRejectedOfficeUsersList(appCtx appc return nil, 0, err } + for i := range rejectedUsers { + sort.Slice(rejectedUsers[i].User.Roles, func(a, b int) bool { + return rejectedUsers[i].User.Roles[a].RoleName < rejectedUsers[i].User.Roles[b].RoleName + }) + } + if orderTerm == "transportation_office_id" { if order == "desc" { sort.Slice(rejectedUsers, func(i, j int) bool { diff --git a/src/pages/Admin/RejectedOfficeUsers/RejectedOfficeUserList.jsx b/src/pages/Admin/RejectedOfficeUsers/RejectedOfficeUserList.jsx index 029e5a6643e..1a9c5f0825e 100644 --- a/src/pages/Admin/RejectedOfficeUsers/RejectedOfficeUserList.jsx +++ b/src/pages/Admin/RejectedOfficeUsers/RejectedOfficeUserList.jsx @@ -25,7 +25,6 @@ const RejectedOfficeUserShowRoles = () => { } } - uniqueRoleNamesList.sort(); return {uniqueRoleNamesList.join(', ')}; }; @@ -61,7 +60,7 @@ const RejectedOfficeUserList = () => ( - + From d9cd0e7c1d29ac41766fd992a5d99c36d14bbfa1 Mon Sep 17 00:00:00 2001 From: Konstance Haffaney Date: Wed, 19 Feb 2025 18:23:58 +0000 Subject: [PATCH 30/37] update comment --- .../rejected_office_users/rejected_office_users_list_fetcher.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pkg/services/rejected_office_users/rejected_office_users_list_fetcher.go b/pkg/services/rejected_office_users/rejected_office_users_list_fetcher.go index 9529d62ca77..33495a3979c 100644 --- a/pkg/services/rejected_office_users/rejected_office_users_list_fetcher.go +++ b/pkg/services/rejected_office_users/rejected_office_users_list_fetcher.go @@ -95,7 +95,7 @@ func (o *rejectedOfficeUserListFetcher) FetchRejectedOfficeUsersCount(appCtx app return count, err } -// NewAdminUserListFetcher returns an implementation of AdminUserListFetcher +// NewRejectedUserListFetcher returns an implementation of RejectedUserListFetcher func NewRejectedOfficeUsersListFetcher(builder rejectedOfficeUsersListQueryBuilder) services.RejectedOfficeUserListFetcher { return &rejectedOfficeUserListFetcher{builder} } From e01808792834fe7e92bd0f00f7c17a275697d80a Mon Sep 17 00:00:00 2001 From: Konstance Haffaney Date: Wed, 19 Feb 2025 19:15:26 +0000 Subject: [PATCH 31/37] adding missing from int and testing --- pkg/handlers/adminapi/api.go | 7 + .../adminapi/rejected_office_users.go | 49 ++++--- .../adminapi/rejected_office_users_test.go | 11 +- .../mocks/RejectedOfficeUserListFetcher.go | 33 +++-- pkg/services/rejected_office_users.go | 8 +- .../rejected_office_user_fetcher.go | 30 ++++ .../rejected_office_user_fetcher_test.go | 66 +++++++++ .../rejected_office_users_list_fetcher.go | 74 +++++++++- ...rejected_office_users_list_fetcher_test.go | 136 +++++++++++++----- .../RejectedOfficeUserList.jsx | 2 +- .../RejectedOfficeUserShow.module.scss | 53 ------- 11 files changed, 331 insertions(+), 138 deletions(-) create mode 100644 pkg/services/rejected_office_users/rejected_office_user_fetcher.go create mode 100644 pkg/services/rejected_office_users/rejected_office_user_fetcher_test.go delete mode 100644 src/pages/Admin/RejectedOfficeUsers/RejectedOfficeUserShow.module.scss diff --git a/pkg/handlers/adminapi/api.go b/pkg/handlers/adminapi/api.go index ffce154f4cc..3263cc482f7 100644 --- a/pkg/handlers/adminapi/api.go +++ b/pkg/handlers/adminapi/api.go @@ -88,6 +88,13 @@ func NewAdminAPI(handlerConfig handlers.HandlerConfig) *adminops.MymoveAPI { pagination.NewPagination, } + adminAPI.RejectedOfficeUsersGetRejectedOfficeUserHandler = GetRejectedOfficeUserHandler{ + handlerConfig, + rejectedofficeusers.NewRejectedOfficeUserFetcher(queryBuilder), + newRolesFetcher, + query.NewQueryFilter, + } + adminAPI.OfficeUsersIndexOfficeUsersHandler = IndexOfficeUsersHandler{ handlerConfig, fetch.NewListFetcher(queryBuilder), diff --git a/pkg/handlers/adminapi/rejected_office_users.go b/pkg/handlers/adminapi/rejected_office_users.go index 80b94fdb033..f5189d5a090 100644 --- a/pkg/handlers/adminapi/rejected_office_users.go +++ b/pkg/handlers/adminapi/rejected_office_users.go @@ -1,9 +1,12 @@ package adminapi import ( + "encoding/json" + "errors" "fmt" "github.com/go-openapi/runtime/middleware" + "github.com/gobuffalo/pop/v6" "go.uber.org/zap" "github.com/transcom/mymove/pkg/appcontext" @@ -59,13 +62,11 @@ type IndexRejectedOfficeUsersHandler struct { services.NewPagination } -var rejectedOfficeUserFilterConverters = map[string]func(string) []services.QueryFilter{ - "search": func(content string) []services.QueryFilter { - nameSearch := fmt.Sprintf("%s%%", content) - return []services.QueryFilter{ - query.NewQueryFilter("email", "ILIKE", fmt.Sprintf("%%%s%%", content)), - query.NewQueryFilter("first_name", "ILIKE", nameSearch), - query.NewQueryFilter("last_name", "ILIKE", nameSearch), +var rejectedOfficeUserFilterConverters = map[string]func(string) func(*pop.Query){ + "search": func(content string) func(*pop.Query) { + return func(query *pop.Query) { + nameSearch := fmt.Sprintf("%%%s%%", content) + query.Where("roles.role_name ILIKE ? AND office_users.status = 'REJECTED' OR transportation_offices.name ILIKE ? AND office_users.status = 'REJECTED' OR office_users.email ILIKE ? AND office_users.status = 'REJECTED' OR office_users.first_name ILIKE ? AND office_users.status = 'REJECTED' OR office_users.last_name ILIKE ? AND office_users.status = 'REJECTED'", nameSearch, nameSearch, nameSearch, nameSearch, nameSearch) } }, } @@ -75,27 +76,25 @@ func (h IndexRejectedOfficeUsersHandler) Handle(params rejected_office_users.Ind return h.AuditableAppContextFromRequestWithErrors(params.HTTPRequest, func(appCtx appcontext.AppContext) (middleware.Responder, error) { - // adding in filters for when a search or filtering is done - queryFilters := generateQueryFilters(appCtx.Logger(), params.Filter, rejectedOfficeUserFilterConverters) + var filtersMap map[string]string + if params.Filter != nil && *params.Filter != "" { + err := json.Unmarshal([]byte(*params.Filter), &filtersMap) + if err != nil { + return handlers.ResponseForError(appCtx.Logger(), errors.New("invalid filter format")), err + } + } - // We only want users that are in a REJECTED status - queryFilters = append(queryFilters, query.NewQueryFilter("status", "=", "REJECTED")) + var filterFuncs []func(*pop.Query) + for key, filterFunc := range rejectedOfficeUserFilterConverters { + if filterValue, exists := filtersMap[key]; exists { + filterFuncs = append(filterFuncs, filterFunc(filterValue)) + } + } - // adding in pagination for the UI pagination := h.NewPagination(params.Page, params.PerPage) ordering := query.NewQueryOrder(params.Sort, params.Order) - // need to also get the user's roles - queryAssociations := query.NewQueryAssociationsPreload([]services.QueryAssociation{ - query.NewQueryAssociation("User.Roles"), - }) - - officeUsers, err := h.RejectedOfficeUserListFetcher.FetchRejectedOfficeUsersList(appCtx, queryFilters, queryAssociations, pagination, ordering) - if err != nil { - return handlers.ResponseForError(appCtx.Logger(), err), err - } - - totalOfficeUsersCount, err := h.RejectedOfficeUserListFetcher.FetchRejectedOfficeUsersCount(appCtx, queryFilters) + officeUsers, count, err := h.RejectedOfficeUserListFetcher.FetchRejectedOfficeUsersList(appCtx, filterFuncs, pagination, ordering) if err != nil { return handlers.ResponseForError(appCtx.Logger(), err), err } @@ -108,7 +107,7 @@ func (h IndexRejectedOfficeUsersHandler) Handle(params rejected_office_users.Ind payload[i] = payloadForRejectedOfficeUserModel(s) } - return rejected_office_users.NewIndexRejectedOfficeUsersOK().WithContentRange(fmt.Sprintf("rejected office users %d-%d/%d", pagination.Offset(), pagination.Offset()+queriedOfficeUsersCount, totalOfficeUsersCount)).WithPayload(payload), nil + return rejected_office_users.NewIndexRejectedOfficeUsersOK().WithContentRange(fmt.Sprintf("rejected office users %d-%d/%d", pagination.Offset(), pagination.Offset()+queriedOfficeUsersCount, count)).WithPayload(payload), nil }) } @@ -146,4 +145,4 @@ func (h GetRejectedOfficeUserHandler) Handle(params rejected_office_users.GetRej return rejected_office_users.NewGetRejectedOfficeUserOK().WithPayload(payload), nil }) -} \ No newline at end of file +} diff --git a/pkg/handlers/adminapi/rejected_office_users_test.go b/pkg/handlers/adminapi/rejected_office_users_test.go index 5ed2d09aa09..e55397e1c9a 100644 --- a/pkg/handlers/adminapi/rejected_office_users_test.go +++ b/pkg/handlers/adminapi/rejected_office_users_test.go @@ -1,6 +1,8 @@ package adminapi import ( + "slices" + "github.com/transcom/mymove/pkg/factory" rejectedofficeuserop "github.com/transcom/mymove/pkg/gen/adminapi/adminoperations/rejected_office_users" "github.com/transcom/mymove/pkg/models" @@ -35,7 +37,12 @@ func (suite *HandlerSuite) TestIndexRejectedOfficeUsersHandler() { // should get an ok response suite.IsType(&rejectedofficeuserop.IndexRejectedOfficeUsersOK{}, response) okResponse := response.(*rejectedofficeuserop.IndexRejectedOfficeUsersOK) - suite.Len(okResponse.Payload, 2) - suite.Equal(rejectedOfficeUsers[0].ID.String(), okResponse.Payload[0].ID.String()) + suite.Equal(len(okResponse.Payload), len(rejectedOfficeUsers)) + + actualID := []string{okResponse.Payload[0].ID.String(), okResponse.Payload[1].ID.String()} + expected := []string{rejectedOfficeUsers[0].ID.String(), rejectedOfficeUsers[1].ID.String()} + for _, expectedID := range expected { + suite.True(slices.Contains(actualID, expectedID)) + } }) } diff --git a/pkg/services/mocks/RejectedOfficeUserListFetcher.go b/pkg/services/mocks/RejectedOfficeUserListFetcher.go index 6c998167d98..b76aa385a76 100644 --- a/pkg/services/mocks/RejectedOfficeUserListFetcher.go +++ b/pkg/services/mocks/RejectedOfficeUserListFetcher.go @@ -8,6 +8,8 @@ import ( models "github.com/transcom/mymove/pkg/models" + pop "github.com/gobuffalo/pop/v6" + services "github.com/transcom/mymove/pkg/services" ) @@ -44,34 +46,41 @@ func (_m *RejectedOfficeUserListFetcher) FetchRejectedOfficeUsersCount(appCtx ap return r0, r1 } -// FetchRejectedOfficeUsersList provides a mock function with given fields: appCtx, filters, associations, pagination, ordering -func (_m *RejectedOfficeUserListFetcher) FetchRejectedOfficeUsersList(appCtx appcontext.AppContext, filters []services.QueryFilter, associations services.QueryAssociations, pagination services.Pagination, ordering services.QueryOrder) (models.OfficeUsers, error) { - ret := _m.Called(appCtx, filters, associations, pagination, ordering) +// FetchRejectedOfficeUsersList provides a mock function with given fields: appCtx, filterFuncs, pagination, ordering +func (_m *RejectedOfficeUserListFetcher) FetchRejectedOfficeUsersList(appCtx appcontext.AppContext, filterFuncs []func(*pop.Query), pagination services.Pagination, ordering services.QueryOrder) (models.OfficeUsers, int, error) { + ret := _m.Called(appCtx, filterFuncs, pagination, ordering) if len(ret) == 0 { panic("no return value specified for FetchRejectedOfficeUsersList") } var r0 models.OfficeUsers - var r1 error - if rf, ok := ret.Get(0).(func(appcontext.AppContext, []services.QueryFilter, services.QueryAssociations, services.Pagination, services.QueryOrder) (models.OfficeUsers, error)); ok { - return rf(appCtx, filters, associations, pagination, ordering) + var r1 int + var r2 error + if rf, ok := ret.Get(0).(func(appcontext.AppContext, []func(*pop.Query), services.Pagination, services.QueryOrder) (models.OfficeUsers, int, error)); ok { + return rf(appCtx, filterFuncs, pagination, ordering) } - if rf, ok := ret.Get(0).(func(appcontext.AppContext, []services.QueryFilter, services.QueryAssociations, services.Pagination, services.QueryOrder) models.OfficeUsers); ok { - r0 = rf(appCtx, filters, associations, pagination, ordering) + if rf, ok := ret.Get(0).(func(appcontext.AppContext, []func(*pop.Query), services.Pagination, services.QueryOrder) models.OfficeUsers); ok { + r0 = rf(appCtx, filterFuncs, pagination, ordering) } else { if ret.Get(0) != nil { r0 = ret.Get(0).(models.OfficeUsers) } } - if rf, ok := ret.Get(1).(func(appcontext.AppContext, []services.QueryFilter, services.QueryAssociations, services.Pagination, services.QueryOrder) error); ok { - r1 = rf(appCtx, filters, associations, pagination, ordering) + if rf, ok := ret.Get(1).(func(appcontext.AppContext, []func(*pop.Query), services.Pagination, services.QueryOrder) int); ok { + r1 = rf(appCtx, filterFuncs, pagination, ordering) } else { - r1 = ret.Error(1) + r1 = ret.Get(1).(int) } - return r0, r1 + if rf, ok := ret.Get(2).(func(appcontext.AppContext, []func(*pop.Query), services.Pagination, services.QueryOrder) error); ok { + r2 = rf(appCtx, filterFuncs, pagination, ordering) + } else { + r2 = ret.Error(2) + } + + return r0, r1, r2 } // NewRejectedOfficeUserListFetcher creates a new instance of RejectedOfficeUserListFetcher. It also registers a testing interface on the mock and a cleanup function to assert the mocks expectations. diff --git a/pkg/services/rejected_office_users.go b/pkg/services/rejected_office_users.go index 1a7d57990f4..4fc962f491b 100644 --- a/pkg/services/rejected_office_users.go +++ b/pkg/services/rejected_office_users.go @@ -1,19 +1,21 @@ package services import ( + "github.com/gobuffalo/pop/v6" + "github.com/transcom/mymove/pkg/appcontext" "github.com/transcom/mymove/pkg/models" ) -// RejectedOfficeUserListFetcher is the exported interface for fetching multiple rejected rejected office users +// RejectedOfficeUserListFetcher is the exported interface for fetching multiple rejected office users // //go:generate mockery --name RejectedOfficeUserListFetcher type RejectedOfficeUserListFetcher interface { - FetchRejectedOfficeUsersList(appCtx appcontext.AppContext, filters []QueryFilter, associations QueryAssociations, pagination Pagination, ordering QueryOrder) (models.OfficeUsers, error) + FetchRejectedOfficeUsersList(appCtx appcontext.AppContext, filterFuncs []func(*pop.Query), pagination Pagination, ordering QueryOrder) (models.OfficeUsers, int, error) FetchRejectedOfficeUsersCount(appCtx appcontext.AppContext, filters []QueryFilter) (int, error) } -// RejectedOfficeUserFetcher is the exported interface for fetching a single rejected rejected office user +// RejectedOfficeUserFetcher is the exported interface for fetching a single rejected office user // //go:generate mockery --name RejectedOfficeUserFetcher type RejectedOfficeUserFetcher interface { diff --git a/pkg/services/rejected_office_users/rejected_office_user_fetcher.go b/pkg/services/rejected_office_users/rejected_office_user_fetcher.go new file mode 100644 index 00000000000..5c6b85bd413 --- /dev/null +++ b/pkg/services/rejected_office_users/rejected_office_user_fetcher.go @@ -0,0 +1,30 @@ +package adminuser + +import ( + "github.com/gobuffalo/validate/v3" + + "github.com/transcom/mymove/pkg/appcontext" + "github.com/transcom/mymove/pkg/models" + "github.com/transcom/mymove/pkg/services" +) + +type rejectedOfficeUserQueryBuilder interface { + FetchOne(appCtx appcontext.AppContext, model interface{}, filters []services.QueryFilter) error + UpdateOne(appCtx appcontext.AppContext, model interface{}, eTag *string) (*validate.Errors, error) +} + +type rejectedOfficeUserFetcher struct { + builder rejectedOfficeUserQueryBuilder +} + +// FetchRejectedOfficeUser fetches an office user given a slice of filters +func (o *rejectedOfficeUserFetcher) FetchRejectedOfficeUser(appCtx appcontext.AppContext, filters []services.QueryFilter) (models.OfficeUser, error) { + var rejectedOfficeUser models.OfficeUser + err := o.builder.FetchOne(appCtx, &rejectedOfficeUser, filters) + return rejectedOfficeUser, err +} + +// NewAdminUserFetcher return an implementation of the AdminUserFetcher interface +func NewRejectedOfficeUserFetcher(builder rejectedOfficeUserQueryBuilder) services.RejectedOfficeUserFetcher { + return &rejectedOfficeUserFetcher{builder} +} diff --git a/pkg/services/rejected_office_users/rejected_office_user_fetcher_test.go b/pkg/services/rejected_office_users/rejected_office_user_fetcher_test.go new file mode 100644 index 00000000000..82dea63c812 --- /dev/null +++ b/pkg/services/rejected_office_users/rejected_office_user_fetcher_test.go @@ -0,0 +1,66 @@ +package adminuser + +import ( + "errors" + "reflect" + + "github.com/gobuffalo/validate/v3" + "github.com/gofrs/uuid" + + "github.com/transcom/mymove/pkg/appcontext" + "github.com/transcom/mymove/pkg/models" + "github.com/transcom/mymove/pkg/services" + "github.com/transcom/mymove/pkg/services/query" +) + +type testRejectedOfficeUsersQueryBuilder struct { + fakeFetchOne func(appConfig appcontext.AppContext, model interface{}) error +} + +func (t *testRejectedOfficeUsersQueryBuilder) FetchOne(appConfig appcontext.AppContext, model interface{}, _ []services.QueryFilter) error { + m := t.fakeFetchOne(appConfig, model) + return m +} + +func (t *testRejectedOfficeUsersQueryBuilder) UpdateOne(_ appcontext.AppContext, _ interface{}, _ *string) (*validate.Errors, error) { + return nil, nil +} + +func (suite *RejectedOfficeUsersServiceSuite) TestFetchRejectedOfficeUser() { + suite.Run("if the rejected office user is fetched, it should be returned", func() { + id, err := uuid.NewV4() + suite.NoError(err) + fakeFetchOne := func(_ appcontext.AppContext, model interface{}) error { + reflect.ValueOf(model).Elem().FieldByName("ID").Set(reflect.ValueOf(id)) + return nil + } + + builder := &testRejectedOfficeUsersQueryBuilder{ + fakeFetchOne: fakeFetchOne, + } + + fetcher := NewRejectedOfficeUserFetcher(builder) + filters := []services.QueryFilter{query.NewQueryFilter("id", "=", id.String())} + + rejectedOfficeUser, err := fetcher.FetchRejectedOfficeUser(suite.AppContextForTest(), filters) + + suite.NoError(err) + suite.Equal(id, rejectedOfficeUser.ID) + }) + + suite.Run("if there is an error, we get it with zero admin user", func() { + fakeFetchOne := func(_ appcontext.AppContext, _ interface{}) error { + return errors.New("Fetch error") + } + builder := &testRejectedOfficeUsersQueryBuilder{ + fakeFetchOne: fakeFetchOne, + } + fetcher := NewRejectedOfficeUserFetcher(builder) + + rejectedOfficeUser, err := fetcher.FetchRejectedOfficeUser(suite.AppContextForTest(), []services.QueryFilter{}) + + suite.Error(err) + suite.Equal(err.Error(), "Fetch error") + suite.Equal(models.OfficeUser{}, rejectedOfficeUser) + }) +} diff --git a/pkg/services/rejected_office_users/rejected_office_users_list_fetcher.go b/pkg/services/rejected_office_users/rejected_office_users_list_fetcher.go index 2a753020d70..33495a3979c 100644 --- a/pkg/services/rejected_office_users/rejected_office_users_list_fetcher.go +++ b/pkg/services/rejected_office_users/rejected_office_users_list_fetcher.go @@ -1,13 +1,17 @@ package adminuser import ( + "fmt" + "sort" + + "github.com/gobuffalo/pop/v6" + "github.com/transcom/mymove/pkg/appcontext" "github.com/transcom/mymove/pkg/models" "github.com/transcom/mymove/pkg/services" ) type rejectedOfficeUsersListQueryBuilder interface { - FetchMany(appCtx appcontext.AppContext, model interface{}, filters []services.QueryFilter, associations services.QueryAssociations, pagination services.Pagination, ordering services.QueryOrder) error Count(appCtx appcontext.AppContext, model interface{}, filters []services.QueryFilter) (int, error) } @@ -16,10 +20,72 @@ type rejectedOfficeUserListFetcher struct { } // FetchRejectedUserList uses the passed query builder to fetch a list of office users -func (o *rejectedOfficeUserListFetcher) FetchRejectedOfficeUsersList(appCtx appcontext.AppContext, filters []services.QueryFilter, associations services.QueryAssociations, pagination services.Pagination, ordering services.QueryOrder) (models.OfficeUsers, error) { +func (o *rejectedOfficeUserListFetcher) FetchRejectedOfficeUsersList(appCtx appcontext.AppContext, filterFuncs []func(*pop.Query), pagination services.Pagination, ordering services.QueryOrder) (models.OfficeUsers, int, error) { + var query *pop.Query var rejectedUsers models.OfficeUsers - err := o.builder.FetchMany(appCtx, &rejectedUsers, filters, associations, pagination, ordering) - return rejectedUsers, err + + query = appCtx.DB().Q().EagerPreload( + "User.Roles", + "TransportationOffice"). + 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") + + for _, filterFunc := range filterFuncs { + filterFunc(query) + } + + query = query.Where("status = ?", models.OfficeUserStatusREJECTED) + query.GroupBy("office_users.id") + + var order = "desc" + if ordering.SortOrder() != nil && *ordering.SortOrder() { + order = "asc" + } + + var orderTerm = "id" + if ordering.Column() != nil { + orderTerm = *ordering.Column() + } + + if orderTerm == "role" { + if order == "asc" { + query = query.Order("MIN(roles.role_name) ASC") + } else { + query = query.Order("MIN(roles.role_name) DESC") + } + } else { + query = query.Order(fmt.Sprintf("%s %s", orderTerm, order)) + } + + query.Select("office_users.*") + + err := query.Paginate(pagination.Page(), pagination.PerPage()).All(&rejectedUsers) + if err != nil { + return nil, 0, err + } + + for i := range rejectedUsers { + sort.Slice(rejectedUsers[i].User.Roles, func(a, b int) bool { + return rejectedUsers[i].User.Roles[a].RoleName < rejectedUsers[i].User.Roles[b].RoleName + }) + } + + if orderTerm == "transportation_office_id" { + if order == "desc" { + sort.Slice(rejectedUsers, func(i, j int) bool { + return rejectedUsers[i].TransportationOffice.Name > rejectedUsers[j].TransportationOffice.Name + }) + } else { + sort.Slice(rejectedUsers, func(i, j int) bool { + return rejectedUsers[i].TransportationOffice.Name < rejectedUsers[j].TransportationOffice.Name + }) + } + } + + count := query.Paginator.TotalEntriesSize + return rejectedUsers, count, nil } // FetchRejectedUserList uses the passed query builder to fetch a list of office users diff --git a/pkg/services/rejected_office_users/rejected_office_users_list_fetcher_test.go b/pkg/services/rejected_office_users/rejected_office_users_list_fetcher_test.go index ace816aeeb1..bef14132191 100644 --- a/pkg/services/rejected_office_users/rejected_office_users_list_fetcher_test.go +++ b/pkg/services/rejected_office_users/rejected_office_users_list_fetcher_test.go @@ -1,26 +1,17 @@ package adminuser import ( - "errors" - "reflect" - - "github.com/gofrs/uuid" - "github.com/transcom/mymove/pkg/appcontext" + "github.com/transcom/mymove/pkg/factory" "github.com/transcom/mymove/pkg/models" + "github.com/transcom/mymove/pkg/models/roles" "github.com/transcom/mymove/pkg/services" "github.com/transcom/mymove/pkg/services/pagination" "github.com/transcom/mymove/pkg/services/query" ) type testRejectedOfficeUsersListQueryBuilder struct { - fakeFetchMany func(appCtx appcontext.AppContext, model interface{}) error - fakeCount func(appCtx appcontext.AppContext, model interface{}) (int, error) -} - -func (t *testRejectedOfficeUsersListQueryBuilder) FetchMany(appCtx appcontext.AppContext, model interface{}, _ []services.QueryFilter, _ services.QueryAssociations, _ services.Pagination, _ services.QueryOrder) error { - m := t.fakeFetchMany(appCtx, model) - return m + fakeCount func(appCtx appcontext.AppContext, model interface{}) (int, error) } func (t *testRejectedOfficeUsersListQueryBuilder) Count(appCtx appcontext.AppContext, model interface{}, _ []services.QueryFilter) (int, error) { @@ -33,50 +24,119 @@ func defaultPagination() services.Pagination { return pagination.NewPagination(&page, &perPage) } -func defaultAssociations() services.QueryAssociations { - return query.NewQueryAssociations([]services.QueryAssociation{}) -} - func defaultOrdering() services.QueryOrder { return query.NewQueryOrder(nil, nil) } func (suite *RejectedOfficeUsersServiceSuite) TestFetchRejectedOfficeUserList() { suite.Run("if the users are successfully fetched, they should be returned", func() { - id, err := uuid.NewV4() + rejectedStatus := models.OfficeUserStatusREJECTED + officeUser1 := factory.BuildOfficeUserWithRoles(suite.DB(), []factory.Customization{ + { + Model: models.OfficeUser{ + Status: &rejectedStatus, + }, + }, + }, []roles.RoleType{roles.RoleTypeTOO}) + builder := &testRejectedOfficeUsersListQueryBuilder{} + + fetcher := NewRejectedOfficeUsersListFetcher(builder) + + rejectedOfficeUsers, _, err := fetcher.FetchRejectedOfficeUsersList(suite.AppContextForTest(), nil, defaultPagination(), defaultOrdering()) + suite.NoError(err) - fakeFetchMany := func(_ appcontext.AppContext, model interface{}) error { - value := reflect.ValueOf(model).Elem() - rejectedStatus := models.OfficeUserStatusREJECTED - value.Set(reflect.Append(value, reflect.ValueOf(models.OfficeUser{ID: id, Status: &rejectedStatus}))) - return nil - } - builder := &testRejectedOfficeUsersListQueryBuilder{ - fakeFetchMany: fakeFetchMany, - } + suite.Equal(officeUser1.ID, rejectedOfficeUsers[0].ID) + }) + + suite.Run("if there are no rejected office users, we don't receive any rejected office users", func() { + builder := &testRejectedOfficeUsersListQueryBuilder{} fetcher := NewRejectedOfficeUsersListFetcher(builder) - rejectedOfficeUsers, err := fetcher.FetchRejectedOfficeUsersList(suite.AppContextForTest(), nil, defaultAssociations(), defaultPagination(), defaultOrdering()) + rejectedOfficeUsers, _, err := fetcher.FetchRejectedOfficeUsersList(suite.AppContextForTest(), nil, defaultPagination(), defaultOrdering()) suite.NoError(err) - suite.Equal(id, rejectedOfficeUsers[0].ID) + suite.Equal(models.OfficeUsers(nil), rejectedOfficeUsers) }) - suite.Run("if there is an error, we get it with no rejected office users", func() { - fakeFetchMany := func(_ appcontext.AppContext, _ interface{}) error { - return errors.New("Fetch error") - } - builder := &testRejectedOfficeUsersListQueryBuilder{ - fakeFetchMany: fakeFetchMany, - } + suite.Run("should sort and order rejected office users", func() { + rejectedStatus := models.OfficeUserStatusREJECTED + officeUser1 := factory.BuildOfficeUserWithRoles(suite.DB(), []factory.Customization{ + { + Model: models.OfficeUser{ + FirstName: "Angelina", + LastName: "Jolie", + Email: "laraCroft@mail.mil", + Status: &rejectedStatus, + }, + }, + { + Model: models.TransportationOffice{ + Name: "PPPO Kirtland AFB - USAF", + }, + }, + }, []roles.RoleType{roles.RoleTypeTOO}) + officeUser2 := factory.BuildOfficeUserWithRoles(suite.DB(), []factory.Customization{ + { + Model: models.OfficeUser{ + FirstName: "Billy", + LastName: "Bob", + Email: "bigBob@mail.mil", + Status: &rejectedStatus, + }, + }, + { + Model: models.TransportationOffice{ + Name: "PPPO Fort Knox - USA", + }, + }, + }, []roles.RoleType{roles.RoleTypeTIO}) + officeUser3 := factory.BuildOfficeUserWithRoles(suite.DB(), []factory.Customization{ + { + Model: models.OfficeUser{ + FirstName: "Nick", + LastName: "Cage", + Email: "conAirKilluh@mail.mil", + Status: &rejectedStatus, + }, + }, + { + Model: models.TransportationOffice{ + Name: "PPPO Detroit Arsenal - USA", + }, + }, + }, []roles.RoleType{roles.RoleTypeServicesCounselor}) + + builder := &testRejectedOfficeUsersListQueryBuilder{} fetcher := NewRejectedOfficeUsersListFetcher(builder) - rejectedOfficeUsers, err := fetcher.FetchRejectedOfficeUsersList(suite.AppContextForTest(), []services.QueryFilter{}, defaultAssociations(), defaultPagination(), defaultOrdering()) + column := "transportation_office_id" + ordering := query.NewQueryOrder(&column, models.BoolPointer(true)) + + rejectedOfficeUsers, _, err := fetcher.FetchRejectedOfficeUsersList(suite.AppContextForTest(), nil, defaultPagination(), ordering) + + suite.NoError(err) + suite.Len(rejectedOfficeUsers, 3) + suite.Equal(officeUser3.ID.String(), rejectedOfficeUsers[0].ID.String()) + suite.Equal(officeUser2.ID.String(), rejectedOfficeUsers[1].ID.String()) + suite.Equal(officeUser1.ID.String(), rejectedOfficeUsers[2].ID.String()) + + ordering = query.NewQueryOrder(&column, models.BoolPointer(false)) + + rejectedOfficeUsers, _, err = fetcher.FetchRejectedOfficeUsersList(suite.AppContextForTest(), nil, defaultPagination(), ordering) + + suite.NoError(err) + suite.Len(rejectedOfficeUsers, 3) + suite.Equal(officeUser1.ID.String(), rejectedOfficeUsers[0].ID.String()) + suite.Equal(officeUser2.ID.String(), rejectedOfficeUsers[1].ID.String()) + suite.Equal(officeUser3.ID.String(), rejectedOfficeUsers[2].ID.String()) + + column = "unknown_column" + + rejectedOfficeUsers, _, err = fetcher.FetchRejectedOfficeUsersList(suite.AppContextForTest(), nil, defaultPagination(), ordering) suite.Error(err) - suite.Equal(err.Error(), "Fetch error") - suite.Equal(models.OfficeUsers(nil), rejectedOfficeUsers) + suite.Len(rejectedOfficeUsers, 0) }) } diff --git a/src/pages/Admin/RejectedOfficeUsers/RejectedOfficeUserList.jsx b/src/pages/Admin/RejectedOfficeUsers/RejectedOfficeUserList.jsx index c014cf485bc..1a9c5f0825e 100644 --- a/src/pages/Admin/RejectedOfficeUsers/RejectedOfficeUserList.jsx +++ b/src/pages/Admin/RejectedOfficeUsers/RejectedOfficeUserList.jsx @@ -60,7 +60,7 @@ const RejectedOfficeUserList = () => ( - + diff --git a/src/pages/Admin/RejectedOfficeUsers/RejectedOfficeUserShow.module.scss b/src/pages/Admin/RejectedOfficeUsers/RejectedOfficeUserShow.module.scss deleted file mode 100644 index 2e8c5d470b7..00000000000 --- a/src/pages/Admin/RejectedOfficeUsers/RejectedOfficeUserShow.module.scss +++ /dev/null @@ -1,53 +0,0 @@ -@import 'shared/styles/colors.scss'; - -.btnContainer { - display: flex; - justify-content: flex-start; - align-self: center; - gap: 10px; - - .approveBtn { - width: 125px; - margin-left: 15px; - background-color: $primary; - - &:active, - &:hover, - &:focus { - background-color: $primary; - opacity: 80%; - } - } - - .rejectBtn { - width: 125px; - background-color: $error; - - &:active, - &:hover, - &:focus { - background-color: $error; - opacity: 80%; - } - } -} - -.rejectionInput { - margin-left: 15px; - margin-bottom: 10px; -} - -.error { - width: auto; - background-color: $error; - margin-left: 15px; - margin-right: 15px; -} - -.rejErrorEdit { - width: auto; - background-color: $error; - margin-left: 15px; - margin-right: 15px; - margin-bottom: 10px; -} From c82a7a689f037ff1d20452b0f6e7770ab9d6589b Mon Sep 17 00:00:00 2001 From: Konstance Haffaney Date: Thu, 20 Feb 2025 16:04:05 +0000 Subject: [PATCH 32/37] added test, moved migration, updated comment/record, ran mocks --- migrations/app/migrations_manifest.txt | 2 +- .../adminapi/rejected_office_users_test.go | 137 ++++++++++++++++++ .../mocks/RejectedOfficeUserListFetcher.go | 33 +++-- pkg/services/move/move_fetcher_test.go | 84 ----------- .../rejected_office_user_fetcher.go | 2 +- .../RejectedOfficeUserShow.jsx | 2 +- 6 files changed, 161 insertions(+), 99 deletions(-) diff --git a/migrations/app/migrations_manifest.txt b/migrations/app/migrations_manifest.txt index bd3f9734603..ca7c8232545 100644 --- a/migrations/app/migrations_manifest.txt +++ b/migrations/app/migrations_manifest.txt @@ -1095,10 +1095,10 @@ 20250123173216_add_destination_queue_db_func_and_gbloc_view.up.sql 20250123210535_update_re_intl_transit_times_for_ak_hhg.up.sql 20250127143137_insert_nsra_re_intl_transit_times.up.sql +20250131205338_add_rejected_col_to_admin_users.up.sql 20250204162411_updating_create_accessorial_service_item_proc_for_crating.up.sql 20250206173204_add_hawaii_data.up.sql 20250207153450_add_fetch_documents_func.up.sql 20250210175754_B22451_update_dest_queue_to_consider_sit_extensions.up.sql 20250213151815_fix_spacing_fetch_documents.up.sql 20250213214427_drop_received_by_gex_payment_request_status_type.up.sql -20250131205338_add_rejected_col_to_admin_users.up.sql diff --git a/pkg/handlers/adminapi/rejected_office_users_test.go b/pkg/handlers/adminapi/rejected_office_users_test.go index e55397e1c9a..6f91d6877e0 100644 --- a/pkg/handlers/adminapi/rejected_office_users_test.go +++ b/pkg/handlers/adminapi/rejected_office_users_test.go @@ -1,12 +1,20 @@ package adminapi import ( + "fmt" + "net/http" "slices" + "time" + "github.com/go-openapi/strfmt" + "github.com/gofrs/uuid" + "github.com/stretchr/testify/mock" "github.com/transcom/mymove/pkg/factory" rejectedofficeuserop "github.com/transcom/mymove/pkg/gen/adminapi/adminoperations/rejected_office_users" + "github.com/transcom/mymove/pkg/handlers" "github.com/transcom/mymove/pkg/models" "github.com/transcom/mymove/pkg/models/roles" + "github.com/transcom/mymove/pkg/services/mocks" "github.com/transcom/mymove/pkg/services/pagination" "github.com/transcom/mymove/pkg/services/query" rejectedofficeusers "github.com/transcom/mymove/pkg/services/rejected_office_users" @@ -46,3 +54,132 @@ func (suite *HandlerSuite) TestIndexRejectedOfficeUsersHandler() { } }) } + +func (suite *HandlerSuite) TestGetRejectedOfficeUserHandler() { + suite.Run("integration test ok response", func() { + rejectedOfficeUser := factory.BuildOfficeUserWithRoles(suite.DB(), factory.GetTraitRejectedOfficeUser(), []roles.RoleType{roles.RoleTypeQae}) + params := rejectedofficeuserop.GetRejectedOfficeUserParams{ + HTTPRequest: suite.setupAuthenticatedRequest("GET", fmt.Sprintf("/requested_office_users/%s", rejectedOfficeUser.ID)), + OfficeUserID: strfmt.UUID(rejectedOfficeUser.ID.String()), + } + + mockRoleAssociator := &mocks.RoleAssociater{} + mockRoles := roles.Roles{ + roles.Role{ + ID: uuid.Must(uuid.NewV4()), + RoleType: roles.RoleTypeTOO, + RoleName: "Task Ordering Officer", + CreatedAt: time.Now(), + UpdatedAt: time.Now(), + }, + } + mockRoleAssociator.On( + "FetchRolesForUser", + mock.AnythingOfType("*appcontext.appContext"), + mock.Anything, + ).Return(mockRoles, nil) + + queryBuilder := query.NewQueryBuilder() + handler := GetRejectedOfficeUserHandler{ + suite.HandlerConfig(), + rejectedofficeusers.NewRejectedOfficeUserFetcher(queryBuilder), + mockRoleAssociator, + query.NewQueryFilter, + } + + response := handler.Handle(params) + + suite.IsType(&rejectedofficeuserop.GetRejectedOfficeUserOK{}, response) + okResponse := response.(*rejectedofficeuserop.GetRejectedOfficeUserOK) + suite.Equal(rejectedOfficeUser.ID.String(), okResponse.Payload.ID.String()) + }) + + suite.Run("successful response", func() { + rejectedOfficeUser := factory.BuildOfficeUserWithRoles(suite.DB(), factory.GetTraitRejectedOfficeUser(), []roles.RoleType{roles.RoleTypeQae}) + params := rejectedofficeuserop.GetRejectedOfficeUserParams{ + HTTPRequest: suite.setupAuthenticatedRequest("GET", fmt.Sprintf("/requested_office_users/%s", rejectedOfficeUser.ID)), + OfficeUserID: strfmt.UUID(rejectedOfficeUser.ID.String()), + } + + rejectedOfficeUserFetcher := &mocks.RejectedOfficeUserFetcher{} + rejectedOfficeUserFetcher.On("FetchRejectedOfficeUser", + mock.AnythingOfType("*appcontext.appContext"), + mock.Anything, + ).Return(rejectedOfficeUser, nil).Once() + + mockRoleAssociator := &mocks.RoleAssociater{} + mockRoles := roles.Roles{ + roles.Role{ + ID: uuid.Must(uuid.NewV4()), + RoleType: roles.RoleTypeTOO, + RoleName: "Task Ordering Officer", + CreatedAt: time.Now(), + UpdatedAt: time.Now(), + }, + } + mockRoleAssociator.On( + "FetchRolesForUser", + mock.AnythingOfType("*appcontext.appContext"), + mock.Anything, + ).Return(mockRoles, nil) + + handler := GetRejectedOfficeUserHandler{ + suite.HandlerConfig(), + rejectedOfficeUserFetcher, + mockRoleAssociator, + newMockQueryFilterBuilder(&mocks.QueryFilter{}), + } + + response := handler.Handle(params) + + suite.IsType(&rejectedofficeuserop.GetRejectedOfficeUserOK{}, response) + okResponse := response.(*rejectedofficeuserop.GetRejectedOfficeUserOK) + suite.Equal(rejectedOfficeUser.ID.String(), okResponse.Payload.ID.String()) + }) + + suite.Run("unsuccessful response when fetch fails", func() { + rejectedOfficeUser := factory.BuildOfficeUserWithRoles(suite.DB(), factory.GetTraitRejectedOfficeUser(), []roles.RoleType{roles.RoleTypeQae}) + params := rejectedofficeuserop.GetRejectedOfficeUserParams{ + HTTPRequest: suite.setupAuthenticatedRequest("GET", fmt.Sprintf("/requested_office_users/%s", rejectedOfficeUser.ID)), + OfficeUserID: strfmt.UUID(rejectedOfficeUser.ID.String()), + } + + expectedError := models.ErrFetchNotFound + rejectedOfficeUserFetcher := &mocks.RejectedOfficeUserFetcher{} + rejectedOfficeUserFetcher.On("FetchRejectedOfficeUser", + mock.AnythingOfType("*appcontext.appContext"), + mock.Anything, + ).Return(models.OfficeUser{}, expectedError).Once() + + mockRoleAssociator := &mocks.RoleAssociater{} + mockRoles := roles.Roles{ + roles.Role{ + ID: uuid.Must(uuid.NewV4()), + RoleType: roles.RoleTypeTOO, + RoleName: "Task Ordering Officer", + CreatedAt: time.Now(), + UpdatedAt: time.Now(), + }, + } + mockRoleAssociator.On( + "FetchRolesForUser", + mock.AnythingOfType("*appcontext.appContext"), + mock.Anything, + ).Return(mockRoles, nil) + + handler := GetRejectedOfficeUserHandler{ + suite.HandlerConfig(), + rejectedOfficeUserFetcher, + mockRoleAssociator, + newMockQueryFilterBuilder(&mocks.QueryFilter{}), + } + + response := handler.Handle(params) + + expectedResponse := &handlers.ErrResponse{ + Code: http.StatusNotFound, + Err: expectedError, + } + suite.Equal(expectedResponse, response) + }) +} \ No newline at end of file diff --git a/pkg/services/mocks/RejectedOfficeUserListFetcher.go b/pkg/services/mocks/RejectedOfficeUserListFetcher.go index 6c998167d98..b76aa385a76 100644 --- a/pkg/services/mocks/RejectedOfficeUserListFetcher.go +++ b/pkg/services/mocks/RejectedOfficeUserListFetcher.go @@ -8,6 +8,8 @@ import ( models "github.com/transcom/mymove/pkg/models" + pop "github.com/gobuffalo/pop/v6" + services "github.com/transcom/mymove/pkg/services" ) @@ -44,34 +46,41 @@ func (_m *RejectedOfficeUserListFetcher) FetchRejectedOfficeUsersCount(appCtx ap return r0, r1 } -// FetchRejectedOfficeUsersList provides a mock function with given fields: appCtx, filters, associations, pagination, ordering -func (_m *RejectedOfficeUserListFetcher) FetchRejectedOfficeUsersList(appCtx appcontext.AppContext, filters []services.QueryFilter, associations services.QueryAssociations, pagination services.Pagination, ordering services.QueryOrder) (models.OfficeUsers, error) { - ret := _m.Called(appCtx, filters, associations, pagination, ordering) +// FetchRejectedOfficeUsersList provides a mock function with given fields: appCtx, filterFuncs, pagination, ordering +func (_m *RejectedOfficeUserListFetcher) FetchRejectedOfficeUsersList(appCtx appcontext.AppContext, filterFuncs []func(*pop.Query), pagination services.Pagination, ordering services.QueryOrder) (models.OfficeUsers, int, error) { + ret := _m.Called(appCtx, filterFuncs, pagination, ordering) if len(ret) == 0 { panic("no return value specified for FetchRejectedOfficeUsersList") } var r0 models.OfficeUsers - var r1 error - if rf, ok := ret.Get(0).(func(appcontext.AppContext, []services.QueryFilter, services.QueryAssociations, services.Pagination, services.QueryOrder) (models.OfficeUsers, error)); ok { - return rf(appCtx, filters, associations, pagination, ordering) + var r1 int + var r2 error + if rf, ok := ret.Get(0).(func(appcontext.AppContext, []func(*pop.Query), services.Pagination, services.QueryOrder) (models.OfficeUsers, int, error)); ok { + return rf(appCtx, filterFuncs, pagination, ordering) } - if rf, ok := ret.Get(0).(func(appcontext.AppContext, []services.QueryFilter, services.QueryAssociations, services.Pagination, services.QueryOrder) models.OfficeUsers); ok { - r0 = rf(appCtx, filters, associations, pagination, ordering) + if rf, ok := ret.Get(0).(func(appcontext.AppContext, []func(*pop.Query), services.Pagination, services.QueryOrder) models.OfficeUsers); ok { + r0 = rf(appCtx, filterFuncs, pagination, ordering) } else { if ret.Get(0) != nil { r0 = ret.Get(0).(models.OfficeUsers) } } - if rf, ok := ret.Get(1).(func(appcontext.AppContext, []services.QueryFilter, services.QueryAssociations, services.Pagination, services.QueryOrder) error); ok { - r1 = rf(appCtx, filters, associations, pagination, ordering) + if rf, ok := ret.Get(1).(func(appcontext.AppContext, []func(*pop.Query), services.Pagination, services.QueryOrder) int); ok { + r1 = rf(appCtx, filterFuncs, pagination, ordering) } else { - r1 = ret.Error(1) + r1 = ret.Get(1).(int) } - return r0, r1 + if rf, ok := ret.Get(2).(func(appcontext.AppContext, []func(*pop.Query), services.Pagination, services.QueryOrder) error); ok { + r2 = rf(appCtx, filterFuncs, pagination, ordering) + } else { + r2 = ret.Error(2) + } + + return r0, r1, r2 } // NewRejectedOfficeUserListFetcher creates a new instance of RejectedOfficeUserListFetcher. It also registers a testing interface on the mock and a cleanup function to assert the mocks expectations. diff --git a/pkg/services/move/move_fetcher_test.go b/pkg/services/move/move_fetcher_test.go index dd173d568b5..6a6db7f28be 100644 --- a/pkg/services/move/move_fetcher_test.go +++ b/pkg/services/move/move_fetcher_test.go @@ -519,90 +519,6 @@ func (suite *MoveServiceSuite) TestMoveFetcherBulkAssignmentSC() { suite.Equal(1, len(moves)) suite.NotEqual(marinePPM.ID, moves[0].ID) }) - - suite.Run("Closeout returns non Navy/USCG/USMC ppms in needs closeout status", func() { - moveFetcher := NewMoveFetcherBulkAssignment() - transportationOffice := factory.BuildTransportationOffice(suite.DB(), nil, nil) - officeUser := factory.BuildOfficeUserWithRoles(suite.DB(), []factory.Customization{ - { - Model: transportationOffice, - LinkOnly: true, - Type: &factory.TransportationOffices.CloseoutOffice, - }, - }, []roles.RoleType{roles.RoleTypeServicesCounselor}) - - submittedAt := time.Now() - - // create non USMC/USCG/NAVY ppm in need closeout status - factory.BuildMoveWithPPMShipment(suite.DB(), []factory.Customization{ - { - Model: transportationOffice, - LinkOnly: true, - Type: &factory.TransportationOffices.CloseoutOffice, - }, - { - Model: models.PPMShipment{ - Status: models.PPMShipmentStatusNeedsCloseout, - SubmittedAt: &submittedAt, - }, - }, - { - Model: models.Move{ - Status: models.MoveStatusAPPROVED, - }, - }, - }, nil) - - // create non closeout needed ppm - factory.BuildMoveWithPPMShipment(suite.DB(), []factory.Customization{ - { - Model: transportationOffice, - LinkOnly: true, - Type: &factory.TransportationOffices.CloseoutOffice, - }, - { - Model: models.PPMShipment{ - Status: models.PPMShipmentStatusWaitingOnCustomer, - SubmittedAt: &submittedAt, - }, - }, - { - Model: models.Move{ - Status: models.MoveStatusAPPROVED, - }, - }, - }, nil) - - marine := models.AffiliationMARINES - marinePPM := factory.BuildPPMShipment(suite.DB(), []factory.Customization{ - { - Model: models.Move{ - Status: models.MoveStatusAPPROVED, - }, - }, - { - Model: models.MTOShipment{ - ShipmentType: models.MTOShipmentTypePPM, - }, - }, - { - Model: models.PPMShipment{ - Status: models.PPMShipmentStatusNeedsCloseout, - SubmittedAt: &submittedAt, - }, - }, - { - Model: models.ServiceMember{ - Affiliation: &marine, - }, - }, - }, nil) - - moves, err := moveFetcher.FetchMovesForBulkAssignmentCloseout(suite.AppContextForTest(), "KKFA", officeUser.TransportationOffice.ID) - suite.FatalNoError(err) - suite.Equal(1, len(moves)) - suite.NotEqual(marinePPM.ID, moves[0].ID) - }) } func (suite *MoveServiceSuite) TestMoveFetcherBulkAssignmentTOO() { diff --git a/pkg/services/rejected_office_users/rejected_office_user_fetcher.go b/pkg/services/rejected_office_users/rejected_office_user_fetcher.go index 5c6b85bd413..eb5da0aaad7 100644 --- a/pkg/services/rejected_office_users/rejected_office_user_fetcher.go +++ b/pkg/services/rejected_office_users/rejected_office_user_fetcher.go @@ -24,7 +24,7 @@ func (o *rejectedOfficeUserFetcher) FetchRejectedOfficeUser(appCtx appcontext.Ap return rejectedOfficeUser, err } -// NewAdminUserFetcher return an implementation of the AdminUserFetcher interface +// NewRejectedUserFetcher return an implementation of the AdminUserFetcher interface func NewRejectedOfficeUserFetcher(builder rejectedOfficeUserQueryBuilder) services.RejectedOfficeUserFetcher { return &rejectedOfficeUserFetcher{builder} } diff --git a/src/pages/Admin/RejectedOfficeUsers/RejectedOfficeUserShow.jsx b/src/pages/Admin/RejectedOfficeUsers/RejectedOfficeUserShow.jsx index c5493f53f5c..47185786299 100644 --- a/src/pages/Admin/RejectedOfficeUsers/RejectedOfficeUserShow.jsx +++ b/src/pages/Admin/RejectedOfficeUsers/RejectedOfficeUserShow.jsx @@ -18,7 +18,7 @@ const RejectedOfficeUserShowTitle = () => { const RejectedOfficeUserShowRoles = () => { const record = useRecordContext(); - if (!record?.roles) return

This user has not rejected any roles.

; + if (!record?.roles) return

This user has not requested any roles.

; return ( From 7bdf0209b21a1e5df9b4e6316aee2f85d23172a3 Mon Sep 17 00:00:00 2001 From: Konstance Haffaney Date: Thu, 20 Feb 2025 16:14:45 +0000 Subject: [PATCH 33/37] left requested request lol --- pkg/handlers/adminapi/rejected_office_users_test.go | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/pkg/handlers/adminapi/rejected_office_users_test.go b/pkg/handlers/adminapi/rejected_office_users_test.go index 6f91d6877e0..c5fc979f57a 100644 --- a/pkg/handlers/adminapi/rejected_office_users_test.go +++ b/pkg/handlers/adminapi/rejected_office_users_test.go @@ -59,7 +59,7 @@ func (suite *HandlerSuite) TestGetRejectedOfficeUserHandler() { suite.Run("integration test ok response", func() { rejectedOfficeUser := factory.BuildOfficeUserWithRoles(suite.DB(), factory.GetTraitRejectedOfficeUser(), []roles.RoleType{roles.RoleTypeQae}) params := rejectedofficeuserop.GetRejectedOfficeUserParams{ - HTTPRequest: suite.setupAuthenticatedRequest("GET", fmt.Sprintf("/requested_office_users/%s", rejectedOfficeUser.ID)), + HTTPRequest: suite.setupAuthenticatedRequest("GET", fmt.Sprintf("/rejected_office_users/%s", rejectedOfficeUser.ID)), OfficeUserID: strfmt.UUID(rejectedOfficeUser.ID.String()), } @@ -97,7 +97,7 @@ func (suite *HandlerSuite) TestGetRejectedOfficeUserHandler() { suite.Run("successful response", func() { rejectedOfficeUser := factory.BuildOfficeUserWithRoles(suite.DB(), factory.GetTraitRejectedOfficeUser(), []roles.RoleType{roles.RoleTypeQae}) params := rejectedofficeuserop.GetRejectedOfficeUserParams{ - HTTPRequest: suite.setupAuthenticatedRequest("GET", fmt.Sprintf("/requested_office_users/%s", rejectedOfficeUser.ID)), + HTTPRequest: suite.setupAuthenticatedRequest("GET", fmt.Sprintf("/rejected_office_users/%s", rejectedOfficeUser.ID)), OfficeUserID: strfmt.UUID(rejectedOfficeUser.ID.String()), } @@ -140,7 +140,7 @@ func (suite *HandlerSuite) TestGetRejectedOfficeUserHandler() { suite.Run("unsuccessful response when fetch fails", func() { rejectedOfficeUser := factory.BuildOfficeUserWithRoles(suite.DB(), factory.GetTraitRejectedOfficeUser(), []roles.RoleType{roles.RoleTypeQae}) params := rejectedofficeuserop.GetRejectedOfficeUserParams{ - HTTPRequest: suite.setupAuthenticatedRequest("GET", fmt.Sprintf("/requested_office_users/%s", rejectedOfficeUser.ID)), + HTTPRequest: suite.setupAuthenticatedRequest("GET", fmt.Sprintf("/rejected_office_users/%s", rejectedOfficeUser.ID)), OfficeUserID: strfmt.UUID(rejectedOfficeUser.ID.String()), } From 043409fecb74ca1c80b81d0cd3b55a550dbbed7c Mon Sep 17 00:00:00 2001 From: Konstance Haffaney Date: Thu, 20 Feb 2025 16:19:47 +0000 Subject: [PATCH 34/37] remove admin --- .../rejected_office_users/rejected_office_user_fetcher.go | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/pkg/services/rejected_office_users/rejected_office_user_fetcher.go b/pkg/services/rejected_office_users/rejected_office_user_fetcher.go index eb5da0aaad7..723cb752ff3 100644 --- a/pkg/services/rejected_office_users/rejected_office_user_fetcher.go +++ b/pkg/services/rejected_office_users/rejected_office_user_fetcher.go @@ -24,7 +24,7 @@ func (o *rejectedOfficeUserFetcher) FetchRejectedOfficeUser(appCtx appcontext.Ap return rejectedOfficeUser, err } -// NewRejectedUserFetcher return an implementation of the AdminUserFetcher interface +// NewRejectedUserFetcher return an implementation of the RejectedUserFetcher interface func NewRejectedOfficeUserFetcher(builder rejectedOfficeUserQueryBuilder) services.RejectedOfficeUserFetcher { return &rejectedOfficeUserFetcher{builder} } From dc4f1c4bbec4a2eaa0d9a9d10ef77b08cf7d7847 Mon Sep 17 00:00:00 2001 From: Konstance Haffaney Date: Thu, 20 Feb 2025 17:16:46 +0000 Subject: [PATCH 35/37] adding pr comment changes --- migrations/app/migrations_manifest.txt | 2 +- .../adminapi/rejected_office_users_test.go | 137 ++++++++++++++++++ pkg/services/move/move_fetcher_test.go | 84 ----------- .../rejected_office_user_fetcher.go | 2 +- .../RejectedOfficeUserShow.jsx | 2 +- 5 files changed, 140 insertions(+), 87 deletions(-) diff --git a/migrations/app/migrations_manifest.txt b/migrations/app/migrations_manifest.txt index 1fdc2a617d9..8634c62fb26 100644 --- a/migrations/app/migrations_manifest.txt +++ b/migrations/app/migrations_manifest.txt @@ -1090,6 +1090,6 @@ 20250120214107_add_international_ntsr_service_items.up.sql 20250121153007_update_pricing_proc_to_handle_international_shuttle.up.sql 20250121184450_upd_duty_loc_B-22242.up.sql +20250131205338_add_rejected_col_to_admin_users.up.sql 20250204162411_updating_create_accessorial_service_item_proc_for_crating.up.sql 20250206173204_add_hawaii_data.up.sql -20250131205338_add_rejected_col_to_admin_users.up.sql diff --git a/pkg/handlers/adminapi/rejected_office_users_test.go b/pkg/handlers/adminapi/rejected_office_users_test.go index e55397e1c9a..b212f7f985a 100644 --- a/pkg/handlers/adminapi/rejected_office_users_test.go +++ b/pkg/handlers/adminapi/rejected_office_users_test.go @@ -1,12 +1,20 @@ package adminapi import ( + "fmt" + "net/http" "slices" + "time" + "github.com/go-openapi/strfmt" + "github.com/gofrs/uuid" + "github.com/stretchr/testify/mock" "github.com/transcom/mymove/pkg/factory" rejectedofficeuserop "github.com/transcom/mymove/pkg/gen/adminapi/adminoperations/rejected_office_users" + "github.com/transcom/mymove/pkg/handlers" "github.com/transcom/mymove/pkg/models" "github.com/transcom/mymove/pkg/models/roles" + "github.com/transcom/mymove/pkg/services/mocks" "github.com/transcom/mymove/pkg/services/pagination" "github.com/transcom/mymove/pkg/services/query" rejectedofficeusers "github.com/transcom/mymove/pkg/services/rejected_office_users" @@ -46,3 +54,132 @@ func (suite *HandlerSuite) TestIndexRejectedOfficeUsersHandler() { } }) } + +func (suite *HandlerSuite) TestGetRejectedOfficeUserHandler() { + suite.Run("integration test ok response", func() { + rejectedOfficeUser := factory.BuildOfficeUserWithRoles(suite.DB(), factory.GetTraitRejectedOfficeUser(), []roles.RoleType{roles.RoleTypeQae}) + params := rejectedofficeuserop.GetRejectedOfficeUserParams{ + HTTPRequest: suite.setupAuthenticatedRequest("GET", fmt.Sprintf("/rejected_office_users/%s", rejectedOfficeUser.ID)), + OfficeUserID: strfmt.UUID(rejectedOfficeUser.ID.String()), + } + + mockRoleAssociator := &mocks.RoleAssociater{} + mockRoles := roles.Roles{ + roles.Role{ + ID: uuid.Must(uuid.NewV4()), + RoleType: roles.RoleTypeTOO, + RoleName: "Task Ordering Officer", + CreatedAt: time.Now(), + UpdatedAt: time.Now(), + }, + } + mockRoleAssociator.On( + "FetchRolesForUser", + mock.AnythingOfType("*appcontext.appContext"), + mock.Anything, + ).Return(mockRoles, nil) + + queryBuilder := query.NewQueryBuilder() + handler := GetRejectedOfficeUserHandler{ + suite.HandlerConfig(), + rejectedofficeusers.NewRejectedOfficeUserFetcher(queryBuilder), + mockRoleAssociator, + query.NewQueryFilter, + } + + response := handler.Handle(params) + + suite.IsType(&rejectedofficeuserop.GetRejectedOfficeUserOK{}, response) + okResponse := response.(*rejectedofficeuserop.GetRejectedOfficeUserOK) + suite.Equal(rejectedOfficeUser.ID.String(), okResponse.Payload.ID.String()) + }) + + suite.Run("successful response", func() { + rejectedOfficeUser := factory.BuildOfficeUserWithRoles(suite.DB(), factory.GetTraitRejectedOfficeUser(), []roles.RoleType{roles.RoleTypeQae}) + params := rejectedofficeuserop.GetRejectedOfficeUserParams{ + HTTPRequest: suite.setupAuthenticatedRequest("GET", fmt.Sprintf("/rejected_office_users/%s", rejectedOfficeUser.ID)), + OfficeUserID: strfmt.UUID(rejectedOfficeUser.ID.String()), + } + + rejectedOfficeUserFetcher := &mocks.RejectedOfficeUserFetcher{} + rejectedOfficeUserFetcher.On("FetchRejectedOfficeUser", + mock.AnythingOfType("*appcontext.appContext"), + mock.Anything, + ).Return(rejectedOfficeUser, nil).Once() + + mockRoleAssociator := &mocks.RoleAssociater{} + mockRoles := roles.Roles{ + roles.Role{ + ID: uuid.Must(uuid.NewV4()), + RoleType: roles.RoleTypeTOO, + RoleName: "Task Ordering Officer", + CreatedAt: time.Now(), + UpdatedAt: time.Now(), + }, + } + mockRoleAssociator.On( + "FetchRolesForUser", + mock.AnythingOfType("*appcontext.appContext"), + mock.Anything, + ).Return(mockRoles, nil) + + handler := GetRejectedOfficeUserHandler{ + suite.HandlerConfig(), + rejectedOfficeUserFetcher, + mockRoleAssociator, + newMockQueryFilterBuilder(&mocks.QueryFilter{}), + } + + response := handler.Handle(params) + + suite.IsType(&rejectedofficeuserop.GetRejectedOfficeUserOK{}, response) + okResponse := response.(*rejectedofficeuserop.GetRejectedOfficeUserOK) + suite.Equal(rejectedOfficeUser.ID.String(), okResponse.Payload.ID.String()) + }) + + suite.Run("unsuccessful response when fetch fails", func() { + rejectedOfficeUser := factory.BuildOfficeUserWithRoles(suite.DB(), factory.GetTraitRejectedOfficeUser(), []roles.RoleType{roles.RoleTypeQae}) + params := rejectedofficeuserop.GetRejectedOfficeUserParams{ + HTTPRequest: suite.setupAuthenticatedRequest("GET", fmt.Sprintf("/rejected_office_users/%s", rejectedOfficeUser.ID)), + OfficeUserID: strfmt.UUID(rejectedOfficeUser.ID.String()), + } + + expectedError := models.ErrFetchNotFound + rejectedOfficeUserFetcher := &mocks.RejectedOfficeUserFetcher{} + rejectedOfficeUserFetcher.On("FetchRejectedOfficeUser", + mock.AnythingOfType("*appcontext.appContext"), + mock.Anything, + ).Return(models.OfficeUser{}, expectedError).Once() + + mockRoleAssociator := &mocks.RoleAssociater{} + mockRoles := roles.Roles{ + roles.Role{ + ID: uuid.Must(uuid.NewV4()), + RoleType: roles.RoleTypeTOO, + RoleName: "Task Ordering Officer", + CreatedAt: time.Now(), + UpdatedAt: time.Now(), + }, + } + mockRoleAssociator.On( + "FetchRolesForUser", + mock.AnythingOfType("*appcontext.appContext"), + mock.Anything, + ).Return(mockRoles, nil) + + handler := GetRejectedOfficeUserHandler{ + suite.HandlerConfig(), + rejectedOfficeUserFetcher, + mockRoleAssociator, + newMockQueryFilterBuilder(&mocks.QueryFilter{}), + } + + response := handler.Handle(params) + + expectedResponse := &handlers.ErrResponse{ + Code: http.StatusNotFound, + Err: expectedError, + } + suite.Equal(expectedResponse, response) + }) +} diff --git a/pkg/services/move/move_fetcher_test.go b/pkg/services/move/move_fetcher_test.go index b37cdb6c277..62b6551add5 100644 --- a/pkg/services/move/move_fetcher_test.go +++ b/pkg/services/move/move_fetcher_test.go @@ -519,90 +519,6 @@ func (suite *MoveServiceSuite) TestMoveFetcherBulkAssignmentSC() { suite.Equal(1, len(moves)) suite.NotEqual(marinePPM.ID, moves[0].ID) }) - - suite.Run("Closeout returns non Navy/USCG/USMC ppms in needs closeout status", func() { - moveFetcher := NewMoveFetcherBulkAssignment() - transportationOffice := factory.BuildTransportationOffice(suite.DB(), nil, nil) - officeUser := factory.BuildOfficeUserWithRoles(suite.DB(), []factory.Customization{ - { - Model: transportationOffice, - LinkOnly: true, - Type: &factory.TransportationOffices.CloseoutOffice, - }, - }, []roles.RoleType{roles.RoleTypeServicesCounselor}) - - submittedAt := time.Now() - - // create non USMC/USCG/NAVY ppm in need closeout status - factory.BuildMoveWithPPMShipment(suite.DB(), []factory.Customization{ - { - Model: transportationOffice, - LinkOnly: true, - Type: &factory.TransportationOffices.CloseoutOffice, - }, - { - Model: models.PPMShipment{ - Status: models.PPMShipmentStatusNeedsCloseout, - SubmittedAt: &submittedAt, - }, - }, - { - Model: models.Move{ - Status: models.MoveStatusAPPROVED, - }, - }, - }, nil) - - // create non closeout needed ppm - factory.BuildMoveWithPPMShipment(suite.DB(), []factory.Customization{ - { - Model: transportationOffice, - LinkOnly: true, - Type: &factory.TransportationOffices.CloseoutOffice, - }, - { - Model: models.PPMShipment{ - Status: models.PPMShipmentStatusWaitingOnCustomer, - SubmittedAt: &submittedAt, - }, - }, - { - Model: models.Move{ - Status: models.MoveStatusAPPROVED, - }, - }, - }, nil) - - marine := models.AffiliationMARINES - marinePPM := factory.BuildPPMShipment(suite.DB(), []factory.Customization{ - { - Model: models.Move{ - Status: models.MoveStatusAPPROVED, - }, - }, - { - Model: models.MTOShipment{ - ShipmentType: models.MTOShipmentTypePPM, - }, - }, - { - Model: models.PPMShipment{ - Status: models.PPMShipmentStatusNeedsCloseout, - SubmittedAt: &submittedAt, - }, - }, - { - Model: models.ServiceMember{ - Affiliation: &marine, - }, - }, - }, nil) - - moves, err := moveFetcher.FetchMovesForBulkAssignmentCloseout(suite.AppContextForTest(), "KKFA", officeUser.TransportationOffice.ID) - suite.FatalNoError(err) - suite.Equal(1, len(moves)) - suite.NotEqual(marinePPM.ID, moves[0].ID) - }) } func (suite *MoveServiceSuite) TestMoveFetcherBulkAssignmentTOO() { diff --git a/pkg/services/rejected_office_users/rejected_office_user_fetcher.go b/pkg/services/rejected_office_users/rejected_office_user_fetcher.go index 5c6b85bd413..723cb752ff3 100644 --- a/pkg/services/rejected_office_users/rejected_office_user_fetcher.go +++ b/pkg/services/rejected_office_users/rejected_office_user_fetcher.go @@ -24,7 +24,7 @@ func (o *rejectedOfficeUserFetcher) FetchRejectedOfficeUser(appCtx appcontext.Ap return rejectedOfficeUser, err } -// NewAdminUserFetcher return an implementation of the AdminUserFetcher interface +// NewRejectedUserFetcher return an implementation of the RejectedUserFetcher interface func NewRejectedOfficeUserFetcher(builder rejectedOfficeUserQueryBuilder) services.RejectedOfficeUserFetcher { return &rejectedOfficeUserFetcher{builder} } diff --git a/src/pages/Admin/RejectedOfficeUsers/RejectedOfficeUserShow.jsx b/src/pages/Admin/RejectedOfficeUsers/RejectedOfficeUserShow.jsx index c5493f53f5c..47185786299 100644 --- a/src/pages/Admin/RejectedOfficeUsers/RejectedOfficeUserShow.jsx +++ b/src/pages/Admin/RejectedOfficeUsers/RejectedOfficeUserShow.jsx @@ -18,7 +18,7 @@ const RejectedOfficeUserShowTitle = () => { const RejectedOfficeUserShowRoles = () => { const record = useRecordContext(); - if (!record?.roles) return

This user has not rejected any roles.

; + if (!record?.roles) return

This user has not requested any roles.

; return ( From 7eb9661ba9952a78044f9327e431c2f058e94696 Mon Sep 17 00:00:00 2001 From: Konstance Haffaney Date: Fri, 21 Feb 2025 20:12:36 +0000 Subject: [PATCH 36/37] remove old migration and replace with new --- .../20250221195633_tbl_alter_office_users_B-21966.up.sql} | 5 +++-- migrations/app/ddl_tables_manifest.txt | 1 + migrations/app/migrations_manifest.txt | 1 - 3 files changed, 4 insertions(+), 3 deletions(-) rename migrations/app/{schema/20250131205338_add_rejected_col_to_admin_users.up.sql => ddl_migrations/ddl_tables/20250221195633_tbl_alter_office_users_B-21966.up.sql} (62%) diff --git a/migrations/app/schema/20250131205338_add_rejected_col_to_admin_users.up.sql b/migrations/app/ddl_migrations/ddl_tables/20250221195633_tbl_alter_office_users_B-21966.up.sql similarity index 62% rename from migrations/app/schema/20250131205338_add_rejected_col_to_admin_users.up.sql rename to migrations/app/ddl_migrations/ddl_tables/20250221195633_tbl_alter_office_users_B-21966.up.sql index a68cfad4a1e..e771c560d83 100644 --- a/migrations/app/schema/20250131205338_add_rejected_col_to_admin_users.up.sql +++ b/migrations/app/ddl_migrations/ddl_tables/20250221195633_tbl_alter_office_users_B-21966.up.sql @@ -1,5 +1,6 @@ --- Adds new column to office_users table +--B-21966 Konstance Haffaney Add column to office_users + ALTER TABLE public.office_users ADD COLUMN IF NOT EXISTS rejected_on timestamptz; -COMMENT on COLUMN office_users.rejected_on IS 'Date requested office users were rejected.'; +COMMENT on COLUMN office_users.rejected_on IS 'Date requested office users were rejected.'; \ No newline at end of file diff --git a/migrations/app/ddl_tables_manifest.txt b/migrations/app/ddl_tables_manifest.txt index 8fd6841c337..b2affc1ea9f 100644 --- a/migrations/app/ddl_tables_manifest.txt +++ b/migrations/app/ddl_tables_manifest.txt @@ -1,3 +1,4 @@ # This is the tables migrations manifest. # If a migration is not recorded here, then it will error. # Naming convention: tbl_some_table.up.sql running will create this file. +20250221195633_tbl_alter_office_users_B-21966.up.sql diff --git a/migrations/app/migrations_manifest.txt b/migrations/app/migrations_manifest.txt index 18c7d96d8aa..85d12df5c23 100644 --- a/migrations/app/migrations_manifest.txt +++ b/migrations/app/migrations_manifest.txt @@ -1091,7 +1091,6 @@ 20250121153007_update_pricing_proc_to_handle_international_shuttle.up.sql 20250121184450_upd_duty_loc_B-22242.up.sql 20250123173216_add_destination_queue_db_func_and_gbloc_view.up.sql -20250131205338_add_rejected_col_to_admin_users.up.sql 20250204162411_updating_create_accessorial_service_item_proc_for_crating.up.sql 20250206173204_add_hawaii_data.up.sql 20250210175754_B22451_update_dest_queue_to_consider_sit_extensions.up.sql From 9ba68360cd8e3bd489a72a2b44ed33da59e28051 Mon Sep 17 00:00:00 2001 From: Konstance Haffaney Date: Fri, 21 Feb 2025 20:28:43 +0000 Subject: [PATCH 37/37] remove migration file --- migrations/app/migrations_manifest.txt | 1 - 1 file changed, 1 deletion(-) diff --git a/migrations/app/migrations_manifest.txt b/migrations/app/migrations_manifest.txt index c6534f52e0d..5f2cc6257eb 100644 --- a/migrations/app/migrations_manifest.txt +++ b/migrations/app/migrations_manifest.txt @@ -1095,7 +1095,6 @@ 20250123173216_add_destination_queue_db_func_and_gbloc_view.up.sql 20250123210535_update_re_intl_transit_times_for_ak_hhg.up.sql 20250127143137_insert_nsra_re_intl_transit_times.up.sql -20250131205338_add_rejected_col_to_admin_users.up.sql 20250204162411_updating_create_accessorial_service_item_proc_for_crating.up.sql 20250206173204_add_hawaii_data.up.sql 20250207153450_add_fetch_documents_func.up.sql