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

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 (23) 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/view/expenseAutomationView/epics/actualMatching/matchAndReverseAccrualsEpic.js +51 -12
  9. package/lib/esm/view/expenseAutomationView/epics/actualMatching/undoReversalAccrualsEpic.js +41 -3
  10. package/lib/esm/view/expenseAutomationView/reducers/actualMatchingViewReducer.js +2 -2
  11. package/lib/esm/view/expenseAutomationView/selectors/actualMatchingViewSelector.js +32 -3
  12. package/lib/view/expenseAutomationView/epics/actualMatching/matchAndReverseAccrualsEpic.d.ts +2 -1
  13. package/lib/view/expenseAutomationView/epics/actualMatching/matchAndReverseAccrualsEpic.js +49 -10
  14. package/lib/view/expenseAutomationView/epics/actualMatching/undoReversalAccrualsEpic.d.ts +2 -1
  15. package/lib/view/expenseAutomationView/epics/actualMatching/undoReversalAccrualsEpic.js +41 -3
  16. package/lib/view/expenseAutomationView/helpers/transactionCategorizationLocalDataHelper.d.ts +1 -1
  17. package/lib/view/expenseAutomationView/payload/actualMatchingPayload.d.ts +1 -1
  18. package/lib/view/expenseAutomationView/reducers/actualMatchingViewReducer.d.ts +2 -2
  19. package/lib/view/expenseAutomationView/reducers/actualMatchingViewReducer.js +2 -2
  20. package/lib/view/expenseAutomationView/selectorTypes/actualMatchingViewSelectorTypes.d.ts +3 -0
  21. package/lib/view/expenseAutomationView/selectors/actualMatchingViewSelector.js +32 -3
  22. package/lib/view/expenseAutomationView/types/actualMatchingViewState.d.ts +1 -1
  23. 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',
@@ -1,48 +1,87 @@
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 matchAndReverseSnackbar(results, vendorName) {
14
+ const completeCount = results.filter((result) => isMatchCompleteStatus(result.status)).length;
15
+ const failedCount = results.length - completeCount;
16
+ const variables = [
17
+ { variableName: '_count_', variableValue: String(completeCount) },
18
+ { variableName: '_vendor_name_', variableValue: vendorName },
19
+ ];
20
+ if (results.length > 0 && failedCount === 0) {
21
+ return openSnackbar({
22
+ messageSection: 'actual_matching_match_and_reverse',
23
+ messageText: 'success',
24
+ type: 'success',
25
+ variables,
26
+ });
27
+ }
28
+ if (completeCount > 0 && failedCount > 0) {
29
+ return openSnackbar({
30
+ messageSection: 'actual_matching_match_and_reverse',
31
+ messageText: 'notification',
32
+ type: 'warning',
33
+ variables,
34
+ });
35
+ }
36
+ return openSnackbar({
37
+ messageSection: 'actual_matching_match_and_reverse',
38
+ messageText: 'failed',
39
+ type: 'error',
40
+ variables,
41
+ });
42
+ }
43
+ function matchVendorName(state, matchId) {
44
+ return getActualMatchingMatchById(state.actualMatchingState, matchId)?.vendorName ?? '';
45
+ }
8
46
  export const matchAndReverseAccrualsEpic = (actions$, state$, zeniAPI) => actions$.pipe(filter(matchAndReverseAccruals.match),
9
47
  // Posts reversing JEs; drop duplicate clicks while a request is in flight.
10
48
  exhaustMap((action) => {
11
- const { transactionId, transactionIntegrationId, transactionType, lineId, accrualIds, transactionSyncToken, } = action.payload;
49
+ const { transactionId, transactionIntegrationId, transactionType, lineIds, accrualIds, transactionSyncToken, } = action.payload;
12
50
  const body = {
13
51
  transaction_id: transactionId,
14
52
  transaction_integration_id: transactionIntegrationId,
15
53
  transaction_type: transactionType,
16
- line_id: lineId,
54
+ line_ids: lineIds,
17
55
  transaction_sync_token: transactionSyncToken,
18
56
  accrual_ids: accrualIds,
19
57
  };
58
+ const openedFromMatchId = state$.value.expenseAutomationActualMatchingViewState.matchModal
59
+ .openedFromMatchId;
60
+ const matchId = openedFromMatchId ?? `${transactionType}:${transactionIntegrationId}`;
61
+ const vendorName = matchVendorName(state$.value, matchId);
20
62
  return zeniAPI
21
63
  .postAndGetJSON(`${zeniAPI.apiEndPoints.accountMicroServiceBaseUrl}/1.0/accruals/match-and-reverse`, body)
22
64
  .pipe(mergeMap((response) => {
23
65
  if (isSuccessResponse(response) && response.data != null) {
24
66
  const results = response.data.results.map(toMatchAndReverseResult);
25
- const openedFromMatchId = state$.value.expenseAutomationActualMatchingViewState.matchModal
26
- .openedFromMatchId;
27
- const matchId = openedFromMatchId ??
28
- `${transactionType}:${transactionIntegrationId}`;
29
67
  const successActions = [
30
68
  matchAndReverseAccrualsSuccess({ matchId, results }),
31
69
  ];
32
- const occupancyChanged = results.some((result) => result.status === 'reversed' || result.status === 'noop');
70
+ const occupancyChanged = results.some((result) => isMatchCompleteStatus(result.status));
33
71
  const allComplete = results.length > 0 &&
34
- results.every((result) => result.status === 'reversed' || result.status === 'noop');
72
+ results.every((result) => isMatchCompleteStatus(result.status));
35
73
  if (occupancyChanged) {
36
74
  successActions.push(...refreshActualMatchingList(state$.value));
37
75
  }
76
+ successActions.push(matchAndReverseSnackbar(results, vendorName));
38
77
  if (allComplete) {
39
78
  successActions.push(clearMatchNewModal());
40
79
  }
41
80
  return from(successActions);
42
81
  }
43
- return of(matchAndReverseAccrualsFailure({ status: response.status }));
82
+ return of(matchAndReverseAccrualsFailure({ status: response.status }), matchAndReverseSnackbar([], vendorName));
44
83
  }), catchError((error) => of(matchAndReverseAccrualsFailure({
45
84
  status: createZeniAPIStatus('Unexpected Error', 'Match and reverse accruals REST API call errored out' +
46
85
  JSON.stringify(error)),
47
- }))), takeUntil(actions$.pipe(filter(clearAll.match))));
86
+ }), matchAndReverseSnackbar([], vendorName))), takeUntil(actions$.pipe(filter(clearAll.match))));
48
87
  }));
@@ -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
  }));
@@ -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
  },
@@ -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
@@ -320,7 +342,11 @@ export function getExpenseAutomationActualMatchingView(state) {
320
342
  ...(openedMatch?.members ?? []),
321
343
  ...(openedMatch?.leftovers ?? []),
322
344
  ].map(toMatchModalAccrual);
323
- const firstSuggestion = openedMatch?.members[0]?.matchSuggestion;
345
+ const firstMember = openedMatch?.members[0];
346
+ const cleared = firstMember?.cleared;
347
+ const suggestion = firstMember?.matchSuggestion;
348
+ const stamp = cleared ?? suggestion;
349
+ const consumedLineIds = cleared?.consumedLineIds;
324
350
  const prefill = openedMatch == null
325
351
  ? undefined
326
352
  : {
@@ -329,8 +355,11 @@ export function getExpenseAutomationActualMatchingView(state) {
329
355
  ...(openedMatch.leftovers ?? []).map((leftover) => leftover.accrualId),
330
356
  ],
331
357
  actualAmount: openedMatch.actualAmount.amount,
332
- matchedLineId: firstSuggestion?.matchedLineId,
333
- matchedTransactionId: firstSuggestion?.matchedTransactionId,
358
+ matchedTransactionId: stamp?.matchedTransactionId,
359
+ matchedLineId: cleared == null ? suggestion?.matchedLineId : undefined,
360
+ ...(consumedLineIds != null && consumedLineIds.length > 0
361
+ ? { consumedLineIds }
362
+ : {}),
334
363
  };
335
364
  return {
336
365
  fetchState,
@@ -1,8 +1,9 @@
1
1
  import { ActionsObservable, StateObservable } from 'redux-observable';
2
2
  import { Observable } from 'rxjs';
3
+ import { openSnackbar } from '../../../../entity/snackbar/snackbarReducer';
3
4
  import { clearAll } from '../../../../rootActions';
4
5
  import { RootState } from '../../../../rootStateTypes';
5
6
  import { ZeniAPI } from '../../../../zeniAPI';
6
7
  import { clearMatchNewModal, fetchActualMatching, matchAndReverseAccruals, matchAndReverseAccrualsFailure, matchAndReverseAccrualsSuccess } from '../../reducers/actualMatchingViewReducer';
7
- export type ActionType = ReturnType<typeof clearAll> | ReturnType<typeof clearMatchNewModal> | ReturnType<typeof fetchActualMatching> | ReturnType<typeof matchAndReverseAccruals> | ReturnType<typeof matchAndReverseAccrualsFailure> | ReturnType<typeof matchAndReverseAccrualsSuccess>;
8
+ export type ActionType = ReturnType<typeof clearAll> | ReturnType<typeof clearMatchNewModal> | ReturnType<typeof fetchActualMatching> | ReturnType<typeof matchAndReverseAccruals> | ReturnType<typeof matchAndReverseAccrualsFailure> | ReturnType<typeof matchAndReverseAccrualsSuccess> | ReturnType<typeof openSnackbar>;
8
9
  export declare const matchAndReverseAccrualsEpic: (actions$: ActionsObservable<ActionType>, state$: StateObservable<RootState>, zeniAPI: ZeniAPI) => Observable<ActionType>;
@@ -3,50 +3,89 @@ Object.defineProperty(exports, "__esModule", { value: true });
3
3
  exports.matchAndReverseAccrualsEpic = void 0;
4
4
  const rxjs_1 = require("rxjs");
5
5
  const operators_1 = require("rxjs/operators");
6
+ const actualMatchingSelector_1 = require("../../../../entity/actualMatching/actualMatchingSelector");
7
+ const snackbarReducer_1 = require("../../../../entity/snackbar/snackbarReducer");
6
8
  const responsePayload_1 = require("../../../../responsePayload");
7
9
  const rootActions_1 = require("../../../../rootActions");
8
10
  const actualMatchingPayload_1 = require("../../payload/actualMatchingPayload");
9
11
  const actualMatchingViewReducer_1 = require("../../reducers/actualMatchingViewReducer");
10
12
  const refreshActualMatchingList_1 = require("./refreshActualMatchingList");
13
+ function isMatchCompleteStatus(status) {
14
+ return status === 'reversed' || status === 'noop';
15
+ }
16
+ function matchAndReverseSnackbar(results, vendorName) {
17
+ const completeCount = results.filter((result) => isMatchCompleteStatus(result.status)).length;
18
+ const failedCount = results.length - completeCount;
19
+ const variables = [
20
+ { variableName: '_count_', variableValue: String(completeCount) },
21
+ { variableName: '_vendor_name_', variableValue: vendorName },
22
+ ];
23
+ if (results.length > 0 && failedCount === 0) {
24
+ return (0, snackbarReducer_1.openSnackbar)({
25
+ messageSection: 'actual_matching_match_and_reverse',
26
+ messageText: 'success',
27
+ type: 'success',
28
+ variables,
29
+ });
30
+ }
31
+ if (completeCount > 0 && failedCount > 0) {
32
+ return (0, snackbarReducer_1.openSnackbar)({
33
+ messageSection: 'actual_matching_match_and_reverse',
34
+ messageText: 'notification',
35
+ type: 'warning',
36
+ variables,
37
+ });
38
+ }
39
+ return (0, snackbarReducer_1.openSnackbar)({
40
+ messageSection: 'actual_matching_match_and_reverse',
41
+ messageText: 'failed',
42
+ type: 'error',
43
+ variables,
44
+ });
45
+ }
46
+ function matchVendorName(state, matchId) {
47
+ return (0, actualMatchingSelector_1.getActualMatchingMatchById)(state.actualMatchingState, matchId)?.vendorName ?? '';
48
+ }
11
49
  const matchAndReverseAccrualsEpic = (actions$, state$, zeniAPI) => actions$.pipe((0, operators_1.filter)(actualMatchingViewReducer_1.matchAndReverseAccruals.match),
12
50
  // Posts reversing JEs; drop duplicate clicks while a request is in flight.
13
51
  (0, operators_1.exhaustMap)((action) => {
14
- const { transactionId, transactionIntegrationId, transactionType, lineId, accrualIds, transactionSyncToken, } = action.payload;
52
+ const { transactionId, transactionIntegrationId, transactionType, lineIds, accrualIds, transactionSyncToken, } = action.payload;
15
53
  const body = {
16
54
  transaction_id: transactionId,
17
55
  transaction_integration_id: transactionIntegrationId,
18
56
  transaction_type: transactionType,
19
- line_id: lineId,
57
+ line_ids: lineIds,
20
58
  transaction_sync_token: transactionSyncToken,
21
59
  accrual_ids: accrualIds,
22
60
  };
61
+ const openedFromMatchId = state$.value.expenseAutomationActualMatchingViewState.matchModal
62
+ .openedFromMatchId;
63
+ const matchId = openedFromMatchId ?? `${transactionType}:${transactionIntegrationId}`;
64
+ const vendorName = matchVendorName(state$.value, matchId);
23
65
  return zeniAPI
24
66
  .postAndGetJSON(`${zeniAPI.apiEndPoints.accountMicroServiceBaseUrl}/1.0/accruals/match-and-reverse`, body)
25
67
  .pipe((0, operators_1.mergeMap)((response) => {
26
68
  if ((0, responsePayload_1.isSuccessResponse)(response) && response.data != null) {
27
69
  const results = response.data.results.map(actualMatchingPayload_1.toMatchAndReverseResult);
28
- const openedFromMatchId = state$.value.expenseAutomationActualMatchingViewState.matchModal
29
- .openedFromMatchId;
30
- const matchId = openedFromMatchId ??
31
- `${transactionType}:${transactionIntegrationId}`;
32
70
  const successActions = [
33
71
  (0, actualMatchingViewReducer_1.matchAndReverseAccrualsSuccess)({ matchId, results }),
34
72
  ];
35
- const occupancyChanged = results.some((result) => result.status === 'reversed' || result.status === 'noop');
73
+ const occupancyChanged = results.some((result) => isMatchCompleteStatus(result.status));
36
74
  const allComplete = results.length > 0 &&
37
- results.every((result) => result.status === 'reversed' || result.status === 'noop');
75
+ results.every((result) => isMatchCompleteStatus(result.status));
38
76
  if (occupancyChanged) {
39
77
  successActions.push(...(0, refreshActualMatchingList_1.refreshActualMatchingList)(state$.value));
40
78
  }
79
+ successActions.push(matchAndReverseSnackbar(results, vendorName));
41
80
  if (allComplete) {
42
81
  successActions.push((0, actualMatchingViewReducer_1.clearMatchNewModal)());
43
82
  }
44
83
  return (0, rxjs_1.from)(successActions);
45
84
  }
46
- return (0, rxjs_1.of)((0, actualMatchingViewReducer_1.matchAndReverseAccrualsFailure)({ status: response.status }));
85
+ return (0, rxjs_1.of)((0, actualMatchingViewReducer_1.matchAndReverseAccrualsFailure)({ status: response.status }), matchAndReverseSnackbar([], vendorName));
47
86
  }), (0, operators_1.catchError)((error) => (0, rxjs_1.of)((0, actualMatchingViewReducer_1.matchAndReverseAccrualsFailure)({
48
87
  status: (0, responsePayload_1.createZeniAPIStatus)('Unexpected Error', 'Match and reverse accruals REST API call errored out' +
49
88
  JSON.stringify(error)),
50
- }))), (0, operators_1.takeUntil)(actions$.pipe((0, operators_1.filter)(rootActions_1.clearAll.match))));
89
+ }), matchAndReverseSnackbar([], vendorName))), (0, operators_1.takeUntil)(actions$.pipe((0, operators_1.filter)(rootActions_1.clearAll.match))));
51
90
  }));
52
91
  exports.matchAndReverseAccrualsEpic = matchAndReverseAccrualsEpic;
@@ -1,8 +1,9 @@
1
1
  import { ActionsObservable, StateObservable } from 'redux-observable';
2
2
  import { Observable } from 'rxjs';
3
+ import { openSnackbar } from '../../../../entity/snackbar/snackbarReducer';
3
4
  import { clearAll } from '../../../../rootActions';
4
5
  import { RootState } from '../../../../rootStateTypes';
5
6
  import { ZeniAPI } from '../../../../zeniAPI';
6
7
  import { fetchActualMatching, fetchActualMatchingMatch, undoReversalAccruals, undoReversalAccrualsFailure, undoReversalAccrualsSuccess } from '../../reducers/actualMatchingViewReducer';
7
- export type ActionType = ReturnType<typeof clearAll> | ReturnType<typeof fetchActualMatching> | ReturnType<typeof fetchActualMatchingMatch> | ReturnType<typeof undoReversalAccruals> | ReturnType<typeof undoReversalAccrualsFailure> | ReturnType<typeof undoReversalAccrualsSuccess>;
8
+ export type ActionType = ReturnType<typeof clearAll> | ReturnType<typeof fetchActualMatching> | ReturnType<typeof fetchActualMatchingMatch> | ReturnType<typeof openSnackbar> | ReturnType<typeof undoReversalAccruals> | ReturnType<typeof undoReversalAccrualsFailure> | ReturnType<typeof undoReversalAccrualsSuccess>;
8
9
  export declare const undoReversalAccrualsEpic: (actions$: ActionsObservable<ActionType>, state$: StateObservable<RootState>, zeniAPI: ZeniAPI) => Observable<ActionType>;
@@ -3,18 +3,55 @@ Object.defineProperty(exports, "__esModule", { value: true });
3
3
  exports.undoReversalAccrualsEpic = void 0;
4
4
  const rxjs_1 = require("rxjs");
5
5
  const operators_1 = require("rxjs/operators");
6
+ const actualMatchingSelector_1 = require("../../../../entity/actualMatching/actualMatchingSelector");
7
+ const snackbarReducer_1 = require("../../../../entity/snackbar/snackbarReducer");
6
8
  const responsePayload_1 = require("../../../../responsePayload");
7
9
  const rootActions_1 = require("../../../../rootActions");
8
10
  const actualMatchingPayload_1 = require("../../payload/actualMatchingPayload");
9
11
  const actualMatchingViewReducer_1 = require("../../reducers/actualMatchingViewReducer");
10
12
  const refreshActualMatchingList_1 = require("./refreshActualMatchingList");
13
+ function undoReversalSnackbar(results, vendorName) {
14
+ const undoneCount = results.filter((result) => result.status === 'undone').length;
15
+ const failedCount = results.length - undoneCount;
16
+ const variables = [
17
+ { variableName: '_count_', variableValue: String(undoneCount) },
18
+ { variableName: '_vendor_name_', variableValue: vendorName },
19
+ ];
20
+ if (results.length > 0 && failedCount === 0) {
21
+ return (0, snackbarReducer_1.openSnackbar)({
22
+ messageSection: 'actual_matching_undo_reversal',
23
+ messageText: 'success',
24
+ type: 'success',
25
+ variables,
26
+ });
27
+ }
28
+ if (undoneCount > 0 && failedCount > 0) {
29
+ return (0, snackbarReducer_1.openSnackbar)({
30
+ messageSection: 'actual_matching_undo_reversal',
31
+ messageText: 'notification',
32
+ type: 'warning',
33
+ variables,
34
+ });
35
+ }
36
+ return (0, snackbarReducer_1.openSnackbar)({
37
+ messageSection: 'actual_matching_undo_reversal',
38
+ messageText: 'failed',
39
+ type: 'error',
40
+ variables,
41
+ });
42
+ }
43
+ function matchVendorName(state, matchId) {
44
+ return ((0, actualMatchingSelector_1.getActualMatchingMatchById)(state.actualMatchingState, matchId)?.vendorName ??
45
+ '');
46
+ }
11
47
  const undoReversalAccrualsEpic = (actions$, state$, zeniAPI) => actions$.pipe((0, operators_1.filter)(actualMatchingViewReducer_1.undoReversalAccruals.match),
12
- // Posts QBO deletes; drop duplicate clicks while a request is in flight.
48
+ // Posts QBO deletes; drop duplicate clicks while the first request is in flight.
13
49
  (0, operators_1.exhaustMap)((action) => {
14
50
  const { accrualIds, matchId } = action.payload;
15
51
  const body = {
16
52
  accrual_ids: accrualIds,
17
53
  };
54
+ const vendorName = matchVendorName(state$.value, matchId);
18
55
  return zeniAPI
19
56
  .postAndGetJSON(`${zeniAPI.apiEndPoints.accountMicroServiceBaseUrl}/1.0/accruals/undo-reversal`, body)
20
57
  .pipe((0, operators_1.mergeMap)((response) => {
@@ -27,16 +64,17 @@ const undoReversalAccrualsEpic = (actions$, state$, zeniAPI) => actions$.pipe((0
27
64
  if (anyUndone) {
28
65
  successActions.push(...(0, refreshActualMatchingList_1.refreshActualMatchingList)(state$.value), (0, actualMatchingViewReducer_1.fetchActualMatchingMatch)(matchId, true));
29
66
  }
67
+ successActions.push(undoReversalSnackbar(results, vendorName));
30
68
  return (0, rxjs_1.from)(successActions);
31
69
  }
32
70
  return (0, rxjs_1.of)((0, actualMatchingViewReducer_1.undoReversalAccrualsFailure)({
33
71
  matchId,
34
72
  status: response.status,
35
- }));
73
+ }), undoReversalSnackbar([], vendorName));
36
74
  }), (0, operators_1.catchError)((error) => (0, rxjs_1.of)((0, actualMatchingViewReducer_1.undoReversalAccrualsFailure)({
37
75
  matchId,
38
76
  status: (0, responsePayload_1.createZeniAPIStatus)('Unexpected Error', 'Undo reversal accruals REST API call errored out' +
39
77
  JSON.stringify(error)),
40
- }))), (0, operators_1.takeUntil)(actions$.pipe((0, operators_1.filter)(rootActions_1.clearAll.match))));
78
+ }), undoReversalSnackbar([], vendorName))), (0, operators_1.takeUntil)(actions$.pipe((0, operators_1.filter)(rootActions_1.clearAll.match))));
41
79
  }));
42
80
  exports.undoReversalAccrualsEpic = undoReversalAccrualsEpic;
@@ -39,7 +39,7 @@ export declare const getLineItemsByTransactionsIdsFromResponse: (transactions: S
39
39
  export declare const getLineItemsByTransactionIdsFromLocalData: (transactionLocalData: TransactionReviewLocalDataSelectorView[], selectedTab: TransactionsTab) => Record<ID, string[]>;
40
40
  export declare const mergeTabSpecificLineItems: (currentTabSpecificLineItems: TabSpecificLineItems, selectedTab: TransactionsTab, newLineItems: TabSpecificLineItems) => TabSpecificLineItems;
41
41
  export declare const getSnackbarMessageForTransactionReview: (updatedCount: number, failedCount: number, categorizedCount: number) => {
42
- messageSection: "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";
42
+ messageSection: "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";
43
43
  messageText: "notification" | "failed" | "success";
44
44
  type: "error" | "success" | "info";
45
45
  variables: {
@@ -50,7 +50,7 @@ export type MatchTransactionSearchResponse = ZeniAPIResponse<MatchTransactionSea
50
50
  export declare function toActualMatchingTransactionSearchResult(payload: MatchTransactionSearchResultPayload, fallbackCurrency?: DisplayCurrencyFallback): ActualMatchingTransactionSearchResult;
51
51
  export interface MatchAndReverseRequestPayload {
52
52
  accrual_ids: ID[];
53
- line_id: string;
53
+ line_ids: ID[];
54
54
  transaction_id: ID;
55
55
  transaction_integration_id: string;
56
56
  transaction_sync_token: string;
@@ -31,11 +31,11 @@ export declare const clearActualMatchingView: import("@reduxjs/toolkit").ActionC
31
31
  matchIds: ActualMatchingMatchId[];
32
32
  refreshViewInBackground: boolean;
33
33
  selectedPeriod: MonthYearPeriod;
34
- }, "expenseAutomationActualMatchingView/fetchActualMatchingSuccess">, matchAndReverseAccruals: import("@reduxjs/toolkit").ActionCreatorWithPreparedPayload<[transactionId: string, transactionIntegrationId: string, transactionType: string, lineId: string, transactionSyncToken: string, accrualIds: string[]], {
34
+ }, "expenseAutomationActualMatchingView/fetchActualMatchingSuccess">, matchAndReverseAccruals: import("@reduxjs/toolkit").ActionCreatorWithPreparedPayload<[transactionId: string, transactionIntegrationId: string, transactionType: string, lineIds: string[], transactionSyncToken: string, accrualIds: string[]], {
35
35
  transactionId: string;
36
36
  transactionIntegrationId: string;
37
37
  transactionType: string;
38
- lineId: string;
38
+ lineIds: string[];
39
39
  transactionSyncToken: string;
40
40
  accrualIds: string[];
41
41
  }, "expenseAutomationActualMatchingView/matchAndReverseAccruals", never, never>, matchAndReverseAccrualsFailure: import("@reduxjs/toolkit").ActionCreatorWithPayload<{
@@ -319,13 +319,13 @@ const expenseAutomationActualMatchingView = (0, toolkit_1.createSlice)({
319
319
  error: undefined,
320
320
  };
321
321
  },
322
- prepare(transactionId, transactionIntegrationId, transactionType, lineId, transactionSyncToken, accrualIds) {
322
+ prepare(transactionId, transactionIntegrationId, transactionType, lineIds, transactionSyncToken, accrualIds) {
323
323
  return {
324
324
  payload: {
325
325
  transactionId,
326
326
  transactionIntegrationId,
327
327
  transactionType,
328
- lineId,
328
+ lineIds,
329
329
  transactionSyncToken,
330
330
  accrualIds,
331
331
  },
@@ -19,6 +19,8 @@ export interface ActualMatchingRow extends JEOneTimeAccrual {
19
19
  matchId: string;
20
20
  groupedAccrualIds?: ID[];
21
21
  groupedMembers?: ActualMatchingGroupedAccrual[];
22
+ intendedAccrualIds?: ID[];
23
+ leftovers?: ActualMatchingGroupedAccrual[];
22
24
  matchShape?: string;
23
25
  matchTier?: string;
24
26
  reversalDate?: ZeniDate;
@@ -69,6 +71,7 @@ export interface ActualMatchingMatchModalView {
69
71
  prefill?: {
70
72
  selectedAccrualIds: ID[];
71
73
  actualAmount?: number;
74
+ consumedLineIds?: ID[];
72
75
  matchedLineId?: string;
73
76
  matchedTransactionId?: string;
74
77
  };
@@ -128,12 +128,32 @@ function collectGroupedMembers(members) {
128
128
  serviceMonth: member.serviceMonth,
129
129
  }));
130
130
  }
131
+ function collectLeftoverMembers(leftovers) {
132
+ if (leftovers == null || leftovers.length === 0) {
133
+ return undefined;
134
+ }
135
+ return leftovers.map((member) => ({
136
+ accrualId: member.accrualId,
137
+ estimatedAmount: member.estimatedAmount,
138
+ jeDebitAccountName: member.jeDebitAccountName,
139
+ memo: member.memo,
140
+ serviceMonth: member.serviceMonth,
141
+ }));
142
+ }
131
143
  function toActualMatchingRow(match) {
132
144
  const firstMember = match.members[0];
133
145
  if (firstMember == null) {
134
146
  throw new Error('Actual matching row requires at least one member');
135
147
  }
136
148
  const first = toMatchModalAccrual(firstMember);
149
+ const leftoverMembers = match.leftovers ?? [];
150
+ const fromCleared = firstMember.cleared?.intendedAccrualIds;
151
+ const intendedAccrualIds = fromCleared != null && fromCleared.length > 0
152
+ ? fromCleared
153
+ : [
154
+ ...match.members.map((member) => member.accrualId),
155
+ ...leftoverMembers.map((leftover) => leftover.accrualId),
156
+ ];
137
157
  return {
138
158
  ...first,
139
159
  matchId: match.matchId,
@@ -146,6 +166,8 @@ function toActualMatchingRow(match) {
146
166
  transactionDate: match.transactionDate,
147
167
  groupedAccrualIds: match.members.map((member) => member.accrualId),
148
168
  groupedMembers: collectGroupedMembers(match.members),
169
+ intendedAccrualIds,
170
+ leftovers: collectLeftoverMembers(match.leftovers),
149
171
  reversalDate: getActualMatchingReversalDate(first),
150
172
  vendorName: match.vendorName != null && match.vendorName !== ''
151
173
  ? match.vendorName
@@ -338,7 +360,11 @@ function getExpenseAutomationActualMatchingView(state) {
338
360
  ...(openedMatch?.members ?? []),
339
361
  ...(openedMatch?.leftovers ?? []),
340
362
  ].map(toMatchModalAccrual);
341
- const firstSuggestion = openedMatch?.members[0]?.matchSuggestion;
363
+ const firstMember = openedMatch?.members[0];
364
+ const cleared = firstMember?.cleared;
365
+ const suggestion = firstMember?.matchSuggestion;
366
+ const stamp = cleared ?? suggestion;
367
+ const consumedLineIds = cleared?.consumedLineIds;
342
368
  const prefill = openedMatch == null
343
369
  ? undefined
344
370
  : {
@@ -347,8 +373,11 @@ function getExpenseAutomationActualMatchingView(state) {
347
373
  ...(openedMatch.leftovers ?? []).map((leftover) => leftover.accrualId),
348
374
  ],
349
375
  actualAmount: openedMatch.actualAmount.amount,
350
- matchedLineId: firstSuggestion?.matchedLineId,
351
- matchedTransactionId: firstSuggestion?.matchedTransactionId,
376
+ matchedTransactionId: stamp?.matchedTransactionId,
377
+ matchedLineId: cleared == null ? suggestion?.matchedLineId : undefined,
378
+ ...(consumedLineIds != null && consumedLineIds.length > 0
379
+ ? { consumedLineIds }
380
+ : {}),
352
381
  };
353
382
  return {
354
383
  fetchState,
@@ -51,7 +51,7 @@ export interface MatchAndReverseResult {
51
51
  }
52
52
  export interface MatchAndReverseAccrualsParams {
53
53
  accrualIds: ID[];
54
- lineId: string;
54
+ lineIds: ID[];
55
55
  transactionId: ID;
56
56
  transactionIntegrationId: string;
57
57
  transactionSyncToken: string;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@zeniai/client-epic-state",
3
- "version": "5.2.35-beta4MM",
3
+ "version": "5.2.35-beta5MM",
4
4
  "description": "Shared module between Web & Mobile containing required abstractions for state management, async network communication. ",
5
5
  "main": "lib/index.js",
6
6
  "module": "lib/esm/index.js",