@mj-biz-apps/sales-ng 6.4.0 → 6.6.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 (89) hide show
  1. package/dist/lib/board/deal-board.component.js +2 -2
  2. package/dist/lib/board/deal-board.component.js.map +1 -1
  3. package/dist/lib/custom/company-from-pipeline.d.ts +66 -0
  4. package/dist/lib/custom/company-from-pipeline.d.ts.map +1 -0
  5. package/dist/lib/custom/company-from-pipeline.js +67 -0
  6. package/dist/lib/custom/company-from-pipeline.js.map +1 -0
  7. package/dist/lib/custom/deal-form.component.d.ts +43 -2
  8. package/dist/lib/custom/deal-form.component.d.ts.map +1 -1
  9. package/dist/lib/custom/deal-form.component.js +153 -68
  10. package/dist/lib/custom/deal-form.component.js.map +1 -1
  11. package/dist/lib/custom/deal-stage-event-form.component.js +6 -4
  12. package/dist/lib/custom/deal-stage-event-form.component.js.map +1 -1
  13. package/dist/lib/data/entity-names.d.ts +11 -0
  14. package/dist/lib/data/entity-names.d.ts.map +1 -1
  15. package/dist/lib/data/entity-names.js +11 -0
  16. package/dist/lib/data/entity-names.js.map +1 -1
  17. package/dist/lib/form-panels/deal-form.panels.d.ts +570 -10
  18. package/dist/lib/form-panels/deal-form.panels.d.ts.map +1 -1
  19. package/dist/lib/form-panels/deal-form.panels.js +2785 -375
  20. package/dist/lib/form-panels/deal-form.panels.js.map +1 -1
  21. package/dist/lib/form-panels/deal-hero.panel.d.ts +85 -2
  22. package/dist/lib/form-panels/deal-hero.panel.d.ts.map +1 -1
  23. package/dist/lib/form-panels/deal-hero.panel.js +264 -87
  24. package/dist/lib/form-panels/deal-hero.panel.js.map +1 -1
  25. package/dist/lib/form-panels/deal-line-editor.component.d.ts +241 -0
  26. package/dist/lib/form-panels/deal-line-editor.component.d.ts.map +1 -0
  27. package/dist/lib/form-panels/deal-line-editor.component.js +882 -0
  28. package/dist/lib/form-panels/deal-line-editor.component.js.map +1 -0
  29. package/dist/lib/form-panels/deal-related-links.d.ts +70 -0
  30. package/dist/lib/form-panels/deal-related-links.d.ts.map +1 -0
  31. package/dist/lib/form-panels/deal-related-links.js +86 -0
  32. package/dist/lib/form-panels/deal-related-links.js.map +1 -0
  33. package/dist/lib/form-panels/order-related-links.d.ts +84 -0
  34. package/dist/lib/form-panels/order-related-links.d.ts.map +1 -0
  35. package/dist/lib/form-panels/order-related-links.js +66 -0
  36. package/dist/lib/form-panels/order-related-links.js.map +1 -0
  37. package/dist/lib/form-panels/order-related.panel.d.ts +53 -0
  38. package/dist/lib/form-panels/order-related.panel.d.ts.map +1 -0
  39. package/dist/lib/form-panels/order-related.panel.js +175 -0
  40. package/dist/lib/form-panels/order-related.panel.js.map +1 -0
  41. package/dist/lib/form-panels/party-deals.panels.d.ts.map +1 -1
  42. package/dist/lib/form-panels/party-deals.panels.js +47 -39
  43. package/dist/lib/form-panels/party-deals.panels.js.map +1 -1
  44. package/dist/lib/generated/Entities/mjBizAppsSalesDeal/mjbizappssalesdeal.form.component.js +51 -29
  45. package/dist/lib/generated/Entities/mjBizAppsSalesDeal/mjbizappssalesdeal.form.component.js.map +1 -1
  46. package/dist/lib/generated/Entities/mjBizAppsSalesDealStageEvent/mjbizappssalesdealstageevent.form.component.js +6 -4
  47. package/dist/lib/generated/Entities/mjBizAppsSalesDealStageEvent/mjbizappssalesdealstageevent.form.component.js.map +1 -1
  48. package/dist/lib/generated/Entities/mjBizAppsSalesPipelineStage/mjbizappssalespipelinestage.form.component.js +2 -2
  49. package/dist/lib/generated/Entities/mjBizAppsSalesSalesAccount/mjbizappssalessalesaccount.form.component.js +2 -2
  50. package/dist/lib/generated/Entities/mjBizAppsSalesSalesAccount/mjbizappssalessalesaccount.form.component.js.map +1 -1
  51. package/dist/lib/generated/Entities/mjBizAppsSalesSalesContact/mjbizappssalessalescontact.form.component.js +2 -2
  52. package/dist/lib/generated/Entities/mjBizAppsSalesSalesContact/mjbizappssalessalescontact.form.component.js.map +1 -1
  53. package/dist/lib/generated/generated-forms.module.d.ts +102 -27
  54. package/dist/lib/generated/generated-forms.module.d.ts.map +1 -1
  55. package/dist/lib/generated/generated-forms.module.js +492 -42
  56. package/dist/lib/generated/generated-forms.module.js.map +1 -1
  57. package/dist/lib/pages/dashboard-dates.d.ts +25 -0
  58. package/dist/lib/pages/dashboard-dates.d.ts.map +1 -0
  59. package/dist/lib/pages/dashboard-dates.js +32 -0
  60. package/dist/lib/pages/dashboard-dates.js.map +1 -0
  61. package/dist/lib/pages/dashboard-inspect.d.ts +50 -5
  62. package/dist/lib/pages/dashboard-inspect.d.ts.map +1 -1
  63. package/dist/lib/pages/dashboard-inspect.js +70 -13
  64. package/dist/lib/pages/dashboard-inspect.js.map +1 -1
  65. package/dist/lib/pages/dashboard-period.d.ts +144 -0
  66. package/dist/lib/pages/dashboard-period.d.ts.map +1 -0
  67. package/dist/lib/pages/dashboard-period.js +267 -0
  68. package/dist/lib/pages/dashboard-period.js.map +1 -0
  69. package/dist/lib/sections/sales-section.component.d.ts +71 -0
  70. package/dist/lib/sections/sales-section.component.d.ts.map +1 -1
  71. package/dist/lib/sections/sales-section.component.js +398 -199
  72. package/dist/lib/sections/sales-section.component.js.map +1 -1
  73. package/dist/lib/workspace/deal-workspace.component.d.ts +58 -4
  74. package/dist/lib/workspace/deal-workspace.component.d.ts.map +1 -1
  75. package/dist/lib/workspace/deal-workspace.component.js +113 -35
  76. package/dist/lib/workspace/deal-workspace.component.js.map +1 -1
  77. package/dist/lib/workspace/deal-workspace.service.d.ts +44 -1
  78. package/dist/lib/workspace/deal-workspace.service.d.ts.map +1 -1
  79. package/dist/lib/workspace/deal-workspace.service.js +103 -2
  80. package/dist/lib/workspace/deal-workspace.service.js.map +1 -1
  81. package/dist/lib/workspace/deal-workspace.validation.d.ts +18 -0
  82. package/dist/lib/workspace/deal-workspace.validation.d.ts.map +1 -1
  83. package/dist/lib/workspace/deal-workspace.validation.js +18 -0
  84. package/dist/lib/workspace/deal-workspace.validation.js.map +1 -1
  85. package/dist/public-api.d.ts +3 -0
  86. package/dist/public-api.d.ts.map +1 -1
  87. package/dist/public-api.js +10 -0
  88. package/dist/public-api.js.map +1 -1
  89. package/package.json +4 -3
@@ -583,7 +583,7 @@ export class DealBoardComponent {
583
583
  }
584
584
  TrackColumn = (_, column) => column.StageID;
585
585
  static ɵfac = function DealBoardComponent_Factory(__ngFactoryType__) { return new (__ngFactoryType__ || DealBoardComponent)(); };
586
- static ɵcmp = /*@__PURE__*/ i0.ɵɵdefineComponent({ type: DealBoardComponent, selectors: [["mjs-deal-board"]], inputs: { Deals: "Deals", Pipelines: "Pipelines", Stages: "Stages", DealStatusTypes: "DealStatusTypes" }, outputs: { DealOpened: "DealOpened", StageMoved: "StageMoved" }, decls: 11, vars: 3, consts: [[1, "db"], [1, "db-bar"], [1, "db-bar__label"], ["role", "tablist", "aria-label", "Pipeline", 1, "db-bar__pipes"], ["type", "button", "role", "tab", 1, "db-pipe", 3, "db-pipe--on"], [1, "db-bar__busy"], ["role", "status", 1, "db-msg"], [1, "db-empty"], ["type", "button", "role", "tab", 1, "db-pipe", 3, "click"], ["aria-hidden", "true", 1, "fa-solid", "fa-spinner", "fa-spin"], ["aria-hidden", "true", 1, "fa-solid", "fa-circle-info"], [1, "db-cols"], [1, "db-col", 3, "db-col--closing"], [1, "db-unstaged"], [1, "db-col"], [1, "db-col__head"], [1, "db-col__name"], ["aria-hidden", "true", "title", "Arriving here closes and locks the deal \u2014 close it from the deal form.", 1, "fa-solid", "fa-lock", "db-col__lock"], [1, "db-col__meta"], [1, "db-col__count"], ["title", "This stage holds deals in more than one currency, so a single total would be meaningless.", 1, "db-col__total", "db-col__total--mixed"], [1, "db-col__total", 3, "db-col__total--stated"], [1, "db-col__partial", 3, "title"], ["cdkDropList", "", 1, "db-col__drop", 3, "cdkDropListDropped", "id", "cdkDropListData", "cdkDropListConnectedTo", "cdkDropListEnterPredicate"], ["cdkDrag", "", "tabindex", "0", "role", "button", 1, "db-card", 3, "cdkDragData", "cdkDragDisabled"], [1, "db-col__empty"], [1, "db-col__total"], ["aria-hidden", "true", 1, "fa-solid", "fa-pen-nib"], ["cdkDrag", "", "tabindex", "0", "role", "button", 1, "db-card", 3, "click", "keydown.enter", "cdkDragData", "cdkDragDisabled"], [1, "db-card__name"], [1, "db-card__customer"], ["aria-hidden", "true", 1, "fa-solid", "fa-building"], [1, "db-card__figures"], [1, "db-card__amount"], ["title", "No amount recorded yet", 1, "db-card__noamount"], [1, "db-card__prob"], [1, "db-card__foot"], [1, "db-card__owner"], [1, "db-card__close"], ["class", "db-card__ghost", 4, "cdkDragPreview"], ["aria-hidden", "true", "title", "Priced by the orders engine", 1, "fa-solid", "fa-calculator", "db-card__computed"], ["aria-hidden", "true", "title", "Stated by a person, not priced by the orders engine", 1, "fa-solid", "fa-pen-nib", "db-card__stated"], [1, "db-card__ghost"], [1, "db-unstaged__head"], ["aria-hidden", "true", 1, "fa-solid", "fa-circle-question"], [1, "db-unstaged__list"], ["type", "button", 1, "db-chip"], ["type", "button", 1, "db-chip", 3, "click"]], template: function DealBoardComponent_Template(rf, ctx) { if (rf & 1) {
586
+ static ɵcmp = /*@__PURE__*/ i0.ɵɵdefineComponent({ type: DealBoardComponent, selectors: [["mjs-deal-board"]], inputs: { Deals: "Deals", Pipelines: "Pipelines", Stages: "Stages", DealStatusTypes: "DealStatusTypes" }, outputs: { DealOpened: "DealOpened", StageMoved: "StageMoved" }, decls: 11, vars: 3, consts: [[1, "db"], [1, "db-bar"], [1, "db-bar__label"], ["role", "tablist", "aria-label", "Pipeline", 1, "db-bar__pipes"], ["type", "button", "role", "tab", 1, "db-pipe", 3, "db-pipe--on"], [1, "db-bar__busy"], ["role", "status", 1, "db-msg"], [1, "db-empty"], ["type", "button", "role", "tab", 1, "db-pipe", 3, "click"], ["aria-hidden", "true", 1, "fa-solid", "fa-spinner", "fa-spin"], ["aria-hidden", "true", 1, "fa-solid", "fa-circle-info"], [1, "db-cols"], [1, "db-col", 3, "db-col--closing"], [1, "db-unstaged"], [1, "db-col"], [1, "db-col__head"], [1, "db-col__name"], ["aria-hidden", "true", "title", "Deals cannot be moved here. Close a deal from the deal form.", 1, "fa-solid", "fa-lock", "db-col__lock"], [1, "db-col__meta"], [1, "db-col__count"], ["title", "This stage holds deals in more than one currency, so a single total would be meaningless.", 1, "db-col__total", "db-col__total--mixed"], [1, "db-col__total", 3, "db-col__total--stated"], [1, "db-col__partial", 3, "title"], ["cdkDropList", "", 1, "db-col__drop", 3, "cdkDropListDropped", "id", "cdkDropListData", "cdkDropListConnectedTo", "cdkDropListEnterPredicate"], ["cdkDrag", "", "tabindex", "0", "role", "button", 1, "db-card", 3, "cdkDragData", "cdkDragDisabled"], [1, "db-col__empty"], [1, "db-col__total"], ["aria-hidden", "true", 1, "fa-solid", "fa-pen-nib"], ["cdkDrag", "", "tabindex", "0", "role", "button", 1, "db-card", 3, "click", "keydown.enter", "cdkDragData", "cdkDragDisabled"], [1, "db-card__name"], [1, "db-card__customer"], ["aria-hidden", "true", 1, "fa-solid", "fa-building"], [1, "db-card__figures"], [1, "db-card__amount"], ["title", "No amount recorded yet", 1, "db-card__noamount"], [1, "db-card__prob"], [1, "db-card__foot"], [1, "db-card__owner"], [1, "db-card__close"], ["class", "db-card__ghost", 4, "cdkDragPreview"], ["aria-hidden", "true", "title", "Priced by Orders", 1, "fa-solid", "fa-calculator", "db-card__computed"], ["aria-hidden", "true", "title", "Entered manually rather than priced by Orders", 1, "fa-solid", "fa-pen-nib", "db-card__stated"], [1, "db-card__ghost"], [1, "db-unstaged__head"], ["aria-hidden", "true", 1, "fa-solid", "fa-circle-question"], [1, "db-unstaged__list"], ["type", "button", 1, "db-chip"], ["type", "button", 1, "db-chip", 3, "click"]], template: function DealBoardComponent_Template(rf, ctx) { if (rf & 1) {
587
587
  i0.ɵɵelementStart(0, "div", 0)(1, "div", 1)(2, "span", 2);
588
588
  i0.ɵɵtext(3, "Pipeline");
589
589
  i0.ɵɵelementEnd();
@@ -608,7 +608,7 @@ export class DealBoardComponent {
608
608
  }
609
609
  (() => { (typeof ngDevMode === "undefined" || ngDevMode) && i0.ɵsetClassMetadata(DealBoardComponent, [{
610
610
  type: Component,
611
- args: [{ selector: 'mjs-deal-board', standalone: true, imports: [CommonModule, CdkDropList, CdkDrag], template: "<!--\n The pipeline board. Columns are stages in DisplayOrder; cards are deals.\n\n A closing column renders disabled with a hint rather than being hidden: hiding it would make the board\n lie about the pipeline's shape, and a rep looking for \"where do won deals go\" needs to see that the\n answer is \"not by dragging\".\n-->\n<div class=\"db\">\n\n <!-- Pipeline switcher. A pipeline defines the stages, so this is the board's one real control. -->\n <div class=\"db-bar\">\n <span class=\"db-bar__label\">Pipeline</span>\n <div class=\"db-bar__pipes\" role=\"tablist\" aria-label=\"Pipeline\">\n @for (pipeline of Pipelines; track pipeline.ID) {\n <button\n type=\"button\"\n role=\"tab\"\n class=\"db-pipe\"\n [class.db-pipe--on]=\"pipeline.ID === ActivePipelineID\"\n [attr.aria-selected]=\"pipeline.ID === ActivePipelineID\"\n (click)=\"SelectPipeline(pipeline.ID)\">\n {{ pipeline.Name }}\n </button>\n }\n </div>\n @if (Moving) {\n <span class=\"db-bar__busy\"><i class=\"fa-solid fa-spinner fa-spin\" aria-hidden=\"true\"></i> Moving\u2026</span>\n }\n </div>\n\n @if (Message) {\n <p class=\"db-msg\" role=\"status\">\n <i class=\"fa-solid fa-circle-info\" aria-hidden=\"true\"></i> {{ Message }}\n </p>\n }\n\n @if (Columns.length === 0) {\n <p class=\"db-empty\">This pipeline has no stages yet.</p>\n } @else {\n <div class=\"db-cols\">\n @for (column of Columns; track TrackColumn($index, column)) {\n <section\n class=\"db-col\"\n [class.db-col--closing]=\"column.IsClosing\"\n [attr.aria-label]=\"column.Label\">\n\n <header class=\"db-col__head\">\n <span class=\"db-col__name\">\n {{ column.Label }}\n @if (column.IsClosing) {\n <i class=\"fa-solid fa-lock db-col__lock\"\n aria-hidden=\"true\"\n title=\"Arriving here closes and locks the deal \u2014 close it from the deal form.\"></i>\n }\n </span>\n <span class=\"db-col__meta\">\n <span class=\"db-col__count\">{{ column.Cards.length }}</span>\n <!--\n A SUM of stored Deal.Amount values. This app prices nothing; the marker says whether the\n ORDERS engine did, and the currency question is separate from the provenance question.\n\n NO TOTAL WHEN THE COLUMN MIXES CURRENCIES. Adding EUR to USD produces a number that is\n wrong in a way nobody can see; an absent figure prompts a question instead.\n\n UNIONED, and the board branch's half needed one correction to survive: it carried\n `currency:'USD'`, which is the hardcoding the currency work removed. The `--stated` class\n is its contribution and is kept; the literal is not.\n -->\n @if (column.MixedCurrency) {\n <span class=\"db-col__total db-col__total--mixed\"\n title=\"This stage holds deals in more than one currency, so a single total would be meaningless.\">\n mixed currencies\n </span>\n } @else {\n <span class=\"db-col__total\" [class.db-col__total--stated]=\"column.Unpriced > 0\">\n <!-- `?? DefaultCurrency` because Currency is null in two different situations and only\n one of them is \"mixed\": an EMPTY column has no currency to disagree about, and its\n total is 0. The mixed case never reaches here \u2014 it is the @if above. -->\n {{ column.Total | currency:(column.Currency ?? DefaultCurrency):'symbol':'1.0-0' }}\n </span>\n }\n </span>\n @if (column.Unpriced > 0) {\n <!--\n SAYS WHICH OF THE TWO IT IS. A total nobody priced and a total that is only partly\n priced are different claims, and collapsing them is how a stated figure passes for an\n authoritative one. The wording lives in PricingNote() -- a template expression cannot\n hold a sentence without becoming unreadable.\n -->\n <span class=\"db-col__partial\" [title]=\"PricingNote(column)\">\n <i class=\"fa-solid fa-pen-nib\" aria-hidden=\"true\"></i>\n @if (column.NonePriced) {\n stated, not priced\n } @else {\n {{ column.Unpriced }} of {{ column.Cards.length }} stated\n }\n </span>\n }\n </header>\n\n <div\n class=\"db-col__drop\"\n cdkDropList\n [id]=\"'col-' + column.StageID\"\n [cdkDropListData]=\"column\"\n [cdkDropListConnectedTo]=\"ColumnIDs\"\n [cdkDropListEnterPredicate]=\"CanDropInto(column)\"\n (cdkDropListDropped)=\"OnDrop($event, column)\">\n\n @for (deal of column.Cards; track TrackCard($index, deal)) {\n <article\n class=\"db-card\"\n cdkDrag\n [cdkDragData]=\"deal\"\n [cdkDragDisabled]=\"Moving\"\n (click)=\"OpenCard(deal)\"\n (keydown.enter)=\"OpenCard(deal)\"\n tabindex=\"0\"\n role=\"button\"\n [attr.aria-label]=\"'Open ' + deal.Name\">\n\n <div class=\"db-card__name\">{{ deal.Name }}</div>\n <div class=\"db-card__customer\">\n <i class=\"fa-solid fa-building\" aria-hidden=\"true\"></i> {{ deal.CustomerName }}\n </div>\n\n <div class=\"db-card__figures\">\n <span class=\"db-card__amount\">\n @if (deal.Amount === null) {\n <span class=\"db-card__noamount\" title=\"No amount recorded yet\">\u2014</span>\n } @else {\n {{ deal.Amount | currency:(deal.CurrencyID ?? DefaultCurrency):'symbol':'1.0-0' }}\n }\n <!--\n BOTH CASES ARE MARKED, and marking only one was the defect. A calculator on the\n priced figure and nothing on the stated one means the reader has to notice an\n ABSENCE to learn anything -- and on data where nothing is priced, no card carries\n a marker at all, so the whole board reads as authoritative. A positive mark on\n each says which it is without anyone having to know the convention.\n -->\n @if (deal.Amount !== null) {\n @if (deal.AmountIsComputed) {\n <i class=\"fa-solid fa-calculator db-card__computed\"\n aria-hidden=\"true\"\n title=\"Priced by the orders engine\"></i>\n } @else {\n <i class=\"fa-solid fa-pen-nib db-card__stated\"\n aria-hidden=\"true\"\n title=\"Stated by a person, not priced by the orders engine\"></i>\n }\n }\n </span>\n @if (deal.Probability !== null) {\n <span class=\"db-card__prob\">{{ deal.Probability }}%</span>\n }\n </div>\n\n <div class=\"db-card__foot\">\n <span class=\"db-card__owner\">{{ deal.OwnerEmployee ?? 'Unassigned' }}</span>\n <span class=\"db-card__close\">{{ deal.ExpectedCloseDate ? (deal.ExpectedCloseDate | date:'MMM d, y') : 'No date' }}</span>\n </div>\n\n <div class=\"db-card__ghost\" *cdkDragPreview>{{ deal.Name }}</div>\n </article>\n }\n\n @if (column.Cards.length === 0) {\n <p class=\"db-col__empty\">\n @if (column.IsClosing) { Close deals from the deal form. } @else { Nothing here. }\n </p>\n }\n </div>\n </section>\n }\n </div>\n\n @if (Unstaged.length > 0) {\n <!-- Deals with no stage would otherwise be invisible on a board built from stage columns, and\n \"missing from the board\" is indistinguishable from \"does not exist\". -->\n <section class=\"db-unstaged\">\n <h4 class=\"db-unstaged__head\">\n <i class=\"fa-solid fa-circle-question\" aria-hidden=\"true\"></i>\n No stage set ({{ Unstaged.length }})\n </h4>\n <div class=\"db-unstaged__list\">\n @for (deal of Unstaged; track TrackCard($index, deal)) {\n <button type=\"button\" class=\"db-chip\" (click)=\"OpenCard(deal)\">\n {{ deal.Name }}\n </button>\n }\n </div>\n </section>\n }\n }\n</div>\n", styles: ["/*\n Board styles.\n\n SEMANTIC TOKENS ONLY \u2014 the same `--mj-*` set the workspace uses, so the board inherits dark mode rather\n than needing its own. No hardcoded colour appears in this file.\n*/\n\n.db {\n display: flex;\n flex-direction: column;\n gap: 0.75rem;\n min-height: 0;\n}\n\n/* \u2500\u2500 Pipeline switcher \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500 */\n\n.db-bar {\n display: flex;\n align-items: center;\n gap: 0.75rem;\n flex-wrap: wrap;\n}\n\n.db-bar__label {\n font-size: 0.8125rem;\n color: var(--mj-text-muted);\n}\n\n.db-bar__pipes {\n display: flex;\n gap: 0.25rem;\n}\n\n.db-bar__busy {\n font-size: 0.8125rem;\n color: var(--mj-text-secondary);\n}\n\n.db-pipe {\n padding: 0.3rem 0.75rem;\n border: 1px solid var(--mj-border-default);\n border-radius: 999px;\n background: var(--mj-bg-surface);\n color: var(--mj-text-secondary);\n font-size: 0.8125rem;\n cursor: pointer;\n}\n\n.db-pipe:hover {\n background: var(--mj-bg-surface-hover);\n}\n\n.db-pipe--on {\n border-color: var(--mj-brand-primary);\n color: var(--mj-brand-primary);\n font-weight: 600;\n}\n\n.db-msg {\n margin: 0;\n padding: 0.5rem 0.75rem;\n border: 1px solid var(--mj-status-warning-border);\n border-radius: 4px;\n color: var(--mj-status-warning);\n font-size: 0.8125rem;\n}\n\n.db-empty {\n color: var(--mj-text-muted);\n font-size: 0.875rem;\n}\n\n/* \u2500\u2500 Columns \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500 */\n\n/*\n Horizontal scroll lives HERE rather than on the page: a board with eight stages must not make the whole\n shell scroll sideways, which would drag the rail and the header out of view.\n*/\n.db-cols {\n display: flex;\n gap: 0.75rem;\n overflow-x: auto;\n padding-bottom: 0.5rem;\n align-items: flex-start;\n}\n\n.db-col {\n flex: 0 0 15rem;\n display: flex;\n flex-direction: column;\n background: var(--mj-bg-surface);\n border: 1px solid var(--mj-border-default);\n border-radius: 6px;\n min-height: 8rem;\n}\n\n/* A closing column is visibly inert \u2014 it accepts no drops, and should not invite one. */\n.db-col--closing {\n border-style: dashed;\n opacity: 0.75;\n}\n\n.db-col__head {\n display: flex;\n flex-direction: column;\n gap: 0.125rem;\n padding: 0.5rem 0.625rem;\n border-bottom: 1px solid var(--mj-border-default);\n}\n\n.db-col__name {\n font-size: 0.8125rem;\n font-weight: 600;\n color: var(--mj-text-primary);\n display: flex;\n align-items: center;\n gap: 0.375rem;\n}\n\n.db-col__lock {\n color: var(--mj-text-muted);\n font-size: 0.6875rem;\n}\n\n.db-col__meta {\n display: flex;\n justify-content: space-between;\n align-items: baseline;\n gap: 0.5rem;\n}\n\n.db-col__count {\n font-size: 0.75rem;\n color: var(--mj-text-muted);\n}\n\n.db-col__total {\n font-size: 0.75rem;\n color: var(--mj-text-secondary);\n font-variant-numeric: tabular-nums;\n}\n\n/* A total that nobody priced still reads as a figure -- this keeps it from reading as a FINAL one. */\n.db-col__total--stated {\n font-style: italic;\n}\n\n.db-col__partial {\n font-size: 0.6875rem;\n color: var(--mj-status-warning);\n}\n\n.db-col__drop {\n display: flex;\n flex-direction: column;\n gap: 0.375rem;\n padding: 0.5rem;\n min-height: 4rem;\n}\n\n.db-col__empty {\n margin: 0;\n font-size: 0.75rem;\n color: var(--mj-text-muted);\n text-align: center;\n padding: 0.75rem 0.25rem;\n}\n\n/* \u2500\u2500 Cards \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500 */\n\n.db-card {\n background: var(--mj-bg-surface-card);\n border: 1px solid var(--mj-border-default);\n border-radius: 4px;\n padding: 0.5rem 0.625rem;\n cursor: pointer;\n display: flex;\n flex-direction: column;\n gap: 0.25rem;\n}\n\n.db-card:hover {\n background: var(--mj-bg-surface-hover);\n}\n\n.db-card:focus-visible {\n outline: 2px solid var(--mj-border-focus);\n outline-offset: 1px;\n}\n\n.db-card__name {\n font-size: 0.8125rem;\n font-weight: 600;\n color: var(--mj-text-primary);\n line-height: 1.25;\n}\n\n.db-card__customer {\n font-size: 0.75rem;\n color: var(--mj-text-secondary);\n display: flex;\n align-items: center;\n gap: 0.3rem;\n}\n\n.db-card__figures {\n display: flex;\n justify-content: space-between;\n align-items: baseline;\n gap: 0.5rem;\n}\n\n.db-card__amount {\n font-size: 0.8125rem;\n color: var(--mj-text-primary);\n font-variant-numeric: tabular-nums;\n display: flex;\n align-items: center;\n gap: 0.3rem;\n}\n\n/*\n * The two provenance markers are deliberately the SAME weight as each other.\n *\n * Making the stated one louder would read as an error, which it is not -- a stated amount is a\n * legitimate answer, just a different kind of fact from a priced one. Making it quieter would put us\n * back where we started, with the reader learning nothing unless they notice an absence.\n */\n.db-card__stated,\n.db-card__noamount,\n.db-card__computed {\n color: var(--mj-text-muted);\n font-size: 0.6875rem;\n}\n\n.db-card__prob {\n font-size: 0.75rem;\n color: var(--mj-text-muted);\n}\n\n.db-card__foot {\n display: flex;\n justify-content: space-between;\n gap: 0.5rem;\n font-size: 0.6875rem;\n color: var(--mj-text-muted);\n}\n\n.db-card__owner,\n.db-card__close {\n overflow: hidden;\n text-overflow: ellipsis;\n white-space: nowrap;\n}\n\n.db-card__ghost {\n padding: 0.375rem 0.625rem;\n background: var(--mj-bg-surface-card);\n border: 1px solid var(--mj-brand-primary);\n border-radius: 4px;\n font-size: 0.8125rem;\n color: var(--mj-text-primary);\n}\n\n/* \u2500\u2500 Unstaged \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500 */\n\n.db-unstaged {\n border-top: 1px solid var(--mj-border-default);\n padding-top: 0.625rem;\n}\n\n.db-unstaged__head {\n margin: 0 0 0.375rem;\n font-size: 0.75rem;\n font-weight: 600;\n color: var(--mj-text-muted);\n display: flex;\n align-items: center;\n gap: 0.375rem;\n}\n\n.db-unstaged__list {\n display: flex;\n flex-wrap: wrap;\n gap: 0.375rem;\n}\n\n.db-chip {\n padding: 0.25rem 0.625rem;\n border: 1px solid var(--mj-border-default);\n border-radius: 999px;\n background: var(--mj-bg-surface);\n color: var(--mj-text-secondary);\n font-size: 0.75rem;\n cursor: pointer;\n}\n\n.db-chip:hover {\n background: var(--mj-bg-surface-hover);\n}\n"] }]
611
+ args: [{ selector: 'mjs-deal-board', standalone: true, imports: [CommonModule, CdkDropList, CdkDrag], template: "<!--\n The pipeline board. Columns are stages in DisplayOrder; cards are deals.\n\n A closing column renders disabled with a hint rather than being hidden: hiding it would make the board\n lie about the pipeline's shape, and a rep looking for \"where do won deals go\" needs to see that the\n answer is \"not by dragging\".\n-->\n<div class=\"db\">\n\n <!-- Pipeline switcher. A pipeline defines the stages, so this is the board's one real control. -->\n <div class=\"db-bar\">\n <span class=\"db-bar__label\">Pipeline</span>\n <div class=\"db-bar__pipes\" role=\"tablist\" aria-label=\"Pipeline\">\n @for (pipeline of Pipelines; track pipeline.ID) {\n <button\n type=\"button\"\n role=\"tab\"\n class=\"db-pipe\"\n [class.db-pipe--on]=\"pipeline.ID === ActivePipelineID\"\n [attr.aria-selected]=\"pipeline.ID === ActivePipelineID\"\n (click)=\"SelectPipeline(pipeline.ID)\">\n {{ pipeline.Name }}\n </button>\n }\n </div>\n @if (Moving) {\n <span class=\"db-bar__busy\"><i class=\"fa-solid fa-spinner fa-spin\" aria-hidden=\"true\"></i> Moving\u2026</span>\n }\n </div>\n\n @if (Message) {\n <p class=\"db-msg\" role=\"status\">\n <i class=\"fa-solid fa-circle-info\" aria-hidden=\"true\"></i> {{ Message }}\n </p>\n }\n\n @if (Columns.length === 0) {\n <p class=\"db-empty\">This pipeline has no stages yet.</p>\n } @else {\n <div class=\"db-cols\">\n @for (column of Columns; track TrackColumn($index, column)) {\n <section\n class=\"db-col\"\n [class.db-col--closing]=\"column.IsClosing\"\n [attr.aria-label]=\"column.Label\">\n\n <header class=\"db-col__head\">\n <span class=\"db-col__name\">\n {{ column.Label }}\n @if (column.IsClosing) {\n <!--\n THIS SAID THE OPPOSITE OF WHAT HAPPENS. \"Arriving here closes and locks the\n deal\" describes a behaviour the server deliberately refuses: a stage whose\n status locks contributes NO status to a save, so a deal moved into this\n column keeps the status it had (`planStageDefaults` gates on `LocksDeal`).\n A rep reading the old text would think a drag closes the deal.\n\n And the drag cannot happen either: `CanDropInto` returns false for a closing\n column, with a second guard behind it. So the tooltip says what the lock icon\n actually means -- this column is not a destination -- and where closing lives,\n which is the same place the empty state below points.\n -->\n <i class=\"fa-solid fa-lock db-col__lock\"\n aria-hidden=\"true\"\n title=\"Deals cannot be moved here. Close a deal from the deal form.\"></i>\n }\n </span>\n <span class=\"db-col__meta\">\n <span class=\"db-col__count\">{{ column.Cards.length }}</span>\n <!--\n A SUM of stored Deal.Amount values. This app prices nothing; the marker says whether the\n ORDERS engine did, and the currency question is separate from the provenance question.\n\n NO TOTAL WHEN THE COLUMN MIXES CURRENCIES. Adding EUR to USD produces a number that is\n wrong in a way nobody can see; an absent figure prompts a question instead.\n\n UNIONED, and the board branch's half needed one correction to survive: it carried\n `currency:'USD'`, which is the hardcoding the currency work removed. The `--stated` class\n is its contribution and is kept; the literal is not.\n -->\n @if (column.MixedCurrency) {\n <span class=\"db-col__total db-col__total--mixed\"\n title=\"This stage holds deals in more than one currency, so a single total would be meaningless.\">\n mixed currencies\n </span>\n } @else {\n <span class=\"db-col__total\" [class.db-col__total--stated]=\"column.Unpriced > 0\">\n <!-- `?? DefaultCurrency` because Currency is null in two different situations and only\n one of them is \"mixed\": an EMPTY column has no currency to disagree about, and its\n total is 0. The mixed case never reaches here \u2014 it is the @if above. -->\n {{ column.Total | currency:(column.Currency ?? DefaultCurrency):'symbol':'1.0-0' }}\n </span>\n }\n </span>\n @if (column.Unpriced > 0) {\n <!--\n SAYS WHICH OF THE TWO IT IS. A total nobody priced and a total that is only partly\n priced are different claims, and collapsing them is how a stated figure passes for an\n authoritative one. The wording lives in PricingNote() -- a template expression cannot\n hold a sentence without becoming unreadable.\n -->\n <span class=\"db-col__partial\" [title]=\"PricingNote(column)\">\n <i class=\"fa-solid fa-pen-nib\" aria-hidden=\"true\"></i>\n @if (column.NonePriced) {\n stated, not priced\n } @else {\n {{ column.Unpriced }} of {{ column.Cards.length }} stated\n }\n </span>\n }\n </header>\n\n <div\n class=\"db-col__drop\"\n cdkDropList\n [id]=\"'col-' + column.StageID\"\n [cdkDropListData]=\"column\"\n [cdkDropListConnectedTo]=\"ColumnIDs\"\n [cdkDropListEnterPredicate]=\"CanDropInto(column)\"\n (cdkDropListDropped)=\"OnDrop($event, column)\">\n\n @for (deal of column.Cards; track TrackCard($index, deal)) {\n <article\n class=\"db-card\"\n cdkDrag\n [cdkDragData]=\"deal\"\n [cdkDragDisabled]=\"Moving\"\n (click)=\"OpenCard(deal)\"\n (keydown.enter)=\"OpenCard(deal)\"\n tabindex=\"0\"\n role=\"button\"\n [attr.aria-label]=\"'Open ' + deal.Name\">\n\n <div class=\"db-card__name\">{{ deal.Name }}</div>\n <div class=\"db-card__customer\">\n <i class=\"fa-solid fa-building\" aria-hidden=\"true\"></i> {{ deal.CustomerName }}\n </div>\n\n <div class=\"db-card__figures\">\n <span class=\"db-card__amount\">\n @if (deal.Amount === null) {\n <span class=\"db-card__noamount\" title=\"No amount recorded yet\">\u2014</span>\n } @else {\n {{ deal.Amount | currency:(deal.CurrencyID ?? DefaultCurrency):'symbol':'1.0-0' }}\n }\n <!--\n BOTH CASES ARE MARKED, and marking only one was the defect. A calculator on the\n priced figure and nothing on the stated one means the reader has to notice an\n ABSENCE to learn anything -- and on data where nothing is priced, no card carries\n a marker at all, so the whole board reads as authoritative. A positive mark on\n each says which it is without anyone having to know the convention.\n -->\n @if (deal.Amount !== null) {\n @if (deal.AmountIsComputed) {\n <i class=\"fa-solid fa-calculator db-card__computed\"\n aria-hidden=\"true\"\n title=\"Priced by Orders\"></i>\n } @else {\n <i class=\"fa-solid fa-pen-nib db-card__stated\"\n aria-hidden=\"true\"\n title=\"Entered manually rather than priced by Orders\"></i>\n }\n }\n </span>\n @if (deal.Probability !== null) {\n <span class=\"db-card__prob\">{{ deal.Probability }}%</span>\n }\n </div>\n\n <div class=\"db-card__foot\">\n <span class=\"db-card__owner\">{{ deal.OwnerEmployee ?? 'Unassigned' }}</span>\n <span class=\"db-card__close\">{{ deal.ExpectedCloseDate ? (deal.ExpectedCloseDate | date:'MMM d, y') : 'No date' }}</span>\n </div>\n\n <div class=\"db-card__ghost\" *cdkDragPreview>{{ deal.Name }}</div>\n </article>\n }\n\n @if (column.Cards.length === 0) {\n <p class=\"db-col__empty\">\n @if (column.IsClosing) { Close deals from the deal form. } @else { Nothing here. }\n </p>\n }\n </div>\n </section>\n }\n </div>\n\n @if (Unstaged.length > 0) {\n <!-- Deals with no stage would otherwise be invisible on a board built from stage columns, and\n \"missing from the board\" is indistinguishable from \"does not exist\". -->\n <section class=\"db-unstaged\">\n <h4 class=\"db-unstaged__head\">\n <i class=\"fa-solid fa-circle-question\" aria-hidden=\"true\"></i>\n No stage set ({{ Unstaged.length }})\n </h4>\n <div class=\"db-unstaged__list\">\n @for (deal of Unstaged; track TrackCard($index, deal)) {\n <button type=\"button\" class=\"db-chip\" (click)=\"OpenCard(deal)\">\n {{ deal.Name }}\n </button>\n }\n </div>\n </section>\n }\n }\n</div>\n", styles: ["/*\n Board styles.\n\n SEMANTIC TOKENS ONLY \u2014 the same `--mj-*` set the workspace uses, so the board inherits dark mode rather\n than needing its own. No hardcoded colour appears in this file.\n*/\n\n.db {\n display: flex;\n flex-direction: column;\n gap: 0.75rem;\n min-height: 0;\n}\n\n/* \u2500\u2500 Pipeline switcher \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500 */\n\n.db-bar {\n display: flex;\n align-items: center;\n gap: 0.75rem;\n flex-wrap: wrap;\n}\n\n.db-bar__label {\n font-size: 0.8125rem;\n color: var(--mj-text-muted);\n}\n\n.db-bar__pipes {\n display: flex;\n gap: 0.25rem;\n}\n\n.db-bar__busy {\n font-size: 0.8125rem;\n color: var(--mj-text-secondary);\n}\n\n.db-pipe {\n padding: 0.3rem 0.75rem;\n border: 1px solid var(--mj-border-default);\n border-radius: 999px;\n background: var(--mj-bg-surface);\n color: var(--mj-text-secondary);\n font-size: 0.8125rem;\n cursor: pointer;\n}\n\n.db-pipe:hover {\n background: var(--mj-bg-surface-hover);\n}\n\n.db-pipe--on {\n border-color: var(--mj-brand-primary);\n color: var(--mj-brand-primary);\n font-weight: 600;\n}\n\n.db-msg {\n margin: 0;\n padding: 0.5rem 0.75rem;\n border: 1px solid var(--mj-status-warning-border);\n border-radius: 4px;\n color: var(--mj-status-warning);\n font-size: 0.8125rem;\n}\n\n.db-empty {\n color: var(--mj-text-muted);\n font-size: 0.875rem;\n}\n\n/* \u2500\u2500 Columns \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500 */\n\n/*\n Horizontal scroll lives HERE rather than on the page: a board with eight stages must not make the whole\n shell scroll sideways, which would drag the rail and the header out of view.\n*/\n.db-cols {\n display: flex;\n gap: 0.75rem;\n overflow-x: auto;\n padding-bottom: 0.5rem;\n align-items: flex-start;\n}\n\n.db-col {\n flex: 0 0 15rem;\n display: flex;\n flex-direction: column;\n background: var(--mj-bg-surface);\n border: 1px solid var(--mj-border-default);\n border-radius: 6px;\n min-height: 8rem;\n}\n\n/* A closing column is visibly inert \u2014 it accepts no drops, and should not invite one. */\n.db-col--closing {\n border-style: dashed;\n opacity: 0.75;\n}\n\n.db-col__head {\n display: flex;\n flex-direction: column;\n gap: 0.125rem;\n padding: 0.5rem 0.625rem;\n border-bottom: 1px solid var(--mj-border-default);\n}\n\n.db-col__name {\n font-size: 0.8125rem;\n font-weight: 600;\n color: var(--mj-text-primary);\n display: flex;\n align-items: center;\n gap: 0.375rem;\n}\n\n.db-col__lock {\n color: var(--mj-text-muted);\n font-size: 0.6875rem;\n}\n\n.db-col__meta {\n display: flex;\n justify-content: space-between;\n align-items: baseline;\n gap: 0.5rem;\n}\n\n.db-col__count {\n font-size: 0.75rem;\n color: var(--mj-text-muted);\n}\n\n.db-col__total {\n font-size: 0.75rem;\n color: var(--mj-text-secondary);\n font-variant-numeric: tabular-nums;\n}\n\n/* A total that nobody priced still reads as a figure -- this keeps it from reading as a FINAL one. */\n.db-col__total--stated {\n font-style: italic;\n}\n\n.db-col__partial {\n font-size: 0.6875rem;\n color: var(--mj-status-warning);\n}\n\n.db-col__drop {\n display: flex;\n flex-direction: column;\n gap: 0.375rem;\n padding: 0.5rem;\n min-height: 4rem;\n}\n\n.db-col__empty {\n margin: 0;\n font-size: 0.75rem;\n color: var(--mj-text-muted);\n text-align: center;\n padding: 0.75rem 0.25rem;\n}\n\n/* \u2500\u2500 Cards \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500 */\n\n.db-card {\n background: var(--mj-bg-surface-card);\n border: 1px solid var(--mj-border-default);\n border-radius: 4px;\n padding: 0.5rem 0.625rem;\n cursor: pointer;\n display: flex;\n flex-direction: column;\n gap: 0.25rem;\n}\n\n.db-card:hover {\n background: var(--mj-bg-surface-hover);\n}\n\n.db-card:focus-visible {\n outline: 2px solid var(--mj-border-focus);\n outline-offset: 1px;\n}\n\n.db-card__name {\n font-size: 0.8125rem;\n font-weight: 600;\n color: var(--mj-text-primary);\n line-height: 1.25;\n}\n\n.db-card__customer {\n font-size: 0.75rem;\n color: var(--mj-text-secondary);\n display: flex;\n align-items: center;\n gap: 0.3rem;\n}\n\n.db-card__figures {\n display: flex;\n justify-content: space-between;\n align-items: baseline;\n gap: 0.5rem;\n}\n\n.db-card__amount {\n font-size: 0.8125rem;\n color: var(--mj-text-primary);\n font-variant-numeric: tabular-nums;\n display: flex;\n align-items: center;\n gap: 0.3rem;\n}\n\n/*\n * The two provenance markers are deliberately the SAME weight as each other.\n *\n * Making the stated one louder would read as an error, which it is not -- a stated amount is a\n * legitimate answer, just a different kind of fact from a priced one. Making it quieter would put us\n * back where we started, with the reader learning nothing unless they notice an absence.\n */\n.db-card__stated,\n.db-card__noamount,\n.db-card__computed {\n color: var(--mj-text-muted);\n font-size: 0.6875rem;\n}\n\n.db-card__prob {\n font-size: 0.75rem;\n color: var(--mj-text-muted);\n}\n\n.db-card__foot {\n display: flex;\n justify-content: space-between;\n gap: 0.5rem;\n font-size: 0.6875rem;\n color: var(--mj-text-muted);\n}\n\n.db-card__owner,\n.db-card__close {\n overflow: hidden;\n text-overflow: ellipsis;\n white-space: nowrap;\n}\n\n.db-card__ghost {\n padding: 0.375rem 0.625rem;\n background: var(--mj-bg-surface-card);\n border: 1px solid var(--mj-brand-primary);\n border-radius: 4px;\n font-size: 0.8125rem;\n color: var(--mj-text-primary);\n}\n\n/* \u2500\u2500 Unstaged \u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500\u2500 */\n\n.db-unstaged {\n border-top: 1px solid var(--mj-border-default);\n padding-top: 0.625rem;\n}\n\n.db-unstaged__head {\n margin: 0 0 0.375rem;\n font-size: 0.75rem;\n font-weight: 600;\n color: var(--mj-text-muted);\n display: flex;\n align-items: center;\n gap: 0.375rem;\n}\n\n.db-unstaged__list {\n display: flex;\n flex-wrap: wrap;\n gap: 0.375rem;\n}\n\n.db-chip {\n padding: 0.25rem 0.625rem;\n border: 1px solid var(--mj-border-default);\n border-radius: 999px;\n background: var(--mj-bg-surface);\n color: var(--mj-text-secondary);\n font-size: 0.75rem;\n cursor: pointer;\n}\n\n.db-chip:hover {\n background: var(--mj-bg-surface-hover);\n}\n"] }]
612
612
  }], null, { Deals: [{
613
613
  type: Input
614
614
  }], Pipelines: [{
@@ -1 +1 @@
1
- {"version":3,"file":"deal-board.component.js","sourceRoot":"","sources":["../../../src/lib/board/deal-board.component.ts","../../../src/lib/board/deal-board.component.html"],"names":[],"mappings":"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"}
1
+ {"version":3,"file":"deal-board.component.js","sourceRoot":"","sources":["../../../src/lib/board/deal-board.component.ts","../../../src/lib/board/deal-board.component.html"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAwCG;AACH,OAAO,EAAE,OAAO,EAAe,WAAW,EAAE,MAAM,wBAAwB,CAAC;AAC3E,OAAO,EAAE,YAAY,EAAE,MAAM,iBAAiB,CAAC;AAC/C,OAAO,EACH,iBAAiB,EACjB,SAAS,EACT,YAAY,EACZ,KAAK,EACL,MAAM,EACN,MAAM,GACT,MAAM,eAAe,CAAC;AAEvB,OAAO,EAAE,oBAAoB,EAAsB,MAAM,qCAAqC,CAAC;;;;;;ICtCvF,iCAMwC;IAAtC,4MAAS,qCAA2B,KAAC;IACrC,YACF;IAAA,iBAAS;;;;IAJP,yEAAsD;;IAGtD,cACF;IADE,iDACF;;;IAIF,+BAA2B;IAAA,uBAA8D;IAAC,6BAAO;IAAA,iBAAO;;;IAK1G,4BAAgC;IAC9B,wBAA0D;IAAC,YAC7D;IAAA,iBAAI;;;IADyD,eAC7D;IAD6D,+CAC7D;;;IAIA,4BAAoB;IAAA,gDAAgC;IAAA,iBAAI;;;IAyB5C,wBAE4E;;;IAiB5E,gCACwG;IACtG,kCACF;IAAA,iBAAO;;;IAEP,gCAAgF;IAI9E,YACF;;IAAA,iBAAO;;;;IALqB,+DAAmD;IAI7E,cACF;IADE,uIACF;;;IAaE,oCACF;;;IACE,YACF;;;IADE,0FACF;;;IANF,gCAA4D;IAC1D,wBAAsD;IAGpD,AAFF,8GAAyB,wFAEhB;IAGX,iBAAO;;;;IAPuB,qDAA6B;IAEzD,eAIC;IAJD,8CAIC;;;IAkCK,gCAA+D;IAAA,sBAAC;IAAA,iBAAO;;;IAEvE,YACF;;;;;IADE,sIACF;;;IAUI,wBAEgC;;;IAEhC,wBAE6D;;;IAH7D,AAJF,8HAA6B,wGAIpB;;;IAJT,kDAQC;;;IAIH,gCAA4B;IAAA,YAAuB;IAAA,iBAAO;;;IAA9B,cAAuB;IAAvB,mDAAuB;;;IASvD,+BAA4C;IAAA,YAAe;IAAA,iBAAM;;;IAArB,cAAe;IAAf,kCAAe;;;;IApD7D,mCAS0C;IAHxC,AADA,gOAAS,wBAAc,KAAC,mOACP,wBAAc,KAAC;IAKhC,+BAA2B;IAAA,YAAe;IAAA,iBAAM;IAChD,+BAA+B;IAC7B,wBAAuD;IAAC,YAC1D;IAAA,iBAAM;IAGJ,AADF,+BAA8B,eACE;IAG1B,AAFF,kHAA4B,gFAEnB;IAUT,wGAA4B;IAW9B,iBAAO;IACP,oHAAiC;IAGnC,iBAAM;IAGJ,AADF,gCAA2B,gBACI;IAAA,aAAwC;IAAA,iBAAO;IAC5E,iCAA6B;IAAA,aAAqF;;IACpH,AADoH,iBAAO,EACrH;IAEN,kGAA4C;IAC9C,iBAAU;;;;IAjDR,AADA,qCAAoB,kCACM;;IAOC,eAAe;IAAf,kCAAe;IAEgB,eAC1D;IAD0D,qDAC1D;IAII,eAIC;IAJD,iDAIC;IAQD,eAUC;IAVD,mDAUC;IAEH,cAEC;IAFD,wDAEC;IAI4B,eAAwC;IAAxC,2DAAwC;IACxC,eAAqF;IAArF,2HAAqF;;;IAS3F,iDAAgC;;;IAAU,+BAAc;;;IADnF,6BAAyB;IACoC,AAA3D,8GAAwB,wFAA0C;IACpE,iBAAI;;;IADF,cAAkF;IAAlF,6CAAkF;;;;IArItF,AADF,AALF,mCAGmC,iBAEJ,eACA;IACzB,YACA;IAAA,wGAAwB;IAiB1B,iBAAO;IAEL,AADF,gCAA2B,eACG;IAAA,YAAyB;IAAA,iBAAO;IAiB1D,AALF,2GAA4B,qFAKnB;IAQX,iBAAO;IACP,6GAA2B;IAgB7B,iBAAS;IAET,gCAOgD;IAA9C,wPAAsB,gCAAsB,KAAC;IAE7C,iJAuDC;IAED,0GAAiC;IAMrC,AADE,iBAAM,EACE;;;;IA7IR,sDAA0C;;IAKtC,eACA;IADA,gDACA;IAAA,cAgBC;IAhBD,8CAgBC;IAG2B,eAAyB;IAAzB,4CAAyB;IAYrD,cAYC;IAZD,iDAYC;IAEH,eAeC;IAfD,kDAeC;IAMD,cAA8B;IAG9B,AADA,AADA,AADA,+CAA8B,8BACJ,4CACU,4DACa;IAGjD,cAuDC;IAvDD,8BAuDC;IAED,eAIC;IAJD,wDAIC;;;;IAgBD,kCAA+D;IAAzB,sOAAS,wBAAc,KAAC;IAC5D,YACF;IAAA,iBAAS;;;IADP,cACF;IADE,6CACF;;;IARJ,AADF,mCAA6B,aACG;IAC5B,wBAA8D;IAC9D,YACF;IAAA,iBAAK;IACL,+BAA+B;IAC7B,oJAIC;IAEL,AADE,iBAAM,EACE;;;IATN,eACF;IADE,sEACF;IAEE,eAIC;IAJD,8BAIC;;;IAlKP,+BAAqB;IACnB,2IAiJC;IACH,iBAAM;IAEN,wGAA2B;;;IApJzB,cAiJC;IAjJD,6BAiJC;IAGH,eAgBC;IAhBD,qDAgBC;;ADrJL;;;;;;;GAOG;AACH,MAAM,UAAU,gBAAgB,CAAC,KAA+B;IAC5D,IAAI,KAAK,CAAC,MAAM,KAAK,CAAC,EAAE,CAAC;QACrB,OAAO,IAAI,CAAC;IAChB,CAAC;IACD,MAAM,QAAQ,GAAG,IAAI,GAAG,CAAC,KAAK,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,UAAU,IAAI,EAAE,CAAC,CAAC,CAAC;IAC/D,IAAI,QAAQ,CAAC,IAAI,GAAG,CAAC,EAAE,CAAC;QACpB,OAAO,IAAI,CAAC;IAChB,CAAC;IACD,MAAM,IAAI,GAAG,CAAC,GAAG,QAAQ,CAAC,CAAC,CAAC,CAAC,CAAC;IAC9B,OAAO,IAAI,KAAK,EAAE,CAAC,CAAC,CAAC,wBAAwB,CAAC,CAAC,CAAC,IAAI,CAAC;AACzD,CAAC;AAED;;;;;;GAMG;AACH,MAAM,CAAC,MAAM,wBAAwB,GAAG,KAAK,CAAC;AA8C9C,MAAM,OAAO,kBAAkB;IACV,OAAO,GAAG,MAAM,CAAC,oBAAoB,CAAC,CAAC;IACvC,GAAG,GAAG,MAAM,CAAC,iBAAiB,CAAC,CAAC;IAEjD,oGAAoG;IACpF,KAAK,GAAoB,EAAE,CAAC;IAC5B,SAAS,GAAqB,EAAE,CAAC;IACjC,MAAM,GAAkB,EAAE,CAAC;IAC3B,eAAe,GAAuB,EAAE,CAAC;IAEzD,2EAA2E;IACjD,UAAU,GAAG,IAAI,YAAY,EAAiB,CAAC;IACzE,0FAA0F;IAChE,UAAU,GAAG,IAAI,YAAY,EAAQ,CAAC;IAEzD,kBAAkB,GAAkB,IAAI,CAAC;IAChD,gGAAgG;IACzF,OAAO,GAAkB,IAAI,CAAC;IAC9B,MAAM,GAAG,KAAK,CAAC;IAEtB,wFAAwF;IACxF,IAAW,gBAAgB;QACvB,IAAI,IAAI,CAAC,kBAAkB,EAAE,CAAC;YAC1B,OAAO,IAAI,CAAC,kBAAkB,CAAC;QACnC,CAAC;QACD,MAAM,UAAU,GAAG,IAAI,CAAC,SAAS,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,IAAI,CAAC,MAAM,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,UAAU,KAAK,CAAC,CAAC,EAAE,CAAC,CAAC,CAAC;QAC9F,OAAO,UAAU,EAAE,EAAE,IAAI,IAAI,CAAC,SAAS,CAAC,CAAC,CAAC,EAAE,EAAE,IAAI,IAAI,CAAC;IAC3D,CAAC;IAED;;;;;;OAMG;IACH,IAAW,OAAO;QACd,MAAM,UAAU,GAAG,IAAI,CAAC,gBAAgB,CAAC;QACzC,IAAI,CAAC,UAAU,EAAE,CAAC;YACd,OAAO,EAAE,CAAC;QACd,CAAC;QAED,MAAM,OAAO,GAAG,IAAI,GAAG,CACnB,IAAI,CAAC,eAAe,CAAC,MAAM,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,SAAS,CAAC,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,EAAE,CAAC,CACnE,CAAC;QAEF,OAAO,IAAI,CAAC,MAAM,CAAC,MAAM,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,UAAU,KAAK,UAAU,CAAC;aACxD,KAAK,EAAE;aACP,IAAI,CAAC,CAAC,CAAC,EAAE,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,YAAY,GAAG,CAAC,CAAC,YAAY,CAAC;aAC/C,GAAG,CAAc,CAAC,KAAK,EAAE,EAAE;YACxB,MAAM,KAAK,GAAG,IAAI,CAAC,KAAK,CAAC,MAAM,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,eAAe,KAAK,KAAK,CAAC,EAAE,CAAC,CAAC;YACvE,OAAO;gBACH,OAAO,EAAE,KAAK,CAAC,EAAE;gBACjB,KAAK,EAAE,KAAK,CAAC,IAAI;gBACjB,SAAS,EAAE,CAAC,CAAC,KAAK,CAAC,gBAAgB,IAAI,OAAO,CAAC,GAAG,CAAC,KAAK,CAAC,gBAAgB,CAAC;gBAC1E,KAAK,EAAE,KAAK;gBACZ,qFAAqF;gBACrF;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;mBAmDG;gBACH,KAAK,EAAE,KAAK,CAAC,MAAM,CAAC,CAAC,GAAG,EAAE,CAAC,EAAE,EAAE,CAAC,GAAG,GAAG,CAAC,CAAC,CAAC,MAAM,IAAI,CAAC,CAAC,EAAE,CAAC,CAAC,EAAI,+OAA+O;gBAC5S,QAAQ,EAAE,gBAAgB,CAAC,KAAK,CAAC;gBACjC,aAAa,EAAE,gBAAgB,CAAC,KAAK,CAAC,KAAK,IAAI,IAAI,KAAK,CAAC,MAAM,GAAG,CAAC;uBAC5D,IAAI,GAAG,CAAC,KAAK,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,UAAU,IAAI,EAAE,CAAC,CAAC,CAAC,IAAI,GAAG,CAAC;gBAC7D;;;;mBAIG;gBACH,QAAQ,EAAE,KAAK,CAAC,MAAM,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,CAAC,gBAAgB,CAAC,CAAC,MAAM;gBACzD,UAAU,EAAE,KAAK,CAAC,MAAM,GAAG,CAAC,IAAI,KAAK,CAAC,KAAK,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,CAAC,gBAAgB,CAAC;aAC1E,CAAC;QACN,CAAC,CAAC,CAAC;IACX,CAAC;IAED,kGAAkG;IAClG,IAAW,QAAQ;QACf,MAAM,UAAU,GAAG,IAAI,CAAC,gBAAgB,CAAC;QACzC,OAAO,IAAI,CAAC,KAAK,CAAC,MAAM,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,UAAU,KAAK,UAAU,IAAI,CAAC,CAAC,CAAC,eAAe,CAAC,CAAC;IACvF,CAAC;IAED;;;;;;;;;;;;;;;;;OAiBG;IACH,IAAW,SAAS;QAChB,MAAM,GAAG,GAAG,IAAI,CAAC,OAAO,CAAC,GAAG,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,OAAO,CAAC,CAAC,OAAO,EAAE,CAAC,CAAC;QACxD,MAAM,GAAG,GAAG,GAAG,CAAC,IAAI,CAAC,GAAG,CAAC,CAAC;QAC1B,IAAI,GAAG,KAAK,IAAI,CAAC,aAAa,EAAE,CAAC;YAC7B,IAAI,CAAC,aAAa,GAAG,GAAG,CAAC;YACzB,IAAI,CAAC,UAAU,GAAG,GAAG,CAAC;QAC1B,CAAC;QACD,OAAO,IAAI,CAAC,UAAU,CAAC;IAC3B,CAAC;IAEO,aAAa,GAAG,GAAG,CAAC,CAAG,6DAA6D;IACpF,UAAU,GAAa,EAAE,CAAC;IAE3B,cAAc,CAAC,UAAkB;QACpC,IAAI,CAAC,kBAAkB,GAAG,UAAU,CAAC;QACrC,IAAI,CAAC,OAAO,GAAG,IAAI,CAAC;QACpB,IAAI,CAAC,GAAG,CAAC,aAAa,EAAE,CAAC;IAC7B,CAAC;IAEM,QAAQ,CAAC,IAAmB;QAC/B,IAAI,CAAC,UAAU,CAAC,IAAI,CAAC,IAAI,CAAC,CAAC;IAC/B,CAAC;IAED,+FAA+F;IACxF,WAAW,GAAG,CAAC,MAAmB,EAAE,EAAE,CAAC,GAAY,EAAE,CAAC,CAAC,MAAM,CAAC,SAAS,IAAI,CAAC,IAAI,CAAC,MAAM,CAAC;IAE/F;;;;;;;;OAQG;IACI,KAAK,CAAC,MAAM,CAAC,KAA+B,EAAE,MAAmB;QACpE,IAAI,CAAC,OAAO,GAAG,IAAI,CAAC;QAEpB,MAAM,IAAI,GAAG,KAAK,CAAC,IAAI,CAAC,IAAqB,CAAC;QAC9C,IAAI,CAAC,IAAI,EAAE,CAAC;YACR,OAAO;QACX,CAAC;QACD,IAAI,IAAI,CAAC,eAAe,KAAK,MAAM,CAAC,OAAO,EAAE,CAAC;YAC1C,OAAO;QACX,CAAC;QACD,IAAI,MAAM,CAAC,SAAS,EAAE,CAAC;YACnB,uFAAuF;YACvF,IAAI,CAAC,OAAO;gBACR,IAAI,MAAM,CAAC,KAAK,0EAA0E;oBAC1F,8CAA8C,CAAC;YACnD,IAAI,CAAC,GAAG,CAAC,aAAa,EAAE,CAAC;YACzB,OAAO;QACX,CAAC;QAED,IAAI,CAAC,MAAM,GAAG,IAAI,CAAC;QACnB,IAAI,CAAC,GAAG,CAAC,aAAa,EAAE,CAAC;QAEzB,IAAI,CAAC;YACD,MAAM,KAAK,GAAG,MAAM,IAAI,CAAC,OAAO,CAAC,QAAQ,CAAC,IAAI,CAAC,EAAE,CAAC,CAAC;YACnD,IAAI,CAAC,KAAK,EAAE,CAAC;gBACT,IAAI,CAAC,OAAO,GAAG,IAAI,IAAI,CAAC,IAAI,2CAA2C,CAAC;gBACxE,OAAO;YACX,CAAC;YAED,KAAK,CAAC,eAAe,GAAG,MAAM,CAAC,OAAO,CAAC;YAEvC,MAAM,OAAO,GAAG,MAAM,IAAI,CAAC,OAAO,CAAC,IAAI,CAAC,KAAK,CAAC,CAAC;YAC/C,IAAI,CAAC,OAAO,CAAC,OAAO,EAAE,CAAC;gBACnB,IAAI,CAAC,OAAO;oBACR,OAAO,CAAC,UAAU,EAAE,MAAM,CAAC,CAAC,CAAC,EAAE,OAAO;wBACtC,OAAO,CAAC,YAAY;wBACpB,IAAI,IAAI,CAAC,IAAI,uBAAuB,CAAC;gBACzC,OAAO;YACX,CAAC;YAED,4FAA4F;YAC5F,+BAA+B;YAC/B,IAAI,CAAC,eAAe,GAAG,MAAM,CAAC,OAAO,CAAC;YACtC,IAAI,CAAC,aAAa,GAAG,MAAM,CAAC,KAAK,CAAC;YAClC,IAAI,CAAC,UAAU,CAAC,IAAI,EAAE,CAAC;QAC3B,CAAC;QAAC,OAAO,GAAG,EAAE,CAAC;YACX,IAAI,CAAC,OAAO,GAAG,IAAI,IAAI,CAAC,IAAI,yBAAyB,GAAG,EAAE,CAAC;QAC/D,CAAC;gBAAS,CAAC;YACP,IAAI,CAAC,MAAM,GAAG,KAAK,CAAC;YACpB,IAAI,CAAC,GAAG,CAAC,aAAa,EAAE,CAAC;QAC7B,CAAC;IACL,CAAC;IAED;;;;;;;;;;;;;;OAcG;IAEI,MAAM,CAAC,UAAyB;QACnC,OAAO,IAAI,CAAC,SAAS,CAAC,IAAI,CAAC,CAAC,CAAC,EAAE,EAAE,CAAC,CAAC,CAAC,EAAE,KAAK,UAAU,CAAC,EAAE,IAAI,IAAI,GAAG,CAAC;IACxE,CAAC;IAED,gEAAgE;IACzD,SAAS,GAAG,CAAC,CAAS,EAAE,IAAmB,EAAU,EAAE,CAAC,IAAI,CAAC,EAAE,CAAC;IACvE,kFAAkF;IAClE,eAAe,GAAG,wBAAwB,CAAC;IAC3D;;;;;OAKG;IACI,WAAW,CAAC,MAAmB;QAClC,OAAO,MAAM,CAAC,UAAU;YACpB,CAAC,CAAC,yFAAyF;kBACrF,wBAAwB;YAC9B,CAAC,CAAC,GAAG,MAAM,CAAC,QAAQ,OAAO,MAAM,CAAC,KAAK,CAAC,MAAM,8CAA8C;kBACtF,6DAA6D,CAAC;IAC5E,CAAC;IAEM,WAAW,GAAG,CAAC,CAAS,EAAE,MAAmB,EAAU,EAAE,CAAC,MAAM,CAAC,OAAO,CAAC;4GAlRvE,kBAAkB;6DAAlB,kBAAkB;YCrH3B,AADF,AAHF,8BAAgB,aAGM,cACU;YAAA,wBAAQ;YAAA,iBAAO;YAC3C,8BAAgE;YAC9D,wFAUC;YACH,iBAAM;YACN,qFAAc;YAGhB,iBAAM;YAEN,kFAAe;YAQb,AAFF,kFAA4B,sDAEnB;YAwKX,iBAAM;;YAjMA,eAUC;YAVD,4BAUC;YAEH,eAEC;YAFD,qCAEC;YAGH,cAIC;YAJD,sCAIC;YAED,cAyKC;YAzKD,mDAyKC;4BDjFW,YAAY,EAAE,WAAW,EAAE,OAAO;;iFAInC,kBAAkB;cAP9B,SAAS;2BACI,gBAAgB,cACd,IAAI,WACP,CAAC,YAAY,EAAE,WAAW,EAAE,OAAO,CAAC;;kBAS5C,KAAK;;kBACL,KAAK;;kBACL,KAAK;;kBACL,KAAK;;kBAGL,MAAM;;kBAEN,MAAM;;kFAbE,kBAAkB"}
@@ -0,0 +1,66 @@
1
+ /**
2
+ * @fileoverview Supplying `Deal.CompanyID` on a new deal, so the form can be saved at all.
3
+ *
4
+ * ── THE DEFECT THIS EXISTS FOR ──────────────────────────────────────────────────────────────────
5
+ *
6
+ * A new deal could not be saved through the form. `Deal.CompanyID` is `NOT NULL` with no default, the
7
+ * form renders it as a server-maintained field (correctly — a rep must not choose the selling company),
8
+ * and `DealEntityServer.stampCompanyFromPipeline()` fills it on save. But `BaseFormComponent.SaveRecord`
9
+ * runs `Validate()` FIRST and returns early when it fails, so the save never reached the server that was
10
+ * going to supply the value. Required, unsettable, and filled too late: the record was unsaveable.
11
+ *
12
+ * It worked in the deal workspace because `SelectPipeline` stamped it client-side — "so the record
13
+ * validates locally", in its own words. Unmounting the workspace (9d6ef9e) took the only code that did
14
+ * this with it, and the form was never given the equivalent. That is the whole bug.
15
+ *
16
+ * ── WHY THE CLIENT MAY WRITE A SERVER-OWNED FIELD HERE, WHICH LOOKS WRONG ───────────────────────
17
+ *
18
+ * It is not the client DECIDING the selling company. It is the client pre-filling the answer the server
19
+ * is about to write, read from the SAME authority the server reads — the pipeline. `stampCompanyFromPipeline`
20
+ * overwrites whatever arrives, so the two cannot disagree: if this stamps the wrong value the server
21
+ * replaces it, and if it stamps the right one the server writes it again. The pipeline remains the only
22
+ * thing that can be correct about which company is selling.
23
+ *
24
+ * That is also why this does not make `CompanyID` editable. `deal-form.panels.ts` keeps it
25
+ * `serverMaintained: true` and `server-owned-fields.ts` refuses a user's edit to it. Those stay exactly
26
+ * as they were — what changes is that the value now arrives without a user having to supply one.
27
+ *
28
+ * ── KEYED ON THE CAUSE, NOT ON `IsSaved` ────────────────────────────────────────────────────────
29
+ *
30
+ * The obvious guard is "new deals only". The cause is not newness, it is an ABSENT CompanyID with a
31
+ * pipeline available to resolve it — so that is what is tested. A saved deal always has one (the column
32
+ * is NOT NULL), so the extra breadth costs nothing today and survives a path that creates a deal some
33
+ * other way tomorrow. A guard keyed on a threshold gets outgrown; one keyed on a cause does not.
34
+ *
35
+ * @module @mj-biz-apps/sales-ng
36
+ */
37
+ /**
38
+ * The one column read off a pipeline. CodeGen generates no `PipelineEntity` subclass, and this only
39
+ * ever reads — so the view runs `ResultType: 'simple'` and the row is typed here rather than borrowed.
40
+ */
41
+ export interface PipelineCompanyRow {
42
+ CompanyID: string | null;
43
+ }
44
+ /** What the decision needs to know. Kept flat so it can be tested without an entity or a DOM. */
45
+ export interface CompanyStampState {
46
+ /** True when the form actually holds a record. */
47
+ HasRecord: boolean;
48
+ /** The pipeline the deal is in, as currently chosen. */
49
+ PipelineID: string | null;
50
+ /** The company currently on the deal, if any. */
51
+ CompanyID: string | null;
52
+ }
53
+ /**
54
+ * Whether `CompanyID` should be resolved from the pipeline and stamped.
55
+ *
56
+ * Pure and exported so the rule can be pinned without a database. Each clause is a way the stamp would
57
+ * be wrong:
58
+ *
59
+ * - no record, nothing to stamp;
60
+ * - no pipeline chosen yet, so there is no authority to read the company FROM — the rep has not made
61
+ * the choice that decides it, and inventing one would be the client deciding after all;
62
+ * - a company already present is left alone. On a saved deal that is the stored value, and overwriting
63
+ * it here would make this code an authority it is explicitly not.
64
+ */
65
+ export declare function ShouldStampCompanyFromPipeline(state: CompanyStampState): boolean;
66
+ //# sourceMappingURL=company-from-pipeline.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"company-from-pipeline.d.ts","sourceRoot":"","sources":["../../../src/lib/custom/company-from-pipeline.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAmCG;AAEH;;;GAGG;AACH,MAAM,WAAW,kBAAkB;IAC/B,SAAS,EAAE,MAAM,GAAG,IAAI,CAAC;CAC5B;AAED,iGAAiG;AACjG,MAAM,WAAW,iBAAiB;IAC9B,kDAAkD;IAClD,SAAS,EAAE,OAAO,CAAC;IACnB,wDAAwD;IACxD,UAAU,EAAE,MAAM,GAAG,IAAI,CAAC;IAC1B,iDAAiD;IACjD,SAAS,EAAE,MAAM,GAAG,IAAI,CAAC;CAC5B;AAED;;;;;;;;;;;GAWG;AACH,wBAAgB,8BAA8B,CAAC,KAAK,EAAE,iBAAiB,GAAG,OAAO,CAQhF"}
@@ -0,0 +1,67 @@
1
+ /**
2
+ * @fileoverview Supplying `Deal.CompanyID` on a new deal, so the form can be saved at all.
3
+ *
4
+ * ── THE DEFECT THIS EXISTS FOR ──────────────────────────────────────────────────────────────────
5
+ *
6
+ * A new deal could not be saved through the form. `Deal.CompanyID` is `NOT NULL` with no default, the
7
+ * form renders it as a server-maintained field (correctly — a rep must not choose the selling company),
8
+ * and `DealEntityServer.stampCompanyFromPipeline()` fills it on save. But `BaseFormComponent.SaveRecord`
9
+ * runs `Validate()` FIRST and returns early when it fails, so the save never reached the server that was
10
+ * going to supply the value. Required, unsettable, and filled too late: the record was unsaveable.
11
+ *
12
+ * It worked in the deal workspace because `SelectPipeline` stamped it client-side — "so the record
13
+ * validates locally", in its own words. Unmounting the workspace (9d6ef9e) took the only code that did
14
+ * this with it, and the form was never given the equivalent. That is the whole bug.
15
+ *
16
+ * ── WHY THE CLIENT MAY WRITE A SERVER-OWNED FIELD HERE, WHICH LOOKS WRONG ───────────────────────
17
+ *
18
+ * It is not the client DECIDING the selling company. It is the client pre-filling the answer the server
19
+ * is about to write, read from the SAME authority the server reads — the pipeline. `stampCompanyFromPipeline`
20
+ * overwrites whatever arrives, so the two cannot disagree: if this stamps the wrong value the server
21
+ * replaces it, and if it stamps the right one the server writes it again. The pipeline remains the only
22
+ * thing that can be correct about which company is selling.
23
+ *
24
+ * That is also why this does not make `CompanyID` editable. `deal-form.panels.ts` keeps it
25
+ * `serverMaintained: true` and `server-owned-fields.ts` refuses a user's edit to it. Those stay exactly
26
+ * as they were — what changes is that the value now arrives without a user having to supply one.
27
+ *
28
+ * ── KEYED ON THE CAUSE, NOT ON `IsSaved` ────────────────────────────────────────────────────────
29
+ *
30
+ * The obvious guard is "new deals only". The cause is not newness, it is an ABSENT CompanyID with a
31
+ * pipeline available to resolve it — so that is what is tested. A saved deal always has one (the column
32
+ * is NOT NULL), so the extra breadth costs nothing today and survives a path that creates a deal some
33
+ * other way tomorrow. A guard keyed on a threshold gets outgrown; one keyed on a cause does not.
34
+ *
35
+ * @module @mj-biz-apps/sales-ng
36
+ */
37
+ /**
38
+ * Whether `CompanyID` should be resolved from the pipeline and stamped.
39
+ *
40
+ * Pure and exported so the rule can be pinned without a database. Each clause is a way the stamp would
41
+ * be wrong:
42
+ *
43
+ * - no record, nothing to stamp;
44
+ * - no pipeline chosen yet, so there is no authority to read the company FROM — the rep has not made
45
+ * the choice that decides it, and inventing one would be the client deciding after all;
46
+ * - a company already present is left alone. On a saved deal that is the stored value, and overwriting
47
+ * it here would make this code an authority it is explicitly not.
48
+ */
49
+ export function ShouldStampCompanyFromPipeline(state) {
50
+ if (!state.HasRecord) {
51
+ return false;
52
+ }
53
+ if (!isSet(state.PipelineID)) {
54
+ return false;
55
+ }
56
+ return !isSet(state.CompanyID);
57
+ }
58
+ /**
59
+ * A GUID field counts as absent when it is null, undefined, or blank.
60
+ *
61
+ * The empty string matters: a picker that has been opened and cleared leaves `''`, not null, and a
62
+ * truthiness test alone would have treated `' '` as a real company id.
63
+ */
64
+ function isSet(value) {
65
+ return typeof value === 'string' && value.trim().length > 0;
66
+ }
67
+ //# sourceMappingURL=company-from-pipeline.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"company-from-pipeline.js","sourceRoot":"","sources":["../../../src/lib/custom/company-from-pipeline.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;GAmCG;AAoBH;;;;;;;;;;;GAWG;AACH,MAAM,UAAU,8BAA8B,CAAC,KAAwB;IACnE,IAAI,CAAC,KAAK,CAAC,SAAS,EAAE,CAAC;QACnB,OAAO,KAAK,CAAC;IACjB,CAAC;IACD,IAAI,CAAC,KAAK,CAAC,KAAK,CAAC,UAAU,CAAC,EAAE,CAAC;QAC3B,OAAO,KAAK,CAAC;IACjB,CAAC;IACD,OAAO,CAAC,KAAK,CAAC,KAAK,CAAC,SAAS,CAAC,CAAC;AACnC,CAAC;AAED;;;;;GAKG;AACH,SAAS,KAAK,CAAC,KAAgC;IAC3C,OAAO,OAAO,KAAK,KAAK,QAAQ,IAAI,KAAK,CAAC,IAAI,EAAE,CAAC,MAAM,GAAG,CAAC,CAAC;AAChE,CAAC"}
@@ -5,9 +5,25 @@ import * as i0 from "@angular/core";
5
5
  export declare class DealFormComponentExtended extends mjBizAppsSalesDealFormComponent {
6
6
  /** True when the PERSISTED status locks the deal. Resolved once per load. */
7
7
  IsLocked: boolean;
8
+ /**
9
+ * Whether the locking status is a LOSS — which decides exactly one field.
10
+ *
11
+ * golive#206 keeps Loss Notes editable on a lost deal and frozen on a won one. Resolved once, with
12
+ * the lock, by `ResolveDealLockState`, and handed to the panels; nothing here reads a status name.
13
+ */
14
+ IsLost: boolean;
15
+ /**
16
+ * Whether the PERSISTED status is a WIN — read as its own flag, never inferred from `!IsLost`.
17
+ *
18
+ * golive#226: the Order and Contract chips belong on a won deal and on no other, because an open
19
+ * deal's order is still a draft nobody should be editing directly. golive#231's outcome tiles read
20
+ * the same flag. Resolved with the lock, from the same status row; the panels read it here rather
21
+ * than asking again.
22
+ */
23
+ IsWon: boolean;
8
24
  /** Shown when locked, so the greyed-out-ness the form cannot render is at least explained. */
9
25
  LockNotice: string | null;
10
- /** Set when `Deal.Amount` predates its line set. Null when the amount is trustworthy or absent. */
26
+ /** Set when `Deal.Amount` no longer matches its order's total. Null when trustworthy, absent or locked. */
11
27
  StaleAmountNotice: string | null;
12
28
  ngOnInit(): Promise<void>;
13
29
  /** The fields a user may still edit right now — everything when open, the carve-outs when locked. */
@@ -20,9 +36,34 @@ export declare class DealFormComponentExtended extends mjBizAppsSalesDealFormCom
20
36
  */
21
37
  private resolveCloseLock;
22
38
  /**
23
- * Compares the amount's stamp against the lines it claims to describe. No arithmetic.
39
+ * Compares the cached amount against the order it claims to describe. No arithmetic.
40
+ *
41
+ * The rule lives in `ResolveDealAmountFreshness` so this form and the deal hero cannot answer it
42
+ * differently — the same reason `ResolveDealLockState` is shared. Read that file's header for why
43
+ * this is no longer a timestamp comparison (golive#230).
44
+ *
45
+ * ORDER MATTERS: `resolveCloseLock()` runs first in `ngOnInit`, so `IsLocked` is settled before it
46
+ * is passed here. A locked deal never warns.
24
47
  */
25
48
  private resolveAmountFreshness;
49
+ /**
50
+ * Fills the selling company from the pipeline before the save is validated.
51
+ *
52
+ * WHY IT IS HERE AND NOT IN `Validate()`. `SaveRecord` calls `Validate()` and returns early when it
53
+ * fails, so a stamp applied inside validation would be racing the thing it exists to satisfy. This
54
+ * runs before `super.SaveRecord()` — which is what puts it ahead of the validator.
55
+ *
56
+ * `company-from-pipeline.ts` holds the decision and the reasoning, including why the client is
57
+ * allowed to write a server-owned field at all. This method owns only the lookup.
58
+ *
59
+ * A pipeline that cannot be read is NOT an error here. The stamp is best-effort: if it fails, the
60
+ * save proceeds and validation refuses exactly as it did before, which is the behaviour this is
61
+ * replacing rather than something it makes worse. Swallowing a real problem is the risk, so the
62
+ * refusal the user then sees still names `CompanyID`.
63
+ */
64
+ SaveRecord(StopEditModeAfterSave: boolean): Promise<boolean>;
65
+ /** Reads the chosen pipeline's company and writes it to the deal. See `SaveRecord` for why. */
66
+ private stampCompanyFromPipeline;
26
67
  /**
27
68
  * Refuses a locked edit BEFORE the round trip, naming the fields.
28
69
  *
@@ -1 +1 @@
1
- {"version":3,"file":"deal-form.component.d.ts","sourceRoot":"","sources":["../../../src/lib/custom/deal-form.component.ts"],"names":[],"mappings":"AAqCA,OAAO,KAAK,EAAE,gBAAgB,EAAE,MAAM,sBAAsB,CAAC;AAE7D,OAAO,EAAE,+BAA+B,EAAE,MAAM,4EAA4E,CAAC;;AAM7H,0GAA0G;AAC1G,qBAMa,yBAA0B,SAAQ,+BAA+B;IAC1E,6EAA6E;IACtE,QAAQ,UAAS;IAExB,8FAA8F;IACvF,UAAU,EAAE,MAAM,GAAG,IAAI,CAAQ;IAExC,mGAAmG;IAC5F,iBAAiB,EAAE,MAAM,GAAG,IAAI,CAAQ;IAEzB,QAAQ,IAAI,OAAO,CAAC,IAAI,CAAC;IAO/C,qGAAqG;IAC9F,kBAAkB,IAAI,SAAS,MAAM,EAAE,GAAG,IAAI;IAIrD;;;;;OAKG;YACW,gBAAgB;IAO9B;;OAEG;YACW,sBAAsB;IA2CpC;;;;;OAKG;IACa,QAAQ,IAAI,gBAAgB;yCAvFnC,yBAAyB;2CAAzB,yBAAyB;CAiHrC;AAED,gCAAgC;AAChC,wBAAgB,YAAY,IAAI,IAAI,CAEnC"}
1
+ {"version":3,"file":"deal-form.component.d.ts","sourceRoot":"","sources":["../../../src/lib/custom/deal-form.component.ts"],"names":[],"mappings":"AA6CA,OAAO,KAAK,EAAE,gBAAgB,EAAE,MAAM,sBAAsB,CAAC;AAG7D,OAAO,EAAE,+BAA+B,EAAE,MAAM,4EAA4E,CAAC;;AAI7H,0GAA0G;AAC1G,qBAMa,yBAA0B,SAAQ,+BAA+B;IAC1E,6EAA6E;IACtE,QAAQ,UAAS;IAExB;;;;;OAKG;IACI,MAAM,UAAS;IAEtB;;;;;;;OAOG;IACI,KAAK,UAAS;IAErB,8FAA8F;IACvF,UAAU,EAAE,MAAM,GAAG,IAAI,CAAQ;IAExC,2GAA2G;IACpG,iBAAiB,EAAE,MAAM,GAAG,IAAI,CAAQ;IAEzB,QAAQ,IAAI,OAAO,CAAC,IAAI,CAAC;IAO/C,qGAAqG;IAC9F,kBAAkB,IAAI,SAAS,MAAM,EAAE,GAAG,IAAI;IAIrD;;;;;OAKG;YACW,gBAAgB;IAS9B;;;;;;;;;OASG;YACW,sBAAsB;IAepC;;;;;;;;;;;;;;OAcG;IACmB,UAAU,CAAC,qBAAqB,EAAE,OAAO,GAAG,OAAO,CAAC,OAAO,CAAC;IAKlF,+FAA+F;YACjF,wBAAwB;IAiCtC;;;;;OAKG;IACa,QAAQ,IAAI,gBAAgB;yCA5InC,yBAAyB;2CAAzB,yBAAyB;CA6KrC;AAED,gCAAgC;AAChC,wBAAgB,YAAY,IAAI,IAAI,CAEnC"}