@mj-biz-apps/contracts-entities 0.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 (46) hide show
  1. package/LICENSE +183 -0
  2. package/dist/ContractEntity.d.ts +181 -0
  3. package/dist/ContractEntity.d.ts.map +1 -0
  4. package/dist/ContractEntity.js +261 -0
  5. package/dist/ContractEntity.js.map +1 -0
  6. package/dist/ContractTemplateEntity.d.ts +50 -0
  7. package/dist/ContractTemplateEntity.d.ts.map +1 -0
  8. package/dist/ContractTemplateEntity.js +85 -0
  9. package/dist/ContractTemplateEntity.js.map +1 -0
  10. package/dist/ContractTemplateModificationEntity.d.ts +46 -0
  11. package/dist/ContractTemplateModificationEntity.d.ts.map +1 -0
  12. package/dist/ContractTemplateModificationEntity.js +72 -0
  13. package/dist/ContractTemplateModificationEntity.js.map +1 -0
  14. package/dist/ContractTemplateProvisionEntity.d.ts +45 -0
  15. package/dist/ContractTemplateProvisionEntity.d.ts.map +1 -0
  16. package/dist/ContractTemplateProvisionEntity.js +73 -0
  17. package/dist/ContractTemplateProvisionEntity.js.map +1 -0
  18. package/dist/ContractTypeEntity.d.ts +55 -0
  19. package/dist/ContractTypeEntity.d.ts.map +1 -0
  20. package/dist/ContractTypeEntity.js +82 -0
  21. package/dist/ContractTypeEntity.js.map +1 -0
  22. package/dist/contract-state.d.ts +49 -0
  23. package/dist/contract-state.d.ts.map +1 -0
  24. package/dist/contract-state.js +48 -0
  25. package/dist/contract-state.js.map +1 -0
  26. package/dist/generated/entity_subclasses.d.ts +1235 -0
  27. package/dist/generated/entity_subclasses.d.ts.map +1 -0
  28. package/dist/generated/entity_subclasses.js +1817 -0
  29. package/dist/generated/entity_subclasses.js.map +1 -0
  30. package/dist/generated/remote_operations.d.ts +1145 -0
  31. package/dist/generated/remote_operations.d.ts.map +1 -0
  32. package/dist/generated/remote_operations.js +426 -0
  33. package/dist/generated/remote_operations.js.map +1 -0
  34. package/dist/index.d.ts +30 -0
  35. package/dist/index.d.ts.map +1 -0
  36. package/dist/index.js +49 -0
  37. package/dist/index.js.map +1 -0
  38. package/dist/required-field-prose.d.ts +48 -0
  39. package/dist/required-field-prose.d.ts.map +1 -0
  40. package/dist/required-field-prose.js +55 -0
  41. package/dist/required-field-prose.js.map +1 -0
  42. package/dist/value-list-validation.d.ts +69 -0
  43. package/dist/value-list-validation.d.ts.map +1 -0
  44. package/dist/value-list-validation.js +88 -0
  45. package/dist/value-list-validation.js.map +1 -0
  46. package/package.json +33 -0
@@ -0,0 +1,50 @@
1
+ /**
2
+ * @fileoverview `ContractTemplateEntity` — the publication lifecycle, and the one rule that makes it
3
+ * mean anything.
4
+ *
5
+ * A template version is either a **Draft** (freely editable, not referenceable) or **Published**
6
+ * (frozen, referenceable). The freeze itself is enforced by
7
+ * `trg_ContractTemplateProvision_Immutability` against INSERT, UPDATE and DELETE on its provisions —
8
+ * a trigger, because rewriting signed terms is the case where a bypass is silent corruption rather
9
+ * than a bad edit in our own UI.
10
+ *
11
+ * WHAT LIVES HERE IS THE TRANSITION RULE, which the trigger cannot see: **publishing is one-way.**
12
+ * Without it the freeze is decorative — anyone wanting to edit a published version would flip
13
+ * `Status` back to Draft, edit, and flip it forward again, and every guarantee above evaporates. To
14
+ * change published terms you publish a NEW VERSION, which is what `VersionLabel` and `IntroducedDate`
15
+ * exist for.
16
+ *
17
+ * WHY NOT A CHECK CONSTRAINT: a CHECK sees one row's final state, not the transition. "Was Published,
18
+ * is now Draft" is a comparison against `OldValue`, which only the entity layer has.
19
+ *
20
+ * WHY PROVISION-LEVEL DEACTIVATION WAS REJECTED (Marcelo, 2026-08-20), recorded so it is not
21
+ * re-proposed: soft-deleting provisions would build a second, finer-grained versioning system beside
22
+ * the one that already exists, and "what did this customer sign" would degrade from "template T" into
23
+ * "the provisions of T that were active on date X" — a temporal query, which is exactly what
24
+ * versioning avoids. The lifecycle belongs to the VERSION, not to the clause.
25
+ *
26
+ * @module @mj-biz-apps/contracts-entities
27
+ */
28
+ import { ValidationResult } from '@memberjunction/core';
29
+ import { mjBizAppsContractsContractTemplateEntity } from './generated/entity_subclasses.js';
30
+ /** The published state — the string the `IN (...)` CHECK constrains `Status` to. */
31
+ export declare const TEMPLATE_PUBLISHED = "Published";
32
+ /** The editable state, and the default for a new version. */
33
+ export declare const TEMPLATE_DRAFT = "Draft";
34
+ export declare class ContractTemplateEntity extends mjBizAppsContractsContractTemplateEntity {
35
+ Validate(): ValidationResult;
36
+ /**
37
+ * Publishing is one-way: `Published` never returns to `Draft`.
38
+ *
39
+ * Compared against `OldValue` rather than probing anything, so it costs nothing and works on a
40
+ * record composed in the browser. Only fires on a SAVED record: a new version is legitimately
41
+ * created as a Draft, and there is no previous state to have been published.
42
+ */
43
+ private refuseUnpublishing;
44
+ }
45
+ /**
46
+ * Anti-tree-shake anchor. Importing this module is what fires `@RegisterClass`; a dropped registration
47
+ * would silently make publishing reversible, with nothing failing.
48
+ */
49
+ export declare function LoadContractTemplateEntity(): void;
50
+ //# sourceMappingURL=ContractTemplateEntity.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"ContractTemplateEntity.d.ts","sourceRoot":"","sources":["../src/ContractTemplateEntity.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;GA0BG;AACH,OAAO,EAAwD,gBAAgB,EAAE,MAAM,sBAAsB,CAAC;AAE9G,OAAO,EAAE,wCAAwC,EAAE,MAAM,+BAA+B,CAAC;AAGzF,oFAAoF;AACpF,eAAO,MAAM,kBAAkB,cAAc,CAAC;AAC9C,6DAA6D;AAC7D,eAAO,MAAM,cAAc,UAAU,CAAC;AAEtC,qBACa,sBAAuB,SAAQ,wCAAwC;IAChE,QAAQ,IAAI,gBAAgB;IAS5C;;;;;;OAMG;IACH,OAAO,CAAC,kBAAkB;CAoB7B;AAED;;;GAGG;AACH,wBAAgB,0BAA0B,IAAI,IAAI,CAEjD"}
@@ -0,0 +1,85 @@
1
+ var __decorate = (this && this.__decorate) || function (decorators, target, key, desc) {
2
+ var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;
3
+ if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc);
4
+ else for (var i = decorators.length - 1; i >= 0; i--) if (d = decorators[i]) r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r;
5
+ return c > 3 && r && Object.defineProperty(target, key, r), r;
6
+ };
7
+ /**
8
+ * @fileoverview `ContractTemplateEntity` — the publication lifecycle, and the one rule that makes it
9
+ * mean anything.
10
+ *
11
+ * A template version is either a **Draft** (freely editable, not referenceable) or **Published**
12
+ * (frozen, referenceable). The freeze itself is enforced by
13
+ * `trg_ContractTemplateProvision_Immutability` against INSERT, UPDATE and DELETE on its provisions —
14
+ * a trigger, because rewriting signed terms is the case where a bypass is silent corruption rather
15
+ * than a bad edit in our own UI.
16
+ *
17
+ * WHAT LIVES HERE IS THE TRANSITION RULE, which the trigger cannot see: **publishing is one-way.**
18
+ * Without it the freeze is decorative — anyone wanting to edit a published version would flip
19
+ * `Status` back to Draft, edit, and flip it forward again, and every guarantee above evaporates. To
20
+ * change published terms you publish a NEW VERSION, which is what `VersionLabel` and `IntroducedDate`
21
+ * exist for.
22
+ *
23
+ * WHY NOT A CHECK CONSTRAINT: a CHECK sees one row's final state, not the transition. "Was Published,
24
+ * is now Draft" is a comparison against `OldValue`, which only the entity layer has.
25
+ *
26
+ * WHY PROVISION-LEVEL DEACTIVATION WAS REJECTED (Marcelo, 2026-08-20), recorded so it is not
27
+ * re-proposed: soft-deleting provisions would build a second, finer-grained versioning system beside
28
+ * the one that already exists, and "what did this customer sign" would degrade from "template T" into
29
+ * "the provisions of T that were active on date X" — a temporal query, which is exactly what
30
+ * versioning avoids. The lifecycle belongs to the VERSION, not to the clause.
31
+ *
32
+ * @module @mj-biz-apps/contracts-entities
33
+ */
34
+ import { BaseEntity, ValidationErrorInfo, ValidationErrorType } from '@memberjunction/core';
35
+ import { RegisterClass } from '@memberjunction/global';
36
+ import { mjBizAppsContractsContractTemplateEntity } from './generated/entity_subclasses.js';
37
+ import { ValidateValueLists } from './value-list-validation.js';
38
+ /** The published state — the string the `IN (...)` CHECK constrains `Status` to. */
39
+ export const TEMPLATE_PUBLISHED = 'Published';
40
+ /** The editable state, and the default for a new version. */
41
+ export const TEMPLATE_DRAFT = 'Draft';
42
+ let ContractTemplateEntity = class ContractTemplateEntity extends mjBizAppsContractsContractTemplateEntity {
43
+ Validate() {
44
+ const result = super.Validate();
45
+ // Status is an exhaustive value list with no generated validator — MJ never checks list
46
+ // membership (MJ#3969), so the generic stopgap covers it like the other lookup columns.
47
+ ValidateValueLists(this, result);
48
+ this.refuseUnpublishing(result);
49
+ return result;
50
+ }
51
+ /**
52
+ * Publishing is one-way: `Published` never returns to `Draft`.
53
+ *
54
+ * Compared against `OldValue` rather than probing anything, so it costs nothing and works on a
55
+ * record composed in the browser. Only fires on a SAVED record: a new version is legitimately
56
+ * created as a Draft, and there is no previous state to have been published.
57
+ */
58
+ refuseUnpublishing(result) {
59
+ if (!this.IsSaved)
60
+ return;
61
+ const field = this.GetFieldByName('Status');
62
+ if (!field)
63
+ return;
64
+ const was = String(field.OldValue ?? '');
65
+ const now = String(field.Value ?? '');
66
+ if (was !== TEMPLATE_PUBLISHED || now === TEMPLATE_PUBLISHED)
67
+ return;
68
+ result.Success = false;
69
+ result.Errors.push(new ValidationErrorInfo('Status', `"${this.Name ?? this.ID}" is published and cannot be returned to draft. Contracts may already ` +
70
+ `incorporate its terms, and un-publishing would let those terms be edited underneath them. ` +
71
+ `Create a new version of this agreement instead — that is what versioning is for.`, now, ValidationErrorType.Failure));
72
+ }
73
+ };
74
+ ContractTemplateEntity = __decorate([
75
+ RegisterClass(BaseEntity, 'MJ_BizApps_Contracts: Contract Templates')
76
+ ], ContractTemplateEntity);
77
+ export { ContractTemplateEntity };
78
+ /**
79
+ * Anti-tree-shake anchor. Importing this module is what fires `@RegisterClass`; a dropped registration
80
+ * would silently make publishing reversible, with nothing failing.
81
+ */
82
+ export function LoadContractTemplateEntity() {
83
+ void ContractTemplateEntity;
84
+ }
85
+ //# sourceMappingURL=ContractTemplateEntity.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"ContractTemplateEntity.js","sourceRoot":"","sources":["../src/ContractTemplateEntity.ts"],"names":[],"mappings":";;;;;;AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;GA0BG;AACH,OAAO,EAAE,UAAU,EAAE,mBAAmB,EAAE,mBAAmB,EAAoB,MAAM,sBAAsB,CAAC;AAC9G,OAAO,EAAE,aAAa,EAAE,MAAM,wBAAwB,CAAC;AACvD,OAAO,EAAE,wCAAwC,EAAE,MAAM,+BAA+B,CAAC;AACzF,OAAO,EAAE,kBAAkB,EAAE,MAAM,yBAAyB,CAAC;AAE7D,oFAAoF;AACpF,MAAM,CAAC,MAAM,kBAAkB,GAAG,WAAW,CAAC;AAC9C,6DAA6D;AAC7D,MAAM,CAAC,MAAM,cAAc,GAAG,OAAO,CAAC;AAG/B,IAAM,sBAAsB,GAA5B,MAAM,sBAAuB,SAAQ,wCAAwC;IAChE,QAAQ;QACpB,MAAM,MAAM,GAAG,KAAK,CAAC,QAAQ,EAAE,CAAC;QAChC,wFAAwF;QACxF,wFAAwF;QACxF,kBAAkB,CAAC,IAAI,EAAE,MAAM,CAAC,CAAC;QACjC,IAAI,CAAC,kBAAkB,CAAC,MAAM,CAAC,CAAC;QAChC,OAAO,MAAM,CAAC;IAClB,CAAC;IAED;;;;;;OAMG;IACK,kBAAkB,CAAC,MAAwB;QAC/C,IAAI,CAAC,IAAI,CAAC,OAAO;YAAE,OAAO;QAC1B,MAAM,KAAK,GAAG,IAAI,CAAC,cAAc,CAAC,QAAQ,CAAC,CAAC;QAC5C,IAAI,CAAC,KAAK;YAAE,OAAO;QACnB,MAAM,GAAG,GAAG,MAAM,CAAC,KAAK,CAAC,QAAQ,IAAI,EAAE,CAAC,CAAC;QACzC,MAAM,GAAG,GAAG,MAAM,CAAC,KAAK,CAAC,KAAK,IAAI,EAAE,CAAC,CAAC;QACtC,IAAI,GAAG,KAAK,kBAAkB,IAAI,GAAG,KAAK,kBAAkB;YAAE,OAAO;QAErE,MAAM,CAAC,OAAO,GAAG,KAAK,CAAC;QACvB,MAAM,CAAC,MAAM,CAAC,IAAI,CACd,IAAI,mBAAmB,CACnB,QAAQ,EACR,IAAI,IAAI,CAAC,IAAI,IAAI,IAAI,CAAC,EAAE,wEAAwE;YAC5F,4FAA4F;YAC5F,kFAAkF,EACtF,GAAG,EACH,mBAAmB,CAAC,OAAO,CAC9B,CACJ,CAAC;IACN,CAAC;CACJ,CAAA;AArCY,sBAAsB;IADlC,aAAa,CAAC,UAAU,EAAE,0CAA0C,CAAC;GACzD,sBAAsB,CAqClC;;AAED;;;GAGG;AACH,MAAM,UAAU,0BAA0B;IACtC,KAAK,sBAAsB,CAAC;AAChC,CAAC"}
@@ -0,0 +1,46 @@
1
+ /**
2
+ * @fileoverview `ContractTemplateModificationEntity` — the SHARED subclass, and it exists for exactly
3
+ * one reason: the three fields a modification cannot do without refuse in prose nobody can act on.
4
+ *
5
+ * IT ADDS NO RULE. That distinction is the whole design, and getting it wrong here is a known trap
6
+ * (R-2 of `plans/backend-requirements.md`, withdrawn because implementing it would have produced a
7
+ * second copy of four working generated rules). `ContractID`, `ContractTemplateProvisionID` and — as
8
+ * of V202608192340 — `ModificationText` are all NOT NULL in the database, so MJ's own
9
+ * `EntityField.Validate()` already refuses an empty one and already names the field. The rule is the
10
+ * metadata; restating it in TypeScript would give one fact two owners and let them drift the next
11
+ * time a column's nullability changes.
12
+ *
13
+ * What MJ cannot know is what the user should DO about it. Its message is
14
+ * `` `${DisplayNameOrName} cannot be null` `` (`baseEntity.ts:320`) — correct, field-named, and mute
15
+ * on the only question the person in front of the form is asking. "Contract Template Provision
16
+ * cannot be null" does not tell anyone to pick a clause. So this class REPLACES those three messages
17
+ * and adds none.
18
+ *
19
+ * The mechanism — replace rather than append, collapse the duplicate absence errors, match on
20
+ * emptiness rather than on MJ's wording — lives in `required-field-prose.ts`, shared with provisions.
21
+ *
22
+ * @module @mj-biz-apps/contracts-entities
23
+ */
24
+ import { ValidationResult } from '@memberjunction/core';
25
+ import { mjBizAppsContractsContractTemplateModificationEntity } from './generated/entity_subclasses.js';
26
+ /**
27
+ * The prose each required field gets instead of "<Display Name> cannot be null".
28
+ *
29
+ * Each one says what to do, not what is wrong. `ContractID` is the odd member and is included
30
+ * deliberately: a user never sets it — MJ stamps it from the parent before validating
31
+ * (`relatedRecordCollection.ts`, `stampParentKey()` ahead of the child's `Validate()`), so inside the
32
+ * modification editor it cannot be empty. It can only be empty on the standalone form or an API
33
+ * call, which is precisely where "Contract cannot be null" is least useful, because the caller has to
34
+ * be told that a modification is meaningless without the contract it belongs to.
35
+ */
36
+ export declare const MODIFICATION_REQUIRED_FIELD_PROSE: Readonly<Record<string, string>>;
37
+ export declare class ContractTemplateModificationEntity extends mjBizAppsContractsContractTemplateModificationEntity {
38
+ Validate(): ValidationResult;
39
+ }
40
+ /**
41
+ * Anti-tree-shake anchor. Importing this module is what fires `@RegisterClass`; a production build can
42
+ * drop an import whose class is never referenced, and a dropped registration would silently restore
43
+ * MJ's flat messages with nothing failing — the same reason `LoadContractEntity` exists.
44
+ */
45
+ export declare function LoadContractTemplateModificationEntity(): void;
46
+ //# sourceMappingURL=ContractTemplateModificationEntity.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"ContractTemplateModificationEntity.d.ts","sourceRoot":"","sources":["../src/ContractTemplateModificationEntity.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;GAsBG;AACH,OAAO,EAAc,gBAAgB,EAAE,MAAM,sBAAsB,CAAC;AAEpE,OAAO,EAAE,oDAAoD,EAAE,MAAM,+BAA+B,CAAC;AAGrG;;;;;;;;;GASG;AACH,eAAO,MAAM,iCAAiC,EAAE,QAAQ,CAAC,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAW9E,CAAC;AAEF,qBACa,kCAAmC,SAAQ,oDAAoD;IACxF,QAAQ,IAAI,gBAAgB;CAK/C;AAED;;;;GAIG;AACH,wBAAgB,sCAAsC,IAAI,IAAI,CAE7D"}
@@ -0,0 +1,72 @@
1
+ var __decorate = (this && this.__decorate) || function (decorators, target, key, desc) {
2
+ var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;
3
+ if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc);
4
+ else for (var i = decorators.length - 1; i >= 0; i--) if (d = decorators[i]) r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r;
5
+ return c > 3 && r && Object.defineProperty(target, key, r), r;
6
+ };
7
+ /**
8
+ * @fileoverview `ContractTemplateModificationEntity` — the SHARED subclass, and it exists for exactly
9
+ * one reason: the three fields a modification cannot do without refuse in prose nobody can act on.
10
+ *
11
+ * IT ADDS NO RULE. That distinction is the whole design, and getting it wrong here is a known trap
12
+ * (R-2 of `plans/backend-requirements.md`, withdrawn because implementing it would have produced a
13
+ * second copy of four working generated rules). `ContractID`, `ContractTemplateProvisionID` and — as
14
+ * of V202608192340 — `ModificationText` are all NOT NULL in the database, so MJ's own
15
+ * `EntityField.Validate()` already refuses an empty one and already names the field. The rule is the
16
+ * metadata; restating it in TypeScript would give one fact two owners and let them drift the next
17
+ * time a column's nullability changes.
18
+ *
19
+ * What MJ cannot know is what the user should DO about it. Its message is
20
+ * `` `${DisplayNameOrName} cannot be null` `` (`baseEntity.ts:320`) — correct, field-named, and mute
21
+ * on the only question the person in front of the form is asking. "Contract Template Provision
22
+ * cannot be null" does not tell anyone to pick a clause. So this class REPLACES those three messages
23
+ * and adds none.
24
+ *
25
+ * The mechanism — replace rather than append, collapse the duplicate absence errors, match on
26
+ * emptiness rather than on MJ's wording — lives in `required-field-prose.ts`, shared with provisions.
27
+ *
28
+ * @module @mj-biz-apps/contracts-entities
29
+ */
30
+ import { BaseEntity } from '@memberjunction/core';
31
+ import { RegisterClass } from '@memberjunction/global';
32
+ import { mjBizAppsContractsContractTemplateModificationEntity } from './generated/entity_subclasses.js';
33
+ import { ExplainMissingRequiredFields } from './required-field-prose.js';
34
+ /**
35
+ * The prose each required field gets instead of "<Display Name> cannot be null".
36
+ *
37
+ * Each one says what to do, not what is wrong. `ContractID` is the odd member and is included
38
+ * deliberately: a user never sets it — MJ stamps it from the parent before validating
39
+ * (`relatedRecordCollection.ts`, `stampParentKey()` ahead of the child's `Validate()`), so inside the
40
+ * modification editor it cannot be empty. It can only be empty on the standalone form or an API
41
+ * call, which is precisely where "Contract cannot be null" is least useful, because the caller has to
42
+ * be told that a modification is meaningless without the contract it belongs to.
43
+ */
44
+ export const MODIFICATION_REQUIRED_FIELD_PROSE = {
45
+ ContractID: 'A modification records what one specific contract negotiated, so it cannot exist on its own — ' +
46
+ 'choose the contract this deviation belongs to.',
47
+ ContractTemplateProvisionID: 'Choose the standard provision this modification changes. The negotiated wording is only ' +
48
+ 'meaningful beside the clause it replaces.',
49
+ ModificationText: 'Record what this contract says instead of the standard clause. A modification that does not ' +
50
+ 'say what was agreed asserts that the paper differs without saying how, which is the one ' +
51
+ 'state this record cannot usefully be in.',
52
+ };
53
+ let ContractTemplateModificationEntity = class ContractTemplateModificationEntity extends mjBizAppsContractsContractTemplateModificationEntity {
54
+ Validate() {
55
+ const result = super.Validate();
56
+ ExplainMissingRequiredFields(this, result, MODIFICATION_REQUIRED_FIELD_PROSE);
57
+ return result;
58
+ }
59
+ };
60
+ ContractTemplateModificationEntity = __decorate([
61
+ RegisterClass(BaseEntity, 'MJ_BizApps_Contracts: Contract Template Modifications')
62
+ ], ContractTemplateModificationEntity);
63
+ export { ContractTemplateModificationEntity };
64
+ /**
65
+ * Anti-tree-shake anchor. Importing this module is what fires `@RegisterClass`; a production build can
66
+ * drop an import whose class is never referenced, and a dropped registration would silently restore
67
+ * MJ's flat messages with nothing failing — the same reason `LoadContractEntity` exists.
68
+ */
69
+ export function LoadContractTemplateModificationEntity() {
70
+ void ContractTemplateModificationEntity;
71
+ }
72
+ //# sourceMappingURL=ContractTemplateModificationEntity.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"ContractTemplateModificationEntity.js","sourceRoot":"","sources":["../src/ContractTemplateModificationEntity.ts"],"names":[],"mappings":";;;;;;AAAA;;;;;;;;;;;;;;;;;;;;;;GAsBG;AACH,OAAO,EAAE,UAAU,EAAoB,MAAM,sBAAsB,CAAC;AACpE,OAAO,EAAE,aAAa,EAAE,MAAM,wBAAwB,CAAC;AACvD,OAAO,EAAE,oDAAoD,EAAE,MAAM,+BAA+B,CAAC;AACrG,OAAO,EAAE,4BAA4B,EAAE,MAAM,wBAAwB,CAAC;AAEtE;;;;;;;;;GASG;AACH,MAAM,CAAC,MAAM,iCAAiC,GAAqC;IAC/E,UAAU,EACN,gGAAgG;QAChG,gDAAgD;IACpD,2BAA2B,EACvB,0FAA0F;QAC1F,2CAA2C;IAC/C,gBAAgB,EACZ,8FAA8F;QAC9F,0FAA0F;QAC1F,0CAA0C;CACjD,CAAC;AAGK,IAAM,kCAAkC,GAAxC,MAAM,kCAAmC,SAAQ,oDAAoD;IACxF,QAAQ;QACpB,MAAM,MAAM,GAAG,KAAK,CAAC,QAAQ,EAAE,CAAC;QAChC,4BAA4B,CAAC,IAAI,EAAE,MAAM,EAAE,iCAAiC,CAAC,CAAC;QAC9E,OAAO,MAAM,CAAC;IAClB,CAAC;CACJ,CAAA;AANY,kCAAkC;IAD9C,aAAa,CAAC,UAAU,EAAE,uDAAuD,CAAC;GACtE,kCAAkC,CAM9C;;AAED;;;;GAIG;AACH,MAAM,UAAU,sCAAsC;IAClD,KAAK,kCAAkC,CAAC;AAC5C,CAAC"}
@@ -0,0 +1,45 @@
1
+ /**
2
+ * @fileoverview `ContractTemplateProvisionEntity` — the SHARED subclass, and like the modification's
3
+ * it exists for one reason: the fields a provision cannot do without refuse in prose nobody can act on.
4
+ *
5
+ * IT ADDS NO RULE. `ContractTemplateID`, `ProvisionNumber`, `Title` and — as of V202608200800 —
6
+ * `ProvisionText` are all required at the database, the last two of them via
7
+ * `CK_ContractTemplateProvision_TextNotBlank` on top of `NOT NULL` (because `NOT NULL` accepts `''`;
8
+ * see the migration). MJ and CodeGen already refuse an empty one and already name the field. Only the
9
+ * sentence changes here.
10
+ *
11
+ * WHY `ProvisionText` MATTERS MORE THAN IT LOOKS. A provision is the STANDARD wording of a clause, and
12
+ * a `ContractTemplateModification` is only meaningful read as a PAIR against it — a dispute needs the
13
+ * comparison, not either half. A provision with no text is therefore worse than a modification with
14
+ * no text: every modification pointing at it inherits the gap, and the contract still renders.
15
+ *
16
+ * SERVER RULES ARE NOT HERE. Provision immutability once a contract references the template (R-1) and
17
+ * the delete guards (R-8) need cross-entity reads, so they live on
18
+ * `ContractTemplateProvisionEntityServer`. What is here is what a browser can preflight.
19
+ *
20
+ * @module @mj-biz-apps/contracts-entities
21
+ */
22
+ import { ValidationResult } from '@memberjunction/core';
23
+ import { mjBizAppsContractsContractTemplateProvisionEntity } from './generated/entity_subclasses.js';
24
+ /**
25
+ * The prose each required field gets instead of "<Display Name> cannot be null".
26
+ *
27
+ * `ContractTemplateID` is included for the same reason `ContractID` is on the modification: a user
28
+ * never sets it inside the template form — MJ stamps it from the parent before validating — so it can
29
+ * only be empty on the standalone form or an API call, which is exactly where the flat message helps
30
+ * least.
31
+ *
32
+ * `ProvisionSortKey` is deliberately ABSENT. It is a persisted computed column and read-only, so it
33
+ * cannot be missing and cannot be set; naming it here would describe a failure that cannot happen.
34
+ */
35
+ export declare const PROVISION_REQUIRED_FIELD_PROSE: Readonly<Record<string, string>>;
36
+ export declare class ContractTemplateProvisionEntity extends mjBizAppsContractsContractTemplateProvisionEntity {
37
+ Validate(): ValidationResult;
38
+ }
39
+ /**
40
+ * Anti-tree-shake anchor. Importing this module is what fires `@RegisterClass`; a production build can
41
+ * drop an import whose class is never referenced, and a dropped registration would silently restore
42
+ * MJ's flat messages with nothing failing.
43
+ */
44
+ export declare function LoadContractTemplateProvisionEntity(): void;
45
+ //# sourceMappingURL=ContractTemplateProvisionEntity.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"ContractTemplateProvisionEntity.d.ts","sourceRoot":"","sources":["../src/ContractTemplateProvisionEntity.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;GAoBG;AACH,OAAO,EAAc,gBAAgB,EAAE,MAAM,sBAAsB,CAAC;AAEpE,OAAO,EAAE,iDAAiD,EAAE,MAAM,+BAA+B,CAAC;AAGlG;;;;;;;;;;GAUG;AACH,eAAO,MAAM,8BAA8B,EAAE,QAAQ,CAAC,MAAM,CAAC,MAAM,EAAE,MAAM,CAAC,CAc3E,CAAC;AAEF,qBACa,+BAAgC,SAAQ,iDAAiD;IAClF,QAAQ,IAAI,gBAAgB;CAK/C;AAED;;;;GAIG;AACH,wBAAgB,mCAAmC,IAAI,IAAI,CAE1D"}
@@ -0,0 +1,73 @@
1
+ var __decorate = (this && this.__decorate) || function (decorators, target, key, desc) {
2
+ var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;
3
+ if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc);
4
+ else for (var i = decorators.length - 1; i >= 0; i--) if (d = decorators[i]) r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r;
5
+ return c > 3 && r && Object.defineProperty(target, key, r), r;
6
+ };
7
+ /**
8
+ * @fileoverview `ContractTemplateProvisionEntity` — the SHARED subclass, and like the modification's
9
+ * it exists for one reason: the fields a provision cannot do without refuse in prose nobody can act on.
10
+ *
11
+ * IT ADDS NO RULE. `ContractTemplateID`, `ProvisionNumber`, `Title` and — as of V202608200800 —
12
+ * `ProvisionText` are all required at the database, the last two of them via
13
+ * `CK_ContractTemplateProvision_TextNotBlank` on top of `NOT NULL` (because `NOT NULL` accepts `''`;
14
+ * see the migration). MJ and CodeGen already refuse an empty one and already name the field. Only the
15
+ * sentence changes here.
16
+ *
17
+ * WHY `ProvisionText` MATTERS MORE THAN IT LOOKS. A provision is the STANDARD wording of a clause, and
18
+ * a `ContractTemplateModification` is only meaningful read as a PAIR against it — a dispute needs the
19
+ * comparison, not either half. A provision with no text is therefore worse than a modification with
20
+ * no text: every modification pointing at it inherits the gap, and the contract still renders.
21
+ *
22
+ * SERVER RULES ARE NOT HERE. Provision immutability once a contract references the template (R-1) and
23
+ * the delete guards (R-8) need cross-entity reads, so they live on
24
+ * `ContractTemplateProvisionEntityServer`. What is here is what a browser can preflight.
25
+ *
26
+ * @module @mj-biz-apps/contracts-entities
27
+ */
28
+ import { BaseEntity } from '@memberjunction/core';
29
+ import { RegisterClass } from '@memberjunction/global';
30
+ import { mjBizAppsContractsContractTemplateProvisionEntity } from './generated/entity_subclasses.js';
31
+ import { ExplainMissingRequiredFields } from './required-field-prose.js';
32
+ /**
33
+ * The prose each required field gets instead of "<Display Name> cannot be null".
34
+ *
35
+ * `ContractTemplateID` is included for the same reason `ContractID` is on the modification: a user
36
+ * never sets it inside the template form — MJ stamps it from the parent before validating — so it can
37
+ * only be empty on the standalone form or an API call, which is exactly where the flat message helps
38
+ * least.
39
+ *
40
+ * `ProvisionSortKey` is deliberately ABSENT. It is a persisted computed column and read-only, so it
41
+ * cannot be missing and cannot be set; naming it here would describe a failure that cannot happen.
42
+ */
43
+ export const PROVISION_REQUIRED_FIELD_PROSE = {
44
+ ContractTemplateID: 'A provision is a clause OF an agreement version, so it cannot stand alone — choose the ' +
45
+ 'template this clause belongs to.',
46
+ ProvisionNumber: 'Give the clause its number as the document states it (for example 1.1, or 2.1A). The number is ' +
47
+ 'also what orders the provisions, so a clause without one sorts to the top until it has one.',
48
+ Title: 'Give the clause a heading, as the document states it. It is what the contract screens show ' +
49
+ 'when the full text is collapsed.',
50
+ ProvisionText: 'Record the standard wording of this clause. A provision with no text leaves every modification ' +
51
+ 'that negotiates it comparing against nothing, and the pair — standard beside negotiated — is ' +
52
+ 'what a dispute actually needs.',
53
+ };
54
+ let ContractTemplateProvisionEntity = class ContractTemplateProvisionEntity extends mjBizAppsContractsContractTemplateProvisionEntity {
55
+ Validate() {
56
+ const result = super.Validate();
57
+ ExplainMissingRequiredFields(this, result, PROVISION_REQUIRED_FIELD_PROSE);
58
+ return result;
59
+ }
60
+ };
61
+ ContractTemplateProvisionEntity = __decorate([
62
+ RegisterClass(BaseEntity, 'MJ_BizApps_Contracts: Contract Template Provisions')
63
+ ], ContractTemplateProvisionEntity);
64
+ export { ContractTemplateProvisionEntity };
65
+ /**
66
+ * Anti-tree-shake anchor. Importing this module is what fires `@RegisterClass`; a production build can
67
+ * drop an import whose class is never referenced, and a dropped registration would silently restore
68
+ * MJ's flat messages with nothing failing.
69
+ */
70
+ export function LoadContractTemplateProvisionEntity() {
71
+ void ContractTemplateProvisionEntity;
72
+ }
73
+ //# sourceMappingURL=ContractTemplateProvisionEntity.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"ContractTemplateProvisionEntity.js","sourceRoot":"","sources":["../src/ContractTemplateProvisionEntity.ts"],"names":[],"mappings":";;;;;;AAAA;;;;;;;;;;;;;;;;;;;;GAoBG;AACH,OAAO,EAAE,UAAU,EAAoB,MAAM,sBAAsB,CAAC;AACpE,OAAO,EAAE,aAAa,EAAE,MAAM,wBAAwB,CAAC;AACvD,OAAO,EAAE,iDAAiD,EAAE,MAAM,+BAA+B,CAAC;AAClG,OAAO,EAAE,4BAA4B,EAAE,MAAM,wBAAwB,CAAC;AAEtE;;;;;;;;;;GAUG;AACH,MAAM,CAAC,MAAM,8BAA8B,GAAqC;IAC5E,kBAAkB,EACd,yFAAyF;QACzF,kCAAkC;IACtC,eAAe,EACX,iGAAiG;QACjG,6FAA6F;IACjG,KAAK,EACD,6FAA6F;QAC7F,kCAAkC;IACtC,aAAa,EACT,iGAAiG;QACjG,+FAA+F;QAC/F,gCAAgC;CACvC,CAAC;AAGK,IAAM,+BAA+B,GAArC,MAAM,+BAAgC,SAAQ,iDAAiD;IAClF,QAAQ;QACpB,MAAM,MAAM,GAAG,KAAK,CAAC,QAAQ,EAAE,CAAC;QAChC,4BAA4B,CAAC,IAAI,EAAE,MAAM,EAAE,8BAA8B,CAAC,CAAC;QAC3E,OAAO,MAAM,CAAC;IAClB,CAAC;CACJ,CAAA;AANY,+BAA+B;IAD3C,aAAa,CAAC,UAAU,EAAE,oDAAoD,CAAC;GACnE,+BAA+B,CAM3C;;AAED;;;;GAIG;AACH,MAAM,UAAU,mCAAmC;IAC/C,KAAK,+BAA+B,CAAC;AACzC,CAAC"}
@@ -0,0 +1,55 @@
1
+ /**
2
+ * @fileoverview `ContractTypeEntity` and `ContractTemplateTypeEntity` — the two lookup tables, which
3
+ * exist as subclasses for exactly one reason: their value-list columns are validated NOWHERE.
4
+ *
5
+ * Both carry an `nvarchar` column constrained by `CHECK (… IN (…))` — `ContractType.Status` and
6
+ * `ContractTemplateType.Status`. (A third, `ContractType.ParentStatusRequirement`, was the original
7
+ * motivating case; R-4 replaced it with two booleans, which need no value list at all — a `bit` has
8
+ * only two possible values. The guard stays generic, so losing a field does not change it.) CodeGen
9
+ * renders that kind of
10
+ * constraint as value-list METADATA rather than as a generated `Validate()` method, and `BaseEntity`
11
+ * never reads value-list metadata, so the constraint has no TypeScript representation at all. Full
12
+ * reasoning, and the deletion plan, in `value-list-validation.ts`; filed as MJ#3969.
13
+ *
14
+ * These are the app's only entities with value-list fields today. `ValidateValueLists` is generic
15
+ * rather than field-specific, so a future one is covered by adding the call, not by writing a check.
16
+ *
17
+ * WHY THESE TWO AND NOT ALL FIVE UNSUBCLASSED ENTITIES. `ContractTemplate` and
18
+ * `ContractTemplateProvision` also lack subclasses, and both will need one — for provision
19
+ * immutability (R-1) and the `ProvisionNumber` sort key (R-11). Neither rule is decided yet, and a
20
+ * subclass created ahead of a rule is a file that says nothing while looking like it says something.
21
+ * They arrive with their rules. `ContractSequence` is a separate question (R-7): whether it should be
22
+ * an API-writable entity at all.
23
+ *
24
+ * @module @mj-biz-apps/contracts-entities
25
+ */
26
+ import { ValidationResult } from '@memberjunction/core';
27
+ import { mjBizAppsContractsContractTemplateTypeEntity, mjBizAppsContractsContractTypeEntity } from './generated/entity_subclasses.js';
28
+ /**
29
+ * `Status` (`Active` / `Inactive`) — the only value-list column left on this table.
30
+ *
31
+ * It is load-bearing rather than cosmetic: R-5 refuses a contract that NEWLY selects a type whose
32
+ * `Status` is `Inactive`, and R-8 refuses deleting a type in use while telling the user to retire it
33
+ * instead. So "Active" / "Inactive" is the vocabulary two rules read, and the database's `CHECK` is
34
+ * what keeps a third string out of the column — but it refuses at the very end, as a constraint
35
+ * violation naming no field. This makes the refusal arrive on the field, in the browser, before the
36
+ * round trip.
37
+ *
38
+ * The type's three RULE columns (`MustBeRoot`, `MustBeChild`, `TemplateRequired`) are `bit`s and need
39
+ * nothing here — a boolean cannot hold an out-of-list value, which is half the argument R-4 made for
40
+ * replacing the three-state string.
41
+ */
42
+ export declare class ContractTypeEntity extends mjBizAppsContractsContractTypeEntity {
43
+ Validate(): ValidationResult;
44
+ }
45
+ /** `Status` (`Active` / `Inactive`) — see the note above. */
46
+ export declare class ContractTemplateTypeEntity extends mjBizAppsContractsContractTemplateTypeEntity {
47
+ Validate(): ValidationResult;
48
+ }
49
+ /**
50
+ * Anti-tree-shake anchor. Importing this module is what fires `@RegisterClass`; a production build can
51
+ * drop an import whose class is never referenced, and a dropped registration means the rules above
52
+ * silently stop existing — the same reason `LoadContractEntity` exists.
53
+ */
54
+ export declare function LoadContractTypeEntities(): void;
55
+ //# sourceMappingURL=ContractTypeEntity.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"ContractTypeEntity.d.ts","sourceRoot":"","sources":["../src/ContractTypeEntity.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;GAwBG;AACH,OAAO,EAAc,gBAAgB,EAAE,MAAM,sBAAsB,CAAC;AAEpE,OAAO,EACH,4CAA4C,EAC5C,oCAAoC,EACvC,MAAM,+BAA+B,CAAC;AAGvC;;;;;;;;;;;;;GAaG;AACH,qBACa,kBAAmB,SAAQ,oCAAoC;IACxD,QAAQ,IAAI,gBAAgB;CAK/C;AAED,6DAA6D;AAC7D,qBACa,0BAA2B,SAAQ,4CAA4C;IACxE,QAAQ,IAAI,gBAAgB;CAK/C;AAED;;;;GAIG;AACH,wBAAgB,wBAAwB,IAAI,IAAI,CAG/C"}
@@ -0,0 +1,82 @@
1
+ var __decorate = (this && this.__decorate) || function (decorators, target, key, desc) {
2
+ var c = arguments.length, r = c < 3 ? target : desc === null ? desc = Object.getOwnPropertyDescriptor(target, key) : desc, d;
3
+ if (typeof Reflect === "object" && typeof Reflect.decorate === "function") r = Reflect.decorate(decorators, target, key, desc);
4
+ else for (var i = decorators.length - 1; i >= 0; i--) if (d = decorators[i]) r = (c < 3 ? d(r) : c > 3 ? d(target, key, r) : d(target, key)) || r;
5
+ return c > 3 && r && Object.defineProperty(target, key, r), r;
6
+ };
7
+ /**
8
+ * @fileoverview `ContractTypeEntity` and `ContractTemplateTypeEntity` — the two lookup tables, which
9
+ * exist as subclasses for exactly one reason: their value-list columns are validated NOWHERE.
10
+ *
11
+ * Both carry an `nvarchar` column constrained by `CHECK (… IN (…))` — `ContractType.Status` and
12
+ * `ContractTemplateType.Status`. (A third, `ContractType.ParentStatusRequirement`, was the original
13
+ * motivating case; R-4 replaced it with two booleans, which need no value list at all — a `bit` has
14
+ * only two possible values. The guard stays generic, so losing a field does not change it.) CodeGen
15
+ * renders that kind of
16
+ * constraint as value-list METADATA rather than as a generated `Validate()` method, and `BaseEntity`
17
+ * never reads value-list metadata, so the constraint has no TypeScript representation at all. Full
18
+ * reasoning, and the deletion plan, in `value-list-validation.ts`; filed as MJ#3969.
19
+ *
20
+ * These are the app's only entities with value-list fields today. `ValidateValueLists` is generic
21
+ * rather than field-specific, so a future one is covered by adding the call, not by writing a check.
22
+ *
23
+ * WHY THESE TWO AND NOT ALL FIVE UNSUBCLASSED ENTITIES. `ContractTemplate` and
24
+ * `ContractTemplateProvision` also lack subclasses, and both will need one — for provision
25
+ * immutability (R-1) and the `ProvisionNumber` sort key (R-11). Neither rule is decided yet, and a
26
+ * subclass created ahead of a rule is a file that says nothing while looking like it says something.
27
+ * They arrive with their rules. `ContractSequence` is a separate question (R-7): whether it should be
28
+ * an API-writable entity at all.
29
+ *
30
+ * @module @mj-biz-apps/contracts-entities
31
+ */
32
+ import { BaseEntity } from '@memberjunction/core';
33
+ import { RegisterClass } from '@memberjunction/global';
34
+ import { mjBizAppsContractsContractTemplateTypeEntity, mjBizAppsContractsContractTypeEntity, } from './generated/entity_subclasses.js';
35
+ import { ValidateValueLists } from './value-list-validation.js';
36
+ /**
37
+ * `Status` (`Active` / `Inactive`) — the only value-list column left on this table.
38
+ *
39
+ * It is load-bearing rather than cosmetic: R-5 refuses a contract that NEWLY selects a type whose
40
+ * `Status` is `Inactive`, and R-8 refuses deleting a type in use while telling the user to retire it
41
+ * instead. So "Active" / "Inactive" is the vocabulary two rules read, and the database's `CHECK` is
42
+ * what keeps a third string out of the column — but it refuses at the very end, as a constraint
43
+ * violation naming no field. This makes the refusal arrive on the field, in the browser, before the
44
+ * round trip.
45
+ *
46
+ * The type's three RULE columns (`MustBeRoot`, `MustBeChild`, `TemplateRequired`) are `bit`s and need
47
+ * nothing here — a boolean cannot hold an out-of-list value, which is half the argument R-4 made for
48
+ * replacing the three-state string.
49
+ */
50
+ let ContractTypeEntity = class ContractTypeEntity extends mjBizAppsContractsContractTypeEntity {
51
+ Validate() {
52
+ const result = super.Validate();
53
+ ValidateValueLists(this, result);
54
+ return result;
55
+ }
56
+ };
57
+ ContractTypeEntity = __decorate([
58
+ RegisterClass(BaseEntity, 'MJ_BizApps_Contracts: Contract Types')
59
+ ], ContractTypeEntity);
60
+ export { ContractTypeEntity };
61
+ /** `Status` (`Active` / `Inactive`) — see the note above. */
62
+ let ContractTemplateTypeEntity = class ContractTemplateTypeEntity extends mjBizAppsContractsContractTemplateTypeEntity {
63
+ Validate() {
64
+ const result = super.Validate();
65
+ ValidateValueLists(this, result);
66
+ return result;
67
+ }
68
+ };
69
+ ContractTemplateTypeEntity = __decorate([
70
+ RegisterClass(BaseEntity, 'MJ_BizApps_Contracts: Contract Template Types')
71
+ ], ContractTemplateTypeEntity);
72
+ export { ContractTemplateTypeEntity };
73
+ /**
74
+ * Anti-tree-shake anchor. Importing this module is what fires `@RegisterClass`; a production build can
75
+ * drop an import whose class is never referenced, and a dropped registration means the rules above
76
+ * silently stop existing — the same reason `LoadContractEntity` exists.
77
+ */
78
+ export function LoadContractTypeEntities() {
79
+ void ContractTypeEntity;
80
+ void ContractTemplateTypeEntity;
81
+ }
82
+ //# sourceMappingURL=ContractTypeEntity.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"ContractTypeEntity.js","sourceRoot":"","sources":["../src/ContractTypeEntity.ts"],"names":[],"mappings":";;;;;;AAAA;;;;;;;;;;;;;;;;;;;;;;;;GAwBG;AACH,OAAO,EAAE,UAAU,EAAoB,MAAM,sBAAsB,CAAC;AACpE,OAAO,EAAE,aAAa,EAAE,MAAM,wBAAwB,CAAC;AACvD,OAAO,EACH,4CAA4C,EAC5C,oCAAoC,GACvC,MAAM,+BAA+B,CAAC;AACvC,OAAO,EAAE,kBAAkB,EAAE,MAAM,yBAAyB,CAAC;AAE7D;;;;;;;;;;;;;GAaG;AAEI,IAAM,kBAAkB,GAAxB,MAAM,kBAAmB,SAAQ,oCAAoC;IACxD,QAAQ;QACpB,MAAM,MAAM,GAAG,KAAK,CAAC,QAAQ,EAAE,CAAC;QAChC,kBAAkB,CAAC,IAAI,EAAE,MAAM,CAAC,CAAC;QACjC,OAAO,MAAM,CAAC;IAClB,CAAC;CACJ,CAAA;AANY,kBAAkB;IAD9B,aAAa,CAAC,UAAU,EAAE,sCAAsC,CAAC;GACrD,kBAAkB,CAM9B;;AAED,6DAA6D;AAEtD,IAAM,0BAA0B,GAAhC,MAAM,0BAA2B,SAAQ,4CAA4C;IACxE,QAAQ;QACpB,MAAM,MAAM,GAAG,KAAK,CAAC,QAAQ,EAAE,CAAC;QAChC,kBAAkB,CAAC,IAAI,EAAE,MAAM,CAAC,CAAC;QACjC,OAAO,MAAM,CAAC;IAClB,CAAC;CACJ,CAAA;AANY,0BAA0B;IADtC,aAAa,CAAC,UAAU,EAAE,+CAA+C,CAAC;GAC9D,0BAA0B,CAMtC;;AAED;;;;GAIG;AACH,MAAM,UAAU,wBAAwB;IACpC,KAAK,kBAAkB,CAAC;IACxB,KAAK,0BAA0B,CAAC;AACpC,CAAC"}
@@ -0,0 +1,49 @@
1
+ /**
2
+ * @fileoverview The contract lifecycle — the VALUES only. The rule itself lives in SQL.
3
+ *
4
+ * `State` is derived, not stored (D-19 / ERD R-18): four of the old `Status` column's five values
5
+ * were projections of the dates and the two self-FKs, and a stored copy of a projection can only
6
+ * agree or lie. It is derived in exactly ONE place — the `CASE` in the app-owned layered base view
7
+ * (`V202608182001`) — and application code READS `contract.State`. It does not re-derive it.
8
+ *
9
+ * WHY THIS FILE NO LONGER CARRIES THE RULE (Marcelo, 2026-08-19). It used to hold
10
+ * `DeriveContractState()` for TypeScript and `StateSQL()` to render the same rule as T-SQL, on the
11
+ * reasoning that one module rendering both copies could not drift. That reasoning was wrong, and it
12
+ * failed in the most direct way available: the TypeScript branch for termination was tightened to
13
+ * "terminated before today", the view was not, and for several hours the same contract read `Active`
14
+ * in the browser and `Terminated` from every view-backed query. The guard did not fire because it
15
+ * compared the two renderings as TEXT, and text cannot see a semantic split.
16
+ *
17
+ * The lesson is not "write a better guard" — a guard that has to be right about two implementations
18
+ * is a third thing to get wrong. It is: **do not mirror a rule.** One definition, in one language.
19
+ * SQL wins here because the rule is time-dependent (`Expired` and `Active` turn over at midnight with
20
+ * no write to trigger them), so it must be evaluated at READ time, which is what a view does and what
21
+ * no amount of TypeScript can do for a row nobody has loaded.
22
+ *
23
+ * WHAT THAT COSTS, stated plainly: the rule can no longer be tested without a database, so
24
+ * `npx vitest run` cannot cover its semantics. Two things stand in for it. `contract-state.test.ts`
25
+ * asserts the committed migration's `CASE` matches the branches and precedence THIS TEST declares —
26
+ * an expectation owned by the test, checked against the single implementation, so it is not two
27
+ * implementations agreeing with each other. And `test-harnesses/state-equivalence.mjs` runs fixtures
28
+ * covering every state and the termination boundary through the deployed view and asserts the answers
29
+ * a person wrote down.
30
+ *
31
+ * A contract being EDITED therefore shows its last-saved state, not a live projection of unsaved
32
+ * dates. That is deliberate: a chip reacting to an unsaved date asserts something no query would
33
+ * agree with.
34
+ *
35
+ * @module @mj-biz-apps/contracts-entities
36
+ */
37
+ /**
38
+ * The six lifecycle states, in precedence order — first match wins (ERD §4.5).
39
+ *
40
+ * Kept in TypeScript because the CLIENT needs the vocabulary (chip colours, a filter pill, a typed
41
+ * `State` accessor) even though it does not own the rule. This is a value list, not a second
42
+ * implementation: nothing here decides which state a contract is in.
43
+ *
44
+ * The order is load-bearing documentation of the view's precedence, and
45
+ * `contract-state.test.ts` asserts the migration's `CASE` still matches it.
46
+ */
47
+ export declare const CONTRACT_STATES: readonly ["Terminated", "Superseded", "Expired", "Active", "Executed", "Draft"];
48
+ export type ContractState = (typeof CONTRACT_STATES)[number];
49
+ //# sourceMappingURL=contract-state.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"contract-state.d.ts","sourceRoot":"","sources":["../src/contract-state.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAmCG;AAEH;;;;;;;;;GASG;AACH,eAAO,MAAM,eAAe,iFAAkF,CAAC;AAE/G,MAAM,MAAM,aAAa,GAAG,CAAC,OAAO,eAAe,CAAC,CAAC,MAAM,CAAC,CAAC"}