@mj-biz-apps/sales-entities 5.1.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (42) hide show
  1. package/LICENSE +183 -0
  2. package/dist/activities/activity-vocabulary.d.ts +103 -0
  3. package/dist/activities/activity-vocabulary.d.ts.map +1 -0
  4. package/dist/activities/activity-vocabulary.js +79 -0
  5. package/dist/activities/activity-vocabulary.js.map +1 -0
  6. package/dist/close-lock.d.ts +72 -0
  7. package/dist/close-lock.d.ts.map +1 -0
  8. package/dist/close-lock.js +94 -0
  9. package/dist/close-lock.js.map +1 -0
  10. package/dist/deal-draft.d.ts +207 -0
  11. package/dist/deal-draft.d.ts.map +1 -0
  12. package/dist/deal-draft.js +318 -0
  13. package/dist/deal-draft.js.map +1 -0
  14. package/dist/deal-entity.d.ts +236 -0
  15. package/dist/deal-entity.d.ts.map +1 -0
  16. package/dist/deal-entity.js +383 -0
  17. package/dist/deal-entity.js.map +1 -0
  18. package/dist/discount-conversion.d.ts +94 -0
  19. package/dist/discount-conversion.d.ts.map +1 -0
  20. package/dist/discount-conversion.js +128 -0
  21. package/dist/discount-conversion.js.map +1 -0
  22. package/dist/downstream-seams.d.ts +179 -0
  23. package/dist/downstream-seams.d.ts.map +1 -0
  24. package/dist/downstream-seams.js +77 -0
  25. package/dist/downstream-seams.js.map +1 -0
  26. package/dist/generated/entity_subclasses.d.ts +4208 -0
  27. package/dist/generated/entity_subclasses.d.ts.map +1 -0
  28. package/dist/generated/entity_subclasses.js +6073 -0
  29. package/dist/generated/entity_subclasses.js.map +1 -0
  30. package/dist/generated/remote_operations.d.ts +2396 -0
  31. package/dist/generated/remote_operations.d.ts.map +1 -0
  32. package/dist/generated/remote_operations.js +660 -0
  33. package/dist/generated/remote_operations.js.map +1 -0
  34. package/dist/index.d.ts +46 -0
  35. package/dist/index.d.ts.map +1 -0
  36. package/dist/index.js +47 -0
  37. package/dist/index.js.map +1 -0
  38. package/dist/product-filter.d.ts +66 -0
  39. package/dist/product-filter.d.ts.map +1 -0
  40. package/dist/product-filter.js +63 -0
  41. package/dist/product-filter.js.map +1 -0
  42. package/package.json +37 -0
@@ -0,0 +1,207 @@
1
+ /**
2
+ * @fileoverview `DealDraft` — the client-side model of a deal being composed.
3
+ *
4
+ * WHY THIS EXISTS. `DealEntityServer` composes a whole deal — header, lines, payment schedule — and
5
+ * writes it in one transaction. A browser cannot use any of that. The class the client holds is the
6
+ * GENERATED `mjBizAppsSalesDealEntity`, not the server subclass, so `.Lines` does not exist there and
7
+ * the transient children have no way to cross the entity-save boundary as scalar fields. The only
8
+ * alternative is what a UI does when it has no other option: save the deal, then each line, then each
9
+ * instalment, as separate round trips — and a failure partway leaves a numbered deal with nothing
10
+ * under it.
11
+ *
12
+ * `DealDraft` is the other half of the answer: something the UI holds and mutates that knows how to
13
+ * become the payload `Sales.SaveDeal` accepts, which the server then rehydrates into the real entity
14
+ * tree. bizapps-orders solved this with `OrderDraft` and bizapps-contracts with `ContractDraft`; this
15
+ * is that pattern applied to a deal.
16
+ *
17
+ * ── WHAT IT DELIBERATELY DOES NOT DO ────────────────────────────────────────────────────────────
18
+ *
19
+ * IT DOES NOT PRICE ANYTHING, and it does not re-implement a single business rule. This app's first
20
+ * rule is that sales never computes money: no multiplying quantity by price, no applying a discount
21
+ * percentage, no summing lines into a header total, no rounding. That rule holds here too. In
22
+ * particular `Total` is NOT derived from `AnnualGrossFees - DiscountAmount` — those three are figures
23
+ * transcribed from a signed document, and the subtraction on the page belongs to the customer and the
24
+ * account director, not to this class. `Validate()` does not check that they are consistent with each
25
+ * other either, because doing so would be asserting the arithmetic by the back door.
26
+ *
27
+ * Likewise the close lock, owner-role uniqueness, company/pipeline agreement and deal numbering all
28
+ * live in the entity subclasses on the server, on the one path every write takes. A second
29
+ * implementation living next to the UI is the thing that eventually disagrees with the first, and the
30
+ * disagreement surfaces as a deal the form said was fine and the server refused.
31
+ *
32
+ * What {@link DealDraft.Validate} checks is only what a form can honestly check without a database:
33
+ * is a required field filled in, do these dates make sense against each other, does this line have a
34
+ * product name. Everything it reports is a REQUIREMENT the user must satisfy before the server will
35
+ * even look at the record — never a judgement about whether the deal is sound.
36
+ *
37
+ * ── FRAMEWORK-FREE ON PURPOSE ───────────────────────────────────────────────────────────────────
38
+ *
39
+ * No Angular, no DOM, no MJ provider. Three consequences that all matter: the create surface and the
40
+ * edit surface can bind to the SAME instance rather than to copies that drift; the whole model is
41
+ * unit-testable with no harness; and the validation shape below can be lifted into MJ core later
42
+ * without dragging a UI framework behind it.
43
+ *
44
+ * @module @mj-biz-apps/sales-entities
45
+ */
46
+ import type { SalesSaveDealInput } from './generated/remote_operations.js';
47
+ /** Which pane of the deal workspace an issue belongs to. Matches the tab keys EXACTLY. */
48
+ export type DealDraftSection = 'party' | 'lines' | 'schedule' | 'terms' | 'variances';
49
+ export type DealDraftSeverity = 'error' | 'warning';
50
+ /** One problem with the draft, addressed to the part of the UI that can fix it. */
51
+ export interface DealDraftIssue {
52
+ Section: DealDraftSection;
53
+ /** The offending field, where one field owns the problem. Null for whole-section issues. */
54
+ Field: string | null;
55
+ /** For a line or instalment issue: which row, by its ClientKey. */
56
+ ClientKey: string | null;
57
+ Severity: DealDraftSeverity;
58
+ /** Human-readable and safe to show verbatim. */
59
+ Message: string;
60
+ }
61
+ export interface DealDraftValidation {
62
+ /** False when at least one issue is an error. Warnings alone do not block a save. */
63
+ IsValid: boolean;
64
+ Issues: DealDraftIssue[];
65
+ }
66
+ /**
67
+ * A line being composed. `ClientKey` is the identity the FORM uses — it exists from the moment the
68
+ * row is added, whereas `ID` only exists after a save, and a grid needs a stable key before then.
69
+ */
70
+ export interface DealDraftLine {
71
+ ClientKey: string;
72
+ /** Null until this line has been saved at least once. */
73
+ ID: string | null;
74
+ ProductID: string | null;
75
+ ProductName: string | null;
76
+ DealLineTypeID: string | null;
77
+ Quantity: number;
78
+ RequestedDiscountPct: number | null;
79
+ OverrideUnitPrice: number | null;
80
+ /** The signed figures. Transcribed, never derived — see the file header. */
81
+ AnnualGrossFees: number | null;
82
+ DiscountAmount: number | null;
83
+ Total: number | null;
84
+ TermMonths: number | null;
85
+ ServicePeriodStart: string | null;
86
+ ServicePeriodEnd: string | null;
87
+ Description: string | null;
88
+ }
89
+ /** One negotiated instalment. No rows at all is the normal case — standard terms. */
90
+ export interface DealDraftScheduleRow {
91
+ ClientKey: string;
92
+ ID: string | null;
93
+ PaymentDate: string | null;
94
+ Amount: number | null;
95
+ Description: string | null;
96
+ }
97
+ /** The deal header, as the form holds it. */
98
+ export interface DealDraftHeader {
99
+ ID: string | null;
100
+ Name: string;
101
+ PipelineID: string | null;
102
+ PipelineStageID: string | null;
103
+ DealTypeID: string | null;
104
+ DealStatusTypeID: string | null;
105
+ AccountID: string | null;
106
+ PrimaryContactID: string | null;
107
+ BillingContactID: string | null;
108
+ CompanyID: string | null;
109
+ OwnerEmployeeID: string | null;
110
+ Amount: number | null;
111
+ CurrencyID: string | null;
112
+ TermMonths: number | null;
113
+ EstimatedProjectWeeks: number | null;
114
+ ExecutionDate: string | null;
115
+ StartDate: string | null;
116
+ ExpectedCloseDate: string | null;
117
+ Probability: number | null;
118
+ ForecastCategoryTypeID: string | null;
119
+ LeadSourceTypeID: string | null;
120
+ AutoRenew: boolean;
121
+ AnnualIncreasePctOverride: number | null;
122
+ CancellationNoticeDaysOverride: number | null;
123
+ PaymentMethod: string | null;
124
+ ContractVariances: string | null;
125
+ Description: string | null;
126
+ NextStep: string | null;
127
+ NextStepDate: string | null;
128
+ }
129
+ /**
130
+ * The house defaults the form pre-fills. `AnnualIncreasePctOverride` and
131
+ * `CancellationNoticeDaysOverride` are NOT among them, deliberately: their real defaults (5% / 90
132
+ * days) live on the contracts ContractType, and null here means "use the standard term". Writing 5
133
+ * and 90 into every draft would freeze this year's policy into next year's renewals. The FORM may
134
+ * display 5 and 90 as placeholder text — that is presentation — but the draft must send null unless
135
+ * the AD actually typed something else.
136
+ */
137
+ export declare const DEAL_DRAFT_DEFAULT_PAYMENT_METHOD = "ACH";
138
+ /**
139
+ * A deal being composed, whether it is new or being edited. The create surface and the edit surface
140
+ * bind to the same class on purpose: a deal being created is just a draft whose `ID` is null, and two
141
+ * separate models would drift apart within a release.
142
+ */
143
+ export declare class DealDraft {
144
+ Header: DealDraftHeader;
145
+ Lines: DealDraftLine[];
146
+ Schedule: DealDraftScheduleRow[];
147
+ /**
148
+ * Monotonic counter behind {@link NextClientKey}. Not an ID and never persisted — it only has to
149
+ * be unique within one editing session, which is all a grid key needs.
150
+ */
151
+ private _keySeq;
152
+ constructor(header?: Partial<DealDraftHeader>);
153
+ /** True when this draft has never been saved — what the UI reads to say "New Deal". */
154
+ get IsNew(): boolean;
155
+ /** A session-unique key for a new row. See {@link _keySeq}. */
156
+ NextClientKey(prefix: string): string;
157
+ /** Appends an empty line and returns it, so the caller can bind to it immediately. */
158
+ AddLine(seed?: Partial<DealDraftLine>): DealDraftLine;
159
+ /**
160
+ * Removes a line from the draft. No deleted-row bookkeeping is needed here — unlike the server
161
+ * subclass, the draft sends its lines as the COMPLETE desired set, so a row that is gone from the
162
+ * array is gone from the payload, and the server deletes whatever is no longer named.
163
+ */
164
+ RemoveLine(lineOrKey: DealDraftLine | string): boolean;
165
+ /** Appends an empty instalment and returns it. */
166
+ AddScheduleRow(seed?: Partial<DealDraftScheduleRow>): DealDraftScheduleRow;
167
+ RemoveScheduleRow(rowOrKey: DealDraftScheduleRow | string): boolean;
168
+ /**
169
+ * What a form can honestly check with no database behind it. Every issue here is a REQUIREMENT
170
+ * the server will reject the draft for anyway — never a judgement about the commercial sense of
171
+ * the deal, and never anything that needs arithmetic.
172
+ */
173
+ Validate(): DealDraftValidation;
174
+ /** Issues for one section — what a tab reads to decide whether to show a badge. */
175
+ IssuesFor(section: DealDraftSection, validation?: DealDraftValidation): DealDraftIssue[];
176
+ /**
177
+ * Becomes the `Sales.SaveDeal` input.
178
+ *
179
+ * TYPED AS THE GENERATED CONTRACT, not as a loose bag. `SalesSaveDealInput` comes from the
180
+ * operation's own metadata, so binding to it here means a field renamed on the server breaks this
181
+ * method at compile time instead of silently dropping out of the payload at runtime. That is the
182
+ * only reason this otherwise framework-free class imports anything.
183
+ *
184
+ * `Lines` and `PaymentSchedule` are ALWAYS included, even when empty, because the operation treats
185
+ * a present array as the complete desired set and an absent one as "leave the children alone". A
186
+ * workspace that holds the whole tree always means the former — if it is showing the user zero
187
+ * lines, zero lines is the intent.
188
+ */
189
+ ToSaveInput(): SalesSaveDealInput;
190
+ /**
191
+ * Folds a successful save result back in, so the same instance keeps being the live model instead
192
+ * of the caller rebuilding one. Matching is by `ClientKey` — which is exactly why the operation
193
+ * echoes it back.
194
+ */
195
+ ApplySaveResult(result: {
196
+ DealID?: string | null;
197
+ Lines?: Array<{
198
+ ClientKey?: string | null;
199
+ ID: string;
200
+ }>;
201
+ PaymentSchedule?: Array<{
202
+ ClientKey?: string | null;
203
+ ID: string;
204
+ }>;
205
+ }): void;
206
+ }
207
+ //# sourceMappingURL=deal-draft.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"deal-draft.d.ts","sourceRoot":"","sources":["../src/deal-draft.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,318 @@
1
+ /**
2
+ * The house defaults the form pre-fills. `AnnualIncreasePctOverride` and
3
+ * `CancellationNoticeDaysOverride` are NOT among them, deliberately: their real defaults (5% / 90
4
+ * days) live on the contracts ContractType, and null here means "use the standard term". Writing 5
5
+ * and 90 into every draft would freeze this year's policy into next year's renewals. The FORM may
6
+ * display 5 and 90 as placeholder text — that is presentation — but the draft must send null unless
7
+ * the AD actually typed something else.
8
+ */
9
+ export const DEAL_DRAFT_DEFAULT_PAYMENT_METHOD = 'ACH';
10
+ /* ────────────────────────────────────────────────────────────────────────────
11
+ * The draft
12
+ * ──────────────────────────────────────────────────────────────────────────── */
13
+ /**
14
+ * A deal being composed, whether it is new or being edited. The create surface and the edit surface
15
+ * bind to the same class on purpose: a deal being created is just a draft whose `ID` is null, and two
16
+ * separate models would drift apart within a release.
17
+ */
18
+ export class DealDraft {
19
+ constructor(header) {
20
+ this.Lines = [];
21
+ this.Schedule = [];
22
+ /**
23
+ * Monotonic counter behind {@link NextClientKey}. Not an ID and never persisted — it only has to
24
+ * be unique within one editing session, which is all a grid key needs.
25
+ */
26
+ this._keySeq = 0;
27
+ this.Header = {
28
+ ID: null,
29
+ Name: '',
30
+ PipelineID: null,
31
+ PipelineStageID: null,
32
+ DealTypeID: null,
33
+ DealStatusTypeID: null,
34
+ AccountID: null,
35
+ PrimaryContactID: null,
36
+ BillingContactID: null,
37
+ CompanyID: null,
38
+ OwnerEmployeeID: null,
39
+ Amount: null,
40
+ CurrencyID: null,
41
+ TermMonths: null,
42
+ EstimatedProjectWeeks: null,
43
+ ExecutionDate: null,
44
+ StartDate: null,
45
+ ExpectedCloseDate: null,
46
+ Probability: null,
47
+ ForecastCategoryTypeID: null,
48
+ LeadSourceTypeID: null,
49
+ AutoRenew: false,
50
+ AnnualIncreasePctOverride: null,
51
+ CancellationNoticeDaysOverride: null,
52
+ PaymentMethod: DEAL_DRAFT_DEFAULT_PAYMENT_METHOD,
53
+ ContractVariances: null,
54
+ Description: null,
55
+ NextStep: null,
56
+ NextStepDate: null,
57
+ ...header,
58
+ };
59
+ }
60
+ /** True when this draft has never been saved — what the UI reads to say "New Deal". */
61
+ get IsNew() {
62
+ return !this.Header.ID;
63
+ }
64
+ /** A session-unique key for a new row. See {@link _keySeq}. */
65
+ NextClientKey(prefix) {
66
+ this._keySeq += 1;
67
+ return `${prefix}-${this._keySeq}`;
68
+ }
69
+ /* ── Lines ──────────────────────────────────────────────────────────── */
70
+ /** Appends an empty line and returns it, so the caller can bind to it immediately. */
71
+ AddLine(seed) {
72
+ const line = {
73
+ ClientKey: this.NextClientKey('line'),
74
+ ID: null,
75
+ ProductID: null,
76
+ ProductName: null,
77
+ DealLineTypeID: null,
78
+ Quantity: 1,
79
+ RequestedDiscountPct: null,
80
+ OverrideUnitPrice: null,
81
+ AnnualGrossFees: null,
82
+ DiscountAmount: null,
83
+ Total: null,
84
+ TermMonths: null,
85
+ ServicePeriodStart: null,
86
+ ServicePeriodEnd: null,
87
+ Description: null,
88
+ ...seed,
89
+ };
90
+ this.Lines.push(line);
91
+ return line;
92
+ }
93
+ /**
94
+ * Removes a line from the draft. No deleted-row bookkeeping is needed here — unlike the server
95
+ * subclass, the draft sends its lines as the COMPLETE desired set, so a row that is gone from the
96
+ * array is gone from the payload, and the server deletes whatever is no longer named.
97
+ */
98
+ RemoveLine(lineOrKey) {
99
+ const key = typeof lineOrKey === 'string' ? lineOrKey : lineOrKey.ClientKey;
100
+ const idx = this.Lines.findIndex((l) => l.ClientKey === key);
101
+ if (idx < 0) {
102
+ return false;
103
+ }
104
+ this.Lines.splice(idx, 1);
105
+ return true;
106
+ }
107
+ /* ── Payment schedule ───────────────────────────────────────────────── */
108
+ /** Appends an empty instalment and returns it. */
109
+ AddScheduleRow(seed) {
110
+ const row = {
111
+ ClientKey: this.NextClientKey('pay'),
112
+ ID: null,
113
+ PaymentDate: null,
114
+ Amount: null,
115
+ Description: null,
116
+ ...seed,
117
+ };
118
+ this.Schedule.push(row);
119
+ return row;
120
+ }
121
+ RemoveScheduleRow(rowOrKey) {
122
+ const key = typeof rowOrKey === 'string' ? rowOrKey : rowOrKey.ClientKey;
123
+ const idx = this.Schedule.findIndex((r) => r.ClientKey === key);
124
+ if (idx < 0) {
125
+ return false;
126
+ }
127
+ this.Schedule.splice(idx, 1);
128
+ return true;
129
+ }
130
+ /* ── Validation ─────────────────────────────────────────────────────── */
131
+ /**
132
+ * What a form can honestly check with no database behind it. Every issue here is a REQUIREMENT
133
+ * the server will reject the draft for anyway — never a judgement about the commercial sense of
134
+ * the deal, and never anything that needs arithmetic.
135
+ */
136
+ Validate() {
137
+ const issues = [];
138
+ const err = (Section, Field, Message, ClientKey = null) => {
139
+ issues.push({ Section, Field, ClientKey, Severity: 'error', Message });
140
+ };
141
+ const warn = (Section, Field, Message, ClientKey = null) => {
142
+ issues.push({ Section, Field, ClientKey, Severity: 'warning', Message });
143
+ };
144
+ // ── Party ──
145
+ if (!this.Header.Name || !this.Header.Name.trim()) {
146
+ err('party', 'Name', 'A deal needs a name.');
147
+ }
148
+ if (!this.Header.PipelineID) {
149
+ err('party', 'PipelineID', 'Choose a pipeline. It determines the stages and the selling company.');
150
+ }
151
+ if (!this.Header.AccountID) {
152
+ // A warning, not an error: the schema allows a deal with no account, and an early-stage
153
+ // opportunity legitimately has none yet. Worth flagging because it is almost always an
154
+ // omission rather than an intent.
155
+ warn('party', 'AccountID', 'No customer chosen yet — this deal is not attached to an account.');
156
+ }
157
+ // ── Terms / dates ──
158
+ // Only orderings the schema itself would reject, or that are unambiguously wrong. Note there
159
+ // is deliberately NO check of ExecutionDate against StartDate: work that begins before
160
+ // signature is common and legitimate, and the database does not constrain them either.
161
+ if (this.Header.Probability !== null && (this.Header.Probability < 0 || this.Header.Probability > 100)) {
162
+ err('terms', 'Probability', 'Probability must be between 0 and 100.');
163
+ }
164
+ if (this.Header.AnnualIncreasePctOverride !== null
165
+ && (this.Header.AnnualIncreasePctOverride < 0 || this.Header.AnnualIncreasePctOverride > 100)) {
166
+ err('terms', 'AnnualIncreasePctOverride', 'Annual increase must be between 0 and 100%.');
167
+ }
168
+ if (this.Header.CancellationNoticeDaysOverride !== null && this.Header.CancellationNoticeDaysOverride < 0) {
169
+ err('terms', 'CancellationNoticeDaysOverride', 'Cancellation notice cannot be negative.');
170
+ }
171
+ if (this.Header.TermMonths !== null && this.Header.TermMonths < 0) {
172
+ err('terms', 'TermMonths', 'Term cannot be negative.');
173
+ }
174
+ if (this.Header.EstimatedProjectWeeks !== null && this.Header.EstimatedProjectWeeks < 0) {
175
+ err('terms', 'EstimatedProjectWeeks', 'Estimated timeline cannot be negative.');
176
+ }
177
+ // ── Lines ──
178
+ for (const line of this.Lines) {
179
+ const label = line.ProductName?.trim() || 'this line';
180
+ if (!line.ProductName || !line.ProductName.trim()) {
181
+ err('lines', 'ProductName', 'Every line needs a product or service name.', line.ClientKey);
182
+ }
183
+ if (line.Quantity === null || line.Quantity === undefined || line.Quantity < 0) {
184
+ err('lines', 'Quantity', `Quantity on ${label} must be zero or more.`, line.ClientKey);
185
+ }
186
+ if (line.RequestedDiscountPct !== null && (line.RequestedDiscountPct < 0 || line.RequestedDiscountPct > 100)) {
187
+ err('lines', 'RequestedDiscountPct', `Requested discount on ${label} must be between 0 and 100%.`, line.ClientKey);
188
+ }
189
+ if (line.AnnualGrossFees !== null && line.AnnualGrossFees < 0) {
190
+ err('lines', 'AnnualGrossFees', `Annual gross fees on ${label} cannot be negative.`, line.ClientKey);
191
+ }
192
+ if (line.DiscountAmount !== null && line.DiscountAmount < 0) {
193
+ err('lines', 'DiscountAmount', `Discount on ${label} cannot be negative — a surcharge belongs on its own line.`, line.ClientKey);
194
+ }
195
+ if (line.ServicePeriodStart && line.ServicePeriodEnd && line.ServicePeriodEnd < line.ServicePeriodStart) {
196
+ err('lines', 'ServicePeriodEnd', `Service period on ${label} ends before it starts.`, line.ClientKey);
197
+ }
198
+ if (!line.DealLineTypeID) {
199
+ warn('lines', 'DealLineTypeID', `${label} has no type set — recurring and one-time lines behave differently downstream.`, line.ClientKey);
200
+ }
201
+ // NOT CHECKED, on purpose: whether Total equals AnnualGrossFees - DiscountAmount. All
202
+ // three are transcribed from a signed document; asserting the relationship would be this
203
+ // app computing money, which is the one thing it must never do.
204
+ }
205
+ // ── Payment schedule ──
206
+ for (const row of this.Schedule) {
207
+ if (row.Amount === null && !row.Description) {
208
+ err('schedule', 'Amount', 'An instalment needs at least an amount or a description.', row.ClientKey);
209
+ }
210
+ }
211
+ // NOT CHECKED: whether the instalments sum to the deal amount. Summing them and comparing is
212
+ // computing money, and the authoritative total lives in orders, not here.
213
+ return { IsValid: !issues.some((i) => i.Severity === 'error'), Issues: issues };
214
+ }
215
+ /** Issues for one section — what a tab reads to decide whether to show a badge. */
216
+ IssuesFor(section, validation) {
217
+ const v = validation ?? this.Validate();
218
+ return v.Issues.filter((i) => i.Section === section);
219
+ }
220
+ /* ── Serialization ──────────────────────────────────────────────────── */
221
+ /**
222
+ * Becomes the `Sales.SaveDeal` input.
223
+ *
224
+ * TYPED AS THE GENERATED CONTRACT, not as a loose bag. `SalesSaveDealInput` comes from the
225
+ * operation's own metadata, so binding to it here means a field renamed on the server breaks this
226
+ * method at compile time instead of silently dropping out of the payload at runtime. That is the
227
+ * only reason this otherwise framework-free class imports anything.
228
+ *
229
+ * `Lines` and `PaymentSchedule` are ALWAYS included, even when empty, because the operation treats
230
+ * a present array as the complete desired set and an absent one as "leave the children alone". A
231
+ * workspace that holds the whole tree always means the former — if it is showing the user zero
232
+ * lines, zero lines is the intent.
233
+ */
234
+ ToSaveInput() {
235
+ if (!this.Header.PipelineID) {
236
+ throw new Error('DealDraft.ToSaveInput: PipelineID is required. Call Validate() first and show the issues.');
237
+ }
238
+ const h = this.Header;
239
+ return {
240
+ ID: h.ID,
241
+ Name: h.Name,
242
+ PipelineID: h.PipelineID,
243
+ PipelineStageID: h.PipelineStageID,
244
+ DealTypeID: h.DealTypeID,
245
+ DealStatusTypeID: h.DealStatusTypeID,
246
+ AccountID: h.AccountID,
247
+ PrimaryContactID: h.PrimaryContactID,
248
+ BillingContactID: h.BillingContactID,
249
+ CompanyID: h.CompanyID,
250
+ OwnerEmployeeID: h.OwnerEmployeeID,
251
+ Amount: h.Amount,
252
+ CurrencyID: h.CurrencyID,
253
+ TermMonths: h.TermMonths,
254
+ EstimatedProjectWeeks: h.EstimatedProjectWeeks,
255
+ ExecutionDate: h.ExecutionDate,
256
+ StartDate: h.StartDate,
257
+ ExpectedCloseDate: h.ExpectedCloseDate,
258
+ Probability: h.Probability,
259
+ ForecastCategoryTypeID: h.ForecastCategoryTypeID,
260
+ LeadSourceTypeID: h.LeadSourceTypeID,
261
+ AutoRenew: h.AutoRenew,
262
+ AnnualIncreasePctOverride: h.AnnualIncreasePctOverride,
263
+ CancellationNoticeDaysOverride: h.CancellationNoticeDaysOverride,
264
+ PaymentMethod: h.PaymentMethod,
265
+ ContractVariances: h.ContractVariances,
266
+ Description: h.Description,
267
+ NextStep: h.NextStep,
268
+ NextStepDate: h.NextStepDate,
269
+ Lines: this.Lines.map((l) => ({
270
+ ClientKey: l.ClientKey,
271
+ ID: l.ID,
272
+ ProductID: l.ProductID,
273
+ ProductName: l.ProductName,
274
+ DealLineTypeID: l.DealLineTypeID,
275
+ Quantity: l.Quantity,
276
+ RequestedDiscountPct: l.RequestedDiscountPct,
277
+ OverrideUnitPrice: l.OverrideUnitPrice,
278
+ AnnualGrossFees: l.AnnualGrossFees,
279
+ DiscountAmount: l.DiscountAmount,
280
+ Total: l.Total,
281
+ TermMonths: l.TermMonths,
282
+ ServicePeriodStart: l.ServicePeriodStart,
283
+ ServicePeriodEnd: l.ServicePeriodEnd,
284
+ Description: l.Description,
285
+ })),
286
+ PaymentSchedule: this.Schedule.map((r) => ({
287
+ ClientKey: r.ClientKey,
288
+ ID: r.ID,
289
+ PaymentDate: r.PaymentDate,
290
+ Amount: r.Amount,
291
+ Description: r.Description,
292
+ })),
293
+ };
294
+ }
295
+ /**
296
+ * Folds a successful save result back in, so the same instance keeps being the live model instead
297
+ * of the caller rebuilding one. Matching is by `ClientKey` — which is exactly why the operation
298
+ * echoes it back.
299
+ */
300
+ ApplySaveResult(result) {
301
+ if (result.DealID) {
302
+ this.Header.ID = result.DealID;
303
+ }
304
+ for (const r of result.Lines ?? []) {
305
+ const line = this.Lines.find((l) => l.ClientKey === r.ClientKey);
306
+ if (line) {
307
+ line.ID = r.ID;
308
+ }
309
+ }
310
+ for (const r of result.PaymentSchedule ?? []) {
311
+ const row = this.Schedule.find((s) => s.ClientKey === r.ClientKey);
312
+ if (row) {
313
+ row.ID = r.ID;
314
+ }
315
+ }
316
+ }
317
+ }
318
+ //# sourceMappingURL=deal-draft.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"deal-draft.js","sourceRoot":"","sources":["../src/deal-draft.ts"],"names":[],"mappings":"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"}