From f798cce4fca0d146d38e09cd1d960191c4d21efc Mon Sep 17 00:00:00 2001 From: Aldo W Date: Mon, 12 Aug 2024 01:37:46 -0400 Subject: [PATCH 1/5] feat: implement, prototype, tests, resources --- resources/fulfillment-order.js | 15 +++++ test/fixtures/fulfillment-order/req/hold.json | 7 +++ test/fixtures/fulfillment-order/req/index.js | 1 + test/fixtures/fulfillment-order/res/hold.json | 61 +++++++++++++++++++ test/fixtures/fulfillment-order/res/index.js | 1 + test/fulfillment-order.test.js | 13 ++++ types/index.d.ts | 1 + 7 files changed, 99 insertions(+) create mode 100644 test/fixtures/fulfillment-order/req/hold.json create mode 100644 test/fixtures/fulfillment-order/res/hold.json diff --git a/resources/fulfillment-order.js b/resources/fulfillment-order.js index 460fe10d..7cb6c290 100644 --- a/resources/fulfillment-order.js +++ b/resources/fulfillment-order.js @@ -127,4 +127,19 @@ FulfillmentOrder.prototype.fulfillments = function fulfillments(id) { return this.shopify.request(url, 'GET', 'fulfillments'); }; +/** + * Halts all fulfillment work on a fulfillment order with + * status OPEN and changes the status of the fulfillment order to ON_HOLD. + * + * @param {Number} id Order ID + * @return {Promise} Promise that resolves with the result + * @public + */ +FulfillmentOrder.prototype.hold = function hold(id, params) { + const url = this.buildUrl(`${id}/hold`); + return this.shopify + .request(url, 'POST', undefined, params) + .then((body) => body[this.key]); +}; + module.exports = FulfillmentOrder; diff --git a/test/fixtures/fulfillment-order/req/hold.json b/test/fixtures/fulfillment-order/req/hold.json new file mode 100644 index 00000000..d7ee489d --- /dev/null +++ b/test/fixtures/fulfillment-order/req/hold.json @@ -0,0 +1,7 @@ +{ + "fulfillment_hold": { + "reason": "inventory_out_of_stock", + "reason_notes": "Not enough inventory to complete this work.", + "fulfillment_order_line_items": [{ "id": 1058737493, "quantity": 1 }] + } +} diff --git a/test/fixtures/fulfillment-order/req/index.js b/test/fixtures/fulfillment-order/req/index.js index 54a1d09a..3aed5fa6 100644 --- a/test/fixtures/fulfillment-order/req/index.js +++ b/test/fixtures/fulfillment-order/req/index.js @@ -4,3 +4,4 @@ exports.cancel = require('./cancel'); exports.close = require('./close'); exports.move = require('./move'); exports.setFulfillmentOrdersDeadline = require('./set-fulfillment-orders-deadline'); +exports.hold = require('./hold'); diff --git a/test/fixtures/fulfillment-order/res/hold.json b/test/fixtures/fulfillment-order/res/hold.json new file mode 100644 index 00000000..31844af5 --- /dev/null +++ b/test/fixtures/fulfillment-order/res/hold.json @@ -0,0 +1,61 @@ +{ + "fulfillment_order": { + "id": 1046000789, + "shop_id": 548380009, + "order_id": 450789469, + "assigned_location_id": 24826418, + "request_status": "unsubmitted", + "status": "on_hold", + "fulfill_at": null, + "supported_actions": ["release_hold"], + "destination": { + "id": 1046000789, + "address1": "Chestnut Street 92", + "address2": "", + "city": "Louisville", + "company": null, + "country": "United States", + "email": "bob.norman@mail.example.com", + "first_name": "Bob", + "last_name": "Norman", + "phone": "+1(502)-459-2181", + "province": "Kentucky", + "zip": "40202" + }, + "line_items": [ + { + "id": 1058737493, + "shop_id": 548380009, + "fulfillment_order_id": 1046000789, + "quantity": 1, + "line_item_id": 518995019, + "inventory_item_id": 49148385, + "fulfillable_quantity": 1, + "variant_id": 49148385 + } + ], + "international_duties": null, + "fulfillment_holds": [ + { + "reason": "inventory_out_of_stock", + "reason_notes": "Not enough inventory to complete this work." + } + ], + "fulfill_by": null, + "created_at": "2024-07-24T06:26:32-04:00", + "updated_at": "2024-07-24T06:26:33-04:00", + "delivery_method": null, + "assigned_location": { + "address1": null, + "address2": null, + "city": null, + "country_code": "DE", + "location_id": 24826418, + "name": "Apple Api Shipwire", + "phone": null, + "province": null, + "zip": null + }, + "merchant_requests": [] + } +} diff --git a/test/fixtures/fulfillment-order/res/index.js b/test/fixtures/fulfillment-order/res/index.js index 56f1bc0e..21cdfab6 100644 --- a/test/fixtures/fulfillment-order/res/index.js +++ b/test/fixtures/fulfillment-order/res/index.js @@ -7,3 +7,4 @@ exports.close = require('./close'); exports.list = require('./list'); exports.move = require('./move'); exports.get = require('./get'); +exports.hold = require('./hold'); diff --git a/test/fulfillment-order.test.js b/test/fulfillment-order.test.js index b3e9626f..a0f8d82e 100644 --- a/test/fulfillment-order.test.js +++ b/test/fulfillment-order.test.js @@ -134,4 +134,17 @@ describe('Shopify#fulfillmentOrder', () => { .fulfillments(1046000823) .then((data) => expect(data).to.deep.equal(output.fulfillments)); }); + + it('applies a fulfillment hold on an open fulfillment order', () => { + const input = fixtures.req.hold; + const output = fixtures.res.hold; + + scope + .post('/admin/fulfillment_orders/1046000789/hold.json', input) + .reply(200, output); + + return shopify.fulfillmentOrder.hold(1046000789).then((data) => { + expect(data).to.deep.equal(output.fulfillment_order); + }); + }); }); diff --git a/types/index.d.ts b/types/index.d.ts index 44c1d9e9..dad80fd1 100644 --- a/types/index.d.ts +++ b/types/index.d.ts @@ -389,6 +389,7 @@ declare class Shopify { fulfillments: ( id: number ) => Promise>; + hold: (id: number, params: any) => Promise; }; fulfillmentRequest: { accept: ( From fe4c2909685d1546643c74a5b5d0c84f5b14403b Mon Sep 17 00:00:00 2001 From: Aldo W Date: Wed, 14 Aug 2024 01:27:25 -0400 Subject: [PATCH 2/5] feat(fulfillment-order): add hold method --- resources/fulfillment-order.js | 18 +++++++++++++++--- 1 file changed, 15 insertions(+), 3 deletions(-) diff --git a/resources/fulfillment-order.js b/resources/fulfillment-order.js index 7cb6c290..5dfa7227 100644 --- a/resources/fulfillment-order.js +++ b/resources/fulfillment-order.js @@ -131,14 +131,26 @@ FulfillmentOrder.prototype.fulfillments = function fulfillments(id) { * Halts all fulfillment work on a fulfillment order with * status OPEN and changes the status of the fulfillment order to ON_HOLD. * - * @param {Number} id Order ID - * @return {Promise} Promise that resolves with the result + * @param {Number} id Fulfillment Order id (fulfillment_order_id). + * @param {Object} params + * @param {String} params.reason 'awaiting_paymet' | 'high_risk_of_fraud' + * | 'incorrect_address' | 'inventory_out_of_stock' | 'other'. + * @param {String} params.reason_notes (optiona) Additional information about + * the fulfillment hold reason. + * @param {Boolean} params.notify_merchant (optional) Whether the merchant + * should receive a notification about the fulfillment hold. + * If set to true, then the merchant will be notified on the Shopify + * mobile app (if they use it to manage their store). + * The default value is false. + * @param {Array} params.fulfillment_order_line_items (optional) array of + * fulfillment order line item ids and the quantity of each to move. + * @return {Promise} Promise that resolves with the result. * @public */ FulfillmentOrder.prototype.hold = function hold(id, params) { const url = this.buildUrl(`${id}/hold`); return this.shopify - .request(url, 'POST', undefined, params) + .request(url, 'POST', undefined, { fulfillment_hold: params }) .then((body) => body[this.key]); }; From 0605e8da8fd7b8b230aa3edf0cdc1e20eff4edfa Mon Sep 17 00:00:00 2001 From: Aldo W Date: Wed, 14 Aug 2024 01:38:06 -0400 Subject: [PATCH 3/5] docs: add types --- types/index.d.ts | 23 ++++++++++++++++++++++- 1 file changed, 22 insertions(+), 1 deletion(-) diff --git a/types/index.d.ts b/types/index.d.ts index dad80fd1..087ed712 100644 --- a/types/index.d.ts +++ b/types/index.d.ts @@ -389,7 +389,10 @@ declare class Shopify { fulfillments: ( id: number ) => Promise>; - hold: (id: number, params: any) => Promise; + hold: ( + id: number, + params: Shopify.IHoldFulfillmentOrder + ) => Promise; }; fulfillmentRequest: { accept: ( @@ -3568,4 +3571,22 @@ declare namespace Shopify { }; updated_at: string; } + + interface IHoldFulfillmentOrder { + reason: + | 'awaiting_payment' + | 'high_risk_of_fraud' + | 'incorrect_address' + | 'inventory_out_of_stock' + | 'other'; + reason_notes?: string; + notify_merchant: boolean; + line_items: IUpdateFulfillmentOrderLineItem; + fulfillment_order_id: number; + } + + interface IUpdateFulfillmentOrderLineItem { + id: number; + quantity: number; + } } From 93f579f15fd7564f24adc1d56c29683134e1cc04 Mon Sep 17 00:00:00 2001 From: Luigi Pinca Date: Tue, 20 Aug 2024 11:06:00 +0200 Subject: [PATCH 4/5] Apply suggestions from code review --- resources/fulfillment-order.js | 16 +++------------- types/index.d.ts | 9 ++++----- 2 files changed, 7 insertions(+), 18 deletions(-) diff --git a/resources/fulfillment-order.js b/resources/fulfillment-order.js index 5dfa7227..1e73b798 100644 --- a/resources/fulfillment-order.js +++ b/resources/fulfillment-order.js @@ -132,19 +132,9 @@ FulfillmentOrder.prototype.fulfillments = function fulfillments(id) { * status OPEN and changes the status of the fulfillment order to ON_HOLD. * * @param {Number} id Fulfillment Order id (fulfillment_order_id). - * @param {Object} params - * @param {String} params.reason 'awaiting_paymet' | 'high_risk_of_fraud' - * | 'incorrect_address' | 'inventory_out_of_stock' | 'other'. - * @param {String} params.reason_notes (optiona) Additional information about - * the fulfillment hold reason. - * @param {Boolean} params.notify_merchant (optional) Whether the merchant - * should receive a notification about the fulfillment hold. - * If set to true, then the merchant will be notified on the Shopify - * mobile app (if they use it to manage their store). - * The default value is false. - * @param {Array} params.fulfillment_order_line_items (optional) array of - * fulfillment order line item ids and the quantity of each to move. - * @return {Promise} Promise that resolves with the result. +* @param {Object} params An object containing the reason for the fulfillment + hold and additional optional information + * @return {Promise} Promise that resolves with the result * @public */ FulfillmentOrder.prototype.hold = function hold(id, params) { diff --git a/types/index.d.ts b/types/index.d.ts index 087ed712..4d88ca88 100644 --- a/types/index.d.ts +++ b/types/index.d.ts @@ -391,7 +391,7 @@ declare class Shopify { ) => Promise>; hold: ( id: number, - params: Shopify.IHoldFulfillmentOrder + params: Shopify.IFulfillmentHold ) => Promise; }; fulfillmentRequest: { @@ -3572,7 +3572,7 @@ declare namespace Shopify { updated_at: string; } - interface IHoldFulfillmentOrder { + interface IFulfillmentHold { reason: | 'awaiting_payment' | 'high_risk_of_fraud' @@ -3580,9 +3580,8 @@ declare namespace Shopify { | 'inventory_out_of_stock' | 'other'; reason_notes?: string; - notify_merchant: boolean; - line_items: IUpdateFulfillmentOrderLineItem; - fulfillment_order_id: number; + notify_merchant?: boolean; + fulfillment_order_line_items?: IUpdateFulfillmentOrderLineItem[]; } interface IUpdateFulfillmentOrderLineItem { From 749760fe519fd0d5655fe08f22dd42c60d1f37ca Mon Sep 17 00:00:00 2001 From: Luigi Pinca Date: Tue, 20 Aug 2024 11:23:59 +0200 Subject: [PATCH 5/5] fixup! Apply suggestions from code review --- README.md | 3 ++- resources/fulfillment-order.js | 6 +++--- test/fixtures/fulfillment-order/req/index.js | 2 +- test/fulfillment-order.test.js | 8 +++++--- types/index.d.ts | 12 ++++++------ 5 files changed, 17 insertions(+), 14 deletions(-) diff --git a/README.md b/README.md index cefc3e20..ffca94c4 100644 --- a/README.md +++ b/README.md @@ -482,12 +482,13 @@ default. - fulfillmentOrder - `cancel(id, params)` - `close(id[, message])` + - `fulfillments(id)` - `get(id)` + - `hold(id, params)` - `list([params])` - `locationsForMove(id)` - `move(id, locationId)` - `setFulfillmentOrdersDeadline(params)` - - `fulfillments(id)` - fulfillmentRequest - `accept(fulfillmentOrderId[, message])` - `create(fulfillmentOrderId, params)` diff --git a/resources/fulfillment-order.js b/resources/fulfillment-order.js index 1e73b798..04a5a8ff 100644 --- a/resources/fulfillment-order.js +++ b/resources/fulfillment-order.js @@ -131,9 +131,9 @@ FulfillmentOrder.prototype.fulfillments = function fulfillments(id) { * Halts all fulfillment work on a fulfillment order with * status OPEN and changes the status of the fulfillment order to ON_HOLD. * - * @param {Number} id Fulfillment Order id (fulfillment_order_id). -* @param {Object} params An object containing the reason for the fulfillment - hold and additional optional information + * @param {Number} id Fulfillment Order ID + * @param {Object} params An object containing the reason for the fulfillment + hold and additional optional information * @return {Promise} Promise that resolves with the result * @public */ diff --git a/test/fixtures/fulfillment-order/req/index.js b/test/fixtures/fulfillment-order/req/index.js index 3aed5fa6..6ed476d7 100644 --- a/test/fixtures/fulfillment-order/req/index.js +++ b/test/fixtures/fulfillment-order/req/index.js @@ -2,6 +2,6 @@ exports.cancel = require('./cancel'); exports.close = require('./close'); +exports.hold = require('./hold'); exports.move = require('./move'); exports.setFulfillmentOrdersDeadline = require('./set-fulfillment-orders-deadline'); -exports.hold = require('./hold'); diff --git a/test/fulfillment-order.test.js b/test/fulfillment-order.test.js index a0f8d82e..dfef4e40 100644 --- a/test/fulfillment-order.test.js +++ b/test/fulfillment-order.test.js @@ -143,8 +143,10 @@ describe('Shopify#fulfillmentOrder', () => { .post('/admin/fulfillment_orders/1046000789/hold.json', input) .reply(200, output); - return shopify.fulfillmentOrder.hold(1046000789).then((data) => { - expect(data).to.deep.equal(output.fulfillment_order); - }); + return shopify.fulfillmentOrder + .hold(1046000789, input.fulfillment_hold) + .then((data) => { + expect(data).to.deep.equal(output.fulfillment_order); + }); }); }); diff --git a/types/index.d.ts b/types/index.d.ts index 4d88ca88..e1677ed2 100644 --- a/types/index.d.ts +++ b/types/index.d.ts @@ -3572,6 +3572,11 @@ declare namespace Shopify { updated_at: string; } + interface IFulfillmentHoldFulfillmentOrderLineItem { + id: number; + quantity: number; + } + interface IFulfillmentHold { reason: | 'awaiting_payment' @@ -3581,11 +3586,6 @@ declare namespace Shopify { | 'other'; reason_notes?: string; notify_merchant?: boolean; - fulfillment_order_line_items?: IUpdateFulfillmentOrderLineItem[]; - } - - interface IUpdateFulfillmentOrderLineItem { - id: number; - quantity: number; + fulfillment_order_line_items?: IFulfillmentHoldFulfillmentOrderLineItem[]; } }