@zeniai/client-epic-state 5.2.3 → 5.2.5
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/invoicing/invoicingCommonPayload.d.ts +27 -0
- package/lib/entity/invoicing/invoicingCommonPayload.js +52 -1
- package/lib/epic.js +12 -0
- package/lib/esm/entity/invoicing/invoicingCommonPayload.js +50 -0
- package/lib/esm/epic.js +12 -0
- package/lib/esm/index.js +3 -3
- package/lib/esm/view/aiCfoView/aiCfoViewReducer.js +411 -9
- package/lib/esm/view/aiCfoView/aiCfoViewSelector.js +49 -0
- package/lib/esm/view/aiCfoView/epics/deleteSkillEpic.js +23 -0
- package/lib/esm/view/aiCfoView/epics/fetchSkillDetailEpic.js +35 -0
- package/lib/esm/view/aiCfoView/epics/fetchSkillVersionBodyEpic.js +45 -0
- package/lib/esm/view/aiCfoView/epics/fetchSkillVersionsEpic.js +37 -0
- package/lib/esm/view/aiCfoView/epics/fetchSkillsEpic.js +11 -6
- package/lib/esm/view/aiCfoView/epics/saveSkillEpic.js +72 -0
- package/lib/esm/view/aiCfoView/epics/setSkillVisibilityEpic.js +32 -0
- package/lib/esm/view/aiCfoView/epics/toSkillDetail.js +102 -0
- package/lib/esm/view/invoicing/auditView/auditViewPayload.js +11 -0
- package/lib/esm/view/invoicing/createInvoice/createInvoiceSelector.js +2 -0
- package/lib/esm/view/invoicing/editInvoicingCatalogItemDetailView/editInvoicingCatalogItemDetailViewSelector.js +2 -1
- package/lib/esm/view/invoicing/editInvoicingCouponDetailView/editInvoicingCouponDetailViewSelector.js +2 -1
- package/lib/esm/view/invoicing/editInvoicingCustomerDetailView/editInvoicingCustomerDetailViewSelector.js +2 -1
- package/lib/esm/view/invoicing/editInvoicingSubscriptionDetailView/editInvoicingSubscriptionDetailViewPayload.js +7 -4
- package/lib/esm/view/invoicing/editInvoicingSubscriptionDetailView/editInvoicingSubscriptionDetailViewSelector.js +3 -5
- package/lib/esm/view/invoicing/editInvoicingSubscriptionDetailView/invoicingSubscriptionFormConfig.js +0 -31
- package/lib/esm/view/invoicing/invoiceDetail/invoiceDetailSelector.js +2 -0
- package/lib/esm/view/invoicing/invoicingCatalogItemDetailView/invoicingCatalogItemDetailViewSelector.js +2 -1
- package/lib/esm/view/invoicing/invoicingConfigView/invoicingConfigViewReducer.js +5 -1
- package/lib/esm/view/invoicing/invoicingConfigView/invoicingConfigViewSelector.js +7 -0
- package/lib/esm/view/invoicing/invoicingCouponDetailView/invoicingCouponDetailViewSelector.js +2 -0
- package/lib/esm/view/invoicing/invoicingCreditNoteDetailView/invoicingCreditNoteDetailViewSelector.js +2 -0
- package/lib/esm/view/invoicing/invoicingCustomerDetailView/invoicingCustomerDetailViewSelector.js +2 -0
- package/lib/esm/view/invoicing/invoicingDunningCaseDetailView/invoicingDunningCaseDetailViewSelector.js +2 -0
- package/lib/esm/view/invoicing/invoicingSubscriptionDetailView/invoicingSubscriptionDetailViewSelector.js +2 -0
- package/lib/esm/view/invoicing/issueCreditNote/issueCreditNoteSelector.js +2 -1
- package/lib/esm/view/invoicing/recordPayment/recordPaymentSelector.js +2 -1
- package/lib/index.d.ts +5 -5
- package/lib/index.js +26 -12
- package/lib/view/aiCfoView/aiCfoViewPayload.d.ts +85 -0
- package/lib/view/aiCfoView/aiCfoViewReducer.d.ts +67 -2
- package/lib/view/aiCfoView/aiCfoViewReducer.js +413 -10
- package/lib/view/aiCfoView/aiCfoViewSelector.d.ts +7 -1
- package/lib/view/aiCfoView/aiCfoViewSelector.js +54 -0
- package/lib/view/aiCfoView/aiCfoViewState.d.ts +143 -1
- package/lib/view/aiCfoView/epics/deleteSkillEpic.d.ts +8 -0
- package/lib/view/aiCfoView/epics/deleteSkillEpic.js +27 -0
- package/lib/view/aiCfoView/epics/fetchSkillDetailEpic.d.ts +8 -0
- package/lib/view/aiCfoView/epics/fetchSkillDetailEpic.js +39 -0
- package/lib/view/aiCfoView/epics/fetchSkillVersionBodyEpic.d.ts +13 -0
- package/lib/view/aiCfoView/epics/fetchSkillVersionBodyEpic.js +49 -0
- package/lib/view/aiCfoView/epics/fetchSkillVersionsEpic.d.ts +8 -0
- package/lib/view/aiCfoView/epics/fetchSkillVersionsEpic.js +41 -0
- package/lib/view/aiCfoView/epics/fetchSkillsEpic.js +11 -6
- package/lib/view/aiCfoView/epics/saveSkillEpic.d.ts +14 -0
- package/lib/view/aiCfoView/epics/saveSkillEpic.js +76 -0
- package/lib/view/aiCfoView/epics/setSkillVisibilityEpic.d.ts +14 -0
- package/lib/view/aiCfoView/epics/setSkillVisibilityEpic.js +36 -0
- package/lib/view/aiCfoView/epics/toSkillDetail.d.ts +88 -0
- package/lib/view/aiCfoView/epics/toSkillDetail.js +110 -0
- package/lib/view/companyView/types/cockpitTabsID.d.ts +1 -1
- package/lib/view/companyView/types/cockpitTypes.d.ts +2 -2
- package/lib/view/invoicing/auditView/auditViewPayload.d.ts +2 -0
- package/lib/view/invoicing/auditView/auditViewPayload.js +11 -0
- package/lib/view/invoicing/couponView/couponViewState.d.ts +1 -1
- package/lib/view/invoicing/createInvoice/createInvoiceSelector.d.ts +6 -1
- package/lib/view/invoicing/createInvoice/createInvoiceSelector.js +2 -0
- package/lib/view/invoicing/editInvoicingCatalogItemDetailView/editInvoicingCatalogItemDetailViewSelector.d.ts +6 -1
- package/lib/view/invoicing/editInvoicingCatalogItemDetailView/editInvoicingCatalogItemDetailViewSelector.js +1 -0
- package/lib/view/invoicing/editInvoicingCouponDetailView/editInvoicingCouponDetailViewSelector.d.ts +6 -1
- package/lib/view/invoicing/editInvoicingCouponDetailView/editInvoicingCouponDetailViewSelector.js +1 -0
- package/lib/view/invoicing/editInvoicingCustomerDetailView/editInvoicingCustomerDetailViewSelector.d.ts +6 -1
- package/lib/view/invoicing/editInvoicingCustomerDetailView/editInvoicingCustomerDetailViewSelector.js +1 -0
- package/lib/view/invoicing/editInvoicingSubscriptionDetailView/editInvoicingSubscriptionDetailViewPayload.d.ts +6 -0
- package/lib/view/invoicing/editInvoicingSubscriptionDetailView/editInvoicingSubscriptionDetailViewPayload.js +6 -3
- package/lib/view/invoicing/editInvoicingSubscriptionDetailView/editInvoicingSubscriptionDetailViewSelector.d.ts +6 -2
- package/lib/view/invoicing/editInvoicingSubscriptionDetailView/editInvoicingSubscriptionDetailViewSelector.js +1 -3
- package/lib/view/invoicing/editInvoicingSubscriptionDetailView/editInvoicingSubscriptionDetailViewState.d.ts +0 -1
- package/lib/view/invoicing/editInvoicingSubscriptionDetailView/invoicingSubscriptionFormConfig.d.ts +0 -13
- package/lib/view/invoicing/editInvoicingSubscriptionDetailView/invoicingSubscriptionFormConfig.js +1 -34
- package/lib/view/invoicing/invoiceDetail/invoiceDetailSelector.d.ts +6 -0
- package/lib/view/invoicing/invoiceDetail/invoiceDetailSelector.js +2 -0
- package/lib/view/invoicing/invoicingCatalogItemDetailView/invoicingCatalogItemDetailViewSelector.d.ts +6 -1
- package/lib/view/invoicing/invoicingCatalogItemDetailView/invoicingCatalogItemDetailViewSelector.js +1 -0
- package/lib/view/invoicing/invoicingConfigView/invoicingConfigViewPayload.d.ts +2 -1
- package/lib/view/invoicing/invoicingConfigView/invoicingConfigViewReducer.d.ts +1 -1
- package/lib/view/invoicing/invoicingConfigView/invoicingConfigViewReducer.js +4 -0
- package/lib/view/invoicing/invoicingConfigView/invoicingConfigViewSelector.d.ts +8 -0
- package/lib/view/invoicing/invoicingConfigView/invoicingConfigViewSelector.js +9 -1
- package/lib/view/invoicing/invoicingConfigView/invoicingConfigViewState.d.ts +3 -1
- package/lib/view/invoicing/invoicingCouponDetailView/invoicingCouponDetailViewSelector.d.ts +6 -0
- package/lib/view/invoicing/invoicingCouponDetailView/invoicingCouponDetailViewSelector.js +2 -0
- package/lib/view/invoicing/invoicingCreditNoteDetailView/invoicingCreditNoteDetailViewSelector.d.ts +6 -0
- package/lib/view/invoicing/invoicingCreditNoteDetailView/invoicingCreditNoteDetailViewSelector.js +2 -0
- package/lib/view/invoicing/invoicingCreditNoteListView/invoicingCreditNoteListViewState.d.ts +1 -1
- package/lib/view/invoicing/invoicingCustomerDetailView/invoicingCustomerDetailViewSelector.d.ts +6 -0
- package/lib/view/invoicing/invoicingCustomerDetailView/invoicingCustomerDetailViewSelector.js +2 -0
- package/lib/view/invoicing/invoicingDunningCaseDetailView/invoicingDunningCaseDetailViewSelector.d.ts +6 -0
- package/lib/view/invoicing/invoicingDunningCaseDetailView/invoicingDunningCaseDetailViewSelector.js +2 -0
- package/lib/view/invoicing/invoicingSubscriptionDetailView/invoicingSubscriptionDetailViewSelector.d.ts +6 -0
- package/lib/view/invoicing/invoicingSubscriptionDetailView/invoicingSubscriptionDetailViewSelector.js +2 -0
- package/lib/view/invoicing/issueCreditNote/issueCreditNoteSelector.d.ts +6 -1
- package/lib/view/invoicing/issueCreditNote/issueCreditNoteSelector.js +1 -0
- package/lib/view/invoicing/recordPayment/recordPaymentSelector.d.ts +6 -1
- package/lib/view/invoicing/recordPayment/recordPaymentSelector.js +1 -0
- package/lib/view/taskManager/taskListView/taskList.d.ts +1 -1
- package/package.json +1 -1
|
@@ -0,0 +1,88 @@
|
|
|
1
|
+
import { SkillDetailDataPayload, SkillSummaryPayload } from '../aiCfoViewPayload';
|
|
2
|
+
import { Skill, SkillDetail, SkillVisibility } from '../aiCfoViewState';
|
|
3
|
+
/**
|
|
4
|
+
* A wire string narrowed to {@link SkillVisibility}, or null.
|
|
5
|
+
*
|
|
6
|
+
* A converter rather than passing the raw string through, because `Skill.visibility` is a
|
|
7
|
+
* union on the state type and this is the boundary where an unvalidated payload becomes
|
|
8
|
+
* it — the repo's rule about explicit converters at scalar boundaries instead of a bare
|
|
9
|
+
* cast.
|
|
10
|
+
*
|
|
11
|
+
* Unrecognised maps to NULL, not to `'private'`. Null already means "does not apply" for a
|
|
12
|
+
* Zeni default, and consumers show no audience badge for it — so an unknown tier renders
|
|
13
|
+
* as no badge. Defaulting to `'private'` would instead label a skill the whole tenant can
|
|
14
|
+
* run as author-only, which is a confident lie rather than a visible gap.
|
|
15
|
+
*/
|
|
16
|
+
export declare const toSkillVisibility: (raw: string | null | undefined) => SkillVisibility | null;
|
|
17
|
+
/**
|
|
18
|
+
* What the version-body read needs, and nothing more.
|
|
19
|
+
*
|
|
20
|
+
* A `Pick` of the payload rather than a type of its own: `SkillDetailDataPayload` now
|
|
21
|
+
* marks the three unchecked fields optional itself, the same way `SkillSummaryPayload`
|
|
22
|
+
* does, so there is one idiom for "this endpoint is not schema-validated" instead of two.
|
|
23
|
+
*/
|
|
24
|
+
type PromptBody = Pick<SkillDetailDataPayload, 'instructions'>;
|
|
25
|
+
/**
|
|
26
|
+
* Everything about a skill summary EXCEPT `exampleHints`, which no shared mapper can
|
|
27
|
+
* honestly supply.
|
|
28
|
+
*
|
|
29
|
+
* Only the LIST route returns `parameter_hints`; the detail and write routes do not. A
|
|
30
|
+
* shared mapper hardcoding `exampleHints: []` would put a "try: …" line under a skill
|
|
31
|
+
* that has hints, or drop them from the menu — so the field is `Omit`ted and each caller
|
|
32
|
+
* spreads in what its own route actually knows.
|
|
33
|
+
*
|
|
34
|
+
* Returning `Omit<Skill, 'exampleHints'>` rather than duplicating the mapper is what
|
|
35
|
+
* makes a new `Skill` field land in one place: this function stops compiling until the
|
|
36
|
+
* field is mapped, and both callers inherit it. The previous shape — two full copies —
|
|
37
|
+
* is how `isMine` was nearly added to only one of them, which would have silently
|
|
38
|
+
* withheld the edit and delete controls on whichever surface was missed.
|
|
39
|
+
*/
|
|
40
|
+
export declare const toBaseSkill: (payload: SkillSummaryPayload) => Omit<Skill, "exampleHints">;
|
|
41
|
+
/**
|
|
42
|
+
* Whether a 2xx body carries a prompt.
|
|
43
|
+
*
|
|
44
|
+
* Narrows to {@link PromptBody} and NOT to the whole payload, because the only consumer —
|
|
45
|
+
* the version-body read — dereferences `instructions` and nothing else. Asserting the
|
|
46
|
+
* whole shape here would claim `skill` was checked when it was not, and tying the read to
|
|
47
|
+
* it would fail a response whose prompt was fine and whose `skill` block was malformed,
|
|
48
|
+
* which is exactly what happened when this was one predicate instead of two.
|
|
49
|
+
*
|
|
50
|
+
* Takes `unknown`: the input is an unvalidated network body, and typing the parameter as
|
|
51
|
+
* the payload interface would assume the very thing being checked.
|
|
52
|
+
*/
|
|
53
|
+
export declare const hasPromptBody: (data: unknown) => data is PromptBody;
|
|
54
|
+
/**
|
|
55
|
+
* Whether a 2xx body can build a whole {@link SkillDetail}.
|
|
56
|
+
*
|
|
57
|
+
* Narrows to the payload type itself, which is now truthful: the two fields this checks
|
|
58
|
+
* are the two the interface still declares required, and the other three are optional
|
|
59
|
+
* there. Stricter than {@link hasPromptBody} by exactly one field. Four epics read this shape
|
|
60
|
+
* and each used to guard it differently — `data != null`, `data?.skill != null`, and a
|
|
61
|
+
* real `instructions` check — so one malformed response became a failure in one place, an
|
|
62
|
+
* empty prompt in another, and `undefined` in a third.
|
|
63
|
+
*/
|
|
64
|
+
export declare const isSkillDetailPayload: (data: unknown) => data is SkillDetailDataPayload;
|
|
65
|
+
/**
|
|
66
|
+
* The detail payload every write route answers with.
|
|
67
|
+
*
|
|
68
|
+
* Shared because three epics need it — save, visibility, and the detail read — and a
|
|
69
|
+
* fourth copy is how one of them quietly stops carrying a field the others do.
|
|
70
|
+
*
|
|
71
|
+
* The coercions are not defensive habit; the payload type makes them mandatory — the
|
|
72
|
+
* three optional fields cannot be assigned to a non-optional `SkillDetail` without one.
|
|
73
|
+
* Which fields get coerced and which do not is the deliberate part:
|
|
74
|
+
*
|
|
75
|
+
* - `instructions` is load-bearing and already proven, so it passes through. Defaulting a
|
|
76
|
+
* missing prompt to `''` is the one thing this module exists to prevent: the user
|
|
77
|
+
* cannot tell an empty prompt from a skill that has one, and may save over the real
|
|
78
|
+
* thing.
|
|
79
|
+
* - `instructionsCharCount` falls back to the prompt's own length, NOT to 0. A 12,000
|
|
80
|
+
* character prompt displayed as "0 characters" is a lie the user can see, and the
|
|
81
|
+
* prompt is right here to measure. Approximate only for astral-plane characters, where
|
|
82
|
+
* UTF-16 units and the server's count differ — a rounding error, against a guaranteed
|
|
83
|
+
* wrong answer.
|
|
84
|
+
* - `artifact` and `artifactTitle` degrade to empty. They render a preview card, so
|
|
85
|
+
* losing them costs a card; failing the whole read would cost the user the skill.
|
|
86
|
+
*/
|
|
87
|
+
export declare const toSkillDetail: (payload: SkillDetailDataPayload) => SkillDetail;
|
|
88
|
+
export {};
|
|
@@ -0,0 +1,110 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.toSkillDetail = exports.isSkillDetailPayload = exports.hasPromptBody = exports.toBaseSkill = exports.toSkillVisibility = void 0;
|
|
4
|
+
/**
|
|
5
|
+
* Every value `SkillVisibility` admits, as data so the converter below cannot drift from
|
|
6
|
+
* the type. Adding a tier to the union without adding it here is a compile error.
|
|
7
|
+
*/
|
|
8
|
+
const SKILL_VISIBILITIES = ['private', 'tenant'];
|
|
9
|
+
/**
|
|
10
|
+
* A wire string narrowed to {@link SkillVisibility}, or null.
|
|
11
|
+
*
|
|
12
|
+
* A converter rather than passing the raw string through, because `Skill.visibility` is a
|
|
13
|
+
* union on the state type and this is the boundary where an unvalidated payload becomes
|
|
14
|
+
* it — the repo's rule about explicit converters at scalar boundaries instead of a bare
|
|
15
|
+
* cast.
|
|
16
|
+
*
|
|
17
|
+
* Unrecognised maps to NULL, not to `'private'`. Null already means "does not apply" for a
|
|
18
|
+
* Zeni default, and consumers show no audience badge for it — so an unknown tier renders
|
|
19
|
+
* as no badge. Defaulting to `'private'` would instead label a skill the whole tenant can
|
|
20
|
+
* run as author-only, which is a confident lie rather than a visible gap.
|
|
21
|
+
*/
|
|
22
|
+
const toSkillVisibility = (raw) => SKILL_VISIBILITIES.find((known) => known === raw) ?? null;
|
|
23
|
+
exports.toSkillVisibility = toSkillVisibility;
|
|
24
|
+
/**
|
|
25
|
+
* Everything about a skill summary EXCEPT `exampleHints`, which no shared mapper can
|
|
26
|
+
* honestly supply.
|
|
27
|
+
*
|
|
28
|
+
* Only the LIST route returns `parameter_hints`; the detail and write routes do not. A
|
|
29
|
+
* shared mapper hardcoding `exampleHints: []` would put a "try: …" line under a skill
|
|
30
|
+
* that has hints, or drop them from the menu — so the field is `Omit`ted and each caller
|
|
31
|
+
* spreads in what its own route actually knows.
|
|
32
|
+
*
|
|
33
|
+
* Returning `Omit<Skill, 'exampleHints'>` rather than duplicating the mapper is what
|
|
34
|
+
* makes a new `Skill` field land in one place: this function stops compiling until the
|
|
35
|
+
* field is mapped, and both callers inherit it. The previous shape — two full copies —
|
|
36
|
+
* is how `isMine` was nearly added to only one of them, which would have silently
|
|
37
|
+
* withheld the edit and delete controls on whichever surface was missed.
|
|
38
|
+
*/
|
|
39
|
+
const toBaseSkill = (payload) => ({
|
|
40
|
+
macroId: payload.macro_id,
|
|
41
|
+
name: payload.name,
|
|
42
|
+
displayName: payload.display_name,
|
|
43
|
+
description: payload.description,
|
|
44
|
+
semver: payload.semver,
|
|
45
|
+
hasScripts: payload.has_scripts === true,
|
|
46
|
+
// === true, so an absent field withholds the write controls rather than offering ones
|
|
47
|
+
// the API refuses.
|
|
48
|
+
isMine: payload.is_mine === true,
|
|
49
|
+
isOwnedByTenant: payload.is_owned_by_tenant === true,
|
|
50
|
+
updatedAt: payload.updated_at ?? null,
|
|
51
|
+
visibility: (0, exports.toSkillVisibility)(payload.visibility),
|
|
52
|
+
});
|
|
53
|
+
exports.toBaseSkill = toBaseSkill;
|
|
54
|
+
/**
|
|
55
|
+
* Whether a 2xx body carries a prompt.
|
|
56
|
+
*
|
|
57
|
+
* Narrows to {@link PromptBody} and NOT to the whole payload, because the only consumer —
|
|
58
|
+
* the version-body read — dereferences `instructions` and nothing else. Asserting the
|
|
59
|
+
* whole shape here would claim `skill` was checked when it was not, and tying the read to
|
|
60
|
+
* it would fail a response whose prompt was fine and whose `skill` block was malformed,
|
|
61
|
+
* which is exactly what happened when this was one predicate instead of two.
|
|
62
|
+
*
|
|
63
|
+
* Takes `unknown`: the input is an unvalidated network body, and typing the parameter as
|
|
64
|
+
* the payload interface would assume the very thing being checked.
|
|
65
|
+
*/
|
|
66
|
+
const hasPromptBody = (data) => typeof data?.instructions ===
|
|
67
|
+
'string';
|
|
68
|
+
exports.hasPromptBody = hasPromptBody;
|
|
69
|
+
/**
|
|
70
|
+
* Whether a 2xx body can build a whole {@link SkillDetail}.
|
|
71
|
+
*
|
|
72
|
+
* Narrows to the payload type itself, which is now truthful: the two fields this checks
|
|
73
|
+
* are the two the interface still declares required, and the other three are optional
|
|
74
|
+
* there. Stricter than {@link hasPromptBody} by exactly one field. Four epics read this shape
|
|
75
|
+
* and each used to guard it differently — `data != null`, `data?.skill != null`, and a
|
|
76
|
+
* real `instructions` check — so one malformed response became a failure in one place, an
|
|
77
|
+
* empty prompt in another, and `undefined` in a third.
|
|
78
|
+
*/
|
|
79
|
+
const isSkillDetailPayload = (data) => (0, exports.hasPromptBody)(data) && data.skill != null;
|
|
80
|
+
exports.isSkillDetailPayload = isSkillDetailPayload;
|
|
81
|
+
/**
|
|
82
|
+
* The detail payload every write route answers with.
|
|
83
|
+
*
|
|
84
|
+
* Shared because three epics need it — save, visibility, and the detail read — and a
|
|
85
|
+
* fourth copy is how one of them quietly stops carrying a field the others do.
|
|
86
|
+
*
|
|
87
|
+
* The coercions are not defensive habit; the payload type makes them mandatory — the
|
|
88
|
+
* three optional fields cannot be assigned to a non-optional `SkillDetail` without one.
|
|
89
|
+
* Which fields get coerced and which do not is the deliberate part:
|
|
90
|
+
*
|
|
91
|
+
* - `instructions` is load-bearing and already proven, so it passes through. Defaulting a
|
|
92
|
+
* missing prompt to `''` is the one thing this module exists to prevent: the user
|
|
93
|
+
* cannot tell an empty prompt from a skill that has one, and may save over the real
|
|
94
|
+
* thing.
|
|
95
|
+
* - `instructionsCharCount` falls back to the prompt's own length, NOT to 0. A 12,000
|
|
96
|
+
* character prompt displayed as "0 characters" is a lie the user can see, and the
|
|
97
|
+
* prompt is right here to measure. Approximate only for astral-plane characters, where
|
|
98
|
+
* UTF-16 units and the server's count differ — a rounding error, against a guaranteed
|
|
99
|
+
* wrong answer.
|
|
100
|
+
* - `artifact` and `artifactTitle` degrade to empty. They render a preview card, so
|
|
101
|
+
* losing them costs a card; failing the whole read would cost the user the skill.
|
|
102
|
+
*/
|
|
103
|
+
const toSkillDetail = (payload) => ({
|
|
104
|
+
skill: { ...(0, exports.toBaseSkill)(payload.skill), exampleHints: [] },
|
|
105
|
+
instructions: payload.instructions,
|
|
106
|
+
instructionsCharCount: payload.instructions_char_count ?? payload.instructions.length,
|
|
107
|
+
artifact: payload.artifact ?? '',
|
|
108
|
+
artifactTitle: payload.artifact_title ?? '',
|
|
109
|
+
});
|
|
110
|
+
exports.toSkillDetail = toSkillDetail;
|
|
@@ -1,5 +1,5 @@
|
|
|
1
1
|
export declare const ALL_COCKPIT_TABS_IDS: readonly ["management", "subscription", "portfolio", "onboarding", "audit", "healthMonitor"];
|
|
2
|
-
export declare const toCockpitTabsIDStrict: (v: string) => "onboarding" | "
|
|
2
|
+
export declare const toCockpitTabsIDStrict: (v: string) => "onboarding" | "subscription" | "management" | "portfolio" | "audit" | "healthMonitor" | undefined;
|
|
3
3
|
export type CockpitTabsID = NonNullable<ReturnType<typeof toCockpitTabsIDStrict>>;
|
|
4
4
|
export type CockpitDownloadTabsID = Exclude<CockpitTabsID, 'audit'>;
|
|
5
5
|
export declare const ALL_COCKPIT_TABS_FILE_TYPES: readonly ["excel"];
|
|
@@ -4,9 +4,9 @@ import { SubscriptionViewSortKey } from '../../subscriptionView/types/subscripti
|
|
|
4
4
|
import { CockpitDownloadTabsID, CockpitTabsFileType } from './cockpitTabsID';
|
|
5
5
|
export type FilterCategoryValueType = string | ZeniDate;
|
|
6
6
|
export declare const toPortfolioSortKeyType: (v: string) => "expenses" | "runway" | "companyName" | "cashBalance" | "revenues" | "netIncome";
|
|
7
|
-
export declare const toManagementSortKeyType: (v: string) => "status" | "bookCloseDate" | "controller" | "preparer" | "reviewer" | "taxStatus" | "companyName" | "plans" | "monthlyRecurringRevenue" | "notes" | "task" | "
|
|
7
|
+
export declare const toManagementSortKeyType: (v: string) => "status" | "bookCloseDate" | "controller" | "preparer" | "reviewer" | "taxStatus" | "group" | "companyName" | "plans" | "monthlyRecurringRevenue" | "notes" | "task" | "productVerticals" | "realmId" | "customerSuccessManager" | "apAnalyst" | "reportSent" | "taxLead" | "annualRecurringRevenue" | "satisfaction";
|
|
8
8
|
export declare const toOnboardingSortKeyType: (v: string) => "companyName" | "notes" | "bankAccountLinked" | "qboLinked" | "identityVerified" | "businessVerified" | "groupCreated" | "customerCreated" | "enroller" | "invite" | "latestCreated";
|
|
9
|
-
export declare const toHealthSortKeyType: (v: string) => "controller" | "
|
|
9
|
+
export declare const toHealthSortKeyType: (v: string) => "controller" | "group" | "runway" | "companyName" | "monthlyRecurringRevenue" | "productVerticals" | "customerSuccessManager" | "issues" | "externalProductServiceExposure" | "companyEngagementMetricsUpdatedAt" | "churnProbability" | "netPromoterScore" | "customerSatisfactionScore" | "lastReportSent" | "subscriptionDate" | "renewalDate" | "dashboardLastSeen" | "lastEngagement";
|
|
10
10
|
export declare const toTaskManagerSortKeyType: (v: string) => "status" | "dueDate" | "name" | "taskName" | "priority" | "assignee" | "tags" | "createdBy";
|
|
11
11
|
export type PortfolioViewSortKey = ReturnType<typeof toPortfolioSortKeyType>;
|
|
12
12
|
export type ManagementViewSortKey = ReturnType<typeof toManagementSortKeyType>;
|
|
@@ -35,6 +35,7 @@ export interface InvoicingAuditLogApiEntry {
|
|
|
35
35
|
target: string;
|
|
36
36
|
time: string;
|
|
37
37
|
timestamp: string;
|
|
38
|
+
action_label?: string;
|
|
38
39
|
change_summary?: unknown[];
|
|
39
40
|
changes?: unknown[];
|
|
40
41
|
context?: Record<string, unknown>;
|
|
@@ -69,6 +70,7 @@ export interface InvoicingAuditEntry {
|
|
|
69
70
|
action: string;
|
|
70
71
|
target: string;
|
|
71
72
|
time: string;
|
|
73
|
+
actionLabel?: string;
|
|
72
74
|
actor?: string;
|
|
73
75
|
customerId?: string;
|
|
74
76
|
detailSegments?: AuditLogDisplaySegment[];
|
|
@@ -42,6 +42,16 @@ function formatActor(actor, sourceLabel) {
|
|
|
42
42
|
}
|
|
43
43
|
return name;
|
|
44
44
|
}
|
|
45
|
+
/**
|
|
46
|
+
* The backend's human-readable action text, or `undefined` when it carries none.
|
|
47
|
+
* Blank copy collapses to `undefined` so the UI's `humanizeToken` fallback runs
|
|
48
|
+
* instead of rendering an empty Action cell, and surrounding whitespace is
|
|
49
|
+
* trimmed so the stored value is what should be displayed verbatim.
|
|
50
|
+
*/
|
|
51
|
+
function invoicingAuditActionLabel(actionLabel) {
|
|
52
|
+
const trimmed = actionLabel?.trim() ?? '';
|
|
53
|
+
return trimmed !== '' ? trimmed : undefined;
|
|
54
|
+
}
|
|
45
55
|
function mapAuditLogEntry(entry) {
|
|
46
56
|
const sourceLabel = entry.source_label ?? '';
|
|
47
57
|
return {
|
|
@@ -52,6 +62,7 @@ function mapAuditLogEntry(entry) {
|
|
|
52
62
|
source: entry.source,
|
|
53
63
|
sourceLabel: sourceLabel || undefined,
|
|
54
64
|
action: entry.action,
|
|
65
|
+
actionLabel: invoicingAuditActionLabel(entry.action_label),
|
|
55
66
|
entityId: entry.entity_id,
|
|
56
67
|
entityType: entry.entity_type,
|
|
57
68
|
customerId: entry.customer_id ?? undefined,
|
|
@@ -5,7 +5,7 @@ export interface InvoicingCouponFilters {
|
|
|
5
5
|
search?: string;
|
|
6
6
|
}
|
|
7
7
|
export declare const ALL_INVOICING_COUPON_SORT_KEYS: readonly ["coupon_id", "name", "discount", "duration", "created", "valid_till", "apply_on", "status", "redemptions"];
|
|
8
|
-
export declare const toInvoicingCouponSortKey: (v: string) => "status" | "name" | "
|
|
8
|
+
export declare const toInvoicingCouponSortKey: (v: string) => "status" | "name" | "discount" | "coupon_id" | "duration" | "created" | "valid_till" | "apply_on" | "redemptions";
|
|
9
9
|
export type InvoicingCouponSortKey = ReturnType<typeof toInvoicingCouponSortKey>;
|
|
10
10
|
/**
|
|
11
11
|
* Structural column descriptor owned by CES so the discounts-list column set,
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import { ID } from '../../../commonStateTypes/common';
|
|
2
2
|
import { SelectorView } from '../../../commonStateTypes/viewAndReport/viewAndReport';
|
|
3
3
|
import { Address } from '../../../entity/address/addressState';
|
|
4
|
-
import { InvoicingSettingsPayload } from '../../../entity/invoicing/invoicingCommonPayload';
|
|
4
|
+
import { InvoicingFieldHelpByCode, InvoicingSettingsPayload } from '../../../entity/invoicing/invoicingCommonPayload';
|
|
5
5
|
import { InvoicingProduct } from '../../../entity/invoicing/product/productState';
|
|
6
6
|
import { RootState } from '../../../rootStateTypes';
|
|
7
7
|
import { InvoicingCreateInvoiceFormLocalData } from './createInvoiceState';
|
|
@@ -26,6 +26,11 @@ export interface InvoicingCreateInvoiceCustomerOption {
|
|
|
26
26
|
}
|
|
27
27
|
export interface CreateInvoiceFormView extends SelectorView {
|
|
28
28
|
customers: InvoicingCreateInvoiceCustomerOption[];
|
|
29
|
+
/**
|
|
30
|
+
* Backend help copy for this screen's field group, keyed by field code.
|
|
31
|
+
* Folded in here so the screen never reaches for the config view itself.
|
|
32
|
+
*/
|
|
33
|
+
fieldHelp: InvoicingFieldHelpByCode;
|
|
29
34
|
localData: InvoicingCreateInvoiceFormLocalData;
|
|
30
35
|
planNames: InvoicingPlanNameOption[];
|
|
31
36
|
products: InvoicingProduct[];
|
|
@@ -3,6 +3,7 @@ Object.defineProperty(exports, "__esModule", { value: true });
|
|
|
3
3
|
exports.getCreateInvoiceFormView = void 0;
|
|
4
4
|
const addressSelector_1 = require("../../../entity/address/addressSelector");
|
|
5
5
|
const invoicingCatalogListViewSelector_1 = require("../invoicingCatalogListView/invoicingCatalogListViewSelector");
|
|
6
|
+
const invoicingConfigViewSelector_1 = require("../invoicingConfigView/invoicingConfigViewSelector");
|
|
6
7
|
const invoicingCustomerListViewSelector_1 = require("../invoicingCustomerListView/invoicingCustomerListViewSelector");
|
|
7
8
|
const settingsViewSelector_1 = require("../settingsView/settingsViewSelector");
|
|
8
9
|
/**
|
|
@@ -35,6 +36,7 @@ const getCreateInvoiceFormView = (state) => {
|
|
|
35
36
|
const createInvoiceState = state.invoicingCreateInvoiceState;
|
|
36
37
|
const catalogListView = (0, invoicingCatalogListViewSelector_1.getInvoicingCatalogListView)(state);
|
|
37
38
|
return {
|
|
39
|
+
fieldHelp: (0, invoicingConfigViewSelector_1.invoicingFieldHelpForGroup)(state, 'invoice'),
|
|
38
40
|
customers: (0, invoicingCustomerListViewSelector_1.getInvoicingCustomerListView)(state).customers.map((customer) => ({
|
|
39
41
|
billingAddress: customer.billingAddressId != null
|
|
40
42
|
? (0, addressSelector_1.getAddressByAddressId)(state.addressState, customer.billingAddressId)
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { FetchStateAndError, ID } from '../../../commonStateTypes/common';
|
|
2
2
|
import { SelectorView } from '../../../commonStateTypes/viewAndReport/viewAndReport';
|
|
3
|
-
import { InvoicingNamedOption, InvoicingNamedOptionsByKey } from '../../../entity/invoicing/invoicingCommonPayload';
|
|
3
|
+
import { InvoicingFieldHelpByCode, InvoicingNamedOption, InvoicingNamedOptionsByKey } from '../../../entity/invoicing/invoicingCommonPayload';
|
|
4
4
|
import { InvoicingPlan } from '../../../entity/invoicing/plan/planState';
|
|
5
5
|
import { RootState } from '../../../rootStateTypes';
|
|
6
6
|
import { InvoicingCatalogItemKind } from '../invoicingCatalogItemDetailView/invoicingCatalogItemDetailViewState';
|
|
@@ -30,6 +30,11 @@ export declare const getInvoicingApplicableCatalogItemOptions: (state: RootState
|
|
|
30
30
|
export interface InvoicingCatalogItemFormView extends SelectorView {
|
|
31
31
|
applicabilityValues: readonly string[];
|
|
32
32
|
applicableItemOptions: ApplicableCatalogItemOption[];
|
|
33
|
+
/**
|
|
34
|
+
* Backend help copy for this screen's field group, keyed by field code.
|
|
35
|
+
* Folded in here so the screen never reaches for the config view itself.
|
|
36
|
+
*/
|
|
37
|
+
fieldHelp: InvoicingFieldHelpByCode;
|
|
33
38
|
localData: InvoicingCatalogItemFormLocalData;
|
|
34
39
|
mode: 'create' | 'edit';
|
|
35
40
|
periodUnitOptions: InvoicingNamedOption[];
|
|
@@ -56,6 +56,7 @@ const getInvoicingCatalogItemFormView = (state, id) => {
|
|
|
56
56
|
: allApplicableItemOptions;
|
|
57
57
|
const { billingPeriodUnitOptions, catalogItemTypeOptions, catalogTierTypeOptionsByPricingModel, catalogTrialEndActionOptions, catalogTrialUnitOptions, } = (0, invoicingConfigViewSelector_1.getInvoicingConfigView)(state);
|
|
58
58
|
return {
|
|
59
|
+
fieldHelp: (0, invoicingConfigViewSelector_1.invoicingFieldHelpForGroup)(state, 'catalog'),
|
|
59
60
|
applicabilityValues: invoicingCatalogItemFormConfig_1.INVOICING_CATALOG_APPLICABILITY_VALUES,
|
|
60
61
|
applicableItemOptions,
|
|
61
62
|
localData,
|
package/lib/view/invoicing/editInvoicingCouponDetailView/editInvoicingCouponDetailViewSelector.d.ts
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import { FetchState, ID } from '../../../commonStateTypes/common';
|
|
2
2
|
import { SelectorView } from '../../../commonStateTypes/viewAndReport/viewAndReport';
|
|
3
3
|
import { InvoicingCoupon } from '../../../entity/invoicing/coupon/couponState';
|
|
4
|
-
import { InvoicingDiscountLifecycleActionOption, InvoicingFormOption } from '../../../entity/invoicing/invoicingCommonPayload';
|
|
4
|
+
import { InvoicingDiscountLifecycleActionOption, InvoicingFieldHelpByCode, InvoicingFormOption } from '../../../entity/invoicing/invoicingCommonPayload';
|
|
5
5
|
import { RootState } from '../../../rootStateTypes';
|
|
6
6
|
import { InvoicingCouponFormLocalData } from './editInvoicingCouponDetailViewState';
|
|
7
7
|
export interface EditInvoicingCouponDetailView extends SelectorView {
|
|
@@ -21,6 +21,11 @@ export interface InvoicingCouponFormView extends EditInvoicingCouponDetailView {
|
|
|
21
21
|
applyOnOptions: InvoicingFormOption[];
|
|
22
22
|
discountTypeOptions: InvoicingFormOption[];
|
|
23
23
|
durationTypeOptions: InvoicingFormOption[];
|
|
24
|
+
/**
|
|
25
|
+
* Backend help copy for this screen's field group, keyed by field code.
|
|
26
|
+
* Folded in here so the screen never reaches for the config view itself.
|
|
27
|
+
*/
|
|
28
|
+
fieldHelp: InvoicingFieldHelpByCode;
|
|
24
29
|
localData: InvoicingCouponFormLocalData;
|
|
25
30
|
mode: 'create' | 'edit';
|
|
26
31
|
periodUnitOptions: InvoicingFormOption[];
|
package/lib/view/invoicing/editInvoicingCouponDetailView/editInvoicingCouponDetailViewSelector.js
CHANGED
|
@@ -41,6 +41,7 @@ const getInvoicingCouponFormView = (state, couponId) => {
|
|
|
41
41
|
: newCouponDraft;
|
|
42
42
|
const { billingPeriodUnitOptions, discountApplyOnOptions, discountDurationTypeOptions, discountTypeOptions, } = (0, invoicingConfigViewSelector_1.getInvoicingConfigView)(state);
|
|
43
43
|
return {
|
|
44
|
+
fieldHelp: (0, invoicingConfigViewSelector_1.invoicingFieldHelpForGroup)(state, 'discount'),
|
|
44
45
|
...base,
|
|
45
46
|
applyOnOptions: discountApplyOnOptions.map(invoicingCommonPayload_1.toInvoicingFormOption),
|
|
46
47
|
discountTypeOptions: discountTypeOptions.map(invoicingCommonPayload_1.toInvoicingFormOption),
|
|
@@ -1,10 +1,15 @@
|
|
|
1
1
|
import { ID } from '../../../commonStateTypes/common';
|
|
2
2
|
import { SelectorView } from '../../../commonStateTypes/viewAndReport/viewAndReport';
|
|
3
|
-
import { InvoicingNamedOption } from '../../../entity/invoicing/invoicingCommonPayload';
|
|
3
|
+
import { InvoicingFieldHelpByCode, InvoicingNamedOption } from '../../../entity/invoicing/invoicingCommonPayload';
|
|
4
4
|
import { RootState } from '../../../rootStateTypes';
|
|
5
5
|
import { InvoicingCustomerFormLocalData } from './editInvoicingCustomerDetailViewState';
|
|
6
6
|
export interface InvoicingCustomerFormView extends SelectorView {
|
|
7
7
|
customerTypeOptions: InvoicingNamedOption[];
|
|
8
|
+
/**
|
|
9
|
+
* Backend help copy for this screen's field group, keyed by field code.
|
|
10
|
+
* Folded in here so the screen never reaches for the config view itself.
|
|
11
|
+
*/
|
|
12
|
+
fieldHelp: InvoicingFieldHelpByCode;
|
|
8
13
|
localData: InvoicingCustomerFormLocalData;
|
|
9
14
|
mode: 'create' | 'edit';
|
|
10
15
|
netTermDayOptions: InvoicingNamedOption[];
|
|
@@ -32,6 +32,7 @@ const getInvoicingCustomerFormView = (state, invoicingCustomerID) => {
|
|
|
32
32
|
: undefined;
|
|
33
33
|
const { customerTypeOptions, netTermDayOptions, taxabilityOptions } = (0, invoicingConfigViewSelector_1.getInvoicingConfigView)(state);
|
|
34
34
|
return {
|
|
35
|
+
fieldHelp: (0, invoicingConfigViewSelector_1.invoicingFieldHelpForGroup)(state, 'customer'),
|
|
35
36
|
customerTypeOptions,
|
|
36
37
|
localData,
|
|
37
38
|
mode,
|
|
@@ -11,5 +11,11 @@ export type SaveInvoicingSubscriptionResponse = ZeniAPIResponse<InvoicingSubscri
|
|
|
11
11
|
* `remaining_billing_cycles` is omitted when the user left the field empty, so
|
|
12
12
|
* the backend applies the plan's own `billing_cycles` (or renews forever when
|
|
13
13
|
* the plan sets no limit) rather than being pinned to a value the form invented.
|
|
14
|
+
*
|
|
15
|
+
* `billing_period` / `billing_period_unit` are deliberately absent. Billing
|
|
16
|
+
* cadence is a property of the selected price point, not of the subscription,
|
|
17
|
+
* and the backend derives it from that price point when the fields are omitted.
|
|
18
|
+
* Sending them made every price point whose cadence the form could not express
|
|
19
|
+
* — a daily plan, for instance — fail with a 422.
|
|
14
20
|
*/
|
|
15
21
|
export declare const localDataToSaveInvoicingSubscriptionPayload: (localData: InvoicingSubscriptionFormLocalData, shippingAddress?: AddressUpdatableInfo) => Record<string, unknown>;
|
|
@@ -11,9 +11,14 @@ const invoicingSubscriptionFormConfig_1 = require("./invoicingSubscriptionFormCo
|
|
|
11
11
|
* `remaining_billing_cycles` is omitted when the user left the field empty, so
|
|
12
12
|
* the backend applies the plan's own `billing_cycles` (or renews forever when
|
|
13
13
|
* the plan sets no limit) rather than being pinned to a value the form invented.
|
|
14
|
+
*
|
|
15
|
+
* `billing_period` / `billing_period_unit` are deliberately absent. Billing
|
|
16
|
+
* cadence is a property of the selected price point, not of the subscription,
|
|
17
|
+
* and the backend derives it from that price point when the fields are omitted.
|
|
18
|
+
* Sending them made every price point whose cadence the form could not express
|
|
19
|
+
* — a daily plan, for instance — fail with a 422.
|
|
14
20
|
*/
|
|
15
21
|
const localDataToSaveInvoicingSubscriptionPayload = (localData, shippingAddress) => {
|
|
16
|
-
const frequency = (0, invoicingSubscriptionFormConfig_1.billingFrequencyToPeriod)(localData.billingFrequency);
|
|
17
22
|
const items = [
|
|
18
23
|
{
|
|
19
24
|
item_price_code: localData.planPriceCode,
|
|
@@ -38,8 +43,6 @@ const localDataToSaveInvoicingSubscriptionPayload = (localData, shippingAddress)
|
|
|
38
43
|
const remainingBillingCycles = (0, invoicingSubscriptionFormConfig_1.toInvoicingSubscriptionBillingCycles)(localData.remainingBillingCycles);
|
|
39
44
|
return {
|
|
40
45
|
auto_collection: localData.autoCollection ? 'on' : 'off',
|
|
41
|
-
billing_period: frequency.period,
|
|
42
|
-
billing_period_unit: frequency.unit,
|
|
43
46
|
currency_code: localData.preferredCurrencyCode,
|
|
44
47
|
customer_id: localData.customerId,
|
|
45
48
|
started_at: startedAt !== '' ? startedAt : (0, invoicingSubscriptionFormConfig_1.invoicingSubscriptionTodayIso)(),
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
import { ID } from '../../../commonStateTypes/common';
|
|
2
2
|
import { SelectorView } from '../../../commonStateTypes/viewAndReport/viewAndReport';
|
|
3
3
|
import { InvoicingCoupon } from '../../../entity/invoicing/coupon/couponState';
|
|
4
|
-
import { InvoicingSubscriptionLifecycleActionOption } from '../../../entity/invoicing/invoicingCommonPayload';
|
|
4
|
+
import { InvoicingFieldHelpByCode, InvoicingSubscriptionLifecycleActionOption } from '../../../entity/invoicing/invoicingCommonPayload';
|
|
5
5
|
import { InvoicingCustomer } from '../../../entity/invoicing/invoicingCustomer/invoicingCustomerState';
|
|
6
6
|
import { InvoicingSubscription } from '../../../entity/invoicing/invoicingSubscription/invoicingSubscriptionState';
|
|
7
7
|
import { InvoicingProduct } from '../../../entity/invoicing/product/productState';
|
|
@@ -30,9 +30,13 @@ export interface EditInvoicingSubscriptionDetailView extends SelectorView {
|
|
|
30
30
|
* to its own option shapes, so this stays free of any web-components dependency.
|
|
31
31
|
*/
|
|
32
32
|
export interface InvoicingSubscriptionFormView extends SelectorView {
|
|
33
|
-
billingFrequencyValues: string[];
|
|
34
33
|
coupons: InvoicingCoupon[];
|
|
35
34
|
customers: InvoicingCustomer[];
|
|
35
|
+
/**
|
|
36
|
+
* Backend help copy for this screen's field group, keyed by field code.
|
|
37
|
+
* Folded in here so the screen never reaches for the config view itself.
|
|
38
|
+
*/
|
|
39
|
+
fieldHelp: InvoicingFieldHelpByCode;
|
|
36
40
|
localData: InvoicingSubscriptionFormLocalData;
|
|
37
41
|
mode: 'create' | 'edit';
|
|
38
42
|
plans: InvoicingProduct[];
|
|
@@ -46,9 +46,7 @@ const getInvoicingSubscriptionFormView = (state, invoicingSubscriptionID) => {
|
|
|
46
46
|
const planPrices = (0, invoicingCatalogListViewSelector_1.getInvoicingCatalogPrices)(catalogListView.plans);
|
|
47
47
|
const addonAndChargePrices = (0, invoicingCatalogListViewSelector_1.getInvoicingCatalogPrices)(catalogListView.products);
|
|
48
48
|
return {
|
|
49
|
-
|
|
50
|
-
...invoicingSubscriptionFormConfig_1.INVOICING_SUBSCRIPTION_BILLING_FREQUENCY_VALUES,
|
|
51
|
-
],
|
|
49
|
+
fieldHelp: (0, invoicingConfigViewSelector_1.invoicingFieldHelpForGroup)(state, 'subscription'),
|
|
52
50
|
coupons: (0, couponViewSelector_1.getInvoicingCouponListItems)(state),
|
|
53
51
|
customers: (0, invoicingCustomerListViewSelector_1.getInvoicingCustomerListView)(state).customers,
|
|
54
52
|
localData,
|
|
@@ -16,7 +16,6 @@ export interface InvoicingSubscriptionFormLocalData {
|
|
|
16
16
|
*/
|
|
17
17
|
addonQuantities: Record<string, number>;
|
|
18
18
|
autoCollection: boolean;
|
|
19
|
-
billingFrequency: string;
|
|
20
19
|
chargePriceCodes: string[];
|
|
21
20
|
/** Per-charge quantity, keyed by item price code. See `addonQuantities`. */
|
|
22
21
|
chargeQuantities: Record<string, number>;
|
package/lib/view/invoicing/editInvoicingSubscriptionDetailView/invoicingSubscriptionFormConfig.d.ts
CHANGED
|
@@ -2,19 +2,6 @@ import { InvoicingSubscription } from '../../../entity/invoicing/invoicingSubscr
|
|
|
2
2
|
import { InvoicingSubscriptionFormLocalData } from './editInvoicingSubscriptionDetailViewState';
|
|
3
3
|
/** `AddressType` key used when the subscription form opens the shared Address screen. */
|
|
4
4
|
export declare const INVOICING_SUBSCRIPTION_SHIPPING_ADDRESS_TYPE: "invoicing_subscription_shipping_address";
|
|
5
|
-
/**
|
|
6
|
-
* Canonical billing-frequency value set for the subscription form. CES owns the
|
|
7
|
-
* values (and their period/unit mapping); web-components maps each value to a
|
|
8
|
-
* localized label (same split as the customer form's value sets).
|
|
9
|
-
*/
|
|
10
|
-
export declare const INVOICING_SUBSCRIPTION_BILLING_FREQUENCY_VALUES: readonly ["weekly", "monthly", "quarterly", "half_yearly", "yearly"];
|
|
11
|
-
/** Map a billing-frequency value to its API `billing_period` / `billing_period_unit`. */
|
|
12
|
-
export declare const billingFrequencyToPeriod: (value: string) => {
|
|
13
|
-
period: number;
|
|
14
|
-
unit: string;
|
|
15
|
-
};
|
|
16
|
-
/** Map an existing subscription's period/unit back to a billing-frequency value. */
|
|
17
|
-
export declare const periodToBillingFrequency: (period?: number, unit?: string) => string;
|
|
18
5
|
/**
|
|
19
6
|
* Today as `YYYY-MM-DD`, the default subscription start date. Goes through
|
|
20
7
|
* dayjs (not `toISOString`, which is UTC) so a user in a UTC+ timezone late in
|
package/lib/view/invoicing/editInvoicingSubscriptionDetailView/invoicingSubscriptionFormConfig.js
CHANGED
|
@@ -1,40 +1,9 @@
|
|
|
1
1
|
"use strict";
|
|
2
2
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
-
exports.entityToInvoicingSubscriptionFormLocalData = exports.initialInvoicingSubscriptionFormLocalData = exports.toInvoicingSubscriptionBillingCycles = exports.toInvoicingSubscriptionQuantity = exports.invoicingSubscriptionTodayIso = exports.
|
|
3
|
+
exports.entityToInvoicingSubscriptionFormLocalData = exports.initialInvoicingSubscriptionFormLocalData = exports.toInvoicingSubscriptionBillingCycles = exports.toInvoicingSubscriptionQuantity = exports.invoicingSubscriptionTodayIso = exports.INVOICING_SUBSCRIPTION_SHIPPING_ADDRESS_TYPE = void 0;
|
|
4
4
|
const zeniDayJS_1 = require("../../../zeniDayJS");
|
|
5
5
|
/** `AddressType` key used when the subscription form opens the shared Address screen. */
|
|
6
6
|
exports.INVOICING_SUBSCRIPTION_SHIPPING_ADDRESS_TYPE = 'invoicing_subscription_shipping_address';
|
|
7
|
-
/**
|
|
8
|
-
* Canonical billing-frequency value set for the subscription form. CES owns the
|
|
9
|
-
* values (and their period/unit mapping); web-components maps each value to a
|
|
10
|
-
* localized label (same split as the customer form's value sets).
|
|
11
|
-
*/
|
|
12
|
-
exports.INVOICING_SUBSCRIPTION_BILLING_FREQUENCY_VALUES = [
|
|
13
|
-
'weekly',
|
|
14
|
-
'monthly',
|
|
15
|
-
'quarterly',
|
|
16
|
-
'half_yearly',
|
|
17
|
-
'yearly',
|
|
18
|
-
];
|
|
19
|
-
const BILLING_FREQUENCY_TO_PERIOD = {
|
|
20
|
-
weekly: { period: 1, unit: 'week' },
|
|
21
|
-
monthly: { period: 1, unit: 'month' },
|
|
22
|
-
quarterly: { period: 3, unit: 'month' },
|
|
23
|
-
half_yearly: { period: 6, unit: 'month' },
|
|
24
|
-
yearly: { period: 1, unit: 'year' },
|
|
25
|
-
};
|
|
26
|
-
/** Map a billing-frequency value to its API `billing_period` / `billing_period_unit`. */
|
|
27
|
-
const billingFrequencyToPeriod = (value) => BILLING_FREQUENCY_TO_PERIOD[value] ?? BILLING_FREQUENCY_TO_PERIOD.monthly;
|
|
28
|
-
exports.billingFrequencyToPeriod = billingFrequencyToPeriod;
|
|
29
|
-
/** Map an existing subscription's period/unit back to a billing-frequency value. */
|
|
30
|
-
const periodToBillingFrequency = (period, unit) => {
|
|
31
|
-
const match = exports.INVOICING_SUBSCRIPTION_BILLING_FREQUENCY_VALUES.find((value) => {
|
|
32
|
-
const mapped = BILLING_FREQUENCY_TO_PERIOD[value];
|
|
33
|
-
return mapped.period === period && mapped.unit === unit;
|
|
34
|
-
});
|
|
35
|
-
return match ?? 'monthly';
|
|
36
|
-
};
|
|
37
|
-
exports.periodToBillingFrequency = periodToBillingFrequency;
|
|
38
7
|
const subscriptionItemPriceCodes = (subscription, itemType) => subscription?.subscriptionItems
|
|
39
8
|
?.filter((item) => item.itemType === itemType)
|
|
40
9
|
.map((item) => item.itemPriceCode)
|
|
@@ -88,7 +57,6 @@ exports.initialInvoicingSubscriptionFormLocalData = {
|
|
|
88
57
|
addonPriceCodes: [],
|
|
89
58
|
addonQuantities: {},
|
|
90
59
|
autoCollection: true,
|
|
91
|
-
billingFrequency: 'monthly',
|
|
92
60
|
chargePriceCodes: [],
|
|
93
61
|
chargeQuantities: {},
|
|
94
62
|
couponId: '',
|
|
@@ -111,7 +79,6 @@ const entityToInvoicingSubscriptionFormLocalData = (subscription) => {
|
|
|
111
79
|
addonPriceCodes: subscriptionItemPriceCodes(subscription, 'addon'),
|
|
112
80
|
addonQuantities: subscriptionItemQuantities(subscription, 'addon'),
|
|
113
81
|
autoCollection: (subscription.autoCollection ?? 'on') === 'on',
|
|
114
|
-
billingFrequency: (0, exports.periodToBillingFrequency)(subscription.billingPeriod, subscription.billingPeriodUnit),
|
|
115
82
|
chargePriceCodes: subscriptionItemPriceCodes(subscription, 'charge'),
|
|
116
83
|
chargeQuantities: subscriptionItemQuantities(subscription, 'charge'),
|
|
117
84
|
couponId: subscription.coupons?.[0]?.couponCode ??
|
|
@@ -2,6 +2,7 @@ import { FetchStateAndError, ID } from '../../../commonStateTypes/common';
|
|
|
2
2
|
import { SelectorView } from '../../../commonStateTypes/viewAndReport/viewAndReport';
|
|
3
3
|
import { Address } from '../../../entity/address/addressState';
|
|
4
4
|
import { InvoicingInvoice } from '../../../entity/invoicing/invoice/invoiceState';
|
|
5
|
+
import type { InvoicingFieldHelpByCode } from '../../../entity/invoicing/invoicingCommonPayload';
|
|
5
6
|
import { RootState } from '../../../rootStateTypes';
|
|
6
7
|
/**
|
|
7
8
|
* Read-only view for the invoice detail page: the invoice entity + its per-id
|
|
@@ -11,6 +12,11 @@ import { RootState } from '../../../rootStateTypes';
|
|
|
11
12
|
*/
|
|
12
13
|
export interface InvoiceDetailView extends SelectorView {
|
|
13
14
|
actionState: FetchStateAndError;
|
|
15
|
+
/**
|
|
16
|
+
* Backend help copy for this screen's field group, keyed by field code.
|
|
17
|
+
* Folded in here so the screen never reaches for the config view itself.
|
|
18
|
+
*/
|
|
19
|
+
fieldHelp: InvoicingFieldHelpByCode;
|
|
14
20
|
billingAddress?: Address;
|
|
15
21
|
invoice?: InvoicingInvoice;
|
|
16
22
|
shippingAddress?: Address;
|
|
@@ -8,10 +8,12 @@ const get_1 = __importDefault(require("lodash/get"));
|
|
|
8
8
|
const addressSelector_1 = require("../../../entity/address/addressSelector");
|
|
9
9
|
const invoiceSelector_1 = require("../../../entity/invoicing/invoice/invoiceSelector");
|
|
10
10
|
const invoiceActionSelector_1 = require("../invoiceAction/invoiceActionSelector");
|
|
11
|
+
const invoicingConfigViewSelector_1 = require("../invoicingConfigView/invoicingConfigViewSelector");
|
|
11
12
|
const getInvoiceDetail = (state, invoiceId) => {
|
|
12
13
|
const detail = (0, get_1.default)(state.invoicingInvoiceDetailState.detailById, invoiceId, undefined);
|
|
13
14
|
const invoice = (0, invoiceSelector_1.getInvoiceById)(state.invoicingInvoiceState, invoiceId);
|
|
14
15
|
return {
|
|
16
|
+
fieldHelp: (0, invoicingConfigViewSelector_1.invoicingFieldHelpForGroup)(state, 'invoice'),
|
|
15
17
|
invoice,
|
|
16
18
|
billingAddress: invoice?.billingAddressId != null
|
|
17
19
|
? (0, addressSelector_1.getAddressByAddressId)(state.addressState, invoice.billingAddressId)
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
import { FetchState, ID } from '../../../commonStateTypes/common';
|
|
2
2
|
import { SelectorView } from '../../../commonStateTypes/viewAndReport/viewAndReport';
|
|
3
|
-
import { InvoicingCatalogItemLifecycleAction, InvoicingCatalogLifecycleActionOption, InvoicingCatalogProductLifecycleAction, InvoicingNamedOption, InvoicingNamedOptionsByKey } from '../../../entity/invoicing/invoicingCommonPayload';
|
|
3
|
+
import { InvoicingCatalogItemLifecycleAction, InvoicingCatalogLifecycleActionOption, InvoicingCatalogProductLifecycleAction, InvoicingFieldHelpByCode, InvoicingNamedOption, InvoicingNamedOptionsByKey } from '../../../entity/invoicing/invoicingCommonPayload';
|
|
4
4
|
import { InvoicingPlan } from '../../../entity/invoicing/plan/planState';
|
|
5
5
|
import { RootState } from '../../../rootStateTypes';
|
|
6
6
|
import { InvoicingCatalogItemKind } from './invoicingCatalogItemDetailViewState';
|
|
@@ -20,6 +20,11 @@ export interface InvoicingCatalogItemDetailView extends SelectorView {
|
|
|
20
20
|
catalogItemLifecycleActionOptions: InvoicingCatalogLifecycleActionOption<InvoicingCatalogItemLifecycleAction>[];
|
|
21
21
|
catalogProductLifecycleActionOptions: InvoicingCatalogLifecycleActionOption<InvoicingCatalogProductLifecycleAction>[];
|
|
22
22
|
configFetchState: FetchState;
|
|
23
|
+
/**
|
|
24
|
+
* Backend help copy for this screen's field group, keyed by field code.
|
|
25
|
+
* Folded in here so the screen never reaches for the config view itself.
|
|
26
|
+
*/
|
|
27
|
+
fieldHelp: InvoicingFieldHelpByCode;
|
|
23
28
|
/**
|
|
24
29
|
* Config option lists the detail page's inline pricing editor renders, so the
|
|
25
30
|
* screen reads them off this view instead of `getInvoicingConfigView`.
|