@khester/create-dynamics-app 1.1.0 → 2.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.
- package/README.md +74 -0
- package/dist/artifacts/registry.d.ts +18 -0
- package/dist/artifacts/registry.d.ts.map +1 -0
- package/dist/artifacts/registry.js +340 -0
- package/dist/artifacts/registry.js.map +1 -0
- package/dist/artifacts/types.d.ts +122 -0
- package/dist/artifacts/types.d.ts.map +1 -0
- package/dist/artifacts/types.js +7 -0
- package/dist/artifacts/types.js.map +1 -0
- package/dist/artifacts/validators.d.ts +16 -0
- package/dist/artifacts/validators.d.ts.map +1 -0
- package/dist/artifacts/validators.js +45 -0
- package/dist/artifacts/validators.js.map +1 -0
- package/dist/fromDesign.d.ts +5 -0
- package/dist/fromDesign.d.ts.map +1 -0
- package/dist/fromDesign.js +98 -0
- package/dist/fromDesign.js.map +1 -0
- package/dist/index.js +129 -177
- package/dist/index.js.map +1 -1
- package/dist/injectDevTools.d.ts +28 -0
- package/dist/injectDevTools.d.ts.map +1 -0
- package/dist/injectDevTools.js +148 -0
- package/dist/injectDevTools.js.map +1 -0
- package/dist/scaffold.d.ts +48 -0
- package/dist/scaffold.d.ts.map +1 -0
- package/dist/scaffold.js +180 -0
- package/dist/scaffold.js.map +1 -0
- package/dist/templatePlan.d.ts +3 -0
- package/dist/templatePlan.d.ts.map +1 -0
- package/dist/templatePlan.js +43 -0
- package/dist/templatePlan.js.map +1 -0
- package/dist/utils/copyTemplate.d.ts +13 -1
- package/dist/utils/copyTemplate.d.ts.map +1 -1
- package/dist/utils/copyTemplate.js +98 -4
- package/dist/utils/copyTemplate.js.map +1 -1
- package/dist/utils/updatePackageJson.d.ts +11 -1
- package/dist/utils/updatePackageJson.d.ts.map +1 -1
- package/dist/utils/updatePackageJson.js +12 -10
- package/dist/utils/updatePackageJson.js.map +1 -1
- package/package.json +10 -7
- package/templates/_shared/dev-tools/auth/get-token.js +72 -0
- package/templates/_shared/dev-tools/dev/mock-xrm.js +42 -0
- package/templates/_shared/dev-tools/metadata-sync/index.js +152 -0
- package/templates/_shared/dev-tools/smoke/test-retrieve.js +44 -0
- package/templates/dialog-form/README.md +27 -0
- package/templates/dialog-form/_variants/App.v8.tsx +39 -0
- package/templates/dialog-form/_variants/App.v9.tsx +41 -0
- package/templates/dialog-form/gitignore +5 -0
- package/templates/dialog-form/package.json +27 -0
- package/templates/dialog-form/public/index.html +11 -0
- package/templates/dialog-form/src/index.tsx +10 -0
- package/templates/dialog-form/src/services/dataverse.ts +30 -0
- package/templates/dialog-form/tsconfig.json +15 -0
- package/templates/dialog-form/webpack.config.js +17 -0
- package/templates/grid-customizer/README.md +28 -0
- package/templates/grid-customizer/gitignore +4 -0
- package/templates/grid-customizer/package.json +25 -0
- package/templates/grid-customizer/src/GridCustomizer.ts +28 -0
- package/templates/grid-customizer/src/cell-renderers.tsx +35 -0
- package/templates/grid-customizer/src/index.ts +4 -0
- package/templates/grid-customizer/src/types/grid-types.ts +30 -0
- package/templates/grid-customizer/src/utils/color-utils.ts +24 -0
- package/templates/grid-customizer/tsconfig.json +15 -0
- package/templates/grid-customizer/webpack.config.js +17 -0
- package/templates/pcf-dataset/ControlManifest.Input.xml +16 -0
- package/templates/pcf-dataset/README.md +21 -0
- package/templates/pcf-dataset/gitignore +5 -0
- package/templates/pcf-dataset/index.ts +39 -0
- package/templates/pcf-dataset/package.json +30 -0
- package/templates/pcf-dataset/strings/{{componentName}}.1033.resx +47 -0
- package/templates/pcf-dataset/tsconfig.json +8 -0
- package/templates/pcf-dataset/{{componentName}}Component.tsx +39 -0
- package/templates/pcf-field/ControlManifest.Input.xml +17 -0
- package/templates/pcf-field/README.md +95 -0
- package/templates/pcf-field/_variants/ValueInput.boolean.tsx +24 -0
- package/templates/pcf-field/_variants/ValueInput.date.tsx +27 -0
- package/templates/pcf-field/_variants/ValueInput.number.tsx +35 -0
- package/templates/pcf-field/_variants/ValueInput.text.tsx +27 -0
- package/templates/pcf-field/gitignore +5 -0
- package/templates/pcf-field/index.ts +61 -0
- package/templates/pcf-field/package.json +30 -0
- package/templates/pcf-field/strings/{{componentName}}.1033.resx +47 -0
- package/templates/pcf-field/tsconfig.json +8 -0
- package/templates/pcf-field/{{componentName}}Component.tsx +35 -0
- package/templates/power-pages-starter/gitignore +5 -0
- package/templates/react-custom-page/gitignore +5 -0
- package/templates/{dynamics-365-starter → react-custom-page}/package.json +3 -3
- package/templates/react-custom-page/tools/metadata-sync/index.js +152 -0
- package/templates/static-web-app/README.md +36 -0
- package/templates/static-web-app/_variants/App.v8.tsx +32 -0
- package/templates/static-web-app/_variants/App.v9.tsx +31 -0
- package/templates/static-web-app/api/host.json +12 -0
- package/templates/static-web-app/api/package.json +19 -0
- package/templates/static-web-app/api/src/functions/hello.ts +16 -0
- package/templates/static-web-app/api/tsconfig.json +14 -0
- package/templates/static-web-app/frontend/index.html +12 -0
- package/templates/static-web-app/frontend/package.json +23 -0
- package/templates/static-web-app/frontend/src/index.tsx +8 -0
- package/templates/static-web-app/frontend/tsconfig.json +16 -0
- package/templates/static-web-app/frontend/vite.config.ts +13 -0
- package/templates/static-web-app/gitignore +8 -0
- package/templates/static-web-app/package.json +15 -0
- package/templates/static-web-app/staticwebapp.config.json +7 -0
- package/templates/teams-app/README.md +27 -0
- package/templates/teams-app/_variants/graph.off.ts +7 -0
- package/templates/teams-app/_variants/graph.on.ts +22 -0
- package/templates/teams-app/appPackage/manifest.json +26 -0
- package/templates/teams-app/gitignore +5 -0
- package/templates/teams-app/index.html +12 -0
- package/templates/teams-app/package.json +26 -0
- package/templates/teams-app/src/App.tsx +25 -0
- package/templates/teams-app/src/index.tsx +8 -0
- package/templates/teams-app/tsconfig.json +16 -0
- package/templates/teams-app/vite.config.ts +9 -0
- package/templates/web-resource/README.md +39 -0
- package/templates/web-resource/_variants/App.v8.tsx +29 -0
- package/templates/web-resource/_variants/App.v9.tsx +28 -0
- package/templates/web-resource/gitignore +5 -0
- package/templates/web-resource/package.json +27 -0
- package/templates/web-resource/public/index.html +11 -0
- package/templates/web-resource/src/index.tsx +10 -0
- package/templates/web-resource/src/services/dataverse.ts +30 -0
- package/templates/web-resource/tsconfig.json +15 -0
- package/templates/web-resource/webpack.config.js +17 -0
- package/dist/utils/consultingHelpers.d.ts +0 -13
- package/dist/utils/consultingHelpers.d.ts.map +0 -1
- package/dist/utils/consultingHelpers.js +0 -569
- package/dist/utils/consultingHelpers.js.map +0 -1
- package/templates/dynamics-365-starter/INTEGRATION_TEST_RESULTS.md +0 -302
- package/templates/dynamics-365-starter/PHASE_4_COMPLETION_SUMMARY.md +0 -305
- package/templates/dynamics-365-starter/deployment/QUICKSTART-MAC.md +0 -507
- package/templates/dynamics-365-starter/deployment/QUICKSTART-WINDOWS.md +0 -372
- package/templates/dynamics-365-starter/deployment/pipelines/README.md +0 -375
- package/templates/dynamics-365-starter/deployment/pipelines/azure-pipelines.yml +0 -330
- package/templates/dynamics-365-starter/deployment/pipelines/github-actions.yml +0 -422
- package/templates/dynamics-365-starter/deployment/pipelines/jenkins.groovy +0 -636
- package/templates/dynamics-365-starter/deployment/scripts/deploy.ps1 +0 -417
- package/templates/dynamics-365-starter/deployment/scripts/deploy.sh +0 -582
- package/templates/dynamics-365-starter/deployment/scripts/team-onboarding.ps1 +0 -486
- package/templates/dynamics-365-starter/deployment/scripts/team-onboarding.sh +0 -567
- package/templates/dynamics-365-starter/deployment/scripts/validate-setup.ps1 +0 -703
- package/templates/dynamics-365-starter/deployment/scripts/validate-setup.sh +0 -671
- package/templates/dynamics-365-starter/docs/team-standards/README.md +0 -273
- package/templates/dynamics-365-starter/docs/team-standards/client-onboarding.md +0 -577
- package/templates/dynamics-365-starter/docs/team-standards/code-review-checklist.md +0 -359
- package/templates/dynamics-365-starter/docs/team-standards/coding-standards.md +0 -700
- package/templates/dynamics-365-starter/docs/team-standards/cross-platform-team-guide.md +0 -736
- package/templates/dynamics-365-starter/docs/team-standards/development-workflows.md +0 -727
- package/templates/dynamics-365-starter/docs/troubleshooting/common-errors.md +0 -758
- package/templates/dynamics-365-starter/docs/troubleshooting/platform-specific-issues.md +0 -878
- package/templates/dynamics-365-starter/src/client-project-template/README.md +0 -234
- package/templates/dynamics-365-starter/src/client-project-template/config/client.template.json +0 -114
- package/templates/dynamics-365-starter/src/client-project-template/config/environments/template.json +0 -186
- package/templates/dynamics-365-starter/src/client-project-template/scripts/client-setup.js +0 -667
- package/templates/dynamics-365-starter/src/examples/README.md +0 -52
- package/templates/dynamics-365-starter/src/examples/component-examples/opportunity-management.tsx +0 -625
- package/templates/dynamics-365-starter/src/examples/entity-examples/opportunity-model.ts +0 -545
- package/templates/dynamics-365-starter/src/examples/integration-examples/custom-pcf-wrapper.tsx +0 -722
- package/templates/dynamics-365-starter/src/examples/workflow-examples/sales-workflow.ts +0 -662
- package/templates/dynamics-365-starter/src/page-templates/EntityDashboard.tsx +0 -519
- package/templates/dynamics-365-starter/src/page-templates/EntityDetailPage.tsx +0 -456
- package/templates/dynamics-365-starter/src/page-templates/EntityListPage.tsx +0 -406
- package/templates/dynamics-365-starter/src/page-templates/RelatedEntitiesPage.tsx +0 -578
- package/templates/dynamics-365-starter/src/page-templates/SearchPage.tsx +0 -629
- package/templates/dynamics-365-starter/tools/entity-generator/index.js +0 -168
- package/templates/dynamics-365-starter/tools/entity-generator/templates/constants.template.ts +0 -124
- package/templates/dynamics-365-starter/tools/entity-generator/templates/form.template.css +0 -283
- package/templates/dynamics-365-starter/tools/entity-generator/templates/form.template.tsx +0 -275
- package/templates/dynamics-365-starter/tools/entity-generator/templates/management.template.css +0 -204
- package/templates/dynamics-365-starter/tools/entity-generator/templates/management.template.tsx +0 -413
- package/templates/dynamics-365-starter/tools/entity-generator/templates/model.template.ts +0 -250
- package/templates/dynamics-365-starter/tools/metadata-sync/d365-client.js +0 -410
- package/templates/dynamics-365-starter/tools/metadata-sync/index.js +0 -512
- package/templates/dynamics-365-starter/tools/metadata-sync/type-generator.js +0 -675
- /package/templates/{dynamics-365-starter → react-custom-page}/README.md +0 -0
- /package/templates/{dynamics-365-starter → react-custom-page}/deployment/README.md +0 -0
- /package/templates/{dynamics-365-starter → react-custom-page}/docs/ARCHITECTURE_OVERVIEW.md +0 -0
- /package/templates/{dynamics-365-starter → react-custom-page}/docs/BEST_PRACTICES.md +0 -0
- /package/templates/{dynamics-365-starter → react-custom-page}/docs/MIGRATION_GUIDE.md +0 -0
- /package/templates/{dynamics-365-starter → react-custom-page}/public/index.html +0 -0
- /package/templates/{dynamics-365-starter → react-custom-page}/scripts/custom-build.js +0 -0
- /package/templates/{dynamics-365-starter → react-custom-page}/src/components/AccountForm.css +0 -0
- /package/templates/{dynamics-365-starter → react-custom-page}/src/components/AccountForm.tsx +0 -0
- /package/templates/{dynamics-365-starter → react-custom-page}/src/components/AccountManagement.css +0 -0
- /package/templates/{dynamics-365-starter → react-custom-page}/src/components/AccountManagement.tsx +0 -0
- /package/templates/{dynamics-365-starter → react-custom-page}/src/components/ContactForm.css +0 -0
- /package/templates/{dynamics-365-starter → react-custom-page}/src/components/ContactForm.tsx +0 -0
- /package/templates/{dynamics-365-starter → react-custom-page}/src/components/ContactManagement.css +0 -0
- /package/templates/{dynamics-365-starter → react-custom-page}/src/components/ContactManagement.tsx +0 -0
- /package/templates/{dynamics-365-starter → react-custom-page}/src/components/Logging/LogDialog.tsx +0 -0
- /package/templates/{dynamics-365-starter → react-custom-page}/src/components/Logging/LoggingContext.tsx +0 -0
- /package/templates/{dynamics-365-starter → react-custom-page}/src/components/Logging/LoggingDebugPanel.css +0 -0
- /package/templates/{dynamics-365-starter → react-custom-page}/src/components/Logging/LoggingDebugPanel.tsx +0 -0
- /package/templates/{dynamics-365-starter → react-custom-page}/src/components/Logging/LoggingProvider.tsx +0 -0
- /package/templates/{dynamics-365-starter → react-custom-page}/src/components/Logging/logger.ts +0 -0
- /package/templates/{dynamics-365-starter → react-custom-page}/src/constants/account.ts +0 -0
- /package/templates/{dynamics-365-starter → react-custom-page}/src/constants/contact.ts +0 -0
- /package/templates/{dynamics-365-starter → react-custom-page}/src/index.tsx +0 -0
- /package/templates/{dynamics-365-starter → react-custom-page}/src/models/Account.ts +0 -0
- /package/templates/{dynamics-365-starter → react-custom-page}/src/models/BaseEntity.ts +0 -0
- /package/templates/{dynamics-365-starter → react-custom-page}/src/models/Contact.ts +0 -0
- /package/templates/{dynamics-365-starter → react-custom-page}/src/pcf/ContactControlWrapper.tsx +0 -0
- /package/templates/{dynamics-365-starter → react-custom-page}/src/pcf/MultiEntityControlWrapper.tsx +0 -0
- /package/templates/{dynamics-365-starter → react-custom-page}/src/providers/DynamicsProvider.tsx +0 -0
- /package/templates/{dynamics-365-starter → react-custom-page}/src/services/MockApiService.ts +0 -0
- /package/templates/{dynamics-365-starter → react-custom-page}/src/services/ServiceFactory.ts +0 -0
- /package/templates/{dynamics-365-starter → react-custom-page}/src/services/XrmApiService.ts +0 -0
- /package/templates/{dynamics-365-starter → react-custom-page}/src/styles/index.css +0 -0
- /package/templates/{dynamics-365-starter → react-custom-page}/tsconfig.json +0 -0
- /package/templates/{dynamics-365-starter → react-custom-page}/webpack.config.js +0 -0
|
@@ -1,545 +0,0 @@
|
|
|
1
|
-
/**
|
|
2
|
-
* Example: Creating a custom Opportunity entity model
|
|
3
|
-
*
|
|
4
|
-
* This example demonstrates how to extend the BaseEntity pattern
|
|
5
|
-
* to create a new entity model with validation, CRUD operations,
|
|
6
|
-
* and integration with the ServiceFactory and logging system.
|
|
7
|
-
*
|
|
8
|
-
* @example
|
|
9
|
-
* ```typescript
|
|
10
|
-
* // Create a new opportunity
|
|
11
|
-
* const opportunity = new Opportunity({
|
|
12
|
-
* name: 'New Sales Opportunity',
|
|
13
|
-
* estimatedvalue: 50000,
|
|
14
|
-
* closeprobability: 75
|
|
15
|
-
* });
|
|
16
|
-
*
|
|
17
|
-
* // Validate and save
|
|
18
|
-
* opportunity.validate();
|
|
19
|
-
* const saved = await Opportunity.create(apiService, opportunity);
|
|
20
|
-
* ```
|
|
21
|
-
*/
|
|
22
|
-
|
|
23
|
-
import { IApiService } from '@khester/dynamics-ui-api-client';
|
|
24
|
-
import { BaseEntity } from '../../models/BaseEntity';
|
|
25
|
-
|
|
26
|
-
/**
|
|
27
|
-
* Opportunity entity interface
|
|
28
|
-
* Define all properties that the Opportunity entity can have
|
|
29
|
-
*/
|
|
30
|
-
export interface IOpportunity {
|
|
31
|
-
/** Unique identifier for the opportunity */
|
|
32
|
-
opportunityid?: string;
|
|
33
|
-
|
|
34
|
-
/** Opportunity name (required) */
|
|
35
|
-
name: string;
|
|
36
|
-
|
|
37
|
-
/** Estimated value of the opportunity */
|
|
38
|
-
estimatedvalue?: number;
|
|
39
|
-
|
|
40
|
-
/** Close probability percentage (0-100) */
|
|
41
|
-
closeprobability?: number;
|
|
42
|
-
|
|
43
|
-
/** Expected close date */
|
|
44
|
-
estimatedclosedate?: string;
|
|
45
|
-
|
|
46
|
-
/** Opportunity description */
|
|
47
|
-
description?: string;
|
|
48
|
-
|
|
49
|
-
/** Associated account ID */
|
|
50
|
-
parentaccountid?: string;
|
|
51
|
-
|
|
52
|
-
/** Associated contact ID */
|
|
53
|
-
parentcontactid?: string;
|
|
54
|
-
|
|
55
|
-
/** Sales stage option set value */
|
|
56
|
-
salesstagecode?: number;
|
|
57
|
-
|
|
58
|
-
/** Opportunity status (open/won/lost) */
|
|
59
|
-
statecode?: number;
|
|
60
|
-
|
|
61
|
-
/** Detailed status reason */
|
|
62
|
-
statuscode?: number;
|
|
63
|
-
|
|
64
|
-
/** Created date */
|
|
65
|
-
createdon?: string;
|
|
66
|
-
|
|
67
|
-
/** Modified date */
|
|
68
|
-
modifiedon?: string;
|
|
69
|
-
|
|
70
|
-
/** Owner ID */
|
|
71
|
-
ownerid?: string;
|
|
72
|
-
}
|
|
73
|
-
|
|
74
|
-
/**
|
|
75
|
-
* Opportunity entity constants
|
|
76
|
-
* Following the same pattern as AccountConstants and ContactConstants
|
|
77
|
-
*/
|
|
78
|
-
export class OpportunityConstants {
|
|
79
|
-
/** Entity name for single opportunity */
|
|
80
|
-
public static readonly EntityName: string = 'opportunity';
|
|
81
|
-
|
|
82
|
-
/** Entity collection name for multiple opportunities */
|
|
83
|
-
public static readonly EntityCollectionName: string = 'opportunities';
|
|
84
|
-
|
|
85
|
-
/** Primary key field */
|
|
86
|
-
public static readonly PrimaryKey: string = 'opportunityid';
|
|
87
|
-
|
|
88
|
-
/** Primary name field */
|
|
89
|
-
public static readonly PrimaryName: string = 'name';
|
|
90
|
-
|
|
91
|
-
/** Estimated value field */
|
|
92
|
-
public static readonly EstimatedValue: string = 'estimatedvalue';
|
|
93
|
-
|
|
94
|
-
/** Close probability field */
|
|
95
|
-
public static readonly CloseProbability: string = 'closeprobability';
|
|
96
|
-
|
|
97
|
-
/** Estimated close date field */
|
|
98
|
-
public static readonly EstimatedCloseDate: string = 'estimatedclosedate';
|
|
99
|
-
|
|
100
|
-
/** Description field */
|
|
101
|
-
public static readonly Description: string = 'description';
|
|
102
|
-
|
|
103
|
-
/** Parent account reference */
|
|
104
|
-
public static readonly ParentAccountId: string = 'parentaccountid';
|
|
105
|
-
|
|
106
|
-
/** Parent contact reference */
|
|
107
|
-
public static readonly ParentContactId: string = 'parentcontactid';
|
|
108
|
-
|
|
109
|
-
/** Sales stage code */
|
|
110
|
-
public static readonly SalesStageCode: string = 'salesstagecode';
|
|
111
|
-
|
|
112
|
-
/** State code (Active/Inactive) */
|
|
113
|
-
public static readonly StateCode: string = 'statecode';
|
|
114
|
-
|
|
115
|
-
/** Status code (detailed status) */
|
|
116
|
-
public static readonly StatusCode: string = 'statuscode';
|
|
117
|
-
|
|
118
|
-
/** Created date */
|
|
119
|
-
public static readonly CreatedOn: string = 'createdon';
|
|
120
|
-
|
|
121
|
-
/** Modified date */
|
|
122
|
-
public static readonly ModifiedOn: string = 'modifiedon';
|
|
123
|
-
|
|
124
|
-
/** Owner ID */
|
|
125
|
-
public static readonly OwnerId: string = 'ownerid';
|
|
126
|
-
}
|
|
127
|
-
|
|
128
|
-
/**
|
|
129
|
-
* Sales Stage Option Set Values
|
|
130
|
-
*/
|
|
131
|
-
export enum SalesStageCode_OptionSet {
|
|
132
|
-
Qualify = 0,
|
|
133
|
-
Develop = 1,
|
|
134
|
-
Propose = 2,
|
|
135
|
-
Close = 3,
|
|
136
|
-
}
|
|
137
|
-
|
|
138
|
-
/**
|
|
139
|
-
* Opportunity State Code Option Set
|
|
140
|
-
*/
|
|
141
|
-
export enum OpportunityStateCode_OptionSet {
|
|
142
|
-
Open = 0,
|
|
143
|
-
Won = 1,
|
|
144
|
-
Lost = 2,
|
|
145
|
-
}
|
|
146
|
-
|
|
147
|
-
/**
|
|
148
|
-
* Opportunity Status Code Option Set
|
|
149
|
-
*/
|
|
150
|
-
export enum OpportunityStatusCode_OptionSet {
|
|
151
|
-
InProgress = 1,
|
|
152
|
-
OnHold = 2,
|
|
153
|
-
Won = 3,
|
|
154
|
-
Canceled = 4,
|
|
155
|
-
OutSold = 5,
|
|
156
|
-
}
|
|
157
|
-
|
|
158
|
-
/**
|
|
159
|
-
* Opportunity entity model class
|
|
160
|
-
*
|
|
161
|
-
* Extends BaseEntity to provide CRUD operations, validation,
|
|
162
|
-
* and integration with the logging system.
|
|
163
|
-
*
|
|
164
|
-
* @example
|
|
165
|
-
* ```typescript
|
|
166
|
-
* // Create and validate an opportunity
|
|
167
|
-
* const opp = new Opportunity({
|
|
168
|
-
* name: 'Q1 Software License Deal',
|
|
169
|
-
* estimatedvalue: 75000,
|
|
170
|
-
* closeprobability: 80,
|
|
171
|
-
* estimatedclosedate: '2024-03-31'
|
|
172
|
-
* });
|
|
173
|
-
*
|
|
174
|
-
* // Validation happens automatically
|
|
175
|
-
* const isValid = opp.validate();
|
|
176
|
-
*
|
|
177
|
-
* // Save to Dynamics 365
|
|
178
|
-
* const savedOpp = await Opportunity.create(apiService, opp);
|
|
179
|
-
* ```
|
|
180
|
-
*/
|
|
181
|
-
export class Opportunity extends BaseEntity implements IOpportunity {
|
|
182
|
-
opportunityid?: string;
|
|
183
|
-
name: string;
|
|
184
|
-
estimatedvalue?: number;
|
|
185
|
-
closeprobability?: number;
|
|
186
|
-
estimatedclosedate?: string;
|
|
187
|
-
description?: string;
|
|
188
|
-
parentaccountid?: string;
|
|
189
|
-
parentcontactid?: string;
|
|
190
|
-
salesstagecode?: number;
|
|
191
|
-
statecode?: number;
|
|
192
|
-
statuscode?: number;
|
|
193
|
-
createdon?: string;
|
|
194
|
-
modifiedon?: string;
|
|
195
|
-
ownerid?: string;
|
|
196
|
-
|
|
197
|
-
/**
|
|
198
|
-
* Constructor for Opportunity entity
|
|
199
|
-
* @param opportunity - The opportunity data to initialize with
|
|
200
|
-
*/
|
|
201
|
-
constructor(opportunity: IOpportunity) {
|
|
202
|
-
super();
|
|
203
|
-
this.opportunityid = opportunity.opportunityid;
|
|
204
|
-
this.name = opportunity.name;
|
|
205
|
-
this.estimatedvalue = opportunity.estimatedvalue;
|
|
206
|
-
this.closeprobability = opportunity.closeprobability;
|
|
207
|
-
this.estimatedclosedate = opportunity.estimatedclosedate;
|
|
208
|
-
this.description = opportunity.description;
|
|
209
|
-
this.parentaccountid = opportunity.parentaccountid;
|
|
210
|
-
this.parentcontactid = opportunity.parentcontactid;
|
|
211
|
-
this.salesstagecode = opportunity.salesstagecode;
|
|
212
|
-
this.statecode = opportunity.statecode;
|
|
213
|
-
this.statuscode = opportunity.statuscode;
|
|
214
|
-
this.createdon = opportunity.createdon;
|
|
215
|
-
this.modifiedon = opportunity.modifiedon;
|
|
216
|
-
this.ownerid = opportunity.ownerid;
|
|
217
|
-
}
|
|
218
|
-
|
|
219
|
-
/**
|
|
220
|
-
* Validates the opportunity instance
|
|
221
|
-
* @returns True if valid, throws error if invalid
|
|
222
|
-
* @throws Error with validation message if validation fails
|
|
223
|
-
*
|
|
224
|
-
* @example
|
|
225
|
-
* ```typescript
|
|
226
|
-
* try {
|
|
227
|
-
* opportunity.validate();
|
|
228
|
-
* console.log('Opportunity is valid');
|
|
229
|
-
* } catch (error) {
|
|
230
|
-
* console.error('Validation failed:', error.message);
|
|
231
|
-
* }
|
|
232
|
-
* ```
|
|
233
|
-
*/
|
|
234
|
-
validate(): boolean {
|
|
235
|
-
if (!this.name || this.name.trim().length === 0) {
|
|
236
|
-
throw new Error('Opportunity name is required');
|
|
237
|
-
}
|
|
238
|
-
|
|
239
|
-
if (this.name.length > 300) {
|
|
240
|
-
throw new Error('Opportunity name cannot exceed 300 characters');
|
|
241
|
-
}
|
|
242
|
-
|
|
243
|
-
if (this.estimatedvalue !== undefined && this.estimatedvalue < 0) {
|
|
244
|
-
throw new Error('Estimated value cannot be negative');
|
|
245
|
-
}
|
|
246
|
-
|
|
247
|
-
if (this.closeprobability !== undefined) {
|
|
248
|
-
if (this.closeprobability < 0 || this.closeprobability > 100) {
|
|
249
|
-
throw new Error('Close probability must be between 0 and 100');
|
|
250
|
-
}
|
|
251
|
-
}
|
|
252
|
-
|
|
253
|
-
if (this.estimatedclosedate) {
|
|
254
|
-
const closeDate = new Date(this.estimatedclosedate);
|
|
255
|
-
const today = new Date();
|
|
256
|
-
if (closeDate < today) {
|
|
257
|
-
throw new Error('Estimated close date cannot be in the past');
|
|
258
|
-
}
|
|
259
|
-
}
|
|
260
|
-
|
|
261
|
-
return true;
|
|
262
|
-
}
|
|
263
|
-
|
|
264
|
-
/**
|
|
265
|
-
* Creates a new opportunity record
|
|
266
|
-
* @param apiService - The API service instance
|
|
267
|
-
* @param opportunity - The opportunity to create
|
|
268
|
-
* @returns Promise resolving to the created opportunity
|
|
269
|
-
*
|
|
270
|
-
* @example
|
|
271
|
-
* ```typescript
|
|
272
|
-
* const newOpportunity = new Opportunity({
|
|
273
|
-
* name: 'Enterprise Software Deal',
|
|
274
|
-
* estimatedvalue: 100000,
|
|
275
|
-
* closeprobability: 70
|
|
276
|
-
* });
|
|
277
|
-
*
|
|
278
|
-
* const created = await Opportunity.create(apiService, newOpportunity);
|
|
279
|
-
* console.log('Created opportunity:', created.opportunityid);
|
|
280
|
-
* ```
|
|
281
|
-
*/
|
|
282
|
-
public static async create(
|
|
283
|
-
apiService: IApiService,
|
|
284
|
-
opportunity: Opportunity
|
|
285
|
-
): Promise<Opportunity> {
|
|
286
|
-
const loggerContext = 'Opportunity.create';
|
|
287
|
-
console.log(`${loggerContext}: Creating new opportunity`, {
|
|
288
|
-
name: opportunity.name,
|
|
289
|
-
});
|
|
290
|
-
|
|
291
|
-
return await this.createEntity<Opportunity>(
|
|
292
|
-
apiService,
|
|
293
|
-
opportunity,
|
|
294
|
-
OpportunityConstants.EntityCollectionName,
|
|
295
|
-
loggerContext
|
|
296
|
-
);
|
|
297
|
-
}
|
|
298
|
-
|
|
299
|
-
/**
|
|
300
|
-
* Updates an existing opportunity record
|
|
301
|
-
* @param apiService - The API service instance
|
|
302
|
-
* @param opportunity - The opportunity to update
|
|
303
|
-
* @returns Promise resolving to the updated opportunity
|
|
304
|
-
*
|
|
305
|
-
* @example
|
|
306
|
-
* ```typescript
|
|
307
|
-
* // Load existing opportunity
|
|
308
|
-
* const opportunity = await Opportunity.retrieveById(apiService, opportunityId);
|
|
309
|
-
*
|
|
310
|
-
* // Update properties
|
|
311
|
-
* opportunity.closeprobability = 90;
|
|
312
|
-
* opportunity.salesstagecode = SalesStageCode_OptionSet.Close;
|
|
313
|
-
*
|
|
314
|
-
* // Save changes
|
|
315
|
-
* const updated = await Opportunity.update(apiService, opportunity);
|
|
316
|
-
* ```
|
|
317
|
-
*/
|
|
318
|
-
public static async update(
|
|
319
|
-
apiService: IApiService,
|
|
320
|
-
opportunity: Opportunity
|
|
321
|
-
): Promise<Opportunity> {
|
|
322
|
-
const loggerContext = 'Opportunity.update';
|
|
323
|
-
|
|
324
|
-
if (!opportunity.opportunityid) {
|
|
325
|
-
throw new Error('Opportunity ID is required for update');
|
|
326
|
-
}
|
|
327
|
-
|
|
328
|
-
console.log(`${loggerContext}: Updating opportunity`, {
|
|
329
|
-
opportunityid: opportunity.opportunityid,
|
|
330
|
-
name: opportunity.name,
|
|
331
|
-
});
|
|
332
|
-
|
|
333
|
-
return await this.updateEntity<Opportunity>(
|
|
334
|
-
apiService,
|
|
335
|
-
opportunity.opportunityid,
|
|
336
|
-
opportunity,
|
|
337
|
-
OpportunityConstants.EntityCollectionName,
|
|
338
|
-
OpportunityConstants.PrimaryKey,
|
|
339
|
-
loggerContext
|
|
340
|
-
);
|
|
341
|
-
}
|
|
342
|
-
|
|
343
|
-
/**
|
|
344
|
-
* Deletes an opportunity record
|
|
345
|
-
* @param apiService - The API service instance
|
|
346
|
-
* @param opportunityId - The ID of the opportunity to delete
|
|
347
|
-
* @returns Promise resolving when deletion is complete
|
|
348
|
-
*
|
|
349
|
-
* @example
|
|
350
|
-
* ```typescript
|
|
351
|
-
* await Opportunity.delete(apiService, opportunityId);
|
|
352
|
-
* console.log('Opportunity deleted successfully');
|
|
353
|
-
* ```
|
|
354
|
-
*/
|
|
355
|
-
public static async delete(
|
|
356
|
-
apiService: IApiService,
|
|
357
|
-
opportunityId: string
|
|
358
|
-
): Promise<void> {
|
|
359
|
-
const loggerContext = 'Opportunity.delete';
|
|
360
|
-
console.log(`${loggerContext}: Deleting opportunity`, {
|
|
361
|
-
opportunityid: opportunityId,
|
|
362
|
-
});
|
|
363
|
-
|
|
364
|
-
return await this.deleteEntity(
|
|
365
|
-
apiService,
|
|
366
|
-
opportunityId,
|
|
367
|
-
OpportunityConstants.EntityCollectionName,
|
|
368
|
-
loggerContext
|
|
369
|
-
);
|
|
370
|
-
}
|
|
371
|
-
|
|
372
|
-
/**
|
|
373
|
-
* Retrieves opportunities based on a filter
|
|
374
|
-
* @param apiService - The API service instance
|
|
375
|
-
* @param filter - Optional FetchXML filter string
|
|
376
|
-
* @returns Promise resolving to an array of opportunities
|
|
377
|
-
*
|
|
378
|
-
* @example
|
|
379
|
-
* ```typescript
|
|
380
|
-
* // Get all high-value opportunities
|
|
381
|
-
* const filter = `<filter type="and">
|
|
382
|
-
* <condition attribute="estimatedvalue" operator="ge" value="50000" />
|
|
383
|
-
* <condition attribute="statecode" operator="eq" value="0" />
|
|
384
|
-
* </filter>`;
|
|
385
|
-
*
|
|
386
|
-
* const opportunities = await Opportunity.retrieveByFilter(apiService, filter);
|
|
387
|
-
* ```
|
|
388
|
-
*/
|
|
389
|
-
public static async retrieveByFilter(
|
|
390
|
-
apiService: IApiService,
|
|
391
|
-
filter?: string
|
|
392
|
-
): Promise<Opportunity[]> {
|
|
393
|
-
const loggerContext = 'Opportunity.retrieveByFilter';
|
|
394
|
-
console.log(`${loggerContext}: Retrieving opportunities with filter`, {
|
|
395
|
-
filter,
|
|
396
|
-
});
|
|
397
|
-
|
|
398
|
-
const attributes = [
|
|
399
|
-
OpportunityConstants.PrimaryKey,
|
|
400
|
-
OpportunityConstants.PrimaryName,
|
|
401
|
-
OpportunityConstants.EstimatedValue,
|
|
402
|
-
OpportunityConstants.CloseProbability,
|
|
403
|
-
OpportunityConstants.EstimatedCloseDate,
|
|
404
|
-
OpportunityConstants.Description,
|
|
405
|
-
OpportunityConstants.ParentAccountId,
|
|
406
|
-
OpportunityConstants.ParentContactId,
|
|
407
|
-
OpportunityConstants.SalesStageCode,
|
|
408
|
-
OpportunityConstants.StateCode,
|
|
409
|
-
OpportunityConstants.StatusCode,
|
|
410
|
-
OpportunityConstants.CreatedOn,
|
|
411
|
-
OpportunityConstants.ModifiedOn,
|
|
412
|
-
OpportunityConstants.OwnerId,
|
|
413
|
-
];
|
|
414
|
-
|
|
415
|
-
const fetchXml = this.buildFetchXml(
|
|
416
|
-
OpportunityConstants.EntityName,
|
|
417
|
-
attributes,
|
|
418
|
-
filter,
|
|
419
|
-
{ attribute: OpportunityConstants.PrimaryName }
|
|
420
|
-
);
|
|
421
|
-
|
|
422
|
-
return await this.retrieveEntitiesByFilter<Opportunity>(
|
|
423
|
-
apiService,
|
|
424
|
-
OpportunityConstants.EntityCollectionName,
|
|
425
|
-
fetchXml,
|
|
426
|
-
Opportunity,
|
|
427
|
-
loggerContext
|
|
428
|
-
);
|
|
429
|
-
}
|
|
430
|
-
|
|
431
|
-
/**
|
|
432
|
-
* Retrieves a single opportunity by ID
|
|
433
|
-
* @param apiService - The API service instance
|
|
434
|
-
* @param opportunityId - The opportunity ID
|
|
435
|
-
* @returns Promise resolving to the opportunity or null if not found
|
|
436
|
-
*
|
|
437
|
-
* @example
|
|
438
|
-
* ```typescript
|
|
439
|
-
* const opportunity = await Opportunity.retrieveById(apiService, 'guid-here');
|
|
440
|
-
* if (opportunity) {
|
|
441
|
-
* console.log('Found opportunity:', opportunity.name);
|
|
442
|
-
* }
|
|
443
|
-
* ```
|
|
444
|
-
*/
|
|
445
|
-
public static async retrieveById(
|
|
446
|
-
apiService: IApiService,
|
|
447
|
-
opportunityId: string
|
|
448
|
-
): Promise<Opportunity | null> {
|
|
449
|
-
const loggerContext = 'Opportunity.retrieveById';
|
|
450
|
-
console.log(`${loggerContext}: Retrieving opportunity by ID`, {
|
|
451
|
-
opportunityid: opportunityId,
|
|
452
|
-
});
|
|
453
|
-
|
|
454
|
-
const filter = `<filter type="and">
|
|
455
|
-
<condition attribute="${OpportunityConstants.PrimaryKey}" operator="eq" value="${this.escapeXml(opportunityId)}" />
|
|
456
|
-
</filter>`;
|
|
457
|
-
|
|
458
|
-
const opportunities = await this.retrieveByFilter(apiService, filter);
|
|
459
|
-
return opportunities.length > 0 ? opportunities[0] : null;
|
|
460
|
-
}
|
|
461
|
-
|
|
462
|
-
/**
|
|
463
|
-
* Retrieves active opportunities only
|
|
464
|
-
* @param apiService - The API service instance
|
|
465
|
-
* @returns Promise resolving to an array of active opportunities
|
|
466
|
-
*
|
|
467
|
-
* @example
|
|
468
|
-
* ```typescript
|
|
469
|
-
* const activeOpportunities = await Opportunity.retrieveActiveOpportunities(apiService);
|
|
470
|
-
* console.log(`Found ${activeOpportunities.length} active opportunities`);
|
|
471
|
-
* ```
|
|
472
|
-
*/
|
|
473
|
-
public static async retrieveActiveOpportunities(
|
|
474
|
-
apiService: IApiService
|
|
475
|
-
): Promise<Opportunity[]> {
|
|
476
|
-
const loggerContext = 'Opportunity.retrieveActiveOpportunities';
|
|
477
|
-
console.log(`${loggerContext}: Retrieving active opportunities`);
|
|
478
|
-
|
|
479
|
-
const filter = `<filter type="and">
|
|
480
|
-
<condition attribute="${OpportunityConstants.StateCode}" operator="eq" value="0" />
|
|
481
|
-
</filter>`;
|
|
482
|
-
|
|
483
|
-
return await this.retrieveByFilter(apiService, filter);
|
|
484
|
-
}
|
|
485
|
-
|
|
486
|
-
/**
|
|
487
|
-
* Retrieves opportunities by sales stage
|
|
488
|
-
* @param apiService - The API service instance
|
|
489
|
-
* @param salesStage - The sales stage to filter by
|
|
490
|
-
* @returns Promise resolving to an array of opportunities in the specified stage
|
|
491
|
-
*
|
|
492
|
-
* @example
|
|
493
|
-
* ```typescript
|
|
494
|
-
* const proposalStageOpps = await Opportunity.retrieveBySalesStage(
|
|
495
|
-
* apiService,
|
|
496
|
-
* SalesStageCode_OptionSet.Propose
|
|
497
|
-
* );
|
|
498
|
-
* ```
|
|
499
|
-
*/
|
|
500
|
-
public static async retrieveBySalesStage(
|
|
501
|
-
apiService: IApiService,
|
|
502
|
-
salesStage: SalesStageCode_OptionSet
|
|
503
|
-
): Promise<Opportunity[]> {
|
|
504
|
-
const loggerContext = 'Opportunity.retrieveBySalesStage';
|
|
505
|
-
console.log(`${loggerContext}: Retrieving opportunities by sales stage`, {
|
|
506
|
-
salesStage,
|
|
507
|
-
});
|
|
508
|
-
|
|
509
|
-
const filter = `<filter type="and">
|
|
510
|
-
<condition attribute="${OpportunityConstants.SalesStageCode}" operator="eq" value="${salesStage}" />
|
|
511
|
-
<condition attribute="${OpportunityConstants.StateCode}" operator="eq" value="0" />
|
|
512
|
-
</filter>`;
|
|
513
|
-
|
|
514
|
-
return await this.retrieveByFilter(apiService, filter);
|
|
515
|
-
}
|
|
516
|
-
|
|
517
|
-
/**
|
|
518
|
-
* Retrieves opportunities by account
|
|
519
|
-
* @param apiService - The API service instance
|
|
520
|
-
* @param accountId - The account ID to filter by
|
|
521
|
-
* @returns Promise resolving to an array of opportunities for the specified account
|
|
522
|
-
*
|
|
523
|
-
* @example
|
|
524
|
-
* ```typescript
|
|
525
|
-
* const accountOpportunities = await Opportunity.retrieveByAccount(apiService, accountId);
|
|
526
|
-
* console.log(`Account has ${accountOpportunities.length} opportunities`);
|
|
527
|
-
* ```
|
|
528
|
-
*/
|
|
529
|
-
public static async retrieveByAccount(
|
|
530
|
-
apiService: IApiService,
|
|
531
|
-
accountId: string
|
|
532
|
-
): Promise<Opportunity[]> {
|
|
533
|
-
const loggerContext = 'Opportunity.retrieveByAccount';
|
|
534
|
-
console.log(`${loggerContext}: Retrieving opportunities by account`, {
|
|
535
|
-
accountId,
|
|
536
|
-
});
|
|
537
|
-
|
|
538
|
-
const filter = `<filter type="and">
|
|
539
|
-
<condition attribute="${OpportunityConstants.ParentAccountId}" operator="eq" value="${this.escapeXml(accountId)}" />
|
|
540
|
-
<condition attribute="${OpportunityConstants.StateCode}" operator="eq" value="0" />
|
|
541
|
-
</filter>`;
|
|
542
|
-
|
|
543
|
-
return await this.retrieveByFilter(apiService, filter);
|
|
544
|
-
}
|
|
545
|
-
}
|