diff --git a/app/models/tasks/hearing_mail_tasks/hearing_postponement_request_mail_task.rb b/app/models/tasks/hearing_mail_tasks/hearing_postponement_request_mail_task.rb index 256941f1aa7..3eb2996c2ba 100644 --- a/app/models/tasks/hearing_mail_tasks/hearing_postponement_request_mail_task.rb +++ b/app/models/tasks/hearing_mail_tasks/hearing_postponement_request_mail_task.rb @@ -45,20 +45,13 @@ def available_actions(user) def update_from_params(params, user) payload_values = params.delete(:business_payloads)&.dig(:values) - if params[:status] == Constants.TASK_STATUSES.completed - # If request to postpone hearing is granted - if payload_values[:granted] - created_tasks = update_hearing_and_create_tasks(payload_values[:after_disposition_update]) - update_self_and_parent_mail_task(user: user, params: params, payload_values: payload_values) - - [self] + created_tasks - # If request to postpone hearing is denied - else - "TO-DO: LOGIC FOR APPEALS-27763" - end - else - super(params, user) + # If request to postpone hearing is granted + if payload_values[:disposition].present? + created_tasks = update_hearing_and_create_tasks(payload_values[:after_disposition_update]) end + update_self_and_parent_mail_task(user: user, params: params, payload_values: payload_values) + + [self] + (created_tasks || []) end # Only show HPR mail task assigned to "HearingAdmin" on the Case Timeline @@ -66,18 +59,16 @@ def hide_from_case_timeline assigned_to.type == "MailTeam" end - private - - # TO-DO: Edge case of request recieved after hearing held? - # - On that note, #available_actions might also fail? - def hearing - @hearing ||= open_assign_hearing_disposition_task&.hearing + def recent_hearing + @recent_hearing ||= open_assign_hearing_disposition_task&.hearing end def hearing_task - @hearing_task ||= hearing&.hearing_task || active_schedule_hearing_task&.parent + @hearing_task ||= recent_hearing&.hearing_task || active_schedule_hearing_task&.parent end + private + def active_schedule_hearing_task appeal.tasks.where(type: ScheduleHearingTask.name).active.first end @@ -93,15 +84,15 @@ def open_assign_hearing_disposition_task end def hearing_scheduled_and_awaiting_disposition? - return false if hearing.nil? + return false if recent_hearing.nil? # Ensure associated hearing is not scheduled for the past - !hearing.scheduled_for_past? + !recent_hearing.scheduled_for_past? end def update_hearing_and_create_tasks(after_disposition_update) multi_transaction do - unless hearing.nil? + unless recent_hearing.nil? update_hearing(disposition: Constants.HEARING_DISPOSITION_TYPES.postponed) clean_up_virtual_hearing end @@ -110,24 +101,31 @@ def update_hearing_and_create_tasks(after_disposition_update) end def update_hearing(hearing_hash) - if hearing.is_a?(LegacyHearing) - hearing.update_caseflow_and_vacols(hearing_hash) + if recent_hearing.is_a?(LegacyHearing) + recent_hearing.update_caseflow_and_vacols(hearing_hash) else - hearing.update(hearing_hash) + recent_hearing.update(hearing_hash) end end - # TO DO: Affected by webex/pexip? def clean_up_virtual_hearing - if hearing.virtual? + if recent_hearing.virtual? perform_later_or_now(VirtualHearings::DeleteConferencesJob) end end def reschedule_or_schedule_later(after_disposition_update) - case after_disposition_update + case after_disposition_update[:action] when "reschedule" - "TO-DO: LOGIC FOR APPEALS-24998" + new_hearing_attrs = after_disposition_update[:new_hearing_attrs] + reschedule( + hearing_day_id: new_hearing_attrs[:hearing_day_id], + scheduled_time_string: new_hearing_attrs[:scheduled_time_string], + hearing_location: new_hearing_attrs[:hearing_location], + virtual_hearing_attributes: new_hearing_attrs[:virtual_hearing_attributes], + notes: new_hearing_attrs[:notes], + email_recipients_attributes: new_hearing_attrs[:email_recipients] + ) when "schedule_later" schedule_later else @@ -135,6 +133,38 @@ def reschedule_or_schedule_later(after_disposition_update) end end + # rubocop:disable Metrics/ParameterLists + def reschedule( + hearing_day_id:, + scheduled_time_string:, + hearing_location: nil, + virtual_hearing_attributes: nil, + notes: nil, + email_recipients_attributes: nil + ) + multi_transaction do + new_hearing_task = hearing_task.cancel_and_recreate + + new_hearing = HearingRepository.slot_new_hearing(hearing_day_id: hearing_day_id, + appeal: appeal, + hearing_location_attrs: hearing_location&.to_hash, + scheduled_time_string: scheduled_time_string, + notes: notes) + if virtual_hearing_attributes.present? + @alerts = VirtualHearings::ConvertToVirtualHearingService + .convert_hearing_to_virtual(new_hearing, virtual_hearing_attributes) + elsif email_recipients_attributes.present? + create_or_update_email_recipients(new_hearing, email_recipients_attributes) + end + + disposition_task = AssignHearingDispositionTask + .create_assign_hearing_disposition_task!(appeal, new_hearing_task, new_hearing) + + [new_hearing_task, disposition_task] + end + end + # rubocop:enable Metrics/ParameterLists + def schedule_later new_hearing_task = hearing_task.cancel_and_recreate schedule_task = ScheduleHearingTask.create!(appeal: appeal, parent: new_hearing_task) @@ -145,7 +175,7 @@ def schedule_later def update_self_and_parent_mail_task(user:, params:, payload_values:) updated_instructions = format_instructions_on_completion( admin_context: params[:instructions], - granted: payload_values[:granted], + granted: payload_values[:disposition].present?, date_of_ruling: payload_values[:date_of_ruling] ) diff --git a/client/app/queue/components/hearingMailRequestModals/CompleteHearingPostponementRequestModal.jsx b/client/app/queue/components/hearingMailRequestModals/CompleteHearingPostponementRequestModal.jsx index a6f5b0875e2..5b257a74fad 100644 --- a/client/app/queue/components/hearingMailRequestModals/CompleteHearingPostponementRequestModal.jsx +++ b/client/app/queue/components/hearingMailRequestModals/CompleteHearingPostponementRequestModal.jsx @@ -3,21 +3,19 @@ import PropTypes from 'prop-types'; import { withRouter } from 'react-router-dom'; import { connect } from 'react-redux'; import { bindActionCreators } from 'redux'; - import { taskById, appealWithDetailSelector } from '../../selectors'; import { requestPatch, showErrorMessage } from '../../uiReducer/uiActions'; import { onReceiveAmaTasks } from '../../QueueActions'; - import COPY from '../../../../COPY'; import TASK_STATUSES from '../../../../constants/TASK_STATUSES'; import HEARING_DISPOSITION_TYPES from '../../../../constants/HEARING_DISPOSITION_TYPES'; - import QueueFlowModal from '../QueueFlowModal'; import RadioField from '../../../components/RadioField'; import Alert from '../../../components/Alert'; import DateSelector from '../../../components/DateSelector'; import TextareaField from '../../../components/TextareaField'; import { marginTop, marginBottom } from '../../constants'; +import { setScheduledHearing } from '../../../components/common/actions'; const ACTIONS = { RESCHEDULE: 'reschedule', @@ -35,6 +33,8 @@ const POSTPONEMENT_OPTIONS = [ ]; const CompleteHearingPostponementRequestModal = (props) => { + const { appealId, appeal, taskId, task, userCanScheduleVirtualHearings } = props; + const formReducer = (state, action) => { switch (action.type) { case 'granted': @@ -95,22 +95,18 @@ const CompleteHearingPostponementRequestModal = (props) => { }; const getPayload = () => { - const { granted, rulingDate, scheduledOption, instructions } = state; - - const afterDispositionPayload = scheduledOption === ACTIONS.RESCHEDULE ? - /* LOGIC FOR APPEALS-24998 INSTEAD OF NULL */ null : ACTIONS.SCHEDULE_LATER; + const { granted, rulingDate, instructions } = state; return { data: { task: { status: TASK_STATUSES.completed, instructions, - // If request is denied, do not assign new disposition to hearing business_payloads: { values: { + // If request is denied, do not assign new disposition to hearing disposition: granted ? HEARING_DISPOSITION_TYPES.postponed : null, - after_disposition_update: granted ? afterDispositionPayload : null, - granted, + after_disposition_update: granted ? { action: ACTIONS.SCHEDULE_LATER } : null, date_of_ruling: rulingDate.value, }, }, @@ -120,36 +116,32 @@ const CompleteHearingPostponementRequestModal = (props) => { }; const getSuccessMsg = () => { - const { granted, scheduledOption } = state; - const { appeal } = props; + const { granted } = state; - if (!granted) { - // LOGIC FOR APPEALS-27763 - } - - if (scheduledOption === ACTIONS.RESCHEDULE) { - // LOGIC FOR APPEALS-24998 - } + const message = granted ? + `${appeal.veteranFullName} was successfully added back to the schedule veteran list.` : + 'You have successfully marked hearing postponement request task as complete.'; return { - title: `${ - appeal.veteranFullName - } was successfully added back to the schedule veteran list.`, + title: message }; }; const submit = () => { - const { userCanScheduleVirtualHearings, task } = props; - const { isPosting } = state; + const { isPosting, granted, scheduledOption } = state; - // If user judge ruling is denied... - if (!state.granted) { - // LOGIC FOR APPEALS-27763 - } + if (granted && scheduledOption === ACTIONS.RESCHEDULE && userCanScheduleVirtualHearings) { + props.setScheduledHearing({ + action: ACTIONS.RESCHEDULE, + taskId, + disposition: HEARING_DISPOSITION_TYPES.postponed + }); + + props.history.push( + `/queue/appeals/${appealId}/tasks/${taskId}/schedule_veteran` + ); - // If user opts to reschedule immediately, redirect to the full page schedule veteran flow - if (state.scheduledOption === ACTIONS.RESCHEDULE && userCanScheduleVirtualHearings) { - // LOGIC FOR APPEALS-24998 + return Promise.reject(); } if (isPosting) { @@ -186,7 +178,7 @@ const CompleteHearingPostponementRequestModal = (props) => { submitDisabled={!validateForm()} validateForm={validateForm} submit={submit} - pathAfterSubmit={`/queue/appeals/${props.appeal.externalId}`} + pathAfterSubmit={`/queue/appeals/${appealId}`} > <> { ); }; -CompleteHearingPostponementRequestModal.propTypes = { - appeal: PropTypes.shape({ - externalId: PropTypes.string, - veteranFullName: PropTypes.string - }), - task: PropTypes.shape({ - taskId: PropTypes.string, - }), - userCanScheduleVirtualHearings: PropTypes.bool, - requestPatch: PropTypes.func, - onReceiveAmaTasks: PropTypes.func, - showErrorMessage: PropTypes.func, - register: PropTypes.func -}; - const mapStateToProps = (state, ownProps) => ({ task: taskById(state, { taskId: ownProps.taskId }), appeal: appealWithDetailSelector(state, ownProps), + scheduleHearingLaterWithAdminAction: + state.components.forms.scheduleHearingLaterWithAdminAction || {} }); const mapDispatchToProps = (dispatch) => bindActionCreators( { + setScheduledHearing, requestPatch, onReceiveAmaTasks, showErrorMessage @@ -273,6 +253,25 @@ const mapDispatchToProps = (dispatch) => dispatch ); +CompleteHearingPostponementRequestModal.propTypes = { + register: PropTypes.func, + appealId: PropTypes.string.isRequired, + taskId: PropTypes.string.isRequired, + history: PropTypes.object, + setScheduledHearing: PropTypes.func, + userCanScheduleVirtualHearings: PropTypes.bool, + appeal: PropTypes.shape({ + externalId: PropTypes.string, + veteranFullName: PropTypes.string + }), + task: PropTypes.shape({ + taskId: PropTypes.string, + }), + requestPatch: PropTypes.func, + onReceiveAmaTasks: PropTypes.func, + showErrorMessage: PropTypes.func, +}; + export default withRouter( connect( mapStateToProps,