diff --git a/CHANGELOG.md b/CHANGELOG.md index 116cc6a..08a22ef 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -5,6 +5,21 @@ All notable changes to this project will be documented in this file. The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/), and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html). +## [1.21.0] - 2022-05-03 + +### Added + +- Adds optional `total_price` and `currency` field to `order` creation +- Adds optional `amount` and `unit` field to `order` creation +- Adds inventory to `project` responses +- Adds inventory to `order` responses + +### Changed + +- Deprecates `mass_g` and `total_price_cents_usd` fields for create `order` requests +- Deprecates `average_price_per_tonne_cents_usd` and `remaining_mass_g` from `project` responses +- Deprecates `price_cents_usd`, `patch_fee_cents_usd`, and `mass_g` from `order` responses + ## [1.20.0] - 2022-04-18 ### Added diff --git a/README.md b/README.md index b978767..eff0bf2 100644 --- a/README.md +++ b/README.md @@ -65,15 +65,17 @@ fulfill the order for you. ```javascript // Create an order - you can create an order -// providing either mass_g or total_price_cents_usd, but not both +// providing either amount (and unit) or total_price (and currency), but not both -// Create order with mass -const mass = 1000000; // Pass in the mass in grams (i.e. 1 metric tonne) -patch.orders.createOrder({ mass_g: mass }); +// Create order with amount +const amount = 1_000_000; // Pass in the amount in unit specified +const unit = 'g'; +patch.orders.createOrder({ amount: amount, unit: unit }); -// Create an order with a maximum total price -const totalPriceCentsUSD = 500; // Pass in the total price in cents (i.e. 5 dollars) -patch.orders.createOrder({ total_price_cents_usd: totalPriceCentsUSD }); +// Create an order with total price +const totalPrice = 500; // Pass in the total price in smallest currency unit (ie cents for USD). +const currency = 'USD'; +patch.orders.createOrder({ total_price: totalPrice, currency: currency }); // Retrieve an order orderId = 'ord_test_1234'; // Pass in the order's id diff --git a/package-lock.json b/package-lock.json index 636e885..3c124c9 100644 --- a/package-lock.json +++ b/package-lock.json @@ -1,12 +1,12 @@ { "name": "@patch-technology/patch", - "version": "1.20.0", + "version": "1.21.0", "lockfileVersion": 2, "requires": true, "packages": { "": { "name": "@patch-technology/patch", - "version": "1.20.0", + "version": "1.21.0", "license": "MIT", "dependencies": { "query-string": "^7.0.1", diff --git a/package.json b/package.json index 30f3b4b..0432280 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "@patch-technology/patch", - "version": "1.20.0", + "version": "1.21.0", "description": "Node.js wrapper for the Patch API", "license": "MIT", "repository": { diff --git a/src/ApiClient.js b/src/ApiClient.js index ec9759f..e1fae62 100644 --- a/src/ApiClient.js +++ b/src/ApiClient.js @@ -16,7 +16,7 @@ class ApiClient { }; this.defaultHeaders = { - 'User-Agent': 'patch-node/1.20.0' + 'User-Agent': 'patch-node/1.21.0' }; /** diff --git a/src/model/CreateOrderRequest.js b/src/model/CreateOrderRequest.js index 4f57f80..e8d02fc 100644 --- a/src/model/CreateOrderRequest.js +++ b/src/model/CreateOrderRequest.js @@ -50,6 +50,25 @@ class CreateOrderRequest { 'Number' ); } + + if (data.hasOwnProperty('total_price')) { + obj['total_price'] = ApiClient.convertToType( + data['total_price'], + 'Number' + ); + } + + if (data.hasOwnProperty('currency')) { + obj['currency'] = ApiClient.convertToType(data['currency'], 'String'); + } + + if (data.hasOwnProperty('amount')) { + obj['amount'] = ApiClient.convertToType(data['amount'], 'Number'); + } + + if (data.hasOwnProperty('unit')) { + obj['unit'] = ApiClient.convertToType(data['unit'], 'String'); + } } return obj; } @@ -67,4 +86,12 @@ CreateOrderRequest.prototype['state'] = undefined; CreateOrderRequest.prototype['vintage_year'] = undefined; +CreateOrderRequest.prototype['total_price'] = undefined; + +CreateOrderRequest.prototype['currency'] = undefined; + +CreateOrderRequest.prototype['amount'] = undefined; + +CreateOrderRequest.prototype['unit'] = undefined; + export default CreateOrderRequest; diff --git a/src/model/Inventory.js b/src/model/Inventory.js new file mode 100644 index 0000000..4164710 --- /dev/null +++ b/src/model/Inventory.js @@ -0,0 +1,74 @@ +/** + * Patch API V1 + * The core API used to integrate with Patch's service + * + * Contact: engineering@usepatch.com + */ + +import ApiClient from '../ApiClient'; + +class Inventory { + constructor(vintageYear, amountAvailable, price, currency, unit) { + Inventory.initialize( + this, + vintageYear, + amountAvailable, + price, + currency, + unit + ); + } + + static initialize(obj, vintageYear, amountAvailable, price, currency, unit) { + obj['vintage_year'] = vintageYear; + obj['amount_available'] = amountAvailable; + obj['price'] = price; + obj['currency'] = currency; + obj['unit'] = unit; + } + + static constructFromObject(data, obj) { + if (data) { + obj = obj || new Inventory(); + + if (data.hasOwnProperty('vintage_year')) { + obj['vintage_year'] = ApiClient.convertToType( + data['vintage_year'], + 'Number' + ); + } + + if (data.hasOwnProperty('amount_available')) { + obj['amount_available'] = ApiClient.convertToType( + data['amount_available'], + 'Number' + ); + } + + if (data.hasOwnProperty('price')) { + obj['price'] = ApiClient.convertToType(data['price'], 'Number'); + } + + if (data.hasOwnProperty('currency')) { + obj['currency'] = ApiClient.convertToType(data['currency'], 'String'); + } + + if (data.hasOwnProperty('unit')) { + obj['unit'] = ApiClient.convertToType(data['unit'], 'String'); + } + } + return obj; + } +} + +Inventory.prototype['vintage_year'] = undefined; + +Inventory.prototype['amount_available'] = undefined; + +Inventory.prototype['price'] = undefined; + +Inventory.prototype['currency'] = undefined; + +Inventory.prototype['unit'] = undefined; + +export default Inventory; diff --git a/src/model/Order.js b/src/model/Order.js index 7f78965..cd9a2fe 100644 --- a/src/model/Order.js +++ b/src/model/Order.js @@ -7,6 +7,7 @@ import ApiClient from '../ApiClient'; import Allocation from './Allocation'; +import OrderInventory from './OrderInventory'; class Order { constructor( @@ -14,6 +15,11 @@ class Order { massG, production, state, + amount, + unit, + price, + patchFee, + currency, allocationState, priceCentsUsd, patchFeeCentsUsd, @@ -25,6 +31,11 @@ class Order { massG, production, state, + amount, + unit, + price, + patchFee, + currency, allocationState, priceCentsUsd, patchFeeCentsUsd, @@ -38,6 +49,11 @@ class Order { massG, production, state, + amount, + unit, + price, + patchFee, + currency, allocationState, priceCentsUsd, patchFeeCentsUsd, @@ -47,6 +63,11 @@ class Order { obj['mass_g'] = massG; obj['production'] = production; obj['state'] = state; + obj['amount'] = amount; + obj['unit'] = unit; + obj['price'] = price; + obj['patch_fee'] = patchFee; + obj['currency'] = currency; obj['allocation_state'] = allocationState; obj['price_cents_usd'] = priceCentsUsd; obj['patch_fee_cents_usd'] = patchFeeCentsUsd; @@ -80,6 +101,26 @@ class Order { obj['state'] = ApiClient.convertToType(data['state'], 'String'); } + if (data.hasOwnProperty('amount')) { + obj['amount'] = ApiClient.convertToType(data['amount'], 'Number'); + } + + if (data.hasOwnProperty('unit')) { + obj['unit'] = ApiClient.convertToType(data['unit'], 'String'); + } + + if (data.hasOwnProperty('price')) { + obj['price'] = ApiClient.convertToType(data['price'], 'Number'); + } + + if (data.hasOwnProperty('patch_fee')) { + obj['patch_fee'] = ApiClient.convertToType(data['patch_fee'], 'Number'); + } + + if (data.hasOwnProperty('currency')) { + obj['currency'] = ApiClient.convertToType(data['currency'], 'String'); + } + if (data.hasOwnProperty('allocation_state')) { obj['allocation_state'] = ApiClient.convertToType( data['allocation_state'], @@ -117,6 +158,12 @@ class Order { if (data.hasOwnProperty('metadata')) { obj['metadata'] = ApiClient.convertToType(data['metadata'], Object); } + + if (data.hasOwnProperty('inventory')) { + obj['inventory'] = ApiClient.convertToType(data['inventory'], [ + OrderInventory + ]); + } } return obj; } @@ -132,6 +179,16 @@ Order.prototype['production'] = undefined; Order.prototype['state'] = undefined; +Order.prototype['amount'] = undefined; + +Order.prototype['unit'] = undefined; + +Order.prototype['price'] = undefined; + +Order.prototype['patch_fee'] = undefined; + +Order.prototype['currency'] = undefined; + Order.prototype['allocation_state'] = undefined; Order.prototype['price_cents_usd'] = undefined; @@ -144,4 +201,6 @@ Order.prototype['registry_url'] = undefined; Order.prototype['metadata'] = undefined; +Order.prototype['inventory'] = undefined; + export default Order; diff --git a/src/model/OrderInventory.js b/src/model/OrderInventory.js new file mode 100644 index 0000000..665ba24 --- /dev/null +++ b/src/model/OrderInventory.js @@ -0,0 +1,83 @@ +/** + * Patch API V1 + * The core API used to integrate with Patch's service + * + * Contact: engineering@usepatch.com + */ + +import ApiClient from '../ApiClient'; +import OrderInventoryProject from './OrderInventoryProject'; + +class OrderInventory { + constructor(project, vintageYear, amount, unit, price, currency) { + OrderInventory.initialize( + this, + project, + vintageYear, + amount, + unit, + price, + currency + ); + } + + static initialize(obj, project, vintageYear, amount, unit, price, currency) { + obj['project'] = project; + obj['vintage_year'] = vintageYear; + obj['amount'] = amount; + obj['unit'] = unit; + obj['price'] = price; + obj['currency'] = currency; + } + + static constructFromObject(data, obj) { + if (data) { + obj = obj || new OrderInventory(); + + if (data.hasOwnProperty('project')) { + obj['project'] = ApiClient.convertToType( + data['project'], + OrderInventoryProject + ); + } + + if (data.hasOwnProperty('vintage_year')) { + obj['vintage_year'] = ApiClient.convertToType( + data['vintage_year'], + 'Number' + ); + } + + if (data.hasOwnProperty('amount')) { + obj['amount'] = ApiClient.convertToType(data['amount'], 'Number'); + } + + if (data.hasOwnProperty('unit')) { + obj['unit'] = ApiClient.convertToType(data['unit'], 'String'); + } + + if (data.hasOwnProperty('price')) { + obj['price'] = ApiClient.convertToType(data['price'], 'Number'); + } + + if (data.hasOwnProperty('currency')) { + obj['currency'] = ApiClient.convertToType(data['currency'], 'String'); + } + } + return obj; + } +} + +OrderInventory.prototype['project'] = undefined; + +OrderInventory.prototype['vintage_year'] = undefined; + +OrderInventory.prototype['amount'] = undefined; + +OrderInventory.prototype['unit'] = undefined; + +OrderInventory.prototype['price'] = undefined; + +OrderInventory.prototype['currency'] = undefined; + +export default OrderInventory; diff --git a/src/model/OrderInventoryProject.js b/src/model/OrderInventoryProject.js new file mode 100644 index 0000000..60701d7 --- /dev/null +++ b/src/model/OrderInventoryProject.js @@ -0,0 +1,40 @@ +/** + * Patch API V1 + * The core API used to integrate with Patch's service + * + * Contact: engineering@usepatch.com + */ + +import ApiClient from '../ApiClient'; + +class OrderInventoryProject { + constructor(id, name) { + OrderInventoryProject.initialize(this, id, name); + } + + static initialize(obj, id, name) { + obj['id'] = id; + obj['name'] = name; + } + + static constructFromObject(data, obj) { + if (data) { + obj = obj || new OrderInventoryProject(); + + if (data.hasOwnProperty('id')) { + obj['id'] = ApiClient.convertToType(data['id'], 'String'); + } + + if (data.hasOwnProperty('name')) { + obj['name'] = ApiClient.convertToType(data['name'], 'String'); + } + } + return obj; + } +} + +OrderInventoryProject.prototype['id'] = undefined; + +OrderInventoryProject.prototype['name'] = undefined; + +export default OrderInventoryProject; diff --git a/src/model/Project.js b/src/model/Project.js index 5e3c2e4..f8bc371 100644 --- a/src/model/Project.js +++ b/src/model/Project.js @@ -7,6 +7,7 @@ import ApiClient from '../ApiClient'; import Highlight from './Highlight'; +import Inventory from './Inventory'; import Photo from './Photo'; import Sdg from './Sdg'; import Standard from './Standard'; @@ -23,7 +24,8 @@ class Project { averagePricePerTonneCentsUsd, remainingMassG, technologyType, - highlights + highlights, + inventory ) { Project.initialize( this, @@ -36,7 +38,8 @@ class Project { averagePricePerTonneCentsUsd, remainingMassG, technologyType, - highlights + highlights, + inventory ); } @@ -51,7 +54,8 @@ class Project { averagePricePerTonneCentsUsd, remainingMassG, technologyType, - highlights + highlights, + inventory ) { obj['id'] = id; obj['production'] = production; @@ -63,6 +67,7 @@ class Project { obj['remaining_mass_g'] = remainingMassG; obj['technology_type'] = technologyType; obj['highlights'] = highlights; + obj['inventory'] = inventory; } static constructFromObject(data, obj) { @@ -164,6 +169,12 @@ class Project { Highlight ]); } + + if (data.hasOwnProperty('inventory')) { + obj['inventory'] = ApiClient.convertToType(data['inventory'], [ + Inventory + ]); + } } return obj; } @@ -209,4 +220,6 @@ Project.prototype['technology_type'] = undefined; Project.prototype['highlights'] = undefined; +Project.prototype['inventory'] = undefined; + export default Project; diff --git a/test/integration/orders.test.js b/test/integration/orders.test.js index 481211a..f814581 100644 --- a/test/integration/orders.test.js +++ b/test/integration/orders.test.js @@ -92,4 +92,29 @@ describe('Orders Integration', function () { expect(createOrderResponse.success).to.equal(true); }); + + it('supports create orders with an amount and unit', async function () { + const createOrderResponse = await patch.orders.createOrder({ + amount: 100, + unit: 'g' + }); + + expect(createOrderResponse.success).to.equal(true); + expect(createOrderResponse.data.amount).to.equal(100); + expect(createOrderResponse.data.unit).to.equal('g'); + expect(createOrderResponse.data.inventory[0].unit).to.equal('g'); + }); + + it('supports create orders with a total price and currency', async function () { + const createOrderResponse = await patch.orders.createOrder({ + total_price: 100, + currency: 'EUR' + }); + + expect(createOrderResponse.success).to.equal(true); + expect( + createOrderResponse.data.price + createOrderResponse.data.patch_fee + ).to.be.within(99, 101); + expect(createOrderResponse.data.currency).to.equal('EUR'); + }); }); diff --git a/test/integration/projects.test.js b/test/integration/projects.test.js index 1a0122b..4f308d1 100644 --- a/test/integration/projects.test.js +++ b/test/integration/projects.test.js @@ -29,6 +29,14 @@ describe('Project Integration', function () { const parent_technology_type = technology_type.parent_technology_type; expect(parent_technology_type.slug).to.be.a('string'); expect(parent_technology_type.name).to.be.a('string'); + + const inventory = projectResponse.data.inventory; + expect(inventory).to.be.a('array'); + expect(inventory[0].vintage_year).to.be.a('number'); + expect(inventory[0].amount_available).to.be.a('number'); + expect(inventory[0].price).to.be.a('number'); + expect(inventory[0].currency).to.be.a('string'); + expect(inventory[0].unit).to.be.a('string'); }); it('supports fetching all projects from the United States', async function () {