@zeniai/client-epic-state 5.2.28 → 5.2.30-betaRD0

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.
@@ -145,9 +145,16 @@ export interface JEAccruedScheduledTransactionState extends Omit<JEScheduledTran
145
145
  export interface OneTimeAccrualEdits {
146
146
  expectedReversalDate?: ZeniDate;
147
147
  jeCreditAccountId?: ID;
148
+ /**
149
+ * Carried beside the id, not derived from it later: the accrual document stores the name too, so
150
+ * an id sent without its name leaves the row displaying the account the user just moved away
151
+ * from.
152
+ */
153
+ jeCreditAccountName?: string;
148
154
  jeDebitAccountId?: ID;
149
155
  jeDebitAccountingClassId?: ID;
150
156
  jeDebitAccountingClassName?: string;
157
+ jeDebitAccountName?: string;
151
158
  memo?: string;
152
159
  /**
153
160
  * The Auto Reversal toggle, modelled as the same boolean the New form and the create payload use
@@ -9,6 +9,18 @@ import { clearAll } from '../../../../rootActions';
9
9
  import { date } from '../../../../zeniDayJS';
10
10
  import { SERVICE_MONTH_FORMAT, } from '../../payload/jeSchedulesPayload';
11
11
  import { fetchJeSchedules, fetchJeSchedulesFailure, fetchJeSchedulesSuccess, initializeJeScheduleLocalData, } from '../../reducers/jeSchedulesViewReducer';
12
+ /**
13
+ * How far back to look for accrued schedules, matching the Vendors page
14
+ * (`getDefaultSelectedTimeframeForScheduleType`, 'accrued_expenses'), which queries the same
15
+ * start_date filter through /1.0/schedules.
16
+ */
17
+ const ACCRUED_LOOKBACK_MONTHS = 24;
18
+ /**
19
+ * One-time accruals keep their own, narrower lookback. Unlike an accrued schedule they belong to
20
+ * exactly one service month and never span months, so the reason the accrued window has to reach
21
+ * back does not apply to them -- widening it would only add older history to the Existing tab.
22
+ */
23
+ const ONE_TIME_ACCRUAL_LOOKBACK_MONTHS = 12;
12
24
  export const fetchJeSchedulesEpic = (actions$, state$, zeniAPI) => actions$.pipe(filter(fetchJeSchedules.match), mergeMap((action) => {
13
25
  const state = state$.value;
14
26
  const { expenseAutomationViewState: { selectedPeriodByTenantId }, } = state;
@@ -30,15 +42,21 @@ export const fetchJeSchedulesEpic = (actions$, state$, zeniAPI) => actions$.pipe
30
42
  const endDate = isClosePeriodTab || existingEndDate == null
31
43
  ? toString(period.end)
32
44
  : toString(existingEndDate);
33
- // Accrued rows are windowed on the schedule's own start_date rather than a transaction date,
34
- // so they get their own bounds. Review wants the month being closed; Existing wants the year
35
- // up to endDate, snapped to the 1st — the same window the server used to compute for itself.
36
- const accruedStartDate = isClosePeriodTab
37
- ? toString(period.start)
38
- : date(endDate)
39
- .subtract(1, 'year')
40
- .startOf('month')
41
- .format(DEFAULT_DATE_FORMAT);
45
+ // Accrued rows are windowed on the schedule's own start_date -- its FIRST posting date --
46
+ // rather than a transaction date, so the lower bound has to reach back past the start of
47
+ // every accrual still running in this period, not just the ones that began in it. Review
48
+ // used to send the close month itself, which returned only accruals whose first posting fell
49
+ // in that month and hid every longer-running one.
50
+ const parsedEndDate = date(endDate);
51
+ const accruedStartDate = parsedEndDate
52
+ .subtract(ACCRUED_LOOKBACK_MONTHS, 'month')
53
+ .startOf('month')
54
+ .format(DEFAULT_DATE_FORMAT);
55
+ // Formatted as a service month, not a date: that is the only thing it is sent as.
56
+ const oneTimeAccrualServiceMonthStart = parsedEndDate
57
+ .subtract(ONE_TIME_ACCRUAL_LOOKBACK_MONTHS, 'month')
58
+ .startOf('month')
59
+ .format(SERVICE_MONTH_FORMAT);
42
60
  const queryParam = {
43
61
  base_transaction_end_date: endDate,
44
62
  end_date: endDate,
@@ -59,8 +77,8 @@ export const fetchJeSchedulesEpic = (actions$, state$, zeniAPI) => actions$.pipe
59
77
  filter_failed_je_postings_by_date: true,
60
78
  }
61
79
  : {
62
- one_time_accrual_service_month_start: date(accruedStartDate).format(SERVICE_MONTH_FORMAT),
63
- one_time_accrual_service_month_end: date(endDate).format(SERVICE_MONTH_FORMAT),
80
+ one_time_accrual_service_month_start: oneTimeAccrualServiceMonthStart,
81
+ one_time_accrual_service_month_end: parsedEndDate.format(SERVICE_MONTH_FORMAT),
64
82
  // Existing lists what actually reached the books.
65
83
  one_time_accrual_statuses: ['posted'],
66
84
  // A failed posting from an earlier month still needs to surface here, so this list
@@ -73,17 +73,39 @@ export const promoteOneTimeAccrualEpic = (actions$, state$, zeniAPI) => actions$
73
73
  const debitClassId = edits?.jeDebitAccountingClassId ?? accrual?.jeDebitAccountingClassId;
74
74
  const debitClassName = edits?.jeDebitAccountingClassName ??
75
75
  accrual?.jeDebitAccountingClassName;
76
+ // The accrual document stores names alongside ids, so every id below travels with its name.
77
+ // Sending an id on its own leaves the stored row -- and the JE posted from it -- naming the
78
+ // account the user just moved away from. Create has always sent the full set; promote did
79
+ // not, which is the difference the two paths were showing.
80
+ const debitAccountName = edits?.jeDebitAccountName ?? accrual?.jeDebitAccountName;
81
+ const creditAccountName = edits?.jeCreditAccountName ?? accrual?.jeCreditAccountName;
82
+ // Credit-side class is never edited on this form -- the liability side is the Balance Sheet
83
+ // class the draft was born with -- so it is echoed straight back from the draft.
84
+ const creditClassId = accrual?.jeCreditAccountingClassId;
85
+ const creditClassName = accrual?.jeCreditAccountingClassName;
76
86
  const payload = {
77
87
  amount,
78
88
  memo: edits?.memo ?? accrual?.memo ?? '',
79
89
  je_debit_account_id: debitAccountId,
80
90
  je_credit_account_id: creditAccountId,
91
+ ...(debitAccountName != null
92
+ ? { je_debit_account_name: debitAccountName }
93
+ : {}),
94
+ ...(creditAccountName != null
95
+ ? { je_credit_account_name: creditAccountName }
96
+ : {}),
81
97
  ...(debitClassId != null
82
98
  ? { je_debit_accounting_class_id: debitClassId }
83
99
  : {}),
84
100
  ...(debitClassName != null
85
101
  ? { je_debit_accounting_class_name: debitClassName }
86
102
  : {}),
103
+ ...(creditClassId != null
104
+ ? { je_credit_accounting_class_id: creditClassId }
105
+ : {}),
106
+ ...(creditClassName != null
107
+ ? { je_credit_accounting_class_name: creditClassName }
108
+ : {}),
87
109
  // Mirrors the create payload: reverse_next_month alone decides the policy, and the date is
88
110
  // only meaningful when it is true -- agent-je derives the reversal from the bill otherwise.
89
111
  reverse_next_month: reverseNextMonth,
@@ -12,6 +12,18 @@ const rootActions_1 = require("../../../../rootActions");
12
12
  const zeniDayJS_1 = require("../../../../zeniDayJS");
13
13
  const jeSchedulesPayload_1 = require("../../payload/jeSchedulesPayload");
14
14
  const jeSchedulesViewReducer_1 = require("../../reducers/jeSchedulesViewReducer");
15
+ /**
16
+ * How far back to look for accrued schedules, matching the Vendors page
17
+ * (`getDefaultSelectedTimeframeForScheduleType`, 'accrued_expenses'), which queries the same
18
+ * start_date filter through /1.0/schedules.
19
+ */
20
+ const ACCRUED_LOOKBACK_MONTHS = 24;
21
+ /**
22
+ * One-time accruals keep their own, narrower lookback. Unlike an accrued schedule they belong to
23
+ * exactly one service month and never span months, so the reason the accrued window has to reach
24
+ * back does not apply to them -- widening it would only add older history to the Existing tab.
25
+ */
26
+ const ONE_TIME_ACCRUAL_LOOKBACK_MONTHS = 12;
15
27
  const fetchJeSchedulesEpic = (actions$, state$, zeniAPI) => actions$.pipe((0, operators_1.filter)(jeSchedulesViewReducer_1.fetchJeSchedules.match), (0, operators_1.mergeMap)((action) => {
16
28
  const state = state$.value;
17
29
  const { expenseAutomationViewState: { selectedPeriodByTenantId }, } = state;
@@ -33,15 +45,21 @@ const fetchJeSchedulesEpic = (actions$, state$, zeniAPI) => actions$.pipe((0, op
33
45
  const endDate = isClosePeriodTab || existingEndDate == null
34
46
  ? (0, timePeriod_2.toString)(period.end)
35
47
  : (0, timePeriod_2.toString)(existingEndDate);
36
- // Accrued rows are windowed on the schedule's own start_date rather than a transaction date,
37
- // so they get their own bounds. Review wants the month being closed; Existing wants the year
38
- // up to endDate, snapped to the 1st — the same window the server used to compute for itself.
39
- const accruedStartDate = isClosePeriodTab
40
- ? (0, timePeriod_2.toString)(period.start)
41
- : (0, zeniDayJS_1.date)(endDate)
42
- .subtract(1, 'year')
43
- .startOf('month')
44
- .format(timePeriod_1.DEFAULT_DATE_FORMAT);
48
+ // Accrued rows are windowed on the schedule's own start_date -- its FIRST posting date --
49
+ // rather than a transaction date, so the lower bound has to reach back past the start of
50
+ // every accrual still running in this period, not just the ones that began in it. Review
51
+ // used to send the close month itself, which returned only accruals whose first posting fell
52
+ // in that month and hid every longer-running one.
53
+ const parsedEndDate = (0, zeniDayJS_1.date)(endDate);
54
+ const accruedStartDate = parsedEndDate
55
+ .subtract(ACCRUED_LOOKBACK_MONTHS, 'month')
56
+ .startOf('month')
57
+ .format(timePeriod_1.DEFAULT_DATE_FORMAT);
58
+ // Formatted as a service month, not a date: that is the only thing it is sent as.
59
+ const oneTimeAccrualServiceMonthStart = parsedEndDate
60
+ .subtract(ONE_TIME_ACCRUAL_LOOKBACK_MONTHS, 'month')
61
+ .startOf('month')
62
+ .format(jeSchedulesPayload_1.SERVICE_MONTH_FORMAT);
45
63
  const queryParam = {
46
64
  base_transaction_end_date: endDate,
47
65
  end_date: endDate,
@@ -62,8 +80,8 @@ const fetchJeSchedulesEpic = (actions$, state$, zeniAPI) => actions$.pipe((0, op
62
80
  filter_failed_je_postings_by_date: true,
63
81
  }
64
82
  : {
65
- one_time_accrual_service_month_start: (0, zeniDayJS_1.date)(accruedStartDate).format(jeSchedulesPayload_1.SERVICE_MONTH_FORMAT),
66
- one_time_accrual_service_month_end: (0, zeniDayJS_1.date)(endDate).format(jeSchedulesPayload_1.SERVICE_MONTH_FORMAT),
83
+ one_time_accrual_service_month_start: oneTimeAccrualServiceMonthStart,
84
+ one_time_accrual_service_month_end: parsedEndDate.format(jeSchedulesPayload_1.SERVICE_MONTH_FORMAT),
67
85
  // Existing lists what actually reached the books.
68
86
  one_time_accrual_statuses: ['posted'],
69
87
  // A failed posting from an earlier month still needs to surface here, so this list
@@ -76,17 +76,39 @@ const promoteOneTimeAccrualEpic = (actions$, state$, zeniAPI) => actions$.pipe((
76
76
  const debitClassId = edits?.jeDebitAccountingClassId ?? accrual?.jeDebitAccountingClassId;
77
77
  const debitClassName = edits?.jeDebitAccountingClassName ??
78
78
  accrual?.jeDebitAccountingClassName;
79
+ // The accrual document stores names alongside ids, so every id below travels with its name.
80
+ // Sending an id on its own leaves the stored row -- and the JE posted from it -- naming the
81
+ // account the user just moved away from. Create has always sent the full set; promote did
82
+ // not, which is the difference the two paths were showing.
83
+ const debitAccountName = edits?.jeDebitAccountName ?? accrual?.jeDebitAccountName;
84
+ const creditAccountName = edits?.jeCreditAccountName ?? accrual?.jeCreditAccountName;
85
+ // Credit-side class is never edited on this form -- the liability side is the Balance Sheet
86
+ // class the draft was born with -- so it is echoed straight back from the draft.
87
+ const creditClassId = accrual?.jeCreditAccountingClassId;
88
+ const creditClassName = accrual?.jeCreditAccountingClassName;
79
89
  const payload = {
80
90
  amount,
81
91
  memo: edits?.memo ?? accrual?.memo ?? '',
82
92
  je_debit_account_id: debitAccountId,
83
93
  je_credit_account_id: creditAccountId,
94
+ ...(debitAccountName != null
95
+ ? { je_debit_account_name: debitAccountName }
96
+ : {}),
97
+ ...(creditAccountName != null
98
+ ? { je_credit_account_name: creditAccountName }
99
+ : {}),
84
100
  ...(debitClassId != null
85
101
  ? { je_debit_accounting_class_id: debitClassId }
86
102
  : {}),
87
103
  ...(debitClassName != null
88
104
  ? { je_debit_accounting_class_name: debitClassName }
89
105
  : {}),
106
+ ...(creditClassId != null
107
+ ? { je_credit_accounting_class_id: creditClassId }
108
+ : {}),
109
+ ...(creditClassName != null
110
+ ? { je_credit_accounting_class_name: creditClassName }
111
+ : {}),
90
112
  // Mirrors the create payload: reverse_next_month alone decides the policy, and the date is
91
113
  // only meaningful when it is true -- agent-je derives the reversal from the bill otherwise.
92
114
  reverse_next_month: reverseNextMonth,
@@ -119,8 +119,10 @@ export interface PromoteOneTimeAccrualPayload {
119
119
  je_debit_account_id: ID;
120
120
  memo: string;
121
121
  expected_reversal_date?: string;
122
+ je_credit_account_name?: string;
122
123
  je_credit_accounting_class_id?: ID;
123
124
  je_credit_accounting_class_name?: string;
125
+ je_debit_account_name?: string;
124
126
  je_debit_accounting_class_id?: ID;
125
127
  je_debit_accounting_class_name?: string;
126
128
  reverse_next_month?: boolean;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@zeniai/client-epic-state",
3
- "version": "5.2.28",
3
+ "version": "5.2.30-betaRD0",
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",