Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Uk/1316 ui grid reports #1547

Closed
wants to merge 63 commits into from
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
63 commits
Select commit Hold shift + click to select a range
9ca5341
Cherry-pick b2d82b6 - Using ofnSelect2 instead of plain select on BOM
RohanM Aug 31, 2016
ad76528
Refactoring ofnSelect2, works with multiple, and with promised data
oeoeaio Aug 31, 2016
009bf0b
Expunge all mentions of includeBlank and blankOption from angular ser…
oeoeaio Sep 18, 2016
8c44add
Changing convention for angular resource services to generic 'byID' o…
oeoeaio Aug 20, 2016
d33df30
Creating new 'resources' module for holding interdependent ngResource…
oeoeaio Aug 21, 2016
74f644b
Adding #load function to services for resources, for generic loading …
oeoeaio Sep 18, 2016
2c287b8
SPIKE: Initial cut at adding UI-Grid
oeoeaio Aug 21, 2016
1f552d2
SPIKE: Basic grid showing data
oeoeaio Sep 21, 2016
206715e
SPIKE: Sorting out ui-grid fonts
oeoeaio Oct 27, 2016
c704925
SPIKE: shifting uigrid inclusion in css manifest (tiny change)
oeoeaio Oct 27, 2016
cd5c4b7
SPIKE: Adding more columns for demonstration
oeoeaio Oct 27, 2016
9dbc135
SPIKE: Using treeView instead of grouping
oeoeaio Oct 25, 2016
346a8f3
SPIKE: Back to grouping with ui-grid, using aggregations to diplay re…
oeoeaio Oct 27, 2016
fa911f3
SPIKE: Getting filters working on orders and fulfillments report page
oeoeaio Oct 27, 2016
fd584bb
SPIKE: Export as CSV using ui-grid
oeoeaio Oct 27, 2016
d566086
Merge oeoeaio/ui-grid-reports
jeronimo Mar 27, 2017
a92071c
Copy paste js files for orders and distributors
jeronimo Mar 27, 2017
b1d69be
Working Orders and Distributors report mockup
jeronimo Mar 29, 2017
444ee92
Orders and Distribution: Make SKU visible for items
jeronimo Mar 29, 2017
a89a08f
Merge branch 'master' into uk/1316-ui-grid-reports
jeronimo Mar 31, 2017
8d12518
Add PdfMake lib for ui-grid PDF export
jeronimo Mar 31, 2017
1328431
Orders and distributions: show all fields and group properly
jeronimo Mar 31, 2017
da10c01
Orders and distributions: enable grid menu and PDF download
jeronimo Mar 31, 2017
457cbfd
Orders and distributions: set MaxGridWidth for PDF export
jeronimo Mar 31, 2017
9247066
Orders and distributions: Add "Loading..." and "No data available" no…
jeronimo Apr 3, 2017
c35a165
Orders and distributions: Add default start date for filter
jeronimo Apr 3, 2017
1e7406a
Orders and distributions: Add default start date for filter && some t…
jeronimo Apr 3, 2017
689afd0
Add capybara-screenshot gem
jeronimo Apr 3, 2017
12e67db
Orders and distributors: Cleanup code and fix tests
jeronimo Apr 3, 2017
cceba09
Add pdfmake js map
jeronimo Apr 3, 2017
40b5ce1
Show currency symbol before amount
jeronimo Apr 6, 2017
3fd7a98
Orders and Fulfillments: Adapt ui grid menu && loading/no-data functi…
jeronimo Apr 6, 2017
8ebda59
Bulk coop: make different ui-grid columns for different report types
jeronimo Apr 7, 2017
4d136f7
Bulk coop: Enable switching between old and new versions
jeronimo Apr 7, 2017
535ec98
Bulk coop: More reports
jeronimo Apr 7, 2017
9b216ee
Bulk coop: Group properly "by supplier" report
jeronimo Apr 10, 2017
ba9383f
Bulk coop: Move export buttons outside ui-grid
jeronimo Apr 10, 2017
d4a6eca
Bulk coop: Move export buttons outside ui-grid+
jeronimo Apr 10, 2017
37ecd52
Orders and distributors: Restore old functionality and move export bu…
jeronimo Apr 10, 2017
8473978
Orders and Fulfillments: First 2 report types init
jeronimo Apr 10, 2017
bb43600
Orders and Fulfillments: Last 2 reports and specific grouping for Ord…
jeronimo Apr 12, 2017
097636e
Merge branch 'master' into uk/1316-ui-grid-reports
jeronimo Apr 12, 2017
a5a1146
Get rid off pdfmake js map
jeronimo Apr 12, 2017
c0022c6
Upgrade ui-grid to 4.0.4 version and override ugly gradient color
jeronimo Apr 12, 2017
1b7fafe
Fix mistypes and refactoring issues
jeronimo Apr 12, 2017
605bf12
Orders and Fulfillments: Different report types via urls && fix repor…
jeronimo Apr 12, 2017
2627c7a
Adapt and fix reports tests with ui-grid
jeronimo Apr 13, 2017
37cb961
More spec tests for overhauled reports
jeronimo Apr 13, 2017
0e99a8e
Fix feature tests for overhauled reports
jeronimo Apr 13, 2017
73580a0
Speed up some feature tests
jeronimo Apr 14, 2017
56ae5dc
Extract duplicated code and add more tests for ruby code
jeronimo Apr 14, 2017
74370b3
Refactoring and adding Angularjs controllers tests
jeronimo Apr 18, 2017
b3ead35
Extract Reports' methods into UIGridHelper
jeronimo Apr 19, 2017
9d84988
UIGridHelper code coverage
jeronimo Apr 19, 2017
c46a09f
Extract duplicated haml code to partials &&
jeronimo Apr 19, 2017
b1f5035
Cleanup and refactoring of reports decorator and line items serializer
jeronimo Apr 20, 2017
7b8221c
Refactor code to BaseReport and fix broken tests
jeronimo Apr 26, 2017
c5a9913
Debugging why test fails in Travis
jeronimo Apr 26, 2017
20b5aca
Time equality match fails in Travis
jeronimo Apr 26, 2017
c60182c
Merge branch 'master' into uk/1316-ui-grid-reports
jeronimo May 3, 2017
954530b
Merge branch 'master' into uk/1316-ui-grid-reports
jeronimo May 7, 2017
fdb1c59
Merge branch 'master' into uk/1316-ui-grid-reports
jeronimo May 12, 2017
9546123
Replace some rspec syntax to expect and cleanup gemfile.lock
jeronimo May 12, 2017
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion Gemfile.lock
Original file line number Diff line number Diff line change
Expand Up @@ -749,4 +749,4 @@ RUBY VERSION
ruby 2.1.5p273

BUNDLED WITH
1.14.3
1.14.6
Binary file added app/assets/fonts/admin/ui-grid.ttf
Binary file not shown.
Binary file added app/assets/fonts/admin/ui-grid.woff
Binary file not shown.
4 changes: 4 additions & 0 deletions app/assets/javascripts/admin/all.js
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,10 @@
//= require admin/spree_promo
//= require admin/spree_paypal_express
//= require ../shared/ng-infinite-scroll.min.js
//= require ../shared/ui-grid.min.js
//= require ../shared/ng-tags-input.min.js
//= require ../shared/pdfmake.min.js
//= require ../shared/vfs_fonts.js
//= require angular-rails-templates
//= require_tree ../templates/admin
//= require ./admin_ofn
Expand All @@ -38,6 +41,7 @@
//= require ./payment_methods/payment_methods
//= require ./products/products
//= require ./resources/resources
//= require ./reports/reports
//= require ./shipping_methods/shipping_methods
//= require ./side_menu/side_menu
//= require ./tag_rules/tag_rules
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -7,3 +7,5 @@ angular.module("admin.indexUtils").directive "datepicker", ->
scope.$apply (scope) ->
# Fires ngModel.$parsers
ngModel.$setViewValue dateText
if attrs.value
ngModel.$setViewValue attrs.value
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This isn't really what this directive is for. If you need to change the datepicker elements to rails form elements rather than pure angular elements, I would suggest removing the ng-model directive altogether (it is doing nothing) and using our custom watch-value-as directive instead.

That said, my preference (instead of c35a165) would be to inject the search data as a service, and have everything be pure angular from there on. I don't like hacking rails form elements to make them 'work' with angular. Too many pitfalls, and too hard to work out what is going wrong when you have multiple custom directives all trying to manipulate the value of the form element directly.

Original file line number Diff line number Diff line change
@@ -0,0 +1,34 @@
angular.module("admin.reports").controller "bulkCoopCtrl", ($scope, $controller, $location, $http, BulkCoopReport, Enterprises, LineItems, Orders, Products, Variants, distributors, reportType) ->
angular.extend this, $controller('ReportsCtrl', {$scope: $scope, $location: $location})

if $location.search().report_type
reportType = $location.search().report_type
$scope.q = {report_type: reportType}
$scope.reportType = reportType
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I am a bit confused about what is happening with reportType. It looks like we are injecting the report type as an angular service based on the @report_type instance variable, but we are also searching the path for a param named report_type? Surely we don't need both? In fact it looks like the latter is overriding the former anyway...


$scope.distributors = distributors
$scope.columnOptions = BulkCoopReport.columnOptions()
$scope.gridOptions = BulkCoopReport.gridOptions(reportType)
$scope.gridOptions.onRegisterApi = (gridApi) -> $scope.gridApi = gridApi

$scope.load = ->
$scope.loading = true
$scope.loadAttempted = false
$scope.gridOptions.data = []
params = {}
params["q[#{param}]"] = value for param, value of $scope.q
$http.get('/admin/reports/bulk_coop.json', params: params)
.success (data) ->
LineItems.load data.line_items
Orders.load data.orders
Variants.load data.variants
Products.load data.products
Enterprises.load data.distributors
LineItems.linkToOrders()
LineItems.linkToVariants()
LineItems.linkToProducts()
$scope.gridOptions.data = LineItems.all
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I realise that this is work in progress, but we will need to at least have a generic "Loading data failed" message render if data can't be loaded.

.finally ->
$scope.loading = false
$scope.loadAttempted = true

Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
angular.module("admin.reports").controller "ordersAndDistributorsCtrl", ($scope, $controller, $http, OrdersAndDistributorsReport, Enterprises, LineItems, Orders, Products, Variants) ->
angular.extend this, $controller('ReportsCtrl', {$scope: $scope})

$scope.gridOptions = OrdersAndDistributorsReport.gridOptions()
$scope.gridOptions.onRegisterApi = (gridApi) -> $scope.gridApi = gridApi

$scope.load = ->
$scope.loading = true
$scope.loadAttempted = false
$scope.gridOptions.data = []
params = {}
params["q[#{param}]"] = value for param, value of $scope.q
$http.get('/admin/reports/orders_and_distributors.json', params: params)
.success (data) ->
LineItems.load data.line_items
Orders.load data.orders
Variants.load data.variants
Products.load data.products
Enterprises.load data.distributors

Orders.linkToDistributors()
LineItems.linkToOrders()
LineItems.linkToVariants()
$scope.gridOptions.data = LineItems.all
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Ditto with error message

.finally ->
$scope.loading = false
$scope.loadAttempted = true

Original file line number Diff line number Diff line change
@@ -0,0 +1,34 @@
angular.module("admin.reports").controller "ordersAndFulfillmentsCtrl", ($scope, $controller, $http, $location, OrdersAndFulfillmentsReport, Enterprises, OrderCycles, LineItems, Orders, Products, Variants, shops, producers, reportType) ->
angular.extend this, $controller('ReportsCtrl', {$scope: $scope, $location: $location})

$scope.shops = shops
$scope.producers = producers
$scope.orderCycles = OrderCycles.all
$scope.columnOptions = OrdersAndFulfillmentsReport.columnOptions()

if $location.search().report_type
reportType = $location.search().report_type
$scope.q = {report_type: reportType}
$scope.reportType = reportType

$scope.gridOptions = OrdersAndFulfillmentsReport.gridOptions(reportType)
$scope.gridOptions.onRegisterApi = (gridApi) -> $scope.gridApi = gridApi

$scope.load = ->
$scope.loading = true
$scope.loadAttempted = false
$scope.gridOptions.data = []
params = {}
params["q[#{param}]"] = value for param, value of $scope.q
$http.get('/admin/reports/orders_and_fulfillment.json', params: params)
.success (data) ->
LineItems.load data.line_items
Orders.load data.orders
Products.load data.products
Variants.load data.variants
LineItems.linkToOrders()
LineItems.linkToProducts()
$scope.gridOptions.data = LineItems.all
.finally ->
$scope.loading = false
$scope.loadAttempted = true
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
angular.module("admin.reports").controller 'ReportsCtrl', ($scope, $location) ->
$scope.loading = false
$scope.loadAttempted = false

$scope.download = ($event, type, visibility = 'all') ->
$event.stopPropagation()
$event.preventDefault()
if type == 'csv'
$scope.gridApi.exporter.csvExport(visibility, visibility)
else
$scope.gridApi.exporter.pdfExport(visibility, visibility)

$scope.reload = ->
$scope.loading = false
$scope.loadAttempted = false
$scope.reportType = $scope.q.report_type
$scope.gridOptions.columnDefs = $scope.$eval('columnOptions.' + $scope.reportType)
Copy link
Contributor

@oeoeaio oeoeaio Jun 16, 2017

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Do we need reportType and q.report_type? It looks like they are alway the same value? As soon as q.report_type changes it called reload() which then changes reportType...

$location.search('report_type', $scope.reportType)
$scope.gridOptions.data = new Array()
$scope.gridApi.grid.refresh()
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
angular.module("admin.reports").filter "customCurrency", ($filter, currencyConfig) ->
return (value) ->
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Could rename this as localizeCurrency and make it the same as the service of that name in the frontend (Darkswarm)?

value = 0 if !value
if currencyConfig && currencyConfig.currency
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

By requesting currencyConfig on the first line, you are setting it as a dependency, so no need to test for it here. If you want this to run on pages with and without currencyConfig being defined, you can remove it as a dependency and use the $injector service instead to test for the presence of currencyConfig.

return currencyConfig.symbol + parseFloat(value).toFixed(2)
else
return parseFloat(value).toFixed(2)
1 change: 1 addition & 0 deletions app/assets/javascripts/admin/reports/reports.js.coffee
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
angular.module("admin.reports", ['admin.indexUtils', 'ui.grid', 'ui.grid.resizeColumns', 'ui.grid.moveColumns', 'ui.grid.grouping', 'ui.grid.exporter', 'admin.resources'])
Original file line number Diff line number Diff line change
@@ -0,0 +1,60 @@
angular.module("admin.reports").factory 'BulkCoopReport', (uiGridGroupingConstants, UIGridReport) ->
new class BulkCoopReport extends UIGridReport
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This bit is awesome 👍


columnOptions: ->
{supplier_report: [
{ field: 'id', displayName: 'Line Item ID', width: '5%', visible: false, groupingShowAggregationMenu: false, groupingShowGroupingMenu: false }
{ field: 'product.producer.name', displayName: 'Supplier', width: '15%', sort: { priority: 0, direction: 'asc' }, grouping: { groupPriority: 1 }, groupingShowAggregationMenu: false, groupingShowGroupingMenu: false }
{ field: 'product.name', displayName: 'Product', width: '15%', sort: { priority: 1, direction: 'asc' }, grouping: { groupPriority: 10 }, groupingShowAggregationMenu: false, groupingShowGroupingMenu: false }
{ field: 'product.group_buy_unit_size', displayName: 'Bulk Unit size', width: '8%', groupingShowAggregationMenu: false, groupingShowGroupingMenu: false, treeAggregationType: uiGridGroupingConstants.aggregation.SUM, customTreeAggregationFinalizerFn: @basicFinalizer }
{ field: 'full_name', displayName: 'Variant', width: '10%', groupingShowAggregationMenu: false, groupingShowGroupingMenu: false }
{ field: 'variant.value', displayName: 'Variant value', width: '10%', groupingShowAggregationMenu: false, groupingShowGroupingMenu: false }
{ field: 'variant.unit', displayName: 'Variant unit', width: '10%', groupingShowAggregationMenu: false, groupingShowGroupingMenu: false }
{ field: 'variant.weight_from_unit_value', displayName: 'Weight', width: '8%', groupingShowAggregationMenu: false, groupingShowGroupingMenu: false }
{ field: 'scaled_final_weight_volume', displayName: 'Sum Total', width: '8%', groupingShowAggregationMenu: false, groupingShowGroupingMenu: false, treeAggregationType: uiGridGroupingConstants.aggregation.SUM, customTreeAggregationFinalizerFn: @basicFinalizer }
{ field: 'units_required', displayName: 'Units required', width: '8%', groupingShowAggregationMenu: false, groupingShowGroupingMenu: false, treeAggregationType: uiGridGroupingConstants.aggregation.SUM, customTreeAggregationFinalizerFn: @basicFinalizer }
{ field: 'remainder', displayName: 'Unallocated', width: '8%', groupingShowAggregationMenu: false, groupingShowGroupingMenu: false, treeAggregationType: uiGridGroupingConstants.aggregation.SUM, customTreeAggregationFinalizerFn: @basicFinalizer }
{ field: 'max_quantity_excess', displayName: 'Max quantity excess', width: '8%', groupingShowAggregationMenu: false, groupingShowGroupingMenu: false, treeAggregationType: uiGridGroupingConstants.aggregation.SUM, customTreeAggregationFinalizerFn: @basicFinalizer }
],
allocation: [
{ field: 'id', displayName: 'Line Item ID', width: '5%', visible: false, groupingShowAggregationMenu: false, groupingShowGroupingMenu: false }
{ field: 'order.customer', displayName: 'Customer', width: '15%', groupingShowAggregationMenu: false, groupingShowGroupingMenu: false }
{ field: 'product.name', displayName: 'Product', width: '15%', sort: { priority: 0, direction: 'asc' }, grouping: { groupPriority: 0 }, groupingShowAggregationMenu: false, groupingShowGroupingMenu: false }
{ field: 'product.group_buy_unit_size', displayName: 'Bulk Unit size', width: '8%', groupingShowAggregationMenu: false, groupingShowGroupingMenu: false }
{ field: 'full_name', displayName: 'Variant', width: '10%', groupingShowAggregationMenu: false, groupingShowGroupingMenu: false }
{ field: 'variant.value', displayName: 'Variant value', width: '10%', groupingShowAggregationMenu: false, groupingShowGroupingMenu: false }
{ field: 'variant.unit', displayName: 'Variant unit', width: '10%', groupingShowAggregationMenu: false, groupingShowGroupingMenu: false }
{ field: 'variant.weight_from_unit_value', displayName: 'Weight', width: '8%', groupingShowAggregationMenu: false, groupingShowGroupingMenu: false }
{ field: 'scaled_final_weight_volume', displayName: 'Sum Total', width: '8%', groupingShowAggregationMenu: false, groupingShowGroupingMenu: false, treeAggregationType: uiGridGroupingConstants.aggregation.SUM, customTreeAggregationFinalizerFn: @basicFinalizer }
{ field: 'total_available', displayName: 'Total available', width: '8%', groupingShowAggregationMenu: false, groupingShowGroupingMenu: false, treeAggregationType: uiGridGroupingConstants.aggregation.SUM, customTreeAggregationFinalizerFn: @basicFinalizer }
{ field: 'remainder', displayName: 'Unallocated', width: '8%', groupingShowAggregationMenu: false, groupingShowGroupingMenu: false }
{ field: 'max_quantity_excess', displayName: 'Max quantity excess', width: '8%', groupingShowAggregationMenu: false, groupingShowGroupingMenu: false, treeAggregationType: uiGridGroupingConstants.aggregation.SUM, customTreeAggregationFinalizerFn: @basicFinalizer }
],
packing_sheets: [
{ field: 'id', displayName: 'Line Item ID', width: '*', visible: false, groupingShowAggregationMenu: false, groupingShowGroupingMenu: false }
{ field: 'order.customer', displayName: 'Customer', width: '*', groupingShowAggregationMenu: false, groupingShowGroupingMenu: false }
{ field: 'product.name', displayName: 'Product', width: '*', sort: { priority: 0, direction: 'asc' }, groupingShowAggregationMenu: false, groupingShowGroupingMenu: false }
{ field: 'full_name', displayName: 'Variant', width: '*', groupingShowAggregationMenu: false, groupingShowGroupingMenu: false }
{ field: 'quantity', displayName: 'Sum total', width: '*', groupingShowAggregationMenu: false, groupingShowGroupingMenu: false }
],
customer_payments: [
{ field: 'order.id', displayName: 'Order ID', width: '*', visible: false, grouping: { groupPriority: 0 }, groupingShowAggregationMenu: false, groupingShowGroupingMenu: false }
{ field: 'order.customer', displayName: 'Customer', width: '*', groupingShowAggregationMenu: false, groupingShowGroupingMenu: false, treeAggregationType: uiGridGroupingConstants.aggregation.CUSTOM, customTreeAggregationFn: @orderAggregator, customTreeAggregationFinalizerFn: @customerFinalizer }
{ field: 'order.completed_at', displayName: 'Date of order', width: '*', sort: { priority: 0, direction: 'asc' }, groupingShowAggregationMenu: false, groupingShowGroupingMenu: false, treeAggregationType: uiGridGroupingConstants.aggregation.CUSTOM, customTreeAggregationFn: @orderAggregator, customTreeAggregationFinalizerFn: @orderDateFinalizer }
{ field: 'order.total', displayName: 'Total cost', width: '*', cellFilter: "customCurrency", groupingShowAggregationMenu: false, groupingShowGroupingMenu: false, treeAggregationType: uiGridGroupingConstants.aggregation.CUSTOM, customTreeAggregationFn: @orderAggregator, customTreeAggregationFinalizerFn: @orderTotalFinalizer }
{ field: 'order.outstanding_balance', displayName: 'Amount owing', width: '*', cellFilter: "customCurrency", groupingShowAggregationMenu: false, groupingShowGroupingMenu: false, treeAggregationType: uiGridGroupingConstants.aggregation.CUSTOM, customTreeAggregationFn: @orderAggregator, customTreeAggregationFinalizerFn: @orderOutstandingBalanceFinalizer }
{ field: 'order.payment_total', displayName: 'Amount paid', width: '*', cellFilter: "customCurrency", groupingShowAggregationMenu: false, groupingShowGroupingMenu: false, treeAggregationType: uiGridGroupingConstants.aggregation.CUSTOM, customTreeAggregationFn: @orderAggregator, customTreeAggregationFinalizerFn: @orderPaymentTotalFinalizer }
]
}

gridOptions: (reportType = 'supplier_report') ->
enableSorting: true
enableFiltering: true
enableGridMenu: true
exporterMenuAllData: false
exporterMenuVisibleData: false
exporterPdfDefaultStyle: {fontSize: 6 }
exporterPdfTableHeaderStyle: { fontSize: 5, bold: true }
exporterPdfTableStyle: { width: 'auto'}
exporterPdfMaxGridWidth: 600
columnDefs: eval('this.columnOptions().' + reportType)
Loading