@zeniai/client-epic-state 5.2.29 → 5.2.30-betaRD0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/lib/entity/aiCfo/aiCfoPayload.d.ts +21 -0
- package/lib/entity/aiCfo/aiCfoReducer.js +73 -1
- package/lib/entity/aiCfo/aiCfoState.d.ts +24 -0
- package/lib/entity/file/fileState.d.ts +3 -3
- package/lib/entity/file/fileState.js +2 -0
- package/lib/entity/invoicing/creditNote/creditNotePayload.d.ts +0 -1
- package/lib/entity/invoicing/creditNote/creditNotePayload.js +0 -1
- package/lib/entity/invoicing/creditNote/creditNoteState.d.ts +0 -1
- package/lib/entity/invoicing/invoice/invoicePayload.d.ts +0 -1
- package/lib/entity/invoicing/invoice/invoicePayload.js +0 -1
- package/lib/entity/invoicing/invoice/invoiceState.d.ts +0 -1
- package/lib/entity/invoicing/invoicingCommonPayload.d.ts +2 -0
- package/lib/entity/invoicing/invoicingCustomer/invoicingCustomerPayload.d.ts +0 -1
- package/lib/entity/invoicing/invoicingCustomer/invoicingCustomerPayload.js +0 -1
- package/lib/entity/invoicing/invoicingCustomer/invoicingCustomerState.d.ts +0 -1
- package/lib/entity/invoicing/invoicingSubscription/invoicingSubscriptionPayload.d.ts +1 -2
- package/lib/entity/invoicing/invoicingSubscription/invoicingSubscriptionPayload.js +1 -2
- package/lib/entity/invoicing/invoicingSubscription/invoicingSubscriptionState.d.ts +1 -2
- package/lib/epic.d.ts +2 -1
- package/lib/epic.js +2 -0
- package/lib/esm/entity/aiCfo/aiCfoReducer.js +73 -1
- package/lib/esm/entity/file/fileState.js +2 -0
- package/lib/esm/entity/invoicing/creditNote/creditNotePayload.js +0 -1
- package/lib/esm/entity/invoicing/invoice/invoicePayload.js +0 -1
- package/lib/esm/entity/invoicing/invoicingCustomer/invoicingCustomerPayload.js +0 -1
- package/lib/esm/entity/invoicing/invoicingSubscription/invoicingSubscriptionPayload.js +1 -2
- package/lib/esm/epic.js +2 -0
- package/lib/esm/index.js +2 -2
- package/lib/esm/view/aiCfoView/aiCfoViewReducer.js +5 -0
- package/lib/esm/view/aiCfoView/aiCfoViewSelector.js +1 -0
- package/lib/esm/view/expenseAutomationView/epics/jeSchedule/fetchJeSchedulesEpic.js +29 -11
- package/lib/esm/view/expenseAutomationView/selectors/jeSchedulesViewSelector.js +4 -2
- package/lib/esm/view/invoicing/couponView/couponViewState.js +4 -4
- package/lib/esm/view/invoicing/dataImportView/dataImportViewSelector.js +2 -0
- package/lib/esm/view/invoicing/invoicingCatalogListView/invoicingCatalogListViewSelector.js +1 -0
- package/lib/esm/view/invoicing/invoicingConfigView/invoicingConfigViewReducer.js +2 -0
- package/lib/esm/view/invoicing/invoicingCustomerListView/invoicingCustomerListViewState.js +3 -3
- package/lib/esm/view/invoicing/invoicingDunningCaseListView/invoicingDunningCaseListViewState.js +4 -4
- package/lib/esm/view/invoicing/invoicingOverview/invoicingOverviewPayload.js +0 -1
- package/lib/esm/view/invoicing/invoicingSubscriptionDetailView/invoicingSubscriptionDetailViewSelector.js +2 -1
- package/lib/esm/view/invoicing/invoicingSubscriptionListView/invoicingSubscriptionListViewSelector.js +1 -0
- package/lib/esm/view/invoicing/invoicingSubscriptionListView/invoicingSubscriptionListViewState.js +0 -2
- package/lib/esm/view/invoicing/settingsView/invoicingBrandingFormConfig.js +5 -0
- package/lib/esm/view/invoicing/settingsView/settingsViewSelector.js +5 -1
- package/lib/esm/view/recommendation/recommendationReducer.js +13 -1
- package/lib/esm/view/recommendation/submitRecommendationFeedbackEpic.js +52 -0
- package/lib/esm/view/spendManagement/billPay/billPaySetupApproverView/epic/fetchBillPaySetupApproverViewEpic.js +18 -2
- package/lib/esm/view/spendManagement/billPay/billPaySetupApproverView/epic/initializeBillPaySetupApproverViewUpdateDataEpic.js +0 -1
- package/lib/esm/view/spendManagement/billPay/billPaySetupApproverView/types/commonPayload.js +0 -3
- package/lib/esm/view/spendManagement/reimbursement/remiSetupApproverView/epic/fetchRemiSetupApproverViewEpic.js +18 -2
- package/lib/esm/view/spendManagement/reimbursement/remiSetupApproverView/epic/initializeRemiSetupApproverViewUpdateDataEpic.js +0 -1
- package/lib/index.d.ts +7 -5
- package/lib/index.js +24 -23
- package/lib/view/aiCfoView/aiCfoViewReducer.js +5 -0
- package/lib/view/aiCfoView/aiCfoViewSelector.js +1 -0
- package/lib/view/aiCfoView/aiCfoViewState.d.ts +7 -0
- package/lib/view/expenseAutomationView/epics/jeSchedule/fetchJeSchedulesEpic.js +29 -11
- package/lib/view/expenseAutomationView/selectorTypes/jeSchedulesSelectorTypes.d.ts +5 -3
- package/lib/view/expenseAutomationView/selectors/jeSchedulesViewSelector.d.ts +2 -5
- package/lib/view/expenseAutomationView/selectors/jeSchedulesViewSelector.js +4 -2
- package/lib/view/invoicing/couponView/couponViewState.d.ts +2 -2
- package/lib/view/invoicing/couponView/couponViewState.js +4 -4
- package/lib/view/invoicing/dataImportView/dataImportViewSelector.d.ts +2 -0
- package/lib/view/invoicing/dataImportView/dataImportViewSelector.js +2 -0
- package/lib/view/invoicing/invoicingCatalogListView/invoicingCatalogListViewSelector.d.ts +1 -0
- package/lib/view/invoicing/invoicingCatalogListView/invoicingCatalogListViewSelector.js +1 -0
- package/lib/view/invoicing/invoicingConfigView/invoicingConfigViewPayload.d.ts +1 -0
- package/lib/view/invoicing/invoicingConfigView/invoicingConfigViewReducer.d.ts +1 -1
- package/lib/view/invoicing/invoicingConfigView/invoicingConfigViewReducer.js +2 -0
- package/lib/view/invoicing/invoicingConfigView/invoicingConfigViewState.d.ts +1 -0
- package/lib/view/invoicing/invoicingCustomerListView/invoicingCustomerListViewState.d.ts +2 -2
- package/lib/view/invoicing/invoicingCustomerListView/invoicingCustomerListViewState.js +3 -3
- package/lib/view/invoicing/invoicingDunningCaseListView/invoicingDunningCaseListViewState.d.ts +2 -2
- package/lib/view/invoicing/invoicingDunningCaseListView/invoicingDunningCaseListViewState.js +4 -4
- package/lib/view/invoicing/invoicingOverview/invoicingOverviewPayload.d.ts +0 -1
- package/lib/view/invoicing/invoicingOverview/invoicingOverviewPayload.js +0 -1
- package/lib/view/invoicing/invoicingOverview/invoicingOverviewState.d.ts +0 -1
- package/lib/view/invoicing/invoicingSubscriptionDetailView/invoicingSubscriptionDetailViewSelector.d.ts +3 -1
- package/lib/view/invoicing/invoicingSubscriptionDetailView/invoicingSubscriptionDetailViewSelector.js +1 -0
- package/lib/view/invoicing/invoicingSubscriptionListView/invoicingSubscriptionListViewSelector.d.ts +2 -0
- package/lib/view/invoicing/invoicingSubscriptionListView/invoicingSubscriptionListViewSelector.js +1 -0
- package/lib/view/invoicing/invoicingSubscriptionListView/invoicingSubscriptionListViewState.d.ts +2 -2
- package/lib/view/invoicing/invoicingSubscriptionListView/invoicingSubscriptionListViewState.js +0 -2
- package/lib/view/invoicing/issueCreditNote/issueCreditNotePayload.d.ts +0 -1
- package/lib/view/invoicing/settingsView/invoicingBrandingFormConfig.d.ts +1 -0
- package/lib/view/invoicing/settingsView/invoicingBrandingFormConfig.js +5 -0
- package/lib/view/invoicing/settingsView/settingsViewSelector.d.ts +5 -1
- package/lib/view/invoicing/settingsView/settingsViewSelector.js +4 -0
- package/lib/view/invoicing/subscriptionAction/subscriptionActionRequestPayload.d.ts +8 -0
- package/lib/view/recommendation/recommendationPayload.d.ts +34 -0
- package/lib/view/recommendation/recommendationReducer.d.ts +2 -1
- package/lib/view/recommendation/recommendationReducer.js +14 -2
- package/lib/view/recommendation/submitRecommendationFeedbackEpic.d.ts +7 -0
- package/lib/view/recommendation/submitRecommendationFeedbackEpic.js +56 -0
- package/lib/view/spendManagement/billPay/billPaySetupApproverView/epic/fetchBillPaySetupApproverViewEpic.d.ts +2 -1
- package/lib/view/spendManagement/billPay/billPaySetupApproverView/epic/fetchBillPaySetupApproverViewEpic.js +18 -2
- package/lib/view/spendManagement/billPay/billPaySetupApproverView/epic/initializeBillPaySetupApproverViewUpdateDataEpic.js +0 -1
- package/lib/view/spendManagement/billPay/billPaySetupApproverView/types/commonPayload.d.ts +0 -1
- package/lib/view/spendManagement/billPay/billPaySetupApproverView/types/commonPayload.js +0 -3
- package/lib/view/spendManagement/billPay/billPaySetupApproverView/types/commonState.d.ts +0 -1
- package/lib/view/spendManagement/commonHistoryView/commonHistory.d.ts +1 -1
- package/lib/view/spendManagement/reimbursement/remiSetupApproverView/epic/fetchRemiSetupApproverViewEpic.d.ts +2 -1
- package/lib/view/spendManagement/reimbursement/remiSetupApproverView/epic/fetchRemiSetupApproverViewEpic.js +18 -2
- package/lib/view/spendManagement/reimbursement/remiSetupApproverView/epic/initializeRemiSetupApproverViewUpdateDataEpic.js +0 -1
- package/package.json +1 -1
|
@@ -110,6 +110,7 @@ function chatHistoryToQA(history) {
|
|
|
110
110
|
? parsedAgentMessage.follow_up_questions
|
|
111
111
|
: [],
|
|
112
112
|
suggestedReply: parsedAgentMessage.suggested_reply ?? undefined,
|
|
113
|
+
capabilityPromo: toCapabilityPromo(parsedAgentMessage.capability_promo),
|
|
113
114
|
assumptions: parsedAgentMessage.assumptions ?? '',
|
|
114
115
|
insights: parsedAgentMessage.insights ?? '',
|
|
115
116
|
summarizedTitle: parsedAgentMessage.summarized_title ?? undefined,
|
|
@@ -118,6 +119,7 @@ function chatHistoryToQA(history) {
|
|
|
118
119
|
artifactTitle: parsedAgentMessage.artifact_title ?? undefined,
|
|
119
120
|
artifactHostUrl: parsedAgentMessage.artifact_host_url ?? undefined,
|
|
120
121
|
exports: toAiCfoExports(parsedAgentMessage.exports),
|
|
122
|
+
skillDraft: toSkillDraft(parsedAgentMessage.skill_draft),
|
|
121
123
|
},
|
|
122
124
|
createdAt: zeniDate(agentMessage.created_at),
|
|
123
125
|
};
|
|
@@ -368,8 +370,76 @@ const toAiCfoVisualizationData = (data) => {
|
|
|
368
370
|
columns,
|
|
369
371
|
};
|
|
370
372
|
};
|
|
373
|
+
const AI_CFO_CAPABILITY_PROMO_SURFACES = [
|
|
374
|
+
'banner',
|
|
375
|
+
'inline',
|
|
376
|
+
];
|
|
377
|
+
const toAiCfoCapabilityPromoSurface = (value) => AI_CFO_CAPABILITY_PROMO_SURFACES.find((surface) => surface === value);
|
|
378
|
+
const trimmedOrUndefined = (value) => {
|
|
379
|
+
const trimmed = value?.trim() ?? '';
|
|
380
|
+
return trimmed.length > 0 ? trimmed : undefined;
|
|
381
|
+
};
|
|
382
|
+
const toSkillDraft = (payload) => {
|
|
383
|
+
// Dropped rather than partially built when either required field is missing:
|
|
384
|
+
// a Save control wired to a body the create endpoint would reject is worse
|
|
385
|
+
// than no control, because the failure only surfaces after the click.
|
|
386
|
+
if (payload == null) {
|
|
387
|
+
return undefined;
|
|
388
|
+
}
|
|
389
|
+
// Trimmed to '' FIRST, then chosen by length. Not `??`: a whitespace-only
|
|
390
|
+
// display_name trims to '', which is not nullish, so `??` would keep the
|
|
391
|
+
// empty string and drop a draft that has a perfectly good `name`.
|
|
392
|
+
const rawName = payload.name?.trim() ?? '';
|
|
393
|
+
const rawDisplayName = payload.display_name?.trim() ?? '';
|
|
394
|
+
const name = rawName.length > 0 ? rawName : rawDisplayName;
|
|
395
|
+
const displayName = rawDisplayName.length > 0 ? rawDisplayName : name;
|
|
396
|
+
const instructions = payload.instructions?.trim() ?? '';
|
|
397
|
+
if (name.length === 0 || instructions.length === 0) {
|
|
398
|
+
return undefined;
|
|
399
|
+
}
|
|
400
|
+
const examples = payload.parameter_hints?.examples;
|
|
401
|
+
return {
|
|
402
|
+
// Kept SEPARATE even though the agent currently sends both the same: the
|
|
403
|
+
// create endpoint takes `name` and `display_name` as distinct fields, and
|
|
404
|
+
// collapsing them here would submit the display label as the identifier if
|
|
405
|
+
// they ever diverge.
|
|
406
|
+
name,
|
|
407
|
+
displayName,
|
|
408
|
+
instructions,
|
|
409
|
+
// An empty description is ABSENT, matching the way blank parameter hints
|
|
410
|
+
// are dropped below — `?? undefined` would store ''.
|
|
411
|
+
description: trimmedOrUndefined(payload.description),
|
|
412
|
+
parameterHints: Array.isArray(examples)
|
|
413
|
+
? examples.filter((hint) => typeof hint === 'string' && hint.trim().length > 0)
|
|
414
|
+
: undefined,
|
|
415
|
+
};
|
|
416
|
+
};
|
|
417
|
+
const toCapabilityPromo = (payload) => {
|
|
418
|
+
// Runtime payloads can miss fields regardless of the wire type — drop the
|
|
419
|
+
// promo on a missing/empty id or copy, and narrow surface to the union.
|
|
420
|
+
if (payload == null || !payload.id || !payload.copy) {
|
|
421
|
+
return undefined;
|
|
422
|
+
}
|
|
423
|
+
const surface = toAiCfoCapabilityPromoSurface(payload.surface);
|
|
424
|
+
if (surface == null) {
|
|
425
|
+
return undefined;
|
|
426
|
+
}
|
|
427
|
+
const cta = toCapabilityPromoCta(payload.cta);
|
|
428
|
+
return {
|
|
429
|
+
copy: payload.copy,
|
|
430
|
+
id: payload.id,
|
|
431
|
+
surface,
|
|
432
|
+
...(cta != null && { cta }),
|
|
433
|
+
};
|
|
434
|
+
};
|
|
435
|
+
const toCapabilityPromoCta = (payload) => {
|
|
436
|
+
if (payload == null || !payload.label || !payload.prefill) {
|
|
437
|
+
return undefined;
|
|
438
|
+
}
|
|
439
|
+
return { label: payload.label, prefill: payload.prefill };
|
|
440
|
+
};
|
|
371
441
|
const toResponseBlockType = (answer, userId) => {
|
|
372
|
-
const { metadata, state, type, text, visualization, table, follow_up_questions, suggested_reply, assumptions, insights, summarized_title, artifact, artifact_title, artifact_host_url, exports, } = answer;
|
|
442
|
+
const { metadata, state, type, text, visualization, table, follow_up_questions, suggested_reply, assumptions, insights, summarized_title, artifact, artifact_title, artifact_host_url, capability_promo, exports, skill_draft, } = answer;
|
|
373
443
|
const { chat_session_id, message_id, timestamp, chain_of_thought_action_steps: chainOfThoughtActionSteps = [], } = metadata;
|
|
374
444
|
return {
|
|
375
445
|
messageId: message_id,
|
|
@@ -384,6 +454,7 @@ const toResponseBlockType = (answer, userId) => {
|
|
|
384
454
|
table: table != null ? toAiCfoVisualization(table) : undefined,
|
|
385
455
|
followUpQuestions: follow_up_questions ?? [],
|
|
386
456
|
suggestedReply: suggested_reply ?? undefined,
|
|
457
|
+
capabilityPromo: toCapabilityPromo(capability_promo),
|
|
387
458
|
assumptions: assumptions ?? '',
|
|
388
459
|
insights: insights ?? '',
|
|
389
460
|
summarizedTitle: summarized_title ?? undefined,
|
|
@@ -392,6 +463,7 @@ const toResponseBlockType = (answer, userId) => {
|
|
|
392
463
|
artifactTitle: artifact_title ?? undefined,
|
|
393
464
|
artifactHostUrl: artifact_host_url ?? undefined,
|
|
394
465
|
exports: toAiCfoExports(exports),
|
|
466
|
+
skillDraft: toSkillDraft(skill_draft),
|
|
395
467
|
},
|
|
396
468
|
createdAt: zeniDate(timestamp),
|
|
397
469
|
};
|
|
@@ -72,6 +72,7 @@ const ALLOWED_DOCUMENT_TYPES = [
|
|
|
72
72
|
'bill_pay',
|
|
73
73
|
'certificate_of_incorporation',
|
|
74
74
|
'check',
|
|
75
|
+
'company_logo',
|
|
75
76
|
'contract',
|
|
76
77
|
'driving_license',
|
|
77
78
|
'employer_identification_number_confirmation',
|
|
@@ -95,6 +96,7 @@ const ALLOWED_PURPOSE_IDS = [
|
|
|
95
96
|
'business_verification_others',
|
|
96
97
|
'bill_pay',
|
|
97
98
|
'international_wire_business_verification',
|
|
99
|
+
'company_logo',
|
|
98
100
|
'others',
|
|
99
101
|
];
|
|
100
102
|
// eslint-disable-next-line @typescript-eslint/no-unused-vars
|
|
@@ -9,7 +9,6 @@ export const mapInvoicingCreditNoteLineItemPayloadToState = (payload, currencyCo
|
|
|
9
9
|
unitAmount: toAmount(payload.unit_amount, currencyCode, currencySymbol),
|
|
10
10
|
entityType: payload.entity_type,
|
|
11
11
|
id: payload.id,
|
|
12
|
-
productCode: payload.product_code,
|
|
13
12
|
});
|
|
14
13
|
export const mapInvoicingCreditNoteAllocationPayloadToState = (payload, currencyCode, currencySymbol) => ({
|
|
15
14
|
allocatedAmount: toAmount(payload.allocated_amount, currencyCode, currencySymbol),
|
|
@@ -19,7 +19,6 @@ const mapLineItem = (payload, currencyCode, currencySymbol) => ({
|
|
|
19
19
|
itemLevelDiscountAmount: payload.item_level_discount_amount != null
|
|
20
20
|
? toAmount(payload.item_level_discount_amount, currencyCode, currencySymbol)
|
|
21
21
|
: undefined,
|
|
22
|
-
productCode: payload.product_code,
|
|
23
22
|
subscriptionID: payload.subscription_id,
|
|
24
23
|
taxAmount: payload.tax_amount != null
|
|
25
24
|
? toAmount(payload.tax_amount, currencyCode, currencySymbol)
|
|
@@ -72,7 +72,6 @@ export const mapInvoicingCustomerPayloadToState = (payload) => {
|
|
|
72
72
|
phone: payload.phone,
|
|
73
73
|
plan: payload.plan,
|
|
74
74
|
planName: payload.plan_name,
|
|
75
|
-
productCode: payload.product_code,
|
|
76
75
|
preferredCurrencyCode: payload.preferred_currency_code,
|
|
77
76
|
promotionalCredits: payload.promotional_credits != null
|
|
78
77
|
? toAmount(payload.promotional_credits, currencyCode, currencySymbol)
|
|
@@ -12,7 +12,6 @@ export const mapInvoicingSubscriptionItemPayloadToState = (payload, currencyCode
|
|
|
12
12
|
itemPriceCode: payload.item_price_code,
|
|
13
13
|
itemPriceID: payload.item_price_id,
|
|
14
14
|
itemType: payload.item_type,
|
|
15
|
-
productCode: payload.product_code,
|
|
16
15
|
quantity: payload.quantity,
|
|
17
16
|
unitPrice: payload.unit_price != null
|
|
18
17
|
? toAmount(payload.unit_price, currencyCode, currencySymbol)
|
|
@@ -58,6 +57,7 @@ export const mapInvoicingSubscriptionPayloadToState = (payload) => {
|
|
|
58
57
|
billingPeriod: payload.billing_period,
|
|
59
58
|
billingPeriodUnit: payload.billing_period_unit,
|
|
60
59
|
cancelReason: payload.cancel_reason,
|
|
60
|
+
cancelReasonCode: payload.cancel_reason_code,
|
|
61
61
|
cancelledAt: payload.cancelled_at != null ? date(payload.cancelled_at) : undefined,
|
|
62
62
|
catalogItemID: payload.catalog_item_id,
|
|
63
63
|
contractTerm: payload.contract_term != null
|
|
@@ -88,7 +88,6 @@ export const mapInvoicingSubscriptionPayloadToState = (payload) => {
|
|
|
88
88
|
: undefined,
|
|
89
89
|
planID: payload.plan_id,
|
|
90
90
|
planName: payload.plan_name,
|
|
91
|
-
productCode: payload.product_code,
|
|
92
91
|
poNumber: payload.po_number,
|
|
93
92
|
remainingBillingCycles: payload.remaining_billing_cycles,
|
|
94
93
|
resumeDate: payload.resume_date != null ? date(payload.resume_date) : undefined,
|
package/lib/esm/epic.js
CHANGED
|
@@ -400,6 +400,7 @@ import { fetchEntityRecommendationsByTransactionIdEpic, } from './view/recommend
|
|
|
400
400
|
import { fetchEntityRecommendationsForLineUpdateEpic, } from './view/recommendation/fetchEntityRecommendationsForLineUpdateEpic';
|
|
401
401
|
import { fetchRecommendationByEntityIdEpic, } from './view/recommendation/fetchRecommendationByEntityIdEpic';
|
|
402
402
|
import { fetchRecommendationByEntityNameEpic, } from './view/recommendation/fetchRecommendationByEntityNameEpic';
|
|
403
|
+
import { submitRecommendationFeedbackEpic, } from './view/recommendation/submitRecommendationFeedbackEpic';
|
|
403
404
|
import { fetchReferralsEpic, } from './view/referralView/epics/fetchReferralsEpic';
|
|
404
405
|
import { fetchRewardsPlanEpic, } from './view/referralView/epics/fetchRewardsPlanEpic';
|
|
405
406
|
import { resendReferralInviteEpic, } from './view/referralView/epics/resendReferralInviteEpic';
|
|
@@ -1382,6 +1383,7 @@ const ALL_EPICS = [
|
|
|
1382
1383
|
submitInvoicingBrandingFormEpic,
|
|
1383
1384
|
submitInvoicingQboSettingsEpic,
|
|
1384
1385
|
submitQuestionEpic,
|
|
1386
|
+
submitRecommendationFeedbackEpic,
|
|
1385
1387
|
switchExpenseAutomationJESchedulesTabEpic,
|
|
1386
1388
|
syncInvoicingSubscriptionCouponsEpic,
|
|
1387
1389
|
syncTabsAfterAutomatchEpic,
|
package/lib/esm/index.js
CHANGED
|
@@ -266,7 +266,7 @@ import { fetchProfitAndLossForTimeframeProjectView, fetchProfitAndLossProjectVie
|
|
|
266
266
|
import { getProfitAndLossProjectView } from './view/profitAndLossProjectView/profitAndLossProjectViewSelector';
|
|
267
267
|
import { fetchProjectList } from './view/projectList/projectListReducer';
|
|
268
268
|
import { getProjectList, } from './view/projectList/projectListSelector';
|
|
269
|
-
import { fetchEntityRecommendationsByTransactionId, fetchEntityRecommendationsForLineUpdate, fetchRecommendationByEntityId, fetchRecommendationByEntityName, } from './view/recommendation/recommendationReducer';
|
|
269
|
+
import { fetchEntityRecommendationsByTransactionId, fetchEntityRecommendationsForLineUpdate, fetchRecommendationByEntityId, fetchRecommendationByEntityName, submitRecommendationFeedback, } from './view/recommendation/recommendationReducer';
|
|
270
270
|
import { DEFAULT_REFERRER_AMOUNT, clearReferrals, fetchReferrals, fetchRewardsPlan, resendReferralInvite, saveReferralFormDataInLocalStore, sendReferralInvite, updateReferViewed, updateReferralListSortUiState, } from './view/referralView/referralReducer';
|
|
271
271
|
import { getInviteFormView, getReferralListView, getRewardsPlanCard, } from './view/referralView/referralSelector';
|
|
272
272
|
import { AmountStatusTypes, StatusTypes, toReferralListViewSortKeyType, } from './view/referralView/referralState';
|
|
@@ -632,7 +632,7 @@ export { getSpendManagementEffectiveListPeriod, getSelectedCompanyOfficer, showB
|
|
|
632
632
|
export { canSendMonthEndEmailReport, shouldEnableCalendarPickerForLastReportSent, };
|
|
633
633
|
export { getInternationalSubConfigCodeKey, BILL_NEW_PAYMENT_METHODS, NEW_INTERNATIONAL_METHOD_SUBTEXT, SWIFT_OUR_INTERNATIONAL_METHOD_SUBTEXT, LOCAL_CURRENCY_INTERNATIONAL_METHOD_SUBTEXT, };
|
|
634
634
|
export { getVendorList, updateSortUiState, updatePageToken, updateYTDSelectionUIState, isColumnYTDSpend, isVendorsTabVisible, toVendorReportIDType, getVendorFiling1099List, fetchVendorsFiling1099Download, };
|
|
635
|
-
export { fetchEntityRecommendationsByTransactionId, fetchEntityRecommendationsForLineUpdate, fetchRecommendationByEntityId, fetchRecommendationByEntityName, };
|
|
635
|
+
export { fetchEntityRecommendationsByTransactionId, fetchEntityRecommendationsForLineUpdate, fetchRecommendationByEntityId, fetchRecommendationByEntityName, submitRecommendationFeedback, };
|
|
636
636
|
export { fetchOwnerList };
|
|
637
637
|
export { getZeniAccountsConfigDetail, getZeniAccountList, fetchZeniAccountList, fetchAccountList, createCheckingAccount, fetchPaymentAccountList, unlinkPaymentAccount, getDepositAccountDetail, getAllDepositAccounts, getDepositAccountDetailForPDF, fetchDepositAccount, fetchZeniAccountsConfig, updateTransferMoneyLocalData, updateTransferToLocalData, updateDepositToLocalData, transferMoney, getTransferDetail, clearTransferDetail, clearReviewTransferDetail, fetchReviewTransferDetail, fetchDepositAccountDetail, depositCheck, updateCheckDepositLocalData, clearCheckDeposit, getCheckDepositDetail, updateDepositAccount, fetchDepositAccountHistorySuccess, fetchDepositAccountHistoryFailure, fetchZeniAccStatementPage, getZeniAccStatements, };
|
|
638
638
|
export { fetchDepositAccountTransactionList, getDepositAccountTransactionList, };
|
|
@@ -58,6 +58,7 @@ export const initialAiCfoViewState = {
|
|
|
58
58
|
fetchState: 'Not-Started',
|
|
59
59
|
error: undefined,
|
|
60
60
|
savedMacroId: undefined,
|
|
61
|
+
kind: undefined,
|
|
61
62
|
},
|
|
62
63
|
skillVersionBody: {
|
|
63
64
|
fetchState: 'Not-Started',
|
|
@@ -777,6 +778,7 @@ const aiCfoView = createSlice({
|
|
|
777
778
|
fetchState: 'In-Progress',
|
|
778
779
|
error: undefined,
|
|
779
780
|
savedMacroId: undefined,
|
|
781
|
+
kind: 'save',
|
|
780
782
|
};
|
|
781
783
|
},
|
|
782
784
|
prepare(payload) {
|
|
@@ -828,6 +830,7 @@ const aiCfoView = createSlice({
|
|
|
828
830
|
fetchState: 'In-Progress',
|
|
829
831
|
error: undefined,
|
|
830
832
|
savedMacroId: undefined,
|
|
833
|
+
kind: 'visibility',
|
|
831
834
|
};
|
|
832
835
|
},
|
|
833
836
|
prepare(payload) {
|
|
@@ -863,6 +866,7 @@ const aiCfoView = createSlice({
|
|
|
863
866
|
fetchState: 'In-Progress',
|
|
864
867
|
error: undefined,
|
|
865
868
|
savedMacroId: undefined,
|
|
869
|
+
kind: 'delete',
|
|
866
870
|
};
|
|
867
871
|
},
|
|
868
872
|
prepare(payload) {
|
|
@@ -891,6 +895,7 @@ const aiCfoView = createSlice({
|
|
|
891
895
|
fetchState: 'Not-Started',
|
|
892
896
|
error: undefined,
|
|
893
897
|
savedMacroId: undefined,
|
|
898
|
+
kind: undefined,
|
|
894
899
|
};
|
|
895
900
|
},
|
|
896
901
|
openSkillsBrowser(draft) {
|
|
@@ -9,6 +9,18 @@ import { clearAll } from '../../../../rootActions';
|
|
|
9
9
|
import { date } from '../../../../zeniDayJS';
|
|
10
10
|
import { SERVICE_MONTH_FORMAT, } from '../../payload/jeSchedulesPayload';
|
|
11
11
|
import { fetchJeSchedules, fetchJeSchedulesFailure, fetchJeSchedulesSuccess, initializeJeScheduleLocalData, } from '../../reducers/jeSchedulesViewReducer';
|
|
12
|
+
/**
|
|
13
|
+
* How far back to look for accrued schedules, matching the Vendors page
|
|
14
|
+
* (`getDefaultSelectedTimeframeForScheduleType`, 'accrued_expenses'), which queries the same
|
|
15
|
+
* start_date filter through /1.0/schedules.
|
|
16
|
+
*/
|
|
17
|
+
const ACCRUED_LOOKBACK_MONTHS = 24;
|
|
18
|
+
/**
|
|
19
|
+
* One-time accruals keep their own, narrower lookback. Unlike an accrued schedule they belong to
|
|
20
|
+
* exactly one service month and never span months, so the reason the accrued window has to reach
|
|
21
|
+
* back does not apply to them -- widening it would only add older history to the Existing tab.
|
|
22
|
+
*/
|
|
23
|
+
const ONE_TIME_ACCRUAL_LOOKBACK_MONTHS = 12;
|
|
12
24
|
export const fetchJeSchedulesEpic = (actions$, state$, zeniAPI) => actions$.pipe(filter(fetchJeSchedules.match), mergeMap((action) => {
|
|
13
25
|
const state = state$.value;
|
|
14
26
|
const { expenseAutomationViewState: { selectedPeriodByTenantId }, } = state;
|
|
@@ -30,15 +42,21 @@ export const fetchJeSchedulesEpic = (actions$, state$, zeniAPI) => actions$.pipe
|
|
|
30
42
|
const endDate = isClosePeriodTab || existingEndDate == null
|
|
31
43
|
? toString(period.end)
|
|
32
44
|
: toString(existingEndDate);
|
|
33
|
-
// Accrued rows are windowed on the schedule's own start_date
|
|
34
|
-
//
|
|
35
|
-
//
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
45
|
+
// Accrued rows are windowed on the schedule's own start_date -- its FIRST posting date --
|
|
46
|
+
// rather than a transaction date, so the lower bound has to reach back past the start of
|
|
47
|
+
// every accrual still running in this period, not just the ones that began in it. Review
|
|
48
|
+
// used to send the close month itself, which returned only accruals whose first posting fell
|
|
49
|
+
// in that month and hid every longer-running one.
|
|
50
|
+
const parsedEndDate = date(endDate);
|
|
51
|
+
const accruedStartDate = parsedEndDate
|
|
52
|
+
.subtract(ACCRUED_LOOKBACK_MONTHS, 'month')
|
|
53
|
+
.startOf('month')
|
|
54
|
+
.format(DEFAULT_DATE_FORMAT);
|
|
55
|
+
// Formatted as a service month, not a date: that is the only thing it is sent as.
|
|
56
|
+
const oneTimeAccrualServiceMonthStart = parsedEndDate
|
|
57
|
+
.subtract(ONE_TIME_ACCRUAL_LOOKBACK_MONTHS, 'month')
|
|
58
|
+
.startOf('month')
|
|
59
|
+
.format(SERVICE_MONTH_FORMAT);
|
|
42
60
|
const queryParam = {
|
|
43
61
|
base_transaction_end_date: endDate,
|
|
44
62
|
end_date: endDate,
|
|
@@ -59,8 +77,8 @@ export const fetchJeSchedulesEpic = (actions$, state$, zeniAPI) => actions$.pipe
|
|
|
59
77
|
filter_failed_je_postings_by_date: true,
|
|
60
78
|
}
|
|
61
79
|
: {
|
|
62
|
-
one_time_accrual_service_month_start:
|
|
63
|
-
one_time_accrual_service_month_end:
|
|
80
|
+
one_time_accrual_service_month_start: oneTimeAccrualServiceMonthStart,
|
|
81
|
+
one_time_accrual_service_month_end: parsedEndDate.format(SERVICE_MONTH_FORMAT),
|
|
64
82
|
// Existing lists what actually reached the books.
|
|
65
83
|
one_time_accrual_statuses: ['posted'],
|
|
66
84
|
// A failed posting from an earlier month still needs to surface here, so this list
|
|
@@ -12,8 +12,8 @@ import { getClassList, getNestedClassListHierarchy, } from '../../classList/clas
|
|
|
12
12
|
import { getAccountsTypesForScheduleDetails } from '../../scheduleView/scheduleDetailView/scheduleDetailLocalDataHelper';
|
|
13
13
|
import { filterNestedAccountHierarchyById } from '../../scheduleView/scheduleDetailView/scheduleDetailSelector';
|
|
14
14
|
import { getAccountLabelForScheduleType, getAccountsTypesForScheduleList, } from '../../scheduleView/scheduleListView/scheduleListHelper';
|
|
15
|
-
import { getAllSteps } from './getAllStepsHelper';
|
|
16
15
|
import { ALL_JE_PAGE_TABS, getJESchedulePeriodTabKey, } from '../types/jeSchedulesViewState';
|
|
16
|
+
import { getAllSteps } from './getAllStepsHelper';
|
|
17
17
|
import { getJEAccountSettingsView } from './jeAccountSettingsViewSelector';
|
|
18
18
|
import { getNewScheduleView } from './jeNewScheduleViewSelector';
|
|
19
19
|
// Matches the AI-automation user addresses webc's schedule list row already
|
|
@@ -330,7 +330,9 @@ export function getExpenseAutomationJESchedulesView(state) {
|
|
|
330
330
|
*/
|
|
331
331
|
const sumToAmount = (schedules) => {
|
|
332
332
|
const first = schedules[0];
|
|
333
|
-
const currency = first != null
|
|
333
|
+
const currency = first != null
|
|
334
|
+
? getScheduleAmountObject(first)
|
|
335
|
+
: allScheduleAmountFallback;
|
|
334
336
|
return {
|
|
335
337
|
...currency,
|
|
336
338
|
amount: sumAmount(schedules),
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import { stringToUnion } from '../../../commonStateTypes/stringToUnion';
|
|
2
2
|
export const ALL_INVOICING_COUPON_SORT_KEYS = [
|
|
3
|
-
'
|
|
4
|
-
'
|
|
3
|
+
'code',
|
|
4
|
+
'coupon',
|
|
5
5
|
'discount',
|
|
6
6
|
'duration',
|
|
7
7
|
'created',
|
|
@@ -12,8 +12,8 @@ export const ALL_INVOICING_COUPON_SORT_KEYS = [
|
|
|
12
12
|
];
|
|
13
13
|
export const toInvoicingCouponSortKey = (v) => stringToUnion(v, ALL_INVOICING_COUPON_SORT_KEYS);
|
|
14
14
|
export const INVOICING_COUPON_COLUMNS = [
|
|
15
|
-
{ key: '
|
|
16
|
-
{ key: '
|
|
15
|
+
{ key: 'code', sortable: true },
|
|
16
|
+
{ key: 'coupon', sortable: true },
|
|
17
17
|
{ key: 'discount', sortable: false },
|
|
18
18
|
{ key: 'duration', sortable: true },
|
|
19
19
|
{ key: 'created', sortable: true },
|
|
@@ -1,3 +1,4 @@
|
|
|
1
|
+
import { invoicingFieldHelpForGroup } from '../invoicingConfigView/invoicingConfigViewSelector';
|
|
1
2
|
/**
|
|
2
3
|
* Single bundled view for the invoicing data-import surfaces — consumers read
|
|
3
4
|
* only this. Carries the migration `sessions` list + `sessionsFetch`, the
|
|
@@ -7,6 +8,7 @@
|
|
|
7
8
|
export const getInvoicingDataImportView = (state) => {
|
|
8
9
|
const dataImportState = state.invoicingDataImportViewState;
|
|
9
10
|
return {
|
|
11
|
+
fieldHelp: invoicingFieldHelpForGroup(state, 'data_import'),
|
|
10
12
|
activeMigrationSessionId: dataImportState.activeDetailId,
|
|
11
13
|
sessionDetail: dataImportState.sessionDetail,
|
|
12
14
|
sessionDetailFetch: dataImportState.sessionDetailFetch,
|
|
@@ -18,6 +18,7 @@ export const getInvoicingCatalogPrices = (items) => items.flatMap((item) => (ite
|
|
|
18
18
|
export const getInvoicingCatalogListView = createSelector((state) => state.invoicingPlanState, (state) => state.invoicingCatalogListViewState, (state) => state.invoicingConfigViewState.catalogItemLifecycleActionOptions, (planState, listViewState, catalogItemLifecycleActionOptions) => ({
|
|
19
19
|
catalogItemLifecycleActionOptions,
|
|
20
20
|
plans: getInvoicingPlansByIds(planState, listViewState.planIds),
|
|
21
|
+
planSort: listViewState.planSort,
|
|
21
22
|
productColumns: INVOICING_PRODUCT_COLUMNS,
|
|
22
23
|
products: getInvoicingPlansByIds(planState, listViewState.productIds),
|
|
23
24
|
productSort: listViewState.productSort,
|
|
@@ -34,6 +34,7 @@ export const initialState = {
|
|
|
34
34
|
discountStatusOptions: [],
|
|
35
35
|
dunningCaseStatusOptions: [],
|
|
36
36
|
invoiceStatusOptions: [],
|
|
37
|
+
subscriptionCancelReasonCodeOptions: [],
|
|
37
38
|
subscriptionStatusOptions: [],
|
|
38
39
|
transactionStatusOptions: [],
|
|
39
40
|
transactionTypeOptions: [],
|
|
@@ -103,6 +104,7 @@ export function mapInvoicingConfigPayloadToState(payload) {
|
|
|
103
104
|
discountStatusOptions: (payload.discount_status_options ?? []).map(toInvoicingNamedOption),
|
|
104
105
|
dunningCaseStatusOptions: (payload.dunning_case_status_options ?? []).map(toInvoicingNamedOption),
|
|
105
106
|
invoiceStatusOptions: (payload.invoice_status_options ?? []).map(toInvoicingNamedOption),
|
|
107
|
+
subscriptionCancelReasonCodeOptions: (payload.subscription_cancel_reason_code_options ?? []).map(toInvoicingNamedOption),
|
|
106
108
|
subscriptionStatusOptions: (payload.subscription_status_options ?? []).map(toInvoicingNamedOption),
|
|
107
109
|
transactionStatusOptions: (payload.transaction_status_options ?? []).map(toInvoicingNamedOption),
|
|
108
110
|
transactionTypeOptions: (payload.transaction_type_options ?? []).map(toInvoicingNamedOption),
|
|
@@ -3,16 +3,16 @@ export const ALL_INVOICING_CUSTOMER_SORT_KEYS = [
|
|
|
3
3
|
'name',
|
|
4
4
|
'email',
|
|
5
5
|
'billingAddress',
|
|
6
|
-
'
|
|
6
|
+
'card',
|
|
7
7
|
'autoCollect',
|
|
8
8
|
'status',
|
|
9
9
|
];
|
|
10
10
|
export const toInvoicingCustomerSortKey = (v) => stringToUnion(v, ALL_INVOICING_CUSTOMER_SORT_KEYS);
|
|
11
11
|
export const INVOICING_CUSTOMER_COLUMNS = [
|
|
12
|
-
{ key: 'name', sortable:
|
|
12
|
+
{ key: 'name', sortable: false },
|
|
13
13
|
{ key: 'email', sortable: true },
|
|
14
14
|
{ key: 'billingAddress', sortable: false },
|
|
15
|
-
{ key: '
|
|
15
|
+
{ key: 'card', sortable: true },
|
|
16
16
|
{ key: 'autoCollect', sortable: true },
|
|
17
17
|
{ key: 'status', sortable: true },
|
|
18
18
|
];
|
package/lib/esm/view/invoicing/invoicingDunningCaseListView/invoicingDunningCaseListViewState.js
CHANGED
|
@@ -3,8 +3,8 @@ export const ALL_INVOICING_DUNNING_CASE_SORT_KEYS = [
|
|
|
3
3
|
'customer',
|
|
4
4
|
'invoice',
|
|
5
5
|
'attempts',
|
|
6
|
-
'
|
|
7
|
-
'
|
|
6
|
+
'next_retry',
|
|
7
|
+
'days_past_due',
|
|
8
8
|
'failureReason',
|
|
9
9
|
'status',
|
|
10
10
|
'amount',
|
|
@@ -14,8 +14,8 @@ export const INVOICING_DUNNING_CASE_COLUMNS = [
|
|
|
14
14
|
{ key: 'customer', sortable: true },
|
|
15
15
|
{ key: 'invoice', sortable: true },
|
|
16
16
|
{ key: 'attempts', sortable: true },
|
|
17
|
-
{ key: '
|
|
18
|
-
{ key: '
|
|
17
|
+
{ key: 'next_retry', sortable: true },
|
|
18
|
+
{ key: 'days_past_due', sortable: true },
|
|
19
19
|
{ key: 'failureReason', sortable: false },
|
|
20
20
|
{ key: 'status', sortable: true },
|
|
21
21
|
{ key: 'amount', sortable: true },
|
|
@@ -37,7 +37,6 @@ export const mapInvoicingPlanRevenuePointPayloadToState = (payload) => ({
|
|
|
37
37
|
mrr: toAmount(payload.mrr, 'USD', '$'),
|
|
38
38
|
pct: payload.pct,
|
|
39
39
|
planID: payload.plan,
|
|
40
|
-
productCode: payload.product_code,
|
|
41
40
|
});
|
|
42
41
|
export const mapInvoicingDashboardSummaryPayloadToState = (payload) => ({
|
|
43
42
|
customerMovement: {
|
|
@@ -1,11 +1,12 @@
|
|
|
1
1
|
import { getInvoicingSubscriptionById as getInvoicingSubscriptionByIdFromState } from '../../../entity/invoicing/invoicingSubscription/invoicingSubscriptionSelector';
|
|
2
|
-
import { invoicingFieldHelpForGroup } from '../invoicingConfigView/invoicingConfigViewSelector';
|
|
2
|
+
import { getInvoicingConfigView, invoicingFieldHelpForGroup, } from '../invoicingConfigView/invoicingConfigViewSelector';
|
|
3
3
|
import { getInvoicingSubscriptionActionState } from '../subscriptionAction/subscriptionActionSelector';
|
|
4
4
|
export const getInvoicingSubscriptionById = (state, id) => getInvoicingSubscriptionByIdFromState(state.invoicingSubscriptionState, id);
|
|
5
5
|
export const getInvoicingSubscriptionDetail = (state, invoicingSubscriptionID) => {
|
|
6
6
|
const { error, fetchState } = state.invoicingSubscriptionDetailViewState;
|
|
7
7
|
return {
|
|
8
8
|
fieldHelp: invoicingFieldHelpForGroup(state, 'subscription'),
|
|
9
|
+
cancelReasonCodeOptions: getInvoicingConfigView(state).subscriptionCancelReasonCodeOptions,
|
|
9
10
|
actionState: getInvoicingSubscriptionActionState(invoicingSubscriptionID)(state),
|
|
10
11
|
subscription: getInvoicingSubscriptionById(state, invoicingSubscriptionID),
|
|
11
12
|
fetchState,
|
|
@@ -28,6 +28,7 @@ export const getInvoicingSubscriptionListView = createSelector((state) => state.
|
|
|
28
28
|
count: listViewState.counts,
|
|
29
29
|
countsFetchState: listViewState.countsFetchState,
|
|
30
30
|
subscriptionCommercialEditAllowedFromStatuses: configState.subscriptionCommercialEditAllowedFromStatuses,
|
|
31
|
+
cancelReasonCodeOptions: configState.subscriptionCancelReasonCodeOptions,
|
|
31
32
|
subscriptionLifecycleActionOptions: configState.subscriptionLifecycleActionOptions,
|
|
32
33
|
subscriptionMetadataEditAllowedFromStatuses: configState.subscriptionMetadataEditAllowedFromStatuses,
|
|
33
34
|
statusOptions,
|
package/lib/esm/view/invoicing/invoicingSubscriptionListView/invoicingSubscriptionListViewState.js
CHANGED
|
@@ -3,7 +3,6 @@ export const ALL_INVOICING_SUBSCRIPTION_SORT_KEYS = [
|
|
|
3
3
|
'subscription',
|
|
4
4
|
'customer',
|
|
5
5
|
'plan',
|
|
6
|
-
'product_code',
|
|
7
6
|
'term_end',
|
|
8
7
|
'next_billing',
|
|
9
8
|
'auto_collect',
|
|
@@ -15,7 +14,6 @@ export const INVOICING_SUBSCRIPTION_COLUMNS = [
|
|
|
15
14
|
{ key: 'subscription', sortable: true },
|
|
16
15
|
{ key: 'customer', sortable: false },
|
|
17
16
|
{ key: 'plan', sortable: true },
|
|
18
|
-
{ key: 'product_code', sortable: true },
|
|
19
17
|
{ key: 'term_end', sortable: true },
|
|
20
18
|
{ key: 'next_billing', sortable: true },
|
|
21
19
|
{ key: 'auto_collect', sortable: true },
|
|
@@ -7,6 +7,7 @@ export const initialInvoicingBrandingFormLocalData = {
|
|
|
7
7
|
dateFormat: '',
|
|
8
8
|
defaultMemo: '',
|
|
9
9
|
email: '',
|
|
10
|
+
invoiceFooterText: '',
|
|
10
11
|
invoicePrefix: '',
|
|
11
12
|
logoFileId: '',
|
|
12
13
|
phone: '',
|
|
@@ -19,6 +20,7 @@ export const entityToInvoicingBrandingFormLocalData = (settings) => ({
|
|
|
19
20
|
dateFormat: settings?.date_format ?? '',
|
|
20
21
|
defaultMemo: settings?.default_memo ?? '',
|
|
21
22
|
email: settings?.email ?? '',
|
|
23
|
+
invoiceFooterText: settings?.invoice_footer_text ?? '',
|
|
22
24
|
invoicePrefix: settings?.invoice_prefix ?? '',
|
|
23
25
|
logoFileId: settings?.logo_file_id ?? '',
|
|
24
26
|
phone: settings?.phone ?? '',
|
|
@@ -39,6 +41,9 @@ export const brandingLocalDataToSettingsPayload = (localData, address) => ({
|
|
|
39
41
|
date_format: trimOrUndefined(localData.dateFormat),
|
|
40
42
|
default_memo: trimOrUndefined(localData.defaultMemo),
|
|
41
43
|
email: trimOrUndefined(localData.email),
|
|
44
|
+
// Sent even when blank: "" is how the API is told to hide the footer line,
|
|
45
|
+
// so this one must not collapse to `undefined` like the fields above.
|
|
46
|
+
invoice_footer_text: localData.invoiceFooterText.trim(),
|
|
42
47
|
invoice_prefix: trimOrUndefined(localData.invoicePrefix),
|
|
43
48
|
logo_file_id: localData.logoFileId,
|
|
44
49
|
phone: trimOrUndefined(localData.phone),
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { getInvoicingQboAccountMappingId, } from '../../../entity/invoicing/invoicingCommonPayload';
|
|
2
2
|
import { getFormattedAddress } from '../../addressView/addressViewSelector';
|
|
3
|
-
import { getInvoicingConfigView } from '../invoicingConfigView/invoicingConfigViewSelector';
|
|
3
|
+
import { getInvoicingConfigView, invoicingFieldHelpForGroup, } from '../invoicingConfigView/invoicingConfigViewSelector';
|
|
4
4
|
import { getInvoicingQboView, isInvoicingAccountingPickerDataLoading, } from '../invoicingQboView/invoicingQboViewSelector';
|
|
5
5
|
import { INVOICING_BUSINESS_ADDRESS_TYPE, entityToInvoicingBrandingFormLocalData, } from './invoicingBrandingFormConfig';
|
|
6
6
|
import { initialInvoicingQboSettingsLocalData, } from './invoicingQboSettingsFormConfig';
|
|
@@ -26,6 +26,7 @@ export const getInvoicingSettingsFetchState = (state) => ({
|
|
|
26
26
|
export const getInvoicingSettingsView = (state) => {
|
|
27
27
|
const { error, fetchState, saveFetchState, settings, stripeFetchState } = state.invoicingSettingsViewState;
|
|
28
28
|
return {
|
|
29
|
+
fieldHelp: invoicingFieldHelpForGroup(state, 'settings'),
|
|
29
30
|
error,
|
|
30
31
|
fetchState,
|
|
31
32
|
saveState: saveFetchState,
|
|
@@ -78,6 +79,7 @@ export const getInvoicingSettingsHubView = (state) => {
|
|
|
78
79
|
const { dunningScheduleActionOptions, enableState, error: configError, fetchState: configFetchState, qboAccountMappingKindOptions, qboCustomerMatchingOptions, qboSyncStatusOptions, status, } = getInvoicingConfigView(state);
|
|
79
80
|
const { canEnable, isQboConfigured, isStripeConnected } = deriveInvoicingEnablePrerequisites(state.invoicingSettingsViewState.settings, state.invoicingQboViewState.connection?.connected === true, qboAccountMappingKindOptions);
|
|
80
81
|
return {
|
|
82
|
+
fieldHelp: invoicingFieldHelpForGroup(state, 'settings'),
|
|
81
83
|
// Keeps the onboarding step in the gate: a tenant that has not accepted the
|
|
82
84
|
// terms cannot enable invoicing, whatever the integrations say.
|
|
83
85
|
canEnableInvoicing: status === 'settings' && canEnable,
|
|
@@ -108,6 +110,7 @@ export const getInvoicingQboSettingsFormView = (state) => {
|
|
|
108
110
|
const { fetchState: configFetchState, qboAccountMappingKindOptions, qboCustomerMatchingOptions, qboSyncStatusOptions, } = getInvoicingConfigView(state);
|
|
109
111
|
const qboView = getInvoicingQboView(state);
|
|
110
112
|
return {
|
|
113
|
+
fieldHelp: invoicingFieldHelpForGroup(state, 'settings'),
|
|
111
114
|
accountMappingKindOptions: qboAccountMappingKindOptions,
|
|
112
115
|
accounts: qboView.accounts,
|
|
113
116
|
backfillState: qboView.backfillState,
|
|
@@ -147,6 +150,7 @@ export const getInvoicingBrandingFormView = (state) => {
|
|
|
147
150
|
? getFormattedAddress(newAddress.addressToCreate)
|
|
148
151
|
: undefined;
|
|
149
152
|
return {
|
|
153
|
+
fieldHelp: invoicingFieldHelpForGroup(state, 'settings'),
|
|
150
154
|
addressLabel,
|
|
151
155
|
dateFormatOptions: getInvoicingConfigView(state).dateFormatOptions,
|
|
152
156
|
localData: brandingDraft ?? entityToInvoicingBrandingFormLocalData(settings),
|
|
@@ -131,6 +131,18 @@ const recommendation = createSlice({
|
|
|
131
131
|
};
|
|
132
132
|
},
|
|
133
133
|
},
|
|
134
|
+
// Fire-and-forget human feedback on a recommendation (accept, ranked
|
|
135
|
+
// override or outside override). Handled by submitRecommendationFeedbackEpic
|
|
136
|
+
// which POSTs to the accounting recommendation-feedback endpoint. No state
|
|
137
|
+
// mutation: the categorization UX must not depend on the feedback round-trip.
|
|
138
|
+
submitRecommendationFeedback: {
|
|
139
|
+
reducer() {
|
|
140
|
+
// Fire-and-forget: no state mutation; the epic performs the POST.
|
|
141
|
+
},
|
|
142
|
+
prepare(args) {
|
|
143
|
+
return { payload: args };
|
|
144
|
+
},
|
|
145
|
+
},
|
|
134
146
|
},
|
|
135
147
|
extraReducers: (builder) => {
|
|
136
148
|
builder.addCase(clearAll, (draft) => {
|
|
@@ -138,7 +150,7 @@ const recommendation = createSlice({
|
|
|
138
150
|
});
|
|
139
151
|
},
|
|
140
152
|
});
|
|
141
|
-
export const { fetchEntityRecommendationsByTransactionId, fetchEntityRecommendationsForLineUpdate, fetchRecommendationByEntityName, fetchRecommendationByEntityId, updateRecommendationForEntity, updateRecommendationForEntityFailure, indicateReadyToInitializeRecommendation, } = recommendation.actions;
|
|
153
|
+
export const { fetchEntityRecommendationsByTransactionId, fetchEntityRecommendationsForLineUpdate, fetchRecommendationByEntityName, fetchRecommendationByEntityId, updateRecommendationForEntity, updateRecommendationForEntityFailure, indicateReadyToInitializeRecommendation, submitRecommendationFeedback, } = recommendation.actions;
|
|
142
154
|
export default recommendation.reducer;
|
|
143
155
|
const doUpdateRecommendationForEntity = (draft, entityId, entityType, payload) => {
|
|
144
156
|
const key = getEntityRecommendationKey(entityType, entityId);
|