Skip to content

Commit

Permalink
Merge pull request #104 from jordanwalsh23/issue_101
Browse files Browse the repository at this point in the history
Issue 101 - Add support for linked transactions
  • Loading branch information
philals authored Sep 14, 2017
2 parents a069326 + 8dd6758 commit 3e8e2d4
Show file tree
Hide file tree
Showing 12 changed files with 528 additions and 22 deletions.
1 change: 1 addition & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -32,6 +32,7 @@ The following Xero API functions are supported:
* Items
* Journals
* Manual Journals
* Linked Transactions
* Organisations
* Overpayments
* Payments
Expand Down
164 changes: 164 additions & 0 deletions docs/Linked-Transactions.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,164 @@
The following examples explain the Linked Transactions section of the SDK. The API documentation on Linked Transactions can be found [here](https://developer.xero.com/documentation/api/linked-transactions).

### Supported functions

* Create New Linked Transactions
* Retrieve Linked Transactions (all, paginated, by ID, by SourceTransactionID, by ContactID, by Status, by TargetTransactionID)
* Update Linked Transactions
* Delete Linked Transactions

These functions are explained further below.

### Entity Helper

The entity helper that has been created for the linked transactions functions exists in the following place:

`client.core.linkedTransactions`

This helper contains the following functions:

* `newLinkedTransaction(data[, options])`
* `getLinkedTransactions([options])`
* `getLinkedTransaction(id[, modifiedAfter])`
* `deleteLinkedTransaction(id)`

### Creating a new linkedTransaction

This code assumes you've already created a client using the xero-node sdk.

```javascript

const sampleTransaction = {
SourceTransactionID: expenseInvoiceID,
SourceLineItemID: expenseLineItemID,
ContactID: expenseContactID,
};

var linkedTransactionObj = xeroClient.core.linkedTransactions.newLinkedTransaction(sampleTransaction);

linkedTransactionObj.save()
.then(function(linkedTransactions) {
//LinkedTransaction has been created
var myLinkedTransaction = linkedTransactions.entities[0];
})
.catch(function(err) {
//Some error occurred
});
```

Some points to note with the code snippet above:

* The `.newLinkedTransaction()` function doesn't actually make any API call to Xero. It only creates an object according to the linkedTransaction schema that _can_ be saved using the `.save()` function at some point in future.
* The `.save()` function returns a promise that can be met using the `.then()` function, and rejections can be caught using the `.catch()` function.
* The promise that is returned by the `.save()` function contains a response object. This has a bunch of information about the state of the response, but also contains an `entities` array. This array is what actually contains the object that was just created.
* For single object saving, this `entities` array should only ever contain one element, but some objects support a multiple object save and in this case the `entities` array will contain all of the objects that were created.

### Retrieving All Linked Transactions

This example shows how to retrieve all linked transactions in a single call.

```javascript

xeroClient.core.linkedTransactions.getLinkedTransactions()
.then(function(linkedTransactions) {
//We've got some linkedTransactions
linkedTransactions.forEach(function(linkedTransaction){
//do something useful
console.log(linkedTransaction.Name);
});
})
```

* When using the getLinkedTransactions method, as no object is being saved there is no `entities` array. Instead you are provided an array of linkedTransaction objects that you can use directly in your application.

### Retrieving Linked Transactions by ID

This example shows how to retrieve a linked transaction using the Xero supplied GUID.

```javascript

var myLinkedTransactionID = '288762e4-67a9-442d-9956-9a14e9d8826e';

xeroClient.core.linkedTransactions.getLinkedTransaction(myLinkedTransactionID)
.then(function(linkedTransaction) {
//We've got the linkedTransaction so do something useful
console.log(linkedTransaction.Name);
});
```

### Retrieving Linked Transactions with filters

This example shows how to retrieve an linkedTransaction using the filters.

```javascript

var myContactID = '288762e4-67a9-442d-9956-9a14e9d8826e';

xeroClient.core.linkedTransactions.getLinkedTransactions({
params: {
Status: 'BILLED',
ContactID: myContactID
}
})
.then(function(linkedTransactions) {
//We've got some linkedTransactions
linkedTransactions.forEach(function(linkedTransaction){
//do something useful
console.log(linkedTransaction.Status); // Billed
});
})
```

### Retrieving Linked Transactions Modified Since X

This example shows how to retrieve a list of linkedTransactions that have been updated since a specified date.

```javascript

//Return dates with an UpdatedDateUTC greater than midnight on March 24th, 2017.
var modifiedDate = new Date("March 24, 2017 00:00:00");

xeroClient.core.linkedTransactions.getLinkedTransactions({ modifiedAfter: modifiedDate })
.then(function(linkedTransactions) {
//We've got some linkedTransactions
linkedTransactions.forEach(function(linkedTransaction){
//do something useful
console.log(linkedTransaction.IsTrackedAsInventory);
});
})
```

### Updating Linked Transactions

This example shows how to update an linkedTransaction that's been retrieved via the SDK.

```javascript

var someLinkedTransactionID = '75520d2e-e19d-4f36-b19b-e3b9000b2daa';

xeroClient.core.linkedTransactions.getLinkedTransaction(someLinkedTransactionID)
.then(function(linkedTransaction) {
//We've got the linkedTransaction so now let's change the name
linkedTransaction.TargetTransactionID = '75520d2e-e19d-4f36-b19b-e3b9000b2daa';

linkedTransaction.save()
.then(function(response) {
var thisLinkedTransaction = response.entities[0];
console.log(thisLinkedTransaction.Name); //'75520d2e-e19d-4f36-b19b-e3b9000b2daa'
})
});
```

### Deleting Linked Transactions

This example shows how to delete an linkedTransaction that's been retrieved via the SDK.

```javascript

var someLinkedTransactionID = '75520d2e-e19d-4f36-b19b-e3b9000b2daa';

xeroClient.core.linkedTransactions.deleteLinkedTransaction(someLinkedTransactionID)
.then(function(res) {
console.log(res); //LinkedTransaction has been deleted
});
```
5 changes: 1 addition & 4 deletions docs/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -24,6 +24,7 @@ The following Xero API functions are supported:
* [Invoice Reminders](./Invoice-Reminders.md)
* [Items](./Items.md)
* [Journals](./Journals.md)
* [Linked Transactions](./Linked-Transactions.md)
* [Manual Journals](./Manual-Journals.md)
* [Organisations](./Organisations.md)
* [Overpayments](./Overpayments.md)
Expand All @@ -37,10 +38,6 @@ The following Xero API functions are supported:
* [Tracking Categories (and Tracking Options)](./Tracking-Categories.md)
* [Users](./Users.md)

Endpoints not currently supported:

* Linked Transactions

### Other Xero APIs

Support for the other Xero APIs is not currently available, but is coming soon.
Expand Down
1 change: 1 addition & 0 deletions lib/core.js
Original file line number Diff line number Diff line change
Expand Up @@ -31,6 +31,7 @@ const HELPERS = {
overpayments: { file: 'overpayments' },
prepayments: { file: 'prepayments' },
allocations: { file: 'allocations' },
linkedTransactions: { file: 'linkedtransactions' },
};

function Core(application) {
Expand Down
53 changes: 53 additions & 0 deletions lib/entities/accounting/linkedtransaction.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,53 @@
'use strict';

const Entity = require('../entity');

const LinkedTransactionSchema = Entity.SchemaObject({
LinkedTransactionID: { type: String, toObject: 'hasValue' },
SourceTransactionID: { type: String, toObject: 'hasValue' },
SourceLineItemID: { type: String, toObject: 'hasValue' },
ContactID: { type: String, toObject: 'hasValue' },
TargetTransactionID: { type: String, toObject: 'hasValue' },
TargetLineItemID: { type: String, toObject: 'hasValue' },
Status: { type: String, toObject: 'always' },
Type: { type: String, toObject: 'hasValue' },
UpdatedDateUTC: { type: Date, toObject: 'hasValue' },
SourceTransactionTypeCode: { type: String, toObject: 'hasValue' },
});

const LinkedTransaction = Entity.extend(LinkedTransactionSchema, {
constructor: function(application, data, options) {
this.Entity.apply(this, arguments);
},
initialize: function(data, options) {},
save: function(options) {
const self = this;
let path;
let method;
if (this.LinkedTransactionID) {
path = `LinkedTransactions/${this.LinkedTransactionID}`;
method = 'post';
} else {
path = 'LinkedTransactions';
method = 'put';
}

return this.application.putOrPostEntity(
method,
path,
JSON.stringify(self),
{
entityPath: 'LinkedTransactions',
entityConstructor(data) {
return self.application.core.linkedTransactions.newLinkedTransaction(
data
);
},
}
);
}
});


module.exports.LinkedTransaction = LinkedTransaction;
module.exports.LinkedTransactionSchema = LinkedTransactionSchema;
49 changes: 49 additions & 0 deletions lib/entity_helpers/accounting/linkedtransactions.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,49 @@
'use strict';

const _ = require('lodash');
const EntityHelper = require('../entity_helper');
const LinkedTransaction = require('../../entities/accounting/linkedtransaction')
.LinkedTransaction;

const LinkedTransactions = EntityHelper.extend({
constructor: function(application, options) {
EntityHelper.call(
this,
application,
Object.assign({ entityPlural: 'LinkedTransactions' }, options)
);
},
newLinkedTransaction: function(data, options) {
return new LinkedTransaction(this.application, data, options);
},
getLinkedTransaction: function(id, modifiedAfter) {
return this.getLinkedTransactions({ id: id, modifiedAfter: modifiedAfter })
.then(function(linkedTransactions) {
return _.first(linkedTransactions);
});
},
getLinkedTransactions: function(options) {
var self = this;
var clonedOptions = _.clone(options || {});
clonedOptions.entityConstructor = function(data) { return self.newLinkedTransaction(data) };
return this.getEntities(clonedOptions)
},
deleteLinkedTransaction: function(id) {
var options = {
id: id
};
return this.deleteEntities(options);
},
saveLinkedTransactions: function(linkedTransactions, options) {
return this.saveEntities(linkedTransactions, this.setUpOptions(options));
},
setUpOptions: function(options) {
var self = this;
var clonedOptions = _.clone(options || {});
clonedOptions.entityPath = 'LinkedTransactions';
clonedOptions.entityConstructor = function(data) { return self.newLinkedTransaction(data) };
return clonedOptions;
}
});

module.exports = LinkedTransactions;
4 changes: 2 additions & 2 deletions test/core/expenseclaims_tests.js
Original file line number Diff line number Diff line change
Expand Up @@ -111,8 +111,8 @@ describe('ExpenseClaims', () => {
sampleExpenseClaim.Receipts.length = 0;
let numberOfReceipts = receipts.length;

if (numberOfReceipts > 5) {
numberOfReceipts = 5;
if (numberOfReceipts > 3) {
numberOfReceipts = 3;
}

for (let i = 0; i < numberOfReceipts; i += 1) {
Expand Down
Loading

0 comments on commit 3e8e2d4

Please sign in to comment.