From 3593f293ce42844e5a0a7727120a832ad99c25c1 Mon Sep 17 00:00:00 2001 From: Sylvain Date: Tue, 31 May 2016 10:02:27 +0200 Subject: [PATCH] [feature] partial load of invoices list --- .../controllers/admin/invoices.coffee.erb | 82 ++++++++++++++++++- .../controllers/admin/members.coffee.erb | 13 ++- app/assets/javascripts/router.coffee.erb | 5 ++ .../javascripts/services/invoice.coffee | 4 + .../templates/admin/invoices/index.html.erb | 11 ++- app/controllers/api/invoices_controller.rb | 45 ++++++++++ app/policies/invoice_policy.rb | 4 + app/views/api/invoices/list.json.jbuilder | 12 +++ config/locales/app.admin.en.yml | 1 + config/locales/app.admin.fr.yml | 1 + config/routes.rb | 1 + 11 files changed, 171 insertions(+), 8 deletions(-) create mode 100644 app/views/api/invoices/list.json.jbuilder diff --git a/app/assets/javascripts/controllers/admin/invoices.coffee.erb b/app/assets/javascripts/controllers/admin/invoices.coffee.erb index ce723d05b..9d48892aa 100644 --- a/app/assets/javascripts/controllers/admin/invoices.coffee.erb +++ b/app/assets/javascripts/controllers/admin/invoices.coffee.erb @@ -3,15 +3,34 @@ ## # Controller used in the admin invoices listing page ## -Application.Controllers.controller "InvoicesController", ["$scope", "$state", 'Invoice', '$uibModal', "growl", "$filter", 'Setting', 'settings', '_t' -, ($scope, $state, Invoice, $uibModal, growl, $filter, Setting, settings, _t) -> +Application.Controllers.controller "InvoicesController", ["$scope", "$state", 'Invoice', 'invoices', '$uibModal', "growl", "$filter", 'Setting', 'settings', '_t' +, ($scope, $state, Invoice, invoices, $uibModal, growl, $filter, Setting, settings, _t) -> + + + + ### PRIVATE STATIC CONSTANTS ### + + # 10 invoices loaded each time we click on 'load more...' + INVOICES_PER_PAGE = 10 ### PUBLIC SCOPE ### ## List of all users invoices - $scope.invoices = Invoice.query() + $scope.invoices = invoices + + # Invoices filters + $scope.searchInvoice = + date: null + name: '' + reference: '' + + # currently displayed page of invoices (search results) + $scope.page = 1 + + # true when all invoices are loaded + $scope.noMoreResults = false ## Default invoices ordering/sorting $scope.orderInvoice = '-reference' @@ -61,6 +80,9 @@ Application.Controllers.controller "InvoicesController", ["$scope", "$state", 'I else $scope.orderInvoice = orderBy + resetSearchInvoice() + invoiceSearch() + ## @@ -323,6 +345,26 @@ Application.Controllers.controller "InvoicesController", ["$scope", "$state", 'I + ## + # Callback when any of the filters changes. + # Full reload the results list + ## + $scope.handleFilterChange = -> + resetSearchInvoice() + invoiceSearch() + + + + ## + # Callback for the 'load more' button. + # Will load the next results of the current search, if any + ## + $scope.showNextInvoices = -> + $scope.page += 1 + invoiceSearch(true) + + + ### PRIVATE SCOPE ### ## @@ -381,6 +423,40 @@ Application.Controllers.controller "InvoicesController", ["$scope", "$state", 'I + ## + # Reinitialize the context of invoices' search to display new results set + ## + resetSearchInvoice = -> + $scope.page = 1 + $scope.noMoreResults = false + + + + ## + # Run a search query with the current parameters set concerning invoices, then affect or concat the results + # to $scope.invoices + # @param concat {boolean} if true, the result will be append to $scope.invoices instead of being affected + ## + invoiceSearch = (concat) -> + Invoice.list { + query: + number: $scope.searchInvoice.reference + customer: $scope.searchInvoice.name + date: $scope.searchInvoice.date + order_by: $scope.orderInvoice + page: $scope.page + size: INVOICES_PER_PAGE + }, (invoices) -> + if (invoices.length < INVOICES_PER_PAGE) + $scope.noMoreResults = true + + if concat + $scope.invoices = $scope.invoices.concat(invoices) + else + $scope.invoices = invoices + + + ## !!! MUST BE CALLED AT THE END of the controller initialize() ] diff --git a/app/assets/javascripts/controllers/admin/members.coffee.erb b/app/assets/javascripts/controllers/admin/members.coffee.erb index 9a5f0b944..0b8726df2 100644 --- a/app/assets/javascripts/controllers/admin/members.coffee.erb +++ b/app/assets/javascripts/controllers/admin/members.coffee.erb @@ -127,7 +127,7 @@ Application.Controllers.controller "AdminMembersController", ["$scope", 'members searchText: '' ## Members ordering/sorting. Default: not sorted order: 'id' - ## current displayed page of members + ## currently displayed page of members page: 1 ## true when all members where loaded noMore: false @@ -186,15 +186,26 @@ Application.Controllers.controller "AdminMembersController", ["$scope", 'members growl.error(_t('unable_to_delete_the_administrator')) + + ## + # Callback for the 'load more' button. + # Will load the next results of the current search, if any + ## $scope.showNextMembers = -> $scope.member.page += 1 memberSearch(true) + + + ## + # Callback when the search field content changes: reload the search results + ## $scope.updateTextSearch = -> resetSearchMember() memberSearch() + ### PRIVATE SCOPE ### ## diff --git a/app/assets/javascripts/router.coffee.erb b/app/assets/javascripts/router.coffee.erb index 196d63eab..5a9719a87 100644 --- a/app/assets/javascripts/router.coffee.erb +++ b/app/assets/javascripts/router.coffee.erb @@ -669,6 +669,11 @@ angular.module('application.router', ['ui.router']). 'invoice_logo' ]").$promise ] + invoices: [ 'Invoice', (Invoice) -> + Invoice.list({ + query: { number: '', customer: '', date: null, order_by: '-reference', page: 1, size: 10 } + }).$promise + ] translations: [ 'Translations', (Translations) -> Translations.query('app.admin.invoices').$promise ] diff --git a/app/assets/javascripts/services/invoice.coffee b/app/assets/javascripts/services/invoice.coffee index d2b3c34ff..d7ba86963 100644 --- a/app/assets/javascripts/services/invoice.coffee +++ b/app/assets/javascripts/services/invoice.coffee @@ -5,4 +5,8 @@ Application.Services.factory 'Invoice', ["$resource", ($resource)-> {id: "@id"}, update: method: 'PUT' + list: + url: '/api/invoices/list' + method: 'POST' + isArray: true ] diff --git a/app/assets/templates/admin/invoices/index.html.erb b/app/assets/templates/admin/invoices/index.html.erb index 11d7b2ee3..730c0c01d 100644 --- a/app/assets/templates/admin/invoices/index.html.erb +++ b/app/assets/templates/admin/invoices/index.html.erb @@ -26,7 +26,7 @@
{{ 'invoice_#_' }} - +
@@ -35,7 +35,7 @@
{{ 'customer_' }} - +
@@ -44,7 +44,7 @@
{{ "date_" | translate }} - +
@@ -69,7 +69,7 @@ - + {{ invoice.reference }} {{ invoice.date | amDateFormat:'L LTS' }} {{ invoice.date | amDateFormat:'L' }} @@ -91,6 +91,9 @@ +
+ +

{{ 'no_invoices_for_now' }}

diff --git a/app/controllers/api/invoices_controller.rb b/app/controllers/api/invoices_controller.rb index de79dafce..22f210a68 100644 --- a/app/controllers/api/invoices_controller.rb +++ b/app/controllers/api/invoices_controller.rb @@ -12,6 +12,51 @@ class API::InvoicesController < API::ApiController send_file File.join(Rails.root, @invoice.file), :type => 'application/pdf', :disposition => 'attachment' end + def list + authorize Invoice + + p = params.require(:query).permit(:number, :customer, :date, :order_by, :page, :size) + + unless p[:page].is_a? Integer + render json: {error: 'page must be an integer'}, status: :unprocessable_entity + end + + unless p[:size].is_a? Integer + render json: {error: 'size must be an integer'}, status: :unprocessable_entity + end + + + direction = (p[:order_by][0] == '-' ? 'DESC' : 'ASC') + order_key = (p[:order_by][0] == '-' ? p[:order_by][1, p[:order_by].size] : p[:order_by]) + + case order_key + when 'reference' + order_key = 'invoices.reference' + when 'date' + order_key = 'invoices.created_at' + when 'total' + order_key = 'invoices.total' + when 'name' + order_key = 'profiles.first_name' + else + order_key = 'invoices.id' + end + + @invoices = Invoice.includes(:avoir, :invoiced, invoice_items: [:subscription, :invoice_item], user: [:profile, :trainings]) + .joins(:user => :profile) + .order("#{order_key} #{direction}") + .page(p[:page]) + .per(p[:size]) + + # ILIKE => PostgreSQL case-insensitive LIKE + @invoices = @invoices.where('invoices.reference LIKE :search', search: "#{p[:number].to_s}%") if p[:number].size > 0 + @invoices = @invoices.where('profiles.first_name ILIKE :search OR profiles.last_name ILIKE :search', search: "%#{p[:customer]}%") if p[:customer].size > 0 + @invoices = @invoices.where("date_trunc('day', invoices.created_at) = :search", search: "%#{DateTime.iso8601(p[:date]).to_time.to_date.to_s}%") unless p[:date].nil? + + @invoices + + end + # only for create avoir def create authorize Invoice diff --git a/app/policies/invoice_policy.rb b/app/policies/invoice_policy.rb index e27c314e5..db3f6127c 100644 --- a/app/policies/invoice_policy.rb +++ b/app/policies/invoice_policy.rb @@ -10,4 +10,8 @@ class InvoicePolicy < ApplicationPolicy def create? user.is_admin? end + + def list? + user.is_admin? + end end diff --git a/app/views/api/invoices/list.json.jbuilder b/app/views/api/invoices/list.json.jbuilder new file mode 100644 index 000000000..09cef1451 --- /dev/null +++ b/app/views/api/invoices/list.json.jbuilder @@ -0,0 +1,12 @@ +json.array!(@invoices) do |invoice| + json.extract! invoice, :id, :created_at, :reference, :invoiced_type, :user_id, :avoir_date + json.total (invoice.total / 100.00) + json.url invoice_url(invoice, format: :json) + json.name invoice.user.profile.full_name + json.has_avoir invoice.has_avoir + json.is_avoir invoice.is_a?(Avoir) + json.is_subscription_invoice invoice.is_subscription_invoice? + json.stripe invoice.stp_invoice_id? + json.date invoice.is_a?(Avoir) ? invoice.avoir_date : invoice.created_at + json.prevent_refund invoice.prevent_refund? +end diff --git a/config/locales/app.admin.en.yml b/config/locales/app.admin.en.yml index ae135f45d..77c179066 100644 --- a/config/locales/app.admin.en.yml +++ b/config/locales/app.admin.en.yml @@ -160,6 +160,7 @@ en: invoice_#: "Invoice #" customer: "Customer" credit_note: "Credit note" + display_more_invoices: "Display more invoices..." invoicing_settings: "Invoicing settings" change_logo: "Change logo" john_smith: "John Smith" diff --git a/config/locales/app.admin.fr.yml b/config/locales/app.admin.fr.yml index 0a44d524c..3d3bb1a9a 100644 --- a/config/locales/app.admin.fr.yml +++ b/config/locales/app.admin.fr.yml @@ -160,6 +160,7 @@ fr: invoice_#: "Facture n°" customer: "Client" credit_note: "Avoir" + display_more_invoices: "Afficher plus de factures ..." invoicing_settings: "Paramètres de facturation" change_logo: "Changer le logo" john_smith: "Jean Dupont" diff --git a/config/routes.rb b/config/routes.rb index c34b94d86..9bbb98a86 100644 --- a/config/routes.rb +++ b/config/routes.rb @@ -79,6 +79,7 @@ Rails.application.routes.draw do resources :invoices, only: [:index, :show, :create] do get ':id/download', action: 'download', on: :collection + post 'list', action: 'list', on: :collection end # for admin