@zeniai/client-epic-state 5.1.45-betaDI3 → 5.1.45

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 (85) hide show
  1. package/lib/entity/snackbar/snackbarTypes.d.ts +1 -1
  2. package/lib/entity/snackbar/snackbarTypes.js +0 -3
  3. package/lib/entity/task/taskPayload.d.ts +1 -3
  4. package/lib/entity/task/taskPayload.js +2 -24
  5. package/lib/entity/task/taskReducer.d.ts +1 -8
  6. package/lib/entity/task/taskReducer.js +4 -29
  7. package/lib/entity/task/taskState.d.ts +0 -2
  8. package/lib/entity/tenant/epic/saveExternalConnectionEpic.d.ts +1 -2
  9. package/lib/entity/tenant/epic/saveExternalConnectionEpic.js +0 -17
  10. package/lib/epic.d.ts +3 -6
  11. package/lib/epic.js +3 -6
  12. package/lib/esm/entity/snackbar/snackbarTypes.js +0 -3
  13. package/lib/esm/entity/task/taskPayload.js +2 -24
  14. package/lib/esm/entity/task/taskReducer.js +3 -28
  15. package/lib/esm/entity/tenant/epic/saveExternalConnectionEpic.js +0 -17
  16. package/lib/esm/epic.js +3 -6
  17. package/lib/esm/index.js +8 -8
  18. package/lib/esm/view/aiCfoView/aiCfoViewReducer.js +1 -31
  19. package/lib/esm/view/aiCfoView/epics/fetchSkillsEpic.js +8 -33
  20. package/lib/esm/view/companyTaskManagerView/epics/fetchCompanyTaskManagerViewEpic.js +0 -3
  21. package/lib/esm/view/companyTaskManagerView/epics/fetchTaskManagerMetricsEpic.js +1 -7
  22. package/lib/esm/view/expenseAutomationView/reducers/transactionsViewReducer.js +0 -7
  23. package/lib/esm/view/taskManager/taskDetailView/epics/initializeTaskToLocalStoreEpic.js +0 -1
  24. package/lib/esm/view/taskManager/taskDetailView/epics/saveTaskDetailEpic.js +9 -70
  25. package/lib/esm/view/taskManager/taskDetailView/taskDetailReducer.js +2 -56
  26. package/lib/esm/view/taskManager/taskDetailView/taskDetailSelector.js +9 -35
  27. package/lib/esm/view/taskManager/taskListView/epics/fetchTaskListEpic.js +1 -3
  28. package/lib/esm/view/taskManager/taskListView/taskList.js +0 -1
  29. package/lib/esm/view/taskManager/taskListView/taskListReducer.js +18 -310
  30. package/lib/esm/view/taskManager/taskListView/taskListSelector.js +0 -1
  31. package/lib/esm/view/taskManager/taskListView/taskListViewHelpers.js +0 -58
  32. package/lib/esm/view/transactionDetail/epics/saveTransactionHelper.js +0 -22
  33. package/lib/esm/view/transactionDetail/epics/updateTransactionDetailEpic.js +3 -75
  34. package/lib/esm/view/transactionDetail/journalEntryLinesViewModel.js +0 -58
  35. package/lib/esm/view/transactionDetail/transactionDetailLocalDataHelper.js +8 -10
  36. package/lib/esm/view/transactionDetail/transactionDetailReducer.js +1 -66
  37. package/lib/index.d.ts +11 -12
  38. package/lib/index.js +28 -37
  39. package/lib/view/aiCfoView/aiCfoViewPayload.d.ts +0 -10
  40. package/lib/view/aiCfoView/aiCfoViewReducer.d.ts +2 -7
  41. package/lib/view/aiCfoView/aiCfoViewReducer.js +2 -32
  42. package/lib/view/aiCfoView/aiCfoViewState.d.ts +1 -5
  43. package/lib/view/aiCfoView/epics/fetchSkillsEpic.js +8 -33
  44. package/lib/view/companyTaskManagerView/epics/fetchCompanyTaskManagerViewEpic.js +0 -3
  45. package/lib/view/companyTaskManagerView/epics/fetchTaskManagerMetricsEpic.js +1 -7
  46. package/lib/view/companyView/types/cockpitTypes.d.ts +0 -3
  47. package/lib/view/expenseAutomationView/helpers/transactionCategorizationLocalDataHelper.d.ts +1 -1
  48. package/lib/view/expenseAutomationView/reducers/transactionsViewReducer.js +0 -7
  49. package/lib/view/taskManager/taskDetailView/epics/initializeTaskToLocalStoreEpic.js +0 -1
  50. package/lib/view/taskManager/taskDetailView/epics/saveTaskDetailEpic.d.ts +2 -2
  51. package/lib/view/taskManager/taskDetailView/epics/saveTaskDetailEpic.js +8 -69
  52. package/lib/view/taskManager/taskDetailView/taskDetail.d.ts +0 -15
  53. package/lib/view/taskManager/taskDetailView/taskDetailReducer.d.ts +2 -14
  54. package/lib/view/taskManager/taskDetailView/taskDetailReducer.js +3 -57
  55. package/lib/view/taskManager/taskDetailView/taskDetailSelector.d.ts +1 -3
  56. package/lib/view/taskManager/taskDetailView/taskDetailSelector.js +7 -33
  57. package/lib/view/taskManager/taskListView/epics/fetchTaskListEpic.js +1 -3
  58. package/lib/view/taskManager/taskListView/taskList.d.ts +1 -1
  59. package/lib/view/taskManager/taskListView/taskList.js +0 -1
  60. package/lib/view/taskManager/taskListView/taskListPayload.d.ts +0 -4
  61. package/lib/view/taskManager/taskListView/taskListReducer.d.ts +2 -6
  62. package/lib/view/taskManager/taskListView/taskListReducer.js +19 -311
  63. package/lib/view/taskManager/taskListView/taskListSelector.js +0 -1
  64. package/lib/view/taskManager/taskListView/taskListViewHelpers.d.ts +0 -11
  65. package/lib/view/taskManager/taskListView/taskListViewHelpers.js +1 -60
  66. package/lib/view/transactionDetail/epics/saveTransactionHelper.js +0 -22
  67. package/lib/view/transactionDetail/epics/updateTransactionDetailEpic.d.ts +1 -5
  68. package/lib/view/transactionDetail/epics/updateTransactionDetailEpic.js +4 -77
  69. package/lib/view/transactionDetail/journalEntryLinesViewModel.d.ts +0 -27
  70. package/lib/view/transactionDetail/journalEntryLinesViewModel.js +1 -61
  71. package/lib/view/transactionDetail/transactionDetailLocalDataHelper.js +8 -10
  72. package/lib/view/transactionDetail/transactionDetailReducer.d.ts +2 -11
  73. package/lib/view/transactionDetail/transactionDetailReducer.js +2 -67
  74. package/lib/view/transactionDetail/transactionDetailState.d.ts +1 -8
  75. package/lib/view/transactionDetail/transactionDetailTypes.d.ts +0 -2
  76. package/package.json +1 -1
  77. package/lib/esm/view/aiCfoView/epics/submitFeedbackEpic.js +0 -39
  78. package/lib/esm/view/taskManager/taskDetailView/epics/createSubTaskEpic.js +0 -96
  79. package/lib/esm/view/taskManager/taskDetailView/epics/fetchSubTasksEpic.js +0 -53
  80. package/lib/view/aiCfoView/epics/submitFeedbackEpic.d.ts +0 -13
  81. package/lib/view/aiCfoView/epics/submitFeedbackEpic.js +0 -43
  82. package/lib/view/taskManager/taskDetailView/epics/createSubTaskEpic.d.ts +0 -9
  83. package/lib/view/taskManager/taskDetailView/epics/createSubTaskEpic.js +0 -100
  84. package/lib/view/taskManager/taskDetailView/epics/fetchSubTasksEpic.d.ts +0 -8
  85. package/lib/view/taskManager/taskDetailView/epics/fetchSubTasksEpic.js +0 -57
@@ -3,7 +3,7 @@ var __importDefault = (this && this.__importDefault) || function (mod) {
3
3
  return (mod && mod.__esModule) ? mod : { "default": mod };
4
4
  };
5
5
  Object.defineProperty(exports, "__esModule", { value: true });
6
- exports.toNewTransactionLine = exports.toTransactionUpdatePayload = exports.updateTransactionDetailEpic = void 0;
6
+ exports.toTransactionUpdatePayload = exports.updateTransactionDetailEpic = void 0;
7
7
  const get_1 = __importDefault(require("lodash/get"));
8
8
  const rxjs_1 = require("rxjs");
9
9
  const operators_1 = require("rxjs/operators");
@@ -64,9 +64,7 @@ const updateTransactionDetailEpic = (actions$, state$, zeniAPI) => actions$.pipe
64
64
  if (response.data.vendors != null) {
65
65
  actions.push((0, vendorReducer_1.updateVendors)(response.data.vendors, 'merge'));
66
66
  }
67
- // 'replace' so deleted lines are removed from Redux; 'merge' would
68
- // keep any line absent from the server response (deletion bug).
69
- actions.push((0, transactionReducer_1.updateTransaction)(transactionDetailKeyForResponse, response.data.transaction, 'replace'));
67
+ actions.push((0, transactionReducer_1.updateTransaction)(transactionDetailKeyForResponse, response.data.transaction));
70
68
  actions.push((0, transactionDetailReducer_1.initializeTransactionDetailLocalData)({
71
69
  transactionId: transactionIdResp,
72
70
  vendorId: response.data.vendors?.[0]?.vendor_id,
@@ -168,7 +166,7 @@ function preparePayload(transactionState, vendorState, transactionDetailState, t
168
166
  };
169
167
  }
170
168
  if (detail != null) {
171
- const transUpdates = (0, exports.toTransactionUpdatePayload)(saveUpdates.updates, detail, cotTransactionTracking, isAccountingProjectsEnabled, vendorUpdates, customerUpdates, currentSelectedEntity, saveUpdates.deletedLineIds, saveUpdates.addedLines);
169
+ const transUpdates = (0, exports.toTransactionUpdatePayload)(saveUpdates.updates, detail, cotTransactionTracking, isAccountingProjectsEnabled, vendorUpdates, customerUpdates, currentSelectedEntity);
172
170
  const entityUpdates = toEntityUpdatePayload(saveUpdates.entityRelatedUpdates);
173
171
  return {
174
172
  entity_related_updates: entityUpdates,
@@ -178,7 +176,7 @@ function preparePayload(transactionState, vendorState, transactionDetailState, t
178
176
  }
179
177
  return undefined;
180
178
  }
181
- const toTransactionUpdatePayload = (updates, detail, cotTransactionTracking, isAccountingProjectsEnabled, vendorUpdates, customerUpdates, tranSelectedEntity, deletedLineIds, addedLines) => {
179
+ const toTransactionUpdatePayload = (updates, detail, cotTransactionTracking, isAccountingProjectsEnabled, vendorUpdates, customerUpdates, tranSelectedEntity) => {
182
180
  const transaction = Object.assign({}, detail);
183
181
  transaction.memo = updates.memo ?? '';
184
182
  // Unlike `memo` (always reset to '' when absent), `documentId` falls back to
@@ -187,11 +185,6 @@ const toTransactionUpdatePayload = (updates, detail, cotTransactionTracking, isA
187
185
  // either the unchanged current value or undefined, and we must not send an
188
186
  // empty `document_id` that the server would treat as clearing the number.
189
187
  transaction.documentId = updates.documentId ?? transaction.documentId;
190
- // Remove lines deleted by the user in edit mode before patching or serializing.
191
- if (deletedLineIds != null && deletedLineIds.length > 0) {
192
- const deletedSet = new Set(deletedLineIds);
193
- transaction.lines = transaction.lines?.filter((line) => !deletedSet.has(line.id));
194
- }
195
188
  const recommendationUpdates = {};
196
189
  for (const key in updates.updatesByLineId) {
197
190
  const lineUpdates = updates.updatesByLineId[key];
@@ -199,9 +192,6 @@ const toTransactionUpdatePayload = (updates, detail, cotTransactionTracking, isA
199
192
  if (line.id === key) {
200
193
  const lineTobeUpdated = Object.assign({}, line);
201
194
  lineTobeUpdated.lineDescription = lineUpdates.lineDescription ?? '';
202
- if (lineUpdates.amount != null) {
203
- lineTobeUpdated.amount = lineUpdates.amount;
204
- }
205
195
  if (lineUpdates.class != null) {
206
196
  lineTobeUpdated.class = lineUpdates.class;
207
197
  }
@@ -223,16 +213,6 @@ const toTransactionUpdatePayload = (updates, detail, cotTransactionTracking, isA
223
213
  else {
224
214
  lineTobeUpdated.vendor = undefined;
225
215
  }
226
- // Persist a debit↔credit flip on an existing JE line. `lineTobeUpdated`
227
- // is typed as the account-and-class shape, but for a JE the runtime
228
- // object is a JournalEntryTransactionLine, so cast to set the side.
229
- if (lineUpdates.postingType != null) {
230
- const journalEntryLine = lineTobeUpdated;
231
- journalEntryLine.postingType = lineUpdates.postingType;
232
- if (lineUpdates.postingTypeName != null) {
233
- journalEntryLine.postingTypeName = lineUpdates.postingTypeName;
234
- }
235
- }
236
216
  if (lineUpdates.recommendation != null) {
237
217
  recommendationUpdates[line.id] = lineUpdates.recommendation;
238
218
  }
@@ -252,12 +232,6 @@ const toTransactionUpdatePayload = (updates, detail, cotTransactionTracking, isA
252
232
  });
253
233
  transaction.lines = newLineMap;
254
234
  }
255
- // Append lines added by the user in edit mode. Sending id='' tells the
256
- // backend to create a new QBO line rather than updating an existing one.
257
- if (addedLines != null && addedLines.length > 0) {
258
- const newLines = addedLines.map(exports.toNewTransactionLine);
259
- transaction.lines = [...(transaction.lines ?? []), ...newLines];
260
- }
261
235
  transaction.recommendations = recommendationUpdates;
262
236
  // Convert transaction to payload first
263
237
  let basePayload;
@@ -333,53 +307,6 @@ const checkIfVendorOrCustomerMissingForAnyLineItem = (transactionPayload) => {
333
307
  }
334
308
  return isAnyVendorOrCustomerMissing;
335
309
  };
336
- // Converts a locally-created line item (from edit mode) into the wire shape
337
- // expected by the categorize endpoint. Sending id='' signals the backend to
338
- // create a new QBO line rather than update an existing one.
339
- //
340
- // Type-dispatched so each transaction family contributes its own new-line
341
- // shape: journal entries carry debit/credit `postingType`, expenses carry
342
- // `billable`. Phase 3 types extend this by adding a branch rather than forking
343
- // the function.
344
- const EMPTY_ACCOUNT = {
345
- accountDescription: '',
346
- accountId: '',
347
- accountName: '',
348
- labels: [],
349
- };
350
- const toNewTransactionLine = (item) => {
351
- if (item.type === 'journal_entry_transaction_line') {
352
- const journalEntryLine = {
353
- ...item,
354
- id: '',
355
- type: 'journal_entry_transaction_line',
356
- platformLineDetailType: item.platformLineDetailType ?? 'journal_entry_line_detail',
357
- account: item.account ?? EMPTY_ACCOUNT,
358
- billable: item.billable ?? 'not_billable',
359
- isCategoryMiscategorized: false,
360
- isClassMiscategorized: false,
361
- lineTransactionType: item.lineTransactionType ?? 'journal_entry',
362
- postingType: item.postingType ?? 'debit',
363
- postingTypeName: item.postingTypeName != null && item.postingTypeName !== ''
364
- ? item.postingTypeName
365
- : (item.postingType ?? 'debit').charAt(0).toUpperCase() +
366
- (item.postingType ?? 'debit').slice(1),
367
- };
368
- return journalEntryLine;
369
- }
370
- const accountAndClassLine = {
371
- ...item,
372
- id: '',
373
- type: 'transaction_with_account_and_class_line',
374
- platformLineDetailType: item.platformLineDetailType ?? 'account_based_expense_line_detail',
375
- account: item.account ?? EMPTY_ACCOUNT,
376
- billable: item.billable ?? 'not_billable',
377
- isCategoryMiscategorized: false,
378
- isClassMiscategorized: false,
379
- };
380
- return accountAndClassLine;
381
- };
382
- exports.toNewTransactionLine = toNewTransactionLine;
383
310
  const toEntityUpdatePayload = (entityUpdates) => {
384
311
  const entityUpdatesPayload = [];
385
312
  let entityKey;
@@ -64,33 +64,6 @@ export declare const journalEntryTotalsByPostingSide: (lines: ReadonlyArray<Pick
64
64
  creditTotal?: Amount;
65
65
  debitTotal?: Amount;
66
66
  };
67
- type PostingBearer = Pick<JournalEntryTransactionLine, 'amount' | 'postingType'>;
68
- export interface JournalEntrySplitReconciliation {
69
- creditTotal: number;
70
- debitTotal: number;
71
- /** Total debits == total credits == original transaction total. */
72
- isBalanced: boolean;
73
- }
74
- /**
75
- * Sums debit and credit sides (big.js-exact) and reports whether the split is
76
- * balanced: total debits equal total credits AND equal the original
77
- * transaction total. The original total of a valid JE equals its total debits,
78
- * so it is passed in by the caller (`transaction.amount.amount`).
79
- */
80
- export declare const journalEntrySplitReconciliation: (lines: ReadonlyArray<PostingBearer>, originalTotal: number) => JournalEntrySplitReconciliation;
81
- export type JournalEntrySplitErrorKey = 'lineNeedsDebitOrCredit' | 'totalsMustEqual';
82
- export interface JournalEntrySplitValidation {
83
- ok: boolean;
84
- errorKey?: JournalEntrySplitErrorKey;
85
- }
86
- /**
87
- * Save-time validation for a JE split (Figma `4165:33028` / `4165:45379`):
88
- * 1. every line needs a non-zero debit or credit, and
89
- * 2. total debits == total credits == original total.
90
- * Returns the first failing rule's `errorKey` (maps to a strings entry). Does
91
- * NOT require category/class to be chosen — balance is the only gate.
92
- */
93
- export declare const validateJournalEntrySplit: (lines: ReadonlyArray<PostingBearer>, originalTotal: number) => JournalEntrySplitValidation;
94
67
  /**
95
68
  * Drops `linked_transaction_line` entries — equivalent to legacy
96
69
  * `filterOutLinkedTransactionLine` in `transactionDetail.helpers.ts`.
@@ -3,8 +3,7 @@ var __importDefault = (this && this.__importDefault) || function (mod) {
3
3
  return (mod && mod.__esModule) ? mod : { "default": mod };
4
4
  };
5
5
  Object.defineProperty(exports, "__esModule", { value: true });
6
- exports.sortJournalEntryLines = exports.filterJournalEntryLinesExcludingLinked = exports.validateJournalEntrySplit = exports.journalEntrySplitReconciliation = exports.journalEntryTotalsByPostingSide = exports.sumJournalEntryAmounts = exports.journalEntryDefaultSortConfig = exports.toJournalEntrySortKey = exports.JOURNAL_ENTRY_SORT_KEYS = void 0;
7
- const big_js_1 = __importDefault(require("big.js"));
6
+ exports.sortJournalEntryLines = exports.filterJournalEntryLinesExcludingLinked = exports.journalEntryTotalsByPostingSide = exports.sumJournalEntryAmounts = exports.journalEntryDefaultSortConfig = exports.toJournalEntrySortKey = exports.JOURNAL_ENTRY_SORT_KEYS = void 0;
8
7
  const orderBy_1 = __importDefault(require("lodash/orderBy"));
9
8
  const stringToUnion_1 = require("../../commonStateTypes/stringToUnion");
10
9
  const transactionLine_1 = require("../../entity/transaction/stateTypes/transactionLine");
@@ -111,65 +110,6 @@ const journalEntryTotalsByPostingSide = (lines) => {
111
110
  };
112
111
  exports.journalEntryTotalsByPostingSide = journalEntryTotalsByPostingSide;
113
112
  // ---------------------------------------------------------------------------
114
- // Split reconciliation & validation (Phase 2 — JE split)
115
- // ---------------------------------------------------------------------------
116
- // Half-cent tolerance for the balance equality checks, matching the expense
117
- // reconciliation row's epsilon. Sums use big.js so repeated decimal addition
118
- // doesn't drift before the comparison.
119
- const JOURNAL_ENTRY_BALANCE_EPSILON = 0.005;
120
- /**
121
- * Sums debit and credit sides (big.js-exact) and reports whether the split is
122
- * balanced: total debits equal total credits AND equal the original
123
- * transaction total. The original total of a valid JE equals its total debits,
124
- * so it is passed in by the caller (`transaction.amount.amount`).
125
- */
126
- const journalEntrySplitReconciliation = (lines, originalTotal) => {
127
- let debit = new big_js_1.default(0);
128
- let credit = new big_js_1.default(0);
129
- for (const line of lines) {
130
- const amount = new big_js_1.default(line.amount?.amount ?? 0);
131
- if (line.postingType === 'debit') {
132
- debit = debit.plus(amount);
133
- }
134
- else if (line.postingType === 'credit') {
135
- credit = credit.plus(amount);
136
- }
137
- }
138
- const balancedToEachOther = debit
139
- .minus(credit)
140
- .abs()
141
- .lt(JOURNAL_ENTRY_BALANCE_EPSILON);
142
- const balancedToOriginal = debit
143
- .minus(originalTotal)
144
- .abs()
145
- .lt(JOURNAL_ENTRY_BALANCE_EPSILON);
146
- return {
147
- debitTotal: debit.toNumber(),
148
- creditTotal: credit.toNumber(),
149
- isBalanced: balancedToEachOther && balancedToOriginal,
150
- };
151
- };
152
- exports.journalEntrySplitReconciliation = journalEntrySplitReconciliation;
153
- /**
154
- * Save-time validation for a JE split (Figma `4165:33028` / `4165:45379`):
155
- * 1. every line needs a non-zero debit or credit, and
156
- * 2. total debits == total credits == original total.
157
- * Returns the first failing rule's `errorKey` (maps to a strings entry). Does
158
- * NOT require category/class to be chosen — balance is the only gate.
159
- */
160
- const validateJournalEntrySplit = (lines, originalTotal) => {
161
- const everyLineHasSide = lines.every((line) => (line.postingType === 'debit' || line.postingType === 'credit') &&
162
- Math.abs(line.amount?.amount ?? 0) > JOURNAL_ENTRY_BALANCE_EPSILON);
163
- if (!everyLineHasSide) {
164
- return { ok: false, errorKey: 'lineNeedsDebitOrCredit' };
165
- }
166
- if (!(0, exports.journalEntrySplitReconciliation)(lines, originalTotal).isBalanced) {
167
- return { ok: false, errorKey: 'totalsMustEqual' };
168
- }
169
- return { ok: true };
170
- };
171
- exports.validateJournalEntrySplit = validateJournalEntrySplit;
172
- // ---------------------------------------------------------------------------
173
113
  // Filter
174
114
  // ---------------------------------------------------------------------------
175
115
  /**
@@ -834,16 +834,14 @@ const getChangedLineItemCountFromLocalData = (transaction, transactionLocalData)
834
834
  line.type === 'transaction_with_product_or_service_line' ||
835
835
  line.type === 'journal_entry_transaction_line') {
836
836
  const accountLineLocal = transactionLocalData.lineItemById[lineId];
837
- if (accountLineLocal != null) {
838
- const accountLine = line;
839
- hasCategoryChanged =
840
- accountLineLocal.account?.qboId !== accountLine.account.qboId &&
841
- accountLineLocal.account?.accountId !== accountLine.account.accountId;
842
- hasClassChanged =
843
- (accountLineLocal.class?.qboId != null ||
844
- accountLine.class?.qboId != null) &&
845
- accountLineLocal.class?.qboId !== accountLine.class?.qboId;
846
- }
837
+ const accountLine = line;
838
+ hasCategoryChanged =
839
+ accountLineLocal.account?.qboId !== accountLine.account.qboId &&
840
+ accountLineLocal.account?.accountId !== accountLine.account.accountId;
841
+ hasClassChanged =
842
+ (accountLineLocal.class?.qboId != null ||
843
+ accountLine.class?.qboId != null) &&
844
+ accountLineLocal.class?.qboId !== accountLine.class?.qboId;
847
845
  }
848
846
  hasDescriptionChanged =
849
847
  transactionLocalData.lineItemById[lineId] != null
@@ -8,7 +8,7 @@ import { SupportedTransaction, SupportedTransactionPayload } from '../../entity/
8
8
  import { ZeniAPIStatus } from '../../responsePayload';
9
9
  import { UncategorizedAccounts } from '../accountList/accountListSelector';
10
10
  import { TransactionDetailState, TransactionSaveUpdates } from './transactionDetailState';
11
- import { TransactionDetailLineItemData, TransactionDetailLocalData, TransactionVendorUpdates } from './transactionDetailTypes';
11
+ import { TransactionDetailLocalData, TransactionVendorUpdates } from './transactionDetailTypes';
12
12
  export declare const initialState: TransactionDetailState;
13
13
  export declare const downloadAccountingProviderAttachment: import("@reduxjs/toolkit").ActionCreatorWithPreparedPayload<[attachmentId: string], {
14
14
  attachmentId: string;
@@ -166,15 +166,6 @@ export declare const downloadAccountingProviderAttachment: import("@reduxjs/tool
166
166
  transactionId: TransactionID;
167
167
  transaction: SupportedTransaction;
168
168
  isEnabled: boolean;
169
- }, "transactionDetail/setIsVendorUpdateAllChecked", never, never>, addSplitLine: import("@reduxjs/toolkit").ActionCreatorWithPreparedPayload<[transactionId: TransactionID, newLine: TransactionDetailLineItemData], {
170
- transactionId: TransactionID;
171
- newLine: TransactionDetailLineItemData;
172
- }, "transactionDetail/addSplitLine", never, never>, deleteSplitLine: import("@reduxjs/toolkit").ActionCreatorWithPreparedPayload<[transactionId: TransactionID, lineId: string], {
173
- transactionId: TransactionID;
174
- lineId: string;
175
- }, "transactionDetail/deleteSplitLine", never, never>, toggleSplitEditMode: import("@reduxjs/toolkit").ActionCreatorWithPreparedPayload<[transactionId: TransactionID, editMode: boolean], {
176
- transactionId: TransactionID;
177
- editMode: boolean;
178
- }, "transactionDetail/toggleSplitEditMode", never, never>;
169
+ }, "transactionDetail/setIsVendorUpdateAllChecked", never, never>;
179
170
  declare const _default: import("redux").Reducer<TransactionDetailState>;
180
171
  export default _default;
@@ -4,7 +4,7 @@ var __importDefault = (this && this.__importDefault) || function (mod) {
4
4
  };
5
5
  var _a;
6
6
  Object.defineProperty(exports, "__esModule", { value: true });
7
- exports.toggleSplitEditMode = exports.deleteSplitLine = exports.addSplitLine = exports.setIsVendorUpdateAllChecked = exports.updateVendorBulkRecommendationsFetchStatus = exports.updateLatestSelectedEntity = exports.resetAllLineItemsToVendor = exports.updateVendorToAllLineItems = exports.updateLocalDataWithTransactionsUpdateWithVendorCheckbox = exports.resetSelectedCustomer = exports.resetVendor = exports.updateSelectedCustomer = exports.updateSelectedVendor = exports.removeEntityRecommendationForLineIdForTransactionDetail = exports.markCategoryClassRecommendationsFailureForTransactionDetail = exports.markCategoryClassRecommendationsCompletedForTransactionDetail = exports.markCategoryClassRecommendationsInProgressForTransactionDetail = exports.setEntityRecommendationForLineIdsForTransactionDetail = exports.setAllLineItemsLocalDataIsUpdateAllChecked = exports.setAllLineItemsToCategoryClassInLocalData = exports.resetLineItemsCategoryClassInLocalData = exports.clearTransactionDetailLocalData = exports.saveTransactionDetailLocalData = exports.initializeTransactionDetailLocalData = exports.saveTransactionDetail = exports.updateTransactionStateIfUpdateActionNotAllowed = exports.updateStatusConsolidatedSaveTransactionDetail = exports.updateStatusForTransactionNotMiscategorizedUpdate = exports.deleteTransactionAttachmentSuccess = exports.deleteTransactionAttachmentFailure = exports.deleteTransactionAttachment = exports.markTransactionAsNotMiscategorized = exports.clearTransactionDetailSaveStatus = exports.updateTransactionDetailSaveStatus = exports.updateTransactionDetail = exports.uploadMissingAttachmentSuccess = exports.clearTransactionDetail = exports.removeTransactionDetail = exports.updateTransactionDetailFetchState = exports.fetchTransactionDetail = exports.downloadAccountingProviderAttachmentFailure = exports.downloadAccountingProviderAttachmentSuccess = exports.downloadAccountingProviderAttachment = exports.initialState = void 0;
7
+ exports.setIsVendorUpdateAllChecked = exports.updateVendorBulkRecommendationsFetchStatus = exports.updateLatestSelectedEntity = exports.resetAllLineItemsToVendor = exports.updateVendorToAllLineItems = exports.updateLocalDataWithTransactionsUpdateWithVendorCheckbox = exports.resetSelectedCustomer = exports.resetVendor = exports.updateSelectedCustomer = exports.updateSelectedVendor = exports.removeEntityRecommendationForLineIdForTransactionDetail = exports.markCategoryClassRecommendationsFailureForTransactionDetail = exports.markCategoryClassRecommendationsCompletedForTransactionDetail = exports.markCategoryClassRecommendationsInProgressForTransactionDetail = exports.setEntityRecommendationForLineIdsForTransactionDetail = exports.setAllLineItemsLocalDataIsUpdateAllChecked = exports.setAllLineItemsToCategoryClassInLocalData = exports.resetLineItemsCategoryClassInLocalData = exports.clearTransactionDetailLocalData = exports.saveTransactionDetailLocalData = exports.initializeTransactionDetailLocalData = exports.saveTransactionDetail = exports.updateTransactionStateIfUpdateActionNotAllowed = exports.updateStatusConsolidatedSaveTransactionDetail = exports.updateStatusForTransactionNotMiscategorizedUpdate = exports.deleteTransactionAttachmentSuccess = exports.deleteTransactionAttachmentFailure = exports.deleteTransactionAttachment = exports.markTransactionAsNotMiscategorized = exports.clearTransactionDetailSaveStatus = exports.updateTransactionDetailSaveStatus = exports.updateTransactionDetail = exports.uploadMissingAttachmentSuccess = exports.clearTransactionDetail = exports.removeTransactionDetail = exports.updateTransactionDetailFetchState = exports.fetchTransactionDetail = exports.downloadAccountingProviderAttachmentFailure = exports.downloadAccountingProviderAttachmentSuccess = exports.downloadAccountingProviderAttachment = exports.initialState = void 0;
8
8
  const toolkit_1 = require("@reduxjs/toolkit");
9
9
  const get_1 = __importDefault(require("lodash/get"));
10
10
  const entity_1 = require("../../entity/genericEntity/entity");
@@ -670,71 +670,6 @@ const transactionDetail = (0, toolkit_1.createSlice)({
670
670
  };
671
671
  },
672
672
  },
673
- // Split transaction — Phase 1 (expense)
674
- addSplitLine: {
675
- reducer(draft, action) {
676
- const key = (0, transactionDetailState_1.getTransactionDetailKey)(action.payload.transactionId);
677
- const detail = (0, get_1.default)(draft.transactionDetailById, key, undefined);
678
- if (detail != null) {
679
- draft.transactionDetailById[key] = {
680
- ...detail,
681
- transactionDetailLocalData: {
682
- ...detail.transactionDetailLocalData,
683
- lineItemById: {
684
- ...detail.transactionDetailLocalData.lineItemById,
685
- [action.payload.newLine.id]: action.payload.newLine,
686
- },
687
- },
688
- };
689
- }
690
- },
691
- prepare(transactionId, newLine) {
692
- return { payload: { transactionId, newLine } };
693
- },
694
- },
695
- deleteSplitLine: {
696
- reducer(draft, action) {
697
- const key = (0, transactionDetailState_1.getTransactionDetailKey)(action.payload.transactionId);
698
- const detail = (0, get_1.default)(draft.transactionDetailById, key, undefined);
699
- if (detail == null) {
700
- return;
701
- }
702
- const { lineItemById, deletedLineIds = [] } = detail.transactionDetailLocalData;
703
- const updated = { ...lineItemById };
704
- delete updated[action.payload.lineId];
705
- draft.transactionDetailById[key] = {
706
- ...detail,
707
- transactionDetailLocalData: {
708
- ...detail.transactionDetailLocalData,
709
- lineItemById: updated,
710
- deletedLineIds: [...deletedLineIds, action.payload.lineId],
711
- },
712
- };
713
- },
714
- prepare(transactionId, lineId) {
715
- return { payload: { transactionId, lineId } };
716
- },
717
- },
718
- toggleSplitEditMode: {
719
- reducer(draft, action) {
720
- const key = (0, transactionDetailState_1.getTransactionDetailKey)(action.payload.transactionId);
721
- const detail = (0, get_1.default)(draft.transactionDetailById, key, undefined);
722
- if (detail != null) {
723
- draft.transactionDetailById[key] = {
724
- ...detail,
725
- transactionDetailLocalData: {
726
- ...detail.transactionDetailLocalData,
727
- editMode: action.payload.editMode,
728
- // Clear delete tracking when exiting edit mode without saving.
729
- ...(!action.payload.editMode && { deletedLineIds: [] }),
730
- },
731
- };
732
- }
733
- },
734
- prepare(transactionId, editMode) {
735
- return { payload: { transactionId, editMode } };
736
- },
737
- },
738
673
  clearRecommendedVendorsList(draft) {
739
674
  Object.assign(draft, exports.initialState);
740
675
  },
@@ -843,7 +778,7 @@ const transactionDetail = (0, toolkit_1.createSlice)({
843
778
  },
844
779
  },
845
780
  });
846
- _a = transactionDetail.actions, exports.downloadAccountingProviderAttachment = _a.downloadAccountingProviderAttachment, exports.downloadAccountingProviderAttachmentSuccess = _a.downloadAccountingProviderAttachmentSuccess, exports.downloadAccountingProviderAttachmentFailure = _a.downloadAccountingProviderAttachmentFailure, exports.fetchTransactionDetail = _a.fetchTransactionDetail, exports.updateTransactionDetailFetchState = _a.updateTransactionDetailFetchState, exports.removeTransactionDetail = _a.removeTransactionDetail, exports.clearTransactionDetail = _a.clearTransactionDetail, exports.uploadMissingAttachmentSuccess = _a.uploadMissingAttachmentSuccess, exports.updateTransactionDetail = _a.updateTransactionDetail, exports.updateTransactionDetailSaveStatus = _a.updateTransactionDetailSaveStatus, exports.clearTransactionDetailSaveStatus = _a.clearTransactionDetailSaveStatus, exports.markTransactionAsNotMiscategorized = _a.markTransactionAsNotMiscategorized, exports.deleteTransactionAttachment = _a.deleteTransactionAttachment, exports.deleteTransactionAttachmentFailure = _a.deleteTransactionAttachmentFailure, exports.deleteTransactionAttachmentSuccess = _a.deleteTransactionAttachmentSuccess, exports.updateStatusForTransactionNotMiscategorizedUpdate = _a.updateStatusForTransactionNotMiscategorizedUpdate, exports.updateStatusConsolidatedSaveTransactionDetail = _a.updateStatusConsolidatedSaveTransactionDetail, exports.updateTransactionStateIfUpdateActionNotAllowed = _a.updateTransactionStateIfUpdateActionNotAllowed, exports.saveTransactionDetail = _a.saveTransactionDetail, exports.initializeTransactionDetailLocalData = _a.initializeTransactionDetailLocalData, exports.saveTransactionDetailLocalData = _a.saveTransactionDetailLocalData, exports.clearTransactionDetailLocalData = _a.clearTransactionDetailLocalData, exports.resetLineItemsCategoryClassInLocalData = _a.resetLineItemsCategoryClassInLocalData, exports.setAllLineItemsToCategoryClassInLocalData = _a.setAllLineItemsToCategoryClassInLocalData, exports.setAllLineItemsLocalDataIsUpdateAllChecked = _a.setAllLineItemsLocalDataIsUpdateAllChecked, exports.setEntityRecommendationForLineIdsForTransactionDetail = _a.setEntityRecommendationForLineIdsForTransactionDetail, exports.markCategoryClassRecommendationsInProgressForTransactionDetail = _a.markCategoryClassRecommendationsInProgressForTransactionDetail, exports.markCategoryClassRecommendationsCompletedForTransactionDetail = _a.markCategoryClassRecommendationsCompletedForTransactionDetail, exports.markCategoryClassRecommendationsFailureForTransactionDetail = _a.markCategoryClassRecommendationsFailureForTransactionDetail, exports.removeEntityRecommendationForLineIdForTransactionDetail = _a.removeEntityRecommendationForLineIdForTransactionDetail, exports.updateSelectedVendor = _a.updateSelectedVendor, exports.updateSelectedCustomer = _a.updateSelectedCustomer, exports.resetVendor = _a.resetVendor, exports.resetSelectedCustomer = _a.resetSelectedCustomer, exports.updateLocalDataWithTransactionsUpdateWithVendorCheckbox = _a.updateLocalDataWithTransactionsUpdateWithVendorCheckbox, exports.updateVendorToAllLineItems = _a.updateVendorToAllLineItems, exports.resetAllLineItemsToVendor = _a.resetAllLineItemsToVendor, exports.updateLatestSelectedEntity = _a.updateLatestSelectedEntity, exports.updateVendorBulkRecommendationsFetchStatus = _a.updateVendorBulkRecommendationsFetchStatus, exports.setIsVendorUpdateAllChecked = _a.setIsVendorUpdateAllChecked, exports.addSplitLine = _a.addSplitLine, exports.deleteSplitLine = _a.deleteSplitLine, exports.toggleSplitEditMode = _a.toggleSplitEditMode;
781
+ _a = transactionDetail.actions, exports.downloadAccountingProviderAttachment = _a.downloadAccountingProviderAttachment, exports.downloadAccountingProviderAttachmentSuccess = _a.downloadAccountingProviderAttachmentSuccess, exports.downloadAccountingProviderAttachmentFailure = _a.downloadAccountingProviderAttachmentFailure, exports.fetchTransactionDetail = _a.fetchTransactionDetail, exports.updateTransactionDetailFetchState = _a.updateTransactionDetailFetchState, exports.removeTransactionDetail = _a.removeTransactionDetail, exports.clearTransactionDetail = _a.clearTransactionDetail, exports.uploadMissingAttachmentSuccess = _a.uploadMissingAttachmentSuccess, exports.updateTransactionDetail = _a.updateTransactionDetail, exports.updateTransactionDetailSaveStatus = _a.updateTransactionDetailSaveStatus, exports.clearTransactionDetailSaveStatus = _a.clearTransactionDetailSaveStatus, exports.markTransactionAsNotMiscategorized = _a.markTransactionAsNotMiscategorized, exports.deleteTransactionAttachment = _a.deleteTransactionAttachment, exports.deleteTransactionAttachmentFailure = _a.deleteTransactionAttachmentFailure, exports.deleteTransactionAttachmentSuccess = _a.deleteTransactionAttachmentSuccess, exports.updateStatusForTransactionNotMiscategorizedUpdate = _a.updateStatusForTransactionNotMiscategorizedUpdate, exports.updateStatusConsolidatedSaveTransactionDetail = _a.updateStatusConsolidatedSaveTransactionDetail, exports.updateTransactionStateIfUpdateActionNotAllowed = _a.updateTransactionStateIfUpdateActionNotAllowed, exports.saveTransactionDetail = _a.saveTransactionDetail, exports.initializeTransactionDetailLocalData = _a.initializeTransactionDetailLocalData, exports.saveTransactionDetailLocalData = _a.saveTransactionDetailLocalData, exports.clearTransactionDetailLocalData = _a.clearTransactionDetailLocalData, exports.resetLineItemsCategoryClassInLocalData = _a.resetLineItemsCategoryClassInLocalData, exports.setAllLineItemsToCategoryClassInLocalData = _a.setAllLineItemsToCategoryClassInLocalData, exports.setAllLineItemsLocalDataIsUpdateAllChecked = _a.setAllLineItemsLocalDataIsUpdateAllChecked, exports.setEntityRecommendationForLineIdsForTransactionDetail = _a.setEntityRecommendationForLineIdsForTransactionDetail, exports.markCategoryClassRecommendationsInProgressForTransactionDetail = _a.markCategoryClassRecommendationsInProgressForTransactionDetail, exports.markCategoryClassRecommendationsCompletedForTransactionDetail = _a.markCategoryClassRecommendationsCompletedForTransactionDetail, exports.markCategoryClassRecommendationsFailureForTransactionDetail = _a.markCategoryClassRecommendationsFailureForTransactionDetail, exports.removeEntityRecommendationForLineIdForTransactionDetail = _a.removeEntityRecommendationForLineIdForTransactionDetail, exports.updateSelectedVendor = _a.updateSelectedVendor, exports.updateSelectedCustomer = _a.updateSelectedCustomer, exports.resetVendor = _a.resetVendor, exports.resetSelectedCustomer = _a.resetSelectedCustomer, exports.updateLocalDataWithTransactionsUpdateWithVendorCheckbox = _a.updateLocalDataWithTransactionsUpdateWithVendorCheckbox, exports.updateVendorToAllLineItems = _a.updateVendorToAllLineItems, exports.resetAllLineItemsToVendor = _a.resetAllLineItemsToVendor, exports.updateLatestSelectedEntity = _a.updateLatestSelectedEntity, exports.updateVendorBulkRecommendationsFetchStatus = _a.updateVendorBulkRecommendationsFetchStatus, exports.setIsVendorUpdateAllChecked = _a.setIsVendorUpdateAllChecked;
847
782
  exports.default = transactionDetail.reducer;
848
783
  function getUpdatedEntityLocalData(detail, updates, entity, resetRecommendations, type) {
849
784
  const key = type === 'customer' ? 'customerUpdates' : 'vendorUpdates';
@@ -1,5 +1,4 @@
1
1
  import { FetchState, FetchStateAndError, FetchedState, ID } from '../../commonStateTypes/common';
2
- import { Amount } from '../../commonStateTypes/amount';
3
2
  import { Recommendation } from '../../commonStateTypes/recommendationBase';
4
3
  import { AccountBase } from '../../entity/account/accountState';
5
4
  import { ClassBase } from '../../entity/class/classState';
@@ -7,10 +6,9 @@ import { CustomerBase } from '../../entity/customer/customerState';
7
6
  import { EntityType } from '../../entity/genericEntity/entity';
8
7
  import { ProjectBase } from '../../entity/project/projectState';
9
8
  import { Transaction, TransactionID } from '../../entity/transaction/stateTypes/transaction';
10
- import { TransactionCategory } from '../../entity/transaction/stateTypes/transactionType';
11
9
  import { VendorBase } from '../../entity/vendor/vendorState';
12
10
  import { EntityRecommendationKey } from '../recommendation/recommendationState';
13
- import { TransactionDetailLineItemData, TransactionDetailLocalData } from './transactionDetailTypes';
11
+ import { TransactionDetailLocalData } from './transactionDetailTypes';
14
12
  export declare const getTransactionDetailKey: (transactionId: TransactionID) => `${string}_bill` | `${string}_expense` | `${string}_check` | `${string}_refund` | `${string}_invoice` | `${string}_payment` | `${string}_credit_memo` | `${string}_sales_receipt` | `${string}_delayed_credit` | `${string}_delayed_charge` | `${string}_bill_payment` | `${string}_bill_payment_check` | `${string}_bill_payment_credit_card` | `${string}_vendor_credit` | `${string}_credit_card_credit` | `${string}_transfer` | `${string}_credit_card_payment` | `${string}_deposit` | `${string}_journal_entry`;
15
13
  export type TransactionDetailKey = ReturnType<typeof getTransactionDetailKey>;
16
14
  export declare const getZeniTransactionDetailKey: (transactionId: TransactionID) => `${string}_bill` | `${string}_expense` | `${string}_check` | `${string}_refund` | `${string}_invoice` | `${string}_payment` | `${string}_credit_memo` | `${string}_sales_receipt` | `${string}_delayed_credit` | `${string}_delayed_charge` | `${string}_bill_payment` | `${string}_bill_payment_check` | `${string}_bill_payment_credit_card` | `${string}_vendor_credit` | `${string}_credit_card_credit` | `${string}_transfer` | `${string}_credit_card_payment` | `${string}_deposit` | `${string}_journal_entry`;
@@ -52,12 +50,9 @@ export interface TransactionDetailState {
52
50
  }
53
51
  export interface TransactionLineUpdates {
54
52
  account?: AccountBase;
55
- amount?: Amount;
56
53
  class?: ClassBase;
57
54
  customer?: CustomerBase;
58
55
  lineDescription?: string;
59
- postingType?: TransactionCategory;
60
- postingTypeName?: string;
61
56
  project?: ProjectBase;
62
57
  recommendation?: Recommendation[];
63
58
  vendor?: VendorBase;
@@ -83,7 +78,5 @@ export interface TransactionSaveUpdates {
83
78
  entityRelatedUpdates: Record<EntityRecommendationKey, EntityRelatedRecommendationUpdates>;
84
79
  markAsMiscatUpdates: boolean;
85
80
  updates: TransactionUpdates;
86
- addedLines?: TransactionDetailLineItemData[];
87
- deletedLineIds?: ID[];
88
81
  }
89
82
  export {};
@@ -50,9 +50,7 @@ export interface TransactionDetailLocalData {
50
50
  qboId: ID;
51
51
  };
52
52
  customerUpdates?: TransactionVendorUpdates;
53
- deletedLineIds?: ID[];
54
53
  documentId?: string;
55
- editMode?: boolean;
56
54
  latestSelectedEntityOnLineItem?: Entity;
57
55
  latestUpdatedLineWithEntity?: ID;
58
56
  memo?: string;
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@zeniai/client-epic-state",
3
- "version": "5.1.45-betaDI3",
3
+ "version": "5.1.45",
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",
@@ -1,39 +0,0 @@
1
- import { of } from 'rxjs';
2
- import { catchError, filter, groupBy, mergeMap, switchMap } from 'rxjs/operators';
3
- import { createZeniAPIStatus, isSuccessStatus, } from '../../../responsePayload';
4
- import { submitFeedback, submitFeedbackFailure, submitFeedbackSuccess, } from '../aiCfoViewReducer';
5
- /**
6
- * Thin wiring for AI CFO answer feedback (👍/👎). Dispatch `submitFeedback(...)` (defined on the
7
- * aiCfoView slice) to POST to the AI CFO micro-service `/1.0/feedback` endpoint, which emits the
8
- * analytics event server-side and routes negatives to the review queue. The capture-prompt UI
9
- * that dispatches this lands in a fast-follow PR.
10
- */
11
- export const submitFeedbackEpic = (actions$, _state$, zeniAPI) => actions$.pipe(filter(submitFeedback.match),
12
- // Per-message dedup: group by chatMessageId so rapid repeat clicks on the SAME answer cancel
13
- // the in-flight request (switchMap) — no duplicate POST / analytics / Slack row — while
14
- // feedback on different answers still runs concurrently (separate groups under mergeMap).
15
- groupBy((action) => action.payload.chatMessageId), mergeMap((perMessage$) => perMessage$.pipe(switchMap((action) => {
16
- const { chatMessageId, chatSessionId, feedbackType, answerText, model, questionText, } = action.payload;
17
- const body = {
18
- chat_message_id: chatMessageId,
19
- chat_session_id: chatSessionId,
20
- feedback_type: feedbackType,
21
- ...(answerText != null && { answer_text: answerText }),
22
- ...(model != null && { model }),
23
- ...(questionText != null && { question_text: questionText }),
24
- };
25
- return zeniAPI
26
- .postAndGetJSON(`${zeniAPI.apiEndPoints.aiCfoMicroServiceBaseUrl}/1.0/feedback`, body)
27
- .pipe(
28
- // Status-only success check (no `data`): /1.0/feedback returns a 2xx with status and no
29
- // body, so isSuccessResponse (which requires response.data) would wrongly fail it.
30
- mergeMap((response) => isSuccessStatus(response)
31
- ? of(submitFeedbackSuccess(chatMessageId))
32
- : of(submitFeedbackFailure(chatMessageId, response.status))), catchError((error) => of(submitFeedbackFailure(chatMessageId, createZeniAPIStatus(
33
- // message (detailed) first, then the short title — per createZeniAPIStatus(message, title).
34
- // JSON.stringify(Error) drops the (non-enumerable) message — extract it explicitly.
35
- 'Feedback REST API call errored out: ' +
36
- (error instanceof Error
37
- ? error.message
38
- : String(error)), 'Unexpected Error')))));
39
- }))));
@@ -1,96 +0,0 @@
1
- import { from, of } from 'rxjs';
2
- import { catchError, filter, mergeMap } from 'rxjs/operators';
3
- import { convertHHMMStrToMinutes } from '../../../../commonStateTypes/fiscalYearHelpers/formatMinutesToFromHHMM';
4
- import { openSnackbar } from '../../../../entity/snackbar/snackbarReducer';
5
- import { appendSubTaskId, updateTasks, } from '../../../../entity/task/taskReducer';
6
- import { getTaskById } from '../../../../entity/task/taskSelector';
7
- import { createZeniAPIStatus, isSuccessResponse, } from '../../../../responsePayload';
8
- import { updateTaskListOnNewTaskCreationSuccess } from '../../taskListView/taskListReducer';
9
- import { createSubTask, createSubTaskSuccessOrFailure, } from '../taskDetailReducer';
10
- export const createSubTaskEpic = (actions$, state$, zeniAPI) => actions$.pipe(filter(createSubTask.match), mergeMap((action) => {
11
- const state = state$.value;
12
- const parentTask = getTaskById(state.taskState, action.payload.parentTaskId);
13
- // Subtasks inherit every parent group membership, not just the first,
14
- // so the subtask surfaces in all the same buckets as its parent.
15
- const parentTaskGroupIds = parentTask?.taskGroupIds ?? [];
16
- const parentTaskGroupId = parentTaskGroupIds[0];
17
- const isTaskListFetched = state.taskListState.fetchState === 'Completed';
18
- const payload = prepareSubTaskPayload(action.payload, parentTaskGroupIds);
19
- return zeniAPI
20
- .postAndGetJSON(`${zeniAPI.apiEndPoints.taskMicroServiceBaseUrl}/1.0/task-manager/tasks`, payload)
21
- .pipe(mergeMap((response) => {
22
- if (isSuccessResponse(response) &&
23
- response.data != null &&
24
- response.data.tasks.length > 0) {
25
- const newTaskId = response.data.tasks[0].task_id;
26
- const actions = [
27
- updateTasks(response.data.tasks),
28
- appendSubTaskId({
29
- parentTaskId: action.payload.parentTaskId,
30
- subTaskId: newTaskId,
31
- }),
32
- createSubTaskSuccessOrFailure({
33
- fetchState: 'Completed',
34
- newTaskId,
35
- }),
36
- openSnackbar({
37
- messageSection: 'create_sub_task',
38
- messageText: 'success',
39
- type: 'success',
40
- }),
41
- ];
42
- // The task list is keyed on parent tasks (no parent_task_id)
43
- // — subtasks belong to their parent's children list, not the
44
- // top-level list. Pushing a subtask into the list would
45
- // surface it as an orphan row at the top of the group.
46
- // Only fire the list-update for actual parent tasks.
47
- const createdTask = response.data.tasks[0];
48
- const isSubtask = createdTask.parent_task_id != null &&
49
- createdTask.parent_task_id !== '';
50
- if (!isSubtask &&
51
- isTaskListFetched === true &&
52
- parentTaskGroupId != null) {
53
- actions.push(updateTaskListOnNewTaskCreationSuccess({
54
- taskGroupId: parentTaskGroupId,
55
- task: createdTask,
56
- }));
57
- }
58
- return from(actions);
59
- }
60
- else {
61
- return of(createSubTaskSuccessOrFailure({
62
- fetchState: 'Error',
63
- error: response.status,
64
- }), openSnackbar({
65
- messageSection: 'create_sub_task',
66
- messageText: 'failed',
67
- type: 'error',
68
- variables: [
69
- {
70
- variableName: '_api-error_',
71
- variableValue: response.status.message,
72
- },
73
- ],
74
- }));
75
- }
76
- }), catchError((error) => of(createSubTaskSuccessOrFailure({
77
- fetchState: 'Error',
78
- error: createZeniAPIStatus('Unexpected Error', 'Create Sub Task REST API call errored out' +
79
- JSON.stringify(error)),
80
- }))));
81
- }));
82
- const prepareSubTaskPayload = (subTask, parentTaskGroupIds) => ({
83
- name: subTask.name,
84
- assignees: subTask.assignee,
85
- description: subTask.description,
86
- priority: subTask.priority,
87
- status: subTask.status,
88
- tags: subTask.tagIds,
89
- time_spent: convertHHMMStrToMinutes(subTask.timeSpent),
90
- group_assignees: subTask.groupAssignees,
91
- parent_task_id: subTask.parentTaskId,
92
- // Inherit every parent group, not just the first — see callsite for
93
- // the two-scope rationale.
94
- task_group_ids: parentTaskGroupIds,
95
- due_date: subTask.dueDate?.format('YYYY-MM-DD') ?? null,
96
- });