diff --git a/packages/integrations/src/builders/brands/brandAdministrativeActionBuilder.ts b/packages/integrations/src/builders/brands/brandAdministrativeActionBuilder.ts new file mode 100644 index 0000000..da7e2c8 --- /dev/null +++ b/packages/integrations/src/builders/brands/brandAdministrativeActionBuilder.ts @@ -0,0 +1,44 @@ +import { BrandAdministrativeAction, FilterBuilder } from '@relewise/client'; + +export class BrandAdministrativeActionBuilder { + private filterBuilder = new FilterBuilder(); + private kind: 'Disable' | 'Enable' | 'Delete'; + + language: string | null | undefined; + currency: string | null | undefined; + + constructor({ language, currency, kind, filters }: { + currency?: string | null, + language?: string | null, + kind: 'Disable' | 'Enable' | 'Delete', + filters: (filterBuilder: FilterBuilder) => void + }) { + this.language = language; + this.currency = currency; + this.kind = kind; + + filters(this.filterBuilder); + } + + filters(filters: (filterBuilder: FilterBuilder) => void): this { + filters(this.filterBuilder); + + return this; + } + + build(): BrandAdministrativeAction { + const filters = this.filterBuilder.build(); + + if (!filters || !filters.items || filters.items.length === 0) { + throw new Error('No filters were provided for the brand administrative action'); + } + + return { + $type: 'Relewise.Client.DataTypes.BrandAdministrativeAction, Relewise.Client', + ...(this.language && { language: { value: this.language } }), + ...(this.currency && { currency: { value: this.currency } }), + filters: filters, + kind: this.kind, + }; + } +} \ No newline at end of file diff --git a/packages/integrations/src/builders/brands/brandUpdateBuilder.ts b/packages/integrations/src/builders/brands/brandUpdateBuilder.ts new file mode 100644 index 0000000..fb9aeeb --- /dev/null +++ b/packages/integrations/src/builders/brands/brandUpdateBuilder.ts @@ -0,0 +1,40 @@ +import { DataValue, Brand, BrandUpdate } from '@relewise/client'; + +export class BrandUpdateBuilder { + private brand: Brand; + private updateKind: 'None' | 'UpdateAndAppend' | 'ReplaceProvidedProperties' | 'ClearAndReplace'; + + constructor({ id, updateKind }: { + id: string, + updateKind: 'None' | 'UpdateAndAppend' | 'ReplaceProvidedProperties' | 'ClearAndReplace', + }) { + this.brand = { id: id }; + this.updateKind = updateKind; + } + + displayName(name: string): this { + this.brand.displayName = name; + + return this; + } + + data(data: Record): this { + this.brand.data = data as Record; // TODO remove dirty hack + + return this; + } + + assortments(assortments: number[]): this { + this.brand.assortments = assortments; + + return this; + } + + build(): BrandUpdate { + return { + $type: 'Relewise.Client.DataTypes.BrandUpdate, Relewise.Client', + brand: this.brand, + kind: this.updateKind, + }; + } +} \ No newline at end of file diff --git a/packages/integrations/src/builders/brands/index.ts b/packages/integrations/src/builders/brands/index.ts new file mode 100644 index 0000000..5541a3c --- /dev/null +++ b/packages/integrations/src/builders/brands/index.ts @@ -0,0 +1,2 @@ +export * from './brandUpdateBuilder'; +export * from './brandAdministrativeActionBuilder'; \ No newline at end of file diff --git a/packages/integrations/src/builders/index.ts b/packages/integrations/src/builders/index.ts index 1d9d19d..8d3ff69 100644 --- a/packages/integrations/src/builders/index.ts +++ b/packages/integrations/src/builders/index.ts @@ -2,4 +2,5 @@ export * from './categoryPathBuilder'; export * from './products'; export * from './productcategories'; export * from './contentcategories'; -export * from './content'; \ No newline at end of file +export * from './content'; +export * from './brands'; \ No newline at end of file diff --git a/packages/integrations/src/integrator.ts b/packages/integrations/src/integrator.ts index 9e84980..68b8c5f 100644 --- a/packages/integrations/src/integrator.ts +++ b/packages/integrations/src/integrator.ts @@ -1,4 +1,4 @@ -import { RelewiseClient, RelewiseClientOptions, ProductUpdate, RelewiseRequestOptions, TrackProductUpdateRequest, ProductAdministrativeAction, TrackProductAdministrativeActionRequest, Trackable, SearchResponseCollection, BatchedTrackingRequest, ProductCategoryUpdate, TrackProductCategoryUpdateRequest, TrackProductCategoryAdministrativeActionRequest, ProductCategoryAdministrativeAction, ContentCategoryAdministrativeAction, ContentCategoryUpdate, TrackContentCategoryAdministrativeActionRequest, TrackContentCategoryUpdateRequest, ContentUpdate, TrackContentUpdateRequest, ContentAdministrativeAction, TrackContentAdministrativeActionRequest } from '@relewise/client'; +import { RelewiseClient, RelewiseClientOptions, ProductUpdate, RelewiseRequestOptions, TrackProductUpdateRequest, ProductAdministrativeAction, TrackProductAdministrativeActionRequest, Trackable, SearchResponseCollection, BatchedTrackingRequest, ProductCategoryUpdate, TrackProductCategoryUpdateRequest, TrackProductCategoryAdministrativeActionRequest, ProductCategoryAdministrativeAction, ContentCategoryAdministrativeAction, ContentCategoryUpdate, TrackContentCategoryAdministrativeActionRequest, TrackContentCategoryUpdateRequest, ContentUpdate, TrackContentUpdateRequest, ContentAdministrativeAction, TrackContentAdministrativeActionRequest, BrandUpdate, BrandAdministrativeAction, TrackBrandAdministrativeActionRequest, TrackBrandUpdateRequest } from '@relewise/client'; export class Integrator extends RelewiseClient { @@ -88,6 +88,26 @@ export class Integrator extends RelewiseClient { options); } + public async updateBrand(request: BrandUpdate, options?: RelewiseRequestOptions): Promise { + return this.request( + 'TrackBrandUpdateRequest', + { + $type: 'Relewise.Client.Requests.Tracking.TrackBrandUpdateRequest, Relewise.Client', + brandUpdate: request, + }, + options); + } + + public async executeBrandAdministrativeAction(request: BrandAdministrativeAction, options?: RelewiseRequestOptions): Promise { + return this.request( + 'TrackBrandAdministrativeActionRequest', + { + $type: 'Relewise.Client.Requests.Tracking.TrackBrandAdministrativeActionRequest, Relewise.Client', + administrativeAction: request, + }, + options); + } + public async batch(trackable: Trackable[], options?: RelewiseRequestOptions): Promise { if (!trackable) { throw new Error('No trackable items was provided'); diff --git a/packages/integrations/tests/integration-tests/brands/updates.integration.test.ts b/packages/integrations/tests/integration-tests/brands/updates.integration.test.ts new file mode 100644 index 0000000..9bddb9d --- /dev/null +++ b/packages/integrations/tests/integration-tests/brands/updates.integration.test.ts @@ -0,0 +1,41 @@ +import { test } from '@jest/globals'; +import { BrandUpdateBuilder, BrandAdministrativeActionBuilder, Integrator } from '../../../src'; +import { DataValueFactory } from '@relewise/client'; +const { npm_config_API_KEY: API_KEY, npm_config_DATASET_ID: DATASET_ID, npm_config_SERVER_URL: SERVER_URL } = process.env; + +const integrator = new Integrator(DATASET_ID!, API_KEY!, { serverUrl: SERVER_URL }); + +const unixTimeStamp: number = Date.now(); + +test('Create Brand', async() => { + const brand = new BrandUpdateBuilder({ + id: '1234', + updateKind: 'ReplaceProvidedProperties', + }) + .displayName('HP') + .data({ + 'UnixTimestamp': DataValueFactory.number(unixTimeStamp), + 'Description': DataValueFactory.string('Really nice Brand'), + 'Tags': DataValueFactory.stringCollection(['fall collection', 'blue', 'good-deal']), + 'InStock': DataValueFactory.boolean(true), + 'Removed': null, + 'Complex': DataValueFactory.object({ + 'nestedDataKey': DataValueFactory.string('Key'), + }), + }) + .assortments([1, 2, 3]); + + await integrator.updateBrand(brand.build()); + + const enable = new BrandAdministrativeActionBuilder({ + filters: (f) => f.addBrandDataFilter('UnixTimeStamp', c => c.addEqualsCondition(DataValueFactory.number(unixTimeStamp))), + kind: 'Enable', + }); + await integrator.executeBrandAdministrativeAction(enable.build()); + + const disable = new BrandAdministrativeActionBuilder({ + filters: (f) => f.addBrandDataFilter('UnixTimeStamp', c => c.addEqualsCondition(DataValueFactory.number(unixTimeStamp), /* negated: */ true)), + kind: 'Disable', + }); + await integrator.executeBrandAdministrativeAction(disable.build()); +}); \ No newline at end of file