@pinelab/vendure-plugin-sendcloud 1.1.0 → 1.2.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/CHANGELOG.md CHANGED
@@ -1,3 +1,7 @@
1
+ # 1.2.0 (2023-11-16)
2
+
3
+ - Fulfill on order placement, to prevent stock levels going out of sync
4
+
1
5
  # 1.1.0 (2023-10-24)
2
6
 
3
7
  - Updated vendure to 2.1.1
@@ -46,7 +46,7 @@ let SendcloudController = class SendcloudController {
46
46
  if (!body.parcel?.order_number) {
47
47
  return core_1.Logger.warn(`No order_number in incoming Sendcloud webhook: ${JSON.stringify(body.parcel)}`, constants_1.loggerCtx);
48
48
  }
49
- await this.sendcloudService.updateOrderStatus(ctx, status, body.parcel.order_number, body.parcel.tracking_number);
49
+ await this.sendcloudService.updateOrderStatus(ctx, status, body.parcel.order_number);
50
50
  }
51
51
  };
52
52
  __decorate([
@@ -1,7 +1,2 @@
1
1
  import { FulfillmentHandler } from '@vendure/core';
2
- export declare const sendcloudHandler: FulfillmentHandler<{
3
- trackingNumber: {
4
- type: "string";
5
- required: false;
6
- };
7
- }>;
2
+ export declare const sendcloudHandler: FulfillmentHandler<{}>;
@@ -11,18 +11,12 @@ exports.sendcloudHandler = new core_1.FulfillmentHandler({
11
11
  value: 'Send order to SendCloud',
12
12
  },
13
13
  ],
14
- args: {
15
- trackingNumber: {
16
- type: 'string',
17
- required: false,
18
- },
19
- },
14
+ args: {},
20
15
  createFulfillment: async (ctx, orders, orderItems, args) => {
21
16
  const orderCodes = orders.map((o) => o.code);
22
17
  core_1.Logger.info(`Fulfilled orders ${orderCodes.join(',')}`, constants_1.loggerCtx);
23
18
  return {
24
- method: `SendCloud - ${args.trackingNumber || orderCodes.join(',')} `,
25
- trackingCode: args.trackingNumber,
19
+ method: `SendCloud - ${orderCodes.join(',')} `,
26
20
  };
27
21
  },
28
22
  });
@@ -1,11 +1,11 @@
1
- import { OnApplicationBootstrap, OnModuleInit } from '@nestjs/common';
1
+ import { OnApplicationBootstrap } from '@nestjs/common';
2
2
  import { ModuleRef } from '@nestjs/core';
3
3
  import { ChannelService, EntityHydrator, EventBus, HistoryService, ID, JobQueueService, Order, OrderService, RequestContext, TransactionalConnection } from '@vendure/core';
4
4
  import { SendcloudConfigEntity } from './sendcloud-config.entity';
5
5
  import { SendcloudClient } from './sendcloud.client';
6
6
  import { Parcel } from './types/sendcloud-api.types';
7
7
  import { SendcloudParcelStatus, SendcloudPluginOptions } from './types/sendcloud.types';
8
- export declare class SendcloudService implements OnApplicationBootstrap, OnModuleInit {
8
+ export declare class SendcloudService implements OnApplicationBootstrap {
9
9
  private eventBus;
10
10
  private connection;
11
11
  private orderService;
@@ -17,18 +17,21 @@ export declare class SendcloudService implements OnApplicationBootstrap, OnModul
17
17
  private historyService;
18
18
  private jobQueue;
19
19
  constructor(eventBus: EventBus, connection: TransactionalConnection, orderService: OrderService, channelService: ChannelService, jobQueueService: JobQueueService, moduleRef: ModuleRef, options: SendcloudPluginOptions, entityHydrator: EntityHydrator, historyService: HistoryService);
20
- onModuleInit(): Promise<void>;
21
- onApplicationBootstrap(): void;
20
+ onApplicationBootstrap(): Promise<void>;
22
21
  createOrderInSendcloud(userCtx: RequestContext, order: Order): Promise<Parcel | undefined>;
23
22
  /**
24
23
  * Update order by given orderCode, returns undefined if no action was taken
25
24
  * Returns order if transition was successful
26
25
  */
27
- updateOrderStatus(ctx: RequestContext, sendcloudStatus: SendcloudParcelStatus, orderCode: string, trackingNumber: string): Promise<void>;
26
+ updateOrderStatus(ctx: RequestContext, sendcloudStatus: SendcloudParcelStatus, orderCode: string): Promise<void>;
28
27
  /**
29
- * Fulfill and ship all items
28
+ * Ship all items
30
29
  */
31
- shipAll(ctx: RequestContext, order: Order, trackingNumber: string): Promise<void>;
30
+ shipAll(ctx: RequestContext, order: Order): Promise<void>;
31
+ /**
32
+ * Fulfill without throwing errors. Logs an error if fulfilment fails
33
+ */
34
+ private safeFulfill;
32
35
  upsertConfig(ctx: RequestContext, config: {
33
36
  secret: string;
34
37
  publicKey: string;
@@ -11,6 +11,9 @@ var __metadata = (this && this.__metadata) || function (k, v) {
11
11
  var __param = (this && this.__param) || function (paramIndex, decorator) {
12
12
  return function (target, key) { decorator(target, key, paramIndex); }
13
13
  };
14
+ var __importDefault = (this && this.__importDefault) || function (mod) {
15
+ return (mod && mod.__esModule) ? mod : { "default": mod };
16
+ };
14
17
  Object.defineProperty(exports, "__esModule", { value: true });
15
18
  exports.SendcloudService = void 0;
16
19
  const common_1 = require("@nestjs/common");
@@ -22,6 +25,7 @@ const sendcloud_config_entity_1 = require("./sendcloud-config.entity");
22
25
  const sendcloud_client_1 = require("./sendcloud.client");
23
26
  const sendcloud_handler_1 = require("./sendcloud.handler");
24
27
  const src_1 = require("../../../util/src");
28
+ const util_1 = __importDefault(require("util"));
25
29
  let SendcloudService = class SendcloudService {
26
30
  constructor(eventBus, connection,
27
31
  // private rawConnection: Connection,
@@ -36,7 +40,15 @@ let SendcloudService = class SendcloudService {
36
40
  this.entityHydrator = entityHydrator;
37
41
  this.historyService = historyService;
38
42
  }
39
- async onModuleInit() {
43
+ async onApplicationBootstrap() {
44
+ // Listen for Settled orders to sync to sendcloud
45
+ this.eventBus.ofType(core_2.OrderPlacedEvent).subscribe(async (event) => {
46
+ await this.jobQueue.add({
47
+ orderCode: event.order.code,
48
+ ctx: event.ctx.serialize(),
49
+ }, { retries: 20 });
50
+ });
51
+ // Handle jobs
40
52
  this.jobQueue = await this.jobQueueService.createQueue({
41
53
  name: 'sendcloud',
42
54
  process: async ({ data }) => {
@@ -51,15 +63,6 @@ let SendcloudService = class SendcloudService {
51
63
  },
52
64
  });
53
65
  }
54
- onApplicationBootstrap() {
55
- // Listen for Settled orders to sync to sendcloud
56
- this.eventBus.ofType(core_2.OrderPlacedEvent).subscribe(async (event) => {
57
- await this.jobQueue.add({
58
- orderCode: event.order.code,
59
- ctx: event.ctx.serialize(),
60
- }, { retries: 20 });
61
- });
62
- }
63
66
  async createOrderInSendcloud(userCtx, order) {
64
67
  if (this.options.disabled) {
65
68
  core_2.Logger.info(`Plugin is disabled, not syncing order ${order.code}`, constants_1.loggerCtx);
@@ -94,7 +97,7 @@ let SendcloudService = class SendcloudService {
94
97
  * Update order by given orderCode, returns undefined if no action was taken
95
98
  * Returns order if transition was successful
96
99
  */
97
- async updateOrderStatus(ctx, sendcloudStatus, orderCode, trackingNumber) {
100
+ async updateOrderStatus(ctx, sendcloudStatus, orderCode) {
98
101
  let order = await this.connection
99
102
  .getRepository(ctx, core_2.Order)
100
103
  .findOne({ where: { code: orderCode }, relations: ['lines'] });
@@ -106,22 +109,16 @@ let SendcloudService = class SendcloudService {
106
109
  return core_2.Logger.info(`Not updating order with code ${orderCode}: Order already has state ${order.state}`, constants_1.loggerCtx);
107
110
  }
108
111
  if (sendcloudStatus.orderState === 'Shipped') {
109
- await this.shipAll(ctx, order, trackingNumber);
112
+ await this.shipAll(ctx, order);
110
113
  return core_2.Logger.info(`Successfully update order ${orderCode} to ${sendcloudStatus.orderState}`, constants_1.loggerCtx);
111
114
  }
112
115
  order = await this.connection
113
116
  .getRepository(ctx, core_2.Order)
114
117
  .findOneOrFail({ where: { code: orderCode }, relations: ['lines'] }); // Refetch in case state was updated
115
118
  if (sendcloudStatus.orderState === 'Delivered') {
116
- //FIX ME
117
119
  await (0, src_1.transitionToDelivered)(this.orderService, ctx, order, {
118
120
  code: sendcloud_handler_1.sendcloudHandler.code,
119
- arguments: [
120
- {
121
- name: 'trackingNumber',
122
- value: trackingNumber,
123
- },
124
- ],
121
+ arguments: [],
125
122
  });
126
123
  return core_2.Logger.info(`Successfully update order ${orderCode} to ${sendcloudStatus.orderState}`, constants_1.loggerCtx);
127
124
  }
@@ -129,19 +126,29 @@ let SendcloudService = class SendcloudService {
129
126
  core_2.Logger.info(`Not handling state ${sendcloudStatus.orderState}`, constants_1.loggerCtx);
130
127
  }
131
128
  /**
132
- * Fulfill and ship all items
129
+ * Ship all items
133
130
  */
134
- async shipAll(ctx, order, trackingNumber) {
131
+ async shipAll(ctx, order) {
135
132
  await (0, src_1.transitionToShipped)(this.orderService, ctx, order, {
136
133
  code: sendcloud_handler_1.sendcloudHandler.code,
137
- arguments: [
138
- {
139
- name: 'trackingNumber',
140
- value: trackingNumber,
141
- },
142
- ],
134
+ arguments: [],
143
135
  });
144
136
  }
137
+ /**
138
+ * Fulfill without throwing errors. Logs an error if fulfilment fails
139
+ */
140
+ async safeFulfill(ctx, order) {
141
+ try {
142
+ const fulfillment = await (0, src_1.fulfillAll)(ctx, this.orderService, order, {
143
+ code: sendcloud_handler_1.sendcloudHandler.code,
144
+ arguments: [],
145
+ });
146
+ core_2.Logger.info(`Created fulfillment (${fulfillment.id}) for order ${order.code}`, constants_1.loggerCtx);
147
+ }
148
+ catch (e) {
149
+ core_2.Logger.error(`Failed to fulfill order ${order.code}: ${e?.message}. Transition this order manually to 'Delivered' after checking that it exists in Sendcloud.`, constants_1.loggerCtx, util_1.default.inspect(e));
150
+ }
151
+ }
145
152
  async upsertConfig(ctx, config) {
146
153
  const repo = this.connection.getRepository(ctx, sendcloud_config_entity_1.SendcloudConfigEntity);
147
154
  const existing = await repo.findOne({
@@ -209,6 +216,7 @@ let SendcloudService = class SendcloudService {
209
216
  if (!hasSendcloudHandler) {
210
217
  return core_2.Logger.info(`Order ${order.code} does not have SendCloud set as handler. Not syncing this order.`, constants_1.loggerCtx);
211
218
  }
219
+ await this.safeFulfill(ctx, order);
212
220
  core_2.Logger.info(`Syncing order ${orderCode} for channel ${ctx.channel.token}`, constants_1.loggerCtx);
213
221
  const result = await this.createOrderInSendcloud(ctx, order);
214
222
  if (result) {
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@pinelab/vendure-plugin-sendcloud",
3
- "version": "1.1.0",
3
+ "version": "1.2.0",
4
4
  "description": "Vendure plugin for syncing orders with SendCloud",
5
5
  "author": "Martijn van de Brug <martijn@pinelab.studio>",
6
6
  "homepage": "https://pinelab-plugins.com/",
@@ -22,5 +22,5 @@
22
22
  "test": "vitest run",
23
23
  "start": "yarn ts-node test/dev-server.ts"
24
24
  },
25
- "gitHead": "985a9e6ffd5cec67d1a3a4d924c9bd4bf7faa982"
25
+ "gitHead": "51491de3e0babe4f579d880f935501c2b4d6f7a1"
26
26
  }