@zeniai/client-epic-state 5.0.83-betaRR3 → 5.0.83-betaRR5

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 (79) hide show
  1. package/lib/entity/aiCfo/aiCfoPayload.d.ts +1 -4
  2. package/lib/entity/aiCfo/aiCfoReducer.js +3 -11
  3. package/lib/entity/aiCfo/aiCfoState.d.ts +0 -19
  4. package/lib/entity/aiCfo/aiCfoState.js +1 -8
  5. package/lib/entity/cardPolicy/policyRecommendationFromUploadEpic.d.ts +3 -2
  6. package/lib/entity/cardPolicy/policyRecommendationFromUploadEpic.js +3 -2
  7. package/lib/epic.d.ts +14 -12
  8. package/lib/epic.js +14 -12
  9. package/lib/esm/entity/aiCfo/aiCfoReducer.js +4 -12
  10. package/lib/esm/entity/aiCfo/aiCfoState.js +0 -7
  11. package/lib/esm/entity/cardPolicy/policyRecommendationFromUploadEpic.js +4 -3
  12. package/lib/esm/epic.js +14 -12
  13. package/lib/esm/index.js +14 -3
  14. package/lib/esm/view/spendManagement/chargeCards/cardPolicy/createCardPolicy/applyAiCardPolicyFormDraftUpdate.js +328 -0
  15. package/lib/esm/view/spendManagement/chargeCards/cardPolicy/createCardPolicy/applyExtractedPolicyToAiCardPolicyDraft.js +120 -0
  16. package/lib/esm/view/spendManagement/chargeCards/cardPolicy/createCardPolicy/applyExtractedPolicyToDraftEpic.js +60 -0
  17. package/lib/esm/view/spendManagement/chargeCards/cardPolicy/createCardPolicy/applyExtractedPolicyToManualCardPolicyDraft.js +118 -0
  18. package/lib/esm/view/spendManagement/chargeCards/cardPolicy/createCardPolicy/applyUploadPlanToAiCardPolicyDraft.js +33 -0
  19. package/lib/esm/view/spendManagement/chargeCards/cardPolicy/createCardPolicy/buildAiCardPolicyFormDraftSeed.js +385 -0
  20. package/lib/esm/view/spendManagement/chargeCards/cardPolicy/createCardPolicy/buildManualCardPolicyFormDraftSeed.js +34 -0
  21. package/lib/esm/view/spendManagement/chargeCards/cardPolicy/createCardPolicy/cardPolicyChipIds.js +33 -0
  22. package/lib/esm/view/spendManagement/chargeCards/cardPolicy/createCardPolicy/cardPolicyFormDraftTypes.js +17 -0
  23. package/lib/esm/view/spendManagement/chargeCards/cardPolicy/createCardPolicy/cardPolicyRequestParts.js +144 -0
  24. package/lib/esm/view/spendManagement/chargeCards/cardPolicy/createCardPolicy/createCardPolicyReducer.js +137 -1
  25. package/lib/esm/view/spendManagement/chargeCards/cardPolicy/createCardPolicy/createCardPolicySelector.js +18 -0
  26. package/lib/esm/view/spendManagement/chargeCards/cardPolicy/createCardPolicy/deriveAiPolicyReviewRowsFromInputs.js +148 -0
  27. package/lib/esm/view/spendManagement/chargeCards/cardPolicy/createCardPolicy/seedAiCardPolicyFormDraftEpic.js +112 -0
  28. package/lib/esm/view/spendManagement/chargeCards/cardPolicy/createCardPolicy/toBulkCardPolicyTemplateRequestsFromDraft.js +101 -0
  29. package/lib/esm/view/spendManagement/chargeCards/cardPolicy/createCardPolicy/toCardPolicyTemplateRequestFromDraft.js +71 -0
  30. package/lib/esm/view/spendManagement/chargeCards/cardPolicy/createCardPolicy/toManualCardPolicyTemplateRequestFromDraft.js +34 -0
  31. package/lib/esm/view/spendManagement/chargeCards/issueChargeCard/applyAiCardCreationFormDraftUpdate.js +0 -1
  32. package/lib/esm/view/spendManagement/chargeCards/issueChargeCard/buildAiCardCreationFormDraftSeed.js +13 -6
  33. package/lib/esm/view/spendManagement/chargeCards/issueChargeCard/deriveAiCardRowsFromTeams.js +1 -3
  34. package/lib/esm/view/spendManagement/chargeCards/issueChargeCard/toIssueChargeCardLocalDataFromDraft.js +0 -5
  35. package/lib/index.d.ts +20 -4
  36. package/lib/index.js +45 -4
  37. package/lib/view/spendManagement/chargeCards/cardPolicy/createCardPolicy/applyAiCardPolicyFormDraftUpdate.d.ts +38 -0
  38. package/lib/view/spendManagement/chargeCards/cardPolicy/createCardPolicy/applyAiCardPolicyFormDraftUpdate.js +333 -0
  39. package/lib/view/spendManagement/chargeCards/cardPolicy/createCardPolicy/applyExtractedPolicyToAiCardPolicyDraft.d.ts +25 -0
  40. package/lib/view/spendManagement/chargeCards/cardPolicy/createCardPolicy/applyExtractedPolicyToAiCardPolicyDraft.js +124 -0
  41. package/lib/view/spendManagement/chargeCards/cardPolicy/createCardPolicy/applyExtractedPolicyToDraftEpic.d.ts +28 -0
  42. package/lib/view/spendManagement/chargeCards/cardPolicy/createCardPolicy/applyExtractedPolicyToDraftEpic.js +64 -0
  43. package/lib/view/spendManagement/chargeCards/cardPolicy/createCardPolicy/applyExtractedPolicyToManualCardPolicyDraft.d.ts +17 -0
  44. package/lib/view/spendManagement/chargeCards/cardPolicy/createCardPolicy/applyExtractedPolicyToManualCardPolicyDraft.js +122 -0
  45. package/lib/view/spendManagement/chargeCards/cardPolicy/createCardPolicy/applyUploadPlanToAiCardPolicyDraft.d.ts +23 -0
  46. package/lib/view/spendManagement/chargeCards/cardPolicy/createCardPolicy/applyUploadPlanToAiCardPolicyDraft.js +37 -0
  47. package/lib/view/spendManagement/chargeCards/cardPolicy/createCardPolicy/buildAiCardPolicyFormDraftSeed.d.ts +38 -0
  48. package/lib/view/spendManagement/chargeCards/cardPolicy/createCardPolicy/buildAiCardPolicyFormDraftSeed.js +391 -0
  49. package/lib/view/spendManagement/chargeCards/cardPolicy/createCardPolicy/buildManualCardPolicyFormDraftSeed.d.ts +11 -0
  50. package/lib/view/spendManagement/chargeCards/cardPolicy/createCardPolicy/buildManualCardPolicyFormDraftSeed.js +38 -0
  51. package/lib/view/spendManagement/chargeCards/cardPolicy/createCardPolicy/cardPolicyChipIds.d.ts +24 -0
  52. package/lib/view/spendManagement/chargeCards/cardPolicy/createCardPolicy/cardPolicyChipIds.js +40 -0
  53. package/lib/view/spendManagement/chargeCards/cardPolicy/createCardPolicy/cardPolicyFormDraftTypes.d.ts +253 -0
  54. package/lib/view/spendManagement/chargeCards/cardPolicy/createCardPolicy/cardPolicyFormDraftTypes.js +21 -0
  55. package/lib/view/spendManagement/chargeCards/cardPolicy/createCardPolicy/cardPolicyRequestParts.d.ts +66 -0
  56. package/lib/view/spendManagement/chargeCards/cardPolicy/createCardPolicy/cardPolicyRequestParts.js +151 -0
  57. package/lib/view/spendManagement/chargeCards/cardPolicy/createCardPolicy/createCardPolicyReducer.d.ts +40 -1
  58. package/lib/view/spendManagement/chargeCards/cardPolicy/createCardPolicy/createCardPolicyReducer.js +138 -2
  59. package/lib/view/spendManagement/chargeCards/cardPolicy/createCardPolicy/createCardPolicySelector.d.ts +15 -0
  60. package/lib/view/spendManagement/chargeCards/cardPolicy/createCardPolicy/createCardPolicySelector.js +20 -0
  61. package/lib/view/spendManagement/chargeCards/cardPolicy/createCardPolicy/createCardPolicyState.d.ts +28 -0
  62. package/lib/view/spendManagement/chargeCards/cardPolicy/createCardPolicy/deriveAiPolicyReviewRowsFromInputs.d.ts +30 -0
  63. package/lib/view/spendManagement/chargeCards/cardPolicy/createCardPolicy/deriveAiPolicyReviewRowsFromInputs.js +152 -0
  64. package/lib/view/spendManagement/chargeCards/cardPolicy/createCardPolicy/seedAiCardPolicyFormDraftEpic.d.ts +26 -0
  65. package/lib/view/spendManagement/chargeCards/cardPolicy/createCardPolicy/seedAiCardPolicyFormDraftEpic.js +116 -0
  66. package/lib/view/spendManagement/chargeCards/cardPolicy/createCardPolicy/toBulkCardPolicyTemplateRequestsFromDraft.d.ts +35 -0
  67. package/lib/view/spendManagement/chargeCards/cardPolicy/createCardPolicy/toBulkCardPolicyTemplateRequestsFromDraft.js +105 -0
  68. package/lib/view/spendManagement/chargeCards/cardPolicy/createCardPolicy/toCardPolicyTemplateRequestFromDraft.d.ts +23 -0
  69. package/lib/view/spendManagement/chargeCards/cardPolicy/createCardPolicy/toCardPolicyTemplateRequestFromDraft.js +75 -0
  70. package/lib/view/spendManagement/chargeCards/cardPolicy/createCardPolicy/toManualCardPolicyTemplateRequestFromDraft.d.ts +15 -0
  71. package/lib/view/spendManagement/chargeCards/cardPolicy/createCardPolicy/toManualCardPolicyTemplateRequestFromDraft.js +38 -0
  72. package/lib/view/spendManagement/chargeCards/issueChargeCard/aiCardCreationFormDraftTypes.d.ts +3 -6
  73. package/lib/view/spendManagement/chargeCards/issueChargeCard/applyAiCardCreationFormDraftUpdate.js +0 -1
  74. package/lib/view/spendManagement/chargeCards/issueChargeCard/buildAiCardCreationFormDraftSeed.d.ts +6 -3
  75. package/lib/view/spendManagement/chargeCards/issueChargeCard/buildAiCardCreationFormDraftSeed.js +13 -6
  76. package/lib/view/spendManagement/chargeCards/issueChargeCard/deriveAiCardRowsFromTeams.d.ts +1 -4
  77. package/lib/view/spendManagement/chargeCards/issueChargeCard/deriveAiCardRowsFromTeams.js +1 -3
  78. package/lib/view/spendManagement/chargeCards/issueChargeCard/toIssueChargeCardLocalDataFromDraft.js +0 -5
  79. package/package.json +1 -1
@@ -0,0 +1,25 @@
1
+ import { CardPolicyChipFieldValue, CardPolicyFormDraft, ExtractedCardPolicyDataView } from './cardPolicyFormDraftTypes';
2
+ export interface ApplyExtractedPolicyToAiCardPolicyDraftArgs {
3
+ /** Category universe the chip picker can offer (search dropdown contents). */
4
+ categorySearchOptions: CardPolicyChipFieldValue[];
5
+ /** Current draft — preserved for slices the response does not cover. */
6
+ current: CardPolicyFormDraft;
7
+ /** The extracted rules returned by the cards micro-service. */
8
+ extracted: ExtractedCardPolicyDataView;
9
+ /** Vendor universe the chip picker can offer. */
10
+ vendorSearchOptions: CardPolicyChipFieldValue[];
11
+ }
12
+ /**
13
+ * Apply an extracted policy document response to the AI CFO card-policy
14
+ * draft. Touches only the slices the extract API populates:
15
+ * - `vendorPolicy` from allow/block `merchantNames` (with allow-wins
16
+ * flip).
17
+ * - `categoryPolicy` from allow/block `categoryCodes` (matched on
18
+ * `optionalCode`).
19
+ * - `limits` rows from `transactionLimit` / `requiredReceiptThreshold`.
20
+ *
21
+ * `cardSelections` and `policiesReview` are preserved verbatim — the
22
+ * user still picks cards on Step 2 and the review step is seeded
23
+ * separately.
24
+ */
25
+ export declare const applyExtractedPolicyToAiCardPolicyDraft: ({ extracted, current, vendorSearchOptions, categorySearchOptions, }: ApplyExtractedPolicyToAiCardPolicyDraftArgs) => CardPolicyFormDraft;
@@ -0,0 +1,124 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.applyExtractedPolicyToAiCardPolicyDraft = void 0;
4
+ const cardPolicyChipIds_1 = require("./cardPolicyChipIds");
5
+ const cardPolicyFormDraftTypes_1 = require("./cardPolicyFormDraftTypes");
6
+ /**
7
+ * Apply an extracted policy document response to the AI CFO card-policy
8
+ * draft. Touches only the slices the extract API populates:
9
+ * - `vendorPolicy` from allow/block `merchantNames` (with allow-wins
10
+ * flip).
11
+ * - `categoryPolicy` from allow/block `categoryCodes` (matched on
12
+ * `optionalCode`).
13
+ * - `limits` rows from `transactionLimit` / `requiredReceiptThreshold`.
14
+ *
15
+ * `cardSelections` and `policiesReview` are preserved verbatim — the
16
+ * user still picks cards on Step 2 and the review step is seeded
17
+ * separately.
18
+ */
19
+ const applyExtractedPolicyToAiCardPolicyDraft = ({ extracted, current, vendorSearchOptions, categorySearchOptions, }) => ({
20
+ ...current,
21
+ vendorPolicy: buildAllowBlockField({
22
+ allowList: extracted.allowedEntity.merchantNames,
23
+ blockList: extracted.blockedEntity.merchantNames,
24
+ currentAllowItems: current.vendorPolicy.allowItems,
25
+ currentBlockItems: current.vendorPolicy.blockItems,
26
+ universe: vendorSearchOptions,
27
+ matchOnCode: false,
28
+ }),
29
+ categoryPolicy: buildAllowBlockField({
30
+ allowList: extracted.allowedEntity.categoryCodes,
31
+ blockList: extracted.blockedEntity.categoryCodes,
32
+ currentAllowItems: current.categoryPolicy.allowItems,
33
+ currentBlockItems: current.categoryPolicy.blockItems,
34
+ universe: categorySearchOptions,
35
+ matchOnCode: true,
36
+ }),
37
+ limits: buildLimitRows({
38
+ current: current.limits,
39
+ transactionLimit: extracted.transactionLimit,
40
+ requiredReceiptThreshold: extracted.requiredReceiptThreshold,
41
+ }),
42
+ });
43
+ exports.applyExtractedPolicyToAiCardPolicyDraft = applyExtractedPolicyToAiCardPolicyDraft;
44
+ const buildAllowBlockField = ({ allowList, blockList, currentAllowItems, currentBlockItems, universe, matchOnCode, }) => {
45
+ const allowItems = buildSideItems({
46
+ selectedValues: allowList,
47
+ currentItems: currentAllowItems,
48
+ universe,
49
+ matchOnCode,
50
+ });
51
+ const blockItems = buildSideItems({
52
+ selectedValues: blockList,
53
+ currentItems: currentBlockItems,
54
+ universe,
55
+ matchOnCode,
56
+ });
57
+ const mode = allowList.length === 0 && blockList.length > 0 ? 'block' : 'allow';
58
+ return { mode, allowItems, blockItems };
59
+ };
60
+ const buildSideItems = ({ selectedValues, currentItems, universe, matchOnCode, }) => {
61
+ const selectedKeys = new Set(selectedValues
62
+ .map((value) => normalizeKey(value))
63
+ .filter((key) => key != null));
64
+ const items = [];
65
+ const seenIds = new Set();
66
+ for (const item of currentItems) {
67
+ const key = normalizeKey(matchOnCode ? item.optionalCode : item.label);
68
+ const isSelected = key != null && selectedKeys.has(key);
69
+ items.push({ ...item, isSelected });
70
+ seenIds.add(item.id);
71
+ if (isSelected && key != null) {
72
+ selectedKeys.delete(key);
73
+ }
74
+ }
75
+ for (const option of universe) {
76
+ if (selectedKeys.size === 0) {
77
+ break;
78
+ }
79
+ const key = normalizeKey(matchOnCode ? option.optionalCode : option.label);
80
+ if (key == null || !selectedKeys.has(key) || seenIds.has(option.id)) {
81
+ continue;
82
+ }
83
+ items.push({ ...option, isSelected: true });
84
+ seenIds.add(option.id);
85
+ selectedKeys.delete(key);
86
+ }
87
+ for (const value of selectedValues) {
88
+ const key = normalizeKey(value);
89
+ if (key == null || !selectedKeys.has(key)) {
90
+ continue;
91
+ }
92
+ const id = matchOnCode
93
+ ? (0, cardPolicyChipIds_1.buildMccCategoryChipId)(value)
94
+ : (0, cardPolicyChipIds_1.buildVendorChipId)(value);
95
+ if (seenIds.has(id)) {
96
+ continue;
97
+ }
98
+ items.push({
99
+ id,
100
+ label: value,
101
+ isSelected: true,
102
+ ...(matchOnCode ? { optionalCode: value } : {}),
103
+ });
104
+ seenIds.add(id);
105
+ selectedKeys.delete(key);
106
+ }
107
+ return items;
108
+ };
109
+ const buildLimitRows = ({ current, transactionLimit, requiredReceiptThreshold, }) => current.map((row) => {
110
+ if (row.id === cardPolicyFormDraftTypes_1.CARD_POLICY_LIMIT_ROW_ID_TRANSACTION) {
111
+ return amountToLimitRow(row, transactionLimit);
112
+ }
113
+ if (row.id === cardPolicyFormDraftTypes_1.CARD_POLICY_LIMIT_ROW_ID_REQUIRE_RECEIPT) {
114
+ return amountToLimitRow(row, requiredReceiptThreshold);
115
+ }
116
+ return row;
117
+ });
118
+ const amountToLimitRow = (row, amount) => {
119
+ if (amount > 0) {
120
+ return { ...row, isEnabled: true, amount };
121
+ }
122
+ return { ...row, isEnabled: false, amount: row.amount };
123
+ };
124
+ const normalizeKey = (value) => value == null || value.length === 0 ? undefined : value.toLowerCase().trim();
@@ -0,0 +1,28 @@
1
+ import { ActionsObservable, StateObservable } from 'redux-observable';
2
+ import { Observable } from 'rxjs';
3
+ import { updatePolicyDocumentExtractionSuccess } from '../../../../../entity/cardPolicy/cardPolicyReducer';
4
+ import { RootState } from '../../../../../reducer';
5
+ import { applyExtractedPolicyToAiCardPolicyDraft, applyExtractedPolicyToManualCardPolicyDraft } from './createCardPolicyReducer';
6
+ export type ActionType = ReturnType<typeof applyExtractedPolicyToAiCardPolicyDraft> | ReturnType<typeof applyExtractedPolicyToManualCardPolicyDraft>;
7
+ type InboundAction = ReturnType<typeof updatePolicyDocumentExtractionSuccess>;
8
+ /**
9
+ * Bridge epic — fans `updatePolicyDocumentExtractionSuccess` out to the
10
+ * right card-policy form draft based on which surface kicked the upload
11
+ * off:
12
+ *
13
+ * - `aiCfoAnswerId != null` → the AI CFO upload-mode wizard owns it;
14
+ * dispatch `applyExtractedPolicyToAiCardPolicyDraft` so the AI draft
15
+ * picks up the extracted allow/block + limits. The wizard's `step_5`
16
+ * review chips are separately patched by
17
+ * `policyRecommendationFromUploadEpic` (the second hop in the chain).
18
+ * - `aiCfoAnswerId == null` → the manual `CardPolicyCreatePage` owns
19
+ * it; dispatch `applyExtractedPolicyToManualCardPolicyDraft` so the
20
+ * manual draft picks up name + allow/block + limits.
21
+ *
22
+ * The bridge reads vendor + category universes off CES
23
+ * (`cardPolicyState.vendorSearch.vendors`,
24
+ * `cardPolicyState.mccCategories`) instead of taking them through the
25
+ * payload, so any caller that drops the action wires up automatically.
26
+ */
27
+ export declare const applyExtractedPolicyToDraftEpic: (actions$: ActionsObservable<InboundAction>, state$: StateObservable<RootState>) => Observable<ActionType>;
28
+ export {};
@@ -0,0 +1,64 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.applyExtractedPolicyToDraftEpic = void 0;
4
+ const rxjs_1 = require("rxjs");
5
+ const operators_1 = require("rxjs/operators");
6
+ const cardPolicyReducer_1 = require("../../../../../entity/cardPolicy/cardPolicyReducer");
7
+ const cardPolicyChipIds_1 = require("./cardPolicyChipIds");
8
+ const cardPolicyFormDraftTypes_1 = require("./cardPolicyFormDraftTypes");
9
+ const createCardPolicyReducer_1 = require("./createCardPolicyReducer");
10
+ const toExtractedView = (rules) => ({
11
+ allowedEntity: {
12
+ categoryCodes: rules.allowedEntity.categoryCodes ?? [],
13
+ merchantNames: rules.allowedEntity.merchantNames ?? [],
14
+ },
15
+ blockedEntity: {
16
+ categoryCodes: rules.blockedEntity.categoryCodes ?? [],
17
+ merchantNames: rules.blockedEntity.merchantNames ?? [],
18
+ },
19
+ confidenceScore: rules.confidenceScore,
20
+ policyName: rules.policyName,
21
+ requiredReceiptThreshold: rules.requiredReceiptThreshold,
22
+ transactionLimit: rules.transactionLimit,
23
+ });
24
+ const readVendorSearchOptions = (state) => state.cardPolicyState.vendorSearch.vendors.map((vendor) => (0, cardPolicyChipIds_1.toVendorChipFieldValue)(vendor.name, false));
25
+ const readCategorySearchOptions = (state) => state.cardPolicyState.mccCategories.map((category) => (0, cardPolicyChipIds_1.toMccCategoryChipFieldValue)((0, cardPolicyFormDraftTypes_1.toMccCategoryLike)(category), false));
26
+ /**
27
+ * Bridge epic — fans `updatePolicyDocumentExtractionSuccess` out to the
28
+ * right card-policy form draft based on which surface kicked the upload
29
+ * off:
30
+ *
31
+ * - `aiCfoAnswerId != null` → the AI CFO upload-mode wizard owns it;
32
+ * dispatch `applyExtractedPolicyToAiCardPolicyDraft` so the AI draft
33
+ * picks up the extracted allow/block + limits. The wizard's `step_5`
34
+ * review chips are separately patched by
35
+ * `policyRecommendationFromUploadEpic` (the second hop in the chain).
36
+ * - `aiCfoAnswerId == null` → the manual `CardPolicyCreatePage` owns
37
+ * it; dispatch `applyExtractedPolicyToManualCardPolicyDraft` so the
38
+ * manual draft picks up name + allow/block + limits.
39
+ *
40
+ * The bridge reads vendor + category universes off CES
41
+ * (`cardPolicyState.vendorSearch.vendors`,
42
+ * `cardPolicyState.mccCategories`) instead of taking them through the
43
+ * payload, so any caller that drops the action wires up automatically.
44
+ */
45
+ const applyExtractedPolicyToDraftEpic = (actions$, state$) => actions$.pipe((0, operators_1.mergeMap)((action) => {
46
+ if (!cardPolicyReducer_1.updatePolicyDocumentExtractionSuccess.match(action)) {
47
+ return rxjs_1.EMPTY;
48
+ }
49
+ const state = state$.value;
50
+ const extraction = state.cardPolicyState.policyDocumentExtraction;
51
+ const rules = extraction.extractedRules;
52
+ if (rules == null) {
53
+ return rxjs_1.EMPTY;
54
+ }
55
+ const extracted = toExtractedView(rules);
56
+ const vendorSearchOptions = readVendorSearchOptions(state);
57
+ const categorySearchOptions = readCategorySearchOptions(state);
58
+ const payload = { extracted, vendorSearchOptions, categorySearchOptions };
59
+ if (extraction.aiCfoAnswerId != null) {
60
+ return (0, rxjs_1.of)((0, createCardPolicyReducer_1.applyExtractedPolicyToAiCardPolicyDraft)(payload));
61
+ }
62
+ return (0, rxjs_1.of)((0, createCardPolicyReducer_1.applyExtractedPolicyToManualCardPolicyDraft)(payload));
63
+ }));
64
+ exports.applyExtractedPolicyToDraftEpic = applyExtractedPolicyToDraftEpic;
@@ -0,0 +1,17 @@
1
+ import { CardPolicyChipFieldValue, CardPolicyCreateFormDraft, ExtractedCardPolicyDataView } from './cardPolicyFormDraftTypes';
2
+ export interface ApplyExtractedPolicyToManualCardPolicyDraftArgs {
3
+ categorySearchOptions: CardPolicyChipFieldValue[];
4
+ current: CardPolicyCreateFormDraft;
5
+ extracted: ExtractedCardPolicyDataView;
6
+ vendorSearchOptions: CardPolicyChipFieldValue[];
7
+ }
8
+ /**
9
+ * Apply an extracted policy document response to the manual
10
+ * `CardPolicyCreatePage` draft. Mirrors the AI variant plus:
11
+ * - `name` is overwritten with `extracted.policyName` when present.
12
+ * - `description` is left as-is (the extract API doesn't return one).
13
+ * - `mode` and `cardSelections` are preserved.
14
+ *
15
+ * Pure / referentially transparent.
16
+ */
17
+ export declare const applyExtractedPolicyToManualCardPolicyDraft: ({ extracted, current, vendorSearchOptions, categorySearchOptions, }: ApplyExtractedPolicyToManualCardPolicyDraftArgs) => CardPolicyCreateFormDraft;
@@ -0,0 +1,122 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.applyExtractedPolicyToManualCardPolicyDraft = void 0;
4
+ const cardPolicyChipIds_1 = require("./cardPolicyChipIds");
5
+ const cardPolicyFormDraftTypes_1 = require("./cardPolicyFormDraftTypes");
6
+ /**
7
+ * Apply an extracted policy document response to the manual
8
+ * `CardPolicyCreatePage` draft. Mirrors the AI variant plus:
9
+ * - `name` is overwritten with `extracted.policyName` when present.
10
+ * - `description` is left as-is (the extract API doesn't return one).
11
+ * - `mode` and `cardSelections` are preserved.
12
+ *
13
+ * Pure / referentially transparent.
14
+ */
15
+ const applyExtractedPolicyToManualCardPolicyDraft = ({ extracted, current, vendorSearchOptions, categorySearchOptions, }) => ({
16
+ ...current,
17
+ name: extracted.policyName ?? current.name,
18
+ description: current.description,
19
+ vendorPolicy: buildAllowBlockField({
20
+ allowList: extracted.allowedEntity.merchantNames,
21
+ blockList: extracted.blockedEntity.merchantNames,
22
+ currentAllowItems: current.vendorPolicy.allowItems,
23
+ currentBlockItems: current.vendorPolicy.blockItems,
24
+ universe: vendorSearchOptions,
25
+ matchOnCode: false,
26
+ }),
27
+ categoryPolicy: buildAllowBlockField({
28
+ allowList: extracted.allowedEntity.categoryCodes,
29
+ blockList: extracted.blockedEntity.categoryCodes,
30
+ currentAllowItems: current.categoryPolicy.allowItems,
31
+ currentBlockItems: current.categoryPolicy.blockItems,
32
+ universe: categorySearchOptions,
33
+ matchOnCode: true,
34
+ }),
35
+ limits: buildLimitRows({
36
+ current: current.limits,
37
+ transactionLimit: extracted.transactionLimit,
38
+ requiredReceiptThreshold: extracted.requiredReceiptThreshold,
39
+ }),
40
+ });
41
+ exports.applyExtractedPolicyToManualCardPolicyDraft = applyExtractedPolicyToManualCardPolicyDraft;
42
+ const buildAllowBlockField = ({ allowList, blockList, currentAllowItems, currentBlockItems, universe, matchOnCode, }) => {
43
+ const allowItems = buildSideItems({
44
+ selectedValues: allowList,
45
+ currentItems: currentAllowItems,
46
+ universe,
47
+ matchOnCode,
48
+ });
49
+ const blockItems = buildSideItems({
50
+ selectedValues: blockList,
51
+ currentItems: currentBlockItems,
52
+ universe,
53
+ matchOnCode,
54
+ });
55
+ const mode = allowList.length === 0 && blockList.length > 0 ? 'block' : 'allow';
56
+ return { mode, allowItems, blockItems };
57
+ };
58
+ const buildSideItems = ({ selectedValues, currentItems, universe, matchOnCode, }) => {
59
+ const selectedKeys = new Set(selectedValues
60
+ .map((value) => normalizeKey(value))
61
+ .filter((key) => key != null));
62
+ const items = [];
63
+ const seenIds = new Set();
64
+ for (const item of currentItems) {
65
+ const key = normalizeKey(matchOnCode ? item.optionalCode : item.label);
66
+ const isSelected = key != null && selectedKeys.has(key);
67
+ items.push({ ...item, isSelected });
68
+ seenIds.add(item.id);
69
+ if (isSelected && key != null) {
70
+ selectedKeys.delete(key);
71
+ }
72
+ }
73
+ for (const option of universe) {
74
+ if (selectedKeys.size === 0) {
75
+ break;
76
+ }
77
+ const key = normalizeKey(matchOnCode ? option.optionalCode : option.label);
78
+ if (key == null || !selectedKeys.has(key) || seenIds.has(option.id)) {
79
+ continue;
80
+ }
81
+ items.push({ ...option, isSelected: true });
82
+ seenIds.add(option.id);
83
+ selectedKeys.delete(key);
84
+ }
85
+ for (const value of selectedValues) {
86
+ const key = normalizeKey(value);
87
+ if (key == null || !selectedKeys.has(key)) {
88
+ continue;
89
+ }
90
+ const id = matchOnCode
91
+ ? (0, cardPolicyChipIds_1.buildMccCategoryChipId)(value)
92
+ : (0, cardPolicyChipIds_1.buildVendorChipId)(value);
93
+ if (seenIds.has(id)) {
94
+ continue;
95
+ }
96
+ items.push({
97
+ id,
98
+ label: value,
99
+ isSelected: true,
100
+ ...(matchOnCode ? { optionalCode: value } : {}),
101
+ });
102
+ seenIds.add(id);
103
+ selectedKeys.delete(key);
104
+ }
105
+ return items;
106
+ };
107
+ const buildLimitRows = ({ current, transactionLimit, requiredReceiptThreshold, }) => current.map((row) => {
108
+ if (row.id === cardPolicyFormDraftTypes_1.CARD_POLICY_LIMIT_ROW_ID_TRANSACTION) {
109
+ return amountToLimitRow(row, transactionLimit);
110
+ }
111
+ if (row.id === cardPolicyFormDraftTypes_1.CARD_POLICY_LIMIT_ROW_ID_REQUIRE_RECEIPT) {
112
+ return amountToLimitRow(row, requiredReceiptThreshold);
113
+ }
114
+ return row;
115
+ });
116
+ const amountToLimitRow = (row, amount) => {
117
+ if (amount > 0) {
118
+ return { ...row, isEnabled: true, amount };
119
+ }
120
+ return { ...row, isEnabled: false, amount: row.amount };
121
+ };
122
+ const normalizeKey = (value) => value == null || value.length === 0 ? undefined : value.toLowerCase().trim();
@@ -0,0 +1,23 @@
1
+ import { CardPolicyUploadSource, CardPolicyWizardPlan } from '../../../../../entity/aiCfo/aiCfoState';
2
+ import { AiCardPolicyFormDraftSeedContext, CardPolicyFormDraft } from './cardPolicyFormDraftTypes';
3
+ export interface ApplyUploadPlanToAiCardPolicyDraftArgs {
4
+ context: AiCardPolicyFormDraftSeedContext;
5
+ current: CardPolicyFormDraft;
6
+ wizardPlan: CardPolicyWizardPlan;
7
+ source?: CardPolicyUploadSource;
8
+ }
9
+ export interface ApplyUploadPlanToAiCardPolicyDraftResult {
10
+ context: AiCardPolicyFormDraftSeedContext;
11
+ draft: CardPolicyFormDraft;
12
+ }
13
+ /**
14
+ * Patch a fresh `wizardPlan` (returned by
15
+ * `policy-recommendation-from-upload`) onto the upload-mode AI
16
+ * card-policy draft + context. Re-derives the Step 5 review rows from
17
+ * the new draft policies while preserving the user's Step 2
18
+ * `cardSelections` and Step 1 `limits` toggles.
19
+ *
20
+ * No-op when the draft isn't in `upload` mode (the bridge epic should
21
+ * still gate on `policyKind === "upload"` upstream).
22
+ */
23
+ export declare const applyUploadPlanToAiCardPolicyDraft: ({ current, context, wizardPlan, source, }: ApplyUploadPlanToAiCardPolicyDraftArgs) => ApplyUploadPlanToAiCardPolicyDraftResult;
@@ -0,0 +1,37 @@
1
+ "use strict";
2
+ Object.defineProperty(exports, "__esModule", { value: true });
3
+ exports.applyUploadPlanToAiCardPolicyDraft = void 0;
4
+ const buildAiCardPolicyFormDraftSeed_1 = require("./buildAiCardPolicyFormDraftSeed");
5
+ /**
6
+ * Patch a fresh `wizardPlan` (returned by
7
+ * `policy-recommendation-from-upload`) onto the upload-mode AI
8
+ * card-policy draft + context. Re-derives the Step 5 review rows from
9
+ * the new draft policies while preserving the user's Step 2
10
+ * `cardSelections` and Step 1 `limits` toggles.
11
+ *
12
+ * No-op when the draft isn't in `upload` mode (the bridge epic should
13
+ * still gate on `policyKind === "upload"` upstream).
14
+ */
15
+ const applyUploadPlanToAiCardPolicyDraft = ({ current, context, wizardPlan, source, }) => {
16
+ if (current.policyKind !== 'upload') {
17
+ return { draft: current, context };
18
+ }
19
+ const policiesReview = (0, buildAiCardPolicyFormDraftSeed_1.buildUploadReviewRows)(wizardPlan.step5Review.draftPolicies, context.cardsMasterList, context.categorySearchOptions);
20
+ return {
21
+ draft: {
22
+ ...current,
23
+ policiesReview,
24
+ },
25
+ context: {
26
+ ...context,
27
+ wizardPlan,
28
+ source: source ?? context.source,
29
+ suggestedPoliciesSeed: wizardPlan.step5Review.draftPolicies.map((draft) => ({
30
+ id: draft.id,
31
+ name: draft.name,
32
+ isChecked: true,
33
+ })),
34
+ },
35
+ };
36
+ };
37
+ exports.applyUploadPlanToAiCardPolicyDraft = applyUploadPlanToAiCardPolicyDraft;
@@ -0,0 +1,38 @@
1
+ import { CardPolicyDraftPolicy, CardPolicyInitialData } from '../../../../../entity/aiCfo/aiCfoState';
2
+ import { AiCardPolicyFormDraftSeedContext, CardPolicyCardSelectionRow, CardPolicyDefaultSeedSuggestions, CardPolicyFormDraft, CardPolicyLimitFieldValue, CardPolicyReviewRow, MccCategoryLike } from './cardPolicyFormDraftTypes';
3
+ export interface BuildAiCardPolicyFormDraftSeedArgs extends CardPolicyDefaultSeedSuggestions {
4
+ initialData: CardPolicyInitialData;
5
+ /**
6
+ * Tenant-wide card master list. Used by both `guided` (Step 3 row
7
+ * universe) and `auto` / `upload` (resolving avatar chips' display
8
+ * names from `applyToCards` IDs).
9
+ */
10
+ cardsMasterList?: CardPolicyCardSelectionRow[];
11
+ /**
12
+ * MCC category lookup used to resolve BE-shipped `category_codes`
13
+ * (e.g. `"6051"`) into human labels (e.g. `"Cryptocurrency"`) for
14
+ * the review chips and the Step-2 seed.
15
+ */
16
+ categorySearchOptions?: MccCategoryLike[];
17
+ }
18
+ export interface BuildAiCardPolicyFormDraftSeedResult {
19
+ context: AiCardPolicyFormDraftSeedContext;
20
+ draft: CardPolicyFormDraft;
21
+ }
22
+ export declare const buildEmptyLimitRows: () => CardPolicyLimitFieldValue[];
23
+ /**
24
+ * Build the initial `CardPolicyFormDraft` + companion seed context for
25
+ * a fresh AI CFO card-policy session. Used by the
26
+ * `seedAiCardPolicyFormDraft` reducer.
27
+ *
28
+ * - `auto` (1-step review): chip groups are built eagerly from each
29
+ * `draftPolicies[i]` since there's no live form to derive from.
30
+ * - `guided` (5-step wizard): Steps 1–4 seeded from `draftPolicies[0]`,
31
+ * Step 5 seeded with one identity-only row per `draftPolicies[i]`;
32
+ * chip groups are re-derived on every `applyAiCardPolicyFormDraftUpdate`.
33
+ * - `upload` (3-step): pre-recommendation returns an empty scaffold;
34
+ * post-recommendation, Step 5 review rows + their chip groups are
35
+ * derived from `wizardPlan.step5Review.draftPolicies`.
36
+ */
37
+ export declare const buildAiCardPolicyFormDraftSeed: ({ initialData, cardsMasterList, categorySearchOptions, suggestedAllowMerchants, suggestedBlockMerchants, suggestedAllowCategories, suggestedBlockCategories, }: BuildAiCardPolicyFormDraftSeedArgs) => BuildAiCardPolicyFormDraftSeedResult;
38
+ export declare const buildUploadReviewRows: (draftPolicies: CardPolicyDraftPolicy[], cardsMasterList: CardPolicyCardSelectionRow[], categorySearchOptions: MccCategoryLike[] | undefined) => CardPolicyReviewRow[];