From 224f05e47c16a03c694b52c8399573e226506a6f Mon Sep 17 00:00:00 2001 From: Martijn Date: Wed, 1 Nov 2023 08:21:04 +0100 Subject: [PATCH 1/4] fix(picqer): fulfill again on incoming webhook for backorders --- packages/util/src/order-state-util.ts | 16 ++++---- packages/vendure-plugin-picqer/package.json | 2 +- .../src/api/picqer.service.ts | 40 ++++++++++++++++++- 3 files changed, 47 insertions(+), 11 deletions(-) diff --git a/packages/util/src/order-state-util.ts b/packages/util/src/order-state-util.ts index 140b3dce..4f697370 100644 --- a/packages/util/src/order-state-util.ts +++ b/packages/util/src/order-state-util.ts @@ -84,7 +84,7 @@ export async function transitionToDelivered( } /** - * Throw an error if the transition failed + * Throws the error result if the transition failed */ export function throwIfTransitionFailed( result: @@ -93,17 +93,15 @@ export function throwIfTransitionFailed( | AddFulfillmentToOrderResult ): void { const stateError = result as FulfillmentStateTransitionError; - if (stateError.transitionError) { - if (stateError.fromState === stateError.toState) { - return; // If already 'Shipped', don't count this as an error - } - throw Error( - `${stateError.message} - from ${stateError.fromState} to ${stateError.toState} - ${stateError.transitionError}` - ); + if ( + stateError.transitionError && + stateError.fromState === stateError.toState + ) { + return; // If already 'Shipped', don't count this as an error } // It's not a stateTransition error const error = result as ErrorResult; if (error.errorCode) { - throw Error(`${error.errorCode}: ${error.message}`); + throw error; } } diff --git a/packages/vendure-plugin-picqer/package.json b/packages/vendure-plugin-picqer/package.json index 2a0bd600..b6c5cae1 100644 --- a/packages/vendure-plugin-picqer/package.json +++ b/packages/vendure-plugin-picqer/package.json @@ -1,6 +1,6 @@ { "name": "@pinelab/vendure-plugin-picqer", - "version": "2.0.1", + "version": "2.0.2", "description": "Vendure plugin syncing to orders and stock with Picqer", "author": "Martijn van de Brug ", "homepage": "https://pinelab-plugins.com/", diff --git a/packages/vendure-plugin-picqer/src/api/picqer.service.ts b/packages/vendure-plugin-picqer/src/api/picqer.service.ts index 3ac664eb..0e52d9d3 100644 --- a/packages/vendure-plugin-picqer/src/api/picqer.service.ts +++ b/packages/vendure-plugin-picqer/src/api/picqer.service.ts @@ -407,8 +407,24 @@ export class PicqerService implements OnApplicationBootstrap { if (data.status === 'completed' && order.state !== 'Delivered') { // Order should be transitioned to Shipped, then to Delivered if (order.state !== 'Shipped') { + // Try to fulfill order first. This should have been done already, except for back orders + try { + const fulfillment = await fulfillAll(ctx, this.orderService, order, { + code: picqerHandler.code, + arguments: [], + }); + Logger.info( + `Created fulfillment (${fulfillment.id}) for order ${order.code}`, + loggerCtx + ); + } catch (e: any) { + Logger.error( + `Failed to fulfill order ${order.code}: ${e?.message}. Transition this order manually to 'Delivered' if it has been sent to Picqer, to prevent future errors related to status changes for this order.`, + loggerCtx, + util.inspect(e) + ); + } // If order isn't Shipped yet, mark all it's fulfillments as Shipped - // The order should already have been fulfilled when pushing to Picqer for (const fulfillment of order.fulfillments) { const result = await this.orderService.transitionFulfillmentToState( ctx, @@ -1177,6 +1193,28 @@ export class PicqerService implements OnApplicationBootstrap { }; } + /** + * Fulfill without throwing errors. Logs an error if fulfilment fails + */ + private async safeFulfill(ctx: RequestContext, order: Order): Promise { + try { + const fulfillment = await fulfillAll(ctx, this.orderService, order, { + code: picqerHandler.code, + arguments: [], + }); + Logger.info( + `Created fulfillment (${fulfillment.id}) for order ${order.code}`, + loggerCtx + ); + } catch (e: any) { + Logger.error( + `Failed to fulfill order ${order.code}: ${e?.message}. Transition this order manually to 'Delivered' after checking that it exists in Picqer.`, + loggerCtx, + util.inspect(e) + ); + } + } + /** * Combine street and housenumber to get a full readable address. * Returns undefined if address undefined From 944a4942ade831b47eb8a07582074dda36cccc9b Mon Sep 17 00:00:00 2001 From: Martijn Date: Wed, 1 Nov 2023 08:22:17 +0100 Subject: [PATCH 2/4] fix(picqer): changelog and version --- packages/vendure-plugin-picqer/CHANGELOG.md | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/packages/vendure-plugin-picqer/CHANGELOG.md b/packages/vendure-plugin-picqer/CHANGELOG.md index 7ebcc131..3b42f7c5 100644 --- a/packages/vendure-plugin-picqer/CHANGELOG.md +++ b/packages/vendure-plugin-picqer/CHANGELOG.md @@ -1,4 +1,8 @@ -# 2.0.0 +# 2.0.2 + +- Try to fulfill again on order status changed webhooks, to support fulfilling of back orders. + +# 2.0.1 - Push to Picqer even when fulfilling failed. Log order codes and manual steps needed when fulfillment fails. From 076e537bbff9626a6be11e583f4ba0b2a1cca77e Mon Sep 17 00:00:00 2001 From: Martijn Date: Wed, 1 Nov 2023 08:32:19 +0100 Subject: [PATCH 3/4] fix(picqer): reusable private fulfill --- .../src/api/picqer.service.ts | 42 ++++--------------- 1 file changed, 8 insertions(+), 34 deletions(-) diff --git a/packages/vendure-plugin-picqer/src/api/picqer.service.ts b/packages/vendure-plugin-picqer/src/api/picqer.service.ts index 0e52d9d3..f660563d 100644 --- a/packages/vendure-plugin-picqer/src/api/picqer.service.ts +++ b/packages/vendure-plugin-picqer/src/api/picqer.service.ts @@ -408,22 +408,7 @@ export class PicqerService implements OnApplicationBootstrap { // Order should be transitioned to Shipped, then to Delivered if (order.state !== 'Shipped') { // Try to fulfill order first. This should have been done already, except for back orders - try { - const fulfillment = await fulfillAll(ctx, this.orderService, order, { - code: picqerHandler.code, - arguments: [], - }); - Logger.info( - `Created fulfillment (${fulfillment.id}) for order ${order.code}`, - loggerCtx - ); - } catch (e: any) { - Logger.error( - `Failed to fulfill order ${order.code}: ${e?.message}. Transition this order manually to 'Delivered' if it has been sent to Picqer, to prevent future errors related to status changes for this order.`, - loggerCtx, - util.inspect(e) - ); - } + await this.safeFulfill(ctx, order, 'order.status_changed webhook'); // If order isn't Shipped yet, mark all it's fulfillments as Shipped for (const fulfillment of order.fulfillments) { const result = await this.orderService.transitionFulfillmentToState( @@ -744,22 +729,7 @@ export class PicqerService implements OnApplicationBootstrap { return; } // Fulfill order first - try { - const fulfillment = await fulfillAll(ctx, this.orderService, order, { - code: picqerHandler.code, - arguments: [], - }); - Logger.info( - `Created fulfillment (${fulfillment.id}) for order ${order.code}`, - loggerCtx - ); - } catch (e: any) { - Logger.error( - `Failed to fulfill order ${order.code}: ${e?.message}. Transition this order manually to 'Delivered' if it has been sent to Picqer, to prevent future errors related to status changes for this order.`, - loggerCtx, - util.inspect(e) - ); - } + await this.safeFulfill(ctx, order, 'order placement'); // Push the order to Picqer await this.pushOrderToPicqer(ctx, order, client); } @@ -1196,7 +1166,11 @@ export class PicqerService implements OnApplicationBootstrap { /** * Fulfill without throwing errors. Logs an error if fulfilment fails */ - private async safeFulfill(ctx: RequestContext, order: Order): Promise { + private async safeFulfill( + ctx: RequestContext, + order: Order, + logAction: string + ): Promise { try { const fulfillment = await fulfillAll(ctx, this.orderService, order, { code: picqerHandler.code, @@ -1208,7 +1182,7 @@ export class PicqerService implements OnApplicationBootstrap { ); } catch (e: any) { Logger.error( - `Failed to fulfill order ${order.code}: ${e?.message}. Transition this order manually to 'Delivered' after checking that it exists in Picqer.`, + `Failed to fulfill order ${order.code} on '${logAction}': ${e?.message}. Transition this order manually to 'Delivered' after checking that it exists in Picqer.`, loggerCtx, util.inspect(e) ); From 5a1645cd5106399fdac4750462f7fa8daf99c2aa Mon Sep 17 00:00:00 2001 From: Martijn Date: Wed, 1 Nov 2023 08:32:52 +0100 Subject: [PATCH 4/4] fix(picqer): extra logging --- packages/vendure-plugin-picqer/src/api/picqer.service.ts | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/packages/vendure-plugin-picqer/src/api/picqer.service.ts b/packages/vendure-plugin-picqer/src/api/picqer.service.ts index f660563d..1fc251bd 100644 --- a/packages/vendure-plugin-picqer/src/api/picqer.service.ts +++ b/packages/vendure-plugin-picqer/src/api/picqer.service.ts @@ -1177,7 +1177,7 @@ export class PicqerService implements OnApplicationBootstrap { arguments: [], }); Logger.info( - `Created fulfillment (${fulfillment.id}) for order ${order.code}`, + `Created fulfillment (${fulfillment.id}) for order ${order.code} on '${logAction}'`, loggerCtx ); } catch (e: any) {