diff --git a/book/en/SUMMARY.md b/book/en/SUMMARY.md
index 985a7d6..e3c3ffe 100644
--- a/book/en/SUMMARY.md
+++ b/book/en/SUMMARY.md
@@ -40,8 +40,9 @@
* [AddressBookV5](code/AddressBookV5.md)
* [AutomaticTerritories](code/AutomaticTerritories.md)
- * [Schedules](code/Schedules.md)
+ * [OptimizationProfiles](code/OptimizationProfiles.md)
* [PodWorkflow](code/PodWorkflow.md)
+ * [Schedules](code/Schedules.md)
* [TeamManagement](code/TeamManagement.md)
* [VehiclesV5](code/VehiclesV5.md)
diff --git a/book/en/code/OptimizationProfiles.md b/book/en/code/OptimizationProfiles.md
new file mode 100644
index 0000000..6531671
--- /dev/null
+++ b/book/en/code/OptimizationProfiles.md
@@ -0,0 +1,75 @@
+
+
+## OptimizationProfiles ℗
+
+Optimization profiles
+
+**Category**: OptimizationProfiles
+**Access**: private
+**See**: [https://route4me.io/docs/#create-an-optimization](https://route4me.io/docs/#create-an-optimization)
+**Since**: 1.2.0
+
+* [OptimizationProfiles](#OptimizationProfiles) ℗
+ * [new OptimizationProfiles(requestManager)](#new_OptimizationProfiles_new)
+ * [.list([callback])](#OptimizationProfiles+list)
+ * [.save(data, [callback])](#OptimizationProfiles+save)
+ * [.remove(data, [callback])](#OptimizationProfiles+remove)
+
+
+
+### new OptimizationProfiles(requestManager)
+
+Constructor
+
+**Returns**: [OptimizationProfiles
](#OptimizationProfiles) - - OptimizationProfiles facility
+
+| Param | Type | Description |
+| --- | --- | --- |
+| requestManager | RequestManager
| Request Manager |
+
+
+
+### optimizationProfiles.list([callback])
+
+Get list of optimization profiles belong to the Route4Me account
+
+**Since**: 1.2.0
+
+| Param | Type |
+| --- | --- |
+| [callback] | OptimizationProfiles.ResponseMany
|
+
+
+
+### optimizationProfiles.save(data, [callback])
+
+Save a OptimizationProfiles.
+
+**Since**: 1.2.0
+
+| Param | Type | Description |
+| --- | --- | --- |
+| data | object
| valid save data |
+| data.items | Array.<object>
| array of objects to save |
+| data.items.guid | string
| GUID |
+| data.items.id | string
| ID |
+| data.items.parts | Array.<object>
| aray of parts |
+| data.items.parts.guid | string
| GUID |
+| data.items.parts.data | object
| data |
+| [callback] | OptimizationProfiles.ResponseSave
| |
+
+
+
+### optimizationProfiles.remove(data, [callback])
+
+Remove a OptimizationProfiles.
+
+**Since**: 1.2.0
+
+| Param | Type | Description |
+| --- | --- | --- |
+| data | object
| valid remove data |
+| data.items | Array.<object>
| array of objects to remove |
+| data.items.id | string
| ID |
+| [callback] | OptimizationProfiles.ResponseRemove
| |
+
diff --git a/book/en/code/Optimizations.md b/book/en/code/Optimizations.md
index a0ca075..e1f0e4f 100644
--- a/book/en/code/Optimizations.md
+++ b/book/en/code/Optimizations.md
@@ -98,6 +98,7 @@ Create a new optimization with Advanced constraints
| [props.parameters.advanced_constraints.location_sequence_pattern.time] | number
| | Location service time |
| [props.parameters.advanced_constraints.group] | string
| | Group name of the advanced constraints. |
| [props.depots] | Array.<object>
| | A valid array of Address objects of Depots. |
+| [props.optimization_profile_id] | object
| | A valid ID of optimization profile. |
| props.addresses | Array.<object>
| | A valid array of Address objects. Here are some required and useful properties of the Address object, for full list of properties look at docs. |
| props.addresses.lat | number
| | Latitude. |
| props.addresses.lng | number
| | Longitude. |
diff --git a/book/en/code/Route4Me.md b/book/en/code/Route4Me.md
index 5ff07c9..5f1957b 100644
--- a/book/en/code/Route4Me.md
+++ b/book/en/code/Route4Me.md
@@ -95,6 +95,7 @@ Main members of the instanse of `Route4Me` class:
* [Members ](Members)
* [Notes ](Notes)
* [Optimizations ](Optimizations)
+* [OptimizationProfiles](OptimizationProfiles)
* [Orders ](Orders)
* [OrderCustomFields ](OrderCustomFields)
* [PodWorkflow ](PodWorkflow)
@@ -139,6 +140,7 @@ For most use cases it is necessary:
* [.Geocoding](#Route4Me+Geocoding) : Geocoding
* [.Notes](#Route4Me+Notes) : Notes
* [.Optimizations](#Route4Me+Optimizations) : Optimizations
+ * [.OptimizationProfiles](#Route4Me+OptimizationProfiles) : OptimizationProfiles
* [.Orders](#Route4Me+Orders) : Orders
* [.PodWorkflow](#Route4Me+PodWorkflow) : PodWorkflow
* [.Routes](#Route4Me+Routes) : Routes
@@ -241,6 +243,13 @@ Create new API client
**Optimizations** related API calls
+
+
+### route4Me.OptimizationProfiles : OptimizationProfiles
+
+**OptimizationProfiles** related API calls
+
+**Since**: 1.2.0
### route4Me.Orders : Orders
diff --git a/examples/OptimizationProfiles/save-data-promise.js b/examples/OptimizationProfiles/save-data-promise.js
new file mode 100644
index 0000000..7293a26
--- /dev/null
+++ b/examples/OptimizationProfiles/save-data-promise.js
@@ -0,0 +1,57 @@
+"use strict"
+
+const path = require("path")
+const chai = require("chai")
+const debug = require("debug")("route4me-node:examples")
+require("../init-examples-suite")
+const helper = require("../../test/helper")
+
+helper.describeIntegration(helper.toSuiteName(__filename), function T() {
+ this.timeout(5000)
+ this.slow(3000)
+ it(path.basename(__filename), (done) => {
+ const expect = chai.expect
+ const apiKey = "11111111111111111111111111111111"
+
+ // To use the Promise style instead of the Callback style send promise=true as an option.
+ const route4me = new Route4Me(apiKey, { promise: true })
+
+ // get default optimization profile id
+ route4me.OptimizationProfiles.list()
+ .then(data => {
+ expect(data).exist
+
+ const default_profile = data.items.find((item) => item.is_default);
+ if(default_profile) {
+
+ // save data
+ const data = {
+ items: [{
+ guid: "eaa",
+ parts: [{
+ guid: "pav",
+ data: { "append_date_to_route_name": true }
+ }],
+ id: default_profile.optimization_profile_id
+ }]
+ };
+ route4me.OptimizationProfiles.save(data)
+ .then(data => {
+ expect(data).exist
+
+ console.log(`Data for optimization_profile_id: '${default_profile.optimization_profile_id}' was saved successful.`);
+ }).catch(err => {
+ console.log("Error: save, " + err);
+ });
+ } else {
+ console.log("Cannot find the default optimization profile id.");
+ }
+ }).catch(err => {
+ expect(err).exist
+ // console.log("Error: list, " + err);
+ });
+
+ // TODO: remove `done` call from examples
+ done()
+ })
+})
diff --git a/examples/OptimizationProfiles/save-data-sync.js b/examples/OptimizationProfiles/save-data-sync.js
new file mode 100644
index 0000000..cf5f506
--- /dev/null
+++ b/examples/OptimizationProfiles/save-data-sync.js
@@ -0,0 +1,56 @@
+"use strict"
+
+const path = require("path")
+const chai = require("chai")
+const debug = require("debug")("route4me-node:examples")
+require("../init-examples-suite")
+const helper = require("../../test/helper")
+
+helper.describeIntegration(helper.toSuiteName(__filename), function T() {
+ this.timeout(5000)
+ this.slow(3000)
+ it(path.basename(__filename), (done) => {
+ const expect = chai.expect
+ const apiKey = "11111111111111111111111111111111"
+
+ // To use the Promise style instead of the Callback style send promise=true as an option.
+ const route4me = new Route4Me(apiKey, { promise: true });
+
+ (async () => {
+ try {
+ // get default optimization profile id
+ const data = await route4me.OptimizationProfiles.list();
+ expect(data).exist
+
+ const default_profile = data.items.find((item) => item.is_default);
+ if(default_profile) {
+
+ // save data
+ const data = {
+ items: [{
+ guid: "eaa",
+ parts: [{
+ guid: "pav",
+ data: { "append_date_to_route_name": true }
+ }],
+ id: default_profile.optimization_profile_id
+ }]
+ };
+ const res = await route4me.OptimizationProfiles.save(data);
+ expect(res).exist
+
+ console.log(`Data for optimization_profile_id: '${default_profile.optimization_profile_id}' was saved successful.`);
+ } else {
+ console.log("Cannot find the default optimization profile id.");
+ }
+ }
+ catch(err) {
+ expect(err).exist
+ // console.log("Error ", err);
+ }
+ })();
+
+ // TODO: remove `done` call from examples
+ done()
+ })
+})
diff --git a/examples/OptimizationProfiles/save-data.js b/examples/OptimizationProfiles/save-data.js
new file mode 100644
index 0000000..c9d02c8
--- /dev/null
+++ b/examples/OptimizationProfiles/save-data.js
@@ -0,0 +1,61 @@
+"use strict"
+
+const path = require("path")
+const chai = require("chai")
+const debug = require("debug")("route4me-node:examples")
+require("../init-examples-suite")
+const helper = require("../../test/helper")
+
+helper.describeIntegration(helper.toSuiteName(__filename), function T() {
+ this.timeout(5000)
+ this.slow(3000)
+ it(path.basename(__filename), (done) => {
+ const expect = chai.expect
+ const apiKey = "11111111111111111111111111111111"
+ const route4me = new Route4Me(apiKey)
+
+ // get default optimization profile id
+ route4me.OptimizationProfiles.list((err, data) => {
+ debug("error ", err)
+ expect(err).is.null
+ expect(data).exist
+
+ if(err) {
+ console.log("Error: list, " + err);
+ return;
+ }
+
+ const default_profile = data.items.find((item) => item.is_default);
+ if(default_profile) {
+
+ // save data
+ const data = {
+ items: [{
+ guid: "eaa",
+ parts: [{
+ guid: "pav",
+ data: { "append_date_to_route_name": true }
+ }],
+ id: default_profile.optimization_profile_id
+ }]
+ };
+ route4me.OptimizationProfiles.save(data, (err, data) => {
+ debug("error ", err)
+ expect(err).is.null
+ expect(data).exist
+
+ if(err) {
+ console.log("Error: save, " + err);
+ return;
+ }
+ console.log(`Data for optimization_profile_id: '${default_profile.optimization_profile_id}' was saved successful.`);
+ });
+ } else {
+ console.log("Cannot find the default optimization profile id.");
+ }
+ });
+
+ // TODO: remove `done` call from examples
+ done()
+ })
+})
diff --git a/package.json b/package.json
index 108e37e..f385918 100644
--- a/package.json
+++ b/package.json
@@ -1,6 +1,6 @@
{
"name": "route4me-nodejs-sdk",
- "version": "1.0.28",
+ "version": "1.2.0",
"description": "Access Route4Me's logistics-as-a-service API using our Node.js SDK",
"main": "src/index.js",
"browser": "src/route4me.js",
diff --git a/src/request-manager.js b/src/request-manager.js
index 1ef5752..d5c0d37 100644
--- a/src/request-manager.js
+++ b/src/request-manager.js
@@ -252,7 +252,7 @@ class RequestManager {
if (form) {
req.type("multipart/form-data")
.field(form)
- } else {
+ } else if (body) {
req.type("application/json")
.send(body)
}
diff --git a/src/resources/optimization-profiles.js b/src/resources/optimization-profiles.js
new file mode 100644
index 0000000..63368e6
--- /dev/null
+++ b/src/resources/optimization-profiles.js
@@ -0,0 +1,83 @@
+"use strict"
+
+/**
+ * Optimization profiles
+ *
+ * @category OptimizationProfiles
+ * @since 1.2.0
+*/
+class OptimizationProfiles {
+ /**
+ * Constructor
+ *
+ * @see {@link https://route4me.io/docs/#create-an-optimization}
+ * @private
+ *
+ * @param {RequestManager} requestManager - Request Manager
+ * @return {OptimizationProfiles} - OptimizationProfiles facility
+ */
+ constructor(requestManager) {
+ this.r = requestManager
+ }
+
+ /**
+ * Get list of optimization profiles belong to the Route4Me account
+ *
+ * @since 1.2.0
+ *
+ * @param {OptimizationProfiles.ResponseMany} [callback]
+ */
+ list(callback) {
+ return this.r._makeRequest5({
+ method: "GET",
+ path: "/api/v5.0/optimization-profiles/data-list",
+ validationContext: "OptimizationProfiles.ResponseMany",
+ }, callback)
+ }
+
+ /**
+ * Save a OptimizationProfiles.
+ *
+ * @since 1.2.0
+ *
+ * @param {object} data - valid save data
+ * @param {object[]} data.items - array of objects to save
+ * @param {string} data.items.guid - GUID
+ * @param {string} data.items.id - ID
+ * @param {object[]} data.items.parts - aray of parts
+ * @param {string} data.items.parts.guid - GUID
+ * @param {object} data.items.parts.data - data
+ *
+ * @param {OptimizationProfiles.ResponseSave} [callback]
+ */
+ save(data, callback) {
+ return this.r._makeRequest5({
+ method: "POST",
+ path: "/api/v5.0/optimization-profiles/save-entities",
+ body: data,
+ validationContext: "OptimizationProfiles.save"
+ }, callback)
+ }
+
+ /**
+ * Remove a OptimizationProfiles.
+ *
+ * @since 1.2.0
+ *
+ * @param {object} data - valid remove data
+ * @param {object[]} data.items - array of objects to remove
+ * @param {string} data.items.id - ID
+ *
+ * @param {OptimizationProfiles.ResponseRemove} [callback]
+ */
+ remove(data, callback) {
+ return this.r._makeRequest5({
+ method: "POST",
+ path: "/api/v5.0/optimization-profiles/delete-entities",
+ body: data,
+ validationContext: "OptimizationProfiles.remove"
+ }, callback)
+ }
+}
+
+module.exports = OptimizationProfiles
diff --git a/src/resources/optimizations.js b/src/resources/optimizations.js
index 6739898..0b9786e 100644
--- a/src/resources/optimizations.js
+++ b/src/resources/optimizations.js
@@ -148,6 +148,7 @@ class Optimizations {
* @param {string} [props.parameters.advanced_constraints.group] - Group name of the advanced constraints.
*
* @param {object[]} [props.depots] - A valid array of Address objects of Depots.
+ * @param {object} [props.optimization_profile_id] - A valid ID of optimization profile.
* @param {object[]} props.addresses - A valid array of Address objects.
* Here are some required and useful properties of the Address object,
* for full list of properties look at docs.
diff --git a/src/route4me.js b/src/route4me.js
index 2206653..0f3af8e 100644
--- a/src/route4me.js
+++ b/src/route4me.js
@@ -14,6 +14,7 @@ const Geocoding = require("./resources/geocoding")
const Members = require("./resources/members")
const Notes = require("./resources/notes")
const Optimizations = require("./resources/optimizations")
+const OptimizationProfiles = require("./resources/optimization-profiles")
const Orders = require("./resources/orders")
const PodWorkflow = require("./resources/proof-of-delivery-workflow")
const Routes = require("./resources/routes")
@@ -50,6 +51,7 @@ const RequestManager = require("./request-manager")
* * [Members ]{@link Members}
* * [Notes ]{@link Notes}
* * [Optimizations ]{@link Optimizations}
+ * * [OptimizationProfiles]{@link OptimizationProfiles}
* * [Orders ]{@link Orders}
* * [OrderCustomFields ]{@link OrderCustomFields}
* * [PodWorkflow ]{@link PodWorkflow}
@@ -195,6 +197,12 @@ class Route4Me {
* @type {Optimizations}
*/
this.Optimizations = new Optimizations(req)
+ /**
+ * **OptimizationProfiles** related API calls
+ * @type {OptimizationProfiles}
+ * @since 1.2.0
+ */
+ this.OptimizationProfiles = new OptimizationProfiles(req)
/**
* **Orders** related API calls
* @type {Orders}
diff --git a/test/helper.js b/test/helper.js
index 20a9349..3dc6bf2 100644
--- a/test/helper.js
+++ b/test/helper.js
@@ -7,6 +7,8 @@ const runIntegrationTests = "1" === process.env["TEST_INTEGRATION"]
//const describeIntegration = runIntegrationTests ? describe : describe.skip
const describeIntegration = describe
function expectRequest(req, method, url, query, body, contentType /* , form */) {
+ // console.log(req)
+ // console.log(body)
const ct = contentType || "application/json"
expect(req).has.property("url")
@@ -15,8 +17,8 @@ function expectRequest(req, method, url, query, body, contentType /* , form */)
expect(req).has.property("method")
.and.is.equal(method)
- expect(req).has.property("headers")
- .that.has.property("content-type", ct)
+ // expect(req).has.property("headers")
+ // .that.has.property("content-type", ct)
// QUERY assertions
expect(req).has.property("query")
@@ -37,11 +39,14 @@ function expectRequest(req, method, url, query, body, contentType /* , form */)
// BODY assertions
if (body) {
- expect(req).has.property("body")
+ expect(req).has.property("headers")
+ .that.has.property("content-type", ct)
+
+ expect(req).has.property("body")
.that.is.deep.equal(body)
} else {
- expect(req).has.property("body")
- .and.is.null
+ // expect(req).has.property("body")
+ // .and.is.null
}
// if (form) {
diff --git a/test/resources/optimization-profiles.spec.js b/test/resources/optimization-profiles.spec.js
new file mode 100644
index 0000000..3a9da3d
--- /dev/null
+++ b/test/resources/optimization-profiles.spec.js
@@ -0,0 +1,99 @@
+"use strict"
+
+const request = require("superagent")
+const saMock = require("superagent-mocker")(request)
+
+const helper = require("./../helper")
+
+const route4me = require("./../../dist")
+
+const testApiKey = "11111111111111111111111111111111"
+
+
+describe(helper.toSuiteName(__filename), () => {
+ describe("SDK methods", () => {
+ const route4meClient = new route4me.Route4Me(testApiKey)
+ const resource = route4meClient.OptimizationProfiles
+ let req
+
+ beforeEach(() => {
+ req = null
+ saMock.get("*", (r) => { req = r; req.method = "GET"; return {} })
+ saMock.post("*", (r) => { req = r; req.method = "POST"; return {} })
+ saMock.del("*", (r) => { req = r; req.method = "DELETE"; return {} })
+ saMock.put("*", (r) => { req = r; req.method = "PUT"; return {} })
+ })
+
+ afterEach(() => {
+ saMock.clearRoutes()
+ })
+
+ describe("list", () => {
+
+ it("list should call route4me", (done) => {
+ resource.list((err, res) => {
+ expect(err).is.null
+ expect(res).is.not.null
+ helper.expectRequest(req,
+ "GET",
+ route4meClient.baseUrl5() + "/api/v5.0/optimization-profiles/data-list",
+ null,
+ null
+ )
+ done()
+ })
+ })
+ })
+
+ describe("save", () => {
+ const data = {
+ items: [{
+ guid: "eaa",
+ parts: [{
+ guid: "pav",
+ data: { "append_date_to_route_name": true }
+ }],
+ id: "f09e3d22-c1d6-473c-8494-41563034b85b"
+ }]
+ };
+
+ it("save should call route4me", (done) => {
+ resource.save(data, (err, res) => {
+ expect(err).is.null
+ expect(res).is.not.null
+ helper.expectRequest(req,
+ "POST",
+ route4meClient.baseUrl5() + "/api/v5.0/optimization-profiles/save-entities",
+ null,
+ data
+ )
+ done()
+ })
+ })
+ })
+
+ describe("remove", () => {
+ const data = {
+ items: [{
+ id: "f09e3d22-c1d6-473c-8494-41563034b85b"
+ }]
+ };
+
+ it("remove should call route4me", (done) => {
+ resource.remove(data, (err, res) => {
+ expect(err).is.null
+ expect(res).is.not.null
+
+ helper.expectRequest(req,
+ "POST",
+ route4meClient.baseUrl5() + "/api/v5.0/optimization-profiles/delete-entities",
+ null,
+ data
+ )
+
+ done()
+ })
+ })
+ })
+ })
+})