@pinelab/vendure-plugin-qls-fulfillment 1.0.0-beta.3 → 1.0.0-beta.5

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
@@ -59,8 +59,9 @@ Make sure to monitor failed jobs: A job that failed after its retries were exhau
59
59
  2. A product was not synced to QLS
60
60
 
61
61
  Monitor your logs for the following text:
62
- * `QLS webhook error` - This means an incoming stock update webhook was not processed correctly.
63
- * `Error creating or updating variant` - This means a product was not synced to QLS.
62
+
63
+ - `QLS webhook error` - This means an incoming stock update webhook was not processed correctly.
64
+ - `Error creating or updating variant` - This means a product was not synced to QLS.
64
65
 
65
66
  Make sure to filter by logger context `QlsPlugin`, to prevent false positive alerts.
66
67
 
@@ -86,7 +86,7 @@ class QlsClient {
86
86
  if (!response.ok) {
87
87
  const errorText = await response.text();
88
88
  // Log error including the request body
89
- core_1.Logger.error(`QLS request failed: ${response.status} ${response.statusText} - ${errorText}`, constants_1.loggerCtx, data ? JSON.stringify(data, null, 2) : undefined);
89
+ core_1.Logger.error(`QLS request to '${url}' failed: ${response.status} ${response.statusText} - ${errorText}`, constants_1.loggerCtx, data ? JSON.stringify(data, null, 2) : undefined);
90
90
  throw new Error(errorText);
91
91
  }
92
92
  const contentType = response.headers.get('content-type') ?? '';
@@ -1,12 +1,13 @@
1
1
  import { OnApplicationBootstrap, OnModuleInit } from '@nestjs/common';
2
- import { EventBus, ID, Job, JobQueueService, ProductVariant, ProductVariantService, RequestContext, StockLevelService, StockLocationService, TransactionalConnection } from '@vendure/core';
2
+ import { EventBus, ID, Job, JobQueueService, ListQueryBuilder, ProductPriceApplicator, ProductVariant, ProductVariantService, RequestContext, StockLevelService, StockLocationService, TransactionalConnection } from '@vendure/core';
3
+ import { FulfillmentProduct } from '../lib/client-types';
3
4
  import { QlsClient } from '../lib/qls-client';
4
5
  import { QlsPluginOptions, QlsProductJobData } from '../types';
5
- import { FulfillmentProduct } from '../lib/client-types';
6
6
  type SyncProductsJobResult = {
7
7
  updatedInQls: number;
8
8
  createdInQls: number;
9
9
  updatedStock: number;
10
+ failed: number;
10
11
  };
11
12
  export declare class QlsProductService implements OnModuleInit, OnApplicationBootstrap {
12
13
  private connection;
@@ -16,8 +17,10 @@ export declare class QlsProductService implements OnModuleInit, OnApplicationBoo
16
17
  private readonly variantService;
17
18
  private readonly stockLocationService;
18
19
  private readonly eventBus;
20
+ private readonly listQueryBuilder;
21
+ private readonly productPriceApplicator;
19
22
  private productJobQueue;
20
- constructor(connection: TransactionalConnection, options: QlsPluginOptions, jobQueueService: JobQueueService, stockLevelService: StockLevelService, variantService: ProductVariantService, stockLocationService: StockLocationService, eventBus: EventBus);
23
+ constructor(connection: TransactionalConnection, options: QlsPluginOptions, jobQueueService: JobQueueService, stockLevelService: StockLevelService, variantService: ProductVariantService, stockLocationService: StockLocationService, eventBus: EventBus, listQueryBuilder: ListQueryBuilder, productPriceApplicator: ProductPriceApplicator);
21
24
  onApplicationBootstrap(): void;
22
25
  onModuleInit(): Promise<void>;
23
26
  /**
@@ -19,11 +19,12 @@ exports.QlsProductService = void 0;
19
19
  const common_1 = require("@nestjs/common");
20
20
  const core_1 = require("@vendure/core");
21
21
  const catch_unknown_1 = require("catch-unknown");
22
+ const typeorm_1 = require("typeorm");
22
23
  const util_1 = __importDefault(require("util"));
23
24
  const constants_1 = require("../constants");
24
25
  const qls_client_1 = require("../lib/qls-client");
25
26
  let QlsProductService = class QlsProductService {
26
- constructor(connection, options, jobQueueService, stockLevelService, variantService, stockLocationService, eventBus) {
27
+ constructor(connection, options, jobQueueService, stockLevelService, variantService, stockLocationService, eventBus, listQueryBuilder, productPriceApplicator) {
27
28
  this.connection = connection;
28
29
  this.options = options;
29
30
  this.jobQueueService = jobQueueService;
@@ -31,6 +32,8 @@ let QlsProductService = class QlsProductService {
31
32
  this.variantService = variantService;
32
33
  this.stockLocationService = stockLocationService;
33
34
  this.eventBus = eventBus;
35
+ this.listQueryBuilder = listQueryBuilder;
36
+ this.productPriceApplicator = productPriceApplicator;
34
37
  }
35
38
  onApplicationBootstrap() {
36
39
  // Listen for ProductVariantEvent and add a job to the queue
@@ -107,6 +110,7 @@ let QlsProductService = class QlsProductService {
107
110
  // Create or update products in QLS
108
111
  let createdQlsProductsCount = 0;
109
112
  let updatedQlsProductsCount = 0;
113
+ let failedCount = 0;
110
114
  for (const variant of allVariants) {
111
115
  try {
112
116
  const existingQlsProduct = allQlsProducts.find((p) => p.sku == variant.sku);
@@ -121,7 +125,9 @@ let QlsProductService = class QlsProductService {
121
125
  catch (e) {
122
126
  const error = (0, catch_unknown_1.asError)(e);
123
127
  core_1.Logger.error(`Error creating or updating variant '${variant.sku}' in QLS: ${error.message}`, constants_1.loggerCtx, error.stack);
128
+ failedCount += 1;
124
129
  }
130
+ await new Promise((resolve) => setTimeout(resolve, 700)); // Avoid rate limit of 500/5 minutes (700ms delay = 85/minute)
125
131
  }
126
132
  core_1.Logger.info(`Created ${createdQlsProductsCount} products in QLS`, constants_1.loggerCtx);
127
133
  core_1.Logger.info(`Updated ${updatedQlsProductsCount} products in QLS`, constants_1.loggerCtx);
@@ -129,6 +135,7 @@ let QlsProductService = class QlsProductService {
129
135
  updatedInQls: updatedQlsProductsCount,
130
136
  createdInQls: createdQlsProductsCount,
131
137
  updatedStock: updateStockCount,
138
+ failed: failedCount,
132
139
  };
133
140
  }
134
141
  catch (e) {
@@ -148,29 +155,44 @@ let QlsProductService = class QlsProductService {
148
155
  updatedInQls: 0,
149
156
  createdInQls: 0,
150
157
  updatedStock: 0,
158
+ failed: 0,
151
159
  };
152
160
  }
153
161
  let updatedInQls = 0;
154
162
  let createdInQls = 0;
163
+ let failedCount = 0;
155
164
  for (const variantId of productVariantIds) {
156
- const variant = await this.variantService.findOne(ctx, variantId);
157
- if (!variant) {
158
- core_1.Logger.error(`Variant with id ${variantId} not found. Not creating or updating product in QLS.`, constants_1.loggerCtx);
159
- continue;
160
- }
161
- const existingQlsProduct = await client.getFulfillmentProductBySku(variant.sku);
162
- const result = await this.createOrUpdateProductInQls(ctx, client, variant, existingQlsProduct ?? null);
163
- if (result === 'created') {
164
- createdInQls += 1;
165
+ try {
166
+ const variant = await this.variantService.findOne(ctx, variantId, [
167
+ 'featuredAsset',
168
+ 'taxCategory',
169
+ 'channels',
170
+ 'product.featuredAsset',
171
+ ]);
172
+ if (!variant) {
173
+ core_1.Logger.error(`Variant with id ${variantId} not found. Not creating or updating product in QLS.`, constants_1.loggerCtx);
174
+ continue;
175
+ }
176
+ const existingQlsProduct = await client.getFulfillmentProductBySku(variant.sku);
177
+ const result = await this.createOrUpdateProductInQls(ctx, client, variant, existingQlsProduct ?? null);
178
+ if (result === 'created') {
179
+ createdInQls += 1;
180
+ }
181
+ else if (result === 'updated') {
182
+ updatedInQls += 1;
183
+ }
165
184
  }
166
- else if (result === 'updated') {
167
- updatedInQls += 1;
185
+ catch (e) {
186
+ const error = (0, catch_unknown_1.asError)(e);
187
+ core_1.Logger.error(`Error syncing variant ${variantId} to QLS: ${error.message}`, constants_1.loggerCtx, error.stack);
188
+ failedCount += 1;
168
189
  }
169
190
  }
170
191
  return {
171
192
  updatedInQls,
172
193
  createdInQls,
173
194
  updatedStock: 0,
195
+ failed: failedCount,
174
196
  };
175
197
  }
176
198
  /**
@@ -270,16 +292,27 @@ let QlsProductService = class QlsProductService {
270
292
  const take = 100;
271
293
  let hasMore = true;
272
294
  while (hasMore) {
273
- const result = await this.variantService.findAll(ctx, {
274
- filter: { deletedAt: { isNull: true } },
295
+ const relations = [
296
+ 'featuredAsset',
297
+ 'taxCategory',
298
+ 'channels',
299
+ 'product.featuredAsset',
300
+ ];
301
+ const [items, totalItems] = await this.listQueryBuilder
302
+ .build(core_1.ProductVariant, {
275
303
  skip,
276
304
  take,
277
- });
278
- if (!result.items.length) {
279
- break;
280
- }
281
- allVariants.push(...result.items);
282
- if (allVariants.length >= result.totalItems) {
305
+ }, {
306
+ relations,
307
+ channelId: ctx.channelId,
308
+ where: { deletedAt: (0, typeorm_1.IsNull)() },
309
+ ctx,
310
+ })
311
+ .getManyAndCount();
312
+ let variants = await Promise.all(items.map(async (item) => this.productPriceApplicator.applyChannelPriceAndTax(item, ctx, undefined, false)));
313
+ variants = variants.map((v) => (0, core_1.translateDeep)(v, ctx.languageCode));
314
+ allVariants.push(...variants);
315
+ if (allVariants.length >= totalItems) {
283
316
  hasMore = false;
284
317
  }
285
318
  skip += take;
@@ -311,5 +344,7 @@ exports.QlsProductService = QlsProductService = __decorate([
311
344
  core_1.StockLevelService,
312
345
  core_1.ProductVariantService,
313
346
  core_1.StockLocationService,
314
- core_1.EventBus])
347
+ core_1.EventBus,
348
+ core_1.ListQueryBuilder,
349
+ core_1.ProductPriceApplicator])
315
350
  ], QlsProductService);
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@pinelab/vendure-plugin-qls-fulfillment",
3
- "version": "1.0.0-beta.3",
3
+ "version": "1.0.0-beta.5",
4
4
  "description": "Vendure plugin to fulfill orders via QLS.",
5
5
  "keywords": [
6
6
  "fulfillment",