Skip to content

Commit

Permalink
Merge pull request #14214 from transcom/B-21680-fix-timeout-counselin…
Browse files Browse the repository at this point in the history
…g-office

21680 counseling office timeout changes
  • Loading branch information
pambecker authored Dec 6, 2024
2 parents f58c4a3 + bcc64e5 commit 652c646
Show file tree
Hide file tree
Showing 9 changed files with 129 additions and 91 deletions.
1 change: 1 addition & 0 deletions migrations/app/migrations_manifest.txt
Original file line number Diff line number Diff line change
Expand Up @@ -1032,6 +1032,7 @@
20241109002854_add_gsr_table_to_move_history.up.sql
20241111203514_add_external_crate_and_remove_icrtsa.up.sql
20241111223224_change_international_sit_services_to_accessorials.up.sql
20241127133504_add_indexes_speed_up_counseling_offices.up.sql
20241202163059_create_test_sequence_dev_env.up.sql
20241203024453_add_ppm_max_incentive_column.up.sql
20241204210208_retroactive_update_of_ppm_max_and_estimated_incentives_prd.up.sql
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
--adding indexes to help speed up counseling_offices dropdown
CREATE INDEX IF NOT EXISTS idx_addresses_postal_code ON addresses(postal_code);
CREATE INDEX IF NOT EXISTS idx_addresses_us_post_region_cities_id ON addresses(us_post_region_cities_id);
CREATE INDEX IF NOT EXISTS idx_addresses_country_id ON addresses(country_id);
CREATE INDEX IF NOT EXISTS idx_duty_locations_provides_services_counseling ON duty_locations(provides_services_counseling);
CREATE INDEX IF NOT EXISTS idx_re_us_post_regions_uspr_zip_id ON re_us_post_regions(uspr_zip_id);
CREATE INDEX IF NOT EXISTS idx_zip3_distances_from_zip3_to_zip3 ON zip3_distances(from_zip3, to_zip3);
CREATE INDEX IF NOT EXISTS idx_zip3_distances_to_zip3_from_zip3 ON zip3_distances(to_zip3, from_zip3);
CREATE INDEX IF NOT EXISTS idx_re_oconus_rate_areas_us_post_region_cities_id ON re_oconus_rate_areas(us_post_region_cities_id);
CREATE INDEX IF NOT EXISTS idx_gbloc_aors_oconus_rate_area_id ON gbloc_aors(oconus_rate_area_id);
CREATE INDEX IF NOT EXISTS idx_gbloc_aors_jppso_regions_id ON gbloc_aors(jppso_regions_id);
CREATE INDEX IF NOT EXISTS idx_transportation_offices_provides_ppm_closeout ON transportation_offices(provides_ppm_closeout);
44 changes: 22 additions & 22 deletions pkg/services/transportation_office/transportation_office_fetcher.go
Original file line number Diff line number Diff line change
Expand Up @@ -203,28 +203,28 @@ func findCounselingOffice(appCtx appcontext.AppContext, dutyLocationID uuid.UUID
// ********************************
sqlQuery = `
with counseling_offices as (
SELECT transportation_offices.id, transportation_offices.name, transportation_offices.address_id as counseling_address, substring(addresses.postal_code, 1,3 ) as origin_zip, substring(a2.postal_code, 1,3 ) as dest_zip
FROM postal_code_to_gblocs
JOIN addresses on postal_code_to_gblocs.postal_code = addresses.postal_code
JOIN duty_locations on addresses.id = duty_locations.address_id
JOIN transportation_offices on postal_code_to_gblocs.gbloc = transportation_offices.gbloc
join addresses a2 on a2.id = transportation_offices.address_id
WHERE duty_locations.provides_services_counseling = true and duty_locations.id = $1
)
SELECT counseling_offices.id, counseling_offices.name
FROM counseling_offices
JOIN duty_locations duty_locations2 on counseling_offices.id = duty_locations2.transportation_office_id
JOIN addresses on counseling_offices.counseling_address = addresses.id
LEFT JOIN zip3_distances ON (
(substring(addresses.postal_code,1 ,3) = zip3_distances.to_zip3
AND counseling_offices.origin_zip = zip3_distances.from_zip3)
OR
(substring(addresses.postal_code,1 ,3) = zip3_distances.from_zip3
AND counseling_offices.origin_zip = zip3_distances.to_zip3)
)
WHERE duty_locations2.provides_services_counseling = true
group by counseling_offices.id, counseling_offices.name, zip3_distances.distance_miles
ORDER BY coalesce(zip3_distances.distance_miles,0), counseling_offices.name asc`
SELECT transportation_offices.id, transportation_offices.name, transportation_offices.address_id as counseling_address, substring(addresses.postal_code, 1,3 ) as pickup_zip
FROM postal_code_to_gblocs
JOIN addresses on postal_code_to_gblocs.postal_code = addresses.postal_code
JOIN duty_locations on addresses.id = duty_locations.address_id
JOIN transportation_offices on postal_code_to_gblocs.gbloc = transportation_offices.gbloc
WHERE duty_locations.provides_services_counseling = true and duty_locations.id = $1
)
SELECT counseling_offices.id, counseling_offices.name
FROM counseling_offices
JOIN duty_locations duty_locations2 on counseling_offices.id = duty_locations2.transportation_office_id
JOIN addresses on counseling_offices.counseling_address = addresses.id
JOIN re_us_post_regions on addresses.postal_code = re_us_post_regions.uspr_zip_id
LEFT JOIN zip3_distances ON (
(re_us_post_regions.zip3 = zip3_distances.to_zip3
AND counseling_offices.pickup_zip = zip3_distances.from_zip3)
OR
(re_us_post_regions.zip3 = zip3_distances.from_zip3
AND counseling_offices.pickup_zip = zip3_distances.to_zip3)
)
WHERE duty_locations2.provides_services_counseling = true
group by counseling_offices.id, counseling_offices.name, zip3_distances.distance_miles
ORDER BY coalesce(zip3_distances.distance_miles,0), counseling_offices.name asc`

query := appCtx.DB().Q().RawQuery(sqlQuery, dutyLocationID)
if err := query.All(&officeList); err != nil {
Expand Down
13 changes: 11 additions & 2 deletions src/components/Customer/EditOrdersForm/EditOrdersForm.jsx
Original file line number Diff line number Diff line change
Expand Up @@ -94,9 +94,16 @@ const EditOrdersForm = ({
validateOnMount
initialTouched={{ orders_type: true, issue_date: true, report_by_date: true, has_dependents: true, grade: true }}
>
{({ isValid, isSubmitting, handleSubmit, values }) => {
{({ isValid, isSubmitting, handleSubmit, setValues, values }) => {
const isRetirementOrSeparation = ['RETIREMENT', 'SEPARATION'].includes(values.orders_type);

const handleCounselingOfficeChange = () => {
setValues({
...values,
counseling_office_id: null,
});
setOfficeOptions(null);
};
if (!values.origin_duty_location) originMeta = 'Required';
else originMeta = null;

Expand Down Expand Up @@ -163,6 +170,7 @@ const EditOrdersForm = ({
hint="Required"
onDutyLocationChange={(e) => {
setDutyLocation(e);
handleCounselingOfficeChange();
}}
required
metaOverride={originMeta}
Expand All @@ -175,7 +183,7 @@ const EditOrdersForm = ({
assist
</Label>
<DropdownInput
label="Counseling Office"
label="Counseling office"
name="counseling_office_id"
id="counseling_office_id"
hint="Required"
Expand Down Expand Up @@ -286,6 +294,7 @@ EditOrdersForm.propTypes = {
origin_duty_location: PropTypes.shape({
name: PropTypes.string,
}),
counseling_office_id: PropTypes.string,
uploaded_orders: ExistingUploadsShape,
}).isRequired,
onCancel: PropTypes.func.isRequired,
Expand Down
19 changes: 9 additions & 10 deletions src/components/Customer/EditOrdersForm/EditOrdersForm.test.jsx
Original file line number Diff line number Diff line change
Expand Up @@ -201,6 +201,7 @@ const initialValues = {
name: 'Yuma AFB',
updated_at: '2020-10-19T17:01:16.114Z',
},
counseling_office_id: '3e937c1f-5539-4919-954d-017989130584',
new_duty_location: {
address: {
city: 'Des Moines',
Expand Down Expand Up @@ -363,8 +364,11 @@ describe('EditOrdersForm component', () => {
{...testProps}
initialValues={{
origin_duty_location: {
name: 'Altus AFB',
provides_services_counseling: true,
address: { isOconus: false },
},
counseling_office_id: '3e937c1f-5539-4919-954d-017989130584',
uploaded_orders: [
{
id: '123',
Expand All @@ -385,16 +389,13 @@ describe('EditOrdersForm component', () => {
await userEvent.click(screen.getByLabelText('No'));
await userEvent.selectOptions(screen.getByLabelText(/Pay grade/), ['E_5']);

// Test Current Duty Location Search Box interaction
await userEvent.type(screen.getByLabelText(/Current duty location/), 'AFB', { delay: 100 });
const selectedOptionCurrent = await screen.findByText(/Altus/);
await userEvent.click(selectedOptionCurrent);

// Test New Duty Location Search Box interaction
await userEvent.type(screen.getByLabelText(/New duty location/), 'AFB', { delay: 100 });
const selectedOptionNew = await screen.findByText(/Luke/);
await userEvent.click(selectedOptionNew);

expect(screen.getByLabelText(/Counseling office/));

await waitFor(() =>
expect(screen.getByRole('form')).toHaveFormValues({
new_duty_location: 'Luke AFB',
Expand Down Expand Up @@ -610,8 +611,11 @@ describe('EditOrdersForm component', () => {
{...testProps}
initialValues={{
origin_duty_location: {
name: 'Altus AFB',
provides_services_counseling: true,
address: { isOconus: false },
},
counseling_office_id: '3e937c1f-5539-4919-954d-017989130584',
uploaded_orders: [
{
id: '123',
Expand All @@ -632,11 +636,6 @@ describe('EditOrdersForm component', () => {
await userEvent.click(screen.getByLabelText('No'));
await userEvent.selectOptions(screen.getByLabelText(/Pay grade/), ['E_8']);

// Test Current Duty Location Search Box interaction
await userEvent.type(screen.getByLabelText(/Current duty location/), 'AFB', { delay: 100 });
const selectedOptionCurrent = await screen.findByText(/Altus/);
await userEvent.click(selectedOptionCurrent);

// Test New Duty Location Search Box interaction
await userEvent.type(screen.getByLabelText(/New duty location/), 'AFB', { delay: 100 });
const selectedOptionNew = await screen.findByText(/Luke/);
Expand Down
13 changes: 11 additions & 2 deletions src/components/Customer/OrdersInfoForm/OrdersInfoForm.jsx
Original file line number Diff line number Diff line change
Expand Up @@ -57,9 +57,16 @@ const OrdersInfoForm = ({ ordersTypeOptions, initialValues, onSubmit, onBack })

return (
<Formik initialValues={initialValues} validateOnMount validationSchema={validationSchema} onSubmit={onSubmit}>
{({ isValid, isSubmitting, handleSubmit, values, touched }) => {
{({ isValid, isSubmitting, handleSubmit, setValues, values, touched }) => {
const isRetirementOrSeparation = ['RETIREMENT', 'SEPARATION'].includes(values.orders_type);

const handleCounselingOfficeChange = () => {
setValues({
...values,
counseling_office_id: null,
});
setCounselingOfficeOptions(null);
};
if (!values.origin_duty_location && touched.origin_duty_location) originMeta = 'Required';
else originMeta = null;

Expand Down Expand Up @@ -129,6 +136,7 @@ const OrdersInfoForm = ({ ordersTypeOptions, initialValues, onSubmit, onBack })
id="origin_duty_location"
onDutyLocationChange={(e) => {
setDutyLocation(e);
handleCounselingOfficeChange();
}}
required
metaOverride={originMeta}
Expand All @@ -141,7 +149,7 @@ const OrdersInfoForm = ({ ordersTypeOptions, initialValues, onSubmit, onBack })
assist you.
</Label>
<DropdownInput
label="Counseling Office"
label="Counseling office"
name="counseling_office_id"
id="counseling_office_id"
hint="Required"
Expand Down Expand Up @@ -226,6 +234,7 @@ OrdersInfoForm.propTypes = {
new_duty_location: PropTypes.shape({}),
grade: PropTypes.string,
origin_duty_location: DutyLocationShape,
counseling_office_id: PropTypes.string,
}).isRequired,
onSubmit: PropTypes.func.isRequired,
onBack: PropTypes.func.isRequired,
Expand Down
115 changes: 60 additions & 55 deletions src/components/Customer/OrdersInfoForm/OrdersInfoForm.test.jsx
Original file line number Diff line number Diff line change
Expand Up @@ -144,6 +144,22 @@ jest.mock('components/LocationSearchBox/api', () => ({
name: 'Wright-Patterson AFB',
updated_at: '2021-02-11T16:48:20.225Z',
},
{
address: {
city: '',
id: '1111111111',
postalCode: '',
state: '',
streetAddress1: '',
},
address_id: '4334640b-c35e-4293-a2f1-36c7b629f903',
affiliation: 'AIR_FORCE',
created_at: '2021-02-11T16:48:04.117Z',
id: '22f0755f-6f35-478b-9a75-35a69211da1c',
name: 'Scott AFB',
updated_at: '2021-02-11T16:48:04.117Z',
provides_services_counseling: true,
},
]),
),
}));
Expand Down Expand Up @@ -258,7 +274,7 @@ describe('OrdersInfoForm component', () => {
expect(testProps.onSubmit).not.toHaveBeenCalled();
});

it('submits the form when its valid and has a counseling office selected', async () => {
it('renders the counseling office if current duty location provides services counseling', async () => {
const testPropsWithCounselingOffice = {
onSubmit: jest.fn().mockImplementation(() => Promise.resolve()),
initialValues: {
Expand All @@ -269,7 +285,7 @@ describe('OrdersInfoForm component', () => {
new_duty_location: {},
grade: '',
origin_duty_location: {},
counseling_office_id: '3be2381f-f9ed-4902-bbdc-69c69e43eb86',
counseling_office_id: '',
},
onBack: jest.fn(),
ordersTypeOptions: [
Expand All @@ -289,70 +305,59 @@ describe('OrdersInfoForm component', () => {
await userEvent.click(screen.getByLabelText('No'));
await userEvent.selectOptions(screen.getByLabelText(/Pay grade/), ['E_5']);

// Test Current Duty Location Search Box interaction
await userEvent.type(screen.getByLabelText(/Current duty location/), 'AFB', { delay: 100 });
const selectedOptionCurrent = await screen.findByText(/Altus/);
const selectedOptionCurrent = await screen.findByText(/Scott/);
await userEvent.click(selectedOptionCurrent);

// Test New Duty Location Search Box interaction
await userEvent.type(screen.getByLabelText(/New duty location/), 'AFB', { delay: 100 });
const selectedOptionNew = await screen.findByText(/Luke/);
await userEvent.click(selectedOptionNew);

await waitFor(() => {
expect(screen.getByRole('form')).toHaveFormValues({
new_duty_location: 'Luke AFB',
origin_duty_location: 'Altus AFB',
});
expect(screen.getByLabelText(/Counseling office/));
});
});

const submitBtn = screen.getByRole('button', { name: 'Next' });
await userEvent.click(submitBtn);
it('does not render the counseling office if current duty location does not provides services counseling', async () => {
const testPropsWithCounselingOffice = {
onSubmit: jest.fn().mockImplementation(() => Promise.resolve()),
initialValues: {
orders_type: '',
issue_date: '',
report_by_date: '',
has_dependents: '',
new_duty_location: {},
grade: '',
origin_duty_location: {},
counseling_office_id: '',
},
onBack: jest.fn(),
ordersTypeOptions: [
{ key: 'PERMANENT_CHANGE_OF_STATION', value: 'Permanent Change Of Station (PCS)' },
{ key: 'LOCAL_MOVE', value: 'Local Move' },
{ key: 'RETIREMENT', value: 'Retirement' },
{ key: 'SEPARATION', value: 'Separation' },
{ key: 'TEMPORARY_DUTY', value: 'Temporary Duty (TDY)' },
],
};

await waitFor(() => {
expect(testPropsWithCounselingOffice.onSubmit).toHaveBeenCalledWith(
expect.objectContaining({
orders_type: ORDERS_TYPE.PERMANENT_CHANGE_OF_STATION,
counseling_office_id: '3be2381f-f9ed-4902-bbdc-69c69e43eb86',
has_dependents: 'no',
issue_date: '08 Nov 2020',
report_by_date: '26 Nov 2020',
new_duty_location: {
address: {
city: 'Glendale Luke AFB',
country: 'United States',
id: 'fa51dab0-4553-4732-b843-1f33407f77bc',
postalCode: '85309',
state: 'AZ',
streetAddress1: 'n/a',
},
address_id: '25be4d12-fe93-47f1-bbec-1db386dfa67f',
affiliation: 'AIR_FORCE',
created_at: '2021-02-11T16:48:04.117Z',
id: 'a8d6b33c-8370-4e92-8df2-356b8c9d0c1a',
name: 'Luke AFB',
updated_at: '2021-02-11T16:48:04.117Z',
},
grade: 'E_5',
origin_duty_location: {
address: {
city: '',
id: '00000000-0000-0000-0000-000000000000',
postalCode: '',
state: '',
streetAddress1: '',
},
address_id: '46c4640b-c35e-4293-a2f1-36c7b629f903',
affiliation: 'AIR_FORCE',
created_at: '2021-02-11T16:48:04.117Z',
id: '93f0755f-6f35-478b-9a75-35a69211da1c',
name: 'Altus AFB',
updated_at: '2021-02-11T16:48:04.117Z',
},
}),
expect.anything(),
);
});
render(<OrdersInfoForm {...testPropsWithCounselingOffice} />);

await userEvent.selectOptions(screen.getByLabelText(/Orders type/), ORDERS_TYPE.PERMANENT_CHANGE_OF_STATION);
await userEvent.type(screen.getByLabelText(/Orders date/), '08 Nov 2020');
await userEvent.type(screen.getByLabelText(/Report by date/), '26 Nov 2020');
await userEvent.click(screen.getByLabelText('No'));
await userEvent.selectOptions(screen.getByLabelText(/Pay grade/), ['E_5']);

await userEvent.type(screen.getByLabelText(/Current duty location/), 'AFB', { delay: 100 });
const selectedOptionCurrent = await screen.findByText(/Altus/);
await userEvent.click(selectedOptionCurrent);

await userEvent.type(screen.getByLabelText(/New duty location/), 'AFB', { delay: 100 });
const selectedOptionNew = await screen.findByText(/Luke/);
await userEvent.click(selectedOptionNew);

expect(screen.queryByText(/Counseling office/)).not.toBeInTheDocument();
});

it('submits the form when its valid', async () => {
Expand Down
2 changes: 2 additions & 0 deletions src/pages/MyMove/AddOrders.jsx
Original file line number Diff line number Diff line change
Expand Up @@ -64,6 +64,7 @@ const AddOrders = ({
grade: values.grade,
origin_duty_location_id: values.origin_duty_location.id,
spouse_has_pro_gear: false,
counseling_office_id: values.counseling_office_id,
};
if (!values.origin_duty_location.provides_services_counseling) {
pendingValues.counseling_office_id = null;
Expand Down Expand Up @@ -95,6 +96,7 @@ const AddOrders = ({
new_duty_location: '',
grade: '',
origin_duty_location: '',
counseling_office_id: '',
};

// Only allow PCS unless feature flag is on
Expand Down
1 change: 1 addition & 0 deletions src/pages/MyMove/EditOrders.jsx
Original file line number Diff line number Diff line change
Expand Up @@ -146,6 +146,7 @@ const EditOrders = ({
report_by_date: formatDateForSwagger(fieldValues.report_by_date),
grade: newPayGrade,
origin_duty_location_id: newOriginDutyLocationId,
counseling_office_id: fieldValues.counseling_office_id,
// spouse_has_pro_gear is not updated by this form but is a required value because the endpoint is shared with the
// ppm office edit orders
spouse_has_pro_gear: currentOrder.spouse_has_pro_gear,
Expand Down

0 comments on commit 652c646

Please sign in to comment.