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-21569-INT 2 #14577

Merged
merged 31 commits into from
Jan 23, 2025
Merged
Show file tree
Hide file tree
Changes from 21 commits
Commits
Show all changes
31 commits
Select commit Hold shift + click to select a range
e1c9254
B-21569 add the service items in their Sort order.
stevengleason-caci Jan 11, 2025
1c96244
B-21569 rename UBP to "International UB price",
stevengleason-caci Jan 13, 2025
0f72565
Merge branch 'B-21569' into B-21569-INT
stevengleason-caci Jan 13, 2025
7d4df07
Merge branch 'integrationTesting' into B-21569-INT
stevengleason-caci Jan 13, 2025
10cfb33
Merge branch 'integrationTesting' into B-21569-INT
stevengleason-caci Jan 13, 2025
ea981ca
B-21569 move the service item sorting from the insert proc to the UI.
stevengleason-caci Jan 16, 2025
acbbd5a
Merge remote-tracking branch 'origin/integrationTesting' into B-21569…
stevengleason-caci Jan 16, 2025
c6dcd96
Merge branch 'B-21569' into B-21569-INT
stevengleason-caci Jan 16, 2025
1837ce2
Merge remote-tracking branch 'origin/B-21569-INT' into B-21569-INT
stevengleason-caci Jan 16, 2025
fc421d6
Merge branch 'integrationTesting' into B-21569-INT
stevengleason-caci Jan 16, 2025
16930fb
Merge branch 'integrationTesting' into B-21569-INT
stevengleason-caci Jan 16, 2025
f3c0599
B-21569 fix null-safe issue with comparing the sort values,
stevengleason-caci Jan 16, 2025
b29387a
Merge branch 'B-21569' into B-21569-INT
stevengleason-caci Jan 16, 2025
327ed63
Merge remote-tracking branch 'origin/integrationTesting' into B-21569…
stevengleason-caci Jan 16, 2025
d06adec
Merge branch 'integrationTesting' into B-21569-INT
stevengleason-caci Jan 16, 2025
1b59d9d
B-21569 nullSafeStringCompare function in utils.js.
stevengleason-caci Jan 16, 2025
a946e9c
Merge branch 'B-21569' into B-21569-INT
stevengleason-caci Jan 16, 2025
d900dee
Merge remote-tracking branch 'origin/integrationTesting' into B-21569…
stevengleason-caci Jan 17, 2025
9b9e235
Merge branch 'integrationTesting' into B-21569-INT
stevengleason-caci Jan 17, 2025
ebf90eb
Merge branch 'integrationTesting' into B-21569-INT
stevengleason-caci Jan 17, 2025
cf97094
Merge branch 'integrationTesting' into B-21569-INT
stevengleason-caci Jan 17, 2025
f7d0ccd
B-21569 Fix the 1-N relationship for ReService and ReServiceItem.
stevengleason-caci Jan 22, 2025
1025de9
Merge remote-tracking branch 'origin/integrationTesting' into B-21569…
stevengleason-caci Jan 22, 2025
9b83c1c
Merge branch 'B-21569' into B-21569-INT
stevengleason-caci Jan 22, 2025
24d6ebb
B-21569 cleanup:
stevengleason-caci Jan 22, 2025
bc37b12
B-21569 move compare function from shared/utils. to new utils/string.js.
stevengleason-caci Jan 23, 2025
6c4f49d
Merge branch 'B-21569' into B-21569-INT
stevengleason-caci Jan 23, 2025
7c09b81
Merge remote-tracking branch 'origin/integrationTesting' into B-21569…
stevengleason-caci Jan 23, 2025
e999361
B-21569 per peer preference, no nill now needed
stevengleason-caci Jan 23, 2025
440dde0
Merge remote-tracking branch 'origin/integrationTesting' into B-21569…
stevengleason-caci Jan 23, 2025
afcc6a9
Merge branch 'B-21569' into B-21569-INT
stevengleason-caci Jan 23, 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
1 change: 1 addition & 0 deletions migrations/app/migrations_manifest.txt
Original file line number Diff line number Diff line change
Expand Up @@ -1074,4 +1074,5 @@
20250110001339_update_nts_release_enum_name.up.sql
20250110153428_add_shipment_address_updates_to_move_history.up.sql
20250110214012_homesafeconnect_cert.up.sql
20250113152050_rename_ubp.up.sql
20250113201232_update_estimated_pricing_procs_add_is_peak_func.up.sql
1 change: 1 addition & 0 deletions migrations/app/schema/20250113152050_rename_ubp.up.sql
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
update re_services set name = 'International UB price' where code = 'UBP';
10 changes: 10 additions & 0 deletions pkg/gen/ghcapi/embedded_spec.go

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

3 changes: 3 additions & 0 deletions pkg/gen/ghcmessages/m_t_o_service_item.go

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

5 changes: 5 additions & 0 deletions pkg/handlers/ghcapi/internal/payloads/model_to_payload.go
Original file line number Diff line number Diff line change
Expand Up @@ -1882,6 +1882,10 @@ func MTOServiceItemModel(s *models.MTOServiceItem, storer storage.FileStorer) *g
serviceRequestDocs[i] = payload
}
}
var sort *string = nil
brianmanley-caci marked this conversation as resolved.
Show resolved Hide resolved
if s.ReService.ReServiceItem != nil {
sort = s.ReService.ReServiceItem.Sort
}
payload := &ghcmessages.MTOServiceItem{
ID: handlers.FmtUUID(s.ID),
MoveTaskOrderID: handlers.FmtUUID(s.MoveTaskOrderID),
Expand All @@ -1897,6 +1901,7 @@ func MTOServiceItemModel(s *models.MTOServiceItem, storer storage.FileStorer) *g
SitDepartureDate: handlers.FmtDateTimePtr(s.SITDepartureDate),
SitCustomerContacted: handlers.FmtDatePtr(s.SITCustomerContacted),
SitRequestedDelivery: handlers.FmtDatePtr(s.SITRequestedDelivery),
Sort: sort,
Status: ghcmessages.MTOServiceItemStatus(s.Status),
Description: handlers.FmtStringPtr(s.Description),
Dimensions: MTOServiceItemDimensions(s.Dimensions),
Expand Down
1 change: 1 addition & 0 deletions pkg/handlers/ghcapi/mto_service_items.go
Original file line number Diff line number Diff line change
Expand Up @@ -350,6 +350,7 @@ func (h ListMTOServiceItemsHandler) Handle(params mtoserviceitemop.ListMTOServic
query.NewQueryAssociation("SITDestinationFinalAddress"),
query.NewQueryAssociation("SITOriginHHGOriginalAddress"),
query.NewQueryAssociation("SITOriginHHGActualAddress"),
query.NewQueryAssociation("ReService.ReServiceItem.Sort"),
})

var serviceItems models.MTOServiceItems
Expand Down
32 changes: 30 additions & 2 deletions pkg/handlers/ghcapi/mto_service_items_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -129,7 +129,28 @@ func (suite *HandlerSuite) TestListMTOServiceItemHandler() {
},
}, nil)

serviceItems := models.MTOServiceItems{serviceItem, originSit, destinationSit}
poeFsc := factory.BuildMTOServiceItem(suite.DB(), []factory.Customization{
{
Model: models.MTOServiceItem{
Status: models.MTOServiceItemStatusApproved,
},
},
{
Model: mto,
LinkOnly: true,
},
{
Model: mtoShipment,
LinkOnly: true,
},
{
Model: models.ReService{
Code: models.ReServiceCodePOEFSC,
},
},
}, nil)

serviceItems := models.MTOServiceItems{serviceItem, originSit, destinationSit, poeFsc}

return requestUser, serviceItems
}
Expand Down Expand Up @@ -178,7 +199,7 @@ func (suite *HandlerSuite) TestListMTOServiceItemHandler() {
suite.NoError(okResponse.Payload.Validate(strfmt.Default))
fmt.Println(okResponse.Payload)

suite.Len(okResponse.Payload, 3)
suite.Len(okResponse.Payload, 4)
for _, serviceItem := range serviceItems {
for _, payload := range okResponse.Payload {
// Validate that the Customer Contacts were included in the payload
Expand All @@ -200,6 +221,13 @@ func (suite *HandlerSuite) TestListMTOServiceItemHandler() {
}
}
}

// Validate that sort field is populated for service items which have it (ie. POEFSC)
for _, payload := range okResponse.Payload {
if payload.ReServiceCode != nil && *payload.ReServiceCode == models.ReServiceCodePOEFSC.String() {
suite.Equal("2", *payload.Sort)
}
}
})

suite.Run("Failure list fetch - Internal Server Error", func() {
Expand Down
3 changes: 2 additions & 1 deletion pkg/models/re_service.go
Original file line number Diff line number Diff line change
Expand Up @@ -119,7 +119,7 @@ const (
ReServiceCodeNSTH ReServiceCode = "NSTH"
// ReServiceCodeNSTUB Nonstandard UB
ReServiceCodeNSTUB ReServiceCode = "NSTUB"
// ReServiceCodeUBP International UB
// ReServiceCodeUBP International UB price
ReServiceCodeUBP ReServiceCode = "UBP"
// ReServiceCodeISLH Shipping & Linehaul
ReServiceCodeISLH ReServiceCode = "ISLH"
Expand Down Expand Up @@ -147,6 +147,7 @@ type ReService struct {
Priority int `db:"priority" rw:"r"`
Name string `json:"name" db:"name" rw:"r"`
ServiceLocation *ServiceLocationType `db:"service_location" rw:"r"`
ReServiceItem *ReServiceItem `has_one:"re_service_item" fk_id:"service_id"`
brianmanley-caci marked this conversation as resolved.
Show resolved Hide resolved
CreatedAt time.Time `json:"created_at" db:"created_at" rw:"r"`
UpdatedAt time.Time `json:"updated_at" db:"updated_at" rw:"r"`
}
Expand Down
39 changes: 31 additions & 8 deletions pkg/services/mto_shipment/shipment_approver_test.go
Original file line number Diff line number Diff line change
Expand Up @@ -1059,17 +1059,25 @@ func (suite *MTOShipmentServiceSuite) TestApproveShipment() {
err2 := suite.AppContextForTest().DB().EagerPreload("ReService").Where("mto_shipment_id = ?", internationalShipment.ID).Order("created_at asc").All(&serviceItems)
suite.NoError(err2)

expectedReserviceCodes := []models.ReServiceCode{
expectedReServiceCodes := []models.ReServiceCode{
models.ReServiceCodeUBP,
models.ReServiceCodePOEFSC,
models.ReServiceCodeIUBPK,
models.ReServiceCodeIUBUPK,
models.ReServiceCodePOEFSC,
}
expectedReServiceNames := []string{
"International UB price",
"International POE Fuel Surcharge",
"International UB pack",
"International UB unpack",
}

suite.Equal(4, len(serviceItems))
for i := 0; i < len(serviceItems); i++ {
actualReServiceCode := serviceItems[i].ReService.Code
suite.True(slices.Contains(expectedReserviceCodes, actualReServiceCode), "Contains unexpected: "+actualReServiceCode.String())
actualReServiceName := serviceItems[i].ReService.Name
suite.True(slices.Contains(expectedReServiceCodes, actualReServiceCode), "Contains unexpected code: "+actualReServiceCode.String())
suite.True(slices.Contains(expectedReServiceNames, actualReServiceName), "Contains unexpected name: "+actualReServiceName)
}
})

Expand Down Expand Up @@ -1119,17 +1127,25 @@ func (suite *MTOShipmentServiceSuite) TestApproveShipment() {
err2 := suite.AppContextForTest().DB().EagerPreload("ReService").Where("mto_shipment_id = ?", internationalShipment.ID).Order("created_at asc").All(&serviceItems)
suite.NoError(err2)

expectedReserviceCodes := []models.ReServiceCode{
expectedReServiceCodes := []models.ReServiceCode{
models.ReServiceCodeUBP,
models.ReServiceCodePODFSC,
models.ReServiceCodeIUBPK,
models.ReServiceCodeIUBUPK,
models.ReServiceCodePODFSC,
}
expectedReServiceNames := []string{
"International UB price",
"International POD Fuel Surcharge",
"International UB pack",
"International UB unpack",
}

suite.Equal(4, len(serviceItems))
for i := 0; i < len(serviceItems); i++ {
actualReServiceCode := serviceItems[i].ReService.Code
suite.True(slices.Contains(expectedReserviceCodes, actualReServiceCode), "Contains unexpected: "+actualReServiceCode.String())
actualReServiceName := serviceItems[i].ReService.Name
suite.True(slices.Contains(expectedReServiceCodes, actualReServiceCode), "Contains unexpected code: "+actualReServiceCode.String())
suite.True(slices.Contains(expectedReServiceNames, actualReServiceName), "Contains unexpected name: "+actualReServiceName)
}
})

Expand Down Expand Up @@ -1179,16 +1195,23 @@ func (suite *MTOShipmentServiceSuite) TestApproveShipment() {
err2 := suite.AppContextForTest().DB().EagerPreload("ReService").Where("mto_shipment_id = ?", internationalShipment.ID).Order("created_at asc").All(&serviceItems)
suite.NoError(err2)

expectedReserviceCodes := []models.ReServiceCode{
expectedReServiceCodes := []models.ReServiceCode{
models.ReServiceCodeUBP,
models.ReServiceCodeIUBPK,
models.ReServiceCodeIUBUPK,
}
expectedReServiceNames := []string{
"International UB price",
"International UB pack",
"International UB unpack",
}

suite.Equal(3, len(serviceItems))
for i := 0; i < len(serviceItems); i++ {
actualReServiceCode := serviceItems[i].ReService.Code
suite.True(slices.Contains(expectedReserviceCodes, actualReServiceCode), "Contains unexpected: "+actualReServiceCode.String())
actualReServiceName := serviceItems[i].ReService.Name
suite.True(slices.Contains(expectedReServiceCodes, actualReServiceCode), "Contains unexpected code: "+actualReServiceCode.String())
suite.True(slices.Contains(expectedReServiceNames, actualReServiceName), "Contains unexpected name: "+actualReServiceName)
}
})

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -61,6 +61,30 @@ const serviceItemWithDetails = {
},
};

const serviceItemUBP = {
id: 'ubp123',
createdAt: '2025-01-15',
serviceItem: 'International UB price',
code: 'UBP',
sort: '1',
};

const serviceItemIUBPK = {
id: 'iubpk123',
createdAt: '2025-01-15',
serviceItem: 'International UB pack',
code: 'IUBPK',
sort: '3',
};

const serviceItemIUBUPK = {
id: 'iubupk123',
createdAt: '2025-01-15',
serviceItem: 'International UB unpack',
code: 'IUBUPK',
sort: '4',
};

const testDetails = (wrapper) => {
const detailTypes = wrapper.find('.detailType');
const detailDefinitions = wrapper.find('.detail dd');
Expand Down Expand Up @@ -226,4 +250,39 @@ describe('RequestedServiceItemsTable', () => {
expect(approveTextButton.at(1).text().includes('Approve')).toBe(true);
expect(approveTextButton.at(2).text().includes('Approve')).toBe(true);
});

it('displays sorted service items in order', () => {
const serviceItems = [serviceItemIUBPK, serviceItemUBP, serviceItemIUBUPK];
const wrapper = mount(
<MockProviders>
<RequestedServiceItemsTable
{...defaultProps}
serviceItems={serviceItems}
statusForTableType={SERVICE_ITEM_STATUS.SUBMITTED}
/>
</MockProviders>,
);

expect(wrapper.find('.codeName').at(0).text()).toBe('International UB price');
expect(wrapper.find('.codeName').at(1).text()).toBe('International UB pack');
expect(wrapper.find('.codeName').at(2).text()).toBe('International UB unpack');
});

it('displays sorted service items in order along with non-sorted service items', () => {
const serviceItems = [serviceItemIUBPK, serviceItemUBP, serviceItemWithCrating, serviceItemIUBUPK];
const wrapper = mount(
<MockProviders>
<RequestedServiceItemsTable
{...defaultProps}
serviceItems={serviceItems}
statusForTableType={SERVICE_ITEM_STATUS.SUBMITTED}
/>
</MockProviders>,
);

expect(wrapper.find('.codeName').at(0).text()).toBe('International UB price');
expect(wrapper.find('.codeName').at(1).text()).toBe('International UB pack');
expect(wrapper.find('.codeName').at(2).text()).toBe('International UB unpack');
expect(wrapper.find('.codeName').at(3).text()).toBe('Domestic crating');
});
});
15 changes: 9 additions & 6 deletions src/components/Office/ServiceItemsTable/ServiceItemsTable.jsx
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@ import { selectDateFieldByStatus, selectDatePrefixByStatus } from 'utils/dates';
import { useGHCGetMoveHistory, useMovePaymentRequestsQueries } from 'hooks/queries';
import ToolTip from 'shared/ToolTip/ToolTip';
import { ShipmentShape } from 'types';
import { nullSafeStringCompare } from 'shared/utils';

// Sorts service items in an order preferred by the customer
// Currently only SIT & shorthaul/linehaul receives special sorting
Expand Down Expand Up @@ -48,12 +49,14 @@ function sortServiceItems(items) {
);

// Filter all service items that are not specifically sorted
const remainingServiceItems = items.filter(
(item) =>
!haulTypeServiceItemCodes.includes(item.code) &&
!destinationServiceItemCodes.includes(item.code) &&
!originServiceItemCodes.includes(item.code),
);
const remainingServiceItems = items
.filter(
(item) =>
!haulTypeServiceItemCodes.includes(item.code) &&
!destinationServiceItemCodes.includes(item.code) &&
!originServiceItemCodes.includes(item.code),
)
.sort((a, b) => nullSafeStringCompare(a.sort, b.sort));

return [
...sortedHaulTypeServiceItems,
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -25,7 +25,7 @@ const reServiceItemResponse = [
isAutoApproved: true,
marketCode: 'i',
serviceCode: 'UBP',
serviceName: 'International UB',
serviceName: 'International UB price',
shipmentType: 'UNACCOMPANIED_BAGGAGE',
},
{
Expand Down Expand Up @@ -370,7 +370,7 @@ describe('Shipment Service Items Table', () => {

describe('renders the intl UB shipment type (CONUS -> OCONUS) with service items', () => {
it.each([
['International UB'],
['International UB price'],
['International POE Fuel Surcharge'],
['International UB pack'],
['International UB unpack'],
Expand All @@ -385,7 +385,7 @@ describe('Shipment Service Items Table', () => {

describe('renders the intl UB shipment type (OCONUS -> CONUS) with service items', () => {
it.each([
['International UB'],
['International UB price'],
['International POD Fuel Surcharge'],
['International UB pack'],
['International UB unpack'],
Expand All @@ -399,7 +399,7 @@ describe('Shipment Service Items Table', () => {
});

describe('renders the intl UB shipment type (OCONUS -> OCONUS) with service items', () => {
it.each([['International UB'], ['International UB pack'], ['International UB unpack']])(
it.each([['International UB price'], ['International UB pack'], ['International UB unpack']])(
'expects %s to be in the document',
async (serviceItem) => {
render(<ShipmentServiceItemsTable shipment={intlUbOconusToOconusShipment} />);
Expand Down
21 changes: 21 additions & 0 deletions src/shared/utils.js
Original file line number Diff line number Diff line change
Expand Up @@ -209,3 +209,24 @@ export function checkAddressTogglesToClearAddresses(body) {

return values;
}

/**
* Compare strings. Null, undefined, and blanks are after other values.
* @returns -1, 0, 1
*/
export function nullSafeStringCompare(a, b) {
const A_BEFORE = -1;
const A_AFTER = 1;
const SAME = 0;

if (isNullUndefinedOrWhitespace(a) && isNullUndefinedOrWhitespace(b)) {
return SAME;
}
if (isNullUndefinedOrWhitespace(a)) {
return A_AFTER;
}
if (isNullUndefinedOrWhitespace(b)) {
return A_BEFORE;
}
return a.localeCompare(b);
}
Loading
Loading