diff --git a/pkg/models/order.go b/pkg/models/order.go index add1e705938..747ce6ac4c2 100644 --- a/pkg/models/order.go +++ b/pkg/models/order.go @@ -342,9 +342,8 @@ func (o *Order) IsCompleteForGBL() bool { } func (o *Order) CanSendEmailWithOrdersType() bool { - if o.OrdersType != "BLUEBARK" && o.OrdersType != "SAFETY" { - return true + if o.OrdersType == internalmessages.OrdersTypeBLUEBARK || o.OrdersType == internalmessages.OrdersTypeSAFETY { + return false } - - return false + return true } diff --git a/pkg/models/order_test.go b/pkg/models/order_test.go index 9e3e84f50f8..6ef09fe7598 100644 --- a/pkg/models/order_test.go +++ b/pkg/models/order_test.go @@ -485,3 +485,44 @@ func (suite *ModelSuite) TestSaveOrderWithoutPPM() { suite.Equal(location.ID, orderUpdated.NewDutyLocationID, "Wrong order new_duty_location_id") suite.Equal(newPostalCode, order.NewDutyLocation.Address.PostalCode, "Wrong orig postal code") } + +func (suite *ModelSuite) TestOrderCanSendEmailWithOrdersType() { + suite.Run("Non safety or BB orders can send email", func() { + order := factory.BuildOrder(suite.DB(), []factory.Customization{ + { + Model: m.Order{ + OrdersType: internalmessages.OrdersTypePERMANENTCHANGEOFSTATION, + }, + }, + }, nil) + + canSendEmail := order.CanSendEmailWithOrdersType() + suite.True(canSendEmail) + }) + + suite.Run(" BB orders cannot send email", func() { + order := factory.BuildOrder(suite.DB(), []factory.Customization{ + { + Model: m.Order{ + OrdersType: internalmessages.OrdersTypeBLUEBARK, + }, + }, + }, nil) + + canSendEmail := order.CanSendEmailWithOrdersType() + suite.False(canSendEmail) + }) + + suite.Run("Safety orders cannot send email", func() { + order := factory.BuildOrder(suite.DB(), []factory.Customization{ + { + Model: m.Order{ + OrdersType: internalmessages.OrdersTypeSAFETY, + }, + }, + }, nil) + + canSendEmail := order.CanSendEmailWithOrdersType() + suite.False(canSendEmail) + }) +} diff --git a/src/components/Office/AddOrdersForm/AddOrdersForm.jsx b/src/components/Office/AddOrdersForm/AddOrdersForm.jsx index 07949b46c2e..ca0b173a684 100644 --- a/src/components/Office/AddOrdersForm/AddOrdersForm.jsx +++ b/src/components/Office/AddOrdersForm/AddOrdersForm.jsx @@ -23,7 +23,14 @@ import ConnectedFlashMessage from 'containers/FlashMessage/FlashMessage'; let originMeta; let newDutyMeta = ''; -const AddOrdersForm = ({ onSubmit, ordersTypeOptions, initialValues, onBack, isSafetyMoveSelected }) => { +const AddOrdersForm = ({ + onSubmit, + ordersTypeOptions, + initialValues, + onBack, + isSafetyMoveSelected, + isBluebarkMoveSelected, +}) => { const payGradeOptions = dropdownInputOptions(ORDERS_PAY_GRADE_OPTIONS); const [currentDutyLocation, setCurrentDutyLocation] = useState(''); const [newDutyLocation, setNewDutyLocation] = useState(''); @@ -122,7 +129,7 @@ const AddOrdersForm = ({ onSubmit, ordersTypeOptions, initialValues, onBack, isS name="ordersType" options={ordersTypeOptions} required - isDisabled={isSafetyMoveSelected} + isDisabled={isSafetyMoveSelected || isBluebarkMoveSelected} /> diff --git a/src/components/Office/AddOrdersForm/AddOrdersForm.test.jsx b/src/components/Office/AddOrdersForm/AddOrdersForm.test.jsx index f6c4f04e22f..611331d78a9 100644 --- a/src/components/Office/AddOrdersForm/AddOrdersForm.test.jsx +++ b/src/components/Office/AddOrdersForm/AddOrdersForm.test.jsx @@ -194,3 +194,23 @@ describe('AddOrdersForm - OCONUS and Accompanied Tour Test', () => { }); }); }); +describe('AddOrdersForm - Edge Cases and Additional Scenarios', () => { + it('disables orders type when safety move is selected', async () => { + render( + + + , + ); + + expect(screen.getByLabelText('Orders type')).toBeDisabled(); + }); + + it('disables orders type when bluebark move is selected', async () => { + render( + + + , + ); + expect(screen.getByLabelText('Orders type')).toBeDisabled(); + }); +}); diff --git a/src/components/Office/OrdersDetailForm/OrdersDetailForm.jsx b/src/components/Office/OrdersDetailForm/OrdersDetailForm.jsx index b24ff3ae670..26028b4ea69 100644 --- a/src/components/Office/OrdersDetailForm/OrdersDetailForm.jsx +++ b/src/components/Office/OrdersDetailForm/OrdersDetailForm.jsx @@ -8,6 +8,7 @@ import { CheckboxField, DropdownInput, DatePickerInput, DutyLocationInput } from import TextField from 'components/form/fields/TextField/TextField'; import MaskedTextField from 'components/form/fields/MaskedTextField/MaskedTextField'; import { DropdownArrayOf } from 'types/form'; +import { SPECIAL_ORDERS_TYPES } from 'constants/orders'; const OrdersDetailForm = ({ deptIndicatorOptions, @@ -82,12 +83,20 @@ const OrdersDetailForm = ({ { setFormOrdersType(e.target.value); setFieldValue('ordersType', e.target.value); }} - isDisabled={formIsDisabled || formOrdersType === 'SAFETY'} + isDisabled={ + formIsDisabled || + formOrdersType === SPECIAL_ORDERS_TYPES.SAFETY_NON_LABEL || + formOrdersType === SPECIAL_ORDERS_TYPES.BLUEBARK + } /> {showOrdersTypeDetail && ( { ordersType: 'SAFETY', }); + // correct labels are visible + expect(await screen.findByLabelText('Orders type')).toBeDisabled(); + }); + it('has orders type dropdown disabled if bluebark move', async () => { + renderOrdersDetailForm({ + showDepartmentIndicator: false, + showOrdersNumber: false, + showOrdersTypeDetail: false, + showHHGTac: false, + showHHGSac: false, + showNTSTac: false, + showNTSSac: false, + showOrdersAcknowledgement: false, + ordersType: 'BLUEBARK', + }); + // correct labels are visible expect(await screen.findByLabelText('Orders type')).toBeDisabled(); }); diff --git a/src/constants/orders.js b/src/constants/orders.js index eb74a318b38..7eeb4ab9e73 100644 --- a/src/constants/orders.js +++ b/src/constants/orders.js @@ -12,6 +12,7 @@ export const SPECIAL_ORDERS_TYPES = { WOUNDED_WARRIOR: 'Wounded Warrior', BLUEBARK: 'BLUEBARK', SAFETY: 'Safety', + SAFETY_NON_LABEL: 'SAFETY', }; export const CHECK_SPECIAL_ORDERS_TYPES = (ordersType) => { diff --git a/src/pages/Office/CustomerOnboarding/CreateCustomerForm.jsx b/src/pages/Office/CustomerOnboarding/CreateCustomerForm.jsx index 63ab89641e1..6b4bd9830cb 100644 --- a/src/pages/Office/CustomerOnboarding/CreateCustomerForm.jsx +++ b/src/pages/Office/CustomerOnboarding/CreateCustomerForm.jsx @@ -36,6 +36,7 @@ export const CreateCustomerForm = ({ userPrivileges, setFlashMessage, setCanAddO const [showEmplid, setShowEmplid] = useState(false); const [isSafetyMove, setIsSafetyMove] = useState(false); const [showSafetyMoveHint, setShowSafetyMoveHint] = useState(false); + const [isBluebarkMove, setIsBluebarkMove] = useState(false); const navigate = useNavigate(); const branchOptions = dropdownInputOptions(SERVICE_MEMBER_AGENCY_LABELS); @@ -96,6 +97,7 @@ export const CreateCustomerForm = ({ userPrivileges, setFlashMessage, setCanAddO create_okta_account: '', cac_user: '', is_safety_move: 'false', + is_bluebark: 'false', }; const handleBack = () => { @@ -140,7 +142,7 @@ export const CreateCustomerForm = ({ userPrivileges, setFlashMessage, setCanAddO generatePath(servicesCounselingRoutes.BASE_CUSTOMERS_ORDERS_ADD_PATH, { customerId, }), - { state: { isSafetyMoveSelected: isSafetyMove } }, + { state: { isSafetyMoveSelected: isSafetyMove, isBluebarkMoveSelected: isBluebarkMove } }, ); }) .catch((e) => { @@ -227,6 +229,7 @@ export const CreateCustomerForm = ({ userPrivileges, setFlashMessage, setCanAddO create_okta_account: '', cac_user: 'true', is_safety_move: 'true', + is_bluebark: 'false', }); } else if (value === 'false') { setIsSafetyMove(false); @@ -275,11 +278,34 @@ export const CreateCustomerForm = ({ userPrivileges, setFlashMessage, setCanAddO }); } }; + const handleBluebarkChange = (e) => { + if (e.target.value === 'true') { + setIsBluebarkMove(true); + setIsSafetyMove(false); + setShowEmplid(false); + setValues({ + ...values, + affiliation: e.target.value, + create_okta_account: 'false', + cac_user: 'false', + is_bluebark: 'true', + is_safety_move: 'false', + }); + } else { + setIsBluebarkMove(false); + setShowEmplid(false); + setValues({ + ...values, + affiliation: e.target.value, + is_bluebark: 'false', + }); + } + }; return (

Create Customer Profile

-

Customer Affiliation

+

Special Moves

{isSafetyPrivileged && (
Is this a Safety move? @@ -307,10 +333,39 @@ export const CreateCustomerForm = ({ userPrivileges, setFlashMessage, setCanAddO
)} +
+ Is this a Bluebark move? +
+ + +
+
+
+ +

Customer Affiliation

{ handleChange(e); @@ -410,8 +465,8 @@ export const CreateCustomerForm = ({ userPrivileges, setFlashMessage, setCanAddO required />
- {values.is_safety_move !== 'true' && ( - + {values.is_safety_move !== 'true' && values.is_bluebark !== 'true' && ( +

Okta Account

Do you want to create an Okta account for this customer? @@ -436,8 +491,8 @@ export const CreateCustomerForm = ({ userPrivileges, setFlashMessage, setCanAddO
)} - {values.is_safety_move !== 'true' && ( - + {values.is_safety_move !== 'true' && values.is_bluebark !== 'true' && ( +

Non-CAC Users

Does the customer have a CAC? diff --git a/src/pages/Office/CustomerOnboarding/CreateCustomerForm.test.jsx b/src/pages/Office/CustomerOnboarding/CreateCustomerForm.test.jsx index 24f15c6e0fa..b49f6aea696 100644 --- a/src/pages/Office/CustomerOnboarding/CreateCustomerForm.test.jsx +++ b/src/pages/Office/CustomerOnboarding/CreateCustomerForm.test.jsx @@ -120,6 +120,7 @@ const fakePayload = { create_okta_account: 'true', cac_user: 'false', is_safety_move: false, + is_bluebark: 'false', }; const fakeResponse = { @@ -207,6 +208,12 @@ const safetyPayload = { create_okta_account: 'true', cac_user: 'false', is_safety_move: 'true', + is_bluebark: 'false', +}; + +const bluebarkPayload = { + is_safety_move: 'false', + is_bluebark: 'true', }; const mockUserPrivileges = [ @@ -327,6 +334,7 @@ describe('CreateCustomerForm', () => { expect(mockNavigate).toHaveBeenCalledWith(ordersPath, { state: { isSafetyMoveSelected: false, + isBluebarkMoveSelected: false, }, }); }); @@ -422,6 +430,7 @@ describe('CreateCustomerForm', () => { expect(mockNavigate).toHaveBeenCalledWith(ordersPath, { state: { isSafetyMoveSelected: false, + isBluebarkMoveSelected: false, }, }); }); @@ -519,6 +528,7 @@ describe('CreateCustomerForm', () => { expect(saveBtn).toBeInTheDocument(); await userEvent.type(getByTestId('is-safety-move-yes'), safetyPayload.is_safety_move); + await userEvent.type(getByTestId('is-bluebark-no'), safetyPayload.is_bluebark); await user.selectOptions(getByLabelText('Branch of service'), [safetyPayload.affiliation]); await user.type(getByLabelText('First name'), safetyPayload.first_name); @@ -565,6 +575,7 @@ describe('CreateCustomerForm', () => { expect(mockNavigate).toHaveBeenCalledWith(ordersPath, { state: { isSafetyMoveSelected: true, + isBluebarkMoveSelected: false, }, }); }); @@ -588,7 +599,7 @@ describe('CreateCustomerForm', () => { // check the safety move box await userEvent.type(getByTestId('is-safety-move-yes'), safetyPayload.is_safety_move); - + await userEvent.type(getByTestId('is-bluebark-no'), safetyPayload.is_bluebark); expect(await screen.findByTestId('safetyMoveHint')).toBeInTheDocument(); await user.selectOptions(getByLabelText('Branch of service'), ['COAST_GUARD']); @@ -645,8 +656,84 @@ describe('CreateCustomerForm', () => { expect(mockNavigate).toHaveBeenCalledWith(ordersPath, { state: { isSafetyMoveSelected: true, + isBluebarkMoveSelected: false, }, }); }); - }, 20000); + }, 50000); + + it('disables okta and non cac user inputs when bluebark move is selected', async () => { + createCustomerWithOktaOption.mockImplementation(() => Promise.resolve(fakeResponse)); + isBooleanFlagEnabled.mockImplementation(() => Promise.resolve(true)); + searchLocationByZipCityState.mockImplementation(mockSearchPickupLocation); + + const { getByLabelText, getByTestId, getByRole } = render( + + + , + ); + + const user = userEvent.setup(); + + 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']); + await user.type(getByTestId('edipiInput'), safetyPayload.edipi); + + await user.type(getByLabelText('First name'), safetyPayload.first_name); + await user.type(getByLabelText('Last name'), safetyPayload.last_name); + + await user.type(getByLabelText('Best contact phone'), safetyPayload.telephone); + await user.type(getByLabelText('Personal email'), safetyPayload.personal_email); + + await userEvent.type( + getByTestId('residential_address.streetAddress1'), + safetyPayload.residential_address.streetAddress1, + ); + + const locationBox = screen.getAllByRole('combobox'); + + await act(async () => { + await userEvent.type(locationBox[1], 'BEVERLY HILLS'); + const selectedResidentialLocation = await screen.findByText(/90210/); + await userEvent.click(selectedResidentialLocation); + }); + + await userEvent.type( + getByTestId('backup_mailing_address.streetAddress1'), + safetyPayload.backup_mailing_address.streetAddress1, + ); + + await act(async () => { + await userEvent.type(locationBox[2], 'DRYDEN'); + const selectedBackupLocation = await screen.findByText(/04225/); + await userEvent.click(selectedBackupLocation); + }); + + await userEvent.type(getByLabelText('Name'), safetyPayload.backup_contact.name); + await userEvent.type(getByRole('textbox', { name: 'Email' }), safetyPayload.backup_contact.email); + await userEvent.type(getByRole('textbox', { name: 'Phone' }), safetyPayload.backup_contact.telephone); + + expect(saveBtn).toBeInTheDocument(); + + await waitFor(() => { + expect(saveBtn).toBeEnabled(); + }); + await userEvent.click(saveBtn); + + await waitFor(() => { + expect(createCustomerWithOktaOption).toHaveBeenCalled(); + expect(mockNavigate).toHaveBeenCalledWith(ordersPath, { + state: { + isSafetyMoveSelected: false, + isBluebarkMoveSelected: true, + }, + }); + }); + }, 50000); }); diff --git a/src/pages/Office/ServicesCounselingAddOrders/ServicesCounselingAddOrders.jsx b/src/pages/Office/ServicesCounselingAddOrders/ServicesCounselingAddOrders.jsx index 9c269782ec7..40ecb706b6a 100644 --- a/src/pages/Office/ServicesCounselingAddOrders/ServicesCounselingAddOrders.jsx +++ b/src/pages/Office/ServicesCounselingAddOrders/ServicesCounselingAddOrders.jsx @@ -25,6 +25,7 @@ const ServicesCounselingAddOrders = ({ userPrivileges, canAddOrders, setCanAddOr const { customerId } = useParams(); const { state } = useLocation(); const isSafetyMoveSelected = state?.isSafetyMoveSelected; + const isBluebarkMoveSelected = state?.isBluebarkMoveSelected; const navigate = useNavigate(); const [isSafetyMoveFF, setSafetyMoveFF] = useState(false); const [hasSubmitted, setHasSubmitted] = useState(false); @@ -82,13 +83,25 @@ const ServicesCounselingAddOrders = ({ userPrivileges, canAddOrders, setCanAddOr ? userPrivileges?.some((privilege) => privilege.privilegeType === elevatedPrivilegeTypes.SAFETY) : false; - const allowedOrdersTypes = isSafetyPrivileged - ? { ...ORDERS_TYPE_OPTIONS, ...{ SAFETY: 'Safety' } } - : ORDERS_TYPE_OPTIONS; + const allowedOrdersTypes = { + ...ORDERS_TYPE_OPTIONS, + ...(isSafetyPrivileged ? { SAFETY: 'Safety' } : {}), + ...(isBluebarkMoveSelected ? { BLUEBARK: 'BLUEBARK' } : {}), + }; const ordersTypeOptions = dropdownInputOptions(allowedOrdersTypes); + const getInitialOrdersType = () => { + if (isSafetyMoveSelected) { + return 'SAFETY'; + } + if (isBluebarkMoveSelected) { + return 'BLUEBARK'; + } + return ''; + }; + const initialValues = { - ordersType: isSafetyMoveSelected ? 'SAFETY' : '', + ordersType: getInitialOrdersType(), issueDate: '', reportByDate: '', hasDependents: '', @@ -128,13 +141,13 @@ const ServicesCounselingAddOrders = ({ userPrivileges, canAddOrders, setCanAddOr initialValues={initialValues} onBack={handleBack} isSafetyMoveSelected={isSafetyMoveSelected} + isBluebarkMoveSelected={isBluebarkMoveSelected} /> ); }; - const mapStateToProps = (state) => { const canAddOrders = selectCanAddOrders(state);