Skip to content
This repository has been archived by the owner on Jul 30, 2018. It is now read-only.

Commit

Permalink
Merge branch 'develop'
Browse files Browse the repository at this point in the history
  • Loading branch information
PierrickP committed Jun 26, 2016
2 parents 7465123 + 3635b9b commit 1638923
Show file tree
Hide file tree
Showing 11 changed files with 556 additions and 1 deletion.
3 changes: 3 additions & 0 deletions .travis.yml
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,9 @@ env:
- secure: "P0ksGaQg9x2OA2+Ue7M8DRMNBS1RrMK4pi5vV4HeGlTDNoZvWhMbmb5RwtykXBR12H8BTzrnsxA5BfMzzVh+F/88eoSL5WJV7n/Ea39xxiATA2edBjbpCFSsAHI8JQWTT0uo2dD5XeLWAx2ZTELRX2PVr6dn7yeJ2PlF39HXXqzi7QeZ+FlHX5dHckrx+9MX9/+qBKzLZegeQHUDgYs7SxFDJ+IshYVY6SMF+fvy7JIVIcQhAZzlyYADaraHmluGuFuNVmfRDOVaDSJX+WQoGfo7UrQawY4hDZRZzXcIBXJSczJJ+JPBXuDDUKznvVifsHR96dxQrOUdyRF3zjRSW3CxFm58loTecsekV1s0f88K0tYfjjreUh5qoPWI2bue5Mqk8AC7hkkWRvOQX9XRrlfzqz5wEWTYIzU44Nv4NzkuBjtgQUMnA7WuMiwjngjGLwHVJfw7TuliYca089xtX6ZocUUXwB834vh2sLIIn/dPLYovOEsWkgav8uzHpizSZwap/gpchbUnIrUeahFjyfr1g5xbzyqkodCe5UhSGjI7OcPbS4WH8/pE7z4Vuz2ZMYcKsdCfyeorzaZ24ERGXQEVA+gA9rWtUM9gyPqdkq2btq75Xxy2lP7HsyA6D637q9Qmn86jgNItVSaFjTaS9AobzaDC8bMDvDV7N6rHLuQ="
- GIT_DEPLOY_REPO=https://[email protected]/PierrickP/number26.git

before_install:
- export TZ=Europe/Berlin

deploy:
- provider: script
script: npm run deployDocs
Expand Down
1 change: 1 addition & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -40,6 +40,7 @@ Not all endpoints are available yet.
number26 depends on:

+ [bluebird](https://www.npmjs.com/package/bluebird): Bluebird is a full featured promise library with unmatched performance.
+ [moment](https://www.npmjs.com/package/moment): A lightweight JavaScript date library for parsing, validating, manipulating, and formatting dates.
+ [request-promise](https://www.npmjs.com/package/request-promise): The world-famous HTTP client 'Request' now Promises/A+ compliant.

### Use :sos:
Expand Down
89 changes: 89 additions & 0 deletions lib/account.js
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
'use strict';
const moment = require('moment');
const Promise = require('bluebird');

const Card = require('./card.js');
Expand Down Expand Up @@ -252,6 +253,20 @@ const utils = require('./utils');
* @property {Number} amount
*/

/**
* @typedef category
*
* @property {String} id
* @property {String} base64Image PNG base64 encoded
* @property {String} name Translated category name
*/

/**
* @typedef csv
*
* @description CSV file with "," delimiter
*/

/**
* Number26 Account
*/
Expand Down Expand Up @@ -321,6 +336,15 @@ class Account {
return utils.callApi(this, 'checkBarzahlen');
}

/**
* Get transaction categories
*
* @return {Promise<category[]>}
*/
categories() {
return utils.callApi(this, 'getCategories');
}

/**
* Get one specific or all cards
*
Expand All @@ -341,6 +365,26 @@ class Account {
}));
}

/**
* Get transactions CSV
*
* @param {Date|Number} from From date
* @param {Date|Number} [to=now()] To date
*
* @return {Promise<csv>}
*/
csv(from, to) {
return Promise.try(() => {
if (!from) {
throw new Error('MISSING_PARAMS');
}

from = ((from instanceof Date) ? from.getTime() : from);
to = ((to instanceof Date) ? to.getTime() : to || new Date().getTime());
return utils.callApi(this, 'getCSV', {from, to});
});
}

/**
* Get contacts
*
Expand Down Expand Up @@ -491,6 +535,51 @@ class Account {
return utils.callApi(this, 'getRecipients');
}

/**
* Get stats
*
* @param {Date|Number} from From date (native date or timestamp)
* @param {Date|Number} to To date (native date or timestamp)
* @param {String} interval Interval data per "days" / "weeks" / "months" / "years"
*
*/
stats(from, to, interval) {
return Promise.try(() => {
if (!from || !to || !interval) {
throw new Error('MISSING_PARAMS');
}

if (['days', 'weeks', 'months', 'years'].indexOf(interval) === -1) {
throw new Error('BAD_PARAMS');
}

const request = [];

from = moment((from instanceof Date) ? from.getTime() / 1000 : from, 'X').startOf(interval);
to = moment((to instanceof Date) ? to.getTime() / 1000 : to, 'X').endOf(interval);

while (from < to) {
const tempTo = moment(from).add(1, interval).endOf(interval);

request.push(utils.callApi(this, 'getStats', {
from: from.valueOf(),
to: tempTo.valueOf()
}));

from.add(1, interval);
}

return Promise.map(request, (slices) => {
const slice = slices.slices[0];
return {
from: slice.from,
to: slice.to,
amount: slice.ammount
};
});
});
}

/**
* Get transactions
*
Expand Down
32 changes: 32 additions & 0 deletions lib/api.js
Original file line number Diff line number Diff line change
Expand Up @@ -125,6 +125,17 @@ module.exports = {
.catch(errorHandler);
},

getCategories(token) {
return request.get({
url: `${api}/api/smrt/categories`,
json: true,
headers: {
Authorization: `Bearer ${token}`
}
})
.catch(errorHandler);
},

getCard(token, cardId) {
return request.get({
url: `${api}/api/cards/${cardId}`,
Expand Down Expand Up @@ -180,6 +191,16 @@ module.exports = {
.catch(errorHandler);
},

getCSV(token, opts) {
return request.get({
url: `${api}/api/smrt/reports/${opts.from}/${opts.to}/statements`,
headers: {
Authorization: `Bearer ${token}`
}
})
.catch(errorHandler);
},

getLimits(token) {
return request.get({
url: `${api}/api/settings/account/limits`,
Expand Down Expand Up @@ -241,6 +262,17 @@ module.exports = {
.catch(errorHandler);
},

getStats(token, opt) {
return request.get({
url: `${api}/api/accounts/stats?type=acct&from=${opt.from}&to=${opt.to}&numSlices=1`,
json: true,
headers: {
Authorization: `Bearer ${token}`
}
})
.catch(errorHandler);
},

getStatuses(token) {
return request.get({
url: `${api}/api/me/statuses`,
Expand Down
3 changes: 2 additions & 1 deletion package.json
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
{
"name": "number26",
"version": "1.1.0",
"version": "1.2.0",
"description": "Un-official node.js module for interact with your number26 account",
"main": "index.js",
"scripts": {
Expand Down Expand Up @@ -45,6 +45,7 @@
},
"dependencies": {
"bluebird": "^3.3.5",
"moment": "^2.13.0",
"request-promise": "^3.0.0"
}
}
150 changes: 150 additions & 0 deletions tests/account/categories.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,150 @@
'use strict';
/* eslint-disable global-require, max-len, arrow-body-style */
const nock = require('nock');
const chai = require('chai');
const dirtyChai = require('dirty-chai');
const expect = chai.expect;

chai.use(dirtyChai);

let n26;
const data = require('../fixtures/data');

beforeEach((done) => {
require('../fixtures/auth')((err, m) => {
n26 = m;

done();
});
});

describe('categories', () => {
const categoriesData = [{
id: 'macro-bbu',
base64Image: 'iVBORw0KGgoAAAANSUhEUgAAAAEAAAABCAQAAAC1HAwCAAAAC0lEQVQYV2NgYAAAAAMAAWgmWQ0AAAAASUVORK5CYII=',
name: 'CASH26 Deposit'
}, {
id: 'micro-insurance',
base64Image: 'iVBORw0KGgoAAAANSUhEUgAAAAEAAAABCAQAAAC1HAwCAAAAC0lEQVQYV2NgYAAAAAMAAWgmWQ0AAAAASUVORK5CYII=',
name: 'Insurance'
}, {
id: 'micro-leisure',
base64Image: 'iVBORw0KGgoAAAANSUhEUgAAAAEAAAABCAQAAAC1HAwCAAAAC0lEQVQYV2NgYAAAAAMAAWgmWQ0AAAAASUVORK5CYII=',
name: 'Leisure'
}, {
id: 'micro-transport',
base64Image: 'iVBORw0KGgoAAAANSUhEUgAAAAEAAAABCAQAAAC1HAwCAAAAC0lEQVQYV2NgYAAAAAMAAWgmWQ0AAAAASUVORK5CYII=',
name: 'Transport'
}, {
id: 'micro-education',
base64Image: 'iVBORw0KGgoAAAANSUhEUgAAAAEAAAABCAQAAAC1HAwCAAAAC0lEQVQYV2NgYAAAAAMAAWgmWQ0AAAAASUVORK5CYII=',
name: 'Education'
}, {
id: 'micro-atm',
base64Image: 'iVBORw0KGgoAAAANSUhEUgAAAAEAAAABCAQAAAC1HAwCAAAAC0lEQVQYV2NgYAAAAAMAAWgmWQ0AAAAASUVORK5CYII=',
name: 'ATM'
}, {
id: 'micro-miscellaneous',
base64Image: 'iVBORw0KGgoAAAANSUhEUgAAAAEAAAABCAQAAAC1HAwCAAAAC0lEQVQYV2NgYAAAAAMAAWgmWQ0AAAAASUVORK5CYII=',
name: 'Miscellaneous'
}, {
id: 'micro-healthcare-drugstores',
base64Image: 'iVBORw0KGgoAAAANSUhEUgAAAAEAAAABCAQAAAC1HAwCAAAAC0lEQVQYV2NgYAAAAAMAAWgmWQ0AAAAASUVORK5CYII=',
name: 'Healthcare & Drug Stores'
}, {
id: 'macro-bub',
base64Image: 'iVBORw0KGgoAAAANSUhEUgAAAAEAAAABCAQAAAC1HAwCAAAAC0lEQVQYV2NgYAAAAAMAAWgmWQ0AAAAASUVORK5CYII=',
name: 'CASH26 Withdraw'
}, {
id: 'micro-finance',
base64Image: 'iVBORw0KGgoAAAANSUhEUgAAAAEAAAABCAQAAAC1HAwCAAAAC0lEQVQYV2NgYAAAAAMAAWgmWQ0AAAAASUVORK5CYII=',
name: 'Finance'
}, {
id: 'micro-housing-energy',
base64Image: 'iVBORw0KGgoAAAANSUhEUgAAAAEAAAABCAQAAAC1HAwCAAAAC0lEQVQYV2NgYAAAAAMAAWgmWQ0AAAAASUVORK5CYII=',
name: 'Housing & Energy'
}, {
id: 'micro-groceries',
base64Image: 'iVBORw0KGgoAAAANSUhEUgAAAAEAAAABCAQAAAC1HAwCAAAAC0lEQVQYV2NgYAAAAAMAAWgmWQ0AAAAASUVORK5CYII=',
name: 'Groceries'
}, {
id: 'macro-ct',
base64Image: 'iVBORw0KGgoAAAANSUhEUgAAAAEAAAABCAQAAAC1HAwCAAAAC0lEQVQYV2NgYAAAAAMAAWgmWQ0AAAAASUVORK5CYII=',
name: 'Income'
}, {
id: 'micro-shopping',
base64Image: 'iVBORw0KGgoAAAANSUhEUgAAAAEAAAABCAQAAAC1HAwCAAAAC0lEQVQYV2NgYAAAAAMAAWgmWQ0AAAAASUVORK5CYII=',
name: 'Shopping'
}, {
id: 'macro-dd',
base64Image: 'iVBORw0KGgoAAAANSUhEUgAAAAEAAAABCAQAAAC1HAwCAAAAC0lEQVQYV2NgYAAAAAMAAWgmWQ0AAAAASUVORK5CYII=',
name: 'Direct debits'
}, {
id: 'macro-tub',
base64Image: 'iVBORw0KGgoAAAANSUhEUgAAAAEAAAABCAQAAAC1HAwCAAAAC0lEQVQYV2NgYAAAAAMAAWgmWQ0AAAAASUVORK5CYII=',
name: 'Foreign Currency Transfer'
}, {
id: 'macro-wu',
base64Image: 'iVBORw0KGgoAAAANSUhEUgAAAAEAAAABCAQAAAC1HAwCAAAAC0lEQVQYV2NgYAAAAAMAAWgmWQ0AAAAASUVORK5CYII=',
name: 'N26 Referrals'
}, {
id: 'micro-salary',
base64Image: 'iVBORw0KGgoAAAANSUhEUgAAAAEAAAABCAQAAAC1HAwCAAAAC0lEQVQYV2NgYAAAAAMAAWgmWQ0AAAAASUVORK5CYII=',
name: 'Salary'
}, {
id: 'micro-car',
base64Image: 'iVBORw0KGgoAAAANSUhEUgAAAAEAAAABCAQAAAC1HAwCAAAAC0lEQVQYV2NgYAAAAAMAAWgmWQ0AAAAASUVORK5CYII=',
name: 'Car'
}, {
id: 'micro-business',
base64Image: 'iVBORw0KGgoAAAANSUhEUgAAAAEAAAABCAQAAAC1HAwCAAAAC0lEQVQYV2NgYAAAAAMAAWgmWQ0AAAAASUVORK5CYII=',
name: 'Business expenses'
}, {
id: 'micro-bars-restaurants',
base64Image: 'iVBORw0KGgoAAAANSUhEUgAAAAEAAAABCAQAAAC1HAwCAAAAC0lEQVQYV2NgYAAAAAMAAWgmWQ0AAAAASUVORK5CYII=',
name: 'Bars & Restaurants'
}, {
id: 'micro-multimedia',
base64Image: 'iVBORw0KGgoAAAANSUhEUgAAAAEAAAABCAQAAAC1HAwCAAAAC0lEQVQYV2NgYAAAAAMAAWgmWQ0AAAAASUVORK5CYII=',
name: 'Multimedia & Telecom'
}, {
id: 'macro-dr',
base64Image: 'iVBORw0KGgoAAAANSUhEUgAAAAEAAAABCAQAAAC1HAwCAAAAC0lEQVQYV2NgYAAAAAMAAWgmWQ0AAAAASUVORK5CYII=',
name: 'Direct debit reversals'
}, {
id: 'macro-ft',
base64Image: 'iVBORw0KGgoAAAANSUhEUgAAAAEAAAABCAQAAAC1HAwCAAAAC0lEQVQYV2NgYAAAAAMAAWgmWQ0AAAAASUVORK5CYII=',
name: 'MoneyBeam'
}, {
id: 'macro-tbu',
base64Image: 'iVBORw0KGgoAAAANSUhEUgAAAAEAAAABCAQAAAC1HAwCAAAAC0lEQVQYV2NgYAAAAAMAAWgmWQ0AAAAASUVORK5CYII=',
name: 'Foreign currency refund'
}, {
id: 'macro-dt',
base64Image: 'iVBORw0KGgoAAAANSUhEUgAAAAEAAAABCAQAAAC1HAwCAAAAC0lEQVQYV2NgYAAAAAMAAWgmWQ0AAAAASUVORK5CYII=',
name: 'Outgoing transfers'
}, {
id: 'micro-children',
base64Image: 'iVBORw0KGgoAAAANSUhEUgAAAAEAAAABCAQAAAC1HAwCAAAAC0lEQVQYV2NgYAAAAAMAAWgmWQ0AAAAASUVORK5CYII=',
name: 'Children'
}, {
id: 'micro-tax-fines',
base64Image: 'iVBORw0KGgoAAAANSUhEUgAAAAEAAAABCAQAAAC1HAwCAAAAC0lEQVQYV2NgYAAAAAMAAWgmWQ0AAAAASUVORK5CYII=',
name: 'Tax & Fines'
}];

it('should return categories', () => {
const api = nock('https://api.tech26.de')
.defaultReplyHeaders({
'Content-Type': 'application/json'
})
.matchHeader('Authorization', `Bearer ${data.account.access_token}`)
.get('/api/smrt/categories')
.reply(200, categoriesData);

return n26.categories().then((categories) => {
expect(categories).to.be.eql(categoriesData);
expect(api.isDone()).to.be.true();
});
});
});
Loading

0 comments on commit 1638923

Please sign in to comment.