Skip to content

Commit

Permalink
Merge pull request #14543 from transcom/INT-B-21984-Add-Move-Managemn…
Browse files Browse the repository at this point in the history
…ent-Fee-Too-Payment-Review

INT-B-21984 Add Move Management Fee to Payment Review
  • Loading branch information
brianmanley-caci authored Jan 16, 2025
2 parents d0c264f + fd60616 commit 5b8a59d
Show file tree
Hide file tree
Showing 12 changed files with 227 additions and 34 deletions.
Original file line number Diff line number Diff line change
Expand Up @@ -832,6 +832,7 @@ func (suite *PayloadsSuite) TestSearchMoves() {
},
},
}, nil)

moves := models.Moves{moveUSMC}
suite.Run("Success - Returns a ghcmessages Upload payload from Upload Struct Marine move with no shipments", func() {
payload := SearchMoves(appCtx, moves)
Expand Down
22 changes: 11 additions & 11 deletions pkg/handlers/primeapiv3/payloads/model_to_payload.go
Original file line number Diff line number Diff line change
Expand Up @@ -1087,17 +1087,6 @@ func MTOShipment(mtoShipment *models.MTOShipment) *primev3messages.MTOShipment {
return payload
}

// PostalCodeToRateArea converts postalCode into RateArea model to payload
func PostalCodeToRateArea(postalCode *string, shipmentPostalCodeRateAreaMap map[string]services.ShipmentPostalCodeRateArea) *primev3messages.RateArea {
if postalCode == nil {
return nil
}
if ra, ok := shipmentPostalCodeRateAreaMap[*postalCode]; ok {
return &primev3messages.RateArea{ID: handlers.FmtUUID(ra.RateArea.ID), RateAreaID: &ra.RateArea.Code, RateAreaName: &ra.RateArea.Name}
}
return nil
}

// Takes the Port Location from the MTO Service item and sets it on the MTOShipmentsWithoutServiceObjects payload
func setPortsOnShipments(mtoServiceItems *models.MTOServiceItems, mtoShipments *primev3messages.MTOShipmentsWithoutServiceObjects) {
shipmentPodMap := make(map[string]*models.PortLocation)
Expand Down Expand Up @@ -1140,3 +1129,14 @@ func Port(portLocation *models.PortLocation) *primev3messages.Port {
Country: portLocation.Country.CountryName,
}
}

// PostalCodeToRateArea converts postalCode into RateArea model to payload
func PostalCodeToRateArea(postalCode *string, shipmentPostalCodeRateAreaMap map[string]services.ShipmentPostalCodeRateArea) *primev3messages.RateArea {
if postalCode == nil {
return nil
}
if ra, ok := shipmentPostalCodeRateAreaMap[*postalCode]; ok {
return &primev3messages.RateArea{ID: handlers.FmtUUID(ra.RateArea.ID), RateAreaID: &ra.RateArea.Code, RateAreaName: &ra.RateArea.Name}
}
return nil
}
20 changes: 20 additions & 0 deletions src/components/Office/AddOrdersForm/AddOrdersForm.test.jsx
Original file line number Diff line number Diff line change
Expand Up @@ -453,3 +453,23 @@ describe('AddOrdersForm - With Counseling Office', () => {
expect(nextBtn.getAttribute('disabled')).toBeFalsy();
});
});
describe('AddOrdersForm - Edge Cases and Additional Scenarios', () => {
it('disables orders type when safety move is selected', async () => {
render(
<Provider store={mockStore.store}>
<AddOrdersForm {...testProps} isSafetyMoveSelected />
</Provider>,
);

expect(screen.getByLabelText('Orders type')).toBeDisabled();
});

it('disables orders type when bluebark move is selected', async () => {
render(
<Provider store={mockStore.store}>
<AddOrdersForm {...testProps} isBluebarkMoveSelected />
</Provider>,
);
expect(screen.getByLabelText('Orders type')).toBeDisabled();
});
});
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,20 @@ const ReviewAccountingCodesItem = ({ shipmentId, shipmentType, tac, sac, amount
);
};

// Renders Move level services such as Move management (MS) and Counseling(CS) that not associated to a shipment.
const ReviewMoveLevelServiceItems = ({ services }) => {
return (
<div className={`${styles.MoveLevelServiceItems}`}>
{services.map((item) => (
<div key={item.id}>
<div className={styles.MoveLevelServiceItemsAmount}>{toDollarString(item.amount)}</div>
<div className={styles.MoveLevelServiceItemsName}>{item.mtoServiceItemName} fee</div>
</div>
))}
</div>
);
};

ReviewAccountingCodesItem.propTypes = {
shipmentId: PropTypes.string,
shipmentType: PropTypes.string,
Expand Down Expand Up @@ -58,7 +72,13 @@ const ReviewAccountingCodes = ({ TACs, SACs, cards }) => {
}, {}),
);

if (shipments.length === 0) {
// Create move level service items. Move level service will not have an associated MTO Shipment ID
const moveLevelServices = [];
cards
.filter((card) => !card.mtoShipmentID && card.status === PAYMENT_SERVICE_ITEM_STATUS.APPROVED)
.forEach((item) => moveLevelServices.push(item));

if (shipments.length === 0 && moveLevelServices.length === 0) {
return null;
}

Expand All @@ -77,6 +97,8 @@ const ReviewAccountingCodes = ({ TACs, SACs, cards }) => {
/>
);
})}

{moveLevelServices.length > 0 && <ReviewMoveLevelServiceItems services={moveLevelServices} />}
</div>
);
};
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -43,3 +43,36 @@
.SAC{
word-wrap: break-word;
}

.MoveLevelServiceItems {
@include u-margin-bottom(1);
@include u-padding-y(1.5);
@include u-padding-x(1);
border: solid 1px $base-lighter;
border-left: solid 5px $base-lighter;
border-radius: 4px;
line-height: 18px;
display: flex;
flex-direction: column;
gap: 10px;

.MoveLevelServiceItemsAmount {
float: right;
}

.MoveLevelServiceItemsName {
@include u-text('bold');
@include u-text('base-darker');
}

> div:not(:last-child) {
@include u-border-bottom('1px');
@include u-border-color('base-lighter');
@include u-padding-top(.5);
@include u-padding-bottom(1.5);
}

> div:last-child {
@include u-padding-top(.5);
}
}
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@ import React from 'react';

import ReviewAccountingCodes from './ReviewAccountingCodes';

import { LOA_TYPE, SHIPMENT_OPTIONS } from 'shared/constants';
import { LOA_TYPE, SHIPMENT_OPTIONS, PAYMENT_SERVICE_ITEM_STATUS } from 'shared/constants';

export default {
title: 'Office Components/ReviewServiceItems/ReviewAccountingCodes',
Expand All @@ -14,14 +14,14 @@ const SACs = { HHG: 'AB12', NTS: 'CD34' };

const serviceItemsHHG = [
{
status: 'APPROVED',
status: PAYMENT_SERVICE_ITEM_STATUS.APPROVED,
mtoShipmentTacType: LOA_TYPE.HHG,
mtoShipmentID: '10',
mtoShipmentType: SHIPMENT_OPTIONS.HHG,
amount: 23.45,
},
{
status: 'APPROVED',
status: PAYMENT_SERVICE_ITEM_STATUS.APPROVED,
mtoShipmentTacType: LOA_TYPE.HHG,
mtoShipmentID: '10',
mtoShipmentType: SHIPMENT_OPTIONS.HHG,
Expand All @@ -31,15 +31,15 @@ const serviceItemsHHG = [

const serviceItemsNTSR = [
{
status: 'APPROVED',
status: PAYMENT_SERVICE_ITEM_STATUS.APPROVED,
mtoShipmentTacType: LOA_TYPE.NTS,
mtoShipmentSacType: LOA_TYPE.NTS,
mtoShipmentID: '20',
mtoShipmentType: SHIPMENT_OPTIONS.NTSR,
amount: 559,
},
{
status: 'APPROVED',
status: PAYMENT_SERVICE_ITEM_STATUS.APPROVED,
mtoShipmentTacType: LOA_TYPE.NTS,
mtoShipmentSacType: LOA_TYPE.NTS,
mtoShipmentID: '20',
Expand All @@ -48,8 +48,29 @@ const serviceItemsNTSR = [
},
];

const moveLevelServices = [
{
amount: 44.33,
status: PAYMENT_SERVICE_ITEM_STATUS.APPROVED,
mtoServiceItemName: 'Move management',
},
{
amount: 20.65,
status: PAYMENT_SERVICE_ITEM_STATUS.APPROVED,
mtoServiceItemName: 'Counseling',
},
];

export const withOneShipment = () => <ReviewAccountingCodes TACs={TACs} SACs={SACs} cards={[...serviceItemsHHG]} />;

export const withMultipleShipments = () => (
<ReviewAccountingCodes TACs={TACs} SACs={SACs} cards={[...serviceItemsHHG, ...serviceItemsNTSR]} />
);

export const withMultipleShipmentsAndMoveLevelServices = () => (
<ReviewAccountingCodes
TACs={TACs}
SACs={SACs}
cards={[...serviceItemsHHG, ...serviceItemsNTSR, ...moveLevelServices]}
/>
);
Original file line number Diff line number Diff line change
Expand Up @@ -7,15 +7,25 @@ import { LOA_TYPE, PAYMENT_SERVICE_ITEM_STATUS, SHIPMENT_OPTIONS } from 'shared/

describe('components/Office/ReviewServiceItems/ReviewAccountingCodes', () => {
describe('can display nothing if there are no valid service items', () => {
it('should not display service items not attached to a shipment', () => {
it('should not display service items when cards is empty', () => {
render(
<ReviewAccountingCodes TACs={{ HHG: '1234', NTS: '5678' }} SACs={{ HHG: 'AB12', NTS: 'CD34' }} cards={[]} />,
);

expect(screen.queryByRole('heading', { level: 4, name: 'Accounting codes' })).not.toBeInTheDocument();
});

it('should not display service items that are rejected', () => {
render(
<ReviewAccountingCodes
TACs={{ HHG: '1234', NTS: '5678' }}
SACs={{ HHG: 'AB12', NTS: 'CD34' }}
cards={[
{
amount: 0.01,
status: PAYMENT_SERVICE_ITEM_STATUS.APPROVED,
mtoShipmentID: 'X',
mtoShipmentType: SHIPMENT_OPTIONS.HHG,
status: PAYMENT_SERVICE_ITEM_STATUS.DENIED,
},
]}
/>,
Expand All @@ -24,23 +34,21 @@ describe('components/Office/ReviewServiceItems/ReviewAccountingCodes', () => {
expect(screen.queryByRole('heading', { level: 4, name: 'Accounting codes' })).not.toBeInTheDocument();
});

it('should not display service items that are rejected', () => {
it('should not display shipment card for service items not attached to a shipment', () => {
render(
<ReviewAccountingCodes
TACs={{ HHG: '1234', NTS: '5678' }}
SACs={{ HHG: 'AB12', NTS: 'CD34' }}
cards={[
{
amount: 0.01,
mtoShipmentID: 'X',
mtoShipmentType: SHIPMENT_OPTIONS.HHG,
status: PAYMENT_SERVICE_ITEM_STATUS.DENIED,
status: PAYMENT_SERVICE_ITEM_STATUS.APPROVED,
},
]}
/>,
);

expect(screen.queryByRole('heading', { level: 4, name: 'Accounting codes' })).not.toBeInTheDocument();
expect(screen.queryByText('HHG')).not.toBeInTheDocument();
});
});

Expand Down Expand Up @@ -124,5 +132,81 @@ describe('components/Office/ReviewServiceItems/ReviewAccountingCodes', () => {
expect(within(thirdShipment).getByText('SAC: CD34 (NTS)')).toBeInTheDocument();
expect(within(thirdShipment).getByText('$30.00')).toBeInTheDocument();
});

it('can display a move level service item card', () => {
render(
<ReviewAccountingCodes
cards={[
{
amount: 44.33,
status: PAYMENT_SERVICE_ITEM_STATUS.APPROVED,
mtoServiceItemName: 'Move management',
},
{
amount: 20,
status: PAYMENT_SERVICE_ITEM_STATUS.APPROVED,
mtoServiceItemName: 'Counseling',
},
]}
/>,
);

expect(screen.getByRole('heading', { level: 4, name: 'Accounting codes' })).toBeInTheDocument();
expect(screen.getByText('Move management fee')).toBeInTheDocument();
expect(screen.getByText('$44.33')).toBeInTheDocument();
expect(screen.getByText('Counseling fee')).toBeInTheDocument();
expect(screen.getByText('$20.00')).toBeInTheDocument();
});

it('can display a move level service item card and multiple shipment cards', () => {
render(
<ReviewAccountingCodes
TACs={{ HHG: '1234', NTS: '5678' }}
SACs={{ HHG: 'AB12', NTS: 'CD34' }}
cards={[
{
amount: 44.33,
status: PAYMENT_SERVICE_ITEM_STATUS.APPROVED,
mtoServiceItemName: 'Move management',
},
{
amount: 20.65,
status: PAYMENT_SERVICE_ITEM_STATUS.APPROVED,
mtoServiceItemName: 'Counseling',
},
{
amount: 10,
mtoShipmentID: '1',
mtoShipmentType: SHIPMENT_OPTIONS.HHG,
status: PAYMENT_SERVICE_ITEM_STATUS.APPROVED,
mtoShipmentTacType: LOA_TYPE.HHG,
},
{
amount: 20,
mtoShipmentID: '2',
mtoShipmentType: SHIPMENT_OPTIONS.NTS,
status: PAYMENT_SERVICE_ITEM_STATUS.APPROVED,
mtoShipmentTacType: LOA_TYPE.NTS,
mtoShipmentSacType: LOA_TYPE.HHG,
},
]}
/>,
);

expect(screen.getByRole('heading', { level: 4, name: 'Accounting codes' })).toBeInTheDocument();
const firstShipment = screen.getByTestId('shipment-1');
expect(within(firstShipment).getByText('HHG')).toBeInTheDocument();
expect(within(firstShipment).queryByText('SAC: AB12 (HHG)')).not.toBeInTheDocument();
expect(within(firstShipment).getByText('$10.00')).toBeInTheDocument();
const secondShipment = screen.getByTestId('shipment-2');
expect(within(secondShipment).getByText('NTS')).toBeInTheDocument();
expect(within(secondShipment).getByText('TAC: 5678 (NTS)')).toBeInTheDocument();
expect(within(secondShipment).getByText('SAC: AB12 (HHG)')).toBeInTheDocument();
expect(within(secondShipment).getByText('$20.00')).toBeInTheDocument();
expect(screen.getByText('Move management fee')).toBeInTheDocument();
expect(screen.getByText('$44.33')).toBeInTheDocument();
expect(screen.getByText('Counseling fee')).toBeInTheDocument();
expect(screen.getByText('$20.65')).toBeInTheDocument();
});
});
});
Original file line number Diff line number Diff line change
Expand Up @@ -248,8 +248,18 @@ export const WithPaymentReviewedApproved = () => (
amount: 5678.05,
createdAt: '2020-01-01T00:08:00.999Z',
},
{
amount: 54.89,
status: PAYMENT_SERVICE_ITEM_STATUS.APPROVED,
mtoServiceItemName: serviceItemCodes.MS,
},
{
amount: 61.32,
status: PAYMENT_SERVICE_ITEM_STATUS.APPROVED,
mtoServiceItemName: serviceItemCodes.CS,
},
]}
curCardIndex={1}
curCardIndex={3}
requestReviewed
handleClose={action('clicked')}
onCompleteReview={action('clicked')}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -678,6 +678,8 @@ describe('CreateCustomerForm', () => {
const saveBtn = await screen.findByRole('button', { name: 'Save' });
expect(saveBtn).toBeInTheDocument();

// check the safety move box
await userEvent.type(getByTestId('is-safety-move-no'), bluebarkPayload.is_safety_move);
await userEvent.type(getByTestId('is-bluebark-yes'), bluebarkPayload.is_bluebark);

await userEvent.selectOptions(getByLabelText('Branch of service'), ['ARMY']);
Expand Down
2 changes: 1 addition & 1 deletion src/shared/styles/colors.scss
Original file line number Diff line number Diff line change
Expand Up @@ -2,7 +2,7 @@
//Group 1: Brand Colors
$mm-blue: #252f3e;
$mm-gold: #ffbe2e;
$mm-periwinkle: #8cafea;
$mm-periwinkle: #8fb2ed;

//Group 2: Background Colors
$bg-white: #fff;
Expand Down
Loading

0 comments on commit 5b8a59d

Please sign in to comment.