spitfirepm 23.9700.7 → 23.9700.9

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 CHANGED
@@ -25,6 +25,8 @@ apiResult.then( (a) => {
25
25
  ### Change Log
26
26
 
27
27
  ```
28
+ 23.9700.9 - QueryCatalog and improve Attachment and Contact endpoints
29
+ 23.9700.8 - Improved ContactClient endpoints
28
30
  23.9700.7 - GetDV method clarifications
29
31
  23.9700.6 - Audit History Model enhanced
30
32
  23.9700.5 - Lookup Editor Endpoints
@@ -1310,7 +1310,7 @@ export declare class ConfigClient extends APIClientBase {
1310
1310
  private processTestLookupResultWithCallbacks;
1311
1311
  protected processTestLookupResult(xhr: any): LookupTestResult | null | null;
1312
1312
  /**
1313
- * Returns the Lookups (pickers)
1313
+ * Returns the Lookups (pickers). Users without LookupEditor permission only see 'Agent' lookups.
1314
1314
  */
1315
1315
  getLookups(): Promise<Lookup[] | null>;
1316
1316
  private getLookupsWithCallbacks;
@@ -1342,7 +1342,7 @@ export declare class ConfigClient extends APIClientBase {
1342
1342
  private processCopyLookupWithCallbacks;
1343
1343
  protected processCopyLookup(xhr: any): Lookup | null | null;
1344
1344
  /**
1345
- * Returns the fields of one Lookup
1345
+ * Returns the fields of one Lookup. Non LookupEditor users only see PredicateMode=I.
1346
1346
  * @param lookupKey Lookup key
1347
1347
  */
1348
1348
  getLookupFields(lookupKey: string): Promise<LookupField[] | null>;
@@ -1373,6 +1373,21 @@ export declare class ConfigClient extends APIClientBase {
1373
1373
  private getManageToolsWithCallbacks;
1374
1374
  private processGetManageToolsWithCallbacks;
1375
1375
  protected processGetManageTools(xhr: any): MenuAction[] | null | null;
1376
+ /**
1377
+ * Returns the dynamic queries this site defines, each with its parameters
1378
+ */
1379
+ getQueries(): Promise<QueryDefinition[] | null>;
1380
+ private getQueriesWithCallbacks;
1381
+ private processGetQueriesWithCallbacks;
1382
+ protected processGetQueries(xhr: any): QueryDefinition[] | null | null;
1383
+ /**
1384
+ * Returns one dynamic query definition with its parameters
1385
+ * @param queryName Query name, e.g. qUserActivitySummary
1386
+ */
1387
+ getQuery(queryName: string | null): Promise<QueryDefinition | null>;
1388
+ private getQueryWithCallbacks;
1389
+ private processGetQueryWithCallbacks;
1390
+ protected processGetQuery(xhr: any): QueryDefinition | null | null;
1376
1391
  /**
1377
1392
  * Returns the list of regions
1378
1393
  */
@@ -1685,8 +1700,8 @@ export declare class DocumentToolsClient extends APIClientBase {
1685
1700
  * @param id Document Key (use empty for auto assign)
1686
1701
  * @param typeKey Type
1687
1702
  * @param forProject (optional) Project
1688
- * @param forParent (optional) Parent Doc Key (NextDocFlow rules apply; See https://support.spitfirepm.com/kba-01517/)
1689
- * @param forBatch (optional) Batch/Subcontract
1703
+ * @param forParent (optional) Parent Doc Key (NextDocFlow rules apply; See https://support.spitfirepm.com/kba-01517/). When the parent is a commitment, its subcontract number is used and its lines are brought in
1704
+ * @param forBatch (optional) Batch/Subcontract. Naming a commitment here brings in its lines, same as forParent
1690
1705
  * @param forSourceContact (optional) Source Contact
1691
1706
  */
1692
1707
  createDocument(id: string, typeKey: string, forProject?: string | null | undefined, forParent?: string | null | undefined, forBatch?: string | null | undefined, forSourceContact?: string | null | undefined): Promise<string>;
@@ -1948,7 +1963,7 @@ export declare class DocumentToolsClient extends APIClientBase {
1948
1963
  private processGetChangedItemsWithCallbacks;
1949
1964
  protected processGetChangedItems(xhr: any): DataDifferential | null;
1950
1965
  /**
1951
- * Returns the comments for the specified document
1966
+ * Returns the comments for the specified document, most recent first.
1952
1967
  * @param id Document Key
1953
1968
  */
1954
1969
  getDocComments(id: string): Promise<Comment[] | null>;
@@ -1976,7 +1991,7 @@ export declare class DocumentToolsClient extends APIClientBase {
1976
1991
  private processUpdateDocCommentsWithCallbacks;
1977
1992
  protected processUpdateDocComments(xhr: any): string | null;
1978
1993
  /**
1979
- * Inserts Comments on the specified document
1994
+ * Inserts Comments on the specified document. Typically TopicKey=DocRevKey because comments are associated with the Doc Revision. You can specify the empty GUID for TopicKey and/or FromUser, the correct defaults will be supplied (the current Revision and the current user). Other values for TopicKey must resolve to this document (for example, a prior revision comment). Any value for created more than 5 days ago stamps the comment with the server time. FromUser is set automatically.
1980
1995
  * @param id Document Key
1981
1996
  * @param newData New comment data
1982
1997
  */
@@ -4661,27 +4676,42 @@ export interface ContactFilters {
4661
4676
  CSIListLike?: string | undefined;
4662
4677
  /** Phone Like (matches any phone number) */
4663
4678
  PhoneLike?: string | undefined;
4664
- /** When true, result is limited to */
4679
+ /** When true, result is limited to contacts who can log in to sfPMS (sfUser=1).
4680
+ These six flags COMBINE WITH AND, not OR - see the remarks on this class. */
4665
4681
  Users?: boolean;
4666
- /** When true, result is limited to */
4682
+ /** When true, result is limited to customer contacts (ContactType='C'). */
4667
4683
  Customers?: boolean;
4668
- /** When true, result is limited to */
4684
+ /** When true, result is limited to employees (ContactType='E'). */
4669
4685
  Employee?: boolean;
4670
- /** When true, result is limited to */
4686
+ /** When true, result is limited to public contacts (IsPublic=1). Rare. */
4671
4687
  Public?: boolean;
4672
- /** When true, result is limited to primary company contacts */
4688
+ /** When true, result is limited to primary company contacts - the company itself
4689
+ rather than a person at it (xsfContactCompany.PrimaryContactKey). */
4673
4690
  Company?: boolean;
4674
- /** When true, result is limited to */
4691
+ /** When true, result is limited to vendor contacts (ContactType='V', or any contact
4692
+ carrying a VendorID). */
4675
4693
  Vendors?: boolean;
4676
- /** 1==Active;0==Inactive; 2==Both */
4677
- ContactState?: number;
4694
+ /** 1==Active; 0==Inactive; 2==Both. Omit (null) for active only.
4695
+ Null and 1 are the same thing. The nullability exists because this is a
4696
+ short: before it was nullable a caller who simply left the field out sent 0 and
4697
+ silently got INACTIVE contacts, which is nobody's intent. Callers that already send an
4698
+ explicit 0, 1 or 2 are unaffected. */
4699
+ ContactState?: number | undefined;
4678
4700
  /** UCRole Key, or use 00000000-0000-0000-0000-000000000000 for unspecified */
4679
4701
  RoleKey?: string | undefined;
4680
4702
  /** Use 00000000-0000-0000-0000-000000000000 for unspecified */
4681
4703
  UserKey?: string | undefined;
4682
- /** Default 2000-01-01 */
4704
+ /** Earliest LastLogin to include. Omit for no lower bound.
4705
+ THIS IS A LOGIN-DATE FILTER, and supplying either bound therefore limits the
4706
+ result to contacts who have signed in at least once - which in practice means system
4707
+ users, since only they have a LastLogin at all. Contacts that have NEVER logged in
4708
+ have no LastLogin and so satisfy no range; if "never signed in" is part of the question,
4709
+ ask for it without a date bound and look for a null LastLogin on the rows. */
4683
4710
  FromDate?: Date | undefined;
4684
- /** Default today */
4711
+ /** Latest LastLogin to include. Omit for no upper bound.
4712
+ Inclusive. A date with no time component covers the whole of that day, so
4713
+ ThruDate 2026-02-04 includes a login at 2026-02-04 16:20. See FromDate
4714
+ for what a login-date bound does to the result set. */
4685
4715
  ThruDate?: Date | undefined;
4686
4716
  }
4687
4717
  /** Summary information about a contact */
@@ -4710,6 +4740,14 @@ export interface ContactSummary {
4710
4740
  Company?: string | undefined;
4711
4741
  /** For Vendors, indicate related CSI */
4712
4742
  CSIList?: string | undefined;
4743
+ /** Readonly. Specifies when this user last logged in. Kept for inactive and former users.
4744
+ NULL means never signed in, and that is a different fact from "signed in a long
4745
+ time ago" - for a seat-licensing question it is usually the more actionable one.
4746
+ Nullable for exactly that reason: as a plain DateTime a never-logged-in contact
4747
+ serialises as 0001-01-01, which reads like a date and buckets like an ancient login.
4748
+ Matches Contact.LastLogin, which is already nullable.
4749
+ Only contacts who can log in (sfUser=1) ever carry a value here. */
4750
+ LastLogin?: Date | undefined;
4713
4751
  /** When false, this row is ignored and ineffective */
4714
4752
  Active?: boolean;
4715
4753
  /** When true, there are no references to this contact */
@@ -8096,6 +8134,57 @@ export interface ProjKPIFact {
8096
8134
  /** UI CFG Item Name */
8097
8135
  ItemName?: string | undefined;
8098
8136
  }
8137
+ /** Describes one dynamic query a site can run - what it answers, what it needs, and who may see it. This is the catalog entry for a query executed through api/query/{queryName}/{dataContext}. */
8138
+ export interface QueryDefinition {
8139
+ /** Name of the query, unique within the rule, and the value passed to api/query. By
8140
+ convention these begin with a lower case q */
8141
+ QueryName: string;
8142
+ /** Document type this definition applies to, or null when it applies everywhere. A site
8143
+ may define the same query name differently per document type */
8144
+ DocTypeKey?: string | undefined;
8145
+ /** Caller-facing description of what this query answers. Carries more weight than the
8146
+ name when choosing between candidates, and is the only prose a caller gets */
8147
+ Purpose?: string | undefined;
8148
+ /** Agent when safe to expose to an external or AI caller; Internal otherwise. Null is
8149
+ unclassified and is treated as Internal, so an unreviewed entry is never exposed.
8150
+ Same vocabulary and the same fail-closed rule as LookupResult.Audience */
8151
+ Audience?: string | undefined;
8152
+ /** The TSQL this query runs, normally a thin EXEC wrapper over a stored procedure.
8153
+ Returned only to a caller entitled to administer the rule; blank otherwise, because
8154
+ this is an execution recipe rather than a description */
8155
+ Alias?: string | undefined;
8156
+ /** Adjustment to the command timeout: a positive value adds that many seconds, a negative
8157
+ value multiplies by its magnitude, and -1 means leave the connection default alone */
8158
+ TimeoutAdjust?: number;
8159
+ /** Role the caller must hold to run this query, or null when unrestricted. Enforced by
8160
+ the engine, which answers with a single explanatory Message row rather than an error
8161
+ when the caller does not hold it */
8162
+ RequiredRole?: string | undefined;
8163
+ /** True when this definition is one Spitfire distributes. A site may override any facet
8164
+ with its own row, which takes precedence - so a distributed definition is a default,
8165
+ not a guarantee of what will run */
8166
+ IsDistributed?: boolean;
8167
+ /** True when the resolved definition includes at least one row the site supplied itself.
8168
+ Worth surfacing: it is the difference between what we shipped and what will run */
8169
+ IsOverridden?: boolean;
8170
+ /** Number of caller-supplied parameters this query expects. Derived from the QPList */
8171
+ DependsCount?: number | undefined;
8172
+ /** True when the query's text references @pDocMasterKey, @pDocTypeKey or @pProject
8173
+ respectively, so a caller knows what document context to supply. A hint derived by
8174
+ inspecting the text, not a contract - a commented-out reference counts */
8175
+ UsesDocMasterKey?: boolean;
8176
+ /** See UsesDocMasterKey */
8177
+ UsesDocTypeKey?: boolean;
8178
+ /** See UsesDocMasterKey */
8179
+ UsesProject?: boolean;
8180
+ /** Caller-supplied parameters, in DependsOn order. Never null; a query taking none has
8181
+ an empty array */
8182
+ Parameters?: QueryParameter[] | undefined;
8183
+ /** Collection of commands for this row */
8184
+ MenuCommands?: MenuAction[] | undefined;
8185
+ /** eTag */
8186
+ ETag?: string | undefined;
8187
+ }
8099
8188
  /** Various common filters - not every filter is supported by every query */
8100
8189
  export interface QueryFilters {
8101
8190
  /** Project Mask (eg GC%) */
@@ -8161,6 +8250,46 @@ export interface QueryFilters {
8161
8250
  /** Key Value pairs of Keys and ETags, applicable to change/diffgram endpoints */
8162
8251
  ClientDataSummary?: CurrentDataSummary[] | undefined;
8163
8252
  }
8253
+ /** Describes one caller-supplied parameter of a dynamic query: what it means, what type of value belongs there, and where it lands in the DependsOn array. */
8254
+ export interface QueryParameter {
8255
+ /** Query this parameter belongs to, matching QueryDefinition.QueryName */
8256
+ QueryName: string;
8257
+ /** SQL parameter name including the @, exactly as it appears in the query's QPList - or,
8258
+ for a context parameter, the engine slot it describes such as @pDocMasterKey */
8259
+ ParameterName: string;
8260
+ /** True where the engine binds this parameter from the REQUEST rather than from DependsOn:
8261
+ @pDocMasterKey, @pProject and @pDocTypeKey are supplied as context, not by position */
8262
+ IsContext?: boolean;
8263
+ /** Zero-based position in the DependsOn array, taken from this parameter's position in the
8264
+ QPList. The engine maps DependsOn positionally, so this is the number a caller needs.
8265
+ Null when IsContext is set, because a context parameter has no
8266
+ position - it is nullable precisely so that a consumer cannot read a meaningful zero
8267
+ where there is no index at all */
8268
+ DependsIndex?: number | undefined;
8269
+ /** What this parameter means to a caller, for example As Of Date or Project ID */
8270
+ Label?: string | undefined;
8271
+ /** Semantic type of the value, for example DATE, GUID or STRING. Advisory only - every
8272
+ parameter is bound as a VarChar regardless, so the query itself must convert */
8273
+ PVType?: string | undefined;
8274
+ /** False where the query tolerates a blank here. Note that an omitted parameter arrives
8275
+ as an empty string rather than NULL, so a query that wants NULL must say so itself */
8276
+ IsRequired?: boolean;
8277
+ /** A concrete sample value; grounds a caller better than the type name alone. Dates
8278
+ should be given in ISO form, since the bound value is interpreted by SQL Server and a
8279
+ day/month ordering depends on the session */
8280
+ ExampleValue?: string | undefined;
8281
+ /** Name of the Lookup that produces a valid value for this parameter, letting a caller
8282
+ chain rather than guess. A soft reference by name, so it may not resolve */
8283
+ SourceLookup?: string | undefined;
8284
+ /** Free-text caveats about this parameter */
8285
+ Notes?: string | undefined;
8286
+ /** Flag */
8287
+ Active?: boolean;
8288
+ /** Collection of commands for this row */
8289
+ MenuCommands?: MenuAction[] | undefined;
8290
+ /** eTag */
8291
+ ETag?: string | undefined;
8292
+ }
8164
8293
  export interface RangeConditionHeaderValue {
8165
8294
  Date?: Date | undefined;
8166
8295
  EntityTag?: EntityTagHeaderValue | undefined;
@@ -12003,7 +12003,7 @@ class ConfigClient extends APIClientBase_1.APIClientBase {
12003
12003
  return null;
12004
12004
  }
12005
12005
  /**
12006
- * Returns the Lookups (pickers)
12006
+ * Returns the Lookups (pickers). Users without LookupEditor permission only see 'Agent' lookups.
12007
12007
  */
12008
12008
  getLookups() {
12009
12009
  return new Promise((resolve, reject) => {
@@ -12336,7 +12336,7 @@ class ConfigClient extends APIClientBase_1.APIClientBase {
12336
12336
  return null;
12337
12337
  }
12338
12338
  /**
12339
- * Returns the fields of one Lookup
12339
+ * Returns the fields of one Lookup. Non LookupEditor users only see PredicateMode=I.
12340
12340
  * @param lookupKey Lookup key
12341
12341
  */
12342
12342
  getLookupFields(lookupKey) {
@@ -12645,6 +12645,142 @@ class ConfigClient extends APIClientBase_1.APIClientBase {
12645
12645
  }
12646
12646
  return null;
12647
12647
  }
12648
+ /**
12649
+ * Returns the dynamic queries this site defines, each with its parameters
12650
+ */
12651
+ getQueries() {
12652
+ return new Promise((resolve, reject) => {
12653
+ this.getQueriesWithCallbacks((result) => resolve(result), (exception, _reason) => reject(exception));
12654
+ });
12655
+ }
12656
+ getQueriesWithCallbacks(onSuccess, onFail) {
12657
+ let url_ = this.baseUrl + "/api/configuration/queries";
12658
+ url_ = url_.replace(/[?&]$/, "");
12659
+ jQuery.ajax({
12660
+ url: url_,
12661
+ beforeSend: this.beforeSend,
12662
+ type: "get",
12663
+ dataType: "text",
12664
+ headers: {
12665
+ "Accept": "application/json"
12666
+ }
12667
+ }).done((_data, _textStatus, xhr) => {
12668
+ this.processGetQueriesWithCallbacks(url_, xhr, onSuccess, onFail);
12669
+ }).fail((xhr) => {
12670
+ this.processGetQueriesWithCallbacks(url_, xhr, onSuccess, onFail);
12671
+ });
12672
+ }
12673
+ processGetQueriesWithCallbacks(_url, xhr, onSuccess, onFail) {
12674
+ try {
12675
+ let result = this.transformResult(_url, xhr, (xhr) => this.processGetQueries(xhr));
12676
+ if (onSuccess !== undefined)
12677
+ onSuccess(result);
12678
+ }
12679
+ catch (e) {
12680
+ if (onFail !== undefined)
12681
+ onFail(e, "http_service_exception");
12682
+ }
12683
+ }
12684
+ processGetQueries(xhr) {
12685
+ const status = xhr.status;
12686
+ let _headers = {};
12687
+ if (status === 200) {
12688
+ const _responseText = xhr.responseText;
12689
+ let result200 = null;
12690
+ result200 = _responseText === "" ? null : JSON.parse(_responseText, this.jsonParseReviver);
12691
+ return result200;
12692
+ }
12693
+ else if (status === 401) {
12694
+ const _responseText = xhr.responseText;
12695
+ let result401 = null;
12696
+ result401 = _responseText === "" ? null : JSON.parse(_responseText, this.jsonParseReviver);
12697
+ return throwException("Not currently authenticated", status, _responseText, _headers, result401);
12698
+ }
12699
+ else if (status === 500) {
12700
+ const _responseText = xhr.responseText;
12701
+ let result500 = null;
12702
+ result500 = _responseText === "" ? null : JSON.parse(_responseText, this.jsonParseReviver);
12703
+ return throwException("Internal failure; see response", status, _responseText, _headers, result500);
12704
+ }
12705
+ else if (status !== 200 && status !== 204) {
12706
+ const _responseText = xhr.responseText;
12707
+ return throwException("An unexpected server error occurred.", status, _responseText, _headers);
12708
+ }
12709
+ return null;
12710
+ }
12711
+ /**
12712
+ * Returns one dynamic query definition with its parameters
12713
+ * @param queryName Query name, e.g. qUserActivitySummary
12714
+ */
12715
+ getQuery(queryName) {
12716
+ return new Promise((resolve, reject) => {
12717
+ this.getQueryWithCallbacks(queryName, (result) => resolve(result), (exception, _reason) => reject(exception));
12718
+ });
12719
+ }
12720
+ getQueryWithCallbacks(queryName, onSuccess, onFail) {
12721
+ let url_ = this.baseUrl + "/api/configuration/queries/{queryName}";
12722
+ if (queryName === undefined || queryName === null)
12723
+ throw new globalThis.Error("The parameter 'queryName' must be defined.");
12724
+ url_ = url_.replace("{queryName}", encodeURIComponent("" + queryName));
12725
+ url_ = url_.replace(/[?&]$/, "");
12726
+ jQuery.ajax({
12727
+ url: url_,
12728
+ beforeSend: this.beforeSend,
12729
+ type: "get",
12730
+ dataType: "text",
12731
+ headers: {
12732
+ "Accept": "application/json"
12733
+ }
12734
+ }).done((_data, _textStatus, xhr) => {
12735
+ this.processGetQueryWithCallbacks(url_, xhr, onSuccess, onFail);
12736
+ }).fail((xhr) => {
12737
+ this.processGetQueryWithCallbacks(url_, xhr, onSuccess, onFail);
12738
+ });
12739
+ }
12740
+ processGetQueryWithCallbacks(_url, xhr, onSuccess, onFail) {
12741
+ try {
12742
+ let result = this.transformResult(_url, xhr, (xhr) => this.processGetQuery(xhr));
12743
+ if (onSuccess !== undefined)
12744
+ onSuccess(result);
12745
+ }
12746
+ catch (e) {
12747
+ if (onFail !== undefined)
12748
+ onFail(e, "http_service_exception");
12749
+ }
12750
+ }
12751
+ processGetQuery(xhr) {
12752
+ const status = xhr.status;
12753
+ let _headers = {};
12754
+ if (status === 200) {
12755
+ const _responseText = xhr.responseText;
12756
+ let result200 = null;
12757
+ result200 = _responseText === "" ? null : JSON.parse(_responseText, this.jsonParseReviver);
12758
+ return result200;
12759
+ }
12760
+ else if (status === 401) {
12761
+ const _responseText = xhr.responseText;
12762
+ let result401 = null;
12763
+ result401 = _responseText === "" ? null : JSON.parse(_responseText, this.jsonParseReviver);
12764
+ return throwException("Not currently authenticated", status, _responseText, _headers, result401);
12765
+ }
12766
+ else if (status === 404) {
12767
+ const _responseText = xhr.responseText;
12768
+ let result404 = null;
12769
+ result404 = _responseText === "" ? null : JSON.parse(_responseText, this.jsonParseReviver);
12770
+ return throwException("No such query is available to you", status, _responseText, _headers, result404);
12771
+ }
12772
+ else if (status === 500) {
12773
+ const _responseText = xhr.responseText;
12774
+ let result500 = null;
12775
+ result500 = _responseText === "" ? null : JSON.parse(_responseText, this.jsonParseReviver);
12776
+ return throwException("Internal failure; see response", status, _responseText, _headers, result500);
12777
+ }
12778
+ else if (status !== 200 && status !== 204) {
12779
+ const _responseText = xhr.responseText;
12780
+ return throwException("An unexpected server error occurred.", status, _responseText, _headers);
12781
+ }
12782
+ return null;
12783
+ }
12648
12784
  /**
12649
12785
  * Returns the list of regions
12650
12786
  */
@@ -14913,6 +15049,12 @@ class ContactClient extends APIClientBase_1.APIClientBase {
14913
15049
  result403 = _responseText === "" ? null : JSON.parse(_responseText, this.jsonParseReviver);
14914
15050
  return throwException("Not allowed", status, _responseText, _headers, result403);
14915
15051
  }
15052
+ else if (status === 500) {
15053
+ const _responseText = xhr.responseText;
15054
+ let result500 = null;
15055
+ result500 = _responseText === "" ? null : JSON.parse(_responseText, this.jsonParseReviver);
15056
+ return throwException("Failed", status, _responseText, _headers, result500);
15057
+ }
14916
15058
  else if (status !== 200 && status !== 204) {
14917
15059
  const _responseText = xhr.responseText;
14918
15060
  return throwException("An unexpected server error occurred.", status, _responseText, _headers);
@@ -15066,6 +15208,12 @@ class ContactClient extends APIClientBase_1.APIClientBase {
15066
15208
  result403 = _responseText === "" ? null : JSON.parse(_responseText, this.jsonParseReviver);
15067
15209
  return throwException("Not allowed", status, _responseText, _headers, result403);
15068
15210
  }
15211
+ else if (status === 500) {
15212
+ const _responseText = xhr.responseText;
15213
+ let result500 = null;
15214
+ result500 = _responseText === "" ? null : JSON.parse(_responseText, this.jsonParseReviver);
15215
+ return throwException("Failed", status, _responseText, _headers, result500);
15216
+ }
15069
15217
  else if (status !== 200 && status !== 204) {
15070
15218
  const _responseText = xhr.responseText;
15071
15219
  return throwException("An unexpected server error occurred.", status, _responseText, _headers);
@@ -15510,8 +15658,8 @@ class DocumentToolsClient extends APIClientBase_1.APIClientBase {
15510
15658
  * @param id Document Key (use empty for auto assign)
15511
15659
  * @param typeKey Type
15512
15660
  * @param forProject (optional) Project
15513
- * @param forParent (optional) Parent Doc Key (NextDocFlow rules apply; See https://support.spitfirepm.com/kba-01517/)
15514
- * @param forBatch (optional) Batch/Subcontract
15661
+ * @param forParent (optional) Parent Doc Key (NextDocFlow rules apply; See https://support.spitfirepm.com/kba-01517/). When the parent is a commitment, its subcontract number is used and its lines are brought in
15662
+ * @param forBatch (optional) Batch/Subcontract. Naming a commitment here brings in its lines, same as forParent
15515
15663
  * @param forSourceContact (optional) Source Contact
15516
15664
  */
15517
15665
  createDocument(id, typeKey, forProject, forParent, forBatch, forSourceContact) {
@@ -17889,7 +18037,7 @@ class DocumentToolsClient extends APIClientBase_1.APIClientBase {
17889
18037
  return null;
17890
18038
  }
17891
18039
  /**
17892
- * Returns the comments for the specified document
18040
+ * Returns the comments for the specified document, most recent first.
17893
18041
  * @param id Document Key
17894
18042
  */
17895
18043
  getDocComments(id) {
@@ -18118,7 +18266,7 @@ class DocumentToolsClient extends APIClientBase_1.APIClientBase {
18118
18266
  return null;
18119
18267
  }
18120
18268
  /**
18121
- * Inserts Comments on the specified document
18269
+ * Inserts Comments on the specified document. Typically TopicKey=DocRevKey because comments are associated with the Doc Revision. You can specify the empty GUID for TopicKey and/or FromUser, the correct defaults will be supplied (the current Revision and the current user). Other values for TopicKey must resolve to this document (for example, a prior revision comment). Any value for created more than 5 days ago stamps the comment with the server time. FromUser is set automatically.
18122
18270
  * @param id Document Key
18123
18271
  * @param newData New comment data
18124
18272
  */