@mj-biz-apps/sales-ng 5.1.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (182) hide show
  1. package/LICENSE +183 -0
  2. package/dist/lib/activities/deal-activity-timeline.component.d.ts +104 -0
  3. package/dist/lib/activities/deal-activity-timeline.component.d.ts.map +1 -0
  4. package/dist/lib/activities/deal-activity-timeline.component.js +580 -0
  5. package/dist/lib/activities/deal-activity-timeline.component.js.map +1 -0
  6. package/dist/lib/board/deal-board.component.d.ts +194 -0
  7. package/dist/lib/board/deal-board.component.d.ts.map +1 -0
  8. package/dist/lib/board/deal-board.component.js +626 -0
  9. package/dist/lib/board/deal-board.component.js.map +1 -0
  10. package/dist/lib/custom/custom-forms.module.d.ts +14 -0
  11. package/dist/lib/custom/custom-forms.module.d.ts.map +1 -0
  12. package/dist/lib/custom/custom-forms.module.js +38 -0
  13. package/dist/lib/custom/custom-forms.module.js.map +1 -0
  14. package/dist/lib/custom/deal-form.component.d.ts +38 -0
  15. package/dist/lib/custom/deal-form.component.d.ts.map +1 -0
  16. package/dist/lib/custom/deal-form.component.js +346 -0
  17. package/dist/lib/custom/deal-form.component.js.map +1 -0
  18. package/dist/lib/custom/deal-line-form.component.d.ts +22 -0
  19. package/dist/lib/custom/deal-line-form.component.d.ts.map +1 -0
  20. package/dist/lib/custom/deal-line-form.component.js +129 -0
  21. package/dist/lib/custom/deal-line-form.component.js.map +1 -0
  22. package/dist/lib/custom/deal-stage-event-form.component.d.ts +26 -0
  23. package/dist/lib/custom/deal-stage-event-form.component.d.ts.map +1 -0
  24. package/dist/lib/custom/deal-stage-event-form.component.js +112 -0
  25. package/dist/lib/custom/deal-stage-event-form.component.js.map +1 -0
  26. package/dist/lib/custom/server-owned-fields.d.ts +47 -0
  27. package/dist/lib/custom/server-owned-fields.d.ts.map +1 -0
  28. package/dist/lib/custom/server-owned-fields.js +31 -0
  29. package/dist/lib/custom/server-owned-fields.js.map +1 -0
  30. package/dist/lib/generated/Entities/mjBizAppsSalesAccountType/mjbizappssalesaccounttype.form.component.d.ts +10 -0
  31. package/dist/lib/generated/Entities/mjBizAppsSalesAccountType/mjbizappssalesaccounttype.form.component.d.ts.map +1 -0
  32. package/dist/lib/generated/Entities/mjBizAppsSalesAccountType/mjbizappssalesaccounttype.form.component.js +90 -0
  33. package/dist/lib/generated/Entities/mjBizAppsSalesAccountType/mjbizappssalesaccounttype.form.component.js.map +1 -0
  34. package/dist/lib/generated/Entities/mjBizAppsSalesBuyingRoleType/mjbizappssalesbuyingroletype.form.component.d.ts +10 -0
  35. package/dist/lib/generated/Entities/mjBizAppsSalesBuyingRoleType/mjbizappssalesbuyingroletype.form.component.d.ts.map +1 -0
  36. package/dist/lib/generated/Entities/mjBizAppsSalesBuyingRoleType/mjbizappssalesbuyingroletype.form.component.js +108 -0
  37. package/dist/lib/generated/Entities/mjBizAppsSalesBuyingRoleType/mjbizappssalesbuyingroletype.form.component.js.map +1 -0
  38. package/dist/lib/generated/Entities/mjBizAppsSalesDeal/mjbizappssalesdeal.form.component.d.ts +10 -0
  39. package/dist/lib/generated/Entities/mjBizAppsSalesDeal/mjbizappssalesdeal.form.component.d.ts.map +1 -0
  40. package/dist/lib/generated/Entities/mjBizAppsSalesDeal/mjbizappssalesdeal.form.component.js +216 -0
  41. package/dist/lib/generated/Entities/mjBizAppsSalesDeal/mjbizappssalesdeal.form.component.js.map +1 -0
  42. package/dist/lib/generated/Entities/mjBizAppsSalesDealContactRole/mjbizappssalesdealcontactrole.form.component.d.ts +10 -0
  43. package/dist/lib/generated/Entities/mjBizAppsSalesDealContactRole/mjbizappssalesdealcontactrole.form.component.d.ts.map +1 -0
  44. package/dist/lib/generated/Entities/mjBizAppsSalesDealContactRole/mjbizappssalesdealcontactrole.form.component.js +65 -0
  45. package/dist/lib/generated/Entities/mjBizAppsSalesDealContactRole/mjbizappssalesdealcontactrole.form.component.js.map +1 -0
  46. package/dist/lib/generated/Entities/mjBizAppsSalesDealLine/mjbizappssalesdealline.form.component.d.ts +10 -0
  47. package/dist/lib/generated/Entities/mjBizAppsSalesDealLine/mjbizappssalesdealline.form.component.d.ts.map +1 -0
  48. package/dist/lib/generated/Entities/mjBizAppsSalesDealLine/mjbizappssalesdealline.form.component.js +95 -0
  49. package/dist/lib/generated/Entities/mjBizAppsSalesDealLine/mjbizappssalesdealline.form.component.js.map +1 -0
  50. package/dist/lib/generated/Entities/mjBizAppsSalesDealLineType/mjbizappssalesdeallinetype.form.component.d.ts +10 -0
  51. package/dist/lib/generated/Entities/mjBizAppsSalesDealLineType/mjbizappssalesdeallinetype.form.component.d.ts.map +1 -0
  52. package/dist/lib/generated/Entities/mjBizAppsSalesDealLineType/mjbizappssalesdeallinetype.form.component.js +86 -0
  53. package/dist/lib/generated/Entities/mjBizAppsSalesDealLineType/mjbizappssalesdeallinetype.form.component.js.map +1 -0
  54. package/dist/lib/generated/Entities/mjBizAppsSalesDealPaymentSchedule/mjbizappssalesdealpaymentschedule.form.component.d.ts +10 -0
  55. package/dist/lib/generated/Entities/mjBizAppsSalesDealPaymentSchedule/mjbizappssalesdealpaymentschedule.form.component.d.ts.map +1 -0
  56. package/dist/lib/generated/Entities/mjBizAppsSalesDealPaymentSchedule/mjbizappssalesdealpaymentschedule.form.component.js +65 -0
  57. package/dist/lib/generated/Entities/mjBizAppsSalesDealPaymentSchedule/mjbizappssalesdealpaymentschedule.form.component.js.map +1 -0
  58. package/dist/lib/generated/Entities/mjBizAppsSalesDealRole/mjbizappssalesdealrole.form.component.d.ts +10 -0
  59. package/dist/lib/generated/Entities/mjBizAppsSalesDealRole/mjbizappssalesdealrole.form.component.d.ts.map +1 -0
  60. package/dist/lib/generated/Entities/mjBizAppsSalesDealRole/mjbizappssalesdealrole.form.component.js +92 -0
  61. package/dist/lib/generated/Entities/mjBizAppsSalesDealRole/mjbizappssalesdealrole.form.component.js.map +1 -0
  62. package/dist/lib/generated/Entities/mjBizAppsSalesDealSequence/mjbizappssalesdealsequence.form.component.d.ts +10 -0
  63. package/dist/lib/generated/Entities/mjBizAppsSalesDealSequence/mjbizappssalesdealsequence.form.component.d.ts.map +1 -0
  64. package/dist/lib/generated/Entities/mjBizAppsSalesDealSequence/mjbizappssalesdealsequence.form.component.js +57 -0
  65. package/dist/lib/generated/Entities/mjBizAppsSalesDealSequence/mjbizappssalesdealsequence.form.component.js.map +1 -0
  66. package/dist/lib/generated/Entities/mjBizAppsSalesDealStageEvent/mjbizappssalesdealstageevent.form.component.d.ts +10 -0
  67. package/dist/lib/generated/Entities/mjBizAppsSalesDealStageEvent/mjbizappssalesdealstageevent.form.component.d.ts.map +1 -0
  68. package/dist/lib/generated/Entities/mjBizAppsSalesDealStageEvent/mjbizappssalesdealstageevent.form.component.js +77 -0
  69. package/dist/lib/generated/Entities/mjBizAppsSalesDealStageEvent/mjbizappssalesdealstageevent.form.component.js.map +1 -0
  70. package/dist/lib/generated/Entities/mjBizAppsSalesDealStatusType/mjbizappssalesdealstatustype.form.component.d.ts +10 -0
  71. package/dist/lib/generated/Entities/mjBizAppsSalesDealStatusType/mjbizappssalesdealstatustype.form.component.d.ts.map +1 -0
  72. package/dist/lib/generated/Entities/mjBizAppsSalesDealStatusType/mjbizappssalesdealstatustype.form.component.js +148 -0
  73. package/dist/lib/generated/Entities/mjBizAppsSalesDealStatusType/mjbizappssalesdealstatustype.form.component.js.map +1 -0
  74. package/dist/lib/generated/Entities/mjBizAppsSalesDealTeamMember/mjbizappssalesdealteammember.form.component.d.ts +10 -0
  75. package/dist/lib/generated/Entities/mjBizAppsSalesDealTeamMember/mjbizappssalesdealteammember.form.component.d.ts.map +1 -0
  76. package/dist/lib/generated/Entities/mjBizAppsSalesDealTeamMember/mjbizappssalesdealteammember.form.component.js +73 -0
  77. package/dist/lib/generated/Entities/mjBizAppsSalesDealTeamMember/mjbizappssalesdealteammember.form.component.js.map +1 -0
  78. package/dist/lib/generated/Entities/mjBizAppsSalesDealType/mjbizappssalesdealtype.form.component.d.ts +10 -0
  79. package/dist/lib/generated/Entities/mjBizAppsSalesDealType/mjbizappssalesdealtype.form.component.d.ts.map +1 -0
  80. package/dist/lib/generated/Entities/mjBizAppsSalesDealType/mjbizappssalesdealtype.form.component.js +108 -0
  81. package/dist/lib/generated/Entities/mjBizAppsSalesDealType/mjbizappssalesdealtype.form.component.js.map +1 -0
  82. package/dist/lib/generated/Entities/mjBizAppsSalesForecastCategoryType/mjbizappssalesforecastcategorytype.form.component.d.ts +10 -0
  83. package/dist/lib/generated/Entities/mjBizAppsSalesForecastCategoryType/mjbizappssalesforecastcategorytype.form.component.d.ts.map +1 -0
  84. package/dist/lib/generated/Entities/mjBizAppsSalesForecastCategoryType/mjbizappssalesforecastcategorytype.form.component.js +126 -0
  85. package/dist/lib/generated/Entities/mjBizAppsSalesForecastCategoryType/mjbizappssalesforecastcategorytype.form.component.js.map +1 -0
  86. package/dist/lib/generated/Entities/mjBizAppsSalesForecastSnapshot/mjbizappssalesforecastsnapshot.form.component.d.ts +10 -0
  87. package/dist/lib/generated/Entities/mjBizAppsSalesForecastSnapshot/mjbizappssalesforecastsnapshot.form.component.d.ts.map +1 -0
  88. package/dist/lib/generated/Entities/mjBizAppsSalesForecastSnapshot/mjbizappssalesforecastsnapshot.form.component.js +77 -0
  89. package/dist/lib/generated/Entities/mjBizAppsSalesForecastSnapshot/mjbizappssalesforecastsnapshot.form.component.js.map +1 -0
  90. package/dist/lib/generated/Entities/mjBizAppsSalesLeadSourceType/mjbizappssalesleadsourcetype.form.component.d.ts +10 -0
  91. package/dist/lib/generated/Entities/mjBizAppsSalesLeadSourceType/mjbizappssalesleadsourcetype.form.component.d.ts.map +1 -0
  92. package/dist/lib/generated/Entities/mjBizAppsSalesLeadSourceType/mjbizappssalesleadsourcetype.form.component.js +126 -0
  93. package/dist/lib/generated/Entities/mjBizAppsSalesLeadSourceType/mjbizappssalesleadsourcetype.form.component.js.map +1 -0
  94. package/dist/lib/generated/Entities/mjBizAppsSalesLifecycleStageType/mjbizappssaleslifecyclestagetype.form.component.d.ts +10 -0
  95. package/dist/lib/generated/Entities/mjBizAppsSalesLifecycleStageType/mjbizappssaleslifecyclestagetype.form.component.d.ts.map +1 -0
  96. package/dist/lib/generated/Entities/mjBizAppsSalesLifecycleStageType/mjbizappssaleslifecyclestagetype.form.component.js +108 -0
  97. package/dist/lib/generated/Entities/mjBizAppsSalesLifecycleStageType/mjbizappssaleslifecyclestagetype.form.component.js.map +1 -0
  98. package/dist/lib/generated/Entities/mjBizAppsSalesLossReason/mjbizappssaleslossreason.form.component.d.ts +10 -0
  99. package/dist/lib/generated/Entities/mjBizAppsSalesLossReason/mjbizappssaleslossreason.form.component.d.ts.map +1 -0
  100. package/dist/lib/generated/Entities/mjBizAppsSalesLossReason/mjbizappssaleslossreason.form.component.js +90 -0
  101. package/dist/lib/generated/Entities/mjBizAppsSalesLossReason/mjbizappssaleslossreason.form.component.js.map +1 -0
  102. package/dist/lib/generated/Entities/mjBizAppsSalesPipeline/mjbizappssalespipeline.form.component.d.ts +10 -0
  103. package/dist/lib/generated/Entities/mjBizAppsSalesPipeline/mjbizappssalespipeline.form.component.d.ts.map +1 -0
  104. package/dist/lib/generated/Entities/mjBizAppsSalesPipeline/mjbizappssalespipeline.form.component.js +150 -0
  105. package/dist/lib/generated/Entities/mjBizAppsSalesPipeline/mjbizappssalespipeline.form.component.js.map +1 -0
  106. package/dist/lib/generated/Entities/mjBizAppsSalesPipelineStage/mjbizappssalespipelinestage.form.component.d.ts +10 -0
  107. package/dist/lib/generated/Entities/mjBizAppsSalesPipelineStage/mjbizappssalespipelinestage.form.component.d.ts.map +1 -0
  108. package/dist/lib/generated/Entities/mjBizAppsSalesPipelineStage/mjbizappssalespipelinestage.form.component.js +138 -0
  109. package/dist/lib/generated/Entities/mjBizAppsSalesPipelineStage/mjbizappssalespipelinestage.form.component.js.map +1 -0
  110. package/dist/lib/generated/Entities/mjBizAppsSalesSalesAccount/mjbizappssalessalesaccount.form.component.d.ts +10 -0
  111. package/dist/lib/generated/Entities/mjBizAppsSalesSalesAccount/mjbizappssalessalesaccount.form.component.d.ts.map +1 -0
  112. package/dist/lib/generated/Entities/mjBizAppsSalesSalesAccount/mjbizappssalessalesaccount.form.component.js +124 -0
  113. package/dist/lib/generated/Entities/mjBizAppsSalesSalesAccount/mjbizappssalessalesaccount.form.component.js.map +1 -0
  114. package/dist/lib/generated/Entities/mjBizAppsSalesSalesContact/mjbizappssalessalescontact.form.component.d.ts +10 -0
  115. package/dist/lib/generated/Entities/mjBizAppsSalesSalesContact/mjbizappssalessalescontact.form.component.d.ts.map +1 -0
  116. package/dist/lib/generated/Entities/mjBizAppsSalesSalesContact/mjbizappssalessalescontact.form.component.js +156 -0
  117. package/dist/lib/generated/Entities/mjBizAppsSalesSalesContact/mjbizappssalessalescontact.form.component.js.map +1 -0
  118. package/dist/lib/generated/class-registrations-manifest.d.ts +20 -0
  119. package/dist/lib/generated/class-registrations-manifest.d.ts.map +1 -0
  120. package/dist/lib/generated/class-registrations-manifest.js +20 -0
  121. package/dist/lib/generated/class-registrations-manifest.js.map +1 -0
  122. package/dist/lib/generated/generated-forms.module.d.ts +37 -0
  123. package/dist/lib/generated/generated-forms.module.d.ts.map +1 -0
  124. package/dist/lib/generated/generated-forms.module.js +120 -0
  125. package/dist/lib/generated/generated-forms.module.js.map +1 -0
  126. package/dist/lib/nav/sales-nav.model.d.ts +93 -0
  127. package/dist/lib/nav/sales-nav.model.d.ts.map +1 -0
  128. package/dist/lib/nav/sales-nav.model.js +126 -0
  129. package/dist/lib/nav/sales-nav.model.js.map +1 -0
  130. package/dist/lib/sections/sales-section.component.d.ts +213 -0
  131. package/dist/lib/sections/sales-section.component.d.ts.map +1 -0
  132. package/dist/lib/sections/sales-section.component.js +905 -0
  133. package/dist/lib/sections/sales-section.component.js.map +1 -0
  134. package/dist/lib/vendored/workspace-tabs/workspace-card.component.d.ts +55 -0
  135. package/dist/lib/vendored/workspace-tabs/workspace-card.component.d.ts.map +1 -0
  136. package/dist/lib/vendored/workspace-tabs/workspace-card.component.js +243 -0
  137. package/dist/lib/vendored/workspace-tabs/workspace-card.component.js.map +1 -0
  138. package/dist/lib/vendored/workspace-tabs/workspace-tab-store.d.ts +47 -0
  139. package/dist/lib/vendored/workspace-tabs/workspace-tab-store.d.ts.map +1 -0
  140. package/dist/lib/vendored/workspace-tabs/workspace-tab-store.js +112 -0
  141. package/dist/lib/vendored/workspace-tabs/workspace-tab-store.js.map +1 -0
  142. package/dist/lib/vendored/workspace-tabs/workspace-tab-strip.component.d.ts +36 -0
  143. package/dist/lib/vendored/workspace-tabs/workspace-tab-strip.component.d.ts.map +1 -0
  144. package/dist/lib/vendored/workspace-tabs/workspace-tab-strip.component.js +179 -0
  145. package/dist/lib/vendored/workspace-tabs/workspace-tab-strip.component.js.map +1 -0
  146. package/dist/lib/vendored/workspace-tabs/workspace-tabs.types.d.ts +36 -0
  147. package/dist/lib/vendored/workspace-tabs/workspace-tabs.types.d.ts.map +1 -0
  148. package/dist/lib/vendored/workspace-tabs/workspace-tabs.types.js +9 -0
  149. package/dist/lib/vendored/workspace-tabs/workspace-tabs.types.js.map +1 -0
  150. package/dist/lib/vendored/workspace-tabs/workspace-tip.directive.d.ts +35 -0
  151. package/dist/lib/vendored/workspace-tabs/workspace-tip.directive.d.ts.map +1 -0
  152. package/dist/lib/vendored/workspace-tabs/workspace-tip.directive.js +124 -0
  153. package/dist/lib/vendored/workspace-tabs/workspace-tip.directive.js.map +1 -0
  154. package/dist/lib/workspace/deal-workspace.component.d.ts +706 -0
  155. package/dist/lib/workspace/deal-workspace.component.d.ts.map +1 -0
  156. package/dist/lib/workspace/deal-workspace.component.js +2749 -0
  157. package/dist/lib/workspace/deal-workspace.component.js.map +1 -0
  158. package/dist/lib/workspace/deal-workspace.dates.d.ts +40 -0
  159. package/dist/lib/workspace/deal-workspace.dates.d.ts.map +1 -0
  160. package/dist/lib/workspace/deal-workspace.dates.js +60 -0
  161. package/dist/lib/workspace/deal-workspace.dates.js.map +1 -0
  162. package/dist/lib/workspace/deal-workspace.products.d.ts +61 -0
  163. package/dist/lib/workspace/deal-workspace.products.d.ts.map +1 -0
  164. package/dist/lib/workspace/deal-workspace.products.js +58 -0
  165. package/dist/lib/workspace/deal-workspace.products.js.map +1 -0
  166. package/dist/lib/workspace/deal-workspace.service.d.ts +207 -0
  167. package/dist/lib/workspace/deal-workspace.service.d.ts.map +1 -0
  168. package/dist/lib/workspace/deal-workspace.service.js +501 -0
  169. package/dist/lib/workspace/deal-workspace.service.js.map +1 -0
  170. package/dist/lib/workspace/deal-workspace.types.d.ts +101 -0
  171. package/dist/lib/workspace/deal-workspace.types.d.ts.map +1 -0
  172. package/dist/lib/workspace/deal-workspace.types.js +35 -0
  173. package/dist/lib/workspace/deal-workspace.types.js.map +1 -0
  174. package/dist/lib/workspace/deal-workspace.validation.d.ts +174 -0
  175. package/dist/lib/workspace/deal-workspace.validation.d.ts.map +1 -0
  176. package/dist/lib/workspace/deal-workspace.validation.js +288 -0
  177. package/dist/lib/workspace/deal-workspace.validation.js.map +1 -0
  178. package/dist/public-api.d.ts +63 -0
  179. package/dist/public-api.d.ts.map +1 -0
  180. package/dist/public-api.js +96 -0
  181. package/dist/public-api.js.map +1 -0
  182. package/package.json +57 -0
@@ -0,0 +1,501 @@
1
+ /**
2
+ * @fileoverview All data access for the deal workspace, so the component itself does none.
3
+ *
4
+ * The workspace component stays presentational: it takes lookups and a `DealEntity`, and asks this
5
+ * service to save it. That split is copied from bizapps-contracts, and the payoff is that the surface can
6
+ * be rendered and reasoned about without a provider behind it.
7
+ *
8
+ * WHAT CHANGED WITH RELATED RECORD COLLECTIONS. This service used to build a `DealDraft` — a UI-side
9
+ * model with its own line and instalment arrays — and send it through the `Sales.SaveDeal` remote
10
+ * operation, because the entity a browser held had no child collections to save. It does now, so the
11
+ * service hands out the real entity and its children, and saving is `deal.Save()`. The two places that
12
+ * needed care are both here rather than in the component: LOADING the collections exactly once
13
+ * ({@link DealWorkspaceService.LoadDeal}) and forcing a full write-out on save
14
+ * ({@link DealWorkspaceService.Save}).
15
+ *
16
+ * @module @mj-biz-apps/sales-ng
17
+ */
18
+ import { Injectable } from '@angular/core';
19
+ import { EntitySaveOptions, LogError, Metadata, RunQuery, RunView } from '@memberjunction/core';
20
+ import { EmptyLookups, } from './deal-workspace.types';
21
+ import { EmptyValidation, ProjectValidation, } from './deal-workspace.validation';
22
+ import { E_ORDERS_PRODUCT, ProductFilterFor } from '@mj-biz-apps/sales-entities';
23
+ import * as i0 from "@angular/core";
24
+ const E_PIPELINE = 'MJ_BizApps_Sales: Pipelines';
25
+ const E_STAGE = 'MJ_BizApps_Sales: Pipeline Stages';
26
+ const E_DEAL_TYPE = 'MJ_BizApps_Sales: Deal Types';
27
+ const E_STATUS_TYPE = 'MJ_BizApps_Sales: Deal Status Types';
28
+ const E_FORECAST_TYPE = 'MJ_BizApps_Sales: Forecast Category Types';
29
+ const E_ACCOUNT = 'MJ_BizApps_Sales: Sales Accounts';
30
+ const E_CONTACT = 'MJ_BizApps_Sales: Sales Contacts';
31
+ const E_EMPLOYEE = 'MJ: Employees';
32
+ const E_DEAL = 'MJ_BizApps_Sales: Deals';
33
+ const E_LOSS_REASON = 'MJ_BizApps_Sales: Loss Reasons';
34
+ /**
35
+ * The collections the workspace edits, named once.
36
+ *
37
+ * Passed to `LoadRelatedRecords` so the load is EXPLICIT about what it wants rather than taking
38
+ * "everything declared". A collection added to the entity later should not start being fetched by a
39
+ * surface that does not render it.
40
+ */
41
+ // 'Lines' is NOT here: the deal holds none. Its order's lines arrive with the embedded order.
42
+ const WORKSPACE_COLLECTIONS = ['PaymentSchedule', 'Team'];
43
+ export class DealWorkspaceService {
44
+ /**
45
+ * Loads every picker's contents in ONE round trip.
46
+ *
47
+ * `RunViews` (plural) rather than nine awaited `RunView` calls — the house rule against querying in
48
+ * a loop applies just as much to a fixed list of nine as to an unbounded one.
49
+ */
50
+ /**
51
+ * The human-facing NUMBER of a record a close routed to.
52
+ *
53
+ * `SalesCloseRoutingResult.RecordID` is an ID; a user needs the number orders or contracts minted.
54
+ * Soft-resolved by target so the workspace degrades to showing nothing rather than erroring when the
55
+ * downstream app is not installed — the routing result already explains that case in its own words.
56
+ *
57
+ * This is a READ of the downstream record's own value. Nothing is computed here; see the money rule.
58
+ */
59
+ async LookupRoutedRecordNumber(target, recordID) {
60
+ const map = {
61
+ Order: { Entity: 'MJ_BizApps_Orders: Order Headers', Field: 'OrderNumber' },
62
+ Contract: { Entity: 'MJ_BizApps_Contracts: Contracts', Field: 'ContractNumber' },
63
+ };
64
+ const spec = map[target];
65
+ if (!spec) {
66
+ return null;
67
+ }
68
+ try {
69
+ const r = await new RunView().RunView({
70
+ EntityName: spec.Entity,
71
+ ExtraFilter: `ID = '${recordID.replace(/'/g, "''")}'`,
72
+ ResultType: 'simple',
73
+ Fields: ['ID', spec.Field],
74
+ });
75
+ const row = r?.Success ? (r.Results ?? [])[0] : undefined;
76
+ const value = row?.[spec.Field];
77
+ return typeof value === 'string' && value.length ? value : null;
78
+ }
79
+ catch {
80
+ return null;
81
+ }
82
+ }
83
+ async LoadLookups() {
84
+ const rv = new RunView();
85
+ const params = [
86
+ { EntityName: E_PIPELINE, ExtraFilter: 'IsActive = 1', OrderBy: 'DisplayRank ASC, Name ASC', ResultType: 'simple', Fields: ['ID', 'Name', 'CompanyID', 'Company'] },
87
+ { EntityName: E_STAGE, ExtraFilter: 'IsActive = 1', OrderBy: 'DisplayOrder ASC', ResultType: 'simple', Fields: ['ID', 'Name', 'PipelineID', 'DisplayOrder', 'Probability', 'ForecastCategoryTypeID', 'DealStatusTypeID'] },
88
+ { EntityName: E_DEAL_TYPE, ExtraFilter: 'IsActive = 1', OrderBy: 'DisplayRank ASC', ResultType: 'simple', Fields: ['ID', 'Name'] },
89
+ // The FLAGS come back with the status, because the dashboard counts open/won deals and the
90
+ // only permitted way to decide either is to read the flag. Comparing a status name is what
91
+ // the vocabulary gate forbids, and it also breaks the moment somebody renames "Won".
92
+ { EntityName: E_STATUS_TYPE, ExtraFilter: 'IsActive = 1', OrderBy: 'DisplayRank ASC', ResultType: 'simple', Fields: ['ID', 'Name', 'IsOpen', 'IsClosed', 'IsWon', 'IsLost', 'LocksDeal'] },
93
+ { EntityName: E_FORECAST_TYPE, ExtraFilter: 'IsActive = 1', OrderBy: 'DisplayRank ASC', ResultType: 'simple', Fields: ['ID', 'Name'] },
94
+ // KI-8: a Deal row cannot resolve its own account or contact name, because both FKs point at
95
+ // IsA CHILDREN whose Name lives on the parent and CodeGen generates no lookup join through
96
+ // that edge. So they are loaded here and resolved client-side. This is the reason the
97
+ // customer-context header exists as a lookup rather than a field on the deal.
98
+ { EntityName: E_ACCOUNT, ExtraFilter: 'IsActive = 1', OrderBy: 'Name ASC', ResultType: 'simple', Fields: ['ID', 'Name'] },
99
+ { EntityName: E_CONTACT, OrderBy: 'LastName ASC', ResultType: 'simple', Fields: ['ID', 'FirstName', 'LastName', 'Email'] },
100
+ { EntityName: E_EMPLOYEE, ExtraFilter: 'Active = 1', OrderBy: 'LastName ASC', ResultType: 'simple', Fields: ['ID', 'FirstLast'] },
101
+ // Index 9 — loss reasons, for the close panel. `RequiresNotes` travels with them because the
102
+ // panel decides whether LossNotes is mandatory from the FLAG on the chosen row.
103
+ { EntityName: E_LOSS_REASON, ExtraFilter: 'IsActive = 1', OrderBy: 'DisplayRank ASC, Name ASC', ResultType: 'simple', Fields: ['ID', 'Name', 'RequiresNotes'] },
104
+ ];
105
+ const results = await rv.RunViews(params);
106
+ /**
107
+ * `RunViews` answers POSITIONALLY, and hand-typed indexes drift the moment a query is added or
108
+ * removed. This file has already been bitten by it: a picker that read as EMPTY because every
109
+ * index after an insertion point was off by one -- which looks like "no rows", not like a bug.
110
+ * Deleting the Deal Line Types query above would have shifted four more.
111
+ *
112
+ * So the order is declared ONCE and every reader asks by NAME. Adding a query means adding its
113
+ * name here beside the param; nothing else moves.
114
+ */
115
+ const ORDER = [
116
+ 'Pipelines', 'Stages', 'DealTypes', 'DealStatusTypes', 'ForecastCategoryTypes',
117
+ 'Accounts', 'Contacts', 'Employees', 'LossReasons',
118
+ ];
119
+ const at = (key) => ORDER.indexOf(key);
120
+ if (results && results.length !== ORDER.length) {
121
+ // Each block below already degrades on its own, so this is not fatal -- but a mismatch means
122
+ // ORDER and `params` have drifted apart, and every picker past the drift is reading the
123
+ // wrong query. Say so rather than let it be discovered as an empty dropdown.
124
+ LogError(`DealWorkspaceService.LoadLookups: ${results.length} result(s) for ${ORDER.length} ` +
125
+ 'named lookups -- ORDER and the params array have drifted.');
126
+ }
127
+ const lookups = EmptyLookups();
128
+ // RunViews does not throw; an unsuccessful view yields an empty list rather than an exception,
129
+ // so each block checks Success independently. A missing picker degrades that one control
130
+ // instead of blanking the whole surface.
131
+ const rows = (index) => {
132
+ const r = results?.[index];
133
+ return r?.Success ? (r.Results ?? []) : [];
134
+ };
135
+ lookups.Pipelines = rows(at('Pipelines')).map((p) => ({
136
+ ID: p.ID, Name: p.Name, CompanyID: p.CompanyID, CompanyName: p.Company ?? null,
137
+ }));
138
+ lookups.Stages = rows(at('Stages')).map((s) => ({
139
+ ID: s.ID, Name: s.Name, PipelineID: s.PipelineID, DisplayOrder: s.DisplayOrder,
140
+ Probability: s.Probability, ForecastCategoryTypeID: s.ForecastCategoryTypeID,
141
+ DealStatusTypeID: s.DealStatusTypeID ?? null,
142
+ }));
143
+ lookups.DealTypes = rows(at('DealTypes')).map((r) => ({ ID: r.ID, Name: r.Name }));
144
+ lookups.DealStatusTypes = rows(at('DealStatusTypes')).map((r) => ({
145
+ ID: r.ID,
146
+ Name: r.Name,
147
+ IsOpen: r.IsOpen === true,
148
+ IsClosed: r.IsClosed === true,
149
+ IsWon: r.IsWon === true,
150
+ IsLost: r.IsLost === true,
151
+ LocksDeal: r.LocksDeal === true,
152
+ }));
153
+ lookups.ForecastCategoryTypes = rows(at('ForecastCategoryTypes')).map((r) => ({ ID: r.ID, Name: r.Name }));
154
+ // Index 9 — the loss reasons queried above. The close panel cannot demand a reason it has no
155
+ // list to offer, and an empty dropdown fails as a TIMEOUT rather than as a missing list, which
156
+ // is a slow way to find out.
157
+ lookups.LossReasons = rows(at('LossReasons')).map((r) => ({
158
+ ID: r.ID, Name: r.Name, RequiresNotes: r.RequiresNotes === true,
159
+ }));
160
+ lookups.Accounts = rows(at('Accounts')).map((r) => ({ ID: r.ID, Name: r.Name }));
161
+ lookups.Contacts = rows(at('Contacts')).map((c) => ({
162
+ ID: c.ID,
163
+ Name: [c.FirstName, c.LastName].filter(Boolean).join(' ').trim() || c.Email || '(unnamed contact)',
164
+ }));
165
+ lookups.Employees = rows(at('Employees')).map((e) => ({
166
+ ID: e.ID, Name: e.FirstLast ?? '(unnamed employee)',
167
+ }));
168
+ return lookups;
169
+ }
170
+ /**
171
+ * The deal roster — what the dashboard and the list both read.
172
+ *
173
+ * ONE `RunViews` call for deals AND accounts. The account read exists only to resolve customer
174
+ * names (KI-8); doing it per row would be the "never query in a loop" rule broken in the most
175
+ * expensive possible place.
176
+ *
177
+ * Returns an empty array on failure rather than throwing, because a roster that cannot load should
178
+ * render as an empty list with a message, not take the whole section down.
179
+ */
180
+ /**
181
+ * The deal roster, from the `Sales: Deal Roster` MJ Query.
182
+ *
183
+ * -- WHAT THIS REPLACED, AND WHY IT IS NOT JUST A RELOCATION --
184
+ *
185
+ * It was two RunViews: every deal, plus every account, joined in the browser with a Map to fill
186
+ * in a customer name. The query does that join in SQL, so the second read and the client-side
187
+ * join both go away -- and with them a whole class of drift, because the roster the dashboard
188
+ * shows and the roster the §9 aggregates are built on are now literally the same definition.
189
+ *
190
+ * It also carries the STATUS FLAGS and IsPastExpectedClose per row, which is what lets the section
191
+ * drop its separate status fetch for flag resolution and its hand-built UTC date comparison.
192
+ *
193
+ * Master plan §9.5 is the rule this satisfies: read models are MJ Queries, so Skip, the query
194
+ * builder and report snapshots reach the same definitions the UI does.
195
+ *
196
+ * COLUMN NAMES ARE MAPPED, NOT PASSED THROUGH. The query names things for a report reader
197
+ * (DealName, AccountName, StageName); DealRosterRow names them for a component (Name,
198
+ * CustomerName, PipelineStage). Mapping here keeps both audiences served and means renaming a
199
+ * column on either side is a one-file change.
200
+ */
201
+ async LoadRoster() {
202
+ const result = await new RunQuery().RunQuery({
203
+ QueryName: 'Sales: Deal Roster',
204
+ CategoryPath: 'Sales',
205
+ });
206
+ if (!result?.Success) {
207
+ LogError(`Sales: Deal Roster failed - ${result?.ErrorMessage ?? 'unknown error'}`);
208
+ return [];
209
+ }
210
+ const bool = (v) => v === true || v === 1 || v === '1';
211
+ /**
212
+ * COERCE THE NUMERICS. They were CAST -- `as number | null` -- which tells TypeScript to trust
213
+ * and enforces nothing at runtime.
214
+ *
215
+ * Measured on this provider today, `Amount` and `Probability` do come back as `number`, so the
216
+ * cast is currently accurate. It is still the wrong construct: `bool()` above exists because
217
+ * this codebase has already met a SQL scalar arriving as `1` rather than `true`, the dashboard
218
+ * loader wraps every numeric in its own `num()`, and the browser reaches these rows over
219
+ * GraphQL rather than in-process -- a different transport that nothing here has verified.
220
+ *
221
+ * The failure mode if that assumption ever breaks is not a type error. `deal-board` reduces
222
+ * these with `+`, so a string turns addition into concatenation: two cards become
223
+ * "027480.000015000.0000", the currency pipe cannot parse it, and the board render dies with
224
+ * InvalidPipeArgumentError. Coercing costs nothing and removes the whole class.
225
+ */
226
+ const num = (v) => {
227
+ if (v === null || v === undefined || v === '') {
228
+ return null;
229
+ }
230
+ const n = Number(v);
231
+ // NaN would propagate silently through every sum and total. A value that is not a number
232
+ // is reported as absent, which every consumer already handles.
233
+ return Number.isFinite(n) ? n : null;
234
+ };
235
+ return (result.Results ?? []).map((d) => ({
236
+ ID: String(d['DealID'] ?? ''),
237
+ DealNumber: d['DealNumber'] ?? null,
238
+ Name: String(d['DealName'] ?? ''),
239
+ AccountID: d['AccountID'] ?? null,
240
+ // Still an em dash rather than a blank: an unattached deal is a STATE, and an empty cell
241
+ // reads as a rendering fault.
242
+ CustomerName: d['AccountName'] ?? '—',
243
+ Amount: num(d['Amount']),
244
+ AmountIsComputed: bool(d['AmountIsComputed']),
245
+ Probability: num(d['Probability']),
246
+ ExpectedCloseDate: d['ExpectedCloseDate'] ?? null,
247
+ Pipeline: d['PipelineName'] ?? null,
248
+ PipelineStage: d['StageName'] ?? null,
249
+ DealType: d['DealTypeName'] ?? null,
250
+ DealStatusType: d['StatusName'] ?? null,
251
+ OwnerEmployee: d['OwnerName'] ?? null,
252
+ ForecastCategoryType: d['ForecastCategoryName'] ?? null,
253
+ DealStatusTypeID: d['DealStatusTypeID'] ?? null,
254
+ PipelineID: d['PipelineID'] ?? null,
255
+ PipelineStageID: d['PipelineStageID'] ?? null,
256
+ CurrencyID: d['CurrencyID'] ?? null,
257
+ IsOpen: bool(d['IsOpen']),
258
+ IsWon: bool(d['IsWon']),
259
+ IsLost: bool(d['IsLost']),
260
+ IsClosed: bool(d['IsClosed']),
261
+ IsPastExpectedClose: bool(d['IsPastExpectedClose']),
262
+ }));
263
+ }
264
+ /**
265
+ * The products a rep may put on a line, for one selling company.
266
+ *
267
+ * SEPARATE FROM `LoadLookups`, deliberately. The other pickers are session-wide and load once; this
268
+ * one depends on the DEAL'S company, so it is fetched when a deal opens and again if its pipeline
269
+ * changes. Folding it into the session lookups would either fetch every company's catalogue or
270
+ * silently show the first deal's.
271
+ *
272
+ * Returns an empty list on failure rather than throwing: a picker that cannot load should offer
273
+ * nothing and let the rest of the line editor keep working. The consequence — a rep unable to select
274
+ * a product — is visible, whereas a half-loaded catalogue silently missing rows is not.
275
+ */
276
+ async LoadProducts(companyID, asOf = new Date()) {
277
+ if (!companyID) {
278
+ return [];
279
+ }
280
+ /**
281
+ * ORDERS MAY NOT BE PRESENT AT ALL, and that is a supported state rather than an error.
282
+ *
283
+ * Sales is designed to run standalone: `DealLine.ProductID` is a SOFT reference and no foreign
284
+ * key crosses into orders' schema, so a deployment can install Sales without orders and every
285
+ * other part of this surface still works. Asking `RunView` for an unregistered entity does not
286
+ * return `Success: false` — it logs `Entity ... not found in metadata`, and the Playwright
287
+ * keystone (correctly) treats a console error as a broken screen. That is how this was found:
288
+ * the picker took the whole workspace gate down on a host where orders is absent.
289
+ *
290
+ * So the entity is checked in metadata FIRST, and its absence simply means no picker.
291
+ */
292
+ const md = new Metadata();
293
+ const known = md.Entities.some((e) => e.Name === E_ORDERS_PRODUCT);
294
+ if (!known) {
295
+ return [];
296
+ }
297
+ const rv = new RunView();
298
+ const result = await rv.RunView({
299
+ EntityName: E_ORDERS_PRODUCT,
300
+ ExtraFilter: ProductFilterFor(companyID, asOf),
301
+ OrderBy: 'Name ASC',
302
+ ResultType: 'simple',
303
+ Fields: ['ID', 'Name', 'SKU'],
304
+ });
305
+ return result?.Success ? (result.Results ?? []) : [];
306
+ }
307
+ /** A blank deal, ready to bind to. Its collections start empty and are never loaded — there is nothing to load. */
308
+ async NewDeal() {
309
+ const md = new Metadata();
310
+ const deal = await md.GetEntityObject(E_DEAL);
311
+ deal.NewRecord();
312
+ return deal;
313
+ }
314
+ /**
315
+ * Reads an existing deal and everything the workspace shows — header, schedule, roster, and the
316
+ * lines, which belong to the deal's embedded order rather than to the deal.
317
+ *
318
+ * THIS IS THE ONLY PLACE THE COLLECTIONS ARE LOADED, and that is a data-loss guard rather than a
319
+ * tidiness preference. Every one of them is declared `Load: 'explicit'`, so nothing populates them
320
+ * lazily;
321
+ * a second load arriving mid-edit is what would replace the user's unsaved rows with whatever is in
322
+ * the database. `LoadRelatedRecords` is itself guarded — it skips a collection that is already loaded
323
+ * or holds staged work — and it batches all three into ONE `RunViews` rather than three round trips.
324
+ *
325
+ * Returns null when the deal or any of its collections could not be read. That distinction matters:
326
+ * `LoadRelatedRecords` logs a failed collection and leaves it EMPTY rather than throwing, so without
327
+ * the `IsLoaded` check below, a failed read would present as a deal that genuinely has no lines.
328
+ */
329
+ async LoadDeal(dealID) {
330
+ const md = new Metadata();
331
+ const deal = await md.GetEntityObject(E_DEAL);
332
+ if (!(await deal.Load(dealID))) {
333
+ return null;
334
+ }
335
+ await deal.LoadRelatedRecords(...WORKSPACE_COLLECTIONS);
336
+ // A collection only reports IsLoaded once its rows actually arrived, so this catches the silent
337
+ // failure above. An empty deal and an unreadable one must never look the same.
338
+ if (!deal.PaymentSchedule.IsLoaded || !deal.Team.IsLoaded) {
339
+ return null;
340
+ }
341
+ /**
342
+ * THE LINES LIVE ON THE ORDER, so they need a load of their own.
343
+ *
344
+ * `WORKSPACE_COLLECTIONS` covers the deal's OWN collections; the embedded order is a separate
345
+ * entity instance and its `Lines` is declared `Load: 'explicit'` just like the deal's are. Nothing
346
+ * populates it lazily, so without this a saved deal with lines opens showing NONE -- and reads as
347
+ * a deal nobody has quoted yet.
348
+ *
349
+ * ── THREE OUTCOMES, AND THEY MUST STAY DISTINGUISHABLE ──
350
+ *
351
+ * The whole point of the `IsLoaded` check above is that a failed read must not look like an empty
352
+ * one. That guarantee has to extend here, and there is a third case now:
353
+ *
354
+ * 1. no `OrderID` at all -- legitimate. A deal saved before the embed landed, or one whose
355
+ * order could not be provisioned. There are no lines to fail to
356
+ * read, so this is NOT an error: the deal opens, empty.
357
+ * 2. `OrderID` set, order absent -- a FAILURE. The FK names a row and the peer did not arrive,
358
+ * which means the read broke or the order was deleted out from
359
+ * under the deal. Returning the deal here would show zero lines
360
+ * for an order that has them.
361
+ * 3. order present, lines unread -- a FAILURE, for the same reason the collections above are
362
+ * checked: `LoadRelatedRecords` logs and leaves the collection
363
+ * empty rather than throwing.
364
+ *
365
+ * Only (1) returns a deal with no lines. (2) and (3) return null, which is what the caller already
366
+ * treats as "could not read this deal" rather than rendering it.
367
+ */
368
+ if (deal.OrderID) {
369
+ const order = deal.OrderID_Object;
370
+ if (!order) {
371
+ LogError(`DealWorkspaceService.LoadDeal: deal ${dealID} points at order ${deal.OrderID} but the ` +
372
+ 'embedded record did not resolve. Refusing to render it as a deal with no lines.');
373
+ return null;
374
+ }
375
+ await order.LoadRelatedRecords('Lines');
376
+ if (!order.Lines.IsLoaded) {
377
+ LogError(`DealWorkspaceService.LoadDeal: could not read the lines of order ${deal.OrderID} for ` +
378
+ `deal ${dealID}. An unreadable line set must not present as an empty one.`);
379
+ return null;
380
+ }
381
+ }
382
+ return deal;
383
+ }
384
+ /**
385
+ * Saves the deal and its children as ONE unit of work.
386
+ *
387
+ * `Save()` on a record carrying related-record collections is not a single-row write: MJ builds a
388
+ * save plan, ships the whole graph in one `MJ.SaveEntityGraph` mutation, and the server executes it
389
+ * inside one transaction — header first, then removals, then children. So either the deal and
390
+ * everything under it landed, or nothing did. There is no path here that leaves a numbered deal with
391
+ * nothing beneath it, which is exactly what the retired `Sales.SaveDeal` operation existed to
392
+ * guarantee.
393
+ *
394
+ * `IgnoreDirtyState` is deliberate and load-bearing: without it, a child that is loaded and unchanged
395
+ * contributes no work, which is normally right — but this surface re-sequences `DisplayOrder` from
396
+ * array position on every add and remove, so a row that merely MOVED is clean by field-comparison and
397
+ * would keep its old position in the database.
398
+ *
399
+ * A record the server refuses for being invalid is an ORDINARY outcome, reported through `Validation`
400
+ * rather than `ErrorMessage`. Only a transport or database failure produces the latter.
401
+ */
402
+ async Save(deal) {
403
+ const wasNew = !deal.IsSaved;
404
+ try {
405
+ const validation = ProjectValidation(deal.Validate());
406
+ if (!validation.IsValid) {
407
+ return {
408
+ Success: false,
409
+ DealID: deal.IsSaved ? deal.ID : null,
410
+ Created: false,
411
+ Validation: validation,
412
+ ErrorMessage: null,
413
+ };
414
+ }
415
+ const options = new EntitySaveOptions();
416
+ options.IgnoreDirtyState = true;
417
+ const saved = await deal.Save(options);
418
+ if (!saved) {
419
+ return {
420
+ Success: false,
421
+ DealID: deal.IsSaved ? deal.ID : null,
422
+ Created: false,
423
+ Validation: EmptyValidation(),
424
+ ErrorMessage: deal.LatestResult?.CompleteMessage ?? 'The deal could not be saved.',
425
+ };
426
+ }
427
+ // The SAME instance now carries the server's IDs, so the surface keeps editing the record it
428
+ // just created rather than a rebuilt copy — the job `ApplySaveResult` used to do by hand.
429
+ return {
430
+ Success: true,
431
+ DealID: deal.ID,
432
+ Created: wasNew,
433
+ Validation: EmptyValidation(),
434
+ ErrorMessage: null,
435
+ };
436
+ }
437
+ catch (err) {
438
+ return {
439
+ Success: false,
440
+ DealID: deal.IsSaved ? deal.ID : null,
441
+ Created: false,
442
+ Validation: EmptyValidation(),
443
+ ErrorMessage: err instanceof Error ? err.message : String(err),
444
+ };
445
+ }
446
+ }
447
+ /**
448
+ * The dashboard's four figures, from the `Sales: Dashboard Summary` MJ Query.
449
+ *
450
+ * -- WHY A QUERY AND NOT A GETTER --
451
+ *
452
+ * These were computed in `sales-section.component.ts` by reducing over the loaded roster. The
453
+ * answers were right; the mechanism was the problem. Master plan §9.5: read models belong in MJ
454
+ * Queries rather than hand-rolled Angular aggregation, so Skip, the query builder and report
455
+ * snapshots all get them for free. A measure living in a component getter is reachable by exactly
456
+ * one caller, and silently diverges the moment a second surface needs the same number.
457
+ *
458
+ * It also stops the tiles depending on the roster being fully loaded to be correct: the old
459
+ * TotalCount was `this.Deals.length`, so any future paging or filtering of the roster would have
460
+ * quietly changed a headline figure that is supposed to describe the whole book.
461
+ *
462
+ * Proven equivalent BEFORE the switch: `test-harnesses/compare-dashboard-measures.mjs` runs both
463
+ * implementations over the same data and fails on any disagreement. All eight comparisons agreed,
464
+ * including the closing-soon ORDER and the slipped set by deal identity rather than by count.
465
+ */
466
+ async LoadDashboardSummary() {
467
+ const result = await new RunQuery().RunQuery({
468
+ QueryName: 'Sales: Dashboard Summary',
469
+ CategoryPath: 'Sales',
470
+ });
471
+ if (!result?.Success) {
472
+ LogError(`Sales: Dashboard Summary failed - ${result?.ErrorMessage ?? 'unknown error'}`);
473
+ return null;
474
+ }
475
+ const row = (result.Results ?? [])[0];
476
+ if (!row) {
477
+ return null;
478
+ }
479
+ // The query aggregates, so it returns a row even over an empty table. A null from here means
480
+ // the query did not RUN, which is a different thing from a database with no deals -- and the
481
+ // caller renders those two states differently.
482
+ const num = (v) => (v === null || v === undefined ? 0 : Number(v));
483
+ return {
484
+ OpenAmount: num(row['OpenAmount']),
485
+ OpenCount: num(row['OpenCount']),
486
+ TotalCount: num(row['TotalCount']),
487
+ PastExpectedCloseCount: num(row['PastExpectedCloseCount']),
488
+ WonCount: num(row['WonCount']),
489
+ OpenPricedAmount: num(row['OpenPricedAmount']),
490
+ OpenStatedAmount: num(row['OpenStatedAmount']),
491
+ OpenNoAmountCount: num(row['OpenNoAmountCount']),
492
+ };
493
+ }
494
+ static ɵfac = function DealWorkspaceService_Factory(__ngFactoryType__) { return new (__ngFactoryType__ || DealWorkspaceService)(); };
495
+ static ɵprov = /*@__PURE__*/ i0.ɵɵdefineInjectable({ token: DealWorkspaceService, factory: DealWorkspaceService.ɵfac, providedIn: 'root' });
496
+ }
497
+ (() => { (typeof ngDevMode === "undefined" || ngDevMode) && i0.ɵsetClassMetadata(DealWorkspaceService, [{
498
+ type: Injectable,
499
+ args: [{ providedIn: 'root' }]
500
+ }], null, null); })();
501
+ //# sourceMappingURL=deal-workspace.service.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"deal-workspace.service.js","sourceRoot":"","sources":["../../../src/lib/workspace/deal-workspace.service.ts"],"names":[],"mappings":"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"}
@@ -0,0 +1,101 @@
1
+ /**
2
+ * @fileoverview Shapes the deal workspace binds to.
3
+ *
4
+ * Two conventions here are load-bearing rather than stylistic:
5
+ *
6
+ * 1. **The pane keys ARE the `DealWorkspaceSection` keys.** `ProjectValidation()` tags every issue with a
7
+ * `Section`, and the tabs below key off the same strings, so one validation pass drives both the tab
8
+ * badges and the field markers with no mapping table in between. Rename a key here and you must
9
+ * rename it in `deal-workspace.validation.ts`; anything else silently stops badging.
10
+ *
11
+ * 2. **Lookups are plain `{ ID, Name }`.** The workspace never queries — the service loads reference
12
+ * data once and hands it in, mirroring how bizapps-contracts keeps its workspace presentational.
13
+ * That is what makes the surface cheap to render repeatedly and testable without a provider.
14
+ *
15
+ * @module @mj-biz-apps/sales-ng
16
+ */
17
+ import type { DealWorkspaceSection } from './deal-workspace.validation';
18
+ /** The minimum a picker needs. Anything richer belongs in a dedicated shape below. */
19
+ export interface DealLookup {
20
+ ID: string;
21
+ Name: string;
22
+ }
23
+ /** A pipeline carries its company, because `Deal.CompanyID` is derived from it and never chosen. */
24
+ export interface PipelineLookup extends DealLookup {
25
+ CompanyID: string;
26
+ CompanyName: string | null;
27
+ }
28
+ /** Stages are filtered by pipeline, so the pipeline has to travel with them. */
29
+ export interface StageLookup extends DealLookup {
30
+ PipelineID: string;
31
+ DisplayOrder: number;
32
+ Probability: number | null;
33
+ ForecastCategoryTypeID: string | null;
34
+ /**
35
+ * The status this stage lands a deal in. Stages carry NO IsWon/IsClosed of their own -- they point at
36
+ * a `DealStatusType` that does, which is what makes "Closed Won" a label a pipeline may rename.
37
+ * Needed by any surface that must know whether arriving here would LOCK the deal.
38
+ */
39
+ DealStatusTypeID: string | null;
40
+ }
41
+ /**
42
+ * A deal status plus its BEHAVIOUR FLAGS.
43
+ *
44
+ * The flags are here because the dashboard has to answer "how many are open" and "how many did we win",
45
+ * and the only permitted way to do that is to read `IsOpen` / `IsWon` off this row. Comparing a status
46
+ * NAME is exactly what `npm run test:vocabulary-gate` exists to catch, and it is also just wrong: a
47
+ * deployment can rename "Won" to "Signed" and every name-based count silently reports zero.
48
+ */
49
+ export interface DealStatusLookup extends DealLookup {
50
+ IsOpen: boolean;
51
+ IsClosed: boolean;
52
+ IsWon: boolean;
53
+ IsLost: boolean;
54
+ /** Entering this status freezes the deal, its lines and its team. Enforced server-side. */
55
+ LocksDeal: boolean;
56
+ }
57
+ /**
58
+ * A loss reason plus the flag that decides whether notes are mandatory.
59
+ *
60
+ * `RequiresNotes` is read as a FLAG for the same reason every other behaviour here is: a deployment
61
+ * renames its reasons freely, and "Price" meaning "explain yourself" is a property of the row, not of
62
+ * the word. The close panel makes LossNotes required from this, and the server enforces the same rule.
63
+ */
64
+ export interface LossReasonLookup extends DealLookup {
65
+ RequiresNotes: boolean;
66
+ }
67
+ /** Everything the surface needs to render its pickers. Loaded once per session. */
68
+ export interface DealWorkspaceLookups {
69
+ Pipelines: PipelineLookup[];
70
+ Stages: StageLookup[];
71
+ DealTypes: DealLookup[];
72
+ DealStatusTypes: DealStatusLookup[];
73
+ LossReasons: LossReasonLookup[];
74
+ ForecastCategoryTypes: DealLookup[];
75
+ Accounts: DealLookup[];
76
+ Contacts: DealLookup[];
77
+ Employees: DealLookup[];
78
+ }
79
+ export declare function EmptyLookups(): DealWorkspaceLookups;
80
+ /** One pane of the workspace. `Key` matches a `DealWorkspaceSection` exactly — see the file header. */
81
+ export interface DealWorkspacePane {
82
+ Key: DealWorkspaceSection;
83
+ Label: string;
84
+ Icon: string;
85
+ }
86
+ /**
87
+ * The panes, in reading order: who the deal is with, what is being sold, how it gets paid, on what
88
+ * terms, and what was negotiated away.
89
+ */
90
+ export declare const DEAL_WORKSPACE_PANES: readonly DealWorkspacePane[];
91
+ /**
92
+ * The standard terms, shown as PLACEHOLDER text and never written into a draft.
93
+ *
94
+ * These live on the contracts `ContractType`, not on a deal. A deal stores an OVERRIDE, and null means
95
+ * "use the standard" — a different fact from "we agreed a number that happens to equal today's
96
+ * standard", and the only one of the two that survives a later policy change. So the form displays
97
+ * them to tell the AD what they are departing from, and sends null unless something was typed.
98
+ */
99
+ export declare const STANDARD_ANNUAL_INCREASE_PCT = 5;
100
+ export declare const STANDARD_CANCELLATION_NOTICE_DAYS = 90;
101
+ //# sourceMappingURL=deal-workspace.types.d.ts.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"deal-workspace.types.d.ts","sourceRoot":"","sources":["../../../src/lib/workspace/deal-workspace.types.ts"],"names":[],"mappings":"AAAA;;;;;;;;;;;;;;;GAeG;AACH,OAAO,KAAK,EAAE,oBAAoB,EAAE,MAAM,6BAA6B,CAAC;AAExE,sFAAsF;AACtF,MAAM,WAAW,UAAU;IACvB,EAAE,EAAE,MAAM,CAAC;IACX,IAAI,EAAE,MAAM,CAAC;CAChB;AAED,oGAAoG;AACpG,MAAM,WAAW,cAAe,SAAQ,UAAU;IAC9C,SAAS,EAAE,MAAM,CAAC;IAClB,WAAW,EAAE,MAAM,GAAG,IAAI,CAAC;CAC9B;AAED,gFAAgF;AAChF,MAAM,WAAW,WAAY,SAAQ,UAAU;IAC3C,UAAU,EAAE,MAAM,CAAC;IACnB,YAAY,EAAE,MAAM,CAAC;IACrB,WAAW,EAAE,MAAM,GAAG,IAAI,CAAC;IAC3B,sBAAsB,EAAE,MAAM,GAAG,IAAI,CAAC;IACtC;;;;OAIG;IACH,gBAAgB,EAAE,MAAM,GAAG,IAAI,CAAC;CACnC;AAGD;;;;;;;GAOG;AACH,MAAM,WAAW,gBAAiB,SAAQ,UAAU;IAChD,MAAM,EAAE,OAAO,CAAC;IAChB,QAAQ,EAAE,OAAO,CAAC;IAClB,KAAK,EAAE,OAAO,CAAC;IACf,MAAM,EAAE,OAAO,CAAC;IAChB,2FAA2F;IAC3F,SAAS,EAAE,OAAO,CAAC;CACtB;AAED;;;;;;GAMG;AACH,MAAM,WAAW,gBAAiB,SAAQ,UAAU;IAChD,aAAa,EAAE,OAAO,CAAC;CAC1B;AAED,mFAAmF;AACnF,MAAM,WAAW,oBAAoB;IACjC,SAAS,EAAE,cAAc,EAAE,CAAC;IAC5B,MAAM,EAAE,WAAW,EAAE,CAAC;IACtB,SAAS,EAAE,UAAU,EAAE,CAAC;IACxB,eAAe,EAAE,gBAAgB,EAAE,CAAC;IACpC,WAAW,EAAE,gBAAgB,EAAE,CAAC;IAChC,qBAAqB,EAAE,UAAU,EAAE,CAAC;IACpC,QAAQ,EAAE,UAAU,EAAE,CAAC;IACvB,QAAQ,EAAE,UAAU,EAAE,CAAC;IACvB,SAAS,EAAE,UAAU,EAAE,CAAC;CAC3B;AAED,wBAAgB,YAAY,IAAI,oBAAoB,CAYnD;AAED,uGAAuG;AACvG,MAAM,WAAW,iBAAiB;IAC9B,GAAG,EAAE,oBAAoB,CAAC;IAC1B,KAAK,EAAE,MAAM,CAAC;IACd,IAAI,EAAE,MAAM,CAAC;CAChB;AAED;;;GAGG;AACH,eAAO,MAAM,oBAAoB,EAAE,SAAS,iBAAiB,EAMnD,CAAC;AAEX;;;;;;;GAOG;AACH,eAAO,MAAM,4BAA4B,IAAI,CAAC;AAC9C,eAAO,MAAM,iCAAiC,KAAK,CAAC"}