@zeniai/client-epic-state 5.3.12 → 5.3.14-beta0MM
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.
- package/lib/commonStateTypes/animations.d.ts +1 -1
- package/lib/commonStateTypes/animations.js +1 -2
- package/lib/entity/actualMatching/actualMatchingPayload.d.ts +1 -0
- package/lib/entity/actualMatching/actualMatchingPayload.js +3 -0
- package/lib/entity/actualMatching/actualMatchingReducer.js +2 -1
- package/lib/entity/actualMatching/actualMatchingState.d.ts +1 -0
- package/lib/entity/actualMatching/actualMatchingTypes.d.ts +2 -0
- package/lib/entity/actualMatching/actualMatchingTypes.js +9 -0
- package/lib/epic.d.ts +2 -1
- package/lib/epic.js +2 -0
- package/lib/esm/commonStateTypes/animations.js +1 -2
- package/lib/esm/entity/actualMatching/actualMatchingPayload.js +3 -0
- package/lib/esm/entity/actualMatching/actualMatchingReducer.js +2 -1
- package/lib/esm/entity/actualMatching/actualMatchingTypes.js +8 -1
- package/lib/esm/epic.js +2 -0
- package/lib/esm/index.js +5 -4
- package/lib/esm/view/aiCfoView/aiCfoViewReducer.js +65 -3
- package/lib/esm/view/aiCfoView/aiCfoViewSelector.js +25 -0
- package/lib/esm/view/aiCfoView/epics/transcribeAudioEpic.js +60 -0
- package/lib/esm/view/expenseAutomationView/epics/jeSchedule/actualMatching/fetchActualMatchingEpic.js +2 -1
- package/lib/esm/view/expenseAutomationView/epics/jeSchedule/actualMatching/fetchActualMatchingMatchEpic.js +8 -2
- package/lib/esm/view/expenseAutomationView/epics/jeSchedule/actualMatching/matchAndReverseAccrualsEpic.js +7 -3
- package/lib/esm/view/expenseAutomationView/epics/jeSchedule/actualMatching/undoReversalAccrualsEpic.js +12 -7
- package/lib/esm/view/expenseAutomationView/reducers/actualMatchingViewReducer.js +30 -23
- package/lib/esm/view/expenseAutomationView/selectors/actualMatchingViewSelector.js +1 -0
- package/lib/esm/view/expenseAutomationView/types/transactionGroup.js +10 -5
- package/lib/esm/view/transactionDetail/createTransaction/createTransactionPayload.js +19 -3
- package/lib/esm/view/transactionDetail/createTransaction/createTransactionState.js +2 -0
- package/lib/index.d.ts +6 -5
- package/lib/index.js +30 -22
- package/lib/view/aiCfoView/aiCfoViewPayload.d.ts +20 -0
- package/lib/view/aiCfoView/aiCfoViewReducer.d.ts +2 -2
- package/lib/view/aiCfoView/aiCfoViewReducer.js +66 -4
- package/lib/view/aiCfoView/aiCfoViewSelector.d.ts +8 -1
- package/lib/view/aiCfoView/aiCfoViewSelector.js +27 -0
- package/lib/view/aiCfoView/aiCfoViewState.d.ts +9 -0
- package/lib/view/aiCfoView/epics/transcribeAudioEpic.d.ts +19 -0
- package/lib/view/aiCfoView/epics/transcribeAudioEpic.js +64 -0
- package/lib/view/expenseAutomationView/epics/jeSchedule/actualMatching/fetchActualMatchingEpic.js +2 -1
- package/lib/view/expenseAutomationView/epics/jeSchedule/actualMatching/fetchActualMatchingMatchEpic.js +8 -2
- package/lib/view/expenseAutomationView/epics/jeSchedule/actualMatching/matchAndReverseAccrualsEpic.js +7 -3
- package/lib/view/expenseAutomationView/epics/jeSchedule/actualMatching/undoReversalAccrualsEpic.js +12 -7
- package/lib/view/expenseAutomationView/payload/transactionCategorizationPayload.d.ts +2 -2
- package/lib/view/expenseAutomationView/reducers/actualMatchingViewReducer.d.ts +9 -3
- package/lib/view/expenseAutomationView/reducers/actualMatchingViewReducer.js +30 -23
- package/lib/view/expenseAutomationView/reducers/transactionsViewReducer.d.ts +2 -2
- package/lib/view/expenseAutomationView/selectorTypes/actualMatchingViewSelectorTypes.d.ts +1 -0
- package/lib/view/expenseAutomationView/selectors/actualMatchingViewSelector.js +1 -0
- package/lib/view/expenseAutomationView/types/transactionGroup.d.ts +6 -6
- package/lib/view/expenseAutomationView/types/transactionGroup.js +10 -5
- package/lib/view/expenseAutomationView/types/transactionsViewState.d.ts +2 -2
- package/lib/view/transactionDetail/createTransaction/createTransactionPayload.d.ts +6 -3
- package/lib/view/transactionDetail/createTransaction/createTransactionPayload.js +19 -3
- package/lib/view/transactionDetail/createTransaction/createTransactionState.d.ts +7 -2
- package/lib/view/transactionDetail/createTransaction/createTransactionState.js +2 -0
- package/lib/view/transactionDetail/transactionDetailReducer.d.ts +20 -20
- package/package.json +1 -1
|
@@ -0,0 +1,64 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.transcribeAudioEpic = void 0;
|
|
4
|
+
const rxjs_1 = require("rxjs");
|
|
5
|
+
const operators_1 = require("rxjs/operators");
|
|
6
|
+
const responsePayload_1 = require("../../../responsePayload");
|
|
7
|
+
const rootActions_1 = require("../../../rootActions");
|
|
8
|
+
const aiCfoViewReducer_1 = require("../aiCfoViewReducer");
|
|
9
|
+
const AUDIO_FIELD = 'audio';
|
|
10
|
+
const LANGUAGE_FIELD = 'language';
|
|
11
|
+
/** Extension only has to match the recorded format; the server reads the part's MIME type. */
|
|
12
|
+
const AUDIO_FILE_NAME = 'dictation.wav';
|
|
13
|
+
/**
|
|
14
|
+
* A hung request would otherwise pin `isTranscribing` true forever, and the composer
|
|
15
|
+
* gates both submit and the mic on it — leaving the user unable to send even typed
|
|
16
|
+
* text until something else resolved it.
|
|
17
|
+
*/
|
|
18
|
+
const TRANSCRIPTION_TIMEOUT_MS = 30000;
|
|
19
|
+
/**
|
|
20
|
+
* Voice dictation for the AI CFO composer. Dispatch `transcribeAudio(blob, language)` with a
|
|
21
|
+
* finished recording to POST it to the AI CFO micro-service `/1.0/transcriptions` endpoint;
|
|
22
|
+
* on success the transcript is appended to the composer input for the user to edit and send.
|
|
23
|
+
*
|
|
24
|
+
* `switchMap` (not `mergeMap`): a newer recording supersedes an older in-flight one, so a
|
|
25
|
+
* slow response can never append a stale transcript after a fresh one has already landed.
|
|
26
|
+
* The AbortController makes that cancellation real — `fetch` wrapped in a promise ignores
|
|
27
|
+
* an RxJS unsubscribe, so without the signal the superseded request would run to completion
|
|
28
|
+
* and still bill a transcription call whose result nothing wants.
|
|
29
|
+
*/
|
|
30
|
+
const transcribeAudioEpic = (actions$, _state$, zeniAPI) => actions$.pipe((0, operators_1.filter)(aiCfoViewReducer_1.transcribeAudio.match), (0, operators_1.switchMap)((action) => {
|
|
31
|
+
const { audio, chatSessionId, language } = action.payload;
|
|
32
|
+
const abortController = new AbortController();
|
|
33
|
+
const formData = new FormData();
|
|
34
|
+
formData.append(AUDIO_FIELD, audio, AUDIO_FILE_NAME);
|
|
35
|
+
if (language != null && language !== '') {
|
|
36
|
+
formData.append(LANGUAGE_FIELD, language);
|
|
37
|
+
}
|
|
38
|
+
return zeniAPI
|
|
39
|
+
.postFormData(`${zeniAPI.apiEndPoints.aiCfoMicroServiceBaseUrl}/1.0/transcriptions`, formData, abortController.signal)
|
|
40
|
+
.pipe((0, operators_1.timeout)(TRANSCRIPTION_TIMEOUT_MS),
|
|
41
|
+
// A tenant switch clears the store; a transcript still in flight must not
|
|
42
|
+
// land in the next tenant's composer (both sessions can be `undefined`, so
|
|
43
|
+
// the reducer's session guard would let it through).
|
|
44
|
+
(0, operators_1.takeUntil)(actions$.pipe((0, operators_1.filter)(rootActions_1.clearAll.match))), (0, operators_1.map)((response) => {
|
|
45
|
+
if (!(0, responsePayload_1.isSuccessResponse)(response)) {
|
|
46
|
+
return (0, aiCfoViewReducer_1.transcribeAudioFailure)(response.status);
|
|
47
|
+
}
|
|
48
|
+
// An EMPTY transcript is a success (the mic caught silence) and the
|
|
49
|
+
// reducer leaves the composer alone. A MISSING one breaks the response
|
|
50
|
+
// contract, so it surfaces as an error rather than being coerced to
|
|
51
|
+
// silence the user cannot distinguish from a quiet room.
|
|
52
|
+
if (response.data?.transcript == null) {
|
|
53
|
+
return (0, aiCfoViewReducer_1.transcribeAudioFailure)((0, responsePayload_1.createZeniAPIStatus)('Transcription succeeded but the response carried no transcript', 'Unexpected Error'));
|
|
54
|
+
}
|
|
55
|
+
// The session id rides along so a transcript that lands after the user
|
|
56
|
+
// switched sessions is dropped rather than misfiled.
|
|
57
|
+
return (0, aiCfoViewReducer_1.transcribeAudioSuccess)(response.data.transcript, chatSessionId);
|
|
58
|
+
}), (0, operators_1.finalize)(() => abortController.abort()), (0, operators_1.catchError)((error) => (0, rxjs_1.of)((0, aiCfoViewReducer_1.transcribeAudioFailure)((0, responsePayload_1.createZeniAPIStatus)(
|
|
59
|
+
// message (detailed) first, then the short title — per createZeniAPIStatus(message, title).
|
|
60
|
+
// JSON.stringify(Error) drops the (non-enumerable) message — extract it explicitly.
|
|
61
|
+
'Transcription REST API call errored out: ' +
|
|
62
|
+
(error instanceof Error ? error.message : String(error)), 'Unexpected Error')))));
|
|
63
|
+
}));
|
|
64
|
+
exports.transcribeAudioEpic = transcribeAudioEpic;
|
package/lib/view/expenseAutomationView/epics/jeSchedule/actualMatching/fetchActualMatchingEpic.js
CHANGED
|
@@ -4,6 +4,7 @@ exports.fetchActualMatchingEpic = void 0;
|
|
|
4
4
|
const rxjs_1 = require("rxjs");
|
|
5
5
|
const operators_1 = require("rxjs/operators");
|
|
6
6
|
const actualMatchingReducer_1 = require("../../../../../entity/actualMatching/actualMatchingReducer");
|
|
7
|
+
const actualMatchingTypes_1 = require("../../../../../entity/actualMatching/actualMatchingTypes");
|
|
7
8
|
const responsePayload_1 = require("../../../../../responsePayload");
|
|
8
9
|
const rootActions_1 = require("../../../../../rootActions");
|
|
9
10
|
const actualMatchingPayload_1 = require("../../../payload/actualMatchingPayload");
|
|
@@ -29,7 +30,7 @@ const fetchActualMatchingEpic = (actions$, state$, zeniAPI) => actions$.pipe((0,
|
|
|
29
30
|
updateActions.push((0, actualMatchingReducer_1.updateActualMatchingMatches)(matches, (0, actualMatchingViewSelector_1.getTenantDisplayCurrency)(state)));
|
|
30
31
|
}
|
|
31
32
|
updateActions.push((0, actualMatchingViewReducer_1.fetchActualMatchingSuccess)({
|
|
32
|
-
matchIds: matches.map((match) => match.match_id),
|
|
33
|
+
matchIds: matches.map((match) => (0, actualMatchingTypes_1.actualMatchingRowKey)(match.match_id, match.match_batch_id)),
|
|
33
34
|
selectedPeriod: requestPeriod,
|
|
34
35
|
refreshViewInBackground,
|
|
35
36
|
}));
|
|
@@ -9,15 +9,19 @@ const rootActions_1 = require("../../../../../rootActions");
|
|
|
9
9
|
const actualMatchingViewReducer_1 = require("../../../reducers/actualMatchingViewReducer");
|
|
10
10
|
const actualMatchingViewSelector_1 = require("../../../selectors/actualMatchingViewSelector");
|
|
11
11
|
const fetchActualMatchingMatchEpic = (actions$, state$, zeniAPI) => actions$.pipe((0, operators_1.filter)(actualMatchingViewReducer_1.fetchActualMatchingMatch.match), (0, operators_1.mergeMap)((action) => {
|
|
12
|
-
const { matchId, refreshViewInBackground } = action.payload;
|
|
12
|
+
const { matchId, matchBatchId, refreshViewInBackground } = action.payload;
|
|
13
|
+
const batchQuery = matchBatchId != null && matchBatchId !== ''
|
|
14
|
+
? `?batch_id=${encodeURIComponent(matchBatchId)}`
|
|
15
|
+
: '';
|
|
13
16
|
return zeniAPI
|
|
14
|
-
.getJSON(`${zeniAPI.apiEndPoints.accountMicroServiceBaseUrl}/1.0/accruals/actual-matching/${encodeURIComponent(matchId)}`)
|
|
17
|
+
.getJSON(`${zeniAPI.apiEndPoints.accountMicroServiceBaseUrl}/1.0/accruals/actual-matching/${encodeURIComponent(matchId)}${batchQuery}`)
|
|
15
18
|
.pipe((0, operators_1.mergeMap)((response) => {
|
|
16
19
|
if ((0, responsePayload_1.isSuccessResponse)(response) && response.data != null) {
|
|
17
20
|
return (0, rxjs_1.from)([
|
|
18
21
|
(0, actualMatchingReducer_1.updateActualMatchingMatches)([response.data], (0, actualMatchingViewSelector_1.getTenantDisplayCurrency)(state$.value)),
|
|
19
22
|
(0, actualMatchingViewReducer_1.fetchActualMatchingMatchSuccess)({
|
|
20
23
|
matchId,
|
|
24
|
+
matchBatchId,
|
|
21
25
|
refreshViewInBackground,
|
|
22
26
|
}),
|
|
23
27
|
]);
|
|
@@ -25,6 +29,7 @@ const fetchActualMatchingMatchEpic = (actions$, state$, zeniAPI) => actions$.pip
|
|
|
25
29
|
return (0, rxjs_1.from)([
|
|
26
30
|
(0, actualMatchingViewReducer_1.fetchActualMatchingMatchFailure)({
|
|
27
31
|
matchId,
|
|
32
|
+
matchBatchId,
|
|
28
33
|
refreshViewInBackground,
|
|
29
34
|
status: response.status,
|
|
30
35
|
}),
|
|
@@ -32,6 +37,7 @@ const fetchActualMatchingMatchEpic = (actions$, state$, zeniAPI) => actions$.pip
|
|
|
32
37
|
}), (0, operators_1.catchError)((error) => (0, rxjs_1.from)([
|
|
33
38
|
(0, actualMatchingViewReducer_1.fetchActualMatchingMatchFailure)({
|
|
34
39
|
matchId,
|
|
40
|
+
matchBatchId,
|
|
35
41
|
refreshViewInBackground,
|
|
36
42
|
status: (0, responsePayload_1.createZeniAPIStatus)('Unexpected Error', `Fetch actual matching match REST API call errored out ${JSON.stringify(error)}`),
|
|
37
43
|
}),
|
|
@@ -59,8 +59,12 @@ function matchAndReverseHttpFailSnackbar(vendorName) {
|
|
|
59
59
|
});
|
|
60
60
|
}
|
|
61
61
|
function matchVendorName(state, matchId) {
|
|
62
|
-
|
|
63
|
-
|
|
62
|
+
const stored = (0, actualMatchingSelector_1.getActualMatchingMatchById)(state.actualMatchingState, matchId);
|
|
63
|
+
if (stored?.vendorName != null && stored.vendorName !== '') {
|
|
64
|
+
return stored.vendorName;
|
|
65
|
+
}
|
|
66
|
+
const sameBill = Object.values(state.actualMatchingState.byMatchId).find((match) => match.matchId === matchId);
|
|
67
|
+
return sameBill?.vendorName ?? '';
|
|
64
68
|
}
|
|
65
69
|
const matchAndReverseAccrualsEpic = (actions$, state$, zeniAPI) => actions$.pipe((0, operators_1.filter)(actualMatchingViewReducer_1.matchAndReverseAccruals.match),
|
|
66
70
|
// Per-match exhaust: a second click on the same match drops while HTTP is in
|
|
@@ -99,7 +103,7 @@ const matchAndReverseAccrualsEpic = (actions$, state$, zeniAPI) => actions$.pipe
|
|
|
99
103
|
// List + detail: list can omit leftovers; detail GET always
|
|
100
104
|
// writes intended occupancy so leftover retry can join C
|
|
101
105
|
// onto the occupied bill instead of a stale cached row.
|
|
102
|
-
successActions.push(...(0, refreshActualMatchingList_1.refreshActualMatchingList)(state$.value), (0, actualMatchingViewReducer_1.fetchActualMatchingMatch)(matchId, true));
|
|
106
|
+
successActions.push(...(0, refreshActualMatchingList_1.refreshActualMatchingList)(state$.value), (0, actualMatchingViewReducer_1.fetchActualMatchingMatch)(matchId, true, response.data.match_batch_id));
|
|
103
107
|
}
|
|
104
108
|
const snackbar = matchAndReverseSnackbar(results, vendorName);
|
|
105
109
|
if (snackbar != null) {
|
package/lib/view/expenseAutomationView/epics/jeSchedule/actualMatching/undoReversalAccrualsEpic.js
CHANGED
|
@@ -4,6 +4,7 @@ exports.undoReversalAccrualsEpic = void 0;
|
|
|
4
4
|
const rxjs_1 = require("rxjs");
|
|
5
5
|
const operators_1 = require("rxjs/operators");
|
|
6
6
|
const actualMatchingSelector_1 = require("../../../../../entity/actualMatching/actualMatchingSelector");
|
|
7
|
+
const actualMatchingTypes_1 = require("../../../../../entity/actualMatching/actualMatchingTypes");
|
|
7
8
|
const snackbarReducer_1 = require("../../../../../entity/snackbar/snackbarReducer");
|
|
8
9
|
const responsePayload_1 = require("../../../../../responsePayload");
|
|
9
10
|
const rootActions_1 = require("../../../../../rootActions");
|
|
@@ -40,41 +41,45 @@ function undoReversalSnackbar(results, vendorName) {
|
|
|
40
41
|
variables,
|
|
41
42
|
});
|
|
42
43
|
}
|
|
43
|
-
function matchVendorName(state, matchId) {
|
|
44
|
-
|
|
44
|
+
function matchVendorName(state, matchId, matchBatchId) {
|
|
45
|
+
const rowKey = (0, actualMatchingTypes_1.actualMatchingRowKey)(matchId, matchBatchId);
|
|
46
|
+
return ((0, actualMatchingSelector_1.getActualMatchingMatchById)(state.actualMatchingState, rowKey)?.vendorName ??
|
|
47
|
+
(0, actualMatchingSelector_1.getActualMatchingMatchById)(state.actualMatchingState, matchId)?.vendorName ??
|
|
45
48
|
'');
|
|
46
49
|
}
|
|
47
50
|
const undoReversalAccrualsEpic = (actions$, state$, zeniAPI) => actions$.pipe((0, operators_1.filter)(actualMatchingViewReducer_1.undoReversalAccruals.match),
|
|
48
51
|
// Per-match exhaust: a second click on the same match drops while HTTP is in
|
|
49
52
|
// flight. A different match must still run — a global exhaustMap left the
|
|
50
53
|
// other match's reducer In-Progress with no request.
|
|
51
|
-
(0, operators_1.groupBy)((action) => action.payload.matchId), (0, operators_1.mergeMap)((perMatch$) => perMatch$.pipe((0, operators_1.exhaustMap)((action) => {
|
|
52
|
-
const { accrualIds, matchId } = action.payload;
|
|
54
|
+
(0, operators_1.groupBy)((action) => (0, actualMatchingTypes_1.actualMatchingRowKey)(action.payload.matchId, action.payload.matchBatchId)), (0, operators_1.mergeMap)((perMatch$) => perMatch$.pipe((0, operators_1.exhaustMap)((action) => {
|
|
55
|
+
const { accrualIds, matchId, matchBatchId } = action.payload;
|
|
53
56
|
const body = {
|
|
54
57
|
accrual_ids: accrualIds,
|
|
55
58
|
};
|
|
56
|
-
const vendorName = matchVendorName(state$.value, matchId);
|
|
59
|
+
const vendorName = matchVendorName(state$.value, matchId, matchBatchId);
|
|
57
60
|
return zeniAPI
|
|
58
61
|
.postAndGetJSON(`${zeniAPI.apiEndPoints.accountMicroServiceBaseUrl}/1.0/accruals/undo-reversal`, body)
|
|
59
62
|
.pipe((0, operators_1.mergeMap)((response) => {
|
|
60
63
|
if ((0, responsePayload_1.isSuccessResponse)(response) && response.data != null) {
|
|
61
64
|
const results = response.data.results.map(actualMatchingPayload_1.toUndoReversalResult);
|
|
62
65
|
const successActions = [
|
|
63
|
-
(0, actualMatchingViewReducer_1.undoReversalAccrualsSuccess)(matchId, results),
|
|
66
|
+
(0, actualMatchingViewReducer_1.undoReversalAccrualsSuccess)(matchId, results, matchBatchId),
|
|
64
67
|
];
|
|
65
68
|
const anyUndone = results.some((result) => result.status === 'undone');
|
|
66
69
|
if (anyUndone) {
|
|
67
|
-
successActions.push(...(0, refreshActualMatchingList_1.refreshActualMatchingList)(state$.value), (0, actualMatchingViewReducer_1.fetchActualMatchingMatch)(matchId, true));
|
|
70
|
+
successActions.push(...(0, refreshActualMatchingList_1.refreshActualMatchingList)(state$.value), (0, actualMatchingViewReducer_1.fetchActualMatchingMatch)(matchId, true, matchBatchId));
|
|
68
71
|
}
|
|
69
72
|
successActions.push(undoReversalSnackbar(results, vendorName));
|
|
70
73
|
return (0, rxjs_1.from)(successActions);
|
|
71
74
|
}
|
|
72
75
|
return (0, rxjs_1.of)((0, actualMatchingViewReducer_1.undoReversalAccrualsFailure)({
|
|
73
76
|
matchId,
|
|
77
|
+
matchBatchId,
|
|
74
78
|
status: response.status,
|
|
75
79
|
}), undoReversalSnackbar([], vendorName));
|
|
76
80
|
}), (0, operators_1.catchError)((error) => (0, rxjs_1.of)((0, actualMatchingViewReducer_1.undoReversalAccrualsFailure)({
|
|
77
81
|
matchId,
|
|
82
|
+
matchBatchId,
|
|
78
83
|
status: (0, responsePayload_1.createZeniAPIStatus)('Unexpected Error', 'Undo reversal accruals REST API call errored out' +
|
|
79
84
|
JSON.stringify(error)),
|
|
80
85
|
}), undoReversalSnackbar([], vendorName))), (0, operators_1.takeUntil)(actions$.pipe((0, operators_1.filter)(rootActions_1.clearAll.match))));
|
|
@@ -28,8 +28,8 @@ export interface TransactionCategorizationQueryPayload {
|
|
|
28
28
|
*/
|
|
29
29
|
search_all_statuses?: boolean;
|
|
30
30
|
/**
|
|
31
|
-
* Statement-level scope (`'expense' | 'income' | 'all'`). Always
|
|
32
|
-
* list epics. The backend `is_revenue_automation_enabled` gate is
|
|
31
|
+
* Statement-level scope (`'expense' | 'income' | 'other' | 'all'`). Always
|
|
32
|
+
* sent by the list epics. The backend `is_revenue_automation_enabled` gate is
|
|
33
33
|
* authoritative: when it is off the backend ignores this and returns the
|
|
34
34
|
* legacy expense scope regardless of the value, so there is no need to gate
|
|
35
35
|
* the send on the client (the gate isn't available to the redux epics anyway
|
|
@@ -14,16 +14,19 @@ export declare const ackCloseMatchAfterIgnore: import("@reduxjs/toolkit").Action
|
|
|
14
14
|
refreshViewInBackground: boolean;
|
|
15
15
|
selectedPeriod: MonthYearPeriod;
|
|
16
16
|
status: ZeniAPIStatus;
|
|
17
|
-
}, "expenseAutomationActualMatchingView/fetchActualMatchingFailure">, fetchActualMatchingMatch: import("@reduxjs/toolkit").ActionCreatorWithPreparedPayload<[matchId: string, refreshViewInBackground?: any], {
|
|
17
|
+
}, "expenseAutomationActualMatchingView/fetchActualMatchingFailure">, fetchActualMatchingMatch: import("@reduxjs/toolkit").ActionCreatorWithPreparedPayload<[matchId: string, refreshViewInBackground?: any, matchBatchId?: string | undefined], {
|
|
18
18
|
matchId: string;
|
|
19
|
+
matchBatchId: string | undefined;
|
|
19
20
|
refreshViewInBackground: any;
|
|
20
21
|
}, "expenseAutomationActualMatchingView/fetchActualMatchingMatch", never, never>, fetchActualMatchingMatchFailure: import("@reduxjs/toolkit").ActionCreatorWithPayload<{
|
|
21
22
|
matchId: ActualMatchingMatchId;
|
|
22
23
|
refreshViewInBackground: boolean;
|
|
23
24
|
status: ZeniAPIStatus;
|
|
25
|
+
matchBatchId?: string;
|
|
24
26
|
}, "expenseAutomationActualMatchingView/fetchActualMatchingMatchFailure">, fetchActualMatchingMatchSuccess: import("@reduxjs/toolkit").ActionCreatorWithPayload<{
|
|
25
27
|
matchId: ActualMatchingMatchId;
|
|
26
28
|
refreshViewInBackground: boolean;
|
|
29
|
+
matchBatchId?: string;
|
|
27
30
|
}, "expenseAutomationActualMatchingView/fetchActualMatchingMatchSuccess">, fetchActualMatchingPage: import("@reduxjs/toolkit").ActionCreatorWithPreparedPayload<[period: TimePeriod, refreshViewInBackground?: any], {
|
|
28
31
|
period: TimePeriod;
|
|
29
32
|
refreshViewInBackground: any;
|
|
@@ -76,15 +79,18 @@ export declare const ackCloseMatchAfterIgnore: import("@reduxjs/toolkit").Action
|
|
|
76
79
|
append: boolean;
|
|
77
80
|
nextPageToken: string | null;
|
|
78
81
|
results: ActualMatchingTransactionSearchResult[];
|
|
79
|
-
}, "expenseAutomationActualMatchingView/searchMatchTransactionsSuccess">, undoReversalAccruals: import("@reduxjs/toolkit").ActionCreatorWithPreparedPayload<[matchId: string, accrualIds: string[]], {
|
|
82
|
+
}, "expenseAutomationActualMatchingView/searchMatchTransactionsSuccess">, undoReversalAccruals: import("@reduxjs/toolkit").ActionCreatorWithPreparedPayload<[matchId: string, accrualIds: string[], matchBatchId?: string | undefined], {
|
|
80
83
|
matchId: string;
|
|
81
84
|
accrualIds: string[];
|
|
85
|
+
matchBatchId: string | undefined;
|
|
82
86
|
}, "expenseAutomationActualMatchingView/undoReversalAccruals", never, never>, undoReversalAccrualsFailure: import("@reduxjs/toolkit").ActionCreatorWithPayload<{
|
|
83
87
|
matchId: ActualMatchingMatchId;
|
|
84
88
|
status: ZeniAPIStatus;
|
|
85
|
-
|
|
89
|
+
matchBatchId?: string;
|
|
90
|
+
}, "expenseAutomationActualMatchingView/undoReversalAccrualsFailure">, undoReversalAccrualsSuccess: import("@reduxjs/toolkit").ActionCreatorWithPreparedPayload<[matchId: string, results: UndoReversalResult[], matchBatchId?: string | undefined], {
|
|
86
91
|
matchId: string;
|
|
87
92
|
results: UndoReversalResult[];
|
|
93
|
+
matchBatchId: string | undefined;
|
|
88
94
|
}, "expenseAutomationActualMatchingView/undoReversalAccrualsSuccess", never, never>, updateActualMatchingUIState: import("@reduxjs/toolkit").ActionCreatorWithPayload<Partial<ActualMatchingViewUIState>, "expenseAutomationActualMatchingView/updateActualMatchingUIState">;
|
|
89
95
|
declare const _default: import("redux").Reducer<ActualMatchingViewState>;
|
|
90
96
|
export default _default;
|
|
@@ -4,6 +4,7 @@ Object.defineProperty(exports, "__esModule", { value: true });
|
|
|
4
4
|
exports.updateActualMatchingUIState = exports.undoReversalAccrualsSuccess = exports.undoReversalAccrualsFailure = exports.undoReversalAccruals = exports.searchMatchTransactionsSuccess = exports.searchMatchTransactionsFailure = exports.searchMatchTransactions = exports.searchMatchAccrualsSuccess = exports.searchMatchAccrualsFailure = exports.searchMatchAccruals = exports.openMatchNewModal = exports.matchAndReverseAccrualsSuccess = exports.matchAndReverseAccrualsFailure = exports.matchAndReverseAccruals = exports.ignoreActualMatchingSuggestionSuccess = exports.ignoreActualMatchingSuggestionFailure = exports.ignoreActualMatchingSuggestion = exports.fetchActualMatchingSuccess = exports.fetchActualMatchingPage = exports.fetchActualMatchingMatchSuccess = exports.fetchActualMatchingMatchFailure = exports.fetchActualMatchingMatch = exports.fetchActualMatchingFailure = exports.fetchActualMatching = exports.closeMatchNewModal = exports.clearMatchNewModal = exports.clearActualMatchingView = exports.ackCloseMatchAfterUndo = exports.ackCloseMatchAfterIgnore = exports.initialState = exports.initialMatchModalState = exports.initialAccrualSearchState = exports.initialTransactionSearchState = void 0;
|
|
5
5
|
const toolkit_1 = require("@reduxjs/toolkit");
|
|
6
6
|
const timePeriod_1 = require("../../../commonStateTypes/timePeriod");
|
|
7
|
+
const actualMatchingTypes_1 = require("../../../entity/actualMatching/actualMatchingTypes");
|
|
7
8
|
const jeScheduleHelper_1 = require("../../../entity/jeSchedules/jeScheduleHelper");
|
|
8
9
|
const responsePayload_1 = require("../../../responsePayload");
|
|
9
10
|
const rootActions_1 = require("../../../rootActions");
|
|
@@ -187,19 +188,20 @@ const expenseAutomationActualMatchingView = (0, toolkit_1.createSlice)({
|
|
|
187
188
|
}
|
|
188
189
|
},
|
|
189
190
|
fetchActualMatchingMatch: {
|
|
190
|
-
prepare(matchId, refreshViewInBackground = false) {
|
|
191
|
-
return { payload: { matchId, refreshViewInBackground } };
|
|
191
|
+
prepare(matchId, refreshViewInBackground = false, matchBatchId) {
|
|
192
|
+
return { payload: { matchId, matchBatchId, refreshViewInBackground } };
|
|
192
193
|
},
|
|
193
194
|
reducer(draft, action) {
|
|
194
|
-
const { matchId, refreshViewInBackground } = action.payload;
|
|
195
|
+
const { matchId, matchBatchId, refreshViewInBackground } = action.payload;
|
|
196
|
+
const rowKey = (0, actualMatchingTypes_1.actualMatchingRowKey)(matchId, matchBatchId);
|
|
195
197
|
if (refreshViewInBackground) {
|
|
196
|
-
draft.detailRefreshStatusByMatchId[
|
|
198
|
+
draft.detailRefreshStatusByMatchId[rowKey] = {
|
|
197
199
|
fetchState: 'In-Progress',
|
|
198
200
|
error: undefined,
|
|
199
201
|
};
|
|
200
202
|
}
|
|
201
203
|
else {
|
|
202
|
-
draft.detailFetchStateByMatchId[
|
|
204
|
+
draft.detailFetchStateByMatchId[rowKey] = {
|
|
203
205
|
fetchState: 'In-Progress',
|
|
204
206
|
error: undefined,
|
|
205
207
|
};
|
|
@@ -207,30 +209,32 @@ const expenseAutomationActualMatchingView = (0, toolkit_1.createSlice)({
|
|
|
207
209
|
},
|
|
208
210
|
},
|
|
209
211
|
fetchActualMatchingMatchSuccess(draft, action) {
|
|
210
|
-
const { matchId, refreshViewInBackground } = action.payload;
|
|
212
|
+
const { matchId, matchBatchId, refreshViewInBackground } = action.payload;
|
|
213
|
+
const rowKey = (0, actualMatchingTypes_1.actualMatchingRowKey)(matchId, matchBatchId);
|
|
211
214
|
if (refreshViewInBackground) {
|
|
212
|
-
draft.detailRefreshStatusByMatchId[
|
|
215
|
+
draft.detailRefreshStatusByMatchId[rowKey] = {
|
|
213
216
|
fetchState: 'Completed',
|
|
214
217
|
error: undefined,
|
|
215
218
|
};
|
|
216
219
|
}
|
|
217
220
|
else {
|
|
218
|
-
draft.detailFetchStateByMatchId[
|
|
221
|
+
draft.detailFetchStateByMatchId[rowKey] = {
|
|
219
222
|
fetchState: 'Completed',
|
|
220
223
|
error: undefined,
|
|
221
224
|
};
|
|
222
225
|
}
|
|
223
226
|
},
|
|
224
227
|
fetchActualMatchingMatchFailure(draft, action) {
|
|
225
|
-
const { matchId, refreshViewInBackground, status } = action.payload;
|
|
228
|
+
const { matchId, matchBatchId, refreshViewInBackground, status } = action.payload;
|
|
229
|
+
const rowKey = (0, actualMatchingTypes_1.actualMatchingRowKey)(matchId, matchBatchId);
|
|
226
230
|
if (refreshViewInBackground) {
|
|
227
|
-
draft.detailRefreshStatusByMatchId[
|
|
231
|
+
draft.detailRefreshStatusByMatchId[rowKey] = {
|
|
228
232
|
fetchState: 'Error',
|
|
229
233
|
error: status,
|
|
230
234
|
};
|
|
231
235
|
}
|
|
232
236
|
else {
|
|
233
|
-
draft.detailFetchStateByMatchId[
|
|
237
|
+
draft.detailFetchStateByMatchId[rowKey] = {
|
|
234
238
|
fetchState: 'Error',
|
|
235
239
|
error: status,
|
|
236
240
|
};
|
|
@@ -421,40 +425,42 @@ const expenseAutomationActualMatchingView = (0, toolkit_1.createSlice)({
|
|
|
421
425
|
},
|
|
422
426
|
undoReversalAccruals: {
|
|
423
427
|
reducer(draft, action) {
|
|
424
|
-
|
|
428
|
+
const rowKey = (0, actualMatchingTypes_1.actualMatchingRowKey)(action.payload.matchId, action.payload.matchBatchId);
|
|
429
|
+
draft.undoReversalStatusByMatchId[rowKey] = {
|
|
425
430
|
fetchState: 'In-Progress',
|
|
426
431
|
error: undefined,
|
|
427
432
|
};
|
|
428
433
|
},
|
|
429
|
-
prepare(matchId, accrualIds) {
|
|
430
|
-
return { payload: { matchId, accrualIds } };
|
|
434
|
+
prepare(matchId, accrualIds, matchBatchId) {
|
|
435
|
+
return { payload: { matchId, accrualIds, matchBatchId } };
|
|
431
436
|
},
|
|
432
437
|
},
|
|
433
438
|
undoReversalAccrualsSuccess: {
|
|
434
439
|
reducer(draft, action) {
|
|
435
|
-
const { matchId, results } = action.payload;
|
|
436
|
-
|
|
440
|
+
const { matchId, matchBatchId, results } = action.payload;
|
|
441
|
+
const rowKey = (0, actualMatchingTypes_1.actualMatchingRowKey)(matchId, matchBatchId);
|
|
442
|
+
draft.undoReversalStatusByMatchId[rowKey] = {
|
|
437
443
|
fetchState: 'Completed',
|
|
438
444
|
error: undefined,
|
|
439
445
|
};
|
|
440
446
|
const allUndone = results.length > 0 &&
|
|
441
447
|
results.every((result) => result.status === 'undone');
|
|
442
448
|
if (allUndone) {
|
|
443
|
-
enqueueCloseMatchId(draft.closeMatchAfterUndoMatchIds,
|
|
449
|
+
enqueueCloseMatchId(draft.closeMatchAfterUndoMatchIds, rowKey);
|
|
444
450
|
}
|
|
445
451
|
else {
|
|
446
|
-
draft.closeMatchAfterUndoMatchIds = dropCloseMatchId(draft.closeMatchAfterUndoMatchIds,
|
|
452
|
+
draft.closeMatchAfterUndoMatchIds = dropCloseMatchId(draft.closeMatchAfterUndoMatchIds, rowKey);
|
|
447
453
|
}
|
|
448
454
|
pruneLastMatchResultsForUndone(draft, matchId, results);
|
|
449
455
|
if (allUndone) {
|
|
450
|
-
delete draft.lastUndoResultsByMatchId[
|
|
456
|
+
delete draft.lastUndoResultsByMatchId[rowKey];
|
|
451
457
|
}
|
|
452
458
|
else {
|
|
453
|
-
draft.lastUndoResultsByMatchId[
|
|
459
|
+
draft.lastUndoResultsByMatchId[rowKey] = results;
|
|
454
460
|
}
|
|
455
461
|
},
|
|
456
|
-
prepare(matchId, results) {
|
|
457
|
-
return { payload: { matchId, results } };
|
|
462
|
+
prepare(matchId, results, matchBatchId) {
|
|
463
|
+
return { payload: { matchId, results, matchBatchId } };
|
|
458
464
|
},
|
|
459
465
|
},
|
|
460
466
|
ackCloseMatchAfterUndo(draft) {
|
|
@@ -498,7 +504,8 @@ const expenseAutomationActualMatchingView = (0, toolkit_1.createSlice)({
|
|
|
498
504
|
draft.closeMatchAfterIgnoreMatchIds.shift();
|
|
499
505
|
},
|
|
500
506
|
undoReversalAccrualsFailure(draft, action) {
|
|
501
|
-
|
|
507
|
+
const rowKey = (0, actualMatchingTypes_1.actualMatchingRowKey)(action.payload.matchId, action.payload.matchBatchId);
|
|
508
|
+
draft.undoReversalStatusByMatchId[rowKey] = {
|
|
502
509
|
fetchState: 'Error',
|
|
503
510
|
error: action.payload.status,
|
|
504
511
|
};
|
|
@@ -70,8 +70,8 @@ export declare const fetchTransactionCategorization: import("@reduxjs/toolkit").
|
|
|
70
70
|
newSelectedTab: "review" | "autoCategorized";
|
|
71
71
|
}, "expenseAutomationTransactionsView/updateCurrentSelectedTransactionCategorizationTab", never, never>, updateTransactionCategorizationCompletedSubTab: import("@reduxjs/toolkit").ActionCreatorWithPreparedPayload<[newSubTab: "manual" | "all" | "ai_accountant"], {
|
|
72
72
|
newSubTab: "manual" | "all" | "ai_accountant";
|
|
73
|
-
}, "expenseAutomationTransactionsView/updateTransactionCategorizationCompletedSubTab", never, never>, updateTransactionGroup: import("@reduxjs/toolkit").ActionCreatorWithPreparedPayload<[newGroup: "income" | "expense" | "all"], {
|
|
74
|
-
newGroup: "income" | "expense" | "all";
|
|
73
|
+
}, "expenseAutomationTransactionsView/updateTransactionCategorizationCompletedSubTab", never, never>, updateTransactionGroup: import("@reduxjs/toolkit").ActionCreatorWithPreparedPayload<[newGroup: "income" | "expense" | "other" | "all"], {
|
|
74
|
+
newGroup: "income" | "expense" | "other" | "all";
|
|
75
75
|
}, "expenseAutomationTransactionsView/updateTransactionGroup", never, never>, updateTransactionCategorizationSaveStatus: import("@reduxjs/toolkit").ActionCreatorWithPreparedPayload<[selectedTab: "review" | "autoCategorized", fetchState: FetchState, error?: ZeniAPIStatus<Record<string, unknown>> | undefined], {
|
|
76
76
|
selectedTab: "review" | "autoCategorized";
|
|
77
77
|
fetchState: FetchState;
|
|
@@ -23,6 +23,7 @@ export interface ActualMatchingRow extends JEOneTimeAccrual {
|
|
|
23
23
|
groupedMembers?: ActualMatchingGroupedAccrual[];
|
|
24
24
|
intendedAccrualIds?: ID[];
|
|
25
25
|
leftovers?: ActualMatchingLeftoverAccrual[];
|
|
26
|
+
matchBatchId?: string;
|
|
26
27
|
matchShape?: string;
|
|
27
28
|
matchTier?: string;
|
|
28
29
|
reversalDate?: ZeniDate;
|
|
@@ -3,16 +3,16 @@
|
|
|
3
3
|
* verbatim to the listing API as `transaction_group`. When revenue automation is
|
|
4
4
|
* enabled for the tenant the backend scopes the whole view by the line
|
|
5
5
|
* account_type: `'expense'` -> expense accounts, `'income'` -> income accounts,
|
|
6
|
-
* `'
|
|
7
|
-
*
|
|
6
|
+
* `'other'` -> balance-sheet accounts other than bank/credit card (plus lines
|
|
7
|
+
* with no account type), `'all'` -> all three. The list epics always send it;
|
|
8
|
+
* when the gate is off the backend ignores it and returns the legacy expense
|
|
9
|
+
* scope.
|
|
8
10
|
*
|
|
9
11
|
* The wire value for expenses is the singular `'expense'` (matches the backend
|
|
10
12
|
* `TransactionGroup` enum) even though the picker labels it "Expenses".
|
|
11
|
-
* Balance-sheet groups (assets, liability) are reserved for later and are not
|
|
12
|
-
* part of this union yet.
|
|
13
13
|
*/
|
|
14
|
-
export declare const TRANSACTION_GROUPS: readonly ["all", "income", "expense"];
|
|
15
|
-
export declare const toTransactionGroup: (v: string | null | undefined) => "income" | "expense" | "all";
|
|
14
|
+
export declare const TRANSACTION_GROUPS: readonly ["all", "income", "expense", "other"];
|
|
15
|
+
export declare const toTransactionGroup: (v: string | null | undefined) => "income" | "expense" | "other" | "all";
|
|
16
16
|
export type TransactionGroup = ReturnType<typeof toTransactionGroup>;
|
|
17
17
|
/**
|
|
18
18
|
* Default group for the listing — matches the picker's default selection ("All").
|
|
@@ -7,15 +7,20 @@ const stringToUnion_1 = require("../../../commonStateTypes/stringToUnion");
|
|
|
7
7
|
* verbatim to the listing API as `transaction_group`. When revenue automation is
|
|
8
8
|
* enabled for the tenant the backend scopes the whole view by the line
|
|
9
9
|
* account_type: `'expense'` -> expense accounts, `'income'` -> income accounts,
|
|
10
|
-
* `'
|
|
11
|
-
*
|
|
10
|
+
* `'other'` -> balance-sheet accounts other than bank/credit card (plus lines
|
|
11
|
+
* with no account type), `'all'` -> all three. The list epics always send it;
|
|
12
|
+
* when the gate is off the backend ignores it and returns the legacy expense
|
|
13
|
+
* scope.
|
|
12
14
|
*
|
|
13
15
|
* The wire value for expenses is the singular `'expense'` (matches the backend
|
|
14
16
|
* `TransactionGroup` enum) even though the picker labels it "Expenses".
|
|
15
|
-
* Balance-sheet groups (assets, liability) are reserved for later and are not
|
|
16
|
-
* part of this union yet.
|
|
17
17
|
*/
|
|
18
|
-
exports.TRANSACTION_GROUPS = [
|
|
18
|
+
exports.TRANSACTION_GROUPS = [
|
|
19
|
+
'all',
|
|
20
|
+
'income',
|
|
21
|
+
'expense',
|
|
22
|
+
'other',
|
|
23
|
+
];
|
|
19
24
|
const toTransactionGroup = (v) => (0, stringToUnion_1.stringToUnion)(v != null ? v.trim().toLowerCase() : '', exports.TRANSACTION_GROUPS);
|
|
20
25
|
exports.toTransactionGroup = toTransactionGroup;
|
|
21
26
|
/**
|
|
@@ -152,8 +152,8 @@ export type TransactionsViewState = {
|
|
|
152
152
|
selectedTransactionCategorizationCompletedSubTab: CompletedSubTab;
|
|
153
153
|
selectedTransactionCategorizationTab: TransactionsTab;
|
|
154
154
|
/**
|
|
155
|
-
* Statement-level scope (`'expense' | 'income' | 'all'`) forwarded
|
|
156
|
-
* listing API as `transaction_group`. Unlike the in-memory {@link
|
|
155
|
+
* Statement-level scope (`'expense' | 'income' | 'other' | 'all'`) forwarded
|
|
156
|
+
* to the listing API as `transaction_group`. Unlike the in-memory {@link
|
|
157
157
|
* TransactionsTabViewState.filters}, a change here invalidates every tab /
|
|
158
158
|
* sub-tab / count and drives a server refetch (the backend re-scopes the
|
|
159
159
|
* whole dataset by account_type). Only surfaced in the UI when the
|
|
@@ -13,8 +13,9 @@ import { CreateTransactionLocalData } from './createTransactionState';
|
|
|
13
13
|
* constant NAMES; ZENI_LINE_DETAIL_TYPE_TO_QBO_LINE_DETAIL_TYPE_MAP converts them for the
|
|
14
14
|
* body the backend sends on to QuickBooks, never for ours.
|
|
15
15
|
* 2. The QBO Purchases (check, credit_card_credit) send their reference number as
|
|
16
|
-
* `document_number`; a journal entry sends its entry name
|
|
17
|
-
*
|
|
16
|
+
* `document_number`; a journal entry sends its entry name, a bill its bill number and a
|
|
17
|
+
* vendor credit its reference number as `document_id`. All land on QBO's DocNumber, but
|
|
18
|
+
* QBOJournalEntry reads only `document_id`.
|
|
18
19
|
*/
|
|
19
20
|
export interface CreateTransactionAccountPayload {
|
|
20
21
|
qbo_id: ID;
|
|
@@ -53,10 +54,12 @@ export interface CreateTransactionRemitToAddressPayload {
|
|
|
53
54
|
export interface CreateTransactionRequest extends Record<string, unknown> {
|
|
54
55
|
transaction_date: string;
|
|
55
56
|
transaction_type: string;
|
|
56
|
-
/** journal_entry entry name (QBO DocNumber). */
|
|
57
|
+
/** journal_entry entry name, bill number or vendor_credit reference number (QBO DocNumber). */
|
|
57
58
|
document_id?: string;
|
|
58
59
|
/** check / credit_card_credit reference number (QBO Purchase). */
|
|
59
60
|
document_number?: string;
|
|
61
|
+
/** bill only. */
|
|
62
|
+
due_date?: string;
|
|
60
63
|
from_account_id?: ID;
|
|
61
64
|
/** credit_card_credit is modelled as a Purchase with Credit: true. */
|
|
62
65
|
is_credit?: boolean;
|
|
@@ -135,13 +135,29 @@ const prepareCreateTransactionPayload = (state, localData) => {
|
|
|
135
135
|
};
|
|
136
136
|
}
|
|
137
137
|
const lines = localData.lines.map((line) => toLinePayload(state, line, transactionType));
|
|
138
|
+
const documentIdField = localData.documentNumber != null && localData.documentNumber !== ''
|
|
139
|
+
? { document_id: localData.documentNumber }
|
|
140
|
+
: {};
|
|
138
141
|
if (transactionType === 'journal_entry') {
|
|
142
|
+
return { ...base, ...documentIdField, lines };
|
|
143
|
+
}
|
|
144
|
+
// Both post to accounts payable, so they carry no header account or payment type.
|
|
145
|
+
if (transactionType === 'vendor_credit') {
|
|
146
|
+
return {
|
|
147
|
+
...base,
|
|
148
|
+
vendor_id: toQboVendorId(state, localData.vendorId),
|
|
149
|
+
...documentIdField,
|
|
150
|
+
lines,
|
|
151
|
+
};
|
|
152
|
+
}
|
|
153
|
+
if (transactionType === 'bill') {
|
|
139
154
|
return {
|
|
140
155
|
...base,
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
|
|
156
|
+
vendor_id: toQboVendorId(state, localData.vendorId),
|
|
157
|
+
...(localData.dueDate != null && {
|
|
158
|
+
due_date: localData.dueDate.format(timePeriod_1.DEFAULT_DATE_FORMAT),
|
|
144
159
|
}),
|
|
160
|
+
...documentIdField,
|
|
145
161
|
lines,
|
|
146
162
|
};
|
|
147
163
|
}
|
|
@@ -9,7 +9,7 @@ import { ZeniDate } from '../../../zeniDayJS';
|
|
|
9
9
|
* The transaction types the Create Transaction flow can originate. A narrow subset of
|
|
10
10
|
* TransactionType -- everything else is read-only and arrives via sync.
|
|
11
11
|
*/
|
|
12
|
-
export declare const ALL_CREATABLE_TRANSACTION_TYPES: readonly ["expense", "check", "credit_card_credit", "transfer", "journal_entry"];
|
|
12
|
+
export declare const ALL_CREATABLE_TRANSACTION_TYPES: readonly ["expense", "check", "credit_card_credit", "transfer", "journal_entry", "bill", "vendor_credit"];
|
|
13
13
|
export type CreatableTransactionType = (typeof ALL_CREATABLE_TRANSACTION_TYPES)[number];
|
|
14
14
|
/**
|
|
15
15
|
* The wire shape the create endpoint expects for a check's remit-to address. Deliberately not
|
|
@@ -54,8 +54,13 @@ export interface CreateTransactionLocalData {
|
|
|
54
54
|
/** Empty for transfer, which has no lines at all. */
|
|
55
55
|
lines: CreateTransactionLineLocalData[];
|
|
56
56
|
transactionType: CreatableTransactionType;
|
|
57
|
-
/**
|
|
57
|
+
/**
|
|
58
|
+
* check / credit_card_credit / vendor_credit reference number, journal_entry entry name, or
|
|
59
|
+
* bill number.
|
|
60
|
+
*/
|
|
58
61
|
documentNumber?: string;
|
|
62
|
+
/** bill only. */
|
|
63
|
+
dueDate?: ZeniDate;
|
|
59
64
|
/** transfer */
|
|
60
65
|
fromAccountId?: ID;
|
|
61
66
|
paymentType?: PaymentType;
|