diff --git a/Gruntfile.js b/Gruntfile.js index 782910149..c86689604 100644 --- a/Gruntfile.js +++ b/Gruntfile.js @@ -95,7 +95,7 @@ module.exports = function(grunt) { 'static/javascripts/lodash/dist/lodash.underscore.js', 'static/javascripts/mixpanel/mixpanel.js', 'static/javascripts/google-code-prettify/src/prettify.js', - 'static/javascripts/strftime/index.js', + 'static/javascripts/crossfilter/index.js', 'static/javascripts/jquery-hotkeys/jquery.hotkeys.js', 'static/javascripts/jquery.cookie/jquery.cookie.js', 'static/javascripts/bootstrap-modal/js/bootstrap-modalmanager.js', @@ -104,7 +104,10 @@ module.exports = function(grunt) { 'static/javascripts/moment/moment.js', 'static/lib/moment-business-days.js', 'static/lib/daterangepicker.js', - 'static/javascripts/timepicker/jquery.timepicker.js' + 'static/javascripts/timepicker/jquery.timepicker.js', + 'static/javascripts/d3/d3.min.js', + 'static/javascripts/c3/c3.min.js', + 'static/javascripts/strftime/index.js' ], dest: 'build/js/lib-dev.js' }, @@ -131,7 +134,10 @@ module.exports = function(grunt) { 'static/javascripts/moment/min/moment.min.js', 'static/lib/moment-business-days.js', 'static/lib/daterangepicker.js', - 'static/javascripts/timepicker/jquery.timepicker.min.js' + 'static/javascripts/timepicker/jquery.timepicker.min.js', + 'static/javascripts/d3/d3.min.js', + 'static/javascripts/c3/c3.min.js', + 'static/javascripts/strftime/index.js' ], dest: 'build/js/lib-prod.js' }, @@ -646,7 +652,8 @@ module.exports = function(grunt) { js: { files: [ 'app/**/*.js', - 'static/lib/**/*.js' + 'static/lib/**/*.js', + 'static/javascripts/**/*.js' ], tasks: ['format', '_buildJSAfterTemplates'], options: { diff --git a/app/controllers/overview.js b/app/controllers/overview.js new file mode 100644 index 000000000..838247d6c --- /dev/null +++ b/app/controllers/overview.js @@ -0,0 +1,146 @@ +Balanced.MarketplaceOverviewController = Balanced.ObjectController.extend( + Ember.Evented, + Balanced.ResultsTable, { + needs: ['marketplace'], + baseClassSelector: '#overview', + pageTitle: 'Overview', + + init: function() { + this._super(); + this.loadAnalytics(); + }, + + totalVolume: [], + transactionsCount: [], + + loadAnalytics: function() { + var connection = Balanced.Connections.ApiConnection.create(); + var self = this; + + connection.ajax({ + uri: "/analytics?type=volume" + }).then(function(response) { + var transactions = response.analytics.map(function(day) { + return day.transactions.map(function(transaction) { + return _.extend({}, transaction, { + start_at: day.start_at + }); + }); + }); + transactions = _.flatten(transactions); + self.formatTransactions(transactions); + }); + }, + + formatTransactions: function(data) { + var cf = crossfilter(data); + + var debitCount = ['debits']; + var creditCount = ['credits']; + var refundCount = ['refunds']; + var reversalCount = ['reversals']; + + var debitAmount = ['debits']; + var creditAmount = ['credits']; + var refundAmount = ['refunds']; + var reversalAmount = ['reversals']; + + function reduceAdd(type) { + return function(p, v) { + if (v["type"] === type) { + p.count += v.count; + p.amount += v.amount; + } + return p; + }; + } + + function reduceRemove(type) { + return function(p, v) { + if (v["type"] === type) { + p.count -= v.count; + p.amount -= v.amount; + } + return p; + }; + } + + function reduceInitial() { + return { + count: 0, + amount: 0 + }; + } + + // group transactions by date + var transactionsByDate = cf.dimension(function(p) { + return p.start_at; + }); + + var dates = transactionsByDate.group().all().map(function(transaction) { + return Date.parseISO8601(transaction.key); + }); + dates = ['x'].concat(dates); + + var debits = transactionsByDate.group().reduce(reduceAdd('debit'), reduceRemove('debit'), reduceInitial).all(); + + debitAmount = debitAmount.concat(_.map(debits, function(debit) { + return debit.value.amount + })); + + debitCount = debitCount.concat(_.map(debits, function(debit) { + return debit.value.count + })); + + var credits = transactionsByDate.group().reduce(reduceAdd('credit'), reduceRemove('credit'), reduceInitial).all(); + + creditAmount = creditAmount.concat(_.map(credits, function(credit) { + return credit.value.amount + })); + + creditCount = creditCount.concat(_.map(credits, function(credit) { + return credit.value.count + })); + + var refunds = transactionsByDate.group().reduce(reduceAdd('refund'), reduceRemove('refund'), reduceInitial).all(); + + refundAmount = refundAmount.concat(_.map(refunds, function(refund) { + return refund.value.amount + })); + + refundCount = refundCount.concat(_.map(refunds, function(refund) { + return refund.value.count + })); + + var reversals = transactionsByDate.group().reduce(reduceAdd('reversal'), reduceRemove('reversal'), reduceInitial).all(); + + reversalAmount = reversalAmount.concat(_.map(reversals, function(reversal) { + return reversal.value.amount + })); + + reversalCount = reversalCount.concat(_.map(reversals, function(reversal) { + return reversal.value.count + })); + + this.set("totalVolume", { + x: 'x', + columns: [dates, debitAmount, creditAmount, refundAmount, reversalAmount] + }); + + this.set("transactionsCount", { + x: 'x', + columns: [dates, debitCount, creditCount, refundCount, reversalCount] + }); + + this.set("verticalBarChartData", { + x: 'x', + columns: [dates, debitCount] + }); + + this.set("horizontalBarChartData", { + x: 'x', + columns: [dates, debitCount] + }); + }, + + }); diff --git a/app/routes/router.js b/app/routes/router.js index 49f7a6d97..c47f12b16 100644 --- a/app/routes/router.js +++ b/app/routes/router.js @@ -78,6 +78,7 @@ Balanced.Router.map(function() { this.resource('marketplace', { path: '/:marketplace_id' }, function() { + this.route('overview'); this.route('settings'); this.route('add_customer'); this.route('import_payouts'); diff --git a/app/templates/charts/line-chart-with-legend.hbs b/app/templates/charts/line-chart-with-legend.hbs new file mode 100644 index 000000000..8eed73073 --- /dev/null +++ b/app/templates/charts/line-chart-with-legend.hbs @@ -0,0 +1,35 @@ +
+

Total volume

+ + + + + + + + + + + +
+ +
+
+ Debits +
+
+ $123.45 +
+ +
+
+ Credits +
+
+ $123.45 +
+
+ +
+ {{view Balanced.LineChartView data=view.data viewName="lineChartView"}} +
diff --git a/app/templates/components/meta.hbs b/app/templates/components/meta.hbs deleted file mode 100644 index 998fb55dc..000000000 --- a/app/templates/components/meta.hbs +++ /dev/null @@ -1,15 +0,0 @@ -
-
-

Meta

-
- {{#if view.meta_array}} -
- {{#each meta in view.meta_array}} -
{{meta.key}}
-
{{meta.value}}
- {{/each}} -
- {{else}} - none - {{/if}} -
diff --git a/app/templates/marketplace/overview.hbs b/app/templates/marketplace/overview.hbs new file mode 100644 index 000000000..b50621729 --- /dev/null +++ b/app/templates/marketplace/overview.hbs @@ -0,0 +1,45 @@ + +
+ {{view Balanced.DateFilterHeaderView}} + + + +
+
+ {{#view Balanced.BodyPanelView}} + {{view Balanced.LineChartWithLegendView data=controller.totalVolume}} + {{/view}} + + {{#view Balanced.BodyPanelView}} + {{view Balanced.LineChartWithLegendView data=controller.transactionsCount}} + {{/view}} + + {{#view Balanced.BodyPanelView}} + {{#view Balanced.SidePanelView model=model}} +

Average transaction size

+ {{/view}} + {{#view Balanced.MainPanelView}} + {{view Balanced.VerticalBarChartView data=verticalBarChartData}} + {{/view}} + {{/view}} +
+
+ {{#view Balanced.BodyPanelView}} + {{#view Balanced.SidePanelView model=model}} +

Total card volume

+ {{/view}} + {{#view Balanced.MainPanelView}} + {{view Balanced.HorizontalBarChartView data=horizontalBarChartData}} + {{/view}} + {{/view}} +
+
+
diff --git a/app/views/charts/chart-with-legend.js b/app/views/charts/chart-with-legend.js new file mode 100644 index 000000000..f7eb8113d --- /dev/null +++ b/app/views/charts/chart-with-legend.js @@ -0,0 +1,5 @@ +Balanced.ChartWithLegendView = Ember.View.extend({}); + +Balanced.LineChartWithLegendView = Balanced.ChartWithLegendView.extend({ + templateName: 'charts/line-chart-with-legend' +}); diff --git a/app/views/charts/chart.js b/app/views/charts/chart.js new file mode 100644 index 000000000..1d95c9404 --- /dev/null +++ b/app/views/charts/chart.js @@ -0,0 +1,89 @@ +Balanced.ChartView = Ember.View.extend({ + tagName: 'div', + classNames: ['chart'], + data: {}, + axis: {}, + regions: {}, + grid: {}, + transition: {}, + legend: {}, + tooltip: {}, + subchart: {}, + zoom: {}, + size: {}, + padding: {}, + type: null, + color: { + pattern: ['#639ABD', '#BC8F30', '#9364A8', '#00A08E'] + }, + // @egyptianBlue80, @turmericYellow80, @byzantiumPurple80, @forestGreen80 + + spline: {}, + bar: {}, + + _chart: undefined, + + chart: function() { + var self = this; + if (Ember.isEqual(self.get('_chart'), undefined)) { + // Empty, create it. + var container = self.get('element'); + if (Ember.isEqual(container, undefined)) { + return undefined; + } else { + var config = self.get('_config'); + var chart = c3.generate(config); + self.set('_chart', chart); + return chart; + } + } else { + // Editor is already created and cached. + return self.get('_chart'); + } + }.property('element', '_config'), + + _config: function() { + var c = this.getProperties([ + 'data', + 'axis', + 'regions', + 'bar', + 'grid', + 'legend', + 'tooltip', + 'subchart', + 'zoom', + 'size', + 'padding', + 'color', + 'transition' + ]); + c.data.type = this.get('type'); + c.bindto = this.get('element'); + return c; + }.property('element', 'data', 'type', 'axis', 'regions', 'bar', 'grid', 'legend', 'tooltip', 'subchart', 'zoom', 'size', 'padding', 'color', 'transition'), + + dataDidChange: function() { + var chart = this.get('chart'); + chart.load(this.get('data')); + }.observes('data').on('didInsertElement'), + + actions: { + toggleLegend: function(seriesKey) { + var chart = this.get('chart'); + var data = this.get('data'); + + data.filterBy('key', seriesKey).forEach(function(series) { + series.disabled = !series.disabled; + }); + + if (data.isEvery('disabled')) { + data.forEach(function(series) { + series.disabled = false; + }); + } + + chart.update(); + } + } +}); diff --git a/app/views/charts/horizontal-bar-chart.js b/app/views/charts/horizontal-bar-chart.js new file mode 100644 index 000000000..334899a8a --- /dev/null +++ b/app/views/charts/horizontal-bar-chart.js @@ -0,0 +1,19 @@ +require("./chart"); + +Balanced.HorizontalBarChartView = Balanced.ChartView.extend({ + axis: { + x: { + type: 'timeseries', + tick: { + format: function(x) { + return d3.time.format('%x')(x); + } + } + } + }, + size: { + width: 600, + height: 320 + }, + type: 'bar' +}); diff --git a/app/views/charts/line-chart.js b/app/views/charts/line-chart.js new file mode 100644 index 000000000..7e6484da0 --- /dev/null +++ b/app/views/charts/line-chart.js @@ -0,0 +1,19 @@ +require("./chart"); + +Balanced.LineChartView = Balanced.ChartView.extend({ + axis: { + x: { + type: 'timeseries', + tick: { + format: function(x) { + return d3.time.format('%x')(x); + } + } + } + }, + size: { + width: 600, + height: 320 + }, + type: 'spline' +}); diff --git a/app/views/charts/vertical-bar-chart.js b/app/views/charts/vertical-bar-chart.js new file mode 100644 index 000000000..1d54787ba --- /dev/null +++ b/app/views/charts/vertical-bar-chart.js @@ -0,0 +1,19 @@ +require("./chart"); + +Balanced.VerticalBarChartView = Balanced.ChartView.extend({ + axis: { + x: { + type: 'timeseries', + tick: { + format: function(x) { + return d3.time.format('%x')(x); + } + } + } + }, + size: { + width: 600, + height: 320 + }, + type: 'bar' +}); diff --git a/app/views/sidebar/marketplace_sidebar_view.js b/app/views/sidebar/marketplace_sidebar_view.js index 6e1bc50d9..d0b32dacd 100644 --- a/app/views/sidebar/marketplace_sidebar_view.js +++ b/app/views/sidebar/marketplace_sidebar_view.js @@ -1,4 +1,9 @@ var SIDEBAR_ITEMS = [{ + linkText: "Overview", + linkIcon: "icon-overview", + routeName: "marketplace.overview", + isSelectedBinding: "controller.marketplace.overviewSelected" +}, { linkText: "Payments", linkIcon: "icon-payments", routeName: "marketplace.transactions", diff --git a/bower.json b/bower.json index d8b47d95e..1836d721a 100644 --- a/bower.json +++ b/bower.json @@ -20,7 +20,9 @@ "qunit": "1.14.0", "moment": "2.6.0", "bootstrap-daterangepicker": "1.3.5", - "timepicker": "jonthornton/jquery-timepicker" + "timepicker": "jonthornton/jquery-timepicker", + "crossfilter": "https://raw.githubusercontent.com/square/crossfilter/master/crossfilter.min.js", + "c3": "0.3.0" }, "resolutions": { "jquery": "2.0.3", diff --git a/static/less/base.less b/static/less/base.less index 6b146feaa..2d65af7a2 100644 --- a/static/less/base.less +++ b/static/less/base.less @@ -1,5 +1,7 @@ @import "/static/less/bootstrap.less"; +@import "/static/javascripts/c3/c3.css"; @import "/static/javascripts/strapped/static/less/strapped.less"; + /* * base.less * diff --git a/static/less/overview.less b/static/less/overview.less new file mode 100644 index 000000000..824cd0fff --- /dev/null +++ b/static/less/overview.less @@ -0,0 +1,26 @@ +#overview { + .checkbox { + width: 14px; + min-height: 14px; + display: inline-block; + vertical-align: middle; + padding: 0; + margin-right: 10px; + margin-bottom: 2px; + background-color: @white; + border: 1px solid @gray2; + + &.checked { + background-color: @gray4; + border: 1px solid @gray4; + } + } + + table.list { + tr:hover { + .checkbox { + border: 1px solid @gray4; + } + } + } +} diff --git a/test/support/fixtures/analytics.js b/test/support/fixtures/analytics.js new file mode 100644 index 000000000..d53d7de69 --- /dev/null +++ b/test/support/fixtures/analytics.js @@ -0,0 +1,904 @@ +Balanced.Adapter.addFixtures([{ + "uri": "/analytics?type=volume", + + "analytics": [{ + "escrow_at_start": 3802647, + "start_at": "2014-09-05T16:04:30.281013Z", + "links": {}, + "transactions": [{ + "status": "succeeded", + "count": 57, + "card_type": null, + "amount": 493366, + "card_brand": "visa", + "type": "debit" + }, { + "status": "succeeded", + "count": 35, + "card_type": null, + "amount": 633616, + "card_brand": "mastercard", + "type": "debit" + }, { + "status": "succeeded", + "count": 32, + "card_type": "credit", + "amount": 298887, + "card_brand": "mastercard", + "type": "debit" + }, { + "status": "succeeded", + "count": 85, + "card_type": "debit", + "amount": 639415, + "card_brand": "visa", + "type": "debit" + }, { + "status": "succeeded", + "count": 19, + "card_type": "credit", + "amount": 63446, + "card_brand": "discover", + "type": "debit" + }, { + "status": "succeeded", + "count": 37, + "card_type": null, + "amount": 403550, + "card_brand": "amex", + "type": "debit" + }, { + "status": "succeeded", + "count": 20, + "card_type": "debit", + "amount": 266440, + "card_brand": "mastercard", + "type": "debit" + }, { + "status": "succeeded", + "count": 16, + "card_type": "credit", + "amount": 135727, + "card_brand": "amex", + "type": "debit" + }, { + "status": "succeeded", + "count": 64, + "card_type": "credit", + "amount": 1501938, + "card_brand": "visa", + "type": "debit" + }, { + "count": 3, + "status": "succeeded", + "card_type": null, + "amount": 53935, + "card_brand": "amex", + "type": "refund" + }, { + "count": 1, + "status": "succeeded", + "card_type": "credit", + "amount": 25000, + "card_brand": "amex", + "type": "refund" + }, { + "count": 1, + "status": "succeeded", + "card_type": "credit", + "amount": 6595, + "card_brand": "discover", + "type": "refund" + }, { + "count": 2, + "status": "succeeded", + "card_type": "credit", + "amount": 11595, + "card_brand": "visa", + "type": "refund" + }, { + "count": 1, + "status": "succeeded", + "card_type": "debit", + "amount": 19695, + "card_brand": "mastercard", + "type": "refund" + }, { + "count": 1, + "status": "succeeded", + "card_type": null, + "amount": 5600, + "card_brand": "mastercard", + "type": "refund" + }, { + "count": 4, + "status": "succeeded", + "card_type": null, + "amount": 42580, + "card_brand": "visa", + "type": "refund" + }, { + "count": 3, + "status": "succeeded", + "card_type": "debit", + "amount": 6938, + "card_brand": "visa", + "type": "refund" + }, { + "count": 2, + "status": "succeeded", + "card_type": "credit", + "amount": 14995, + "card_brand": "mastercard", + "type": "refund" + }], + "escrow_at_end": 7591757, + "end_at": "2014-09-06T16:04:30.281013Z" + }, { + "escrow_at_start": 7591757, + "start_at": "2014-09-06T16:04:30.281013Z", + "links": {}, + "transactions": [{ + "status": "succeeded", + "count": 69, + "card_type": null, + "amount": 531116, + "card_brand": "visa", + "type": "debit" + }, { + "status": "succeeded", + "count": 28, + "card_type": null, + "amount": 200199, + "card_brand": "mastercard", + "type": "debit" + }, { + "status": "succeeded", + "count": 27, + "card_type": "credit", + "amount": 244147, + "card_brand": "mastercard", + "type": "debit" + }, { + "status": "succeeded", + "count": 66, + "card_type": "debit", + "amount": 495486, + "card_brand": "visa", + "type": "debit" + }, { + "status": "succeeded", + "count": 9, + "card_type": "credit", + "amount": 146102, + "card_brand": "discover", + "type": "debit" + }, { + "status": "succeeded", + "count": 22, + "card_type": null, + "amount": 95896, + "card_brand": "amex", + "type": "debit" + }, { + "status": "succeeded", + "count": 14, + "card_type": "debit", + "amount": 96296, + "card_brand": "mastercard", + "type": "debit" + }, { + "status": "succeeded", + "count": 5, + "card_type": "credit", + "amount": 42435, + "card_brand": "amex", + "type": "debit" + }, { + "status": "succeeded", + "count": 54, + "card_type": "credit", + "amount": 502823, + "card_brand": "visa", + "type": "debit" + }, { + "count": 2, + "status": "succeeded", + "card_type": "credit", + "amount": 1610, + "card_brand": "amex", + "type": "refund" + }, { + "count": 2, + "status": "succeeded", + "card_type": null, + "amount": 6515, + "card_brand": "visa", + "type": "refund" + }, { + "count": 2, + "status": "succeeded", + "card_type": "credit", + "amount": 7207, + "card_brand": "mastercard", + "type": "refund" + }, { + "count": 3, + "status": "succeeded", + "card_type": "debit", + "amount": 11985, + "card_brand": "visa", + "type": "refund" + }, { + "count": 2, + "status": "succeeded", + "card_type": "debit", + "amount": 11200, + "card_brand": "mastercard", + "type": "refund" + }], + "escrow_at_end": 9771019, + "end_at": "2014-09-07T16:04:30.281013Z" + }, { + "escrow_at_start": 9771019, + "start_at": "2014-09-07T16:04:30.281013Z", + "links": {}, + "transactions": [{ + "status": "succeeded", + "count": 62, + "card_type": null, + "amount": 573382, + "card_brand": "visa", + "type": "debit" + }, { + "status": "succeeded", + "count": 31, + "card_type": null, + "amount": 698775, + "card_brand": "mastercard", + "type": "debit" + }, { + "status": "succeeded", + "count": 36, + "card_type": "credit", + "amount": 387062, + "card_brand": "mastercard", + "type": "debit" + }, { + "status": "succeeded", + "count": 46, + "card_type": "debit", + "amount": 243088, + "card_brand": "visa", + "type": "debit" + }, { + "status": "succeeded", + "count": 15, + "card_type": "credit", + "amount": 96822, + "card_brand": "discover", + "type": "debit" + }, { + "status": "succeeded", + "count": 22, + "card_type": "debit", + "amount": 92147, + "card_brand": "mastercard", + "type": "debit" + }, { + "status": "succeeded", + "count": 27, + "card_type": null, + "amount": 495753, + "card_brand": "amex", + "type": "debit" + }, { + "status": "succeeded", + "count": 25, + "card_type": "credit", + "amount": 244134, + "card_brand": "amex", + "type": "debit" + }, { + "status": "succeeded", + "count": 73, + "card_type": "credit", + "amount": 867537, + "card_brand": "visa", + "type": "debit" + }, { + "status": "succeeded", + "count": 12, + "amount": 8959189, + "type": "credit" + }, { + "count": 1, + "status": "succeeded", + "card_type": null, + "amount": 1650, + "card_brand": "amex", + "type": "refund" + }, { + "count": 1, + "status": "succeeded", + "card_type": "credit", + "amount": 11795, + "card_brand": "amex", + "type": "refund" + }, { + "count": 11, + "status": "succeeded", + "card_type": "credit", + "amount": 72391, + "card_brand": "visa", + "type": "refund" + }, { + "count": 2, + "status": "succeeded", + "card_type": "debit", + "amount": 2600, + "card_brand": "mastercard", + "type": "refund" + }, { + "count": 6, + "status": "succeeded", + "card_type": null, + "amount": 29866, + "card_brand": "mastercard", + "type": "refund" + }, { + "count": 6, + "status": "succeeded", + "card_type": "debit", + "amount": 10887, + "card_brand": "visa", + "type": "refund" + }, { + "count": 4, + "status": "succeeded", + "card_type": null, + "amount": 16240, + "card_brand": "visa", + "type": "refund" + }, { + "count": 4, + "status": "succeeded", + "card_type": "credit", + "amount": 29433, + "card_brand": "mastercard", + "type": "refund" + }], + "escrow_at_end": 3642661, + "end_at": "2014-09-08T16:04:30.281013Z" + }, { + "escrow_at_start": 3642661, + "start_at": "2014-09-08T16:04:30.281013Z", + "links": {}, + "transactions": [{ + "status": "succeeded", + "count": 73, + "card_type": null, + "amount": 520523, + "card_brand": "visa", + "type": "debit" + }, { + "status": "succeeded", + "count": 31, + "card_type": "credit", + "amount": 269201, + "card_brand": "mastercard", + "type": "debit" + }, { + "status": "succeeded", + "count": 64, + "card_type": "debit", + "amount": 323310, + "card_brand": "visa", + "type": "debit" + }, { + "status": "succeeded", + "count": 31, + "card_type": null, + "amount": 226931, + "card_brand": "amex", + "type": "debit" + }, { + "status": "succeeded", + "count": 21, + "card_type": "debit", + "amount": 157955, + "card_brand": "mastercard", + "type": "debit" + }, { + "status": "succeeded", + "count": 16, + "card_type": "credit", + "amount": 69362, + "card_brand": "discover", + "type": "debit" + }, { + "status": "succeeded", + "count": 11, + "card_type": "credit", + "amount": 99196, + "card_brand": "amex", + "type": "debit" + }, { + "status": "succeeded", + "count": 1, + "card_type": null, + "amount": 51195, + "card_brand": "discover", + "type": "debit" + }, { + "status": "succeeded", + "count": 91, + "card_type": "credit", + "amount": 659896, + "card_brand": "visa", + "type": "debit" + }, { + "status": "succeeded", + "count": 40, + "card_type": null, + "amount": 219792, + "card_brand": "mastercard", + "type": "debit" + }, { + "status": "succeeded", + "count": 8, + "amount": 2501304, + "type": "credit" + }, { + "count": 3, + "status": "succeeded", + "card_type": null, + "amount": 33195, + "card_brand": "amex", + "type": "refund" + }, { + "count": 2, + "status": "succeeded", + "card_type": "credit", + "amount": 14370, + "card_brand": "amex", + "type": "refund" + }, { + "count": 4, + "status": "succeeded", + "card_type": null, + "amount": 22017, + "card_brand": "mastercard", + "type": "refund" + }, { + "count": 3, + "status": "succeeded", + "card_type": "credit", + "amount": 38190, + "card_brand": "visa", + "type": "refund" + }, { + "count": 4, + "status": "succeeded", + "card_type": "debit", + "amount": 52665, + "card_brand": "mastercard", + "type": "refund" + }, { + "count": 4, + "status": "succeeded", + "card_type": "credit", + "amount": 37125, + "card_brand": "mastercard", + "type": "refund" + }, { + "count": 8, + "status": "succeeded", + "card_type": "debit", + "amount": 46826, + "card_brand": "visa", + "type": "refund" + }, { + "count": 3, + "status": "succeeded", + "card_type": null, + "amount": 42395, + "card_brand": "visa", + "type": "refund" + }], + "escrow_at_end": 3173373, + "end_at": "2014-09-09T16:04:30.281013Z" + }, { + "escrow_at_start": 3173373, + "start_at": "2014-09-09T16:04:30.281013Z", + "links": {}, + "transactions": [{ + "status": "succeeded", + "count": 61, + "card_type": null, + "amount": 562451, + "card_brand": "visa", + "type": "debit" + }, { + "status": "succeeded", + "count": 25, + "card_type": null, + "amount": 911769, + "card_brand": "mastercard", + "type": "debit" + }, { + "status": "succeeded", + "count": 39, + "card_type": "credit", + "amount": 486280, + "card_brand": "mastercard", + "type": "debit" + }, { + "status": "succeeded", + "count": 56, + "card_type": "debit", + "amount": 445279, + "card_brand": "visa", + "type": "debit" + }, { + "status": "succeeded", + "count": 14, + "card_type": "debit", + "amount": 70090, + "card_brand": "mastercard", + "type": "debit" + }, { + "status": "succeeded", + "count": 21, + "card_type": null, + "amount": 137243, + "card_brand": "amex", + "type": "debit" + }, { + "status": "succeeded", + "count": 15, + "card_type": "credit", + "amount": 67708, + "card_brand": "discover", + "type": "debit" + }, { + "status": "succeeded", + "count": 10, + "card_type": "credit", + "amount": 115497, + "card_brand": "amex", + "type": "debit" + }, { + "status": "succeeded", + "count": 53, + "card_type": "credit", + "amount": 337598, + "card_brand": "visa", + "type": "debit" + }, { + "status": "succeeded", + "count": 10, + "amount": 2366190, + "type": "credit" + }, { + "count": 1, + "status": "succeeded", + "card_type": "credit", + "amount": 4005, + "card_brand": "discover", + "type": "refund" + }, { + "count": 1, + "status": "succeeded", + "card_type": null, + "amount": 2394, + "card_brand": "mastercard", + "type": "refund" + }, { + "count": 10, + "status": "succeeded", + "card_type": "credit", + "amount": 114960, + "card_brand": "visa", + "type": "refund" + }, { + "count": 4, + "status": "succeeded", + "card_type": "credit", + "amount": 6465, + "card_brand": "mastercard", + "type": "refund" + }, { + "count": 3, + "status": "succeeded", + "card_type": "debit", + "amount": 22890, + "card_brand": "visa", + "type": "refund" + }, { + "count": 3, + "status": "succeeded", + "card_type": null, + "amount": 28575, + "card_brand": "visa", + "type": "refund" + }], + "escrow_at_end": 3510642, + "end_at": "2014-09-10T16:04:30.281013Z" + }, { + "escrow_at_start": 3510642, + "start_at": "2014-09-10T16:04:30.281013Z", + "links": {}, + "transactions": [{ + "status": "succeeded", + "count": 53, + "card_type": null, + "amount": 614741, + "card_brand": "visa", + "type": "debit" + }, { + "status": "succeeded", + "count": 23, + "card_type": null, + "amount": 395992, + "card_brand": "mastercard", + "type": "debit" + }, { + "status": "succeeded", + "count": 32, + "card_type": "credit", + "amount": 451841, + "card_brand": "mastercard", + "type": "debit" + }, { + "status": "succeeded", + "count": 61, + "card_type": "debit", + "amount": 333053, + "card_brand": "visa", + "type": "debit" + }, { + "status": "succeeded", + "count": 29, + "card_type": "debit", + "amount": 166382, + "card_brand": "mastercard", + "type": "debit" + }, { + "status": "succeeded", + "count": 17, + "card_type": "credit", + "amount": 116600, + "card_brand": "discover", + "type": "debit" + }, { + "status": "succeeded", + "count": 24, + "card_type": null, + "amount": 246608, + "card_brand": "amex", + "type": "debit" + }, { + "status": "succeeded", + "count": 24, + "card_type": "credit", + "amount": 419476, + "card_brand": "amex", + "type": "debit" + }, { + "status": "succeeded", + "count": 49, + "card_type": "credit", + "amount": 297795, + "card_brand": "visa", + "type": "debit" + }, { + "status": "succeeded", + "count": 11, + "amount": 2290112, + "type": "credit" + }, { + "count": 3, + "status": "succeeded", + "card_type": null, + "amount": 11993, + "card_brand": "amex", + "type": "refund" + }, { + "count": 5, + "status": "succeeded", + "card_type": "credit", + "amount": 46444, + "card_brand": "amex", + "type": "refund" + }, { + "count": 1, + "status": "succeeded", + "card_type": "credit", + "amount": 5695, + "card_brand": "discover", + "type": "refund" + }, { + "count": 2, + "status": "succeeded", + "card_type": "debit", + "amount": 6015, + "card_brand": "mastercard", + "type": "refund" + }, { + "count": 3, + "status": "succeeded", + "card_type": "credit", + "amount": 159790, + "card_brand": "visa", + "type": "refund" + }, { + "count": 4, + "status": "succeeded", + "card_type": null, + "amount": 39477, + "card_brand": "mastercard", + "type": "refund" + }, { + "count": 4, + "status": "succeeded", + "card_type": null, + "amount": 15575, + "card_brand": "visa", + "type": "refund" + }, { + "count": 5, + "status": "succeeded", + "card_type": "debit", + "amount": 26476, + "card_brand": "visa", + "type": "refund" + }, { + "count": 4, + "status": "succeeded", + "card_type": "credit", + "amount": 11645, + "card_brand": "mastercard", + "type": "refund" + }], + "escrow_at_end": 3332261, + "end_at": "2014-09-11T16:04:30.281013Z" + }, { + "escrow_at_start": 3332261, + "start_at": "2014-09-11T16:04:30.281013Z", + "links": {}, + "transactions": [{ + "status": "succeeded", + "count": 51, + "card_type": null, + "amount": 450954, + "card_brand": "visa", + "type": "debit" + }, { + "status": "succeeded", + "count": 22, + "card_type": null, + "amount": 145887, + "card_brand": "mastercard", + "type": "debit" + }, { + "status": "succeeded", + "count": 32, + "card_type": "credit", + "amount": 311060, + "card_brand": "mastercard", + "type": "debit" + }, { + "status": "succeeded", + "count": 63, + "card_type": "debit", + "amount": 356585, + "card_brand": "visa", + "type": "debit" + }, { + "status": "succeeded", + "count": 31, + "card_type": null, + "amount": 171799, + "card_brand": "amex", + "type": "debit" + }, { + "status": "succeeded", + "count": 9, + "card_type": "credit", + "amount": 29000, + "card_brand": "discover", + "type": "debit" + }, { + "status": "succeeded", + "count": 18, + "card_type": "debit", + "amount": 233259, + "card_brand": "mastercard", + "type": "debit" + }, { + "status": "succeeded", + "count": 16, + "card_type": "credit", + "amount": 124711, + "card_brand": "amex", + "type": "debit" + }, { + "status": "succeeded", + "count": 68, + "card_type": "credit", + "amount": 674797, + "card_brand": "visa", + "type": "debit" + }, { + "count": 2, + "status": "succeeded", + "card_type": null, + "amount": 6630, + "card_brand": "amex", + "type": "refund" + }, { + "count": 3, + "status": "succeeded", + "card_type": "credit", + "amount": 23505, + "card_brand": "amex", + "type": "refund" + }, { + "count": 2, + "status": "succeeded", + "card_type": "credit", + "amount": 7775, + "card_brand": "discover", + "type": "refund" + }, { + "count": 4, + "status": "succeeded", + "card_type": "credit", + "amount": 21550, + "card_brand": "visa", + "type": "refund" + }, { + "count": 1, + "status": "succeeded", + "card_type": null, + "amount": 5195, + "card_brand": "mastercard", + "type": "refund" + }, { + "count": 1, + "status": "succeeded", + "card_type": "debit", + "amount": 1320, + "card_brand": "mastercard", + "type": "refund" + }, { + "count": 4, + "status": "succeeded", + "card_type": "debit", + "amount": 3457, + "card_brand": "visa", + "type": "refund" + }, { + "count": 3, + "status": "succeeded", + "card_type": null, + "amount": 1600, + "card_brand": "visa", + "type": "credit" + }], + "escrow_at_end": 3403184, + "end_at": "2014-09-12T16:04:30.281013Z" + }], + "meta": { + "last": "?limit=10&offset=0", + "next": null, + "href": "?limit=10&offset=0", + "limit": 10, + "offset": 0, + "previous": null, + "total": 7, + "first": "?limit=10&offset=0" + }, + "links": {} +}]);