@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
|
-
|
|
63
|
-
|
|
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
|
|
package/dist/lib/qls-client.js
CHANGED
|
@@ -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
|
-
|
|
157
|
-
|
|
158
|
-
|
|
159
|
-
|
|
160
|
-
|
|
161
|
-
|
|
162
|
-
|
|
163
|
-
|
|
164
|
-
|
|
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
|
-
|
|
167
|
-
|
|
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
|
|
274
|
-
|
|
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
|
-
|
|
279
|
-
|
|
280
|
-
|
|
281
|
-
|
|
282
|
-
|
|
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);
|