Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

B-21941 TOO Queue Filtering For Destination Only Requests #14465

Merged
merged 32 commits into from
Jan 9, 2025
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
32 commits
Select commit Hold shift + click to select a range
13a59c0
Merge remote-tracking branch 'origin/MAIN-B-21940' into B-21941-MAIN-v2
traskowskycaci Dec 23, 2024
35fb8db
easier to read changes
traskowskycaci Dec 23, 2024
3236522
removing moves.status query
traskowskycaci Dec 23, 2024
60bc2f6
removing moves.status query
traskowskycaci Dec 23, 2024
f77045c
Merge branch 'B-21941-MAIN-v2' into B-21941-INT-v2
traskowskycaci Dec 23, 2024
c73ffc8
FINALLY
traskowskycaci Dec 24, 2024
c28be18
FINALLY
traskowskycaci Dec 24, 2024
b8834ff
Merge branch 'B-21941-MAIN-v2' into B-21941-INT-v2
traskowskycaci Dec 24, 2024
5cc5218
test updates
traskowskycaci Dec 24, 2024
8cf07c7
Merge branch 'B-21941-MAIN-v2' into B-21941-INT-v2
traskowskycaci Dec 24, 2024
765c9ba
fix queue handler test
traskowskycaci Dec 24, 2024
f28ec89
Merge branch 'B-21941-MAIN-v2' into B-21941-INT-v2
traskowskycaci Dec 24, 2024
1283fa5
Merge branch 'integrationTesting' into B-21941-INT-v2
danieljordan-caci Dec 26, 2024
fc7bf52
remove comments
traskowskycaci Dec 26, 2024
accea2d
Merge branch 'B-21941-MAIN-v2' into B-21941-INT-v2
traskowskycaci Dec 26, 2024
5556ec6
nicer formatting for AND
traskowskycaci Dec 26, 2024
2a12157
add additional origin service item reservice codes
traskowskycaci Dec 26, 2024
4b0a50f
Merge branch 'B-21941-MAIN-v2' into B-21941-INT-v2
traskowskycaci Dec 27, 2024
374231d
Merge branch 'integrationTesting' into B-21941-INT-v2
traskowskycaci Jan 3, 2025
375c49f
update test to use search
traskowskycaci Jan 3, 2025
1ec6cb5
include DOPSIT
traskowskycaci Jan 3, 2025
5c356c9
refactor into base query plus additional loc query if needed
traskowskycaci Jan 3, 2025
7cf57d6
whoops get back in there DOPSIT
traskowskycaci Jan 3, 2025
7ebe52d
remove nonexistest reservice code
traskowskycaci Jan 3, 2025
6b3df28
Merge branch 'B-21941-MAIN-v2' into B-21941-INT-v2
traskowskycaci Jan 3, 2025
6e35c08
Merge branch 'integrationTesting' into B-21941-INT-v2
traskowskycaci Jan 3, 2025
0142c88
update move status for test
traskowskycaci Jan 6, 2025
576b903
Merge branch 'B-21941-MAIN-v2' into B-21941-INT-v2
traskowskycaci Jan 6, 2025
21e3eb0
add comment and update function name
traskowskycaci Jan 7, 2025
60e0867
Merge branch 'B-21941-MAIN-v2' into B-21941-INT-v2
traskowskycaci Jan 7, 2025
0b061d0
Merge branch 'integrationTesting' into B-21941-INT-v2
danieljordan-caci Jan 7, 2025
79670f6
Merge branch 'integrationTesting' into B-21941-INT-v2
traskowskycaci Jan 8, 2025
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
5 changes: 5 additions & 0 deletions pkg/handlers/ghcapi/queues_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -613,6 +613,11 @@ func (suite *HandlerSuite) TestGetMoveQueuesHandlerFilters() {
Status: models.MTOServiceItemStatusSubmitted,
},
},
{
Model: models.ReService{
Code: models.ReServiceCodeDOFSIT,
},
},
}, nil)

// Service Counseling Completed Move
Expand Down
36 changes: 35 additions & 1 deletion pkg/services/order/order_fetcher.go
Original file line number Diff line number Diff line change
Expand Up @@ -121,8 +121,9 @@ func (f orderFetcher) ListOrders(appCtx appcontext.AppContext, officeUserID uuid
tooAssignedUserQuery := tooAssignedUserFilter(params.TOOAssignedUser)
sortOrderQuery := sortOrder(params.Sort, params.Order, ppmCloseoutGblocs)
counselingQuery := counselingOfficeFilter(params.CounselingOffice)
tooDestinationRequestsQuery := tooQueueOriginRequestsFilter(role, params.Locator)
// Adding to an array so we can iterate over them and apply the filters after the query structure is set below
options := [20]QueryOption{branchQuery, locatorQuery, dodIDQuery, emplidQuery, customerNameQuery, originDutyLocationQuery, destinationDutyLocationQuery, moveStatusQuery, gblocQuery, submittedAtQuery, appearedInTOOAtQuery, requestedMoveDateQuery, ppmTypeQuery, closeoutInitiatedQuery, closeoutLocationQuery, ppmStatusQuery, sortOrderQuery, scAssignedUserQuery, tooAssignedUserQuery, counselingQuery}
options := [21]QueryOption{branchQuery, locatorQuery, dodIDQuery, emplidQuery, customerNameQuery, originDutyLocationQuery, destinationDutyLocationQuery, moveStatusQuery, gblocQuery, submittedAtQuery, appearedInTOOAtQuery, requestedMoveDateQuery, ppmTypeQuery, closeoutInitiatedQuery, closeoutLocationQuery, ppmStatusQuery, sortOrderQuery, scAssignedUserQuery, tooAssignedUserQuery, counselingQuery, tooDestinationRequestsQuery}

var query *pop.Query
if ppmCloseoutGblocs {
Expand Down Expand Up @@ -190,6 +191,10 @@ func (f orderFetcher) ListOrders(appCtx appcontext.AppContext, officeUserID uuid
}
if role == roles.RoleTypeTOO {
query.LeftJoin("office_users as assigned_user", "moves.too_assigned_id = assigned_user.id")
query.LeftJoin("mto_service_items", "mto_shipments.id = mto_service_items.mto_shipment_id").
LeftJoin("re_services", "mto_service_items.re_service_id = re_services.id").
LeftJoin("shipment_address_updates", "shipment_address_updates.shipment_id = mto_shipments.id AND shipment_address_updates.new_address_id != mto_shipments.destination_address_id").
LeftJoin("sit_extensions", "mto_shipments.id = sit_extensions.mto_shipment_id")
}

if params.NeedsPPMCloseout != nil {
Expand Down Expand Up @@ -989,3 +994,32 @@ func sortOrder(sort *string, order *string, ppmCloseoutGblocs bool) QueryOption
}
}
}

// We want to filter out any moves that have ONLY destination type requests to them, such as destination SIT, shuttle, out of the
// task order queue. If the moves have origin SIT, excess weight risks, or sit extensions, they should still appear in the task order
// queue, which is what this query looks for
func tooQueueOriginRequestsFilter(role roles.RoleType, locator *string) QueryOption {
return func(query *pop.Query) {
if role == roles.RoleTypeTOO {
baseQuery := `
(
(mto_service_items.status IS NULL OR (mto_service_items.status = 'SUBMITTED' AND re_services.code IN ('DOFSIT', 'DOASIT', 'DOPSIT', 'DOSHUT', 'DOSFSC', 'IOFSIT', 'IOASIT', 'IODSIT', 'IOSHUT', 'IOPSIT', 'ICRT', 'IOSFSC')))
)
OR
(
((moves.excess_weight_qualified_at IS NOT NULL AND moves.excess_weight_acknowledged_at IS NULL) AND moves.status = 'APPROVALS REQUESTED')
)
OR
(
((sit_extensions.mto_shipment_id IS NOT NULL) AND sit_extensions.status = 'PENDING')
)
`
if locator != nil {
query.Where(`
(moves.locator = ?) AND ( `+baseQuery+`)`, strings.ToUpper(*locator))
} else {
query.Where(baseQuery)
}
}
}
}
146 changes: 146 additions & 0 deletions pkg/services/order/order_fetcher_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -580,6 +580,152 @@ func (suite *OrderServiceSuite) TestListOrders() {
suite.Equal(1, len(moves))
suite.Equal(createdPPM.Shipment.MoveTaskOrder.Locator, moves[0].Locator)
})

suite.Run("task order queue does not return move with ONLY a destination address update request", func() {
officeUser := factory.BuildOfficeUserWithRoles(suite.DB(), nil, []roles.RoleType{roles.RoleTypeTOO})
session := auth.Session{
ApplicationName: auth.OfficeApp,
Roles: officeUser.User.Roles,
OfficeUserID: officeUser.ID,
IDToken: "fake_token",
AccessToken: "fakeAccessToken",
}
// build a move with a destination address request, should NOT appear in Task Order Queue
move := factory.BuildMove(suite.DB(), []factory.Customization{
{
Model: models.Move{
Status: models.MoveStatusAPPROVALSREQUESTED,
Show: models.BoolPointer(true),
},
}}, nil)

testUUID := uuid.UUID{}
shipment := factory.BuildMTOShipment(suite.DB(), []factory.Customization{
{
Model: move,
LinkOnly: true,
},
{
Model: models.MTOShipment{
DestinationAddressID: &testUUID,
},
},
}, nil)

suite.NotNil(shipment)

shipmentAddressUpdate := factory.BuildShipmentAddressUpdate(suite.DB(), []factory.Customization{
{
Model: shipment,
LinkOnly: true,
},
{
Model: move,
LinkOnly: true,
},
{
Model: models.ShipmentAddressUpdate{
NewAddressID: testUUID,
},
},
}, []factory.Trait{factory.GetTraitShipmentAddressUpdateRequested})
suite.NotNil(shipmentAddressUpdate)

// build a second move
move2 := factory.BuildMove(suite.DB(), []factory.Customization{
{
Model: models.Move{
Status: models.MoveStatusAPPROVALSREQUESTED,
Show: models.BoolPointer(true),
},
}}, nil)
suite.NotNil(move2)

moves, moveCount, err := orderFetcher.ListOrders(suite.AppContextWithSessionForTest(&session), officeUser.ID, roles.RoleTypeTOO, &services.ListOrderParams{})

suite.FatalNoError(err)
// even though 2 moves were created, only one will be returned from the call to List Orders since we filter out
// the one with only a shipment address update to be routed to the destination requests queue
suite.Equal(1, moveCount)
suite.Equal(1, len(moves))
})

suite.Run("task order queue does not return move with ONLY requested destination SIT service items", func() {
officeUser := factory.BuildOfficeUserWithRoles(suite.DB(), nil, []roles.RoleType{roles.RoleTypeTOO})
session := auth.Session{
ApplicationName: auth.OfficeApp,
Roles: officeUser.User.Roles,
OfficeUserID: officeUser.ID,
IDToken: "fake_token",
AccessToken: "fakeAccessToken",
}

// build a move with a only origin service items
move := factory.BuildMove(suite.DB(), []factory.Customization{
{
Model: models.Move{
Status: models.MoveStatusAPPROVALSREQUESTED,
Show: models.BoolPointer(true),
},
}}, nil)

shipment := factory.BuildMTOShipment(suite.DB(), []factory.Customization{
{
Model: move,
LinkOnly: true,
},
}, nil)
suite.NotNil(shipment)
originSITServiceItem := factory.BuildMTOServiceItem(suite.DB(), []factory.Customization{
{
Model: shipment,
LinkOnly: true,
},
{
Model: models.ReService{
Code: models.ReServiceCodeDOFSIT,
},
},
}, nil)
suite.NotNil(originSITServiceItem)

// build a move with a both origin and destination service items
move2 := factory.BuildMove(suite.DB(), []factory.Customization{
{
Model: models.Move{
Status: models.MoveStatusAPPROVALSREQUESTED,
Show: models.BoolPointer(true),
},
}}, nil)
shipment2 := factory.BuildMTOShipment(suite.DB(), []factory.Customization{
{
Model: move2,
LinkOnly: true,
},
}, nil)

destinationSITServiceItem := factory.BuildMTOServiceItem(suite.DB(), []factory.Customization{
{
Model: shipment2,
LinkOnly: true,
},
{
Model: models.ReService{
Code: models.ReServiceCodeDDFSIT,
},
},
}, nil)

moves, moveCount, err := orderFetcher.ListOrders(suite.AppContextWithSessionForTest(&session), officeUser.ID, roles.RoleTypeTOO, &services.ListOrderParams{})

suite.Equal(models.MTOServiceItemStatusSubmitted, destinationSITServiceItem.Status)

suite.FatalNoError(err)
// even though 2 moves were created, only one will be returned from the call to List Orders since we filter out
// the one with only destination service items
suite.Equal(1, moveCount)
suite.Equal(1, len(moves))
})
}

func (suite *OrderServiceSuite) TestListDestinationRequestsOrders() {
Expand Down
15 changes: 4 additions & 11 deletions playwright/tests/office/txo/tooFlows.spec.js
Original file line number Diff line number Diff line change
Expand Up @@ -807,17 +807,10 @@ test.describe('TOO user', () => {
await page.getByRole('button', { name: 'Select task_ordering_officer' }).click();
});
test('weight-based multiplier prioritizes billed weight', async ({ page }) => {
await page.getByRole('row', { name: 'Select...' }).getByTestId('locator').getByTestId('TextBoxFilter').click();
await page
.getByRole('row', { name: 'Select...' })
.getByTestId('locator')
.getByTestId('TextBoxFilter')
.fill(moveLoc);
await page
.getByRole('row', { name: 'Select...' })
.getByTestId('locator')
.getByTestId('TextBoxFilter')
.press('Enter');
await page.getByRole('link', { name: 'Search' }).click();
await page.getByTestId('searchText').click();
await page.getByTestId('searchText').fill(moveLoc);
await page.getByTestId('searchText').press('Enter');
await page.getByTestId('locator-0').click();
await page.getByRole('link', { name: 'Payment requests' }).click();
await page.getByRole('button', { name: 'Review shipment weights' }).click();
Expand Down
Loading