@attlaz/client 1.88.0 → 1.90.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/dist/Catalog/Model/Catalog.d.ts +19 -0
- package/dist/Catalog/Model/Catalog.js +28 -0
- package/dist/Catalog/Model/CatalogId.d.ts +4 -0
- package/dist/Catalog/Model/CatalogId.js +4 -0
- package/dist/Catalog/Model/CatalogProduct.d.ts +21 -0
- package/dist/Catalog/Model/CatalogProduct.js +31 -0
- package/dist/Catalog/Service/CatalogEndpoint.d.ts +15 -0
- package/dist/Catalog/Service/CatalogEndpoint.js +21 -0
- package/dist/Catalog/Service/CatalogProductEndpoint.d.ts +16 -0
- package/dist/Catalog/Service/CatalogProductEndpoint.js +24 -0
- package/dist/Client.d.ts +35 -7
- package/dist/Client.js +77 -7
- package/dist/DataQuality/Model/QualityDataset.d.ts +17 -0
- package/dist/DataQuality/Model/QualityDataset.js +26 -0
- package/dist/DataQuality/Model/QualityEntity.d.ts +24 -0
- package/dist/DataQuality/Model/QualityEntity.js +41 -0
- package/dist/DataQuality/Model/QualityProblem.d.ts +25 -0
- package/dist/DataQuality/Model/QualityProblem.js +43 -0
- package/dist/DataQuality/Service/QualityEndpoint.d.ts +45 -0
- package/dist/DataQuality/Service/QualityEndpoint.js +89 -0
- package/dist/EnhanceData/Model/GenerateContentBatch.d.ts +22 -0
- package/dist/EnhanceData/Model/GenerateContentBatch.js +34 -0
- package/dist/EnhanceData/Service/GenerateContentEndpoint.d.ts +23 -0
- package/dist/EnhanceData/Service/GenerateContentEndpoint.js +21 -0
- package/dist/FeedManagement/Model/CatalogFeed.d.ts +26 -0
- package/dist/FeedManagement/Model/CatalogFeed.js +51 -0
- package/dist/FeedManagement/Service/CatalogFeedEndpoint.d.ts +14 -0
- package/dist/FeedManagement/Service/CatalogFeedEndpoint.js +19 -0
- package/dist/{Model/Flow → Flow/Model}/Flow.d.ts +3 -3
- package/dist/{Model/Flow → Flow/Model}/Flow.js +1 -1
- package/dist/{Model/Flow → Flow/Model}/FlowRun.d.ts +3 -3
- package/dist/{Model/Flow → Flow/Model}/FlowRun.js +1 -1
- package/dist/{Model/Flow → Flow/Model}/FlowRunHistory.d.ts +1 -1
- package/dist/{Model/Flow → Flow/Model}/FlowRunLifecycle.d.ts +1 -1
- package/dist/{Model/Flow → Flow/Model}/FlowRunStats.d.ts +1 -1
- package/dist/{Model/Flow → Flow/Model}/FlowRunSummary.d.ts +1 -1
- package/dist/{Model/Flow → Flow/Model}/FlowSummary.d.ts +1 -1
- package/dist/{Service → Flow/Service}/FlowEndpoint.d.ts +5 -5
- package/dist/{Service → Flow/Service}/FlowEndpoint.js +6 -6
- package/dist/{Service → Flow/Service}/FlowRunEndpoint.d.ts +8 -8
- package/dist/{Service → Flow/Service}/FlowRunEndpoint.js +6 -6
- package/dist/Flow/Service/FlowRunRequestEndpoint.d.ts +6 -0
- package/dist/{Service → Flow/Service}/FlowRunRequestEndpoint.js +2 -2
- package/dist/{Service → Flow/Service}/FlowRunStatsEndpoint.d.ts +2 -2
- package/dist/{Service → Flow/Service}/FlowRunStatsEndpoint.js +2 -2
- package/dist/{Model/Log → Logging/Model}/Log.d.ts +2 -2
- package/dist/{Model/Log → Logging/Model}/Log.js +1 -1
- package/dist/{Model/Log → Logging/Model}/LogQuery.d.ts +1 -1
- package/dist/{Model/Log → Logging/Model}/LogStreamId.d.ts +1 -1
- package/dist/{Model/Log → Logging/Model}/LogStreamId.js +1 -1
- package/dist/{Model/Log → Logging/Model}/LogStreamInformation.d.ts +2 -2
- package/dist/{Service → Logging/Service}/LogEndpoint.d.ts +9 -9
- package/dist/{Service → Logging/Service}/LogEndpoint.js +6 -6
- package/dist/Model/Messaging/Subscriber.d.ts +1 -1
- package/dist/Model/Messaging/Subscriber.js +1 -1
- package/dist/Model/Search/SearchResult.d.ts +2 -2
- package/dist/Model/Search/SearchResult.js +2 -2
- package/dist/Pulse/Model/CatalogProductWithMatches.d.ts +31 -0
- package/dist/Pulse/Model/CatalogProductWithMatches.js +50 -0
- package/dist/Pulse/Model/CompetingVendorProduct.d.ts +15 -0
- package/dist/Pulse/Model/CompetingVendorProduct.js +21 -0
- package/dist/Pulse/Model/Competitor.d.ts +27 -0
- package/dist/Pulse/Model/Competitor.js +43 -0
- package/dist/{Model/Pulse → Pulse/Model}/CrawlJob.d.ts +2 -2
- package/dist/Pulse/Model/IndexJob.d.ts +19 -0
- package/dist/Pulse/Model/IndexJob.js +29 -0
- package/dist/Pulse/Model/MatchedVendorProduct.d.ts +29 -0
- package/dist/Pulse/Model/MatchedVendorProduct.js +48 -0
- package/dist/Pulse/Model/PriceAlertConfig.d.ts +22 -0
- package/dist/Pulse/Model/PriceAlertConfig.js +34 -0
- package/dist/Pulse/Model/PriceAlertEvent.d.ts +20 -0
- package/dist/Pulse/Model/PriceAlertEvent.js +33 -0
- package/dist/Pulse/Model/PriceIndexSnapshotEntry.d.ts +16 -0
- package/dist/Pulse/Model/PriceIndexSnapshotEntry.js +23 -0
- package/dist/Pulse/Model/PriceSuggestion.d.ts +29 -0
- package/dist/Pulse/Model/PriceSuggestion.js +46 -0
- package/dist/Pulse/Model/PricingRule.d.ts +30 -0
- package/dist/Pulse/Model/PricingRule.js +49 -0
- package/dist/Pulse/Model/ProductGroup.d.ts +25 -0
- package/dist/Pulse/Model/ProductGroup.js +36 -0
- package/dist/Pulse/Model/ProductMatch.d.ts +21 -0
- package/dist/Pulse/Model/ProductMatch.js +28 -0
- package/dist/Pulse/Model/ProductMatchJob.d.ts +27 -0
- package/dist/Pulse/Model/ProductMatchJob.js +42 -0
- package/dist/Pulse/Model/ReviewMatch.d.ts +42 -0
- package/dist/Pulse/Model/ReviewMatch.js +55 -0
- package/dist/Pulse/Model/TopCompetitor.d.ts +23 -0
- package/dist/Pulse/Model/TopCompetitor.js +37 -0
- package/dist/Pulse/Model/Vendor.d.ts +12 -0
- package/dist/Pulse/Model/Vendor.js +18 -0
- package/dist/{Model/Pulse → Pulse/Model}/VendorProduct.d.ts +6 -1
- package/dist/{Model/Pulse → Pulse/Model}/VendorProduct.js +9 -1
- package/dist/Pulse/Model/VendorProductPriceHistoryEntry.d.ts +18 -0
- package/dist/Pulse/Model/VendorProductPriceHistoryEntry.js +36 -0
- package/dist/Pulse/Model/VendorStatus.d.ts +25 -0
- package/dist/Pulse/Model/VendorStatus.js +34 -0
- package/dist/Pulse/Service/CompetitorEndpoint.d.ts +15 -0
- package/dist/Pulse/Service/CompetitorEndpoint.js +23 -0
- package/dist/{Service/Pulse → Pulse/Service}/CrawlJobEndpoint.d.ts +13 -3
- package/dist/{Service/Pulse → Pulse/Service}/CrawlJobEndpoint.js +18 -5
- package/dist/Pulse/Service/IndexJobEndpoint.d.ts +20 -0
- package/dist/Pulse/Service/IndexJobEndpoint.js +31 -0
- package/dist/Pulse/Service/PriceAlertEndpoint.d.ts +31 -0
- package/dist/Pulse/Service/PriceAlertEndpoint.js +42 -0
- package/dist/Pulse/Service/PricingEndpoint.d.ts +40 -0
- package/dist/Pulse/Service/PricingEndpoint.js +51 -0
- package/dist/Pulse/Service/ProductGroupEndpoint.d.ts +18 -0
- package/dist/Pulse/Service/ProductGroupEndpoint.js +19 -0
- package/dist/Pulse/Service/ProductMatchEndpoint.d.ts +47 -0
- package/dist/Pulse/Service/ProductMatchEndpoint.js +66 -0
- package/dist/Pulse/Service/ProductMatchJobEndpoint.d.ts +19 -0
- package/dist/Pulse/Service/ProductMatchJobEndpoint.js +30 -0
- package/dist/Pulse/Service/PulseCatalogProductEndpoint.d.ts +40 -0
- package/dist/Pulse/Service/PulseCatalogProductEndpoint.js +54 -0
- package/dist/Pulse/Service/PulseStatisticsEndpoint.d.ts +44 -0
- package/dist/Pulse/Service/PulseStatisticsEndpoint.js +65 -0
- package/dist/Pulse/Service/VendorProductEndpoint.d.ts +32 -0
- package/dist/{Service/Pulse → Pulse/Service}/VendorProductEndpoint.js +37 -2
- package/dist/Service/Endpoint.js +5 -3
- package/dist/index.d.ts +67 -27
- package/dist/index.js +67 -27
- package/dist/version.d.ts +1 -1
- package/dist/version.js +1 -1
- package/package.json +1 -1
- package/dist/Service/FlowRunRequestEndpoint.d.ts +0 -6
- package/dist/Service/Pulse/VendorProductEndpoint.d.ts +0 -14
- /package/dist/{Model/Flow → Flow/Model}/FlowRunHistory.js +0 -0
- /package/dist/{Model/Flow → Flow/Model}/FlowRunHistoryStatus.d.ts +0 -0
- /package/dist/{Model/Flow → Flow/Model}/FlowRunHistoryStatus.js +0 -0
- /package/dist/{Model/Flow → Flow/Model}/FlowRunLifecycle.js +0 -0
- /package/dist/{Model/Flow → Flow/Model}/FlowRunPriority.d.ts +0 -0
- /package/dist/{Model/Flow → Flow/Model}/FlowRunPriority.js +0 -0
- /package/dist/{Model/Flow → Flow/Model}/FlowRunResponse.d.ts +0 -0
- /package/dist/{Model/Flow → Flow/Model}/FlowRunResponse.js +0 -0
- /package/dist/{Model/Flow → Flow/Model}/FlowRunStats.js +0 -0
- /package/dist/{Model/Flow → Flow/Model}/FlowRunStatus.d.ts +0 -0
- /package/dist/{Model/Flow → Flow/Model}/FlowRunStatus.js +0 -0
- /package/dist/{Model/Flow → Flow/Model}/FlowRunSummary.js +0 -0
- /package/dist/{Model/Flow → Flow/Model}/FlowSummary.js +0 -0
- /package/dist/{Model/Flow → Flow/Model}/FlowTemplate.d.ts +0 -0
- /package/dist/{Model/Flow → Flow/Model}/FlowTemplate.js +0 -0
- /package/dist/{Model/Log → Logging/Model}/LogLevel.d.ts +0 -0
- /package/dist/{Model/Log → Logging/Model}/LogLevel.js +0 -0
- /package/dist/{Model/Log → Logging/Model}/LogQuery.js +0 -0
- /package/dist/{Model/Log → Logging/Model}/LogStatus.d.ts +0 -0
- /package/dist/{Model/Log → Logging/Model}/LogStatus.js +0 -0
- /package/dist/{Model/Log → Logging/Model}/LogStream.d.ts +0 -0
- /package/dist/{Model/Log → Logging/Model}/LogStream.js +0 -0
- /package/dist/{Model/Log → Logging/Model}/LogStreamInformation.js +0 -0
- /package/dist/{Model/Pulse → Pulse/Model}/CrawlJob.js +0 -0
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
import { CatalogId } from '../../Catalog/Model/CatalogId.js';
|
|
2
|
+
import { CursorPagination } from '../../Model/Pagination/CursorPagination.js';
|
|
3
|
+
import { CollectionResult } from '../../Model/Result/CollectionResult.js';
|
|
4
|
+
import { Endpoint } from '../../Service/Endpoint.js';
|
|
5
|
+
import { IndexJob } from '../Model/IndexJob.js';
|
|
6
|
+
import { VendorStatus } from '../Model/VendorStatus.js';
|
|
7
|
+
/**
|
|
8
|
+
* Market Pulse index jobs — building the embeddings a competitor's products must have before they
|
|
9
|
+
* can be matched — and the resulting per-vendor freshness status.
|
|
10
|
+
*/
|
|
11
|
+
export declare class IndexJobEndpoint extends Endpoint {
|
|
12
|
+
/** Index jobs across every competitor of a catalog, newest first. */
|
|
13
|
+
getByCatalog(catalogId: CatalogId | string, pagination?: CursorPagination | null): Promise<CollectionResult<IndexJob>>;
|
|
14
|
+
/** Index jobs of one competitor. */
|
|
15
|
+
getByVendor(catalogId: CatalogId | string, vendorId: string, pagination?: CursorPagination | null): Promise<CollectionResult<IndexJob>>;
|
|
16
|
+
/** Queue a re-index of a competitor's products, so later matching sees current data. */
|
|
17
|
+
requestReindex(catalogId: CatalogId | string, vendorId: string): Promise<void>;
|
|
18
|
+
/** How fresh a competitor's index and matches are, plus any match job running right now. */
|
|
19
|
+
getVendorStatus(catalogId: CatalogId | string, vendorId: string): Promise<VendorStatus | null>;
|
|
20
|
+
}
|
|
@@ -0,0 +1,31 @@
|
|
|
1
|
+
import { QueryString } from '../../Http/Data/QueryString.js';
|
|
2
|
+
import { Endpoint } from '../../Service/Endpoint.js';
|
|
3
|
+
import { IndexJob } from '../Model/IndexJob.js';
|
|
4
|
+
import { VendorStatus } from '../Model/VendorStatus.js';
|
|
5
|
+
/**
|
|
6
|
+
* Market Pulse index jobs — building the embeddings a competitor's products must have before they
|
|
7
|
+
* can be matched — and the resulting per-vendor freshness status.
|
|
8
|
+
*/
|
|
9
|
+
export class IndexJobEndpoint extends Endpoint {
|
|
10
|
+
/** Index jobs across every competitor of a catalog, newest first. */
|
|
11
|
+
async getByCatalog(catalogId, pagination = null) {
|
|
12
|
+
const queryString = new QueryString('/pulse/catalogs/' + catalogId.toString() + '/index-jobs');
|
|
13
|
+
queryString.addPagination(pagination);
|
|
14
|
+
return await this.requestCollection(queryString, IndexJob.parse);
|
|
15
|
+
}
|
|
16
|
+
/** Index jobs of one competitor. */
|
|
17
|
+
async getByVendor(catalogId, vendorId, pagination = null) {
|
|
18
|
+
const queryString = new QueryString('/pulse/catalogs/' + catalogId.toString() + '/vendors/' + vendorId + '/index-jobs');
|
|
19
|
+
queryString.addPagination(pagination);
|
|
20
|
+
return await this.requestCollection(queryString, IndexJob.parse);
|
|
21
|
+
}
|
|
22
|
+
/** Queue a re-index of a competitor's products, so later matching sees current data. */
|
|
23
|
+
async requestReindex(catalogId, vendorId) {
|
|
24
|
+
await this.requestObject('/pulse/catalogs/' + catalogId.toString() + '/vendors/' + vendorId + '/reindex', {}, (raw) => raw, 'POST');
|
|
25
|
+
}
|
|
26
|
+
/** How fresh a competitor's index and matches are, plus any match job running right now. */
|
|
27
|
+
async getVendorStatus(catalogId, vendorId) {
|
|
28
|
+
const result = await this.requestObject('/pulse/catalogs/' + catalogId.toString() + '/vendors/' + vendorId + '/status', null, VendorStatus.parse, 'GET');
|
|
29
|
+
return result.getData();
|
|
30
|
+
}
|
|
31
|
+
}
|
|
@@ -0,0 +1,31 @@
|
|
|
1
|
+
import { CatalogId } from '../../Catalog/Model/CatalogId.js';
|
|
2
|
+
import { CursorPagination } from '../../Model/Pagination/CursorPagination.js';
|
|
3
|
+
import { CollectionResult } from '../../Model/Result/CollectionResult.js';
|
|
4
|
+
import { Endpoint } from '../../Service/Endpoint.js';
|
|
5
|
+
import { PriceAlertConfig } from '../Model/PriceAlertConfig.js';
|
|
6
|
+
import { PriceAlertEvent } from '../Model/PriceAlertEvent.js';
|
|
7
|
+
/** Fields accepted when creating an alert; camelCase keys are snake_cased by the base Endpoint. */
|
|
8
|
+
export type PriceAlertConfigData = {
|
|
9
|
+
name: string;
|
|
10
|
+
conditionType: string;
|
|
11
|
+
conditionParams?: Record<string, unknown>;
|
|
12
|
+
productGroup?: string | null;
|
|
13
|
+
channelId: string;
|
|
14
|
+
isActive?: boolean;
|
|
15
|
+
};
|
|
16
|
+
/**
|
|
17
|
+
* Price alerts — the standing rules (`/pulse/price-alert-configs`) and the events they produce.
|
|
18
|
+
*/
|
|
19
|
+
export declare class PriceAlertEndpoint extends Endpoint {
|
|
20
|
+
getConfigs(catalogId: CatalogId | string, pagination?: CursorPagination | null): Promise<CollectionResult<PriceAlertConfig>>;
|
|
21
|
+
getConfig(alertConfigId: string): Promise<PriceAlertConfig | null>;
|
|
22
|
+
createConfig(catalogId: CatalogId | string, data: PriceAlertConfigData): Promise<PriceAlertConfig | null>;
|
|
23
|
+
updateConfig(alertConfigId: string, data: Partial<PriceAlertConfigData>): Promise<PriceAlertConfig | null>;
|
|
24
|
+
deleteConfig(alertConfigId: string): Promise<void>;
|
|
25
|
+
getEvents(alertConfigId: string, pagination?: CursorPagination | null): Promise<CollectionResult<PriceAlertEvent>>;
|
|
26
|
+
/**
|
|
27
|
+
* Record that someone has dealt with an event; it stays in the list. The API stamps who and
|
|
28
|
+
* when from the session, so the request carries no body.
|
|
29
|
+
*/
|
|
30
|
+
acknowledgeEvent(alertEventId: string): Promise<PriceAlertEvent | null>;
|
|
31
|
+
}
|
|
@@ -0,0 +1,42 @@
|
|
|
1
|
+
import { QueryString } from '../../Http/Data/QueryString.js';
|
|
2
|
+
import { Endpoint } from '../../Service/Endpoint.js';
|
|
3
|
+
import { PriceAlertConfig } from '../Model/PriceAlertConfig.js';
|
|
4
|
+
import { PriceAlertEvent } from '../Model/PriceAlertEvent.js';
|
|
5
|
+
/**
|
|
6
|
+
* Price alerts — the standing rules (`/pulse/price-alert-configs`) and the events they produce.
|
|
7
|
+
*/
|
|
8
|
+
export class PriceAlertEndpoint extends Endpoint {
|
|
9
|
+
async getConfigs(catalogId, pagination = null) {
|
|
10
|
+
const queryString = new QueryString('/pulse/catalogs/' + catalogId.toString() + '/price-alert-configs');
|
|
11
|
+
queryString.addPagination(pagination);
|
|
12
|
+
return await this.requestCollection(queryString, PriceAlertConfig.parse);
|
|
13
|
+
}
|
|
14
|
+
async getConfig(alertConfigId) {
|
|
15
|
+
const result = await this.requestObject('/pulse/price-alert-configs/' + alertConfigId, null, PriceAlertConfig.parse, 'GET');
|
|
16
|
+
return result.getData();
|
|
17
|
+
}
|
|
18
|
+
async createConfig(catalogId, data) {
|
|
19
|
+
const result = await this.requestObject('/pulse/catalogs/' + catalogId.toString() + '/price-alert-configs', data, PriceAlertConfig.parse, 'POST');
|
|
20
|
+
return result.getData();
|
|
21
|
+
}
|
|
22
|
+
async updateConfig(alertConfigId, data) {
|
|
23
|
+
const result = await this.requestObject('/pulse/price-alert-configs/' + alertConfigId, data, PriceAlertConfig.parse, 'PATCH');
|
|
24
|
+
return result.getData();
|
|
25
|
+
}
|
|
26
|
+
async deleteConfig(alertConfigId) {
|
|
27
|
+
await this.requestObject('/pulse/price-alert-configs/' + alertConfigId, null, (raw) => raw, 'DELETE');
|
|
28
|
+
}
|
|
29
|
+
async getEvents(alertConfigId, pagination = null) {
|
|
30
|
+
const queryString = new QueryString('/pulse/price-alert-configs/' + alertConfigId + '/events');
|
|
31
|
+
queryString.addPagination(pagination);
|
|
32
|
+
return await this.requestCollection(queryString, PriceAlertEvent.parse);
|
|
33
|
+
}
|
|
34
|
+
/**
|
|
35
|
+
* Record that someone has dealt with an event; it stays in the list. The API stamps who and
|
|
36
|
+
* when from the session, so the request carries no body.
|
|
37
|
+
*/
|
|
38
|
+
async acknowledgeEvent(alertEventId) {
|
|
39
|
+
const result = await this.requestObject('/pulse/price-alert-events/' + alertEventId, {}, PriceAlertEvent.parse, 'PATCH');
|
|
40
|
+
return result.getData();
|
|
41
|
+
}
|
|
42
|
+
}
|
|
@@ -0,0 +1,40 @@
|
|
|
1
|
+
import { CatalogId } from '../../Catalog/Model/CatalogId.js';
|
|
2
|
+
import { CursorPagination } from '../../Model/Pagination/CursorPagination.js';
|
|
3
|
+
import { CollectionResult } from '../../Model/Result/CollectionResult.js';
|
|
4
|
+
import { Endpoint } from '../../Service/Endpoint.js';
|
|
5
|
+
import { PriceSuggestion, PriceSuggestionStatus } from '../Model/PriceSuggestion.js';
|
|
6
|
+
import { PricingRule } from '../Model/PricingRule.js';
|
|
7
|
+
/** Fields accepted when writing a rule; camelCase keys are snake_cased by the base Endpoint. */
|
|
8
|
+
export type PricingRuleData = {
|
|
9
|
+
name: string;
|
|
10
|
+
description?: string | null;
|
|
11
|
+
productGroup?: string | null;
|
|
12
|
+
conditions?: Record<string, unknown>;
|
|
13
|
+
actionType: string;
|
|
14
|
+
actionParams?: Record<string, unknown>;
|
|
15
|
+
floorMargin?: number | null;
|
|
16
|
+
floorPrice?: number | null;
|
|
17
|
+
ceilingPrice?: number | null;
|
|
18
|
+
ignoreIfNoCostPrice?: boolean;
|
|
19
|
+
priority?: number;
|
|
20
|
+
isActive?: boolean;
|
|
21
|
+
};
|
|
22
|
+
/**
|
|
23
|
+
* Repricing — the rules that propose prices (`/pulse/pricing-rules`) and the suggestions they
|
|
24
|
+
* produce (`/pulse/price-suggestions`).
|
|
25
|
+
*/
|
|
26
|
+
export declare class PricingEndpoint extends Endpoint {
|
|
27
|
+
getRules(catalogId: CatalogId | string, pagination?: CursorPagination | null): Promise<CollectionResult<PricingRule>>;
|
|
28
|
+
getRule(pricingRuleId: string): Promise<PricingRule | null>;
|
|
29
|
+
createRule(catalogId: CatalogId | string, data: PricingRuleData): Promise<PricingRule | null>;
|
|
30
|
+
updateRule(pricingRuleId: string, data: Partial<PricingRuleData>): Promise<PricingRule | null>;
|
|
31
|
+
deleteRule(pricingRuleId: string): Promise<void>;
|
|
32
|
+
/** Price suggestions of a catalog, optionally only those in one status. */
|
|
33
|
+
getSuggestions(catalogId: CatalogId | string, pagination?: CursorPagination | null, status?: string | null): Promise<CollectionResult<PriceSuggestion>>;
|
|
34
|
+
getSuggestion(priceSuggestionId: string): Promise<PriceSuggestion | null>;
|
|
35
|
+
/**
|
|
36
|
+
* Approve or reject a suggestion. Approving marks it for pushing back to the shop; the write
|
|
37
|
+
* itself is done by a flow, which sets `appliedAt`.
|
|
38
|
+
*/
|
|
39
|
+
reviewSuggestion(priceSuggestionId: string, status: Exclude<PriceSuggestionStatus, 'pending'>): Promise<PriceSuggestion | null>;
|
|
40
|
+
}
|
|
@@ -0,0 +1,51 @@
|
|
|
1
|
+
import { QueryString } from '../../Http/Data/QueryString.js';
|
|
2
|
+
import { Endpoint } from '../../Service/Endpoint.js';
|
|
3
|
+
import { PriceSuggestion } from '../Model/PriceSuggestion.js';
|
|
4
|
+
import { PricingRule } from '../Model/PricingRule.js';
|
|
5
|
+
/**
|
|
6
|
+
* Repricing — the rules that propose prices (`/pulse/pricing-rules`) and the suggestions they
|
|
7
|
+
* produce (`/pulse/price-suggestions`).
|
|
8
|
+
*/
|
|
9
|
+
export class PricingEndpoint extends Endpoint {
|
|
10
|
+
async getRules(catalogId, pagination = null) {
|
|
11
|
+
const queryString = new QueryString('/pulse/catalogs/' + catalogId.toString() + '/pricing-rules');
|
|
12
|
+
queryString.addPagination(pagination);
|
|
13
|
+
return await this.requestCollection(queryString, PricingRule.parse);
|
|
14
|
+
}
|
|
15
|
+
async getRule(pricingRuleId) {
|
|
16
|
+
const result = await this.requestObject('/pulse/pricing-rules/' + pricingRuleId, null, PricingRule.parse, 'GET');
|
|
17
|
+
return result.getData();
|
|
18
|
+
}
|
|
19
|
+
async createRule(catalogId, data) {
|
|
20
|
+
const result = await this.requestObject('/pulse/catalogs/' + catalogId.toString() + '/pricing-rules', data, PricingRule.parse, 'POST');
|
|
21
|
+
return result.getData();
|
|
22
|
+
}
|
|
23
|
+
async updateRule(pricingRuleId, data) {
|
|
24
|
+
const result = await this.requestObject('/pulse/pricing-rules/' + pricingRuleId, data, PricingRule.parse, 'PATCH');
|
|
25
|
+
return result.getData();
|
|
26
|
+
}
|
|
27
|
+
async deleteRule(pricingRuleId) {
|
|
28
|
+
await this.requestObject('/pulse/pricing-rules/' + pricingRuleId, null, (raw) => raw, 'DELETE');
|
|
29
|
+
}
|
|
30
|
+
/** Price suggestions of a catalog, optionally only those in one status. */
|
|
31
|
+
async getSuggestions(catalogId, pagination = null, status = null) {
|
|
32
|
+
const queryString = new QueryString('/pulse/catalogs/' + catalogId.toString() + '/price-suggestions');
|
|
33
|
+
if (status !== null) {
|
|
34
|
+
queryString.set('status', status);
|
|
35
|
+
}
|
|
36
|
+
queryString.addPagination(pagination);
|
|
37
|
+
return await this.requestCollection(queryString, PriceSuggestion.parse);
|
|
38
|
+
}
|
|
39
|
+
async getSuggestion(priceSuggestionId) {
|
|
40
|
+
const result = await this.requestObject('/pulse/price-suggestions/' + priceSuggestionId, null, PriceSuggestion.parse, 'GET');
|
|
41
|
+
return result.getData();
|
|
42
|
+
}
|
|
43
|
+
/**
|
|
44
|
+
* Approve or reject a suggestion. Approving marks it for pushing back to the shop; the write
|
|
45
|
+
* itself is done by a flow, which sets `appliedAt`.
|
|
46
|
+
*/
|
|
47
|
+
async reviewSuggestion(priceSuggestionId, status) {
|
|
48
|
+
const result = await this.requestObject('/pulse/price-suggestions/' + priceSuggestionId, { status }, PriceSuggestion.parse, 'PATCH');
|
|
49
|
+
return result.getData();
|
|
50
|
+
}
|
|
51
|
+
}
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
import { CatalogId } from '../../Catalog/Model/CatalogId.js';
|
|
2
|
+
import { CursorPagination } from '../../Model/Pagination/CursorPagination.js';
|
|
3
|
+
import { CollectionResult } from '../../Model/Result/CollectionResult.js';
|
|
4
|
+
import { Endpoint } from '../../Service/Endpoint.js';
|
|
5
|
+
import { ProductGroup, ProductGroupType } from '../Model/ProductGroup.js';
|
|
6
|
+
/** Fields accepted when writing a group; camelCase keys are snake_cased by the base Endpoint. */
|
|
7
|
+
export type ProductGroupData = {
|
|
8
|
+
name: string;
|
|
9
|
+
description?: string | null;
|
|
10
|
+
groupType?: ProductGroupType;
|
|
11
|
+
criteria?: Record<string, unknown>;
|
|
12
|
+
};
|
|
13
|
+
/** Product groups — `/pulse/catalogs/:catalogId/product-groups`. */
|
|
14
|
+
export declare class ProductGroupEndpoint extends Endpoint {
|
|
15
|
+
getByCatalog(catalogId: CatalogId | string, pagination?: CursorPagination | null): Promise<CollectionResult<ProductGroup>>;
|
|
16
|
+
getById(productGroupId: string): Promise<ProductGroup | null>;
|
|
17
|
+
create(catalogId: CatalogId | string, data: ProductGroupData): Promise<ProductGroup | null>;
|
|
18
|
+
}
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
import { QueryString } from '../../Http/Data/QueryString.js';
|
|
2
|
+
import { Endpoint } from '../../Service/Endpoint.js';
|
|
3
|
+
import { ProductGroup } from '../Model/ProductGroup.js';
|
|
4
|
+
/** Product groups — `/pulse/catalogs/:catalogId/product-groups`. */
|
|
5
|
+
export class ProductGroupEndpoint extends Endpoint {
|
|
6
|
+
async getByCatalog(catalogId, pagination = null) {
|
|
7
|
+
const queryString = new QueryString('/pulse/catalogs/' + catalogId.toString() + '/product-groups');
|
|
8
|
+
queryString.addPagination(pagination);
|
|
9
|
+
return await this.requestCollection(queryString, ProductGroup.parse);
|
|
10
|
+
}
|
|
11
|
+
async getById(productGroupId) {
|
|
12
|
+
const result = await this.requestObject('/pulse/product-groups/' + productGroupId, null, ProductGroup.parse, 'GET');
|
|
13
|
+
return result.getData();
|
|
14
|
+
}
|
|
15
|
+
async create(catalogId, data) {
|
|
16
|
+
const result = await this.requestObject('/pulse/catalogs/' + catalogId.toString() + '/product-groups', data, ProductGroup.parse, 'POST');
|
|
17
|
+
return result.getData();
|
|
18
|
+
}
|
|
19
|
+
}
|
|
@@ -0,0 +1,47 @@
|
|
|
1
|
+
import { CatalogId } from '../../Catalog/Model/CatalogId.js';
|
|
2
|
+
import { CursorPagination } from '../../Model/Pagination/CursorPagination.js';
|
|
3
|
+
import { CollectionResult } from '../../Model/Result/CollectionResult.js';
|
|
4
|
+
import { Endpoint } from '../../Service/Endpoint.js';
|
|
5
|
+
import { ProductMatch } from '../Model/ProductMatch.js';
|
|
6
|
+
import { ReviewMatch } from '../Model/ReviewMatch.js';
|
|
7
|
+
/** Narrows the review queue. Omitting `statuses` returns the pending ones. */
|
|
8
|
+
export type ReviewMatchFilters = {
|
|
9
|
+
statuses?: string[];
|
|
10
|
+
competitor?: string;
|
|
11
|
+
gtin?: string;
|
|
12
|
+
search?: string;
|
|
13
|
+
};
|
|
14
|
+
export type MatchHistoryInterval = 'day' | 'week' | 'month';
|
|
15
|
+
/** Matches discovered and reviewed within one bucket of the history. */
|
|
16
|
+
export type MatchHistoryBucket = {
|
|
17
|
+
date: Date;
|
|
18
|
+
discovered: number;
|
|
19
|
+
manualAccepted: number;
|
|
20
|
+
manualDeclined: number;
|
|
21
|
+
};
|
|
22
|
+
/** A match-history series plus where the queue stands right now. */
|
|
23
|
+
export type MatchHistory = {
|
|
24
|
+
interval: MatchHistoryInterval;
|
|
25
|
+
buckets: MatchHistoryBucket[];
|
|
26
|
+
snapshot: {
|
|
27
|
+
pending: number;
|
|
28
|
+
accepted: number;
|
|
29
|
+
declined: number;
|
|
30
|
+
};
|
|
31
|
+
};
|
|
32
|
+
/**
|
|
33
|
+
* Product matches — reviewing the queue, accepting or declining a match, and the history of how
|
|
34
|
+
* the queue has moved.
|
|
35
|
+
*/
|
|
36
|
+
export declare class ProductMatchEndpoint extends Endpoint {
|
|
37
|
+
/** The review queue of a catalog; pending matches unless `statuses` says otherwise. */
|
|
38
|
+
getForReview(catalogId: CatalogId | string, pagination?: CursorPagination | null, filters?: ReviewMatchFilters): Promise<CollectionResult<ReviewMatch>>;
|
|
39
|
+
/** The match record, or null. */
|
|
40
|
+
getById(matchId: string): Promise<ProductMatch | null>;
|
|
41
|
+
/** Confirm a match. `note` records why, for the reviewer's own audit trail. */
|
|
42
|
+
accept(matchId: string, note?: string | null): Promise<void>;
|
|
43
|
+
/** Reject a match, so it stops counting towards the competitor's price index. */
|
|
44
|
+
decline(matchId: string, note?: string | null): Promise<void>;
|
|
45
|
+
/** How many matches were discovered and reviewed over time, optionally for one competitor. */
|
|
46
|
+
getHistory(catalogId: CatalogId | string, competitor?: string | null, interval?: MatchHistoryInterval): Promise<MatchHistory>;
|
|
47
|
+
}
|
|
@@ -0,0 +1,66 @@
|
|
|
1
|
+
import { QueryString } from '../../Http/Data/QueryString.js';
|
|
2
|
+
import { Endpoint } from '../../Service/Endpoint.js';
|
|
3
|
+
import { ProductMatch } from '../Model/ProductMatch.js';
|
|
4
|
+
import { ReviewMatch } from '../Model/ReviewMatch.js';
|
|
5
|
+
/**
|
|
6
|
+
* Product matches — reviewing the queue, accepting or declining a match, and the history of how
|
|
7
|
+
* the queue has moved.
|
|
8
|
+
*/
|
|
9
|
+
export class ProductMatchEndpoint extends Endpoint {
|
|
10
|
+
/** The review queue of a catalog; pending matches unless `statuses` says otherwise. */
|
|
11
|
+
async getForReview(catalogId, pagination = null, filters = {}) {
|
|
12
|
+
const queryString = new QueryString('/pulse/catalogs/' + catalogId.toString() + '/matches');
|
|
13
|
+
queryString.set('status', (filters.statuses ?? ['pending']).join(','));
|
|
14
|
+
if (filters.competitor) {
|
|
15
|
+
queryString.set('competitor', filters.competitor);
|
|
16
|
+
}
|
|
17
|
+
if (filters.gtin) {
|
|
18
|
+
queryString.set('gtin', filters.gtin);
|
|
19
|
+
}
|
|
20
|
+
if (filters.search) {
|
|
21
|
+
queryString.set('search', filters.search);
|
|
22
|
+
}
|
|
23
|
+
queryString.addPagination(pagination);
|
|
24
|
+
return await this.requestCollection(queryString, ReviewMatch.parse);
|
|
25
|
+
}
|
|
26
|
+
/** The match record, or null. */
|
|
27
|
+
async getById(matchId) {
|
|
28
|
+
const result = await this.requestObject('/pulse/matches/' + matchId, null, ProductMatch.parse, 'GET');
|
|
29
|
+
return result.getData();
|
|
30
|
+
}
|
|
31
|
+
/** Confirm a match. `note` records why, for the reviewer's own audit trail. */
|
|
32
|
+
async accept(matchId, note = null) {
|
|
33
|
+
await this.requestObject('/pulse/matches/' + matchId + '/accept', note === null ? {} : { note }, (raw) => raw, 'POST');
|
|
34
|
+
}
|
|
35
|
+
/** Reject a match, so it stops counting towards the competitor's price index. */
|
|
36
|
+
async decline(matchId, note = null) {
|
|
37
|
+
await this.requestObject('/pulse/matches/' + matchId + '/decline', note === null ? {} : { note }, (raw) => raw, 'POST');
|
|
38
|
+
}
|
|
39
|
+
/** How many matches were discovered and reviewed over time, optionally for one competitor. */
|
|
40
|
+
async getHistory(catalogId, competitor = null, interval = 'day') {
|
|
41
|
+
const queryString = new QueryString('/pulse/catalogs/' + catalogId.toString() + '/matches/history');
|
|
42
|
+
queryString.set('interval', interval);
|
|
43
|
+
if (competitor !== null) {
|
|
44
|
+
queryString.set('competitor', competitor);
|
|
45
|
+
}
|
|
46
|
+
const result = await this.requestObject(queryString, null, (raw) => {
|
|
47
|
+
const buckets = raw.buckets ?? [];
|
|
48
|
+
const snapshot = raw.snapshot ?? {};
|
|
49
|
+
return {
|
|
50
|
+
interval: raw.interval ?? interval,
|
|
51
|
+
buckets: buckets.map((bucket) => ({
|
|
52
|
+
date: new Date(bucket.date),
|
|
53
|
+
discovered: bucket.discovered ?? 0,
|
|
54
|
+
manualAccepted: bucket.manual_accepted ?? 0,
|
|
55
|
+
manualDeclined: bucket.manual_declined ?? 0,
|
|
56
|
+
})),
|
|
57
|
+
snapshot: {
|
|
58
|
+
pending: snapshot.pending ?? 0,
|
|
59
|
+
accepted: snapshot.accepted ?? 0,
|
|
60
|
+
declined: snapshot.declined ?? 0,
|
|
61
|
+
},
|
|
62
|
+
};
|
|
63
|
+
}, 'GET');
|
|
64
|
+
return result.getData() ?? { interval, buckets: [], snapshot: { pending: 0, accepted: 0, declined: 0 } };
|
|
65
|
+
}
|
|
66
|
+
}
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
import { CatalogId } from '../../Catalog/Model/CatalogId.js';
|
|
2
|
+
import { CursorPagination } from '../../Model/Pagination/CursorPagination.js';
|
|
3
|
+
import { ProductMatchJob } from '../Model/ProductMatchJob.js';
|
|
4
|
+
import { CollectionResult } from '../../Model/Result/CollectionResult.js';
|
|
5
|
+
import { Endpoint } from '../../Service/Endpoint.js';
|
|
6
|
+
/**
|
|
7
|
+
* Market Pulse product match jobs — `/pulse/match-jobs`. All three routes return the same shape,
|
|
8
|
+
* so they share {@link ProductMatchJob}.
|
|
9
|
+
*/
|
|
10
|
+
export declare class ProductMatchJobEndpoint extends Endpoint {
|
|
11
|
+
/** Every match job of a catalog, newest first. */
|
|
12
|
+
getByCatalog(catalogId: CatalogId | string, pagination?: CursorPagination | null): Promise<CollectionResult<ProductMatchJob>>;
|
|
13
|
+
/** The match jobs of one of the catalog's competitors. */
|
|
14
|
+
getByVendor(catalogId: CatalogId | string, vendorId: string, pagination?: CursorPagination | null): Promise<CollectionResult<ProductMatchJob>>;
|
|
15
|
+
/** Queue a matching run of the catalog against one competitor. */
|
|
16
|
+
requestMatching(catalogId: CatalogId | string, vendorId: string): Promise<void>;
|
|
17
|
+
/** The match job with this id, or null. */
|
|
18
|
+
getById(productMatchJobId: string): Promise<ProductMatchJob | null>;
|
|
19
|
+
}
|
|
@@ -0,0 +1,30 @@
|
|
|
1
|
+
import { QueryString } from '../../Http/Data/QueryString.js';
|
|
2
|
+
import { ProductMatchJob } from '../Model/ProductMatchJob.js';
|
|
3
|
+
import { Endpoint } from '../../Service/Endpoint.js';
|
|
4
|
+
/**
|
|
5
|
+
* Market Pulse product match jobs — `/pulse/match-jobs`. All three routes return the same shape,
|
|
6
|
+
* so they share {@link ProductMatchJob}.
|
|
7
|
+
*/
|
|
8
|
+
export class ProductMatchJobEndpoint extends Endpoint {
|
|
9
|
+
/** Every match job of a catalog, newest first. */
|
|
10
|
+
async getByCatalog(catalogId, pagination = null) {
|
|
11
|
+
const queryString = new QueryString('/pulse/catalogs/' + catalogId.toString() + '/match-jobs');
|
|
12
|
+
queryString.addPagination(pagination);
|
|
13
|
+
return await this.requestCollection(queryString, ProductMatchJob.parse);
|
|
14
|
+
}
|
|
15
|
+
/** The match jobs of one of the catalog's competitors. */
|
|
16
|
+
async getByVendor(catalogId, vendorId, pagination = null) {
|
|
17
|
+
const queryString = new QueryString('/pulse/catalogs/' + catalogId.toString() + '/vendors/' + vendorId + '/match-jobs');
|
|
18
|
+
queryString.addPagination(pagination);
|
|
19
|
+
return await this.requestCollection(queryString, ProductMatchJob.parse);
|
|
20
|
+
}
|
|
21
|
+
/** Queue a matching run of the catalog against one competitor. */
|
|
22
|
+
async requestMatching(catalogId, vendorId) {
|
|
23
|
+
await this.requestObject('/pulse/catalogs/' + catalogId.toString() + '/vendors/' + vendorId + '/match', {}, (raw) => raw, 'POST');
|
|
24
|
+
}
|
|
25
|
+
/** The match job with this id, or null. */
|
|
26
|
+
async getById(productMatchJobId) {
|
|
27
|
+
const result = await this.requestObject('/pulse/match-jobs/' + productMatchJobId, null, ProductMatchJob.parse, 'GET');
|
|
28
|
+
return result.getData();
|
|
29
|
+
}
|
|
30
|
+
}
|
|
@@ -0,0 +1,40 @@
|
|
|
1
|
+
import { CatalogId } from '../../Catalog/Model/CatalogId.js';
|
|
2
|
+
import { FilterNode } from '../../Model/Filter/FilterNode.js';
|
|
3
|
+
import { CursorPagination } from '../../Model/Pagination/CursorPagination.js';
|
|
4
|
+
import { CollectionResult } from '../../Model/Result/CollectionResult.js';
|
|
5
|
+
import { Endpoint } from '../../Service/Endpoint.js';
|
|
6
|
+
import { CatalogProductWithMatches } from '../Model/CatalogProductWithMatches.js';
|
|
7
|
+
/** Simple narrowing of the product list; `tags` filters on materialised tag values. */
|
|
8
|
+
export type PulseCatalogProductFilters = {
|
|
9
|
+
brand?: string;
|
|
10
|
+
category?: string;
|
|
11
|
+
search?: string;
|
|
12
|
+
productGroup?: string;
|
|
13
|
+
tags?: Record<string, string>;
|
|
14
|
+
};
|
|
15
|
+
/** The values the product list can currently be filtered on. */
|
|
16
|
+
export type PulseCatalogProductFilterOptions = {
|
|
17
|
+
brands: string[];
|
|
18
|
+
categories: string[];
|
|
19
|
+
productGroups: {
|
|
20
|
+
id: string;
|
|
21
|
+
name: string;
|
|
22
|
+
}[];
|
|
23
|
+
tags: Record<string, string[]>;
|
|
24
|
+
};
|
|
25
|
+
/**
|
|
26
|
+
* A catalog's own products as Market Pulse sees them — with the competitor products matched to
|
|
27
|
+
* each. `/pulse/catalogs/:catalogId/products`.
|
|
28
|
+
*/
|
|
29
|
+
export declare class PulseCatalogProductEndpoint extends Endpoint {
|
|
30
|
+
/**
|
|
31
|
+
* The catalog's products, each with its matches expanded.
|
|
32
|
+
*
|
|
33
|
+
* `filters` covers the common narrowing; `filter` takes a structured {@link FilterNode} for
|
|
34
|
+
* anything the simple filters cannot express.
|
|
35
|
+
*/
|
|
36
|
+
getProducts(catalogId: CatalogId | string, pagination?: CursorPagination | null, filters?: PulseCatalogProductFilters, filter?: FilterNode | null): Promise<CollectionResult<CatalogProductWithMatches>>;
|
|
37
|
+
getFilterOptions(catalogId: CatalogId | string): Promise<PulseCatalogProductFilterOptions>;
|
|
38
|
+
/** Recalculate the catalog's cached statistics (price index, match counts, segments). */
|
|
39
|
+
recomputeStatistics(catalogId: CatalogId | string): Promise<void>;
|
|
40
|
+
}
|
|
@@ -0,0 +1,54 @@
|
|
|
1
|
+
import { QueryString } from '../../Http/Data/QueryString.js';
|
|
2
|
+
import { Endpoint } from '../../Service/Endpoint.js';
|
|
3
|
+
import { CatalogProductWithMatches } from '../Model/CatalogProductWithMatches.js';
|
|
4
|
+
/**
|
|
5
|
+
* A catalog's own products as Market Pulse sees them — with the competitor products matched to
|
|
6
|
+
* each. `/pulse/catalogs/:catalogId/products`.
|
|
7
|
+
*/
|
|
8
|
+
export class PulseCatalogProductEndpoint extends Endpoint {
|
|
9
|
+
/**
|
|
10
|
+
* The catalog's products, each with its matches expanded.
|
|
11
|
+
*
|
|
12
|
+
* `filters` covers the common narrowing; `filter` takes a structured {@link FilterNode} for
|
|
13
|
+
* anything the simple filters cannot express.
|
|
14
|
+
*/
|
|
15
|
+
async getProducts(catalogId, pagination = null, filters = {}, filter = null) {
|
|
16
|
+
const queryString = new QueryString('/pulse/catalogs/' + catalogId.toString() + '/products');
|
|
17
|
+
queryString.set('expand', ['matches.vendor']);
|
|
18
|
+
if (filters.brand) {
|
|
19
|
+
queryString.set('brand', filters.brand);
|
|
20
|
+
}
|
|
21
|
+
if (filters.category) {
|
|
22
|
+
queryString.set('category', filters.category);
|
|
23
|
+
}
|
|
24
|
+
if (filters.search) {
|
|
25
|
+
queryString.set('search', filters.search);
|
|
26
|
+
}
|
|
27
|
+
if (filters.productGroup) {
|
|
28
|
+
queryString.set('product_group', filters.productGroup);
|
|
29
|
+
}
|
|
30
|
+
if (filters.tags) {
|
|
31
|
+
for (const [key, value] of Object.entries(filters.tags)) {
|
|
32
|
+
queryString.set('tag[' + key + ']', value);
|
|
33
|
+
}
|
|
34
|
+
}
|
|
35
|
+
if (filter !== null) {
|
|
36
|
+
queryString.set('filter', JSON.stringify(filter));
|
|
37
|
+
}
|
|
38
|
+
queryString.addPagination(pagination);
|
|
39
|
+
return await this.requestCollection(queryString, CatalogProductWithMatches.parse);
|
|
40
|
+
}
|
|
41
|
+
async getFilterOptions(catalogId) {
|
|
42
|
+
const result = await this.requestObject('/pulse/catalogs/' + catalogId.toString() + '/filter-options', null, (raw) => ({
|
|
43
|
+
brands: raw.brands ?? [],
|
|
44
|
+
categories: raw.categories ?? [],
|
|
45
|
+
productGroups: raw.product_groups ?? [],
|
|
46
|
+
tags: raw.tags ?? {},
|
|
47
|
+
}), 'GET');
|
|
48
|
+
return result.getData() ?? { brands: [], categories: [], productGroups: [], tags: {} };
|
|
49
|
+
}
|
|
50
|
+
/** Recalculate the catalog's cached statistics (price index, match counts, segments). */
|
|
51
|
+
async recomputeStatistics(catalogId) {
|
|
52
|
+
await this.requestObject('/pulse/catalogs/' + catalogId.toString() + '/recompute-stats', {}, (raw) => raw, 'POST');
|
|
53
|
+
}
|
|
54
|
+
}
|
|
@@ -0,0 +1,44 @@
|
|
|
1
|
+
import { CatalogId } from '../../Catalog/Model/CatalogId.js';
|
|
2
|
+
import { CollectionResult } from '../../Model/Result/CollectionResult.js';
|
|
3
|
+
import { Endpoint } from '../../Service/Endpoint.js';
|
|
4
|
+
import { PriceIndexSnapshotEntry } from '../Model/PriceIndexSnapshotEntry.js';
|
|
5
|
+
import { TopCompetitor } from '../Model/TopCompetitor.js';
|
|
6
|
+
/** Which axis the products are bucketed on. */
|
|
7
|
+
export type ProductSegmentType = 'price' | 'profit';
|
|
8
|
+
/** How many products fall in a segment now versus the previous period. */
|
|
9
|
+
export type ProductsSegment = {
|
|
10
|
+
code: string;
|
|
11
|
+
current: number;
|
|
12
|
+
previous: number;
|
|
13
|
+
};
|
|
14
|
+
/** One headline figure of the catalog, with its previous-period value to compare against. */
|
|
15
|
+
export type MarketSummaryEntry = {
|
|
16
|
+
id: string;
|
|
17
|
+
title: string;
|
|
18
|
+
currentAmount: number;
|
|
19
|
+
previousAmount: number;
|
|
20
|
+
};
|
|
21
|
+
/**
|
|
22
|
+
* Aggregated Market Pulse figures for a catalog — `/pulse/catalogs/:catalogId/statistics/*`.
|
|
23
|
+
* These are precomputed server-side; `CatalogProductEndpoint.recomputeStatistics` refreshes them.
|
|
24
|
+
*/
|
|
25
|
+
export declare class PulseStatisticsEndpoint extends Endpoint {
|
|
26
|
+
/** Headline figures (products tracked, matches, competitors …) against the previous period. */
|
|
27
|
+
getAccountSummary(catalogId: CatalogId | string): Promise<CollectionResult<MarketSummaryEntry>>;
|
|
28
|
+
/** Distribution of the catalog's products across price or profit segments. */
|
|
29
|
+
getProductSegments(catalogId: CatalogId | string, type?: ProductSegmentType | null): Promise<CollectionResult<ProductsSegment>>;
|
|
30
|
+
/**
|
|
31
|
+
* The competitors with the most matches against this catalog. `period` is the number of days
|
|
32
|
+
* the comparison against the previous period spans.
|
|
33
|
+
*/
|
|
34
|
+
getTopCompetitors(catalogId: CatalogId | string, limit?: number | null, period?: number | null): Promise<CollectionResult<TopCompetitor>>;
|
|
35
|
+
/**
|
|
36
|
+
* Price index per competitor over time, for charting. Pass the competitors to include, and
|
|
37
|
+
* optionally a product group to scope to and a date range (`YYYY-MM-DD`).
|
|
38
|
+
*/
|
|
39
|
+
getPriceIndexHistory(catalogId: CatalogId | string, competitorIds?: string[], options?: {
|
|
40
|
+
group?: string;
|
|
41
|
+
from?: string;
|
|
42
|
+
to?: string;
|
|
43
|
+
}): Promise<CollectionResult<PriceIndexSnapshotEntry>>;
|
|
44
|
+
}
|
|
@@ -0,0 +1,65 @@
|
|
|
1
|
+
import { QueryString } from '../../Http/Data/QueryString.js';
|
|
2
|
+
import { Endpoint } from '../../Service/Endpoint.js';
|
|
3
|
+
import { PriceIndexSnapshotEntry } from '../Model/PriceIndexSnapshotEntry.js';
|
|
4
|
+
import { TopCompetitor } from '../Model/TopCompetitor.js';
|
|
5
|
+
/**
|
|
6
|
+
* Aggregated Market Pulse figures for a catalog — `/pulse/catalogs/:catalogId/statistics/*`.
|
|
7
|
+
* These are precomputed server-side; `CatalogProductEndpoint.recomputeStatistics` refreshes them.
|
|
8
|
+
*/
|
|
9
|
+
export class PulseStatisticsEndpoint extends Endpoint {
|
|
10
|
+
/** Headline figures (products tracked, matches, competitors …) against the previous period. */
|
|
11
|
+
async getAccountSummary(catalogId) {
|
|
12
|
+
return await this.requestCollection('/pulse/catalogs/' + catalogId.toString() + '/statistics/account-summary', (raw) => ({
|
|
13
|
+
id: raw.id,
|
|
14
|
+
title: raw.title,
|
|
15
|
+
currentAmount: raw.current_amount ?? 0,
|
|
16
|
+
previousAmount: raw.previous_amount ?? 0,
|
|
17
|
+
}));
|
|
18
|
+
}
|
|
19
|
+
/** Distribution of the catalog's products across price or profit segments. */
|
|
20
|
+
async getProductSegments(catalogId, type = null) {
|
|
21
|
+
const queryString = new QueryString('/pulse/catalogs/' + catalogId.toString() + '/statistics/product-segments');
|
|
22
|
+
if (type !== null) {
|
|
23
|
+
queryString.set('type', type);
|
|
24
|
+
}
|
|
25
|
+
return await this.requestCollection(queryString, (raw) => ({
|
|
26
|
+
code: raw.code,
|
|
27
|
+
current: raw.current ?? 0,
|
|
28
|
+
previous: raw.previous ?? 0,
|
|
29
|
+
}));
|
|
30
|
+
}
|
|
31
|
+
/**
|
|
32
|
+
* The competitors with the most matches against this catalog. `period` is the number of days
|
|
33
|
+
* the comparison against the previous period spans.
|
|
34
|
+
*/
|
|
35
|
+
async getTopCompetitors(catalogId, limit = null, period = null) {
|
|
36
|
+
const queryString = new QueryString('/pulse/catalogs/' + catalogId.toString() + '/statistics/top-competitors');
|
|
37
|
+
if (limit !== null) {
|
|
38
|
+
queryString.set('limit', limit);
|
|
39
|
+
}
|
|
40
|
+
if (period !== null) {
|
|
41
|
+
queryString.set('period', period);
|
|
42
|
+
}
|
|
43
|
+
return await this.requestCollection(queryString, TopCompetitor.parse);
|
|
44
|
+
}
|
|
45
|
+
/**
|
|
46
|
+
* Price index per competitor over time, for charting. Pass the competitors to include, and
|
|
47
|
+
* optionally a product group to scope to and a date range (`YYYY-MM-DD`).
|
|
48
|
+
*/
|
|
49
|
+
async getPriceIndexHistory(catalogId, competitorIds = [], options = {}) {
|
|
50
|
+
const queryString = new QueryString('/pulse/catalogs/' + catalogId.toString() + '/statistics/price-index-history');
|
|
51
|
+
if (competitorIds.length > 0) {
|
|
52
|
+
queryString.set('competitor', competitorIds.join(','));
|
|
53
|
+
}
|
|
54
|
+
if (options.group) {
|
|
55
|
+
queryString.set('group', options.group);
|
|
56
|
+
}
|
|
57
|
+
if (options.from) {
|
|
58
|
+
queryString.set('from', options.from);
|
|
59
|
+
}
|
|
60
|
+
if (options.to) {
|
|
61
|
+
queryString.set('to', options.to);
|
|
62
|
+
}
|
|
63
|
+
return await this.requestCollection(queryString, PriceIndexSnapshotEntry.parse);
|
|
64
|
+
}
|
|
65
|
+
}
|