From 4ec32e80146a061d846ae88d86afa1c62226f93f Mon Sep 17 00:00:00 2001 From: pambecker Date: Tue, 1 Oct 2024 21:30:25 +0000 Subject: [PATCH 01/25] cancel move for SC and TOO --- pkg/gen/ghcapi/embedded_spec.go | 18 ++- .../move/move_canceler_responses.go | 2 +- pkg/gen/ghcmessages/p_p_m_status.go | 6 +- pkg/handlers/authentication/permissions.go | 2 + .../CancelMoveButton/CancelMoveButton.jsx | 27 ++++ .../CancelMoveButton.module.scss | 25 ++++ .../CancelMoveButton.stories.jsx | 15 +++ .../CancelMoveButton.test.jsx | 36 ++++++ .../CancelMoveModal/CancelMoveModal.jsx | 115 ++++++++++++++++++ .../CancelMoveModal.module.scss | 24 ++++ .../CancelMoveModal.stories.jsx | 11 ++ .../CancelMoveModal/CancelMoveModal.test.jsx | 35 ++++++ src/constants/permissions.js | 1 + src/constants/queues.js | 2 +- src/pages/Office/MoveDetails/MoveDetails.jsx | 28 +++++ .../ServicesCounselingMoveDetails.jsx | 31 ++++- .../ServicesCounselingMoveDetails.module.scss | 5 + .../Office/TXOMoveInfo/TXOTab.module.scss | 5 + swagger-def/ghc.yaml | 6 +- swagger/ghc.yaml | 6 +- 20 files changed, 383 insertions(+), 17 deletions(-) create mode 100644 src/components/Office/CancelMoveButton/CancelMoveButton.jsx create mode 100644 src/components/Office/CancelMoveButton/CancelMoveButton.module.scss create mode 100644 src/components/Office/CancelMoveButton/CancelMoveButton.stories.jsx create mode 100644 src/components/Office/CancelMoveButton/CancelMoveButton.test.jsx create mode 100644 src/components/Office/CancelMoveModal/CancelMoveModal.jsx create mode 100644 src/components/Office/CancelMoveModal/CancelMoveModal.module.scss create mode 100644 src/components/Office/CancelMoveModal/CancelMoveModal.stories.jsx create mode 100644 src/components/Office/CancelMoveModal/CancelMoveModal.test.jsx diff --git a/pkg/gen/ghcapi/embedded_spec.go b/pkg/gen/ghcapi/embedded_spec.go index 08604aa541a..b58b06d7b11 100644 --- a/pkg/gen/ghcapi/embedded_spec.go +++ b/pkg/gen/ghcapi/embedded_spec.go @@ -2351,7 +2351,7 @@ func init() { "operationId": "moveCanceler", "responses": { "200": { - "description": "Successfully cancelled move", + "description": "Successfully canceled move", "schema": { "$ref": "#/definitions/Move" } @@ -2374,7 +2374,10 @@ func init() { "500": { "$ref": "#/responses/ServerError" } - } + }, + "x-permissions": [ + "update.cancelMoveFlag" + ] }, "parameters": [ { @@ -11223,7 +11226,7 @@ func init() { "PPMStatus": { "type": "string", "enum": [ - "CANCELLED", + "CANCELED", "DRAFT", "SUBMITTED", "WAITING_ON_CUSTOMER", @@ -17124,7 +17127,7 @@ func init() { "operationId": "moveCanceler", "responses": { "200": { - "description": "Successfully cancelled move", + "description": "Successfully canceled move", "schema": { "$ref": "#/definitions/Move" } @@ -17165,7 +17168,10 @@ func init() { "$ref": "#/definitions/Error" } } - } + }, + "x-permissions": [ + "update.cancelMoveFlag" + ] }, "parameters": [ { @@ -26950,7 +26956,7 @@ func init() { "PPMStatus": { "type": "string", "enum": [ - "CANCELLED", + "CANCELED", "DRAFT", "SUBMITTED", "WAITING_ON_CUSTOMER", diff --git a/pkg/gen/ghcapi/ghcoperations/move/move_canceler_responses.go b/pkg/gen/ghcapi/ghcoperations/move/move_canceler_responses.go index 828a8086069..d96b78fc5af 100644 --- a/pkg/gen/ghcapi/ghcoperations/move/move_canceler_responses.go +++ b/pkg/gen/ghcapi/ghcoperations/move/move_canceler_responses.go @@ -17,7 +17,7 @@ import ( const MoveCancelerOKCode int = 200 /* -MoveCancelerOK Successfully cancelled move +MoveCancelerOK Successfully canceled move swagger:response moveCancelerOK */ diff --git a/pkg/gen/ghcmessages/p_p_m_status.go b/pkg/gen/ghcmessages/p_p_m_status.go index a581261623a..720b370a8d3 100644 --- a/pkg/gen/ghcmessages/p_p_m_status.go +++ b/pkg/gen/ghcmessages/p_p_m_status.go @@ -30,8 +30,8 @@ func (m PPMStatus) Pointer() *PPMStatus { const ( - // PPMStatusCANCELLED captures enum value "CANCELLED" - PPMStatusCANCELLED PPMStatus = "CANCELLED" + // PPMStatusCANCELED captures enum value "CANCELED" + PPMStatusCANCELED PPMStatus = "CANCELED" // PPMStatusDRAFT captures enum value "DRAFT" PPMStatusDRAFT PPMStatus = "DRAFT" @@ -60,7 +60,7 @@ var pPMStatusEnum []interface{} func init() { var res []PPMStatus - if err := json.Unmarshal([]byte(`["CANCELLED","DRAFT","SUBMITTED","WAITING_ON_CUSTOMER","NEEDS_ADVANCE_APPROVAL","NEEDS_CLOSEOUT","CLOSEOUT_COMPLETE","COMPLETED"]`), &res); err != nil { + if err := json.Unmarshal([]byte(`["CANCELED","DRAFT","SUBMITTED","WAITING_ON_CUSTOMER","NEEDS_ADVANCE_APPROVAL","NEEDS_CLOSEOUT","CLOSEOUT_COMPLETE","COMPLETED"]`), &res); err != nil { panic(err) } for _, v := range res { diff --git a/pkg/handlers/authentication/permissions.go b/pkg/handlers/authentication/permissions.go index 75efbb75cd0..ca2c9045bcb 100644 --- a/pkg/handlers/authentication/permissions.go +++ b/pkg/handlers/authentication/permissions.go @@ -40,6 +40,7 @@ var TOO = RolePermissions{ "update.closeoutOffice", "update.MTOPage", "create.TXOShipment", + "update.cancelMoveFlag", }, } @@ -86,6 +87,7 @@ var ServicesCounselor = RolePermissions{ "update.customer", "update.closeoutOffice", "view.closeoutOffice", + "update.cancelMoveFlag", }, } diff --git a/src/components/Office/CancelMoveButton/CancelMoveButton.jsx b/src/components/Office/CancelMoveButton/CancelMoveButton.jsx new file mode 100644 index 00000000000..c52d738a4ed --- /dev/null +++ b/src/components/Office/CancelMoveButton/CancelMoveButton.jsx @@ -0,0 +1,27 @@ +import React from 'react'; +import { PropTypes } from 'prop-types'; +import { Button } from '@trussworks/react-uswds'; +import classnames from 'classnames'; + +import styles from './CancelMoveButton.module.scss'; + +function CancelMoveButton({ onClick, isMoveLocked }) { + return ( +
+ +
+ ); +} + +CancelMoveButton.propTypes = { + onClick: PropTypes.func.isRequired, +}; + +export default CancelMoveButton; diff --git a/src/components/Office/CancelMoveButton/CancelMoveButton.module.scss b/src/components/Office/CancelMoveButton/CancelMoveButton.module.scss new file mode 100644 index 00000000000..651a2811aec --- /dev/null +++ b/src/components/Office/CancelMoveButton/CancelMoveButton.module.scss @@ -0,0 +1,25 @@ +@import 'shared/styles/basics'; +@import 'shared/styles/mixins'; +@import 'shared/styles/colors'; + +.CancelMoveButton { + @include u-padding-left(0); + float: right; +} + +.EditCancelMoveContainer { + display: flex; + align-content: baseline; + :global(.usa-button) { + width: auto; + } +} + +.EditCancelMoveButton { + @include u-padding-left(1); + @include u-padding-top(0); +} + +.CancelMoveTag { + background-color: $info-light !important; +} diff --git a/src/components/Office/CancelMoveButton/CancelMoveButton.stories.jsx b/src/components/Office/CancelMoveButton/CancelMoveButton.stories.jsx new file mode 100644 index 00000000000..0a0203f6a7a --- /dev/null +++ b/src/components/Office/CancelMoveButton/CancelMoveButton.stories.jsx @@ -0,0 +1,15 @@ +import React from 'react'; +import { action } from '@storybook/addon-actions'; + +import CancelMoveButton from './CancelMoveButton'; + +export default { + title: 'Office Components/CancelMoveButton', + component: CancelMoveButton, +}; + +export const MoveNotCanceled = () => ( +
+ +
+); diff --git a/src/components/Office/CancelMoveButton/CancelMoveButton.test.jsx b/src/components/Office/CancelMoveButton/CancelMoveButton.test.jsx new file mode 100644 index 00000000000..74a0113d6f9 --- /dev/null +++ b/src/components/Office/CancelMoveButton/CancelMoveButton.test.jsx @@ -0,0 +1,36 @@ +import React from 'react'; +import { render, waitFor, screen } from '@testing-library/react'; +import userEvent from '@testing-library/user-event'; + +import CancelMoveButton from './CancelMoveButton'; + +describe('CancelMoveButton', () => { + it('calls the onClick function when clicked', async () => { + const mockOnClick = jest.fn(); + render(); + const submitBtn = screen.getByText('Cancel move'); + + await userEvent.click(submitBtn); + + await waitFor(() => { + expect(mockOnClick).toHaveBeenCalled(); + }); + }); + + // it('displays a tag when a review has been requested', async () => { + // const mockOnClick = jest.fn(); + // render(); + // const tag = screen.getByTestId('tag'); + + // expect(tag).toHaveTextContent('Flagged for financial review'); + // }); + + it('disables the button when the move is locked', async () => { + const mockOnClick = jest.fn(); + const isMoveLocked = true; + render(); + const submitBtn = screen.getByText('Cancel move'); + + expect(submitBtn).toBeDisabled(); + }); +}); diff --git a/src/components/Office/CancelMoveModal/CancelMoveModal.jsx b/src/components/Office/CancelMoveModal/CancelMoveModal.jsx new file mode 100644 index 00000000000..228c5a6961a --- /dev/null +++ b/src/components/Office/CancelMoveModal/CancelMoveModal.jsx @@ -0,0 +1,115 @@ +import React from 'react'; +import classnames from 'classnames'; +import { Formik, Field } from 'formik'; +import PropTypes from 'prop-types'; +import * as Yup from 'yup'; +import { Button, Label, Textarea, Radio, FormGroup } from '@trussworks/react-uswds'; + +import styles from './CancelMoveModal.module.scss'; + +import { Form } from 'components/form'; +import { ModalContainer, Overlay } from 'components/MigratedModal/MigratedModal'; +import Modal, { ModalActions, ModalClose, ModalTitle } from 'components/Modal/Modal'; + +const financialReviewSchema = Yup.object().shape({ + remarks: Yup.string().when('flagForReview', { + is: 'yes', + then: (schema) => schema.test('remarks', 'Remarks are required', (value) => value?.length > 0), + }), + // must select yest or no before they can click save. + flagForReview: Yup.string().required('Required').oneOf(['yes', 'no']), +}); + +function CancelMoveModal({ onClose, onSubmit, initialRemarks, initialSelection }) { + return ( +
+ + + + + +

Does this move need financial review?

+
+
+ onSubmit(values.remarks, values.flagForReview)} + validateOnMount + > + {({ values, isValid }) => { + const { flagForReview } = values; + return ( +
+ +
+ Select Yes to flag this move for review from the service's financial + office. Enter remarks to give more detail. +
+
+ + +
+
+ + {/* Need to set remarks to nothing when no is selected */} + + + + + + + ); + }} +
+
+
+
+
+ ); +} + +CancelMoveModal.propTypes = { + onClose: PropTypes.func.isRequired, + onSubmit: PropTypes.func.isRequired, +}; + +export default CancelMoveModal; diff --git a/src/components/Office/CancelMoveModal/CancelMoveModal.module.scss b/src/components/Office/CancelMoveModal/CancelMoveModal.module.scss new file mode 100644 index 00000000000..4db124ece51 --- /dev/null +++ b/src/components/Office/CancelMoveModal/CancelMoveModal.module.scss @@ -0,0 +1,24 @@ +@import 'shared/styles/colors.scss'; +@import 'shared/styles/basics'; + +.CancelMoveModal { + overflow-y: auto; + max-height: 90vh; + max-width: 574px; + + .RemarksLabelDisabled { + color: color("base"); + } + + .RemarksField { + &:disabled { + background: color("base-lighter"); + color: color("base-lighter"); + border-color: color("base"); + } + } + + .CancelButton { + @include u-bg('transparent'); + } +} diff --git a/src/components/Office/CancelMoveModal/CancelMoveModal.stories.jsx b/src/components/Office/CancelMoveModal/CancelMoveModal.stories.jsx new file mode 100644 index 00000000000..74470f55427 --- /dev/null +++ b/src/components/Office/CancelMoveModal/CancelMoveModal.stories.jsx @@ -0,0 +1,11 @@ +import React from 'react'; +import { action } from '@storybook/addon-actions'; + +import CancelMoveModal from './CancelMoveModal'; + +export default { + title: 'Office Components/CancelMoveModal', + component: CancelMoveModal, +}; + +export const Basic = () => ; diff --git a/src/components/Office/CancelMoveModal/CancelMoveModal.test.jsx b/src/components/Office/CancelMoveModal/CancelMoveModal.test.jsx new file mode 100644 index 00000000000..b4063ef5f01 --- /dev/null +++ b/src/components/Office/CancelMoveModal/CancelMoveModal.test.jsx @@ -0,0 +1,35 @@ +import React from 'react'; +import { render, waitFor, screen } from '@testing-library/react'; +import userEvent from '@testing-library/user-event'; + +import CancelMoveModal from './CancelMoveModal'; + +describe('CancelMoveModal', () => { + it('calls onSubmit prop on approval with form values when validations pass', async () => { + const mockOnSubmit = jest.fn(); + render( {}} />); + const flagForReview = screen.getByLabelText('Yes'); + const remarksInput = screen.getByLabelText('Remarks for financial office'); + const submitBtn = screen.getByRole('button', { name: 'Save' }); + + await userEvent.click(flagForReview); + await userEvent.type(remarksInput, 'Because I said so...'); + await userEvent.click(submitBtn); + + await waitFor(() => { + expect(mockOnSubmit).toHaveBeenCalled(); + }); + }); + + it('calls onclose prop on modal close', async () => { + const mockClose = jest.fn(); + render( {}} onClose={mockClose} />); + const closeBtn = screen.getByText('Cancel'); + + await userEvent.click(closeBtn); + + await waitFor(() => { + expect(mockClose).toHaveBeenCalled(); + }); + }); +}); diff --git a/src/constants/permissions.js b/src/constants/permissions.js index ee37417f4bf..0fa8547afef 100644 --- a/src/constants/permissions.js +++ b/src/constants/permissions.js @@ -22,4 +22,5 @@ export const permissionTypes = { updateCustomer: 'update.customer', createTxoShipment: 'create.TXOShipment', createSupportingDocuments: 'create.supportingDocuments', + cancelMoveFlag: 'update.cancelMoveFlag', }; diff --git a/src/constants/queues.js b/src/constants/queues.js index 17a6e9d4066..ef794ec1eb7 100644 --- a/src/constants/queues.js +++ b/src/constants/queues.js @@ -62,7 +62,7 @@ export const SERVICE_COUNSELING_PPM_STATUS_OPTIONS = [ ]; export const SERVICE_COUNSELING_PPM_STATUS_LABELS = { - CANCELLED: 'Cancelled', + CANCELED: 'Canceled', DRAFT: 'Draft', SUBMITTED: 'Submitted', WAITING_ON_CUSTOMER: 'Waiting on customer', diff --git a/src/pages/Office/MoveDetails/MoveDetails.jsx b/src/pages/Office/MoveDetails/MoveDetails.jsx index e2fb69d7450..27c61d527d8 100644 --- a/src/pages/Office/MoveDetails/MoveDetails.jsx +++ b/src/pages/Office/MoveDetails/MoveDetails.jsx @@ -20,6 +20,8 @@ import OrdersList from 'components/Office/DefinitionLists/OrdersList'; import DetailsPanel from 'components/Office/DetailsPanel/DetailsPanel'; import FinancialReviewButton from 'components/Office/FinancialReviewButton/FinancialReviewButton'; import FinancialReviewModal from 'components/Office/FinancialReviewModal/FinancialReviewModal'; +import CancelMoveButton from 'components/Office/CancelMoveButton/CancelMoveButton'; +import CancelMoveModal from 'components/Office/CancelMoveModal/CancelMoveModal'; import ApprovedRequestedShipments from 'components/Office/RequestedShipments/ApprovedRequestedShipments'; import SubmittedRequestedShipments from 'components/Office/RequestedShipments/SubmittedRequestedShipments'; import { useMoveDetailsQueries } from 'hooks/queries'; @@ -63,6 +65,7 @@ const MoveDetails = ({ }) => { const { moveCode } = useParams(); const [isFinancialModalVisible, setIsFinancialModalVisible] = useState(false); + const [isCancelMoveModalVisible, setIsCancelMoveModalVisible] = useState(false); const [shipmentMissingRequiredInformation, setShipmentMissingRequiredInformation] = useState(false); const [alertMessage, setAlertMessage] = useState(null); const [alertType, setAlertType] = useState('success'); @@ -143,6 +146,23 @@ const MoveDetails = ({ const handleCancelFinancialReviewModal = () => { setIsFinancialModalVisible(false); }; + + const handleShowCancelMoveModal = () => { + setIsCancelMoveModalVisible(true); + }; + + const handleSubmitCancelMoveModal = () => { + mutateFinancialReview({ + moveID: move.id, + ifMatchETag: move.eTag, + }); + setIsCancelMoveModalVisible(false); + }; + + const handleCloseCancelMoveModal = () => { + setIsCancelMoveModalVisible(false); + }; + const submittedShipments = mtoShipments?.filter( (shipment) => shipment.status === shipmentStatuses.SUBMITTED && !shipment.deletedAt, ); @@ -415,6 +435,14 @@ const MoveDetails = ({ )} + +
+ +
+
+ {isCancelMoveModalVisible && ( + + )} {submittedShipments?.length > 0 && (
; if (isError) return ; - const handleShowCancellationModal = () => { + const handleShowSubmitMoveModal = () => { setIsSubmitModalVisible(true); }; @@ -469,6 +472,22 @@ const ServicesCounselingMoveDetails = ({ setIsFinancialModalVisible(false); }; + const handleShowCancelMoveModal = () => { + setIsCancelMoveModalVisible(true); + }; + + const handleSubmitCancelMoveModal = () => { + mutateFinancialReview({ + moveID: move.id, + ifMatchETag: move.eTag, + }); + setIsCancelMoveModalVisible(false); + }; + + const handleCloseCancelMoveModal = () => { + setIsCancelMoveModalVisible(false); + }; + const counselorCanEditOrdersAndAllowances = () => { if (counselorCanEdit || counselorCanEditNonPPM) return true; if ( @@ -525,6 +544,9 @@ const ServicesCounselingMoveDetails = ({ initialSelection={move?.financialReviewFlag} /> )} + {isCancelMoveModalVisible && ( + + )} @@ -564,7 +586,7 @@ const ServicesCounselingMoveDetails = ({ isMoveLocked } type="button" - onClick={handleShowCancellationModal} + onClick={handleShowSubmitMoveModal} > Submit move details @@ -572,6 +594,11 @@ const ServicesCounselingMoveDetails = ({
)} + +
+ +
+
{hasInvalidProGearAllowances ? ( diff --git a/src/pages/Office/ServicesCounselingMoveDetails/ServicesCounselingMoveDetails.module.scss b/src/pages/Office/ServicesCounselingMoveDetails/ServicesCounselingMoveDetails.module.scss index 5e7a5add39d..69b70dec2b6 100644 --- a/src/pages/Office/ServicesCounselingMoveDetails/ServicesCounselingMoveDetails.module.scss +++ b/src/pages/Office/ServicesCounselingMoveDetails/ServicesCounselingMoveDetails.module.scss @@ -28,6 +28,11 @@ @include u-margin-bottom(3); } + .scCancelMoveContainer { + @include u-margin-bottom(3); + align-self: right; + } + .alertContainer { @include u-margin-bottom(4); } diff --git a/src/pages/Office/TXOMoveInfo/TXOTab.module.scss b/src/pages/Office/TXOMoveInfo/TXOTab.module.scss index 5b3f7f1fe11..2078723d0e4 100644 --- a/src/pages/Office/TXOMoveInfo/TXOTab.module.scss +++ b/src/pages/Office/TXOMoveInfo/TXOTab.module.scss @@ -38,6 +38,11 @@ @include u-margin-bottom(0); } + .tooCancelMoveContainer { + @include u-margin-bottom(3); + align-self: right; + } + .gridContainer { .shipmentCard { @include u-padding-left(4); diff --git a/swagger-def/ghc.yaml b/swagger-def/ghc.yaml index 05e5799aa1d..5d59185e949 100644 --- a/swagger-def/ghc.yaml +++ b/swagger-def/ghc.yaml @@ -384,7 +384,7 @@ paths: parameters: [] responses: '200': - description: Successfully cancelled move + description: Successfully canceled move schema: $ref: '#/definitions/Move' '403': @@ -404,6 +404,8 @@ paths: description: cancels a move operationId: moveCanceler summary: Cancels a move + x-permissions: + - update.cancelMoveFlag '/counseling/orders/{orderID}': parameters: - description: ID of order to update @@ -5136,7 +5138,7 @@ definitions: PPMStatus: type: string enum: - - CANCELLED + - CANCELED - DRAFT - SUBMITTED - WAITING_ON_CUSTOMER diff --git a/swagger/ghc.yaml b/swagger/ghc.yaml index cdda0e5ea44..f3a274f1b9d 100644 --- a/swagger/ghc.yaml +++ b/swagger/ghc.yaml @@ -422,7 +422,7 @@ paths: parameters: [] responses: '200': - description: Successfully cancelled move + description: Successfully canceled move schema: $ref: '#/definitions/Move' '403': @@ -442,6 +442,8 @@ paths: description: cancels a move operationId: moveCanceler summary: Cancels a move + x-permissions: + - update.cancelMoveFlag /counseling/orders/{orderID}: parameters: - description: ID of order to update @@ -5357,7 +5359,7 @@ definitions: PPMStatus: type: string enum: - - CANCELLED + - CANCELED - DRAFT - SUBMITTED - WAITING_ON_CUSTOMER From 249bdb7dbfadebf93fac249e64782f6b6159c593 Mon Sep 17 00:00:00 2001 From: pambecker Date: Fri, 4 Oct 2024 16:30:30 +0000 Subject: [PATCH 02/25] updates to button and modal --- .../CancelMoveConfirmationModal.jsx | 47 +++++++ .../CancelMoveConfirmationModal.stories.jsx | 33 +++++ .../CancelMoveConfirmationModal.test.jsx | 53 ++++++++ .../CancelMoveButton/CancelMoveButton.jsx | 27 ---- .../CancelMoveButton.module.scss | 25 ---- .../CancelMoveButton.stories.jsx | 15 --- .../CancelMoveButton.test.jsx | 36 ------ .../CancelMoveModal/CancelMoveModal.jsx | 115 ------------------ .../CancelMoveModal.module.scss | 24 ---- .../CancelMoveModal.stories.jsx | 11 -- .../CancelMoveModal/CancelMoveModal.test.jsx | 35 ------ .../EvaluationReportShipmentDisplay.jsx | 2 +- .../ShipmentDisplay/ShipmentDisplay.jsx | 2 +- .../ShipmentHeading/ShipmentHeading.jsx | 2 +- src/pages/Office/MoveDetails/MoveDetails.jsx | 67 +++++----- .../ServicesCounselingMoveDetails.jsx | 29 +++-- .../ServicesCounselingMoveDetails.module.scss | 5 +- .../Office/TXOMoveInfo/TXOTab.module.scss | 4 +- 18 files changed, 196 insertions(+), 336 deletions(-) create mode 100644 src/components/ConfirmationModals/CancelMoveConfirmationModal.jsx create mode 100644 src/components/ConfirmationModals/CancelMoveConfirmationModal.stories.jsx create mode 100644 src/components/ConfirmationModals/CancelMoveConfirmationModal.test.jsx delete mode 100644 src/components/Office/CancelMoveButton/CancelMoveButton.jsx delete mode 100644 src/components/Office/CancelMoveButton/CancelMoveButton.module.scss delete mode 100644 src/components/Office/CancelMoveButton/CancelMoveButton.stories.jsx delete mode 100644 src/components/Office/CancelMoveButton/CancelMoveButton.test.jsx delete mode 100644 src/components/Office/CancelMoveModal/CancelMoveModal.jsx delete mode 100644 src/components/Office/CancelMoveModal/CancelMoveModal.module.scss delete mode 100644 src/components/Office/CancelMoveModal/CancelMoveModal.stories.jsx delete mode 100644 src/components/Office/CancelMoveModal/CancelMoveModal.test.jsx diff --git a/src/components/ConfirmationModals/CancelMoveConfirmationModal.jsx b/src/components/ConfirmationModals/CancelMoveConfirmationModal.jsx new file mode 100644 index 00000000000..a9f7df6abf5 --- /dev/null +++ b/src/components/ConfirmationModals/CancelMoveConfirmationModal.jsx @@ -0,0 +1,47 @@ +import React from 'react'; +import PropTypes from 'prop-types'; +import { Button } from '@trussworks/react-uswds'; + +import Modal, { ModalTitle, ModalClose, ModalActions, connectModal } from 'components/Modal/Modal'; + +export const CancelMoveConfirmationModal = ({ onClose, onSubmit, moveID, title, content, submitText, closeText }) => ( + + onClose()} /> + +

{title}

+
+

{content}

+ + + + +
+); + +CancelMoveConfirmationModal.propTypes = { + onClose: PropTypes.func.isRequired, + onSubmit: PropTypes.func.isRequired, + + moveID: PropTypes.string.isRequired, + + title: PropTypes.string, + content: PropTypes.string, + submitText: PropTypes.string, + closeText: PropTypes.string, +}; + +CancelMoveConfirmationModal.defaultProps = { + title: 'Are you sure?', + content: + 'You’ll lose all the information in this move. If you want it back later, you’ll have to request a new move.', + submitText: 'Cancel move', + closeText: 'Keep move', +}; + +CancelMoveConfirmationModal.displayName = 'CancelMoveConfirmationModal'; + +export default connectModal(CancelMoveConfirmationModal); diff --git a/src/components/ConfirmationModals/CancelMoveConfirmationModal.stories.jsx b/src/components/ConfirmationModals/CancelMoveConfirmationModal.stories.jsx new file mode 100644 index 00000000000..15205131faa --- /dev/null +++ b/src/components/ConfirmationModals/CancelMoveConfirmationModal.stories.jsx @@ -0,0 +1,33 @@ +import React from 'react'; + +import CancelMoveConfirmationModal from './CancelMoveConfirmationModal'; + +export default { + title: 'Components/CancelMoveConfirmationModal', + component: CancelMoveConfirmationModal, + args: { + moveID: '111', + }, + argTypes: { + onClose: { action: 'close button clicked' }, + onSubmit: { action: 'submit button clicked' }, + }, +}; + +const Template = (args) => ; + +export const Basic = Template.bind({}); + +export const WithOverrides = Template.bind({}); +WithOverrides.args = { + title: 'This is a sample title', + content: 'Some sample description', + submitText: 'YES!', + closeText: 'NO', +}; + +const ConnectedTemplate = (args) => ; +export const ConnectedModal = ConnectedTemplate.bind({}); +ConnectedModal.args = { + isOpen: true, +}; diff --git a/src/components/ConfirmationModals/CancelMoveConfirmationModal.test.jsx b/src/components/ConfirmationModals/CancelMoveConfirmationModal.test.jsx new file mode 100644 index 00000000000..a1f07ae0f12 --- /dev/null +++ b/src/components/ConfirmationModals/CancelMoveConfirmationModal.test.jsx @@ -0,0 +1,53 @@ +import React from 'react'; +import { render, screen } from '@testing-library/react'; +import userEvent from '@testing-library/user-event'; + +import { CancelMoveConfirmationModal } from 'components/ConfirmationModals/CancelMoveConfirmationModal'; + +let onClose; +let onSubmit; +beforeEach(() => { + onClose = jest.fn(); + onSubmit = jest.fn(); +}); + +describe('CancelMoveConfirmationModal', () => { + const moveID = '123456'; + + it('renders the component', async () => { + render(); + + expect(await screen.findByRole('heading', { level: 3, name: 'Are you sure?' })).toBeInTheDocument(); + }); + + it('closes the modal when close icon is clicked', async () => { + render(); + + const closeButton = await screen.findByTestId('modalCloseButton'); + + await userEvent.click(closeButton); + + expect(onClose).toHaveBeenCalledTimes(1); + }); + + it('closes the modal when the keep button is clicked', async () => { + render(); + + const keepButton = await screen.findByRole('button', { name: 'Keep shipment' }); + + await userEvent.click(keepButton); + + expect(onClose).toHaveBeenCalledTimes(1); + }); + + it('calls the submit function when cancel button is clicked', async () => { + render(); + + const cancelButton = await screen.findByRole('button', { name: 'Cancel move' }); + + await userEvent.click(cancelButton); + + expect(onSubmit).toHaveBeenCalledWith(moveID); + expect(onSubmit).toHaveBeenCalledTimes(1); + }); +}); diff --git a/src/components/Office/CancelMoveButton/CancelMoveButton.jsx b/src/components/Office/CancelMoveButton/CancelMoveButton.jsx deleted file mode 100644 index c52d738a4ed..00000000000 --- a/src/components/Office/CancelMoveButton/CancelMoveButton.jsx +++ /dev/null @@ -1,27 +0,0 @@ -import React from 'react'; -import { PropTypes } from 'prop-types'; -import { Button } from '@trussworks/react-uswds'; -import classnames from 'classnames'; - -import styles from './CancelMoveButton.module.scss'; - -function CancelMoveButton({ onClick, isMoveLocked }) { - return ( -
- -
- ); -} - -CancelMoveButton.propTypes = { - onClick: PropTypes.func.isRequired, -}; - -export default CancelMoveButton; diff --git a/src/components/Office/CancelMoveButton/CancelMoveButton.module.scss b/src/components/Office/CancelMoveButton/CancelMoveButton.module.scss deleted file mode 100644 index 651a2811aec..00000000000 --- a/src/components/Office/CancelMoveButton/CancelMoveButton.module.scss +++ /dev/null @@ -1,25 +0,0 @@ -@import 'shared/styles/basics'; -@import 'shared/styles/mixins'; -@import 'shared/styles/colors'; - -.CancelMoveButton { - @include u-padding-left(0); - float: right; -} - -.EditCancelMoveContainer { - display: flex; - align-content: baseline; - :global(.usa-button) { - width: auto; - } -} - -.EditCancelMoveButton { - @include u-padding-left(1); - @include u-padding-top(0); -} - -.CancelMoveTag { - background-color: $info-light !important; -} diff --git a/src/components/Office/CancelMoveButton/CancelMoveButton.stories.jsx b/src/components/Office/CancelMoveButton/CancelMoveButton.stories.jsx deleted file mode 100644 index 0a0203f6a7a..00000000000 --- a/src/components/Office/CancelMoveButton/CancelMoveButton.stories.jsx +++ /dev/null @@ -1,15 +0,0 @@ -import React from 'react'; -import { action } from '@storybook/addon-actions'; - -import CancelMoveButton from './CancelMoveButton'; - -export default { - title: 'Office Components/CancelMoveButton', - component: CancelMoveButton, -}; - -export const MoveNotCanceled = () => ( -
- -
-); diff --git a/src/components/Office/CancelMoveButton/CancelMoveButton.test.jsx b/src/components/Office/CancelMoveButton/CancelMoveButton.test.jsx deleted file mode 100644 index 74a0113d6f9..00000000000 --- a/src/components/Office/CancelMoveButton/CancelMoveButton.test.jsx +++ /dev/null @@ -1,36 +0,0 @@ -import React from 'react'; -import { render, waitFor, screen } from '@testing-library/react'; -import userEvent from '@testing-library/user-event'; - -import CancelMoveButton from './CancelMoveButton'; - -describe('CancelMoveButton', () => { - it('calls the onClick function when clicked', async () => { - const mockOnClick = jest.fn(); - render(); - const submitBtn = screen.getByText('Cancel move'); - - await userEvent.click(submitBtn); - - await waitFor(() => { - expect(mockOnClick).toHaveBeenCalled(); - }); - }); - - // it('displays a tag when a review has been requested', async () => { - // const mockOnClick = jest.fn(); - // render(); - // const tag = screen.getByTestId('tag'); - - // expect(tag).toHaveTextContent('Flagged for financial review'); - // }); - - it('disables the button when the move is locked', async () => { - const mockOnClick = jest.fn(); - const isMoveLocked = true; - render(); - const submitBtn = screen.getByText('Cancel move'); - - expect(submitBtn).toBeDisabled(); - }); -}); diff --git a/src/components/Office/CancelMoveModal/CancelMoveModal.jsx b/src/components/Office/CancelMoveModal/CancelMoveModal.jsx deleted file mode 100644 index 228c5a6961a..00000000000 --- a/src/components/Office/CancelMoveModal/CancelMoveModal.jsx +++ /dev/null @@ -1,115 +0,0 @@ -import React from 'react'; -import classnames from 'classnames'; -import { Formik, Field } from 'formik'; -import PropTypes from 'prop-types'; -import * as Yup from 'yup'; -import { Button, Label, Textarea, Radio, FormGroup } from '@trussworks/react-uswds'; - -import styles from './CancelMoveModal.module.scss'; - -import { Form } from 'components/form'; -import { ModalContainer, Overlay } from 'components/MigratedModal/MigratedModal'; -import Modal, { ModalActions, ModalClose, ModalTitle } from 'components/Modal/Modal'; - -const financialReviewSchema = Yup.object().shape({ - remarks: Yup.string().when('flagForReview', { - is: 'yes', - then: (schema) => schema.test('remarks', 'Remarks are required', (value) => value?.length > 0), - }), - // must select yest or no before they can click save. - flagForReview: Yup.string().required('Required').oneOf(['yes', 'no']), -}); - -function CancelMoveModal({ onClose, onSubmit, initialRemarks, initialSelection }) { - return ( -
- - - - - -

Does this move need financial review?

-
-
- onSubmit(values.remarks, values.flagForReview)} - validateOnMount - > - {({ values, isValid }) => { - const { flagForReview } = values; - return ( -
- -
- Select Yes to flag this move for review from the service's financial - office. Enter remarks to give more detail. -
-
- - -
-
- - {/* Need to set remarks to nothing when no is selected */} - - - - - - - ); - }} -
-
-
-
-
- ); -} - -CancelMoveModal.propTypes = { - onClose: PropTypes.func.isRequired, - onSubmit: PropTypes.func.isRequired, -}; - -export default CancelMoveModal; diff --git a/src/components/Office/CancelMoveModal/CancelMoveModal.module.scss b/src/components/Office/CancelMoveModal/CancelMoveModal.module.scss deleted file mode 100644 index 4db124ece51..00000000000 --- a/src/components/Office/CancelMoveModal/CancelMoveModal.module.scss +++ /dev/null @@ -1,24 +0,0 @@ -@import 'shared/styles/colors.scss'; -@import 'shared/styles/basics'; - -.CancelMoveModal { - overflow-y: auto; - max-height: 90vh; - max-width: 574px; - - .RemarksLabelDisabled { - color: color("base"); - } - - .RemarksField { - &:disabled { - background: color("base-lighter"); - color: color("base-lighter"); - border-color: color("base"); - } - } - - .CancelButton { - @include u-bg('transparent'); - } -} diff --git a/src/components/Office/CancelMoveModal/CancelMoveModal.stories.jsx b/src/components/Office/CancelMoveModal/CancelMoveModal.stories.jsx deleted file mode 100644 index 74470f55427..00000000000 --- a/src/components/Office/CancelMoveModal/CancelMoveModal.stories.jsx +++ /dev/null @@ -1,11 +0,0 @@ -import React from 'react'; -import { action } from '@storybook/addon-actions'; - -import CancelMoveModal from './CancelMoveModal'; - -export default { - title: 'Office Components/CancelMoveModal', - component: CancelMoveModal, -}; - -export const Basic = () => ; diff --git a/src/components/Office/CancelMoveModal/CancelMoveModal.test.jsx b/src/components/Office/CancelMoveModal/CancelMoveModal.test.jsx deleted file mode 100644 index b4063ef5f01..00000000000 --- a/src/components/Office/CancelMoveModal/CancelMoveModal.test.jsx +++ /dev/null @@ -1,35 +0,0 @@ -import React from 'react'; -import { render, waitFor, screen } from '@testing-library/react'; -import userEvent from '@testing-library/user-event'; - -import CancelMoveModal from './CancelMoveModal'; - -describe('CancelMoveModal', () => { - it('calls onSubmit prop on approval with form values when validations pass', async () => { - const mockOnSubmit = jest.fn(); - render( {}} />); - const flagForReview = screen.getByLabelText('Yes'); - const remarksInput = screen.getByLabelText('Remarks for financial office'); - const submitBtn = screen.getByRole('button', { name: 'Save' }); - - await userEvent.click(flagForReview); - await userEvent.type(remarksInput, 'Because I said so...'); - await userEvent.click(submitBtn); - - await waitFor(() => { - expect(mockOnSubmit).toHaveBeenCalled(); - }); - }); - - it('calls onclose prop on modal close', async () => { - const mockClose = jest.fn(); - render( {}} onClose={mockClose} />); - const closeBtn = screen.getByText('Cancel'); - - await userEvent.click(closeBtn); - - await waitFor(() => { - expect(mockClose).toHaveBeenCalled(); - }); - }); -}); diff --git a/src/components/Office/EvaluationReportShipmentDisplay/EvaluationReportShipmentDisplay.jsx b/src/components/Office/EvaluationReportShipmentDisplay/EvaluationReportShipmentDisplay.jsx index b13f4b0f6c6..e562a3d8521 100644 --- a/src/components/Office/EvaluationReportShipmentDisplay/EvaluationReportShipmentDisplay.jsx +++ b/src/components/Office/EvaluationReportShipmentDisplay/EvaluationReportShipmentDisplay.jsx @@ -54,7 +54,7 @@ const EvaluationReportShipmentDisplay = ({ {displayInfo.isDiversion && diversion} - {displayInfo.shipmentStatus === shipmentStatuses.CANCELED && cancelled} + {displayInfo.shipmentStatus === shipmentStatuses.CANCELED && canceled} {displayInfo.shipmentStatus === shipmentStatuses.DIVERSION_REQUESTED && diversion requested} {displayInfo.shipmentStatus === shipmentStatuses.CANCELLATION_REQUESTED && ( cancellation requested diff --git a/src/components/Office/ShipmentDisplay/ShipmentDisplay.jsx b/src/components/Office/ShipmentDisplay/ShipmentDisplay.jsx index d4827aefa74..44d9e5bbe97 100644 --- a/src/components/Office/ShipmentDisplay/ShipmentDisplay.jsx +++ b/src/components/Office/ShipmentDisplay/ShipmentDisplay.jsx @@ -95,7 +95,7 @@ const ShipmentDisplay = ({
{displayInfo.isDiversion && diversion} {displayInfo.shipmentStatus === shipmentStatuses.CANCELED && ( - cancelled + canceled )} {displayInfo.shipmentStatus === shipmentStatuses.DIVERSION_REQUESTED && diversion requested} {displayInfo.shipmentStatus === shipmentStatuses.CANCELLATION_REQUESTED && ( diff --git a/src/components/Office/ShipmentHeading/ShipmentHeading.jsx b/src/components/Office/ShipmentHeading/ShipmentHeading.jsx index cf01b46dd85..27ebdd71dc3 100644 --- a/src/components/Office/ShipmentHeading/ShipmentHeading.jsx +++ b/src/components/Office/ShipmentHeading/ShipmentHeading.jsx @@ -22,7 +22,7 @@ function ShipmentHeading({ shipmentInfo, handleShowCancellationModal, isMoveLock

{shipmentInfo.shipmentType}

- {shipmentStatus === shipmentStatuses.CANCELED && cancelled} + {shipmentStatus === shipmentStatuses.CANCELED && canceled} {shipmentInfo.isDiversion && diversion} {!shipmentInfo.isDiversion && shipmentStatus === shipmentStatuses.DIVERSION_REQUESTED && ( diversion requested diff --git a/src/pages/Office/MoveDetails/MoveDetails.jsx b/src/pages/Office/MoveDetails/MoveDetails.jsx index 27c61d527d8..89e86792047 100644 --- a/src/pages/Office/MoveDetails/MoveDetails.jsx +++ b/src/pages/Office/MoveDetails/MoveDetails.jsx @@ -1,6 +1,6 @@ import React, { useEffect, useMemo, useState } from 'react'; import { generatePath, Link, useNavigate, useParams } from 'react-router-dom'; -import { Alert, Grid, GridContainer } from '@trussworks/react-uswds'; +import { Alert, Grid, GridContainer, Button } from '@trussworks/react-uswds'; import { FontAwesomeIcon } from '@fortawesome/react-fontawesome'; import { useQueryClient, useMutation } from '@tanstack/react-query'; import { func } from 'prop-types'; @@ -20,8 +20,7 @@ import OrdersList from 'components/Office/DefinitionLists/OrdersList'; import DetailsPanel from 'components/Office/DetailsPanel/DetailsPanel'; import FinancialReviewButton from 'components/Office/FinancialReviewButton/FinancialReviewButton'; import FinancialReviewModal from 'components/Office/FinancialReviewModal/FinancialReviewModal'; -import CancelMoveButton from 'components/Office/CancelMoveButton/CancelMoveButton'; -import CancelMoveModal from 'components/Office/CancelMoveModal/CancelMoveModal'; +import CancelMoveConfirmationModal from 'components/ConfirmationModals/CancelMoveConfirmationModal'; import ApprovedRequestedShipments from 'components/Office/RequestedShipments/ApprovedRequestedShipments'; import SubmittedRequestedShipments from 'components/Office/RequestedShipments/SubmittedRequestedShipments'; import { useMoveDetailsQueries } from 'hooks/queries'; @@ -147,12 +146,12 @@ const MoveDetails = ({ setIsFinancialModalVisible(false); }; - const handleShowCancelMoveModal = () => { + const showCancelMoveModal = () => { setIsCancelMoveModalVisible(true); }; - const handleSubmitCancelMoveModal = () => { - mutateFinancialReview({ + const handleCancelMove = () => { + mutateMoveStatus({ moveID: move.id, ifMatchETag: move.eTag, }); @@ -416,32 +415,40 @@ const MoveDetails = ({ )} - {!isMoveLocked && ( - - - - - - - - + + {!isMoveLocked && ( + + + + + + + + + + )} + +
+ +
- )} - -
- -
-
+
{isCancelMoveModalVisible && ( - + )} {submittedShipments?.length > 0 && (
diff --git a/src/pages/Office/ServicesCounselingMoveDetails/ServicesCounselingMoveDetails.jsx b/src/pages/Office/ServicesCounselingMoveDetails/ServicesCounselingMoveDetails.jsx index 7bdc58cb7fa..9b466dfc7e4 100644 --- a/src/pages/Office/ServicesCounselingMoveDetails/ServicesCounselingMoveDetails.jsx +++ b/src/pages/Office/ServicesCounselingMoveDetails/ServicesCounselingMoveDetails.jsx @@ -19,8 +19,7 @@ import OrdersList from 'components/Office/DefinitionLists/OrdersList'; import DetailsPanel from 'components/Office/DetailsPanel/DetailsPanel'; import FinancialReviewButton from 'components/Office/FinancialReviewButton/FinancialReviewButton'; import FinancialReviewModal from 'components/Office/FinancialReviewModal/FinancialReviewModal'; -import CancelMoveButton from 'components/Office/CancelMoveButton/CancelMoveButton'; -import CancelMoveModal from 'components/Office/CancelMoveModal/CancelMoveModal'; +import CancelMoveConfirmationModal from 'components/ConfirmationModals/CancelMoveConfirmationModal'; import ShipmentDisplay from 'components/Office/ShipmentDisplay/ShipmentDisplay'; import { SubmitMoveConfirmationModal } from 'components/Office/SubmitMoveConfirmationModal/SubmitMoveConfirmationModal'; import { useMoveDetailsQueries, useOrdersDocumentQueries } from 'hooks/queries'; @@ -472,12 +471,12 @@ const ServicesCounselingMoveDetails = ({ setIsFinancialModalVisible(false); }; - const handleShowCancelMoveModal = () => { + const showCancelMoveModal = () => { setIsCancelMoveModalVisible(true); }; - const handleSubmitCancelMoveModal = () => { - mutateFinancialReview({ + const handleCancelMove = () => { + mutateMoveStatus({ moveID: move.id, ifMatchETag: move.eTag, }); @@ -545,7 +544,11 @@ const ServicesCounselingMoveDetails = ({ /> )} {isCancelMoveModalVisible && ( - + )} @@ -594,11 +597,15 @@ const ServicesCounselingMoveDetails = ({
)} - -
- -
-
+ + +
+ +
+
+
{hasInvalidProGearAllowances ? ( diff --git a/src/pages/Office/ServicesCounselingMoveDetails/ServicesCounselingMoveDetails.module.scss b/src/pages/Office/ServicesCounselingMoveDetails/ServicesCounselingMoveDetails.module.scss index 69b70dec2b6..4e7038f9271 100644 --- a/src/pages/Office/ServicesCounselingMoveDetails/ServicesCounselingMoveDetails.module.scss +++ b/src/pages/Office/ServicesCounselingMoveDetails/ServicesCounselingMoveDetails.module.scss @@ -29,8 +29,9 @@ } .scCancelMoveContainer { - @include u-margin-bottom(3); - align-self: right; + @include u-margin-bottom(1); + @include u-margin-top(1); + margin-right: 1.4em; } .alertContainer { diff --git a/src/pages/Office/TXOMoveInfo/TXOTab.module.scss b/src/pages/Office/TXOMoveInfo/TXOTab.module.scss index 2078723d0e4..fcb84593e76 100644 --- a/src/pages/Office/TXOMoveInfo/TXOTab.module.scss +++ b/src/pages/Office/TXOMoveInfo/TXOTab.module.scss @@ -39,8 +39,8 @@ } .tooCancelMoveContainer { - @include u-margin-bottom(3); - align-self: right; + @include u-margin-top(3); + padding-left: 630px; } .gridContainer { From 31fcb59f739e798448344096740e6ffc29d0aae9 Mon Sep 17 00:00:00 2001 From: pambecker Date: Fri, 4 Oct 2024 21:24:13 +0000 Subject: [PATCH 03/25] connect cancel to backend call --- pkg/gen/ghcapi/embedded_spec.go | 6 ++- .../ghcapi/ghcoperations/move/search_moves.go | 2 +- pkg/services/event/ghc_endpoint.go | 7 ++++ .../CancelMoveConfirmationModal.jsx | 2 - .../MoveHistory/UIDisplay/Operations.js | 1 + src/constants/queues.js | 2 + src/pages/Office/MoveDetails/MoveDetails.jsx | 42 ++++++++++++------- .../ServicesCounselingMoveDetails.jsx | 41 ++++++++++++------ src/services/ghcApi.js | 12 ++++++ swagger-def/ghc.yaml | 1 + swagger/ghc.yaml | 1 + 11 files changed, 85 insertions(+), 32 deletions(-) diff --git a/pkg/gen/ghcapi/embedded_spec.go b/pkg/gen/ghcapi/embedded_spec.go index b58b06d7b11..dc6352fcb49 100644 --- a/pkg/gen/ghcapi/embedded_spec.go +++ b/pkg/gen/ghcapi/embedded_spec.go @@ -1993,7 +1993,8 @@ func init() { "APPROVALS REQUESTED", "APPROVED", "NEEDS SERVICE COUNSELING", - "SERVICE COUNSELING COMPLETED" + "SERVICE COUNSELING COMPLETED", + "CANCELED" ] } } @@ -16688,7 +16689,8 @@ func init() { "APPROVALS REQUESTED", "APPROVED", "NEEDS SERVICE COUNSELING", - "SERVICE COUNSELING COMPLETED" + "SERVICE COUNSELING COMPLETED", + "CANCELED" ] } } diff --git a/pkg/gen/ghcapi/ghcoperations/move/search_moves.go b/pkg/gen/ghcapi/ghcoperations/move/search_moves.go index 9ca46adcc1f..f22f0fbf7cf 100644 --- a/pkg/gen/ghcapi/ghcoperations/move/search_moves.go +++ b/pkg/gen/ghcapi/ghcoperations/move/search_moves.go @@ -370,7 +370,7 @@ var searchMovesBodyStatusItemsEnum []interface{} func init() { var res []string - if err := json.Unmarshal([]byte(`["DRAFT","SUBMITTED","APPROVALS REQUESTED","APPROVED","NEEDS SERVICE COUNSELING","SERVICE COUNSELING COMPLETED"]`), &res); err != nil { + if err := json.Unmarshal([]byte(`["DRAFT","SUBMITTED","APPROVALS REQUESTED","APPROVED","NEEDS SERVICE COUNSELING","SERVICE COUNSELING COMPLETED","CANCELED"]`), &res); err != nil { panic(err) } for _, v := range res { diff --git a/pkg/services/event/ghc_endpoint.go b/pkg/services/event/ghc_endpoint.go index 78f3c192ab3..8e37fb3a1a9 100644 --- a/pkg/services/event/ghc_endpoint.go +++ b/pkg/services/event/ghc_endpoint.go @@ -127,6 +127,9 @@ const GhcUpdateMaxBillableWeightAsTIOEndpointKey = "Ghc.UpdateMaxBillableWeightA // GhcAcknowledgeExcessWeightRiskEndpointKey is the key for the AcknowledgeExcessWeightRisk endpoint in ghc const GhcAcknowledgeExcessWeightRiskEndpointKey = "Ghc.AcknowledgeExcessWeightRisk" +// GhcMoveCancelerEndpointKey is the key for the moveCanceler endpoint in ghc +const GhcMoveCancelerEndpointKey = "Ghc.MoveCanceler" + // -------------------- ENDPOINT MAP ENTRIES -------------------- var ghcEndpoints = EndpointMapType{ GhcGetCustomerEndpointKey: { @@ -285,4 +288,8 @@ var ghcEndpoints = EndpointMapType{ APIName: GhcAPIName, OperationID: "AcknowledgeExcessWeightRisk", }, + GhcMoveCancelerEndpointKey: { + APIName: GhcAPIName, + OperationID: "moveCanceler", + }, } diff --git a/src/components/ConfirmationModals/CancelMoveConfirmationModal.jsx b/src/components/ConfirmationModals/CancelMoveConfirmationModal.jsx index a9f7df6abf5..3a705d1ab6a 100644 --- a/src/components/ConfirmationModals/CancelMoveConfirmationModal.jsx +++ b/src/components/ConfirmationModals/CancelMoveConfirmationModal.jsx @@ -26,8 +26,6 @@ CancelMoveConfirmationModal.propTypes = { onClose: PropTypes.func.isRequired, onSubmit: PropTypes.func.isRequired, - moveID: PropTypes.string.isRequired, - title: PropTypes.string, content: PropTypes.string, submitText: PropTypes.string, diff --git a/src/constants/MoveHistory/UIDisplay/Operations.js b/src/constants/MoveHistory/UIDisplay/Operations.js index a818d600f61..ec962d22229 100644 --- a/src/constants/MoveHistory/UIDisplay/Operations.js +++ b/src/constants/MoveHistory/UIDisplay/Operations.js @@ -56,4 +56,5 @@ export default { deleteMovingExpense: 'deleteMovingExpense', // internal.yaml submitPPMShipmentDocumentation: 'submitPPMShipmentDocumentation', // internal.yaml finishDocumentReview: 'finishDocumentReview', // ghc.yaml + moveCanceler: 'moveCanceler', // ghc.yaml }; diff --git a/src/constants/queues.js b/src/constants/queues.js index ef794ec1eb7..28ee0fe3557 100644 --- a/src/constants/queues.js +++ b/src/constants/queues.js @@ -20,6 +20,7 @@ export const MOVE_STATUS_LABELS = { [MOVE_STATUSES.NEEDS_SERVICE_COUNSELING]: 'Needs Service Counseling', [MOVE_STATUSES.APPROVALS_REQUESTED]: 'Approvals requested', [MOVE_STATUSES.APPROVED]: 'Move approved', + [MOVE_STATUSES.CANCELED]: 'Canceled', }; export const SEARCH_QUEUE_STATUS_FILTER_OPTIONS = [ @@ -28,6 +29,7 @@ export const SEARCH_QUEUE_STATUS_FILTER_OPTIONS = [ { value: MOVE_STATUSES.NEEDS_SERVICE_COUNSELING, label: 'Needs counseling' }, { value: MOVE_STATUSES.SERVICE_COUNSELING_COMPLETED, label: 'Service counseling completed' }, { value: MOVE_STATUSES.APPROVED, label: 'Move Approved' }, + { value: MOVE_STATUSES.CANCELED, label: 'Canceled' }, ]; export const SERVICE_COUNSELING_MOVE_STATUS_LABELS = { diff --git a/src/pages/Office/MoveDetails/MoveDetails.jsx b/src/pages/Office/MoveDetails/MoveDetails.jsx index 89e86792047..bf40b616507 100644 --- a/src/pages/Office/MoveDetails/MoveDetails.jsx +++ b/src/pages/Office/MoveDetails/MoveDetails.jsx @@ -24,13 +24,13 @@ import CancelMoveConfirmationModal from 'components/ConfirmationModals/CancelMov import ApprovedRequestedShipments from 'components/Office/RequestedShipments/ApprovedRequestedShipments'; import SubmittedRequestedShipments from 'components/Office/RequestedShipments/SubmittedRequestedShipments'; import { useMoveDetailsQueries } from 'hooks/queries'; -import { updateMoveStatus, updateMTOShipmentStatus, updateFinancialFlag } from 'services/ghcApi'; +import { updateMoveStatus, updateMTOShipmentStatus, cancelMove, updateFinancialFlag } from 'services/ghcApi'; import LeftNav from 'components/LeftNav/LeftNav'; import LeftNavTag from 'components/LeftNavTag/LeftNavTag'; import Restricted from 'components/Restricted/Restricted'; import LoadingPlaceholder from 'shared/LoadingPlaceholder'; import SomethingWentWrong from 'shared/SomethingWentWrong'; -import { SHIPMENT_OPTIONS_URL } from 'shared/constants'; +import { SHIPMENT_OPTIONS_URL, MOVE_STATUSES } from 'shared/constants'; import { SIT_EXTENSION_STATUS } from 'constants/sitExtensions'; import { ORDERS_TYPE } from 'constants/orders'; import { permissionTypes } from 'constants/permissions'; @@ -74,6 +74,7 @@ const MoveDetails = ({ const { move, customerData, order, closeoutOffice, mtoShipments, mtoServiceItems, isLoading, isError } = useMoveDetailsQueries(moveCode); + const tooCanCancelMove = move.status !== MOVE_STATUSES.CANCELED; // for now we are only showing dest type on retiree and separatee orders let isRetirementOrSeparation = false; @@ -109,6 +110,19 @@ const MoveDetails = ({ }, }); + const { mutate: mutateCancelMove } = useMutation(cancelMove, { + onSuccess: (data) => { + queryClient.setQueryData([MOVES, data.moveTaskOrderID], data); + queryClient.invalidateQueries([MOVES, data.moveTaskOrderID]); + setAlertMessage('Move canceled.'); + setAlertType('success'); + }, + onError: () => { + setAlertMessage('There was a problem cancelling the move. Please try again later.'); + setAlertType('error'); + }, + }); + const { mutate: mutateFinancialReview } = useMutation(updateFinancialFlag, { onSuccess: (data) => { queryClient.setQueryData([MOVES, data.locator], data); @@ -146,12 +160,12 @@ const MoveDetails = ({ setIsFinancialModalVisible(false); }; - const showCancelMoveModal = () => { + const handleShowCancelMoveModal = () => { setIsCancelMoveModalVisible(true); }; const handleCancelMove = () => { - mutateMoveStatus({ + mutateCancelMove({ moveID: move.id, ifMatchETag: move.eTag, }); @@ -437,19 +451,19 @@ const MoveDetails = ({ )}
- + {tooCanCancelMove && ( + + )}
- {isCancelMoveModalVisible && ( - - )} + {submittedShipments?.length > 0 && (
{ @@ -229,6 +230,7 @@ const ServicesCounselingMoveDetails = ({ counselorCanReview = ppmShipmentsInfoNeedsApproval.length > 0; reviewWeightsURL = generatePath(servicesCounselingRoutes.BASE_REVIEW_SHIPMENT_WEIGHTS_PATH, { moveCode }); counselorCanEdit = move.status === MOVE_STATUSES.NEEDS_SERVICE_COUNSELING && ppmShipmentsOtherStatuses.length > 0; + counselorCanCancelMove = move.status !== MOVE_STATUSES.CANCELED; counselorCanEditNonPPM = move.status === MOVE_STATUSES.NEEDS_SERVICE_COUNSELING && shipmentsInfo.shipmentType !== 'PPM'; @@ -395,6 +397,19 @@ const ServicesCounselingMoveDetails = ({ }, }); + const { mutate: mutateCancelMove } = useMutation(cancelMove, { + onSuccess: (data) => { + queryClient.setQueryData([MOVES, data.id], data); + queryClient.invalidateQueries([MOVES, data.id]); + setAlertMessage('Move canceled.'); + setAlertType('success'); + }, + onError: () => { + setAlertMessage('There was a problem cancelling the move. Please try again later.'); + setAlertType('error'); + }, + }); + const { mutate: mutateFinancialReview } = useMutation(updateFinancialFlag, { onSuccess: (data) => { queryClient.setQueryData([MOVES, data.locator], data); @@ -471,12 +486,12 @@ const ServicesCounselingMoveDetails = ({ setIsFinancialModalVisible(false); }; - const showCancelMoveModal = () => { + const handleShowCancelMoveModal = () => { setIsCancelMoveModalVisible(true); }; const handleCancelMove = () => { - mutateMoveStatus({ + mutateCancelMove({ moveID: move.id, ifMatchETag: move.eTag, }); @@ -543,13 +558,11 @@ const ServicesCounselingMoveDetails = ({ initialSelection={move?.financialReviewFlag} /> )} - {isCancelMoveModalVisible && ( - - )} + @@ -600,9 +613,11 @@ const ServicesCounselingMoveDetails = ({
- + {counselorCanCancelMove && ( + + )}
diff --git a/src/services/ghcApi.js b/src/services/ghcApi.js index ec7bb19df68..a592c8593c8 100644 --- a/src/services/ghcApi.js +++ b/src/services/ghcApi.js @@ -436,6 +436,18 @@ export function updateMoveStatusServiceCounselingCompleted({ moveTaskOrderID, if ); } +export function cancelMove({ moveID, ifMatchETag, normalize = false }) { + const operationPath = 'move.moveCanceler'; + return makeGHCRequest( + operationPath, + { + moveID, + 'If-Match': ifMatchETag, + }, + { normalize }, + ); +} + export function updateMTOShipmentStatus({ shipmentID, diversionReason, diff --git a/swagger-def/ghc.yaml b/swagger-def/ghc.yaml index 5d59185e949..db9c9bc645f 100644 --- a/swagger-def/ghc.yaml +++ b/swagger-def/ghc.yaml @@ -3706,6 +3706,7 @@ paths: - APPROVED - NEEDS SERVICE COUNSELING - SERVICE COUNSELING COMPLETED + - CANCELED originPostalCode: type: string x-nullable: true diff --git a/swagger/ghc.yaml b/swagger/ghc.yaml index f3a274f1b9d..b8cef157aa7 100644 --- a/swagger/ghc.yaml +++ b/swagger/ghc.yaml @@ -3877,6 +3877,7 @@ paths: - APPROVED - NEEDS SERVICE COUNSELING - SERVICE COUNSELING COMPLETED + - CANCELED originPostalCode: type: string x-nullable: true From 903e2aec5d4867e6620f41eb90f509fc3ba8d567 Mon Sep 17 00:00:00 2001 From: pambecker Date: Mon, 7 Oct 2024 19:45:20 +0000 Subject: [PATCH 04/25] cleanup --- pkg/services/move/move_canceler.go | 2 +- .../ShipmentDisplay/ShipmentDisplay.jsx | 4 +++- src/constants/shipments.js | 1 + src/pages/Office/MoveDetails/MoveDetails.jsx | 21 +++++++++++++++---- .../ServicesCounselingMoveDetails.jsx | 18 ++++++++++++---- 5 files changed, 36 insertions(+), 10 deletions(-) diff --git a/pkg/services/move/move_canceler.go b/pkg/services/move/move_canceler.go index 26a0c2e04bb..cb21d2f3028 100644 --- a/pkg/services/move/move_canceler.go +++ b/pkg/services/move/move_canceler.go @@ -39,7 +39,7 @@ func (f *moveCanceler) CancelMove(appCtx appcontext.AppContext, moveID uuid.UUID if shipment.PPMShipment != nil { if shipment.PPMShipment.Status == models.PPMShipmentStatusCloseoutComplete { - return apperror.NewConflictError(move.ID, " cannot cancel move with approved shipment.") + return apperror.NewConflictError(move.ID, " cannot cancel move with a closeout complete shipment.") } var ppmshipment models.PPMShipment qerr := appCtx.DB().Where("id = ?", shipment.PPMShipment.ID).First(&ppmshipment) diff --git a/src/components/Office/ShipmentDisplay/ShipmentDisplay.jsx b/src/components/Office/ShipmentDisplay/ShipmentDisplay.jsx index 44d9e5bbe97..c04154c1c8e 100644 --- a/src/components/Office/ShipmentDisplay/ShipmentDisplay.jsx +++ b/src/components/Office/ShipmentDisplay/ShipmentDisplay.jsx @@ -94,7 +94,9 @@ const ShipmentDisplay = ({
{displayInfo.isDiversion && diversion} - {displayInfo.shipmentStatus === shipmentStatuses.CANCELED && ( + {(displayInfo.shipmentStatus === shipmentStatuses.CANCELED || + displayInfo.status === shipmentStatuses.CANCELED || + displayInfo.ppmShipment?.status === ppmShipmentStatuses.CANCELED) && ( canceled )} {displayInfo.shipmentStatus === shipmentStatuses.DIVERSION_REQUESTED && diversion requested} diff --git a/src/constants/shipments.js b/src/constants/shipments.js index 5de4dc218ea..2552793529d 100644 --- a/src/constants/shipments.js +++ b/src/constants/shipments.js @@ -40,6 +40,7 @@ export const ppmShipmentStatuses = { NEEDS_ADVANCE_APPROVAL: 'NEEDS_ADVANCE_APPROVAL', NEEDS_CLOSEOUT: 'NEEDS_CLOSEOUT', CLOSEOUT_COMPLETE: 'CLOSEOUT_COMPLETE', + CANCELED: 'CANCELED', }; export const boatShipmentTypes = { diff --git a/src/pages/Office/MoveDetails/MoveDetails.jsx b/src/pages/Office/MoveDetails/MoveDetails.jsx index bf40b616507..d3e8d4287f5 100644 --- a/src/pages/Office/MoveDetails/MoveDetails.jsx +++ b/src/pages/Office/MoveDetails/MoveDetails.jsx @@ -12,7 +12,7 @@ import hasRiskOfExcess from 'utils/hasRiskOfExcess'; import { MOVES, MTO_SERVICE_ITEMS, MTO_SHIPMENTS } from 'constants/queryKeys'; import { tooRoutes } from 'constants/routes'; import SERVICE_ITEM_STATUSES from 'constants/serviceItems'; -import { ADDRESS_UPDATE_STATUS, shipmentStatuses } from 'constants/shipments'; +import { ADDRESS_UPDATE_STATUS, shipmentStatuses, ppmShipmentStatuses } from 'constants/shipments'; import AllowancesList from 'components/Office/DefinitionLists/AllowancesList'; import CustomerInfoList from 'components/Office/DefinitionLists/CustomerInfoList'; import ButtonDropdown from 'components/ButtonDropdown/ButtonDropdown'; @@ -74,9 +74,9 @@ const MoveDetails = ({ const { move, customerData, order, closeoutOffice, mtoShipments, mtoServiceItems, isLoading, isError } = useMoveDetailsQueries(moveCode); - const tooCanCancelMove = move.status !== MOVE_STATUSES.CANCELED; // for now we are only showing dest type on retiree and separatee orders let isRetirementOrSeparation = false; + let numberOfShipmentsNotAllowedForCancel = 0; isRetirementOrSeparation = order?.order_type === ORDERS_TYPE.RETIREMENT || order?.order_type === ORDERS_TYPE.SEPARATION; @@ -210,6 +210,18 @@ const MoveDetails = ({ }, [shipmentWithDestinationAddressChangeRequest?.length, setShipmentsWithDeliveryAddressUpdateRequestedCount]); const shipmentsInfoNonPPM = mtoShipments?.filter((shipment) => shipment.shipmentType !== 'PPM'); + if (mtoShipments) { + const nonDeletedShipments = mtoShipments?.filter((shipment) => !shipment.deletedAt); + const nonPpmShipments = nonDeletedShipments.filter((shipment) => shipment.shipmentType !== 'PPM'); + const nonPpmApprovedShipments = nonPpmShipments.filter( + (shipment) => shipment?.status === shipmentStatuses.APPROVED, + ); + const onlyPpmShipments = nonDeletedShipments.filter((shipment) => shipment.shipmentType === 'PPM'); + const ppmCloseoutCompleteShipments = onlyPpmShipments.filter( + (shipment) => shipment.ppmShipment?.status === ppmShipmentStatuses.CLOSEOUT_COMPLETE, + ); + numberOfShipmentsNotAllowedForCancel = nonPpmApprovedShipments.length + ppmCloseoutCompleteShipments.length; + } useEffect(() => { const shipmentCount = submittedShipments?.length || 0; @@ -355,6 +367,7 @@ const MoveDetails = ({ const hasAmendedOrders = ordersInfo.uploadedAmendedOrderID && !ordersInfo.amendedOrdersAcknowledgedAt; const hasDestinationAddressUpdate = shipmentWithDestinationAddressChangeRequest && shipmentWithDestinationAddressChangeRequest.length > 0; + const tooCanCancelMove = move.status !== MOVE_STATUSES.CANCELED && numberOfShipmentsNotAllowedForCancel === 0; return (
@@ -451,8 +464,8 @@ const MoveDetails = ({ )}
- {tooCanCancelMove && ( - )} diff --git a/src/pages/Office/ServicesCounselingMoveDetails/ServicesCounselingMoveDetails.jsx b/src/pages/Office/ServicesCounselingMoveDetails/ServicesCounselingMoveDetails.jsx index 8d4e01e7bbd..09bccd84e48 100644 --- a/src/pages/Office/ServicesCounselingMoveDetails/ServicesCounselingMoveDetails.jsx +++ b/src/pages/Office/ServicesCounselingMoveDetails/ServicesCounselingMoveDetails.jsx @@ -25,7 +25,7 @@ import { SubmitMoveConfirmationModal } from 'components/Office/SubmitMoveConfirm import { useMoveDetailsQueries, useOrdersDocumentQueries } from 'hooks/queries'; import { updateMoveStatusServiceCounselingCompleted, cancelMove, updateFinancialFlag } from 'services/ghcApi'; import { MOVE_STATUSES, SHIPMENT_OPTIONS_URL, SHIPMENT_OPTIONS } from 'shared/constants'; -import { ppmShipmentStatuses } from 'constants/shipments'; +import { ppmShipmentStatuses, shipmentStatuses } from 'constants/shipments'; import shipmentCardsStyles from 'styles/shipmentCards.module.scss'; import LeftNav from 'components/LeftNav/LeftNav'; import LeftNavTag from 'components/LeftNavTag/LeftNavTag'; @@ -117,6 +117,7 @@ const ServicesCounselingMoveDetails = ({ let shipmentsInfo = []; let ppmShipmentsInfoNeedsApproval = []; let ppmShipmentsOtherStatuses = []; + let numberOfShipmentsNotAllowedForCancel = 0; let disableSubmit = false; let disableSubmitDueToMissingOrderInfo = false; let numberOfErrorIfMissingForAllShipments = 0; @@ -169,6 +170,15 @@ const ServicesCounselingMoveDetails = ({ (shipment) => shipment.ppmShipment?.status !== ppmShipmentStatuses.NEEDS_CLOSEOUT, ); + const nonPpmShipments = submittedShipments.filter((shipment) => shipment.shipmentType !== 'PPM'); + const nonPpmApprovedShipments = nonPpmShipments.filter( + (shipment) => shipment?.status === shipmentStatuses.APPROVED, + ); + const ppmCloseoutCompleteShipments = onlyPpmShipments.filter( + (shipment) => shipment.ppmShipment?.status === ppmShipmentStatuses.CLOSEOUT_COMPLETE, + ); + numberOfShipmentsNotAllowedForCancel = nonPpmApprovedShipments.length + ppmCloseoutCompleteShipments.length; + ppmShipmentsInfoNeedsApproval = ppmNeedsApprovalShipments.map((shipment) => { const reviewURL = `../${generatePath(servicesCounselingRoutes.SHIPMENT_REVIEW_PATH, { moveCode, @@ -230,7 +240,7 @@ const ServicesCounselingMoveDetails = ({ counselorCanReview = ppmShipmentsInfoNeedsApproval.length > 0; reviewWeightsURL = generatePath(servicesCounselingRoutes.BASE_REVIEW_SHIPMENT_WEIGHTS_PATH, { moveCode }); counselorCanEdit = move.status === MOVE_STATUSES.NEEDS_SERVICE_COUNSELING && ppmShipmentsOtherStatuses.length > 0; - counselorCanCancelMove = move.status !== MOVE_STATUSES.CANCELED; + counselorCanCancelMove = move.status !== MOVE_STATUSES.CANCELED && numberOfShipmentsNotAllowedForCancel === 0; counselorCanEditNonPPM = move.status === MOVE_STATUSES.NEEDS_SERVICE_COUNSELING && shipmentsInfo.shipmentType !== 'PPM'; @@ -613,8 +623,8 @@ const ServicesCounselingMoveDetails = ({
- {counselorCanCancelMove && ( - )} From 65d6e3c7bdebceacac5a29cbf12284ca17d5f651 Mon Sep 17 00:00:00 2001 From: pambecker Date: Tue, 8 Oct 2024 20:13:37 +0000 Subject: [PATCH 05/25] fix issue with PPM only not canceling --- pkg/services/move/move_canceler.go | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/pkg/services/move/move_canceler.go b/pkg/services/move/move_canceler.go index cb21d2f3028..64ec885b93d 100644 --- a/pkg/services/move/move_canceler.go +++ b/pkg/services/move/move_canceler.go @@ -55,9 +55,7 @@ func (f *moveCanceler) CancelMove(appCtx appcontext.AppContext, moveID uuid.UUID } else if err != nil { return apperror.NewQueryError("PPM Shipment", err, "Failed to update status for ppm shipment") } - } - - if shipment.Status != models.MTOShipmentStatusApproved { + } else if shipment.Status != models.MTOShipmentStatusApproved { verrs, err := txnAppCtx.DB().ValidateAndUpdate(&shipmentDelta) if verrs != nil && verrs.HasAny() { return apperror.NewInvalidInputError(shipment.ID, err, verrs, "Validation errors found while setting shipment status") From 29804ed9420558897a55687944ecf8a81ddb50f8 Mon Sep 17 00:00:00 2001 From: pambecker Date: Tue, 8 Oct 2024 21:38:16 +0000 Subject: [PATCH 06/25] Fix MTO Canceled label for PPM --- src/pages/Office/MoveTaskOrder/MoveTaskOrder.jsx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/pages/Office/MoveTaskOrder/MoveTaskOrder.jsx b/src/pages/Office/MoveTaskOrder/MoveTaskOrder.jsx index 11d670add7f..891f8505b96 100644 --- a/src/pages/Office/MoveTaskOrder/MoveTaskOrder.jsx +++ b/src/pages/Office/MoveTaskOrder/MoveTaskOrder.jsx @@ -1217,7 +1217,7 @@ export const MoveTaskOrder = (props) => { originPostalCode: pickupAddress?.postalCode || '', destinationAddress: destinationAddress || dutyLocationPostal, scheduledPickupDate: formattedScheduledPickup, - shipmentStatus: mtoShipment.status, + shipmentStatus: mtoShipment.ppmShipment?.status || mtoShipment.status, ifMatchEtag: mtoShipment.eTag, moveTaskOrderID: mtoShipment.moveTaskOrderID, shipmentLocator: mtoShipment.shipmentLocator, From bf5634f599e43a7259cb1800447ca8ee32b2408e Mon Sep 17 00:00:00 2001 From: pambecker Date: Wed, 9 Oct 2024 19:44:18 +0000 Subject: [PATCH 07/25] button placement --- .../ServicesCounselingMoveDetails.module.scss | 3 +-- src/pages/Office/TXOMoveInfo/TXOTab.module.scss | 4 ++-- 2 files changed, 3 insertions(+), 4 deletions(-) diff --git a/src/pages/Office/ServicesCounselingMoveDetails/ServicesCounselingMoveDetails.module.scss b/src/pages/Office/ServicesCounselingMoveDetails/ServicesCounselingMoveDetails.module.scss index 4e7038f9271..70809786fa5 100644 --- a/src/pages/Office/ServicesCounselingMoveDetails/ServicesCounselingMoveDetails.module.scss +++ b/src/pages/Office/ServicesCounselingMoveDetails/ServicesCounselingMoveDetails.module.scss @@ -29,9 +29,8 @@ } .scCancelMoveContainer { - @include u-margin-bottom(1); @include u-margin-top(1); - margin-right: 1.4em; + padding-left: 810px; } .alertContainer { diff --git a/src/pages/Office/TXOMoveInfo/TXOTab.module.scss b/src/pages/Office/TXOMoveInfo/TXOTab.module.scss index fcb84593e76..82ea9ac19b6 100644 --- a/src/pages/Office/TXOMoveInfo/TXOTab.module.scss +++ b/src/pages/Office/TXOMoveInfo/TXOTab.module.scss @@ -39,8 +39,8 @@ } .tooCancelMoveContainer { - @include u-margin-top(3); - padding-left: 630px; + @include u-margin-bottom(3); + padding-left: 810px; } .gridContainer { From 5710bc5f259e6ebbded74a87f9bdf6691e6bee1c Mon Sep 17 00:00:00 2001 From: pambecker Date: Thu, 10 Oct 2024 15:45:10 +0000 Subject: [PATCH 08/25] update tests --- .../CancelMoveConfirmationModal.test.jsx | 8 ++++---- .../Office/ShipmentDisplay/ShipmentDisplay.test.jsx | 4 ++-- .../Office/ShipmentHeading/ShipmentHeading.test.jsx | 6 +++--- src/pages/Office/MoveTaskOrder/MoveTaskOrder.test.jsx | 8 ++++---- .../Office/MoveTaskOrder/moveTaskOrderUnitTestData.js | 2 +- 5 files changed, 14 insertions(+), 14 deletions(-) diff --git a/src/components/ConfirmationModals/CancelMoveConfirmationModal.test.jsx b/src/components/ConfirmationModals/CancelMoveConfirmationModal.test.jsx index a1f07ae0f12..76c5b4b885c 100644 --- a/src/components/ConfirmationModals/CancelMoveConfirmationModal.test.jsx +++ b/src/components/ConfirmationModals/CancelMoveConfirmationModal.test.jsx @@ -15,7 +15,7 @@ describe('CancelMoveConfirmationModal', () => { const moveID = '123456'; it('renders the component', async () => { - render(); + render(); expect(await screen.findByRole('heading', { level: 3, name: 'Are you sure?' })).toBeInTheDocument(); }); @@ -31,9 +31,9 @@ describe('CancelMoveConfirmationModal', () => { }); it('closes the modal when the keep button is clicked', async () => { - render(); + render(); - const keepButton = await screen.findByRole('button', { name: 'Keep shipment' }); + const keepButton = await screen.findByRole('button', { name: 'Keep move' }); await userEvent.click(keepButton); @@ -41,7 +41,7 @@ describe('CancelMoveConfirmationModal', () => { }); it('calls the submit function when cancel button is clicked', async () => { - render(); + render(); const cancelButton = await screen.findByRole('button', { name: 'Cancel move' }); diff --git a/src/components/Office/ShipmentDisplay/ShipmentDisplay.test.jsx b/src/components/Office/ShipmentDisplay/ShipmentDisplay.test.jsx index 0aadc275caf..93c0194b5e4 100644 --- a/src/components/Office/ShipmentDisplay/ShipmentDisplay.test.jsx +++ b/src/components/Office/ShipmentDisplay/ShipmentDisplay.test.jsx @@ -78,9 +78,9 @@ describe('Shipment Container', () => { render(); expect(screen.getByText('diversion')).toBeInTheDocument(); }); - it('renders with cancelled tag', () => { + it('renders with canceled tag', () => { render(); - expect(screen.getByText('cancelled')).toBeInTheDocument(); + expect(screen.getByText('canceled')).toBeInTheDocument(); }); it('renders a disabled button when move is locked', () => { render( diff --git a/src/components/Office/ShipmentHeading/ShipmentHeading.test.jsx b/src/components/Office/ShipmentHeading/ShipmentHeading.test.jsx index 910024714c5..27cacf3aa5d 100644 --- a/src/components/Office/ShipmentHeading/ShipmentHeading.test.jsx +++ b/src/components/Office/ShipmentHeading/ShipmentHeading.test.jsx @@ -41,7 +41,7 @@ describe('Shipment Heading with diversion requested shipment', () => { }); }); -describe('Shipment Heading with cancelled shipment', () => { +describe('Shipment Heading with canceled shipment', () => { const wrapper = mount( { , ); - it('renders the cancelled tag next to the shipment type', () => { - expect(wrapper.find({ 'data-testid': 'tag' }).text()).toEqual('cancelled'); + it('renders the canceled tag next to the shipment type', () => { + expect(wrapper.find({ 'data-testid': 'tag' }).text()).toEqual('canceled'); }); it('hides the request cancellation button', () => { diff --git a/src/pages/Office/MoveTaskOrder/MoveTaskOrder.test.jsx b/src/pages/Office/MoveTaskOrder/MoveTaskOrder.test.jsx index 39736569bfa..0f114276dc1 100644 --- a/src/pages/Office/MoveTaskOrder/MoveTaskOrder.test.jsx +++ b/src/pages/Office/MoveTaskOrder/MoveTaskOrder.test.jsx @@ -4,7 +4,7 @@ import { render, screen } from '@testing-library/react'; import { unapprovedMTOQuery, - approvedMTOWithCancelledShipmentQuery, + approvedMTOWithCanceledShipmentQuery, missingWeightQuery, someShipmentsApprovedMTOQuery, someWeightNotReturned, @@ -685,8 +685,8 @@ describe('MoveTaskOrder', () => { }); }); - describe('approved mto with cancelled shipment', () => { - useMoveTaskOrderQueries.mockReturnValue(approvedMTOWithCancelledShipmentQuery); + describe('approved mto with canceled shipment', () => { + useMoveTaskOrderQueries.mockReturnValue(approvedMTOWithCanceledShipmentQuery); const wrapper = mount( { it('renders the ShipmentHeading', () => { expect(wrapper.find('ShipmentHeading').exists()).toBe(true); expect(wrapper.find('h2').at(0).text()).toEqual('Household goods'); - expect(wrapper.find('span[data-testid="tag"]').at(0).text()).toEqual('cancelled'); + expect(wrapper.find('span[data-testid="tag"]').at(0).text()).toEqual('canceled'); }); it('renders the ImportantShipmentDates', () => { diff --git a/src/pages/Office/MoveTaskOrder/moveTaskOrderUnitTestData.js b/src/pages/Office/MoveTaskOrder/moveTaskOrderUnitTestData.js index ffd30aea60a..ea37799f7b9 100644 --- a/src/pages/Office/MoveTaskOrder/moveTaskOrderUnitTestData.js +++ b/src/pages/Office/MoveTaskOrder/moveTaskOrderUnitTestData.js @@ -1268,7 +1268,7 @@ export const riskOfExcessWeightQueryExternalShipment = { ], }; -export const approvedMTOWithCancelledShipmentQuery = { +export const approvedMTOWithCanceledShipmentQuery = { orders: { 1: { id: '1', From abca4eb7c7d7410a1e18a500099a99911c941fe2 Mon Sep 17 00:00:00 2001 From: pambecker Date: Thu, 10 Oct 2024 20:03:45 +0000 Subject: [PATCH 09/25] updates to refresh page --- src/pages/Office/MoveDetails/MoveDetails.jsx | 9 ++++++--- .../ServicesCounselingMoveDetails.jsx | 4 ++-- 2 files changed, 8 insertions(+), 5 deletions(-) diff --git a/src/pages/Office/MoveDetails/MoveDetails.jsx b/src/pages/Office/MoveDetails/MoveDetails.jsx index d3e8d4287f5..9b97f03a6fa 100644 --- a/src/pages/Office/MoveDetails/MoveDetails.jsx +++ b/src/pages/Office/MoveDetails/MoveDetails.jsx @@ -112,8 +112,11 @@ const MoveDetails = ({ const { mutate: mutateCancelMove } = useMutation(cancelMove, { onSuccess: (data) => { - queryClient.setQueryData([MOVES, data.moveTaskOrderID], data); - queryClient.invalidateQueries([MOVES, data.moveTaskOrderID]); + queryClient.setQueryData([MOVES, data.locator], data); + queryClient.invalidateQueries([MOVES, data.locator]); + queryClient + .invalidateQueries([MTO_SHIPMENTS, data.moveTaskOrderID]) + .then(() => queryClient.refetchQueries([MTO_SHIPMENTS, data.moveTaskOrderID])); setAlertMessage('Move canceled.'); setAlertType('success'); }, @@ -443,7 +446,7 @@ const MoveDetails = ({ )} - {!isMoveLocked && ( + {!isMoveLocked && move.status !== MOVE_STATUSES.CANCELED && ( { - queryClient.setQueryData([MOVES, data.id], data); - queryClient.invalidateQueries([MOVES, data.id]); + queryClient.setQueryData([MOVES, data.locator], data); + queryClient.invalidateQueries([MOVES, data.locator]); setAlertMessage('Move canceled.'); setAlertType('success'); }, From dc087427dbcedbaee8cdf707af76be528d20f0c8 Mon Sep 17 00:00:00 2001 From: pambecker Date: Fri, 11 Oct 2024 20:31:23 +0000 Subject: [PATCH 10/25] update shipment labels on cards --- src/pages/Office/MoveDetails/MoveDetails.jsx | 4 +--- .../ServicesCounselingMoveDetails.jsx | 3 ++- 2 files changed, 3 insertions(+), 4 deletions(-) diff --git a/src/pages/Office/MoveDetails/MoveDetails.jsx b/src/pages/Office/MoveDetails/MoveDetails.jsx index 9b97f03a6fa..811d6fdc3f3 100644 --- a/src/pages/Office/MoveDetails/MoveDetails.jsx +++ b/src/pages/Office/MoveDetails/MoveDetails.jsx @@ -114,9 +114,7 @@ const MoveDetails = ({ onSuccess: (data) => { queryClient.setQueryData([MOVES, data.locator], data); queryClient.invalidateQueries([MOVES, data.locator]); - queryClient - .invalidateQueries([MTO_SHIPMENTS, data.moveTaskOrderID]) - .then(() => queryClient.refetchQueries([MTO_SHIPMENTS, data.moveTaskOrderID])); + queryClient.invalidateQueries({ queryKey: [MTO_SHIPMENTS] }); setAlertMessage('Move canceled.'); setAlertType('success'); }, diff --git a/src/pages/Office/ServicesCounselingMoveDetails/ServicesCounselingMoveDetails.jsx b/src/pages/Office/ServicesCounselingMoveDetails/ServicesCounselingMoveDetails.jsx index a77cb955ac2..341d7514fb0 100644 --- a/src/pages/Office/ServicesCounselingMoveDetails/ServicesCounselingMoveDetails.jsx +++ b/src/pages/Office/ServicesCounselingMoveDetails/ServicesCounselingMoveDetails.jsx @@ -10,7 +10,7 @@ import styles from '../ServicesCounselingMoveInfo/ServicesCounselingTab.module.s import scMoveDetailsStyles from './ServicesCounselingMoveDetails.module.scss'; -import { MOVES } from 'constants/queryKeys'; +import { MOVES, MTO_SHIPMENTS } from 'constants/queryKeys'; import { ORDERS_TYPE } from 'constants/orders'; import { servicesCounselingRoutes } from 'constants/routes'; import AllowancesList from 'components/Office/DefinitionLists/AllowancesList'; @@ -411,6 +411,7 @@ const ServicesCounselingMoveDetails = ({ onSuccess: (data) => { queryClient.setQueryData([MOVES, data.locator], data); queryClient.invalidateQueries([MOVES, data.locator]); + queryClient.invalidateQueries({ queryKey: [MTO_SHIPMENTS] }); setAlertMessage('Move canceled.'); setAlertType('success'); }, From 6dd114947757d328dd66169b1db963107ec0f5e4 Mon Sep 17 00:00:00 2001 From: pambecker Date: Fri, 11 Oct 2024 21:31:52 +0000 Subject: [PATCH 11/25] update --- src/pages/Office/MoveDetails/MoveDetails.jsx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/pages/Office/MoveDetails/MoveDetails.jsx b/src/pages/Office/MoveDetails/MoveDetails.jsx index 5703a930fc8..3152b670992 100644 --- a/src/pages/Office/MoveDetails/MoveDetails.jsx +++ b/src/pages/Office/MoveDetails/MoveDetails.jsx @@ -465,7 +465,7 @@ const MoveDetails = ({ )} - {!isMoveLocked && move.status !== MOVE_STATUSES.CANCELED && ( + {!isMoveLocked && ( Date: Wed, 16 Oct 2024 16:09:15 +0000 Subject: [PATCH 12/25] address is_oconus implementation --- ...04203140_update_addresses_is_oconus.up.sql | 17 ++-- pkg/factory/address_factory.go | 1 + pkg/factory/address_factory_test.go | 4 + pkg/handlers/authentication/devlocal.go | 88 ++++--------------- .../internal/payloads/model_to_payload.go | 1 + pkg/handlers/internalapi/addresses_test.go | 2 + .../internal/payloads/model_to_payload.go | 1 + .../fixtures/copyFromStdinKeywords.sql | 6 +- pkg/models/address.go | 31 +++++++ pkg/models/address_test.go | 35 ++++++++ pkg/models/service_member.go | 17 ++++ pkg/services/address/address_creator.go | 7 ++ pkg/services/address/address_creator_test.go | 18 ++++ pkg/services/address/address_updater.go | 7 ++ pkg/services/address/address_updater_test.go | 18 ++++ .../mto_service_item_creator.go | 7 ++ pkg/services/office_user/customer/customer.go | 23 +++++ pkg/testdatagen/make_address.go | 3 + 18 files changed, 203 insertions(+), 83 deletions(-) diff --git a/migrations/app/schema/20241004203140_update_addresses_is_oconus.up.sql b/migrations/app/schema/20241004203140_update_addresses_is_oconus.up.sql index 207e10aca45..9d72e8c70d3 100644 --- a/migrations/app/schema/20241004203140_update_addresses_is_oconus.up.sql +++ b/migrations/app/schema/20241004203140_update_addresses_is_oconus.up.sql @@ -1,8 +1,9 @@ -DO $$ -BEGIN - UPDATE addresses - SET is_oconus = CASE - WHEN country IN ('US', 'United States') THEN false - ELSE true - END; -END $$; \ No newline at end of file +-- Set temp timeout due to potentially large modification +-- Time is 5 minutes in milliseconds +SET statement_timeout = 300000; +SET lock_timeout = 300000; +SET idle_in_transaction_session_timeout = 300000; + +-- Update is_oconus value on the addresses table based on the addresses country and the state +UPDATE addresses +SET is_oconus = CASE \ No newline at end of file diff --git a/pkg/factory/address_factory.go b/pkg/factory/address_factory.go index faf8a206553..aa7bbcf411c 100644 --- a/pkg/factory/address_factory.go +++ b/pkg/factory/address_factory.go @@ -81,6 +81,7 @@ func BuildMinimalAddress(db *pop.Connection, customs []Customization, traits []T State: "GA", PostalCode: "30813", Country: models.StringPointer("US"), + IsOconus: models.BoolPointer(false), } // Overwrite values with those from customizations diff --git a/pkg/factory/address_factory_test.go b/pkg/factory/address_factory_test.go index fa63dc41e5e..3e520495ba8 100644 --- a/pkg/factory/address_factory_test.go +++ b/pkg/factory/address_factory_test.go @@ -52,6 +52,7 @@ func (suite *FactorySuite) TestBuildAddress() { City: customCity, State: customState, PostalCode: customPostalCode, + IsOconus: models.BoolPointer(false), }, }, }, nil) @@ -96,6 +97,7 @@ func (suite *FactorySuite) TestBuildAddress() { Model: models.Address{ StreetAddress1: customAddress1, StreetAddress2: customAddress2, + IsOconus: models.BoolPointer(false), }, }, }, []Trait{ @@ -125,6 +127,7 @@ func (suite *FactorySuite) TestBuildAddress() { { Model: models.Address{ StreetAddress1: customAddress1, + IsOconus: models.BoolPointer(false), }, }, }, []Trait{ @@ -168,6 +171,7 @@ func (suite *FactorySuite) TestBuildAddress() { PostalCode: customPostalCode, Country: models.StringPointer("Canada"), County: "County", + IsOconus: models.BoolPointer(false), }, LinkOnly: true, }, diff --git a/pkg/handlers/authentication/devlocal.go b/pkg/handlers/authentication/devlocal.go index 694991f8854..2e43c1fafe0 100644 --- a/pkg/handlers/authentication/devlocal.go +++ b/pkg/handlers/authentication/devlocal.go @@ -488,6 +488,22 @@ func createUser(h devlocalAuthHandler, w http.ResponseWriter, r *http.Request) ( return nil, userType } + address := models.Address{ + StreetAddress1: "1333 Minna St", + City: "San Francisco", + State: "CA", + PostalCode: "94115", + County: "SAINT CLAIR", + IsOconus: models.BoolPointer(false), + } + + // Evaluate address and populate addresses isOconus value + isOconus, err := models.IsAddressOconus(appCtx.DB(), address) + if err != nil { + return nil, userType + } + address.IsOconus = &isOconus + switch userType { case MilMoveUserType: newServiceMember := models.ServiceMember{ @@ -501,14 +517,6 @@ func createUser(h devlocalAuthHandler, w http.ResponseWriter, r *http.Request) ( } case TOOOfficeUserType: // Now create the Truss JPPSO - address := models.Address{ - StreetAddress1: "1333 Minna St", - City: "San Francisco", - State: "CA", - PostalCode: "94115", - County: "SAINT CLAIR", - } - verrs, err := appCtx.DB().ValidateAndSave(&address) if err != nil { appCtx.Logger().Error("could not create address", zap.Error(err)) @@ -574,14 +582,6 @@ func createUser(h devlocalAuthHandler, w http.ResponseWriter, r *http.Request) ( } case TIOOfficeUserType: // Now create the Truss JPPSO - address := models.Address{ - StreetAddress1: "1333 Minna St", - City: "San Francisco", - State: "CA", - PostalCode: "94115", - County: "SAINT CLAIR", - } - verrs, err := appCtx.DB().ValidateAndSave(&address) if err != nil { appCtx.Logger().Error("could not create address", zap.Error(err)) @@ -646,14 +646,6 @@ func createUser(h devlocalAuthHandler, w http.ResponseWriter, r *http.Request) ( } case ServicesCounselorOfficeUserType: // Now create the Truss JPPSO - address := models.Address{ - StreetAddress1: "1333 Minna St", - City: "San Francisco", - State: "CA", - PostalCode: "94115", - County: "SAINT CLAIR", - } - verrs, err := appCtx.DB().ValidateAndSave(&address) if err != nil { appCtx.Logger().Error("could not create address", zap.Error(err)) @@ -718,14 +710,6 @@ func createUser(h devlocalAuthHandler, w http.ResponseWriter, r *http.Request) ( } case PrimeSimulatorOfficeUserType: // Now create the Truss JPPSO - address := models.Address{ - StreetAddress1: "1333 Minna St", - City: "San Francisco", - State: "CA", - PostalCode: "94115", - County: "SAINT CLAIR", - } - verrs, err := appCtx.DB().ValidateAndSave(&address) if err != nil { appCtx.Logger().Error("could not create address", zap.Error(err)) @@ -790,14 +774,6 @@ func createUser(h devlocalAuthHandler, w http.ResponseWriter, r *http.Request) ( } case QaeOfficeUserType: // Now create the Truss JPPSO - address := models.Address{ - StreetAddress1: "1333 Minna St", - City: "San Francisco", - State: "CA", - PostalCode: "94115", - County: "SAINT CLAIR", - } - verrs, err := appCtx.DB().ValidateAndSave(&address) if err != nil { appCtx.Logger().Error("could not create address", zap.Error(err)) @@ -862,14 +838,6 @@ func createUser(h devlocalAuthHandler, w http.ResponseWriter, r *http.Request) ( appCtx.Logger().Error("validation errors creating office user", zap.Stringer("errors", verrs)) } case CustomerServiceRepresentativeOfficeUserType: - address := models.Address{ - StreetAddress1: "1333 Minna St", - City: "San Francisco", - State: "CA", - PostalCode: "94115", - County: "SAINT CLAIR", - } - verrs, err := appCtx.DB().ValidateAndSave(&address) if err != nil { appCtx.Logger().Error("could not create address", zap.Error(err)) @@ -934,14 +902,6 @@ func createUser(h devlocalAuthHandler, w http.ResponseWriter, r *http.Request) ( appCtx.Logger().Error("validation errors creating office user", zap.Stringer("errors", verrs)) } case HQOfficeUserType: - address := models.Address{ - StreetAddress1: "1333 Minna St", - City: "San Francisco", - State: "CA", - PostalCode: "94115", - County: "SAINT CLAIR", - } - verrs, err := appCtx.DB().ValidateAndSave(&address) if err != nil { appCtx.Logger().Error("could not create address", zap.Error(err)) @@ -1006,14 +966,6 @@ func createUser(h devlocalAuthHandler, w http.ResponseWriter, r *http.Request) ( appCtx.Logger().Error("validation errors creating office user", zap.Stringer("errors", verrs)) } case GSROfficeUserType: - address := models.Address{ - StreetAddress1: "1333 Minna St", - City: "San Francisco", - State: "CA", - PostalCode: "94115", - County: "SAINT CLAIR", - } - verrs, err := appCtx.DB().ValidateAndSave(&address) if err != nil { appCtx.Logger().Error("could not create address", zap.Error(err)) @@ -1079,14 +1031,6 @@ func createUser(h devlocalAuthHandler, w http.ResponseWriter, r *http.Request) ( } case MultiRoleOfficeUserType: // Now create the Truss JPPSO - address := models.Address{ - StreetAddress1: "1333 Minna St", - City: "San Francisco", - State: "CA", - PostalCode: "94115", - County: "SAINT CLAIR", - } - verrs, err := appCtx.DB().ValidateAndSave(&address) if err != nil { appCtx.Logger().Error("could not create address", zap.Error(err)) diff --git a/pkg/handlers/ghcapi/internal/payloads/model_to_payload.go b/pkg/handlers/ghcapi/internal/payloads/model_to_payload.go index 933d9431941..de5ac1e9578 100644 --- a/pkg/handlers/ghcapi/internal/payloads/model_to_payload.go +++ b/pkg/handlers/ghcapi/internal/payloads/model_to_payload.go @@ -724,6 +724,7 @@ func Address(address *models.Address) *ghcmessages.Address { Country: address.Country, County: &address.County, ETag: etag.GenerateEtag(address.UpdatedAt), + IsOconus: address.IsOconus, } } diff --git a/pkg/handlers/internalapi/addresses_test.go b/pkg/handlers/internalapi/addresses_test.go index ee14909386a..db23851dc75 100644 --- a/pkg/handlers/internalapi/addresses_test.go +++ b/pkg/handlers/internalapi/addresses_test.go @@ -21,6 +21,7 @@ func fakeAddressPayload() *internalmessages.Address { State: models.StringPointer("AL"), PostalCode: models.StringPointer("40356"), County: models.StringPointer("JESSAMINE"), + IsOconus: models.BoolPointer(false), } } @@ -33,6 +34,7 @@ func (suite *HandlerSuite) TestShowAddressHandler() { State: "state", PostalCode: "12345", County: "JESSAMINE", + IsOconus: models.BoolPointer(false), } suite.MustSave(&address) diff --git a/pkg/handlers/internalapi/internal/payloads/model_to_payload.go b/pkg/handlers/internalapi/internal/payloads/model_to_payload.go index 96908a15230..905a2b3e2a6 100644 --- a/pkg/handlers/internalapi/internal/payloads/model_to_payload.go +++ b/pkg/handlers/internalapi/internal/payloads/model_to_payload.go @@ -32,6 +32,7 @@ func Address(address *models.Address) *internalmessages.Address { PostalCode: &address.PostalCode, Country: address.Country, County: &address.County, + IsOconus: address.IsOconus, } } diff --git a/pkg/migrate/fixtures/copyFromStdinKeywords.sql b/pkg/migrate/fixtures/copyFromStdinKeywords.sql index 6cd374b1eca..c89f904d17c 100644 --- a/pkg/migrate/fixtures/copyFromStdinKeywords.sql +++ b/pkg/migrate/fixtures/copyFromStdinKeywords.sql @@ -1,3 +1,3 @@ -COPY public.addresses (id, street_address_1, street_address_2, city, state, postal_code, created_at, updated_at, street_address_3, country) FROM stdin; -82b2ee8a-ee1c-48ef-a066-14ba1129330d 123 Any St \N Ellsworth DO AFB SD 57706 2018-05-28 14:27:38.959754 2018-05-28 14:27:38.959755 \N United States -\. +COPY public.addresses (id, street_address_1, street_address_2, city, state, postal_code, created_at, updated_at, street_address_3, is_oconus, country_id) FROM stdin; +82b2ee8a-ee1c-48ef-a066-14ba1129330d 123 Any St \N Ellsworth DO AFB SD 57706 2018-05-28 14:27:38.959754 2018-05-28 14:27:38.959755 \N f 791899e6-cd77-46f2-981b-176ecb8d7098 +\. \ No newline at end of file diff --git a/pkg/models/address.go b/pkg/models/address.go index 93b494b8c58..fe464d75100 100644 --- a/pkg/models/address.go +++ b/pkg/models/address.go @@ -169,3 +169,34 @@ func (a *Address) Copy() *Address { } return nil } + +// Check if an address is CONUS or OCONUS +func IsAddressOconus(db *pop.Connection, address Address) (bool, error) { + // use the data we have first, if it's not nil + if address.Country != nil { + isOconus := EvaluateIsOconus(address) + return isOconus, nil + } else if address.CountryId != nil { + country, err := FetchCountryByID(db, *address.CountryId) + if err != nil { + return false, err + } + address.Country = &country + isOconus := EvaluateIsOconus(address) + return isOconus, nil + } else { + if address.State == "HI" || address.State == "AK" { + return true, nil + } + return false, nil + } +} + +// Conditional logic for a CONUS and OCONUS address +func EvaluateIsOconus(address Address) bool { + if address.Country.Country != "US" || address.Country.Country == "US" && address.State == "AK" || address.Country.Country == "US" && address.State == "HI" { + return true + } else { + return false + } +} diff --git a/pkg/models/address_test.go b/pkg/models/address_test.go index 71dbc0385da..d6d1d2f08ea 100644 --- a/pkg/models/address_test.go +++ b/pkg/models/address_test.go @@ -94,3 +94,38 @@ func (suite *ModelSuite) TestAddressCountryCode() { suite.Equal("NotImplementedCountryCode: Country 'Ireland'", err.Error()) } + +func (suite *ModelSuite) TestIsAddressOconusNoCountry() { + address := m.Address{ + StreetAddress1: "street 1", + StreetAddress2: m.StringPointer("street 2"), + StreetAddress3: m.StringPointer("street 3"), + City: "city", + State: "SC", + PostalCode: "29229", + County: "county", + } + + result, err := m.IsAddressOconus(suite.DB(), address) + suite.NoError(err) + + suite.Equal(false, result) +} + +// Test IsOconus logic for an address with no country and a state of AK +func (suite *ModelSuite) TestIsAddressOconusForAKState() { + address := m.Address{ + StreetAddress1: "street 1", + StreetAddress2: m.StringPointer("street 2"), + StreetAddress3: m.StringPointer("street 3"), + City: "Anchorage", + State: "AK", + PostalCode: "99502", + County: "county", + } + + result, err := m.IsAddressOconus(suite.DB(), address) + suite.NoError(err) + + suite.Equal(true, result) +} diff --git a/pkg/models/service_member.go b/pkg/models/service_member.go index 7395ffa9ec1..49ed0a0e3d9 100644 --- a/pkg/models/service_member.go +++ b/pkg/models/service_member.go @@ -212,6 +212,15 @@ func SaveServiceMember(appCtx appcontext.AppContext, serviceMember *ServiceMembe responseError = err return err } + + // Evaluate address and populate addresses isOconus value + isOconus, err := IsAddressOconus(appCtx.DB(), *serviceMember.ResidentialAddress) + if err != nil { + responseError = err + return err + } + serviceMember.ResidentialAddress.IsOconus = &isOconus + serviceMember.ResidentialAddress.County = county if verrs, err := txnAppCtx.DB().ValidateAndSave(serviceMember.ResidentialAddress); verrs.HasAny() || err != nil { responseVErrors.Append(verrs) @@ -236,6 +245,14 @@ func SaveServiceMember(appCtx appcontext.AppContext, serviceMember *ServiceMembe serviceMember.BackupMailingAddressID = &serviceMember.BackupMailingAddress.ID } + // Evaluate address and populate addresses isOconus value + isOconus, err := IsAddressOconus(appCtx.DB(), *serviceMember.BackupMailingAddress) + if err != nil { + responseError = err + return err + } + serviceMember.BackupMailingAddress.IsOconus = &isOconus + if verrs, err := txnAppCtx.DB().ValidateAndSave(serviceMember); verrs.HasAny() || err != nil { responseVErrors.Append(verrs) responseError = err diff --git a/pkg/services/address/address_creator.go b/pkg/services/address/address_creator.go index 1b244888569..10eb17e6c06 100644 --- a/pkg/services/address/address_creator.go +++ b/pkg/services/address/address_creator.go @@ -36,6 +36,13 @@ func (f *addressCreator) CreateAddress(appCtx appcontext.AppContext, address *mo transformedAddress.County = county } + // Evaluate address and populate addresses isOconus value + isOconus, err := models.IsAddressOconus(appCtx.DB(), transformedAddress) + if err != nil { + return nil, err + } + transformedAddress.IsOconus = &isOconus + txnErr := appCtx.NewTransaction(func(txnCtx appcontext.AppContext) error { verrs, err := txnCtx.DB().Eager().ValidateAndCreate(&transformedAddress) if verrs != nil && verrs.HasAny() { diff --git a/pkg/services/address/address_creator_test.go b/pkg/services/address/address_creator_test.go index 26bf2281a88..c75c3864187 100644 --- a/pkg/services/address/address_creator_test.go +++ b/pkg/services/address/address_creator_test.go @@ -106,4 +106,22 @@ func (suite *AddressSuite) TestAddressCreator() { suite.NotNil(err) suite.Equal("No county found for provided zip code 11111", err.Error()) }) + + suite.Run("Successfully creates a CONUS address", func() { + country := &models.Country{} + country.Country = "US" + addressCreator := NewAddressCreator() + address, err := addressCreator.CreateAddress(suite.AppContextForTest(), &models.Address{ + StreetAddress1: "7645 Ballinshire N", + City: "Indianapolis", + State: "IN", + PostalCode: "46254", + Country: country, + }) + + suite.False(*address.IsOconus) + suite.NotNil(address.ID) + suite.Nil(err) + suite.NotNil(address.Country) + }) } diff --git a/pkg/services/address/address_updater.go b/pkg/services/address/address_updater.go index 46628610f31..7643069030c 100644 --- a/pkg/services/address/address_updater.go +++ b/pkg/services/address/address_updater.go @@ -47,6 +47,13 @@ func (f *addressUpdater) UpdateAddress(appCtx appcontext.AppContext, address *mo return nil, err } + // Evaluate address and populate addresses isOconus value + isOconus, err := models.IsAddressOconus(appCtx.DB(), mergedAddress) + if err != nil { + return nil, err + } + mergedAddress.IsOconus = &isOconus + txnErr := appCtx.NewTransaction(func(txnCtx appcontext.AppContext) error { verrs, err := txnCtx.DB().ValidateAndUpdate(&mergedAddress) if verrs != nil && verrs.HasAny() { diff --git a/pkg/services/address/address_updater_test.go b/pkg/services/address/address_updater_test.go index c062f6d6136..6a8eb61f87e 100644 --- a/pkg/services/address/address_updater_test.go +++ b/pkg/services/address/address_updater_test.go @@ -130,4 +130,22 @@ func (suite *AddressSuite) TestAddressUpdater() { expectedError := fmt.Sprintf("Data received from requester is bad: %s: invalid ID used for address", apperror.BadDataCode) suite.Equal(expectedError, err.Error()) }) + + suite.Run("Successfully updates a conus address and its IsOconus value", func() { + originalAddress := createOriginalAddress() + + addressUpdater := NewAddressUpdater() + desiredAddress := &models.Address{ + ID: originalAddress.ID, + StreetAddress1: streetAddress1, + City: city, + State: state, + PostalCode: postalCode, + } + updatedAddress, err := addressUpdater.UpdateAddress(suite.AppContextForTest(), desiredAddress, etag.GenerateEtag(originalAddress.UpdatedAt)) + + suite.NotNil(updatedAddress) + suite.Nil(err) + suite.Equal(false, *updatedAddress.IsOconus) + }) } diff --git a/pkg/services/mto_service_item/mto_service_item_creator.go b/pkg/services/mto_service_item/mto_service_item_creator.go index ba735f35a85..830de9ecc85 100644 --- a/pkg/services/mto_service_item/mto_service_item_creator.go +++ b/pkg/services/mto_service_item/mto_service_item_creator.go @@ -482,6 +482,13 @@ func (o *mtoServiceItemCreator) CreateMTOServiceItem(appCtx appcontext.AppContex } serviceItem.SITOriginHHGActualAddress.County = county + // Evaluate address and populate addresses isOconus value + isOconus, err := models.IsAddressOconus(appCtx.DB(), *serviceItem.SITOriginHHGActualAddress) + if err != nil { + return nil, nil, err + } + serviceItem.SITOriginHHGActualAddress.IsOconus = &isOconus + // update the SIT service item to track/save the HHG original pickup address (that came from the // MTO shipment serviceItem.SITOriginHHGOriginalAddress = mtoShipment.PickupAddress.Copy() diff --git a/pkg/services/office_user/customer/customer.go b/pkg/services/office_user/customer/customer.go index 1ff0ea7f54b..3fbf4ae2428 100644 --- a/pkg/services/office_user/customer/customer.go +++ b/pkg/services/office_user/customer/customer.go @@ -29,5 +29,28 @@ func (f fetchCustomer) FetchCustomer(appCtx appcontext.AppContext, customerID uu return &models.ServiceMember{}, apperror.NewQueryError("ServiceMember", err, "") } } + + if customer.ResidentialAddress != nil { + if customer.ResidentialAddress.IsOconus == nil { + // Evaluate address and populate addresses isOconus value + isOconus, err := models.IsAddressOconus(appCtx.DB(), *customer.ResidentialAddress) + if err != nil { + return nil, err + } + customer.ResidentialAddress.IsOconus = &isOconus + } + } + + if customer.BackupMailingAddress != nil { + if customer.BackupMailingAddress.IsOconus == nil { + // Evaluate address and populate addresses isOconus value + isOconus, err := models.IsAddressOconus(appCtx.DB(), *customer.BackupMailingAddress) + if err != nil { + return nil, err + } + customer.BackupMailingAddress.IsOconus = &isOconus + } + } + return customer, nil } diff --git a/pkg/testdatagen/make_address.go b/pkg/testdatagen/make_address.go index a251cf43beb..93dc7b145eb 100644 --- a/pkg/testdatagen/make_address.go +++ b/pkg/testdatagen/make_address.go @@ -17,6 +17,7 @@ func MakeAddress(db *pop.Connection, assertions Assertions) models.Address { PostalCode: "90210", Country: models.StringPointer("US"), County: "LOS ANGELES", + IsOconus: models.BoolPointer(false), } mergeModels(&address, assertions.Address) @@ -37,6 +38,7 @@ func MakeAddress2(db *pop.Connection, assertions Assertions) models.Address { PostalCode: "94535", Country: models.StringPointer("US"), County: "SOLANO", + IsOconus: models.BoolPointer(false), } mergeModels(&address, assertions.Address) @@ -57,6 +59,7 @@ func MakeAddress3(db *pop.Connection, assertions Assertions) models.Address { PostalCode: "50309", Country: models.StringPointer("US"), County: "POLK", + IsOconus: models.BoolPointer(false), } mergeModels(&address, assertions.Address) From b65c62178ddf229aaf28f89522d3d95846440753 Mon Sep 17 00:00:00 2001 From: pambecker Date: Thu, 17 Oct 2024 16:02:05 +0000 Subject: [PATCH 13/25] button alignment, css changes --- src/pages/Office/MoveDetails/MoveDetails.jsx | 42 ++++++++++--------- .../Office/TXOMoveInfo/TXOTab.module.scss | 2 +- 2 files changed, 23 insertions(+), 21 deletions(-) diff --git a/src/pages/Office/MoveDetails/MoveDetails.jsx b/src/pages/Office/MoveDetails/MoveDetails.jsx index ac2426904ee..7f1f53212fa 100644 --- a/src/pages/Office/MoveDetails/MoveDetails.jsx +++ b/src/pages/Office/MoveDetails/MoveDetails.jsx @@ -422,17 +422,28 @@ const MoveDetails = ({ -
-

Move details

- -
- -
-
+
+ + {alertMessage && ( + + + {alertMessage} + + + )} + + +

Move details

+ +
+ +
+
+
{isFinancialModalVisible && ( )} - - {alertMessage && ( - - - {alertMessage} - - - )} -
diff --git a/src/pages/Office/TXOMoveInfo/TXOTab.module.scss b/src/pages/Office/TXOMoveInfo/TXOTab.module.scss index d1236e837fa..86ae35a376f 100644 --- a/src/pages/Office/TXOMoveInfo/TXOTab.module.scss +++ b/src/pages/Office/TXOMoveInfo/TXOTab.module.scss @@ -42,11 +42,11 @@ flex-direction: row; justify-content: space-between; align-items: baseline; - padding-bottom: 30px; } .tooMoveDetailsH1 { @include u-margin-bottom(0); + align-self: center; } .tooCancelMoveContainer { From 7e5ab7562316721bb6100a5a9ebcd63d7644435b Mon Sep 17 00:00:00 2001 From: pambecker Date: Fri, 18 Oct 2024 16:39:21 +0000 Subject: [PATCH 14/25] spelling updates, happo changes --- .../Office/ShipmentDisplay/ShipmentDisplay.stories.jsx | 10 +++++----- .../Office/ShipmentDisplay/ShipmentDisplay.test.jsx | 4 ++-- .../Office/ShipmentDisplay/ShipmentDisplayTestData.js | 2 +- .../Office/ShipmentHeading/shipmentheading.stories.jsx | 2 +- 4 files changed, 9 insertions(+), 9 deletions(-) diff --git a/src/components/Office/ShipmentDisplay/ShipmentDisplay.stories.jsx b/src/components/Office/ShipmentDisplay/ShipmentDisplay.stories.jsx index 2f4c4e3ef12..f9bbbb6ba14 100644 --- a/src/components/Office/ShipmentDisplay/ShipmentDisplay.stories.jsx +++ b/src/components/Office/ShipmentDisplay/ShipmentDisplay.stories.jsx @@ -9,7 +9,7 @@ import { ntsReleaseMissingInfo, postalOnlyInfo, diversionInfo, - cancelledInfo, + canceledInfo, ppmInfo, ppmInfoApprovedOrExcluded, ppmInfoRejected, @@ -250,11 +250,11 @@ export const DivertedShipment = () => (
); -export const CancelledShipment = () => ( +export const CanceledShipment = () => (
(
); -export const CancelledShipmentReadOnly = () => ( +export const CanceledShipmentReadOnly = () => (
{ expect(screen.getByText('diversion')).toBeInTheDocument(); }); it('renders with canceled tag', () => { - render(); + render(); expect(screen.getByText('canceled')).toBeInTheDocument(); }); it('renders a disabled button when move is locked', () => { diff --git a/src/components/Office/ShipmentDisplay/ShipmentDisplayTestData.js b/src/components/Office/ShipmentDisplay/ShipmentDisplayTestData.js index 5bf1b4e5a11..b3c584fc751 100644 --- a/src/components/Office/ShipmentDisplay/ShipmentDisplayTestData.js +++ b/src/components/Office/ShipmentDisplay/ShipmentDisplayTestData.js @@ -127,7 +127,7 @@ export const diversionInfo = { counselorRemarks: 'counselor approved', }; -export const cancelledInfo = { +export const canceledInfo = { heading: 'HHG', shipmentId: 'testShipmentId394', isDiversion: false, diff --git a/src/components/Office/ShipmentHeading/shipmentheading.stories.jsx b/src/components/Office/ShipmentHeading/shipmentheading.stories.jsx index 9bc7911df34..e46d51cebee 100644 --- a/src/components/Office/ShipmentHeading/shipmentheading.stories.jsx +++ b/src/components/Office/ShipmentHeading/shipmentheading.stories.jsx @@ -49,7 +49,7 @@ export const shipmentHeadingDiversion = () => ( ); -export const shipmentHeadingCancelled = () => ( +export const shipmentHeadingCanceled = () => ( Date: Tue, 22 Oct 2024 18:18:22 +0000 Subject: [PATCH 15/25] changes per peer review, not needed code --- pkg/services/event/ghc_endpoint.go | 7 ------- .../ServicesCounselingMoveDetails.jsx | 1 - src/services/ghcApi.js | 3 +-- 3 files changed, 1 insertion(+), 10 deletions(-) diff --git a/pkg/services/event/ghc_endpoint.go b/pkg/services/event/ghc_endpoint.go index 8e37fb3a1a9..78f3c192ab3 100644 --- a/pkg/services/event/ghc_endpoint.go +++ b/pkg/services/event/ghc_endpoint.go @@ -127,9 +127,6 @@ const GhcUpdateMaxBillableWeightAsTIOEndpointKey = "Ghc.UpdateMaxBillableWeightA // GhcAcknowledgeExcessWeightRiskEndpointKey is the key for the AcknowledgeExcessWeightRisk endpoint in ghc const GhcAcknowledgeExcessWeightRiskEndpointKey = "Ghc.AcknowledgeExcessWeightRisk" -// GhcMoveCancelerEndpointKey is the key for the moveCanceler endpoint in ghc -const GhcMoveCancelerEndpointKey = "Ghc.MoveCanceler" - // -------------------- ENDPOINT MAP ENTRIES -------------------- var ghcEndpoints = EndpointMapType{ GhcGetCustomerEndpointKey: { @@ -288,8 +285,4 @@ var ghcEndpoints = EndpointMapType{ APIName: GhcAPIName, OperationID: "AcknowledgeExcessWeightRisk", }, - GhcMoveCancelerEndpointKey: { - APIName: GhcAPIName, - OperationID: "moveCanceler", - }, } diff --git a/src/pages/Office/ServicesCounselingMoveDetails/ServicesCounselingMoveDetails.jsx b/src/pages/Office/ServicesCounselingMoveDetails/ServicesCounselingMoveDetails.jsx index b57f50fdbeb..5db21407df5 100644 --- a/src/pages/Office/ServicesCounselingMoveDetails/ServicesCounselingMoveDetails.jsx +++ b/src/pages/Office/ServicesCounselingMoveDetails/ServicesCounselingMoveDetails.jsx @@ -509,7 +509,6 @@ const ServicesCounselingMoveDetails = ({ const handleCancelMove = () => { mutateCancelMove({ moveID: move.id, - ifMatchETag: move.eTag, }); setIsCancelMoveModalVisible(false); }; diff --git a/src/services/ghcApi.js b/src/services/ghcApi.js index 7df5d0c612f..b99dc5c91c9 100644 --- a/src/services/ghcApi.js +++ b/src/services/ghcApi.js @@ -432,13 +432,12 @@ export function updateMoveStatusServiceCounselingCompleted({ moveTaskOrderID, if ); } -export function cancelMove({ moveID, ifMatchETag, normalize = false }) { +export function cancelMove({ moveID, normalize = false }) { const operationPath = 'move.moveCanceler'; return makeGHCRequest( operationPath, { moveID, - 'If-Match': ifMatchETag, }, { normalize }, ); From 4feb66d24c31205a26513cdcc8bdfcfe5245b5f1 Mon Sep 17 00:00:00 2001 From: pambecker Date: Tue, 22 Oct 2024 20:39:14 +0000 Subject: [PATCH 16/25] fix merge conflict --- src/components/Office/ShipmentHeading/ShipmentHeading.jsx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/components/Office/ShipmentHeading/ShipmentHeading.jsx b/src/components/Office/ShipmentHeading/ShipmentHeading.jsx index 99f607ec5dd..b5fccbe774b 100644 --- a/src/components/Office/ShipmentHeading/ShipmentHeading.jsx +++ b/src/components/Office/ShipmentHeading/ShipmentHeading.jsx @@ -25,7 +25,7 @@ function ShipmentHeading({ shipmentInfo, handleShowCancellationModal, isMoveLock {shipmentInfo.marketCode} {shipmentInfo.shipmentType} - {shipmentStatus === shipmentStatuses.CANCELED && cancelled} + {shipmentStatus === shipmentStatuses.CANCELED && canceled} {shipmentInfo.isDiversion && diversion} {!shipmentInfo.isDiversion && shipmentStatus === shipmentStatuses.DIVERSION_REQUESTED && ( diversion requested From a752a618918d592992a8ccaa97be7f6e6567b148 Mon Sep 17 00:00:00 2001 From: pambecker Date: Wed, 23 Oct 2024 14:43:16 +0000 Subject: [PATCH 17/25] adding tests --- pkg/services/move/move_canceler_test.go | 19 ++++++++++++++ .../Office/MoveDetails/MoveDetails.test.jsx | 20 +++++++++++++++ .../ServicesCounselingMoveDetails.test.jsx | 25 +++++++++++++++++++ 3 files changed, 64 insertions(+) diff --git a/pkg/services/move/move_canceler_test.go b/pkg/services/move/move_canceler_test.go index 314b0719075..0cad20c55eb 100644 --- a/pkg/services/move/move_canceler_test.go +++ b/pkg/services/move/move_canceler_test.go @@ -30,4 +30,23 @@ func (suite *MoveServiceSuite) TestMoveCanceler() { _, err := moveCanceler.CancelMove(suite.AppContextForTest(), move.ID) suite.Error(err) }) + + suite.Run("fails to cancel move with close complete ppm shipment", func() { + move := factory.BuildMove(suite.DB(), nil, nil) + + factory.BuildPPMShipment(suite.DB(), []factory.Customization{ + { + Model: move, + LinkOnly: true, + }, + { + Model: models.PPMShipment{ + Status: models.PPMShipmentStatusCloseoutComplete, + }, + }, + }, nil) + + _, err := moveCanceler.CancelMove(suite.AppContextForTest(), move.ID) + suite.Error(err) + }) } diff --git a/src/pages/Office/MoveDetails/MoveDetails.test.jsx b/src/pages/Office/MoveDetails/MoveDetails.test.jsx index 859ddea30b0..a6ad1a97aaf 100644 --- a/src/pages/Office/MoveDetails/MoveDetails.test.jsx +++ b/src/pages/Office/MoveDetails/MoveDetails.test.jsx @@ -1185,6 +1185,26 @@ describe('MoveDetails page', () => { expect(screen.queryByRole('link', { name: 'Edit allowances' })).not.toBeInTheDocument(); expect(screen.queryByRole('link', { name: 'Edit customer info' })).not.toBeInTheDocument(); }); + + it('renders the cancel move button when user has permission', async () => { + render( + + + , + ); + + expect(await screen.getByText('Cancel move')).toBeInTheDocument(); + }); + + it('does not show the cancel move button if user does not have permission', () => { + render( + + + , + ); + + expect(screen.queryByText('Cancel move')).not.toBeInTheDocument(); + }); }); describe('when MTO shipments are not yet defined', () => { diff --git a/src/pages/Office/ServicesCounselingMoveDetails/ServicesCounselingMoveDetails.test.jsx b/src/pages/Office/ServicesCounselingMoveDetails/ServicesCounselingMoveDetails.test.jsx index 2e3c7a329a8..d3484679fe8 100644 --- a/src/pages/Office/ServicesCounselingMoveDetails/ServicesCounselingMoveDetails.test.jsx +++ b/src/pages/Office/ServicesCounselingMoveDetails/ServicesCounselingMoveDetails.test.jsx @@ -1144,6 +1144,31 @@ describe('MoveDetails page', () => { expect(screen.queryByText('Edit customer info')).not.toBeInTheDocument(); }); + + it('renders the cancel move button when user has permission', async () => { + render( + + + , + ); + + expect(await screen.getByText('Cancel move')).toBeInTheDocument(); + }); + + it('does not show the cancel move button if user does not have permission', () => { + render( + + + , + ); + + expect(screen.queryByText('Cancel move')).not.toBeInTheDocument(); + }); }); }); }); From cdaa231202a30de58eb2934256265be009152f1f Mon Sep 17 00:00:00 2001 From: Tevin Adams Date: Wed, 23 Oct 2024 16:59:18 +0000 Subject: [PATCH 18/25] Adding the rest of the changes from int PR --- ...04203140_update_addresses_is_oconus.up.sql | 15 +++++---- pkg/factory/address_factory_test.go | 3 ++ pkg/models/service_member.go | 32 +++++-------------- 3 files changed, 19 insertions(+), 31 deletions(-) diff --git a/migrations/app/schema/20241004203140_update_addresses_is_oconus.up.sql b/migrations/app/schema/20241004203140_update_addresses_is_oconus.up.sql index 9d72e8c70d3..946cf557181 100644 --- a/migrations/app/schema/20241004203140_update_addresses_is_oconus.up.sql +++ b/migrations/app/schema/20241004203140_update_addresses_is_oconus.up.sql @@ -1,9 +1,10 @@ --- Set temp timeout due to potentially large modification --- Time is 5 minutes in milliseconds -SET statement_timeout = 300000; -SET lock_timeout = 300000; -SET idle_in_transaction_session_timeout = 300000; - -- Update is_oconus value on the addresses table based on the addresses country and the state UPDATE addresses -SET is_oconus = CASE \ No newline at end of file +SET is_oconus = CASE + WHEN country_id is null OR (Select country from re_countries where id = country_id ) = 'US' AND state NOT IN ('AK', 'HI') THEN false + ELSE true + END; + +-- Update is_oconus value on the addresses table to be not null +ALTER TABLE addresses + ALTER COLUMN is_oconus SET NOT NULL; diff --git a/pkg/factory/address_factory_test.go b/pkg/factory/address_factory_test.go index 6c77027d5e3..77998151f12 100644 --- a/pkg/factory/address_factory_test.go +++ b/pkg/factory/address_factory_test.go @@ -243,6 +243,7 @@ func (suite *FactorySuite) TestBuildMinimalAddress() { Model: models.Address{ StreetAddress1: customStreet, PostalCode: customPostalCode, + IsOconus: models.BoolPointer(false), }, }, }, nil) @@ -289,6 +290,7 @@ func (suite *FactorySuite) TestBuildMinimalAddress() { Model: models.Address{ StreetAddress1: customStreet, PostalCode: customPostalCode, + IsOconus: models.BoolPointer(false), }, }, }, nil) @@ -316,6 +318,7 @@ func (suite *FactorySuite) TestBuildMinimalAddress() { ID: uuid.Must(uuid.NewV4()), StreetAddress1: customStreet, PostalCode: customPostalCode, + IsOconus: models.BoolPointer(false), }, LinkOnly: true, }, diff --git a/pkg/models/service_member.go b/pkg/models/service_member.go index 53af72415dd..3e555c46aa9 100644 --- a/pkg/models/service_member.go +++ b/pkg/models/service_member.go @@ -297,31 +297,15 @@ func SaveServiceMember(appCtx appcontext.AppContext, serviceMember *ServiceMembe serviceMember.BackupMailingAddress.CountryId = &country.ID } - if serviceMember.BackupMailingAddress.Country != nil { - country := serviceMember.BackupMailingAddress.Country - if country.Country != "US" || country.Country == "US" && serviceMember.BackupMailingAddress.State == "AK" || country.Country == "US" && serviceMember.BackupMailingAddress.State == "HI" { - boolTrueVal := true - serviceMember.BackupMailingAddress.IsOconus = &boolTrueVal - } else { - boolFalseVal := false - serviceMember.BackupMailingAddress.IsOconus = &boolFalseVal - } - } else if serviceMember.BackupMailingAddress.CountryId != nil { - country, err := FetchCountryByID(appCtx.DB(), *serviceMember.BackupMailingAddress.CountryId) - if err != nil { - return err - } - if country.Country != "US" || country.Country == "US" && serviceMember.BackupMailingAddress.State == "AK" || country.Country == "US" && serviceMember.BackupMailingAddress.State == "HI" { - boolTrueVal := true - serviceMember.BackupMailingAddress.IsOconus = &boolTrueVal - } else { - boolFalseVal := false - serviceMember.BackupMailingAddress.IsOconus = &boolFalseVal - } - } else { - boolFalseVal := false - serviceMember.BackupMailingAddress.IsOconus = &boolFalseVal + // Evaluate address and populate addresses isOconus value + isOconus, err := IsAddressOconus(appCtx.DB(), *serviceMember.BackupMailingAddress) + if err != nil { + responseError = err + return err } + + serviceMember.BackupMailingAddress.IsOconus = &isOconus + if verrs, err := txnAppCtx.DB().ValidateAndSave(serviceMember.BackupMailingAddress); verrs.HasAny() || err != nil { responseVErrors.Append(verrs) responseError = err From 0d1ae6525885a0ab98c8cc11b8a96f58efadd26b Mon Sep 17 00:00:00 2001 From: Tevin Adams Date: Wed, 23 Oct 2024 17:10:43 +0000 Subject: [PATCH 19/25] Remove change thats not in int PR --- pkg/models/service_member.go | 9 --------- 1 file changed, 9 deletions(-) diff --git a/pkg/models/service_member.go b/pkg/models/service_member.go index 3e555c46aa9..ff0da40de2c 100644 --- a/pkg/models/service_member.go +++ b/pkg/models/service_member.go @@ -303,7 +303,6 @@ func SaveServiceMember(appCtx appcontext.AppContext, serviceMember *ServiceMembe responseError = err return err } - serviceMember.BackupMailingAddress.IsOconus = &isOconus if verrs, err := txnAppCtx.DB().ValidateAndSave(serviceMember.BackupMailingAddress); verrs.HasAny() || err != nil { @@ -314,14 +313,6 @@ func SaveServiceMember(appCtx appcontext.AppContext, serviceMember *ServiceMembe serviceMember.BackupMailingAddressID = &serviceMember.BackupMailingAddress.ID } - // Evaluate address and populate addresses isOconus value - isOconus, err := IsAddressOconus(appCtx.DB(), *serviceMember.BackupMailingAddress) - if err != nil { - responseError = err - return err - } - serviceMember.BackupMailingAddress.IsOconus = &isOconus - if verrs, err := txnAppCtx.DB().ValidateAndSave(serviceMember); verrs.HasAny() || err != nil { responseVErrors.Append(verrs) responseError = err From be70c0b0eed753a7e9998150d1158bf0f1ac88e5 Mon Sep 17 00:00:00 2001 From: Tevin Adams Date: Wed, 23 Oct 2024 17:39:34 +0000 Subject: [PATCH 20/25] Missed this test addition --- pkg/factory/address_factory.go | 1 + 1 file changed, 1 insertion(+) diff --git a/pkg/factory/address_factory.go b/pkg/factory/address_factory.go index fdd1339cb61..c5cef466f6f 100644 --- a/pkg/factory/address_factory.go +++ b/pkg/factory/address_factory.go @@ -32,6 +32,7 @@ func BuildAddress(db *pop.Connection, customs []Customization, traits []Trait) m State: "CA", PostalCode: "90210", County: "LOS ANGELES", + IsOconus: models.BoolPointer(false), } // Find/create the Country if customization is provided From 3d8884a010a13bce204c4a2ab365f177d9e90e0f Mon Sep 17 00:00:00 2001 From: pambecker Date: Wed, 23 Oct 2024 17:46:55 +0000 Subject: [PATCH 21/25] fix merge conflict --- .../Office/DefinitionLists/ShipmentInfoListSelector.jsx | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/components/Office/DefinitionLists/ShipmentInfoListSelector.jsx b/src/components/Office/DefinitionLists/ShipmentInfoListSelector.jsx index 9c9d6ff7c09..6830db6b735 100644 --- a/src/components/Office/DefinitionLists/ShipmentInfoListSelector.jsx +++ b/src/components/Office/DefinitionLists/ShipmentInfoListSelector.jsx @@ -6,8 +6,8 @@ import ShipmentInfoList from 'components/Office/DefinitionLists/ShipmentInfoList import PPMShipmentInfoList from 'components/Office/DefinitionLists/PPMShipmentInfoList'; import NTSRShipmentInfoList from 'components/Office/DefinitionLists/NTSRShipmentInfoList'; import NTSShipmentInfoList from 'components/Office/DefinitionLists/NTSShipmentInfoList'; -import BoatShipmentInfoList from 'components/Office/DefinitionLists/BoatShipmentInfoList'; import MobileHomeShipmentInfoList from 'components/Office/DefinitionLists/MobileHomeShipmentInfoList'; +import BoatShipmentInfoList from 'components/Office/DefinitionLists/BoatShipmentInfoList'; import { SHIPMENT_OPTIONS, SHIPMENT_TYPES } from 'shared/constants'; import { fieldValidationShape } from 'utils/displayFlags'; From c3f10590260a73f5cc9f654465aaaa5ab8757bfc Mon Sep 17 00:00:00 2001 From: pambecker Date: Wed, 23 Oct 2024 18:30:07 +0000 Subject: [PATCH 22/25] more tests --- .../Office/ShipmentDisplay/ShipmentDisplay.test.jsx | 12 ++++++++++++ 1 file changed, 12 insertions(+) diff --git a/src/components/Office/ShipmentDisplay/ShipmentDisplay.test.jsx b/src/components/Office/ShipmentDisplay/ShipmentDisplay.test.jsx index c7b65b8ebfc..4e349e2f9fa 100644 --- a/src/components/Office/ShipmentDisplay/ShipmentDisplay.test.jsx +++ b/src/components/Office/ShipmentDisplay/ShipmentDisplay.test.jsx @@ -140,6 +140,10 @@ describe('Shipment Container', () => { ); expect(screen.getByTestId('shipment-display-checkbox')).toBeDisabled(); }); + it('renders with canceled tag', () => { + render(); + expect(screen.getByText('canceled')).toBeInTheDocument(); + }); }); describe('NTS-release shipment', () => { @@ -177,6 +181,10 @@ describe('Shipment Container', () => { expect(screen.getByText('external vendor')).toBeInTheDocument(); }); + it('renders with canceled tag', () => { + render(); + expect(screen.getByText('canceled')).toBeInTheDocument(); + }); it('renders with external vendor tag', () => { render( { ); expect(screen.getByTestId('tag', { name: 'packet ready for download' })).toBeInTheDocument(); }); + it('renders with canceled tag', () => { + render(); + expect(screen.getByText('canceled')).toBeInTheDocument(); + }); it('excluded', () => { render( From 1cb99828c590f54aaccc73b6601fcf4cc06ab043 Mon Sep 17 00:00:00 2001 From: Tevin Adams Date: Tue, 15 Oct 2024 17:05:30 +0000 Subject: [PATCH 23/25] increasing statement timeout --- .../schema/20241004203140_update_addresses_is_oconus.up.sql | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/migrations/app/schema/20241004203140_update_addresses_is_oconus.up.sql b/migrations/app/schema/20241004203140_update_addresses_is_oconus.up.sql index 946cf557181..2bc4014cf27 100644 --- a/migrations/app/schema/20241004203140_update_addresses_is_oconus.up.sql +++ b/migrations/app/schema/20241004203140_update_addresses_is_oconus.up.sql @@ -1,3 +1,9 @@ +-- Set temp timeout due to potentially large modification +-- Time is 5 minutes in milliseconds +SET statement_timeout = 300000; +SET lock_timeout = 300000; +SET idle_in_transaction_session_timeout = 300000; + -- Update is_oconus value on the addresses table based on the addresses country and the state UPDATE addresses SET is_oconus = CASE From 216764670abcbee18560c7d8a2a5a73205fe0882 Mon Sep 17 00:00:00 2001 From: pambecker Date: Thu, 24 Oct 2024 11:52:36 +0000 Subject: [PATCH 24/25] test case --- .../ServicesCounselingMoveDetails.jsx | 1 + src/services/ghcApi.js | 3 ++- 2 files changed, 3 insertions(+), 1 deletion(-) diff --git a/src/pages/Office/ServicesCounselingMoveDetails/ServicesCounselingMoveDetails.jsx b/src/pages/Office/ServicesCounselingMoveDetails/ServicesCounselingMoveDetails.jsx index 7251adf1525..ac4e3b3e7dc 100644 --- a/src/pages/Office/ServicesCounselingMoveDetails/ServicesCounselingMoveDetails.jsx +++ b/src/pages/Office/ServicesCounselingMoveDetails/ServicesCounselingMoveDetails.jsx @@ -524,6 +524,7 @@ const ServicesCounselingMoveDetails = ({ const handleCancelMove = () => { mutateCancelMove({ moveID: move.id, + ifMatchETag: move.eTag, }); setIsCancelMoveModalVisible(false); }; diff --git a/src/services/ghcApi.js b/src/services/ghcApi.js index b99dc5c91c9..7df5d0c612f 100644 --- a/src/services/ghcApi.js +++ b/src/services/ghcApi.js @@ -432,12 +432,13 @@ export function updateMoveStatusServiceCounselingCompleted({ moveTaskOrderID, if ); } -export function cancelMove({ moveID, normalize = false }) { +export function cancelMove({ moveID, ifMatchETag, normalize = false }) { const operationPath = 'move.moveCanceler'; return makeGHCRequest( operationPath, { moveID, + 'If-Match': ifMatchETag, }, { normalize }, ); From 67ef509516005808798f563a8a6993393082dc5c Mon Sep 17 00:00:00 2001 From: pambecker Date: Thu, 24 Oct 2024 13:59:58 +0000 Subject: [PATCH 25/25] undoing changes that I thought help test case issues to pass --- .circleci/config.yml | 138 +++++++++--------- .../ServicesCounselingMoveDetails.jsx | 1 - src/services/ghcApi.js | 3 +- 3 files changed, 71 insertions(+), 71 deletions(-) diff --git a/.circleci/config.yml b/.circleci/config.yml index cf8c895b5bc..fc63fab1d8e 100644 --- a/.circleci/config.yml +++ b/.circleci/config.yml @@ -259,7 +259,7 @@ executors: commands: create_dot_go_version: - description: 'Creates a .go-version file (if needed) which can be used for cache keys specific to golang' + description: "Creates a .go-version file (if needed) which can be used for cache keys specific to golang" steps: - run: name: Create a .go-version file @@ -285,13 +285,13 @@ commands: - save_cache: key: go-mod-sources-v8-{{ checksum "go.sum" }}-{{ checksum ".go-version" }} paths: - - '~/go' - - '~/transcom/mymove/bin/swagger' + - "~/go" + - "~/transcom/mymove/bin/swagger" aws_vars_stg: steps: - run: - name: 'Setting up AWS environment variables for stg env' + name: "Setting up AWS environment variables for stg env" command: | echo "export AWS_DEFAULT_REGION=$STG_REGION" >> $BASH_ENV echo "export AWS_ACCOUNT_ID=$STG_ACCOUNT_ID" >> $BASH_ENV @@ -304,7 +304,7 @@ commands: tls_vars_stg: steps: - run: - name: 'Setting up TLS environment variables for stg env' + name: "Setting up TLS environment variables for stg env" command: | echo "export TLS_CERT=$STG_MOVE_MIL_DOD_TLS_CERT" >> $BASH_ENV echo "export TLS_KEY=$STG_MOVE_MIL_DOD_TLS_KEY" >> $BASH_ENV @@ -313,7 +313,7 @@ commands: aws_vars_prd: steps: - run: - name: 'Setting up AWS environment variables for prd env' + name: "Setting up AWS environment variables for prd env" command: | echo "export AWS_DEFAULT_REGION=$PRD_REGION" >> $BASH_ENV echo "export AWS_ACCOUNT_ID=$PRD_ACCOUNT_ID" >> $BASH_ENV @@ -326,7 +326,7 @@ commands: tls_vars_prd: steps: - run: - name: 'Setting up TLS environment variables for prd env' + name: "Setting up TLS environment variables for prd env" command: | echo "export TLS_CERT=$PRD_MOVE_MIL_DOD_TLS_CERT" >> $BASH_ENV echo "export TLS_KEY=$PRD_MOVE_MIL_DOD_TLS_KEY" >> $BASH_ENV @@ -340,7 +340,7 @@ commands: default: on_success steps: - run: - name: 'Setting up AWS environment variables for gov-dev env' + name: "Setting up AWS environment variables for gov-dev env" command: | echo "export AWS_DEFAULT_REGION=$GOV_DEV_REGION" >> $BASH_ENV echo "export AWS_ACCOUNT_ID=$GOV_DEV_ACCOUNT_ID" >> $BASH_ENV @@ -351,7 +351,7 @@ commands: tls_vars_gov_dev: steps: - run: - name: 'Setting up TLS environment variables for gov-dev env' + name: "Setting up TLS environment variables for gov-dev env" command: | echo "export TLS_CERT=$EXPERIMENTAL_MOVE_MIL_DOD_TLS_CERT" >> $BASH_ENV echo "export TLS_KEY=$EXPERIMENTAL_MOVE_MIL_DOD_TLS_KEY" >> $BASH_ENV @@ -360,7 +360,7 @@ commands: aws_vars_transcom_com_dev: steps: - run: - name: 'Setting up AWS environment variables for com-dev env' + name: "Setting up AWS environment variables for com-dev env" command: | echo "export AWS_DEFAULT_REGION=$COM_REGION" >> $BASH_ENV echo "export AWS_ACCOUNT_ID=$DEV_ACCOUNT_ID" >> $BASH_ENV @@ -375,7 +375,7 @@ commands: default: *dp3-env steps: - run: - name: 'Setting up AWS environment variables for dp3 env defined in &dp3-env' + name: "Setting up AWS environment variables for dp3 env defined in &dp3-env" command: | echo "export AWS_DEFAULT_REGION=\$$(echo << parameters.dp3-env >> | tr 'a-z' 'A-Z')_REGION" >> $BASH_ENV echo "export AWS_ACCOUNT_ID=\$$(echo << parameters.dp3-env >> | tr 'a-z' 'A-Z')_ACCOUNT_ID" >> $BASH_ENV @@ -386,7 +386,7 @@ commands: equal: [loadtest, << parameters.dp3-env >>] steps: - run: - name: 'Increase cpu/memory reservation for loadtest' + name: "Increase cpu/memory reservation for loadtest" command: | # override default cpu/memory echo "export SERVICE_RESERVATION_CPU=2048" >> $BASH_ENV @@ -400,7 +400,7 @@ commands: default: *dp3-env steps: - run: - name: 'Setting up TLS environment variables for dp3 env defined in &dp3-env' + name: "Setting up TLS environment variables for dp3 env defined in &dp3-env" command: | echo "export TLS_CERT=\$$(echo << parameters.dp3-env >> | tr 'a-z' 'A-Z')_DP3_CERT" >> $BASH_ENV echo "export TLS_KEY=\$$(echo << parameters.dp3-env >> | tr 'a-z' 'A-Z')_DP3_KEY" >> $BASH_ENV @@ -604,7 +604,7 @@ commands: - setup_remote_docker: docker_layer_caching: false - run: - name: 'Build docker image' + name: "Build docker image" working_directory: << parameters.working_dir >> command: | docker build -f << parameters.dockerfile>> -t << parameters.image_name >>:<< parameters.tag >> . @@ -631,11 +631,11 @@ commands: - setup_remote_docker: docker_layer_caching: false - run: - name: 'Retrieve docker image from workspace' + name: "Retrieve docker image from workspace" command: | docker load -i images/<< parameters.image_name >> - run: - name: 'Tag and push docker image' + name: "Tag and push docker image" command: | aws ecr get-login-password --region $AWS_DEFAULT_REGION | docker login --username AWS --password-stdin ${AWS_ACCOUNT_ID}.dkr.ecr.${AWS_DEFAULT_REGION}.amazonaws.com @@ -652,14 +652,14 @@ commands: docker tag << parameters.image_name >>:<< parameters.tag >> ${AWS_ACCOUNT_ID}.dkr.ecr.${AWS_DEFAULT_REGION}.amazonaws.com/<< parameters.repo >>:git-branch-${docker_tag_shortened_name} docker push ${AWS_ACCOUNT_ID}.dkr.ecr.${AWS_DEFAULT_REGION}.amazonaws.com/<< parameters.repo >>:git-branch-${docker_tag_shortened_name} - run: - name: 'Record ECR Image Digest' + name: "Record ECR Image Digest" command: | mkdir -p images/sha echo $(aws ecr describe-images --repository-name << parameters.repo >> --image-ids imageTag=git-${CIRCLE_SHA1} | jq ".imageDetails[0] .imageDigest" -r) > images/sha/ECR_DIGEST_<< parameters.repo >>_<< parameters.ecr_env >> cat images/sha/ECR_DIGEST_<< parameters.repo >>_<< parameters.ecr_env >> sleep 60 - run: - name: 'Describe image scan findings' + name: "Describe image scan findings" command: scripts/ecr-describe-image-scan-findings << parameters.repo >> $(cat images/sha/ECR_DIGEST_<< parameters.repo >>_<< parameters.ecr_env >>) - persist_to_workspace: root: . @@ -687,7 +687,7 @@ commands: - attach_workspace: at: . - run: - name: 'Tag and push docker image' + name: "Tag and push docker image" command: | aws ecr get-login-password --region $AWS_DEFAULT_REGION | docker login --username AWS --password-stdin ${AWS_ACCOUNT_ID}.dkr.ecr.${AWS_DEFAULT_REGION}.amazonaws.com otel_image=$(echo << parameters.aws_otel_collector_image >>) @@ -704,7 +704,7 @@ commands: docker push "${repo_name}:git-${otel_image_tag}-${CIRCLE_SHA1}" - run: - name: 'Record ECR Image Digest' + name: "Record ECR Image Digest" command: | otel_image=$(echo << parameters.aws_otel_collector_image >>) shopt -s extglob @@ -752,7 +752,7 @@ commands: make server_test no_output_timeout: 20m environment: - APPLICATION: '<< parameters.application >>' + APPLICATION: "<< parameters.application >>" # 8 since this runs on xlarge with 8 CPUs GOTEST_PARALLEL: 8 DB_PASSWORD: mysecretpassword @@ -764,15 +764,15 @@ commands: DB_PORT: 5432 DB_NAME: test_db DB_NAME_TEST: test_db - DTOD_USE_MOCK: 'true' - MIGRATION_MANIFEST: '/home/circleci/transcom/mymove/migrations/<< parameters.application >>/migrations_manifest.txt' - MIGRATION_PATH: 'file:///home/circleci/transcom/mymove/migrations/<< parameters.application >>/schema;file:///home/circleci/transcom/mymove/migrations/<< parameters.application >>/secure' + DTOD_USE_MOCK: "true" + MIGRATION_MANIFEST: "/home/circleci/transcom/mymove/migrations/<< parameters.application >>/migrations_manifest.txt" + MIGRATION_PATH: "file:///home/circleci/transcom/mymove/migrations/<< parameters.application >>/schema;file:///home/circleci/transcom/mymove/migrations/<< parameters.application >>/secure" EIA_KEY: db2522a43820268a41a802a16ae9fd26 # dummy key generated with openssl rand -hex 16 ENV: test ENVIRONMENT: test SERVER_REPORT: 1 COVERAGE: 1 - SERVE_API_INTERNAL: 'true' + SERVE_API_INTERNAL: "true" OKTA_CUSTOMER_CLIENT_ID: 1q2w3e4r5t6y7u8i9o OKTA_ADMIN_CLIENT_ID: AQ1SW2DE3FR4G5 OKTA_OFFICE_CLIENT_ID: 9f9f9s8s90gig9 @@ -817,8 +817,8 @@ commands: background: true name: run server environment: - MIGRATION_MANIFEST: '/home/circleci/project/migrations/app/migrations_manifest.txt' - MIGRATION_PATH: 'file:///home/circleci/project/migrations/app/schema;file:///home/circleci/project/migrations/app/secure' + MIGRATION_MANIFEST: "/home/circleci/project/migrations/app/migrations_manifest.txt" + MIGRATION_PATH: "file:///home/circleci/project/migrations/app/schema;file:///home/circleci/project/migrations/app/secure" command: | export MOVE_MIL_DOD_CA_CERT=$(cat config/tls/devlocal-ca.pem) export MOVE_MIL_DOD_TLS_CERT=$(cat config/tls/devlocal-https.pem) @@ -877,8 +877,8 @@ commands: export FEATURE_FLAG_MANAGE_SUPPORTING_DOCS=false export FEATURE_FLAG_THIRD_ADDRESS_AVAILABLE=false export FEATURE_FLAG_QUEUE_MANAGEMENT=false - export FEATURE_FLAG_ENABLE_ALASKA=false export FEATURE_FLAG_UNACCOMPANIED_BAGGAGE=false + export FEATURE_FLAG_ENABLE_ALASKA=false # disable for speed, playwright tests can fail otherwise export DB_DEBUG=false @@ -962,8 +962,8 @@ commands: background: true name: run server environment: - MIGRATION_MANIFEST: '/home/circleci/transcom/mymove/migrations/app/migrations_manifest.txt' - MIGRATION_PATH: 'file:///home/circleci/transcom/mymove/migrations/app/schema;file:///home/circleci/transcom/mymove/migrations/app/secure' + MIGRATION_MANIFEST: "/home/circleci/transcom/mymove/migrations/app/migrations_manifest.txt" + MIGRATION_PATH: "file:///home/circleci/transcom/mymove/migrations/app/schema;file:///home/circleci/transcom/mymove/migrations/app/secure" command: | export MOVE_MIL_DOD_CA_CERT=$(cat config/tls/devlocal-ca.pem) export MOVE_MIL_DOD_TLS_CERT=$(cat config/tls/devlocal-https.pem) @@ -1051,8 +1051,8 @@ commands: background: true name: run server environment: - MIGRATION_MANIFEST: '/home/circleci/project/migrations/app/migrations_manifest.txt' - MIGRATION_PATH: 'file:///home/circleci/project/migrations/app/schema;file:///home/circleci/project/migrations/app/secure' + MIGRATION_MANIFEST: "/home/circleci/project/migrations/app/migrations_manifest.txt" + MIGRATION_PATH: "file:///home/circleci/project/migrations/app/schema;file:///home/circleci/project/migrations/app/secure" command: | export MOVE_MIL_DOD_CA_CERT=$(cat config/tls/devlocal-ca.pem) export MOVE_MIL_DOD_TLS_CERT=$(cat config/tls/devlocal-https.pem) @@ -1146,7 +1146,7 @@ commands: - save_cache: key: v2-pipenv-{{ checksum "Pipfile.lock" }}-{{ .Environment.PYTHON_VERSION }} paths: - - '~/transcom/mymove/tmp/milmove_load_testing/.venv' + - "~/transcom/mymove/tmp/milmove_load_testing/.venv" - run: name: extract results # always try to extract the artifacts so it can help us @@ -1410,8 +1410,8 @@ jobs: DB_PORT: 5432 DB_NAME: dev_db DB_NAME_DEV: dev_db - MIGRATION_MANIFEST: '/home/circleci/transcom/mymove/migrations/app/migrations_manifest.txt' - MIGRATION_PATH: 'file:///home/circleci/transcom/mymove/migrations/app/schema;file:///home/circleci/transcom/mymove/migrations/app/secure' + MIGRATION_MANIFEST: "/home/circleci/transcom/mymove/migrations/app/migrations_manifest.txt" + MIGRATION_PATH: "file:///home/circleci/transcom/mymove/migrations/app/schema;file:///home/circleci/transcom/mymove/migrations/app/secure" EIA_KEY: db2522a43820268a41a802a16ae9fd26 # dummy key generated with openssl rand -hex 16 ENVIRONMENT: development DOD_CA_PACKAGE: /home/circleci/transcom/mymove/config/tls/milmove-cert-bundle.p7b @@ -1512,7 +1512,7 @@ jobs: - run: # on failure, post a comment to the PR with a link to the report when: on_fail - name: 'Post server coverage failure comment to GitHub' + name: "Post server coverage failure comment to GitHub" command: | source server_test_job_id.env ./scripts/handle-pr-comment \ @@ -1523,7 +1523,7 @@ jobs: - run: # on success, check for an existing PR comment and remove it when: on_success - name: 'Delete server coverage failure comment on PR if present' + name: "Delete server coverage failure comment on PR if present" command: | ./scripts/handle-pr-comment \ $CIRCLE_BRANCH \ @@ -1545,7 +1545,7 @@ jobs: - when: always steps: - run: - name: 'Copy coverage to baseline' + name: "Copy coverage to baseline" command: | mkdir -p ~/transcom/mymove/tmp/baseline-go-coverage cp ~/transcom/mymove/tmp/test-results/gotest/app/go-coverage.txt \ @@ -1565,7 +1565,7 @@ jobs: - aws_vars_transcom_gov_dev: when: always - run: - name: 'Record server coverage stats' + name: "Record server coverage stats" command: | timestamp=$(date +"%Y-%m-%dT%H:%M:%SZ") coverage=$(grep statements tmp/test-results/gotest/app/go-coverage.txt | grep -o '[0-9.]*') @@ -1646,7 +1646,7 @@ jobs: - run: # on failure, post a comment to the PR with a link to the report when: on_fail - name: 'Post client coverage failure comment to GitHub' + name: "Post client coverage failure comment to GitHub" command: | source client_test_job_id.env ./scripts/handle-pr-comment \ @@ -1657,7 +1657,7 @@ jobs: - run: # on success, check for an existing PR comment and remove it when: on_success - name: 'Delete client coverage failure comment on PR if present' + name: "Delete client coverage failure comment on PR if present" command: | ./scripts/handle-pr-comment \ $CIRCLE_BRANCH \ @@ -1676,7 +1676,7 @@ jobs: - equal: [main, << pipeline.git.branch >>] steps: - run: - name: 'Copy coverage to baseline' + name: "Copy coverage to baseline" command: | mkdir -p ~/transcom/mymove/tmp/baseline-jest-coverage cp ~/transcom/mymove/coverage/clover.xml \ @@ -1695,7 +1695,7 @@ jobs: - aws_vars_transcom_gov_dev: when: always - run: - name: 'Record client coverage stats' + name: "Record client coverage stats" command: | timestamp=$(date +"%Y-%m-%dT%H:%M:%SZ") coverage=$(grep -B 1 'span.*Statements' coverage/lcov-report/index.html | grep -o '[0-9.]*') @@ -2112,13 +2112,13 @@ jobs: environment: APP_ENVIRONMENT: *dp3-env - OPEN_TELEMETRY_SIDECAR: 'true' - HEALTH_CHECK: 'true' + OPEN_TELEMETRY_SIDECAR: "true" + HEALTH_CHECK: "true" steps: - checkout - aws_vars_dp3 - deploy_app_steps: - compare_host: '' # leave blank since we want dp3 to be able to roll back + compare_host: "" # leave blank since we want dp3 to be able to roll back health_check_hosts: my.<< parameters.dp3-env >>.dp3.us,office.<< parameters.dp3-env >>.dp3.us,admin.<< parameters.dp3-env >>.dp3.us ecr_env: *dp3-env @@ -2131,14 +2131,14 @@ jobs: default: *dp3-env environment: APP_ENVIRONMENT: *dp3-env - OPEN_TELEMETRY_SIDECAR: 'true' - HEALTH_CHECK: 'true' + OPEN_TELEMETRY_SIDECAR: "true" + HEALTH_CHECK: "true" steps: - checkout - aws_vars_dp3 - tls_vars_dp3 - deploy_app_client_tls_steps: - compare_host: '' # leave blank since we want dp3 to be able to roll back + compare_host: "" # leave blank since we want dp3 to be able to roll back health_check_hosts: api.<< parameters.dp3-env >>.dp3.us ecr_env: *dp3-env @@ -2154,7 +2154,7 @@ jobs: deploy_stg_migrations: executor: mymove_pusher environment: - APP_ENVIRONMENT: 'stg' + APP_ENVIRONMENT: "stg" steps: - checkout - aws_vars_stg @@ -2165,7 +2165,7 @@ jobs: deploy_stg_tasks: executor: mymove_pusher environment: - APP_ENVIRONMENT: 'stg' + APP_ENVIRONMENT: "stg" steps: - checkout - aws_vars_stg @@ -2176,9 +2176,9 @@ jobs: deploy_stg_app: executor: mymove_pusher environment: - APP_ENVIRONMENT: 'stg' - OPEN_TELEMETRY_SIDECAR: 'true' - HEALTH_CHECK: 'true' + APP_ENVIRONMENT: "stg" + OPEN_TELEMETRY_SIDECAR: "true" + HEALTH_CHECK: "true" steps: - checkout - aws_vars_stg @@ -2193,9 +2193,9 @@ jobs: # use dockerhub otel collector image as govcloud does not have the # right certs for pulling from public.ecr.aws environment: - APP_ENVIRONMENT: 'stg' - OPEN_TELEMETRY_SIDECAR: 'true' - HEALTH_CHECK: 'true' + APP_ENVIRONMENT: "stg" + OPEN_TELEMETRY_SIDECAR: "true" + HEALTH_CHECK: "true" steps: - checkout - aws_vars_stg @@ -2217,7 +2217,7 @@ jobs: deploy_prd_migrations: executor: mymove_pusher environment: - APP_ENVIRONMENT: 'prd' + APP_ENVIRONMENT: "prd" steps: - checkout - aws_vars_prd @@ -2228,7 +2228,7 @@ jobs: deploy_prd_tasks: executor: mymove_pusher environment: - APP_ENVIRONMENT: 'prd' + APP_ENVIRONMENT: "prd" steps: - checkout - aws_vars_prd @@ -2239,9 +2239,9 @@ jobs: deploy_prd_app: executor: mymove_pusher environment: - APP_ENVIRONMENT: 'prd' - OPEN_TELEMETRY_SIDECAR: 'true' - HEALTH_CHECK: 'true' + APP_ENVIRONMENT: "prd" + OPEN_TELEMETRY_SIDECAR: "true" + HEALTH_CHECK: "true" steps: - checkout - aws_vars_prd @@ -2254,9 +2254,9 @@ jobs: deploy_prd_app_client_tls: executor: mymove_pusher environment: - APP_ENVIRONMENT: 'prd' - OPEN_TELEMETRY_SIDECAR: 'true' - HEALTH_CHECK: 'true' + APP_ENVIRONMENT: "prd" + OPEN_TELEMETRY_SIDECAR: "true" + HEALTH_CHECK: "true" steps: - checkout - aws_vars_prd @@ -2312,7 +2312,8 @@ workflows: - pre_deps_golang filters: branches: - ignore: [*integration-mtls-ignore-branch, *integration-ignore-branch] + ignore: + [*integration-mtls-ignore-branch, *integration-ignore-branch] - pre_test: requires: @@ -2456,7 +2457,8 @@ workflows: - build_migrations filters: branches: - ignore: [*integration-mtls-ignore-branch, *integration-ignore-branch] + ignore: + [*integration-mtls-ignore-branch, *integration-ignore-branch] - build_tasks: requires: @@ -2719,4 +2721,4 @@ experimental: notify: branches: only: - - main + - main \ No newline at end of file diff --git a/src/pages/Office/ServicesCounselingMoveDetails/ServicesCounselingMoveDetails.jsx b/src/pages/Office/ServicesCounselingMoveDetails/ServicesCounselingMoveDetails.jsx index ac4e3b3e7dc..7251adf1525 100644 --- a/src/pages/Office/ServicesCounselingMoveDetails/ServicesCounselingMoveDetails.jsx +++ b/src/pages/Office/ServicesCounselingMoveDetails/ServicesCounselingMoveDetails.jsx @@ -524,7 +524,6 @@ const ServicesCounselingMoveDetails = ({ const handleCancelMove = () => { mutateCancelMove({ moveID: move.id, - ifMatchETag: move.eTag, }); setIsCancelMoveModalVisible(false); }; diff --git a/src/services/ghcApi.js b/src/services/ghcApi.js index 7df5d0c612f..b99dc5c91c9 100644 --- a/src/services/ghcApi.js +++ b/src/services/ghcApi.js @@ -432,13 +432,12 @@ export function updateMoveStatusServiceCounselingCompleted({ moveTaskOrderID, if ); } -export function cancelMove({ moveID, ifMatchETag, normalize = false }) { +export function cancelMove({ moveID, normalize = false }) { const operationPath = 'move.moveCanceler'; return makeGHCRequest( operationPath, { moveID, - 'If-Match': ifMatchETag, }, { normalize }, );