@zeniai/client-epic-state 5.2.35-beta4MM → 5.2.35-beta6MM

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (27) hide show
  1. package/lib/entity/jeSchedules/jeSchedulesPayload.d.ts +1 -0
  2. package/lib/entity/jeSchedules/jeSchedulesPayload.js +1 -0
  3. package/lib/entity/jeSchedules/jeSchedulesState.d.ts +1 -0
  4. package/lib/entity/snackbar/snackbarTypes.d.ts +1 -1
  5. package/lib/entity/snackbar/snackbarTypes.js +2 -0
  6. package/lib/esm/entity/jeSchedules/jeSchedulesPayload.js +1 -0
  7. package/lib/esm/entity/snackbar/snackbarTypes.js +2 -0
  8. package/lib/esm/index.js +3 -3
  9. package/lib/esm/view/expenseAutomationView/epics/actualMatching/matchAndReverseAccrualsEpic.js +71 -12
  10. package/lib/esm/view/expenseAutomationView/epics/actualMatching/undoReversalAccrualsEpic.js +41 -3
  11. package/lib/esm/view/expenseAutomationView/reducers/actualMatchingViewReducer.js +10 -5
  12. package/lib/esm/view/expenseAutomationView/selectors/actualMatchingViewSelector.js +35 -4
  13. package/lib/index.d.ts +3 -3
  14. package/lib/index.js +20 -18
  15. package/lib/view/expenseAutomationView/epics/actualMatching/matchAndReverseAccrualsEpic.d.ts +2 -1
  16. package/lib/view/expenseAutomationView/epics/actualMatching/matchAndReverseAccrualsEpic.js +69 -10
  17. package/lib/view/expenseAutomationView/epics/actualMatching/undoReversalAccrualsEpic.d.ts +2 -1
  18. package/lib/view/expenseAutomationView/epics/actualMatching/undoReversalAccrualsEpic.js +41 -3
  19. package/lib/view/expenseAutomationView/helpers/transactionCategorizationLocalDataHelper.d.ts +1 -1
  20. package/lib/view/expenseAutomationView/payload/actualMatchingPayload.d.ts +1 -1
  21. package/lib/view/expenseAutomationView/reducers/actualMatchingViewReducer.d.ts +3 -3
  22. package/lib/view/expenseAutomationView/reducers/actualMatchingViewReducer.js +11 -6
  23. package/lib/view/expenseAutomationView/selectorTypes/actualMatchingViewSelectorTypes.d.ts +3 -0
  24. package/lib/view/expenseAutomationView/selectors/actualMatchingViewSelector.d.ts +2 -2
  25. package/lib/view/expenseAutomationView/selectors/actualMatchingViewSelector.js +36 -4
  26. package/lib/view/expenseAutomationView/types/actualMatchingViewState.d.ts +2 -2
  27. package/package.json +1 -1
@@ -131,6 +131,7 @@ export interface JEOneTimeAccrualClearedPayload {
131
131
  accrual_ids?: string[] | null;
132
132
  consumed_line_ids?: string[] | null;
133
133
  group_sum?: number | null;
134
+ intended_accrual_ids?: string[] | null;
134
135
  match_shape?: string | null;
135
136
  match_tier?: string | null;
136
137
  matched_amount?: number | null;
@@ -472,6 +472,7 @@ function toJEOneTimeAccrualCleared(payload, currencyCode) {
472
472
  ? toOneTimeAccrualAmount(payload.group_sum, currencyCode)
473
473
  : undefined,
474
474
  accrualIds: payload.accrual_ids ?? undefined,
475
+ intendedAccrualIds: payload.intended_accrual_ids ?? undefined,
475
476
  reversedAt: payload.reversed_at != null ? (0, zeniDayJS_1.date)(payload.reversed_at) : undefined,
476
477
  matchedTransactionDate: payload.matched_transaction_date != null
477
478
  ? (0, zeniDayJS_1.date)(payload.matched_transaction_date)
@@ -209,6 +209,7 @@ export interface JEOneTimeAccrualCleared {
209
209
  accrualIds?: ID[];
210
210
  consumedLineIds?: string[];
211
211
  groupSum?: Amount;
212
+ intendedAccrualIds?: ID[];
212
213
  matchedAmount?: Amount;
213
214
  matchedLineId?: string;
214
215
  matchedTransactionDate?: ZeniDate;
@@ -1,4 +1,4 @@
1
- export declare const toSnackbarMessageSection: (v: string) => "common" | "transactionDetails_updatingPastTransactions" | "transactionDetails_transactionUpdated" | "cockpit_month_end_email_sent" | "cockpit_month_end_email_save" | "cockpit_month_end_email_attachment_upload" | "je_bill_link" | "je_posted" | "audit_score_updated" | "people_invite_people" | "people_invite_multiple_people" | "people_delete_person" | "people_update_person" | "reimbursement_updated" | "reimbursement_deleted" | "reimbursement_cancelled_deleted" | "reimbursement_cancelled" | "reimbursement_approved" | "reimbursement_rejected" | "reimbursement_sent_for_approval" | "account_added" | "business_verification_save" | "business_verification_submit" | "business_verification_from_bills_submit" | "plaid_connection" | "unlink_deposit_account" | "reimbursement_setup" | "reimbursement_approval_create" | "reimbursement_duplicate_approval_create" | "reimbursement_approval_update" | "reimbursement_duplicate_approval_update" | "reimbursement_approval_delete" | "reimbursement_approval_reorder" | "reimbursement_create_mileage" | "reimbursement_update_mileage" | "reimbursement_accept_term" | "reimbursement_accept_employee_term" | "reimbursement_bulk_submit" | "reimbursement_bulk_processed" | "bill_pay_setup" | "zeni_accounts_setup" | "bill_pay_approval_create" | "bill_pay_duplicate_approval_create" | "bill_pay_approval_update" | "bill_pay_duplicate_approval_update" | "bill_pay_approval_delete" | "bill_pay_approval_reorder" | "bill_pay_updated" | "bill_pay_deleted" | "bill_pay_cancelled_deleted" | "bill_pay_cancelled" | "bill_pay_approved" | "real_time_approver_added" | "bill_pay_rejected" | "bill_pay_sent_for_approval" | "bill_pay_accept_term" | "bill_pay_bulk_submit" | "bill_pay_bulk_processed" | "bill_pay_refund" | "bill_pay_retry" | "bill_pay_marked_as_paid" | "zeni_account_accept_term" | "update_vendor" | "data_refresh_update" | "delete_bank_account" | "create_bank_account" | "create_bank_account_ach" | "create_bank_account_wire" | "create_bank_account_international" | "transfer_money" | "update_zeni_account_nickname" | "create_checking_account" | "deposit_check" | "create_vendor" | "onboarding_customer_view" | "onboarding_customer_view_complete" | "onboarding_customer_identity_verification_save" | "onboarding_customer_identity_verification_submit" | "onboarding_customer_business_verification_save" | "onboarding_customer_business_verification_submit" | "retry_bank_account_connection" | "dashboard_invite_sent" | "onboarding_info_saved" | "approve_original_merchant" | "approve_global_merchant" | "reject_global_merchant" | "create_global_merchant" | "fetch_global_merchant_no_recommendation" | "save_vendor_renamed" | "save_vendor_sent_for_review" | "save_vendor_marked_as_employee" | "save_vendor_marked_as_local_contractor" | "charge_card_setup" | "charge_card_accept_term" | "charge_card_receipt_upload" | "charge_card_resend_invite" | "charge_card_revoke_invite" | "card_policy_created" | "card_policy_updated" | "card_policy_deleted" | "charge_card_update_limit" | "charge_cards_update_limit" | "close_charge_card" | "lock_charge_card" | "lock_charge_card_card_user" | "lock_charge_cards" | "unlock_charge_card" | "unlock_charge_card_card_user" | "unlock_charge_cards" | "close_charge_cards" | "revoke_invite_charge_cards" | "charge_card_express_interest" | "create_schedule" | "save_schedule" | "delete_schedule" | "ignore_schedule" | "revert_schedule" | "ignore_accrual" | "revert_accrual" | "save_task_detail" | "fetch_task_detail" | "delete_task" | "archive_task" | "snooze_task" | "unsnooze_task" | "create_tag" | "delete_tag" | "update_charge_card" | "update_charge_card_name" | "update_charge_card_name_card_user" | "issue_charge_card" | "issue_charge_cards" | "notification_settings_saved" | "referral_invite_sent" | "notification_mark_as_read" | "mark_as_complete_schedule" | "cancel_journal_entry" | "settings_accounting_accounts_updated" | "create_card_setup" | "confirm_card_setup" | "add_card_payment_source" | "fetch_payment_sources" | "task_assigned_toast_notification" | "task_due_tomorrow_toast_notification" | "task_deleted_toast_notification" | "task_archived_toast_notification" | "task_overdue_toast_notification" | "task_overdue_toast_notification_creator" | "task_notification_count" | "task_activities_toast_notification" | "task_created_toast_notification" | "task_group_creation_success" | "task_group_deletion_success" | "task_group_update_success" | "primary_funding_account_updated" | "task_time_spent_validation" | "missing_receipts_attachment" | "flux_analysis_unreviewed" | "flux_analysis_reviewed" | "receipt_match" | "receipts_upload" | "receipts_bulk_match" | "billing_address_view" | "express_pay_submit" | "exclude_transaction" | "reconcile" | "save_reconcile_for_later" | "recon_transaction_categorize" | "recon_transaction_match" | "update_debit_card_pin_attempt" | "set_debit_card_pin" | "ai_cfo_create_session_and_submit" | "ai_cfo_chat_session_deleted" | "charge_card_auto_pay_enable" | "charge_card_auto_pay_disable" | "treasury_setup" | "treasury_accept_term" | "treasury_transfer_money" | "treasury_transfer_money_failed" | "auto_transfer_rule_create" | "auto_transfer_rule_update" | "auto_transfer_rule_delete" | "auto_transfer_rule_pause" | "auto_transfer_rule_resume" | "treasury_update_portfolio_allocation" | "send_email_magic_link_to_user" | "complete_profile_done" | "create_transfer_entry" | "reports_resync" | "invalid_phone_number" | "transactions_categorized_updated_failed" | "transaction_categorized_updated_failed" | "transactionsCategorized_transactionsUpdated" | "transactionsCategorized_transactionUpdated" | "transactionCategorized_transactionsUpdated" | "transactionCategorized_transactionUpdated" | "transactionsCategorized_transactionsFailed" | "transactionsCategorized_transactionFailed" | "transactionCategorized_transactionsFailed" | "transactionCategorized_transactionFailed" | "transactionsUpdated_transactionsFailed" | "transactionsUpdated_transactionFailed" | "transactionUpdated_transactionsFailed" | "transactionUpdated_transactionFailed" | "transactionsCategorized_transactionsUpdated_transactionsFailed" | "transactionsCategorized_transactionsUpdated_transactionFailed" | "transactionsCategorized_transactionUpdated_transactionsFailed" | "transactionCategorized_transactionsUpdated_transactionsFailed" | "transactionsCategorized_transactionUpdated_transactionFailed" | "transactionCategorized_transactionsUpdated_transactionFailed" | "transactionCategorized_transactionUpdated_transactionsFailed" | "transactionCategorized_transactionUpdated_transactionFailed" | "accounting_classes_enabled_update" | "accounting_projects_enabled_update" | "accounting_projects_qbo_not_enabled" | "capitalization_threshold_update" | "account_excluded_from_reconciliation" | "account_included_in_reconciliation" | "confirm_statement_mapping" | "statement_parsing_in_progress" | "statement_parsing_complete" | "ai_accountant_trigger_job" | "oauth_consent_approve" | "oauth_consent_invalid_request" | "credit_agent_update_profile" | "credit_agent_save_macro" | "credit_agent_schedule_cron" | "create_sub_task" | "qbo_connection_already_linked" | "qbo_connection_failed" | "accounting_projects_qbo_reconnect_failed" | "product_services_update" | "qbo_realm_id_update" | "invoicing_dunning_case_resolved" | "invoicing_dunning_retry" | "invoicing_dunning_cancel" | "invoicing_dunning_settings_save" | "invoicing_qbo_backfill" | "invoicing_qbo_sync_health_retry" | "invoicing_qbo_settings_save" | "invoicing_branding_save" | "invoicing_discount_archive" | "invoicing_discount_unarchive" | "invoicing_discount_delete" | "invoicing_invoice_reminder_sent" | "invoicing_invoice_regenerated" | "invoicing_invoice_voided" | "invoicing_catalog_item_saved" | "invoicing_customer_saved" | "invoicing_subscription_saved" | "invoicing_coupon_saved" | "invoicing_invoice_saved" | "invoicing_credit_note_saved" | "invoicing_payment_recorded" | "invoicing_subscription_activated" | "invoicing_subscription_cancellation_removed" | "invoicing_subscription_cancelled" | "invoicing_subscription_non_renewing" | "invoicing_subscription_paused" | "invoicing_subscription_reactivated" | "invoicing_subscription_resumed" | "invoicing_subscription_term_end_changed";
1
+ export declare const toSnackbarMessageSection: (v: string) => "common" | "transactionDetails_updatingPastTransactions" | "transactionDetails_transactionUpdated" | "cockpit_month_end_email_sent" | "cockpit_month_end_email_save" | "cockpit_month_end_email_attachment_upload" | "je_bill_link" | "je_posted" | "actual_matching_match_and_reverse" | "actual_matching_undo_reversal" | "audit_score_updated" | "people_invite_people" | "people_invite_multiple_people" | "people_delete_person" | "people_update_person" | "reimbursement_updated" | "reimbursement_deleted" | "reimbursement_cancelled_deleted" | "reimbursement_cancelled" | "reimbursement_approved" | "reimbursement_rejected" | "reimbursement_sent_for_approval" | "account_added" | "business_verification_save" | "business_verification_submit" | "business_verification_from_bills_submit" | "plaid_connection" | "unlink_deposit_account" | "reimbursement_setup" | "reimbursement_approval_create" | "reimbursement_duplicate_approval_create" | "reimbursement_approval_update" | "reimbursement_duplicate_approval_update" | "reimbursement_approval_delete" | "reimbursement_approval_reorder" | "reimbursement_create_mileage" | "reimbursement_update_mileage" | "reimbursement_accept_term" | "reimbursement_accept_employee_term" | "reimbursement_bulk_submit" | "reimbursement_bulk_processed" | "bill_pay_setup" | "zeni_accounts_setup" | "bill_pay_approval_create" | "bill_pay_duplicate_approval_create" | "bill_pay_approval_update" | "bill_pay_duplicate_approval_update" | "bill_pay_approval_delete" | "bill_pay_approval_reorder" | "bill_pay_updated" | "bill_pay_deleted" | "bill_pay_cancelled_deleted" | "bill_pay_cancelled" | "bill_pay_approved" | "real_time_approver_added" | "bill_pay_rejected" | "bill_pay_sent_for_approval" | "bill_pay_accept_term" | "bill_pay_bulk_submit" | "bill_pay_bulk_processed" | "bill_pay_refund" | "bill_pay_retry" | "bill_pay_marked_as_paid" | "zeni_account_accept_term" | "update_vendor" | "data_refresh_update" | "delete_bank_account" | "create_bank_account" | "create_bank_account_ach" | "create_bank_account_wire" | "create_bank_account_international" | "transfer_money" | "update_zeni_account_nickname" | "create_checking_account" | "deposit_check" | "create_vendor" | "onboarding_customer_view" | "onboarding_customer_view_complete" | "onboarding_customer_identity_verification_save" | "onboarding_customer_identity_verification_submit" | "onboarding_customer_business_verification_save" | "onboarding_customer_business_verification_submit" | "retry_bank_account_connection" | "dashboard_invite_sent" | "onboarding_info_saved" | "approve_original_merchant" | "approve_global_merchant" | "reject_global_merchant" | "create_global_merchant" | "fetch_global_merchant_no_recommendation" | "save_vendor_renamed" | "save_vendor_sent_for_review" | "save_vendor_marked_as_employee" | "save_vendor_marked_as_local_contractor" | "charge_card_setup" | "charge_card_accept_term" | "charge_card_receipt_upload" | "charge_card_resend_invite" | "charge_card_revoke_invite" | "card_policy_created" | "card_policy_updated" | "card_policy_deleted" | "charge_card_update_limit" | "charge_cards_update_limit" | "close_charge_card" | "lock_charge_card" | "lock_charge_card_card_user" | "lock_charge_cards" | "unlock_charge_card" | "unlock_charge_card_card_user" | "unlock_charge_cards" | "close_charge_cards" | "revoke_invite_charge_cards" | "charge_card_express_interest" | "create_schedule" | "save_schedule" | "delete_schedule" | "ignore_schedule" | "revert_schedule" | "ignore_accrual" | "revert_accrual" | "save_task_detail" | "fetch_task_detail" | "delete_task" | "archive_task" | "snooze_task" | "unsnooze_task" | "create_tag" | "delete_tag" | "update_charge_card" | "update_charge_card_name" | "update_charge_card_name_card_user" | "issue_charge_card" | "issue_charge_cards" | "notification_settings_saved" | "referral_invite_sent" | "notification_mark_as_read" | "mark_as_complete_schedule" | "cancel_journal_entry" | "settings_accounting_accounts_updated" | "create_card_setup" | "confirm_card_setup" | "add_card_payment_source" | "fetch_payment_sources" | "task_assigned_toast_notification" | "task_due_tomorrow_toast_notification" | "task_deleted_toast_notification" | "task_archived_toast_notification" | "task_overdue_toast_notification" | "task_overdue_toast_notification_creator" | "task_notification_count" | "task_activities_toast_notification" | "task_created_toast_notification" | "task_group_creation_success" | "task_group_deletion_success" | "task_group_update_success" | "primary_funding_account_updated" | "task_time_spent_validation" | "missing_receipts_attachment" | "flux_analysis_unreviewed" | "flux_analysis_reviewed" | "receipt_match" | "receipts_upload" | "receipts_bulk_match" | "billing_address_view" | "express_pay_submit" | "exclude_transaction" | "reconcile" | "save_reconcile_for_later" | "recon_transaction_categorize" | "recon_transaction_match" | "update_debit_card_pin_attempt" | "set_debit_card_pin" | "ai_cfo_create_session_and_submit" | "ai_cfo_chat_session_deleted" | "charge_card_auto_pay_enable" | "charge_card_auto_pay_disable" | "treasury_setup" | "treasury_accept_term" | "treasury_transfer_money" | "treasury_transfer_money_failed" | "auto_transfer_rule_create" | "auto_transfer_rule_update" | "auto_transfer_rule_delete" | "auto_transfer_rule_pause" | "auto_transfer_rule_resume" | "treasury_update_portfolio_allocation" | "send_email_magic_link_to_user" | "complete_profile_done" | "create_transfer_entry" | "reports_resync" | "invalid_phone_number" | "transactions_categorized_updated_failed" | "transaction_categorized_updated_failed" | "transactionsCategorized_transactionsUpdated" | "transactionsCategorized_transactionUpdated" | "transactionCategorized_transactionsUpdated" | "transactionCategorized_transactionUpdated" | "transactionsCategorized_transactionsFailed" | "transactionsCategorized_transactionFailed" | "transactionCategorized_transactionsFailed" | "transactionCategorized_transactionFailed" | "transactionsUpdated_transactionsFailed" | "transactionsUpdated_transactionFailed" | "transactionUpdated_transactionsFailed" | "transactionUpdated_transactionFailed" | "transactionsCategorized_transactionsUpdated_transactionsFailed" | "transactionsCategorized_transactionsUpdated_transactionFailed" | "transactionsCategorized_transactionUpdated_transactionsFailed" | "transactionCategorized_transactionsUpdated_transactionsFailed" | "transactionsCategorized_transactionUpdated_transactionFailed" | "transactionCategorized_transactionsUpdated_transactionFailed" | "transactionCategorized_transactionUpdated_transactionsFailed" | "transactionCategorized_transactionUpdated_transactionFailed" | "accounting_classes_enabled_update" | "accounting_projects_enabled_update" | "accounting_projects_qbo_not_enabled" | "capitalization_threshold_update" | "account_excluded_from_reconciliation" | "account_included_in_reconciliation" | "confirm_statement_mapping" | "statement_parsing_in_progress" | "statement_parsing_complete" | "ai_accountant_trigger_job" | "oauth_consent_approve" | "oauth_consent_invalid_request" | "credit_agent_update_profile" | "credit_agent_save_macro" | "credit_agent_schedule_cron" | "create_sub_task" | "qbo_connection_already_linked" | "qbo_connection_failed" | "accounting_projects_qbo_reconnect_failed" | "product_services_update" | "qbo_realm_id_update" | "invoicing_dunning_case_resolved" | "invoicing_dunning_retry" | "invoicing_dunning_cancel" | "invoicing_dunning_settings_save" | "invoicing_qbo_backfill" | "invoicing_qbo_sync_health_retry" | "invoicing_qbo_settings_save" | "invoicing_branding_save" | "invoicing_discount_archive" | "invoicing_discount_unarchive" | "invoicing_discount_delete" | "invoicing_invoice_reminder_sent" | "invoicing_invoice_regenerated" | "invoicing_invoice_voided" | "invoicing_catalog_item_saved" | "invoicing_customer_saved" | "invoicing_subscription_saved" | "invoicing_coupon_saved" | "invoicing_invoice_saved" | "invoicing_credit_note_saved" | "invoicing_payment_recorded" | "invoicing_subscription_activated" | "invoicing_subscription_cancellation_removed" | "invoicing_subscription_cancelled" | "invoicing_subscription_non_renewing" | "invoicing_subscription_paused" | "invoicing_subscription_reactivated" | "invoicing_subscription_resumed" | "invoicing_subscription_term_end_changed";
2
2
  export type SnackbarMessageSections = ReturnType<typeof toSnackbarMessageSection>;
3
3
  export declare const toSnackbarMessageSectionTexts: (v: string) => "notification" | "failed" | "success";
4
4
  export type SnackbarMessageSectionTexts = ReturnType<typeof toSnackbarMessageSectionTexts>;
@@ -11,6 +11,8 @@ const ALL_SNACKBAR_MESSAGE_SECTIONS = [
11
11
  'cockpit_month_end_email_attachment_upload',
12
12
  'je_bill_link',
13
13
  'je_posted',
14
+ 'actual_matching_match_and_reverse',
15
+ 'actual_matching_undo_reversal',
14
16
  'audit_score_updated',
15
17
  'people_invite_people',
16
18
  'people_invite_multiple_people',
@@ -461,6 +461,7 @@ function toJEOneTimeAccrualCleared(payload, currencyCode) {
461
461
  ? toOneTimeAccrualAmount(payload.group_sum, currencyCode)
462
462
  : undefined,
463
463
  accrualIds: payload.accrual_ids ?? undefined,
464
+ intendedAccrualIds: payload.intended_accrual_ids ?? undefined,
464
465
  reversedAt: payload.reversed_at != null ? date(payload.reversed_at) : undefined,
465
466
  matchedTransactionDate: payload.matched_transaction_date != null
466
467
  ? date(payload.matched_transaction_date)
@@ -8,6 +8,8 @@ const ALL_SNACKBAR_MESSAGE_SECTIONS = [
8
8
  'cockpit_month_end_email_attachment_upload',
9
9
  'je_bill_link',
10
10
  'je_posted',
11
+ 'actual_matching_match_and_reverse',
12
+ 'actual_matching_undo_reversal',
11
13
  'audit_score_updated',
12
14
  'people_invite_people',
13
15
  'people_invite_multiple_people',
package/lib/esm/index.js CHANGED
@@ -188,7 +188,7 @@ import { toExpenseAutomationViewType, toExpenseAutomationViewTypeStrict, } from
188
188
  import { computeNewScheduleJeDetails } from './view/expenseAutomationView/helpers/newScheduleLocalDataHelper';
189
189
  import { isReviewTransactionBankTransferType, isReviewTransactionBillPaymentType, isReviewTransactionCreditCardCreditType, isReviewTransactionCreditCardPaymentType, isReviewTransactionDepositType, isReviewTransactionExpenseType, } from './view/expenseAutomationView/helpers/reconciliationHelpers';
190
190
  import { MAX_SELECTION_LIMIT, checkIfAllLineItemsAreCategoryClassFilled, getLineItemsByTransactionIdsFromLocalData, isAnyItemWithUncategorizedExpenseAccount, } from './view/expenseAutomationView/helpers/transactionCategorizationLocalDataHelper';
191
- import { clearActualMatchingView as clearExpenseAutomationActualMatchingView, clearMatchNewModal, closeMatchNewModal, fetchActualMatching as fetchExpenseAutomationActualMatching, fetchActualMatchingMatch, fetchActualMatchingPage as fetchExpenseAutomationActualMatchingPage, matchAndReverseAccruals, openMatchNewModal, searchMatchAccruals, searchMatchTransactions, undoReversalAccruals, updateActualMatchingUIState as updateExpenseAutomationActualMatchingUIState, } from './view/expenseAutomationView/reducers/actualMatchingViewReducer';
191
+ import { ackCloseMatchAfterUndo, clearActualMatchingView as clearExpenseAutomationActualMatchingView, clearMatchNewModal, closeMatchNewModal, fetchActualMatching as fetchExpenseAutomationActualMatching, fetchActualMatchingMatch, fetchActualMatchingPage as fetchExpenseAutomationActualMatchingPage, matchAndReverseAccruals, openMatchNewModal, searchMatchAccruals, searchMatchTransactions, undoReversalAccruals, updateActualMatchingUIState as updateExpenseAutomationActualMatchingUIState, } from './view/expenseAutomationView/reducers/actualMatchingViewReducer';
192
192
  import { clearExpenseAutomationFluxAnalysisView, fetchFluxAnalysisView, reviewFluxAnalysisView, updateFluxAnalysisViewPageMetaData, updateFluxAnalysisViewUIState, updateOperatingExpensesIdsForReview, updateSelectedSectionIdsForReview, } from './view/expenseAutomationView/reducers/fluxAnalysisViewReducer';
193
193
  import { clearJeScheduleLocalData as clearExpenseAutomationJEScheduleLocalData, clearExpenseAutomationJESchedulesView, clearSearchTransactionsForNewSchedule as clearJeSearchTransactionsForNewSchedule, createOneTimeAccrual, createOneTimeAccrualFailure, createOneTimeAccrualSuccess, fetchJeSchedulesPage as fetchExpenseAutomationJESchedulesPage, fetchOneTimeAccrual, ignoreRecommendedJeSchedule as ignoreExpenseAutomationJESchedule, ignoreOneTimeAccrual, initializeAccountSettingsView as initializeJeAccountSettingsView, initializeNewSchedule as initializeJeNewSchedule, initializeJeScheduleLocalData, promoteOneTimeAccrual, removeJeOneTimeAccrualLocalData, removeJeScheduleTransactionKey, resetNewScheduleLocalData as resetJeNewScheduleLocalData, retryJeSchedule as retryExpenseAutomationJESchedule, revertJeSchedule, revertOneTimeAccrual, saveAccountSettings as saveJeAccountSettings, saveAccountSettingsLocalData as saveJeAccountSettingsLocalData, saveNewSchedule as saveJeNewSchedule, saveNewScheduleFailure as saveJeNewScheduleFailure, saveNewScheduleSuccess as saveJeNewScheduleSuccess, searchTransactionsForNewSchedule as searchJeTransactionsForNewSchedule, searchTransactionsForNewScheduleFailure as searchJeTransactionsForNewScheduleFailure, searchTransactionsForNewScheduleSuccess as searchJeTransactionsForNewScheduleSuccess, toggleJECreatedGroupCollapsed, toggleJEPendingGroupCollapsed, updateJESchedulesUIState as updateExpenseAutomationJESchedulesUIState, updateJEScheduleTypeFilter, updateNewScheduleLocalData as updateJeNewScheduleLocalData, updateJeOneTimeAccrualLocalData, updateJeScheduleLocalDataById, updateJeScheduleTransactionKeys, } from './view/expenseAutomationView/reducers/jeSchedulesViewReducer';
194
194
  import { acknowledgeBulkUploadConfirmMatchComplete, bulkUploadAutomatchingTimedOut, bulkUploadReceipts, bulkUploadReceiptsFailure, bulkUploadReceiptsSuccess, clearBulkUpload, clearBulkUploadBatchDetailsForScopeChange, clearManualSearchResults, clearMissingReceiptsTabNavigation, confirmBulkUploadMatch, confirmBulkUploadMatchFailure, confirmBulkUploadMatchSuccess, fetchBulkUploadBatchDetails, fetchBulkUploadBatchDetailsFailure, fetchBulkUploadBatchDetailsSuccess, fetchBulkUploadBatches, fetchBulkUploadBatchesFailure, fetchBulkUploadBatchesSuccess, fetchCompletedTransactions, fetchCompletedTransactionsFailure, fetchCompletedTransactionsSuccess, fetchMissingReceipts as fetchExpenseAutomationMissingReceipts, fetchMoreBatchDetails, fetchMoreBatchDetailsComplete, fetchMoreBatchDetailsFailure, markBatchDetailRefreshAttempted, markMissingReceiptAsDone as markExpenseAutomationMissingReceiptAsDone, pusherBatchStatusUpdate, refreshBatchDetailsForBatchId, requestMissingReceiptsTabNavigation, restoreBulkUploadAutomatchingOnMount, restoreBulkUploadMatchingState, searchTransactionsForManualMatch, searchTransactionsForManualMatchFailure, searchTransactionsForManualMatchSuccess, setBulkUploadCompletedSubTab, setBulkUploadResultsTab, setBulkUploadSortConfig, setBulkUploadUploadedFileCount, storeBatchDetails, updateBulkUploadProgress, updateMissingReceiptUploadState as updateExpenseAutomationMissingReceiptUploadState, updateMissingReceiptsUIState as updateExpenseAutomationMissingReceiptsUIState, uploadMissingReceiptSuccess as uploadExpenseAutomationMissingReceiptSuccess, } from './view/expenseAutomationView/reducers/missingReceiptsViewReducer';
@@ -662,7 +662,7 @@ export { TIME_SERIES_DURATIONS, convertToTimeSeriesSelectionRange, toTimeSeriesD
662
662
  export { fetchApAging, getApAgingReport, updateApAgingUIState, };
663
663
  export { fetchApAgingDetail, getApAgingDetailForVendor, updateApAgingDetailUIState, };
664
664
  export { clearExpenseAutomationJEScheduleLocalData, clearExpenseAutomationJESchedulesView, clearJeSearchTransactionsForNewSchedule, fetchExpenseAutomationJESchedulesPage, ignoreExpenseAutomationJESchedule, initializeJeAccountSettingsView, initializeJeNewSchedule, initializeJeScheduleLocalData, removeJeScheduleTransactionKey, resetJeNewScheduleLocalData, retryExpenseAutomationJESchedule, saveJeNewSchedule, saveJeNewScheduleFailure, saveJeNewScheduleSuccess, searchJeTransactionsForNewSchedule, searchJeTransactionsForNewScheduleFailure, searchJeTransactionsForNewScheduleSuccess, updateExpenseAutomationJESchedulesUIState, updateJeNewScheduleLocalData, removeJeOneTimeAccrualLocalData, updateJeOneTimeAccrualLocalData, updateJeScheduleLocalDataById, updateJeScheduleTransactionKeys, };
665
- export { clearExpenseAutomationActualMatchingView, closeMatchNewModal, clearMatchNewModal, fetchExpenseAutomationActualMatching, fetchActualMatchingMatch, fetchExpenseAutomationActualMatchingPage, matchAndReverseAccruals, openMatchNewModal, searchMatchAccruals, searchMatchTransactions, undoReversalAccruals, updateExpenseAutomationActualMatchingUIState, };
665
+ export { ackCloseMatchAfterUndo, clearExpenseAutomationActualMatchingView, closeMatchNewModal, clearMatchNewModal, fetchExpenseAutomationActualMatching, fetchActualMatchingMatch, fetchExpenseAutomationActualMatchingPage, matchAndReverseAccruals, openMatchNewModal, searchMatchAccruals, searchMatchTransactions, undoReversalAccruals, updateExpenseAutomationActualMatchingUIState, };
666
666
  export { createNewSchedulesAccrued, deleteScheduleAccruedDetail, cancelScheduleAccruedJournalEntry, fetchScheduleAccruedDetails, fetchScheduleAccruedDetailsPage, resetJEAccruedLinkInLocalData, saveScheduleAccruedDetails, updateAmountsInScheduleAccruedDetail, updatedJEAccruedLinkWithRecommendedLocalData, updatedJELinkInLocalDataAccruedExpenses, fetchRecommendedTransactionRowIndex, clearSelectedJELinkRowIndex, updateLinkBillExpenseLocalData, updateScheduleAccruedDetailsLocalData, updateSelectedJEAccruedScheduleKey, resetSelectedJEAccruedScheduleKey, resetAccruedDetailNewScheduleState, };
667
667
  export { getJEScheduleTransactionKey, ALL_JE_SCHEDULE_IGNORE_REASONS, ALL_JE_SCHEDULE_REVERT_REASONS, ALL_ONE_TIME_ACCRUAL_IGNORE_REASONS, ALL_ONE_TIME_ACCRUAL_REVERT_REASONS, ALL_SCHEDULES_TYPES, getScheduleListReport, getAccruedScheduleListReport, fetchScheduleList, fetchAccruedScheduleList, fetchDownloadSchedules, fetchSchedulesAccount, updateScheduleListLocalData, getFetchStateForScheduleAccountList, toScheduleTypesType, toScheduleTypesTypeStrict, toScheduleListTabsFileTypeStrict, toScheduleSubTabType, updateScheduleListSubTab, updateScheduleListSearchText, updateScheduleListScrollState, updateScheduleListSortState, updateSelectedJEScheduleKey, fetchScheduleDetails, getScheduleDetailsView, getAccruedScheduleDetailsView, fetchScheduleDetailsPage, saveScheduleDetails, deleteScheduleDetail, createNewSchedules, updateScheduleDetailsLocalData, updateScheduleListDownloadState, updateAccruedJEScheduleAccruedByListKey, updatedSelectedJELinkRowIndex, getQBOUrlForLink, getThirdPartyIDFromQBOURL, updatedJELinkInLocalData, updateAmountsInScheduleDetail, resetJELinkInLocalData, updatedJELinkWithRecommendedLocalData, getFetchStateForScheduleListByType, getDefaultSelectedTimeframeForScheduleType, markAsCompleteScheduleDetail, resetMarkAsCompleteStatus, fetchVendorTabView, updateVendorTabViewTab, getVendorTabView, };
668
668
  export { toVendorFirstReviewViewColumnKeyType, getGlobalMerchantAutoCompleteResults, getVendorFirstReviewView, getVendorFirstReviewAttachmentView, fetchVendorFirstReviewView, fetchVendorFirstReviewAttachments, updateVendorFirstReviewViewScrollYOffset, resetVendorFirstReviewLocalData, updateVendorFirstReviewViewPageToken, clearRecentlySavedErroredVendorData, saveVendorFirstReviewView, updateVendorFirstReviewViewLocalData, updateVendorFirstReviewSortUiState, fetchGlobalMerchantAutoCompleteView, clearGlobalMerchantAutoCompleteResults, updateReviewVendorDetailLocalData, saveVendorDetailsView, getVendorDetailSelectorView, };
@@ -866,4 +866,4 @@ export { getInvoicingOnboardingGateView } from './view/invoicing/invoicingConfig
866
866
  // Accrued JE schedules are not a discriminated union member, so consumers need this guard to
867
867
  // narrow a JEScheduleRow before reading baseTransaction / recurringAmount.
868
868
  export { getExpenseAutomationJEOneTimeAccrualDetailView, getJEScheduleRowType, isAccruedScheduleRow, isAiAccountantSchedule, isExistingTabRow, isOneTimeAccrualRow, isRenderableOneTimeAccrual, isPendingReviewRow, } from './view/expenseAutomationView/selectors/jeSchedulesViewSelector';
869
- export { getActualMatchingAmount, getActualMatchingReversalDate, parseActualMatchingMatchId, getExpenseAutomationActualMatchingMatchView, getExpenseAutomationActualMatchingView, isAutoReversedAccrual, isManuallyReversedAccrual, isPendingReviewAccrual, } from './view/expenseAutomationView/selectors/actualMatchingViewSelector';
869
+ export { getActualMatchingAmount, getActualMatchingReversalDate, getCloseMatchAfterUndo, parseActualMatchingMatchId, getExpenseAutomationActualMatchingMatchView, getExpenseAutomationActualMatchingView, isAutoReversedAccrual, isManuallyReversedAccrual, isPendingReviewAccrual, } from './view/expenseAutomationView/selectors/actualMatchingViewSelector';
@@ -1,48 +1,107 @@
1
1
  import { from, of } from 'rxjs';
2
2
  import { catchError, exhaustMap, filter, mergeMap, takeUntil } from 'rxjs/operators';
3
+ import { getActualMatchingMatchById } from '../../../../entity/actualMatching/actualMatchingSelector';
4
+ import { openSnackbar } from '../../../../entity/snackbar/snackbarReducer';
3
5
  import { createZeniAPIStatus, isSuccessResponse } from '../../../../responsePayload';
4
6
  import { clearAll } from '../../../../rootActions';
5
- import { toMatchAndReverseResult } from '../../payload/actualMatchingPayload';
6
- import { clearMatchNewModal, matchAndReverseAccruals, matchAndReverseAccrualsFailure, matchAndReverseAccrualsSuccess } from '../../reducers/actualMatchingViewReducer';
7
+ import { toMatchAndReverseResult, } from '../../payload/actualMatchingPayload';
8
+ import { clearMatchNewModal, matchAndReverseAccruals, matchAndReverseAccrualsFailure, matchAndReverseAccrualsSuccess, } from '../../reducers/actualMatchingViewReducer';
7
9
  import { refreshActualMatchingList } from './refreshActualMatchingList';
10
+ function isMatchCompleteStatus(status) {
11
+ return status === 'reversed' || status === 'noop';
12
+ }
13
+ function isMatchFailedStatus(status) {
14
+ return (status === 'conflict' || status === 'claim_lost' || status === 'error');
15
+ }
16
+ function matchAndReverseSnackbar(results, vendorName) {
17
+ const reversedCount = results.filter((result) => result.status === 'reversed').length;
18
+ const failedCount = results.filter((result) => isMatchFailedStatus(result.status)).length;
19
+ const variables = [
20
+ { variableName: '_count_', variableValue: String(reversedCount) },
21
+ { variableName: '_vendor_name_', variableValue: vendorName },
22
+ ];
23
+ if (results.length === 0 || (reversedCount === 0 && failedCount > 0)) {
24
+ return openSnackbar({
25
+ messageSection: 'actual_matching_match_and_reverse',
26
+ messageText: 'failed',
27
+ type: 'error',
28
+ variables,
29
+ });
30
+ }
31
+ if (reversedCount > 0 && failedCount === 0) {
32
+ return openSnackbar({
33
+ messageSection: 'actual_matching_match_and_reverse',
34
+ messageText: 'success',
35
+ type: 'success',
36
+ variables,
37
+ });
38
+ }
39
+ if (reversedCount > 0 && failedCount > 0) {
40
+ return openSnackbar({
41
+ messageSection: 'actual_matching_match_and_reverse',
42
+ messageText: 'notification',
43
+ type: 'warning',
44
+ variables,
45
+ });
46
+ }
47
+ return null;
48
+ }
49
+ function matchAndReverseHttpFailSnackbar(vendorName) {
50
+ return openSnackbar({
51
+ messageSection: 'actual_matching_match_and_reverse',
52
+ messageText: 'failed',
53
+ type: 'error',
54
+ variables: [
55
+ { variableName: '_count_', variableValue: '0' },
56
+ { variableName: '_vendor_name_', variableValue: vendorName },
57
+ ],
58
+ });
59
+ }
60
+ function matchVendorName(state, matchId) {
61
+ return getActualMatchingMatchById(state.actualMatchingState, matchId)?.vendorName ?? '';
62
+ }
8
63
  export const matchAndReverseAccrualsEpic = (actions$, state$, zeniAPI) => actions$.pipe(filter(matchAndReverseAccruals.match),
9
64
  // Posts reversing JEs; drop duplicate clicks while a request is in flight.
10
65
  exhaustMap((action) => {
11
- const { transactionId, transactionIntegrationId, transactionType, lineId, accrualIds, transactionSyncToken, } = action.payload;
66
+ const { transactionId, transactionIntegrationId, transactionType, lineIds, accrualIds, transactionSyncToken, } = action.payload;
12
67
  const body = {
13
68
  transaction_id: transactionId,
14
69
  transaction_integration_id: transactionIntegrationId,
15
70
  transaction_type: transactionType,
16
- line_id: lineId,
71
+ line_ids: lineIds,
17
72
  transaction_sync_token: transactionSyncToken,
18
73
  accrual_ids: accrualIds,
19
74
  };
75
+ const openedFromMatchId = state$.value.expenseAutomationActualMatchingViewState.matchModal
76
+ .openedFromMatchId;
77
+ const matchId = openedFromMatchId ?? `${transactionType}:${transactionIntegrationId}`;
78
+ const vendorName = matchVendorName(state$.value, matchId);
20
79
  return zeniAPI
21
80
  .postAndGetJSON(`${zeniAPI.apiEndPoints.accountMicroServiceBaseUrl}/1.0/accruals/match-and-reverse`, body)
22
81
  .pipe(mergeMap((response) => {
23
82
  if (isSuccessResponse(response) && response.data != null) {
24
83
  const results = response.data.results.map(toMatchAndReverseResult);
25
- const openedFromMatchId = state$.value.expenseAutomationActualMatchingViewState.matchModal
26
- .openedFromMatchId;
27
- const matchId = openedFromMatchId ??
28
- `${transactionType}:${transactionIntegrationId}`;
29
84
  const successActions = [
30
85
  matchAndReverseAccrualsSuccess({ matchId, results }),
31
86
  ];
32
- const occupancyChanged = results.some((result) => result.status === 'reversed' || result.status === 'noop');
87
+ const occupancyChanged = results.some((result) => isMatchCompleteStatus(result.status));
33
88
  const allComplete = results.length > 0 &&
34
- results.every((result) => result.status === 'reversed' || result.status === 'noop');
89
+ results.every((result) => isMatchCompleteStatus(result.status));
35
90
  if (occupancyChanged) {
36
91
  successActions.push(...refreshActualMatchingList(state$.value));
37
92
  }
93
+ const snackbar = matchAndReverseSnackbar(results, vendorName);
94
+ if (snackbar != null) {
95
+ successActions.push(snackbar);
96
+ }
38
97
  if (allComplete) {
39
98
  successActions.push(clearMatchNewModal());
40
99
  }
41
100
  return from(successActions);
42
101
  }
43
- return of(matchAndReverseAccrualsFailure({ status: response.status }));
102
+ return of(matchAndReverseAccrualsFailure({ status: response.status }), matchAndReverseHttpFailSnackbar(vendorName));
44
103
  }), catchError((error) => of(matchAndReverseAccrualsFailure({
45
104
  status: createZeniAPIStatus('Unexpected Error', 'Match and reverse accruals REST API call errored out' +
46
105
  JSON.stringify(error)),
47
- }))), takeUntil(actions$.pipe(filter(clearAll.match))));
106
+ }), matchAndReverseHttpFailSnackbar(vendorName))), takeUntil(actions$.pipe(filter(clearAll.match))));
48
107
  }));
@@ -1,17 +1,54 @@
1
1
  import { from, of } from 'rxjs';
2
2
  import { catchError, exhaustMap, filter, mergeMap, takeUntil, } from 'rxjs/operators';
3
+ import { getActualMatchingMatchById } from '../../../../entity/actualMatching/actualMatchingSelector';
4
+ import { openSnackbar } from '../../../../entity/snackbar/snackbarReducer';
3
5
  import { createZeniAPIStatus, isSuccessResponse, } from '../../../../responsePayload';
4
6
  import { clearAll } from '../../../../rootActions';
5
7
  import { toUndoReversalResult, } from '../../payload/actualMatchingPayload';
6
8
  import { fetchActualMatchingMatch, undoReversalAccruals, undoReversalAccrualsFailure, undoReversalAccrualsSuccess, } from '../../reducers/actualMatchingViewReducer';
7
9
  import { refreshActualMatchingList } from './refreshActualMatchingList';
10
+ function undoReversalSnackbar(results, vendorName) {
11
+ const undoneCount = results.filter((result) => result.status === 'undone').length;
12
+ const failedCount = results.length - undoneCount;
13
+ const variables = [
14
+ { variableName: '_count_', variableValue: String(undoneCount) },
15
+ { variableName: '_vendor_name_', variableValue: vendorName },
16
+ ];
17
+ if (results.length > 0 && failedCount === 0) {
18
+ return openSnackbar({
19
+ messageSection: 'actual_matching_undo_reversal',
20
+ messageText: 'success',
21
+ type: 'success',
22
+ variables,
23
+ });
24
+ }
25
+ if (undoneCount > 0 && failedCount > 0) {
26
+ return openSnackbar({
27
+ messageSection: 'actual_matching_undo_reversal',
28
+ messageText: 'notification',
29
+ type: 'warning',
30
+ variables,
31
+ });
32
+ }
33
+ return openSnackbar({
34
+ messageSection: 'actual_matching_undo_reversal',
35
+ messageText: 'failed',
36
+ type: 'error',
37
+ variables,
38
+ });
39
+ }
40
+ function matchVendorName(state, matchId) {
41
+ return (getActualMatchingMatchById(state.actualMatchingState, matchId)?.vendorName ??
42
+ '');
43
+ }
8
44
  export const undoReversalAccrualsEpic = (actions$, state$, zeniAPI) => actions$.pipe(filter(undoReversalAccruals.match),
9
- // Posts QBO deletes; drop duplicate clicks while a request is in flight.
45
+ // Posts QBO deletes; drop duplicate clicks while the first request is in flight.
10
46
  exhaustMap((action) => {
11
47
  const { accrualIds, matchId } = action.payload;
12
48
  const body = {
13
49
  accrual_ids: accrualIds,
14
50
  };
51
+ const vendorName = matchVendorName(state$.value, matchId);
15
52
  return zeniAPI
16
53
  .postAndGetJSON(`${zeniAPI.apiEndPoints.accountMicroServiceBaseUrl}/1.0/accruals/undo-reversal`, body)
17
54
  .pipe(mergeMap((response) => {
@@ -24,15 +61,16 @@ exhaustMap((action) => {
24
61
  if (anyUndone) {
25
62
  successActions.push(...refreshActualMatchingList(state$.value), fetchActualMatchingMatch(matchId, true));
26
63
  }
64
+ successActions.push(undoReversalSnackbar(results, vendorName));
27
65
  return from(successActions);
28
66
  }
29
67
  return of(undoReversalAccrualsFailure({
30
68
  matchId,
31
69
  status: response.status,
32
- }));
70
+ }), undoReversalSnackbar([], vendorName));
33
71
  }), catchError((error) => of(undoReversalAccrualsFailure({
34
72
  matchId,
35
73
  status: createZeniAPIStatus('Unexpected Error', 'Undo reversal accruals REST API call errored out' +
36
74
  JSON.stringify(error)),
37
- }))), takeUntil(actions$.pipe(filter(clearAll.match))));
75
+ }), undoReversalSnackbar([], vendorName))), takeUntil(actions$.pipe(filter(clearAll.match))));
38
76
  }));
@@ -45,7 +45,7 @@ export const initialState = {
45
45
  },
46
46
  matchModal: initialMatchModalState,
47
47
  undoReversalStatusByMatchId: {},
48
- lastUndoResultsByMatchId: {},
48
+ closeMatchAfterUndo: false,
49
49
  lastMatchResultsByMatchId: {},
50
50
  hasValidState() {
51
51
  return this.fetchState == 'Completed';
@@ -315,13 +315,13 @@ const expenseAutomationActualMatchingView = createSlice({
315
315
  error: undefined,
316
316
  };
317
317
  },
318
- prepare(transactionId, transactionIntegrationId, transactionType, lineId, transactionSyncToken, accrualIds) {
318
+ prepare(transactionId, transactionIntegrationId, transactionType, lineIds, transactionSyncToken, accrualIds) {
319
319
  return {
320
320
  payload: {
321
321
  transactionId,
322
322
  transactionIntegrationId,
323
323
  transactionType,
324
- lineId,
324
+ lineIds,
325
325
  transactionSyncToken,
326
326
  accrualIds,
327
327
  },
@@ -363,12 +363,17 @@ const expenseAutomationActualMatchingView = createSlice({
363
363
  fetchState: 'Completed',
364
364
  error: undefined,
365
365
  };
366
- draft.lastUndoResultsByMatchId[matchId] = results;
366
+ draft.closeMatchAfterUndo =
367
+ results.length > 0 &&
368
+ results.every((result) => result.status === 'undone');
367
369
  },
368
370
  prepare(matchId, results) {
369
371
  return { payload: { matchId, results } };
370
372
  },
371
373
  },
374
+ ackCloseMatchAfterUndo(draft) {
375
+ draft.closeMatchAfterUndo = false;
376
+ },
372
377
  undoReversalAccrualsFailure(draft, action) {
373
378
  draft.undoReversalStatusByMatchId[action.payload.matchId] = {
374
379
  fetchState: 'Error',
@@ -385,5 +390,5 @@ const expenseAutomationActualMatchingView = createSlice({
385
390
  });
386
391
  },
387
392
  });
388
- export const { clearActualMatchingView, clearMatchNewModal, closeMatchNewModal, fetchActualMatching, fetchActualMatchingFailure, fetchActualMatchingMatch, fetchActualMatchingMatchFailure, fetchActualMatchingMatchSuccess, fetchActualMatchingPage, fetchActualMatchingSuccess, matchAndReverseAccruals, matchAndReverseAccrualsFailure, matchAndReverseAccrualsSuccess, openMatchNewModal, searchMatchAccruals, searchMatchAccrualsFailure, searchMatchAccrualsSuccess, searchMatchTransactions, searchMatchTransactionsFailure, searchMatchTransactionsSuccess, undoReversalAccruals, undoReversalAccrualsFailure, undoReversalAccrualsSuccess, updateActualMatchingUIState, } = expenseAutomationActualMatchingView.actions;
393
+ export const { ackCloseMatchAfterUndo, clearActualMatchingView, clearMatchNewModal, closeMatchNewModal, fetchActualMatching, fetchActualMatchingFailure, fetchActualMatchingMatch, fetchActualMatchingMatchFailure, fetchActualMatchingMatchSuccess, fetchActualMatchingPage, fetchActualMatchingSuccess, matchAndReverseAccruals, matchAndReverseAccrualsFailure, matchAndReverseAccrualsSuccess, openMatchNewModal, searchMatchAccruals, searchMatchAccrualsFailure, searchMatchAccrualsSuccess, searchMatchTransactions, searchMatchTransactionsFailure, searchMatchTransactionsSuccess, undoReversalAccruals, undoReversalAccrualsFailure, undoReversalAccrualsSuccess, updateActualMatchingUIState, } = expenseAutomationActualMatchingView.actions;
389
394
  export default expenseAutomationActualMatchingView.reducer;
@@ -110,12 +110,32 @@ function collectGroupedMembers(members) {
110
110
  serviceMonth: member.serviceMonth,
111
111
  }));
112
112
  }
113
+ function collectLeftoverMembers(leftovers) {
114
+ if (leftovers == null || leftovers.length === 0) {
115
+ return undefined;
116
+ }
117
+ return leftovers.map((member) => ({
118
+ accrualId: member.accrualId,
119
+ estimatedAmount: member.estimatedAmount,
120
+ jeDebitAccountName: member.jeDebitAccountName,
121
+ memo: member.memo,
122
+ serviceMonth: member.serviceMonth,
123
+ }));
124
+ }
113
125
  function toActualMatchingRow(match) {
114
126
  const firstMember = match.members[0];
115
127
  if (firstMember == null) {
116
128
  throw new Error('Actual matching row requires at least one member');
117
129
  }
118
130
  const first = toMatchModalAccrual(firstMember);
131
+ const leftoverMembers = match.leftovers ?? [];
132
+ const fromCleared = firstMember.cleared?.intendedAccrualIds;
133
+ const intendedAccrualIds = fromCleared != null && fromCleared.length > 0
134
+ ? fromCleared
135
+ : [
136
+ ...match.members.map((member) => member.accrualId),
137
+ ...leftoverMembers.map((leftover) => leftover.accrualId),
138
+ ];
119
139
  return {
120
140
  ...first,
121
141
  matchId: match.matchId,
@@ -128,6 +148,8 @@ function toActualMatchingRow(match) {
128
148
  transactionDate: match.transactionDate,
129
149
  groupedAccrualIds: match.members.map((member) => member.accrualId),
130
150
  groupedMembers: collectGroupedMembers(match.members),
151
+ intendedAccrualIds,
152
+ leftovers: collectLeftoverMembers(match.leftovers),
131
153
  reversalDate: getActualMatchingReversalDate(first),
132
154
  vendorName: match.vendorName != null && match.vendorName !== ''
133
155
  ? match.vendorName
@@ -291,10 +313,12 @@ export function getExpenseAutomationActualMatchingMatchView(state, matchId) {
291
313
  detailFetchState: view.detailFetchStateByMatchId[matchId] ?? NOT_STARTED,
292
314
  refreshStatus: view.detailRefreshStatusByMatchId[matchId] ?? NOT_STARTED,
293
315
  undoReversalStatus: view.undoReversalStatusByMatchId[matchId] ?? NOT_STARTED,
294
- lastUndoResults: view.lastUndoResultsByMatchId[matchId],
295
316
  lastMatchResults: view.lastMatchResultsByMatchId?.[matchId],
296
317
  };
297
318
  }
319
+ export function getCloseMatchAfterUndo(state) {
320
+ return state.expenseAutomationActualMatchingViewState.closeMatchAfterUndo;
321
+ }
298
322
  export function getExpenseAutomationActualMatchingView(state) {
299
323
  const { expenseAutomationActualMatchingViewState } = state;
300
324
  const { matchIdsByPeriod, fetchState, error, refreshStatus, uiState, matchModal, } = expenseAutomationActualMatchingViewState;
@@ -320,7 +344,11 @@ export function getExpenseAutomationActualMatchingView(state) {
320
344
  ...(openedMatch?.members ?? []),
321
345
  ...(openedMatch?.leftovers ?? []),
322
346
  ].map(toMatchModalAccrual);
323
- const firstSuggestion = openedMatch?.members[0]?.matchSuggestion;
347
+ const firstMember = openedMatch?.members[0];
348
+ const cleared = firstMember?.cleared;
349
+ const suggestion = firstMember?.matchSuggestion;
350
+ const stamp = cleared ?? suggestion;
351
+ const consumedLineIds = cleared?.consumedLineIds;
324
352
  const prefill = openedMatch == null
325
353
  ? undefined
326
354
  : {
@@ -329,8 +357,11 @@ export function getExpenseAutomationActualMatchingView(state) {
329
357
  ...(openedMatch.leftovers ?? []).map((leftover) => leftover.accrualId),
330
358
  ],
331
359
  actualAmount: openedMatch.actualAmount.amount,
332
- matchedLineId: firstSuggestion?.matchedLineId,
333
- matchedTransactionId: firstSuggestion?.matchedTransactionId,
360
+ matchedTransactionId: stamp?.matchedTransactionId,
361
+ matchedLineId: cleared == null ? suggestion?.matchedLineId : undefined,
362
+ ...(consumedLineIds != null && consumedLineIds.length > 0
363
+ ? { consumedLineIds }
364
+ : {}),
334
365
  };
335
366
  return {
336
367
  fetchState,
package/lib/index.d.ts CHANGED
@@ -310,7 +310,7 @@ import { computeNewScheduleJeDetails } from './view/expenseAutomationView/helper
310
310
  import { isReviewTransactionBankTransferType, isReviewTransactionBillPaymentType, isReviewTransactionCreditCardCreditType, isReviewTransactionCreditCardPaymentType, isReviewTransactionDepositType, isReviewTransactionExpenseType } from './view/expenseAutomationView/helpers/reconciliationHelpers';
311
311
  import { MAX_SELECTION_LIMIT, checkIfAllLineItemsAreCategoryClassFilled, getLineItemsByTransactionIdsFromLocalData, isAnyItemWithUncategorizedExpenseAccount } from './view/expenseAutomationView/helpers/transactionCategorizationLocalDataHelper';
312
312
  import { UploadStatementDocumentAIPayload, UploadStatementDocumentAIResponse } from './view/expenseAutomationView/payload/reconciliationPayload';
313
- import { clearActualMatchingView as clearExpenseAutomationActualMatchingView, clearMatchNewModal, closeMatchNewModal, fetchActualMatching as fetchExpenseAutomationActualMatching, fetchActualMatchingMatch, fetchActualMatchingPage as fetchExpenseAutomationActualMatchingPage, matchAndReverseAccruals, openMatchNewModal, searchMatchAccruals, searchMatchTransactions, undoReversalAccruals, updateActualMatchingUIState as updateExpenseAutomationActualMatchingUIState } from './view/expenseAutomationView/reducers/actualMatchingViewReducer';
313
+ import { ackCloseMatchAfterUndo, clearActualMatchingView as clearExpenseAutomationActualMatchingView, clearMatchNewModal, closeMatchNewModal, fetchActualMatching as fetchExpenseAutomationActualMatching, fetchActualMatchingMatch, fetchActualMatchingPage as fetchExpenseAutomationActualMatchingPage, matchAndReverseAccruals, openMatchNewModal, searchMatchAccruals, searchMatchTransactions, undoReversalAccruals, updateActualMatchingUIState as updateExpenseAutomationActualMatchingUIState } from './view/expenseAutomationView/reducers/actualMatchingViewReducer';
314
314
  import { clearExpenseAutomationFluxAnalysisView, fetchFluxAnalysisView, reviewFluxAnalysisView, updateFluxAnalysisViewPageMetaData, updateFluxAnalysisViewUIState, updateOperatingExpensesIdsForReview, updateSelectedSectionIdsForReview } from './view/expenseAutomationView/reducers/fluxAnalysisViewReducer';
315
315
  import { clearJeScheduleLocalData as clearExpenseAutomationJEScheduleLocalData, clearExpenseAutomationJESchedulesView, clearSearchTransactionsForNewSchedule as clearJeSearchTransactionsForNewSchedule, createOneTimeAccrual, createOneTimeAccrualFailure, createOneTimeAccrualSuccess, fetchJeSchedulesPage as fetchExpenseAutomationJESchedulesPage, fetchOneTimeAccrual, ignoreRecommendedJeSchedule as ignoreExpenseAutomationJESchedule, ignoreOneTimeAccrual, initializeAccountSettingsView as initializeJeAccountSettingsView, initializeNewSchedule as initializeJeNewSchedule, initializeJeScheduleLocalData, promoteOneTimeAccrual, removeJeOneTimeAccrualLocalData, removeJeScheduleTransactionKey, resetNewScheduleLocalData as resetJeNewScheduleLocalData, retryJeSchedule as retryExpenseAutomationJESchedule, revertJeSchedule, revertOneTimeAccrual, saveAccountSettings as saveJeAccountSettings, saveAccountSettingsLocalData as saveJeAccountSettingsLocalData, saveNewSchedule as saveJeNewSchedule, saveNewScheduleFailure as saveJeNewScheduleFailure, saveNewScheduleSuccess as saveJeNewScheduleSuccess, searchTransactionsForNewSchedule as searchJeTransactionsForNewSchedule, searchTransactionsForNewScheduleFailure as searchJeTransactionsForNewScheduleFailure, searchTransactionsForNewScheduleSuccess as searchJeTransactionsForNewScheduleSuccess, toggleJECreatedGroupCollapsed, toggleJEPendingGroupCollapsed, updateJESchedulesUIState as updateExpenseAutomationJESchedulesUIState, updateJEScheduleTypeFilter, updateNewScheduleLocalData as updateJeNewScheduleLocalData, updateJeOneTimeAccrualLocalData, updateJeScheduleLocalDataById, updateJeScheduleTransactionKeys } from './view/expenseAutomationView/reducers/jeSchedulesViewReducer';
316
316
  import { acknowledgeBulkUploadConfirmMatchComplete, bulkUploadAutomatchingTimedOut, bulkUploadReceipts, bulkUploadReceiptsFailure, bulkUploadReceiptsSuccess, clearBulkUpload, clearBulkUploadBatchDetailsForScopeChange, clearManualSearchResults, clearMissingReceiptsTabNavigation, confirmBulkUploadMatch, confirmBulkUploadMatchFailure, confirmBulkUploadMatchSuccess, fetchBulkUploadBatchDetails, fetchBulkUploadBatchDetailsFailure, fetchBulkUploadBatchDetailsSuccess, fetchBulkUploadBatches, fetchBulkUploadBatchesFailure, fetchBulkUploadBatchesSuccess, fetchCompletedTransactions, fetchCompletedTransactionsFailure, fetchCompletedTransactionsSuccess, fetchMissingReceipts as fetchExpenseAutomationMissingReceipts, fetchMoreBatchDetails, fetchMoreBatchDetailsComplete, fetchMoreBatchDetailsFailure, markBatchDetailRefreshAttempted, markMissingReceiptAsDone as markExpenseAutomationMissingReceiptAsDone, pusherBatchStatusUpdate, refreshBatchDetailsForBatchId, requestMissingReceiptsTabNavigation, restoreBulkUploadAutomatchingOnMount, restoreBulkUploadMatchingState, searchTransactionsForManualMatch, searchTransactionsForManualMatchFailure, searchTransactionsForManualMatchSuccess, setBulkUploadCompletedSubTab, setBulkUploadResultsTab, setBulkUploadSortConfig, setBulkUploadUploadedFileCount, storeBatchDetails, updateBulkUploadProgress, updateMissingReceiptUploadState as updateExpenseAutomationMissingReceiptUploadState, updateMissingReceiptsUIState as updateExpenseAutomationMissingReceiptsUIState, uploadMissingReceiptSuccess as uploadExpenseAutomationMissingReceiptSuccess } from './view/expenseAutomationView/reducers/missingReceiptsViewReducer';
@@ -951,7 +951,7 @@ export { fetchApAging, getApAgingReport, updateApAgingUIState, AgingReportId, Ap
951
951
  export { fetchApAgingDetail, AgingReportInvoice, ApAgingDetail, getApAgingDetailForVendor, updateApAgingDetailUIState, };
952
952
  export { LinkBillExpenseKey };
953
953
  export { clearExpenseAutomationJEScheduleLocalData, clearExpenseAutomationJESchedulesView, clearJeSearchTransactionsForNewSchedule, fetchExpenseAutomationJESchedulesPage, ignoreExpenseAutomationJESchedule, initializeJeAccountSettingsView, initializeJeNewSchedule, initializeJeScheduleLocalData, removeJeScheduleTransactionKey, resetJeNewScheduleLocalData, retryExpenseAutomationJESchedule, saveJeNewSchedule, saveJeNewScheduleFailure, saveJeNewScheduleSuccess, searchJeTransactionsForNewSchedule, searchJeTransactionsForNewScheduleFailure, searchJeTransactionsForNewScheduleSuccess, updateExpenseAutomationJESchedulesUIState, updateJeNewScheduleLocalData, removeJeOneTimeAccrualLocalData, updateJeOneTimeAccrualLocalData, updateJeScheduleLocalDataById, updateJeScheduleTransactionKeys, };
954
- export { clearExpenseAutomationActualMatchingView, closeMatchNewModal, clearMatchNewModal, fetchExpenseAutomationActualMatching, fetchActualMatchingMatch, fetchExpenseAutomationActualMatchingPage, matchAndReverseAccruals, openMatchNewModal, searchMatchAccruals, searchMatchTransactions, undoReversalAccruals, updateExpenseAutomationActualMatchingUIState, };
954
+ export { ackCloseMatchAfterUndo, clearExpenseAutomationActualMatchingView, closeMatchNewModal, clearMatchNewModal, fetchExpenseAutomationActualMatching, fetchActualMatchingMatch, fetchExpenseAutomationActualMatchingPage, matchAndReverseAccruals, openMatchNewModal, searchMatchAccruals, searchMatchTransactions, undoReversalAccruals, updateExpenseAutomationActualMatchingUIState, };
955
955
  export { createNewSchedulesAccrued, deleteScheduleAccruedDetail, cancelScheduleAccruedJournalEntry, fetchScheduleAccruedDetails, fetchScheduleAccruedDetailsPage, resetJEAccruedLinkInLocalData, saveScheduleAccruedDetails, updateAmountsInScheduleAccruedDetail, updatedJEAccruedLinkWithRecommendedLocalData, updatedJELinkInLocalDataAccruedExpenses, fetchRecommendedTransactionRowIndex, clearSelectedJELinkRowIndex, updateLinkBillExpenseLocalData, updateScheduleAccruedDetailsLocalData, updateSelectedJEAccruedScheduleKey, resetSelectedJEAccruedScheduleKey, resetAccruedDetailNewScheduleState, };
956
956
  export { JEScheduleKey, JEScheduleTransactionKey, ScheduleTransactionID, getJEScheduleTransactionKey, ALL_JE_SCHEDULE_IGNORE_REASONS, ALL_JE_SCHEDULE_REVERT_REASONS, ALL_ONE_TIME_ACCRUAL_IGNORE_REASONS, ALL_ONE_TIME_ACCRUAL_REVERT_REASONS, ALL_SCHEDULES_TYPES, JEScheduledTransaction, JEAccruedSchedule, JEOneTimeAccrual, OneTimeAccrualEdits, JEOneTimeAccrualAiSuggestion, JEOneTimeAccrualBillingPattern, JEOneTimeAccrualCleared, JEOneTimeAccrualMatchSuggestion, JEOneTimeAccrualMonthlyTotal, JEOneTimeAccrualProfileSnapshot, JEOneTimeAccrualKey, JEScheduleAISummaries, JEScheduleFieldRecommendation, JEScheduleSummary, ScheduleTypes, ScheduleJournalEntryStatusCodeType, ScheduleListReport, ScheduleAccruedListReport, getScheduleListReport, getAccruedScheduleListReport, ScheduleSubTabType, ScheduleListSortKey, fetchScheduleList, fetchAccruedScheduleList, fetchDownloadSchedules, fetchSchedulesAccount, updateScheduleListLocalData, getFetchStateForScheduleAccountList, toScheduleTypesType, toScheduleTypesTypeStrict, toScheduleListTabsFileTypeStrict, ScheduleListLocalData, ScheduleDetailsLocalDataFixedAssets, ScheduleDetailsLocalDataAccruedExpenses, ScheduleDetailsView, ScheduleAccruedDetailsView, LinkBillExpenseView, LinkBillExpenseLocalData, JEScheduleDetailsLocalData, ScheduleDetailsLocalData, toScheduleSubTabType, ScheduleStatusCodeType, JEScheduleIgnoreReasonType, JEScheduleRevertReasonType, JournalEntryErrorCodeType, OneTimeAccrualIgnoreReasonType, OneTimeAccrualRevertReasonType, ScheduleTransaction, updateScheduleListSubTab, updateScheduleListSearchText, updateScheduleListScrollState, updateScheduleListSortState, ScheduleDetailSortKey, ScheduledJournalEntry, updateSelectedJEScheduleKey, fetchScheduleDetails, getScheduleDetailsView, getAccruedScheduleDetailsView, fetchScheduleDetailsPage, saveScheduleDetails, deleteScheduleDetail, createNewSchedules, updateScheduleDetailsLocalData, JETransactionLink, updateScheduleListDownloadState, updateAccruedJEScheduleAccruedByListKey, DownloadJEScheduleTabOptions, updatedSelectedJELinkRowIndex, ScheduleListTabsFileType, getQBOUrlForLink, getThirdPartyIDFromQBOURL, updatedJELinkInLocalData, updateAmountsInScheduleDetail, ScheduleDetailUIState, resetJELinkInLocalData, JEScheduledTransactionWithBalance, JEScheduleWithBalance, JELinkType, updatedJELinkWithRecommendedLocalData, getFetchStateForScheduleListByType, getDefaultSelectedTimeframeForScheduleType, markAsCompleteScheduleDetail, resetMarkAsCompleteStatus, fetchVendorTabView, updateVendorTabViewTab, VendorTabViewTabType, getVendorTabView, VendorTabViewSelectorView, };
957
957
  export { GlobalMerchant, GlobalMerchantBase, TenantMerchant };
@@ -1258,7 +1258,7 @@ export type { InvoicingOnboardingGateView } from './view/invoicing/invoicingConf
1258
1258
  export type { InvoicingConfigView } from './view/invoicing/invoicingConfigView/invoicingConfigViewSelector';
1259
1259
  export type { InvoicingOnboardingStatus } from './view/invoicing/invoicingConfigView/invoicingConfigViewPayload';
1260
1260
  export { getExpenseAutomationJEOneTimeAccrualDetailView, getJEScheduleRowType, isAccruedScheduleRow, isAiAccountantSchedule, isExistingTabRow, isOneTimeAccrualRow, isRenderableOneTimeAccrual, isPendingReviewRow, } from './view/expenseAutomationView/selectors/jeSchedulesViewSelector';
1261
- export { getActualMatchingAmount, getActualMatchingReversalDate, parseActualMatchingMatchId, getExpenseAutomationActualMatchingMatchView, getExpenseAutomationActualMatchingView, isAutoReversedAccrual, isManuallyReversedAccrual, isPendingReviewAccrual, } from './view/expenseAutomationView/selectors/actualMatchingViewSelector';
1261
+ export { getActualMatchingAmount, getActualMatchingReversalDate, getCloseMatchAfterUndo, parseActualMatchingMatchId, getExpenseAutomationActualMatchingMatchView, getExpenseAutomationActualMatchingView, isAutoReversedAccrual, isManuallyReversedAccrual, isPendingReviewAccrual, } from './view/expenseAutomationView/selectors/actualMatchingViewSelector';
1262
1262
  export type { ExpenseAutomationActualMatchingMatchView } from './view/expenseAutomationView/selectors/actualMatchingViewSelector';
1263
1263
  export type { ActualMatchingMatch, ActualMatchingMatchKind, } from './entity/actualMatching/actualMatchingState';
1264
1264
  export type { ActualMatchingMatchId } from './entity/actualMatching/actualMatchingTypes';