effective_orders 6.0.1 → 6.1.0

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 962e704970c3ca1f08dba05993e31abd30c20cdf4e6b18669a7df4a13e8d0893
4
- data.tar.gz: d26a74b26fb06f4840a01c1fef8723b6e8f16cca1d2e0148326f38e34bdc03af
3
+ metadata.gz: baba1d8301ce1a4cafcd81d4bf87c4c88d99f003e850aae91aff2f23bd17b50e
4
+ data.tar.gz: 34f2dd677e1a3a62acc726e6c6210e5645d721bf96df9d9572333bef1039094f
5
5
  SHA512:
6
- metadata.gz: aa72c2a7664bfac304b7950f50461f71820b15d7c4854405c9d2c71c0eea372e104bff9e2af0cdb7d38f7aa1d88819e129ac9d263c57f4030930466a6fd8e882
7
- data.tar.gz: 878903576b4aef842dbe1bef169a4ae5565ed6df7ca61c018591bcb69bbd6b14626c461e7e53a8de6aa77eefa68578e30b9677188deebe35b2b2e11f03bd196b
6
+ metadata.gz: 0bb85d2c07857a4d7c07de089fd85a9b7d6247d0a4bd56aa3f90f88bd3658679f6086bbb7d58acbf2e17850900704d914e299be70f51ae4a5ec5d786ace30ec0
7
+ data.tar.gz: e648b6df06efae5b2050fa701130c3a9b00d1ecac7b2c03345a1c04a997d2dc76c2eeb9b48c1046b040b25be3e9c6efe20a72c174426416e184b4144dc7de6dd
data/README.md CHANGED
@@ -362,6 +362,14 @@ In addition to the above, the following permissions allow access to the `/admin`
362
362
 
363
363
  ```ruby
364
364
  can :admin, :effective_orders # Can access the admin screens
365
+
366
+ can :index, :report_transactions
367
+ can :index, :report_grouped_transactions
368
+ can :index, :report_payment_providers
369
+
370
+ can :index, Admin::ReportTransactionsDatatable
371
+ can :index, Admin::ReportGroupedTransactionsDatatable
372
+ can :index, Admin::ReportPaymentProvidersDatatable
365
373
  ```
366
374
 
367
375
  ## Whats Included
@@ -0,0 +1,36 @@
1
+ module Admin
2
+ class OrderReportsController < ApplicationController
3
+ before_action(:authenticate_user!) if defined?(Devise)
4
+ before_action { EffectiveResources.authorize!(self, :admin, :effective_orders) }
5
+
6
+ include Effective::CrudController
7
+
8
+ def transactions
9
+ @page_title = 'Revenue: Individual Transactions'
10
+ @datatable = Admin::ReportTransactionsDatatable.new
11
+
12
+ authorize! :index, :report_transactions
13
+
14
+ render 'index'
15
+ end
16
+
17
+ def grouped_transactions
18
+ @page_title = 'Revenue: Grouped Transactions'
19
+ @datatable = Admin::ReportGroupedTransactionsDatatable.new
20
+
21
+ authorize! :index, :report_grouped_transactions
22
+
23
+ render 'index'
24
+ end
25
+
26
+ def payment_providers
27
+ @page_title = 'Revenue: Payment Providers'
28
+ @datatable = Admin::ReportPaymentProvidersDatatable.new
29
+
30
+ authorize! :index, :report_payment_providers
31
+
32
+ render 'index'
33
+ end
34
+
35
+ end
36
+ end
@@ -1,26 +1,28 @@
1
- class Admin::EffectiveCustomersDatatable < Effective::Datatable
2
- datatable do
1
+ module Admin
2
+ class EffectiveCustomersDatatable < Effective::Datatable
3
+ datatable do
3
4
 
4
- col :id, visible: false
5
+ col :id, visible: false
5
6
 
6
- col :user, search: :string
7
+ col :user, search: :string
7
8
 
8
- col :email do |customer|
9
- customer.user.email
10
- end
9
+ col :email do |customer|
10
+ customer.user.email
11
+ end
11
12
 
12
- if EffectiveOrders.stripe?
13
- col :stripe_customer_id
14
- col :active_card
15
- end
13
+ if EffectiveOrders.stripe?
14
+ col :stripe_customer_id
15
+ col :active_card
16
+ end
16
17
 
17
- actions_col do |customer|
18
- link_to('Manage', "https://dashboard.stripe.com/#{'test/' if Rails.env.development?}customers/#{customer.stripe_customer_id}")
19
- end
18
+ actions_col do |customer|
19
+ link_to('Manage', "https://dashboard.stripe.com/#{'test/' if Rails.env.development?}customers/#{customer.stripe_customer_id}")
20
+ end
20
21
 
21
- end
22
+ end
22
23
 
23
- collection do
24
- Effective::Customer.includes(:user).all
24
+ collection do
25
+ Effective::Customer.includes(:user).all
26
+ end
25
27
  end
26
28
  end
@@ -1,119 +1,121 @@
1
- class Admin::EffectiveOrdersDatatable < Effective::Datatable
2
- bulk_actions do
3
- bulk_action(
4
- 'Send payment request email to selected orders',
5
- effective_orders.bulk_send_payment_request_admin_orders_path,
6
- data: { confirm: 'Send payment request emails?' }
7
- )
8
-
9
- bulk_action(
10
- 'Send receipt email to selected purchased orders',
11
- effective_orders.bulk_send_buyer_receipt_orders_path,
12
- data: { confirm: 'Send receipt emails?' }
13
- )
14
- end
1
+ module Admin
2
+ class EffectiveOrdersDatatable < Effective::Datatable
3
+ bulk_actions do
4
+ bulk_action(
5
+ 'Send payment request email to selected orders',
6
+ effective_orders.bulk_send_payment_request_admin_orders_path,
7
+ data: { confirm: 'Send payment request emails?' }
8
+ )
9
+
10
+ bulk_action(
11
+ 'Send receipt email to selected purchased orders',
12
+ effective_orders.bulk_send_buyer_receipt_orders_path,
13
+ data: { confirm: 'Send receipt emails?' }
14
+ )
15
+ end
15
16
 
16
- filters do
17
- unless attributes[:skip_filters]
18
- scope :all
19
- scope :purchased
17
+ filters do
18
+ unless attributes[:skip_filters]
19
+ scope :all
20
+ scope :purchased
20
21
 
21
- scope :deferred if EffectiveOrders.deferred_providers.present?
22
+ scope :deferred if EffectiveOrders.deferred_providers.present?
22
23
 
23
- scope :pending_refunds if EffectiveOrders.refund && !EffectiveOrders.buyer_purchases_refund?
24
- scope :refunds if EffectiveOrders.refund
24
+ scope :pending_refunds if EffectiveOrders.refund && !EffectiveOrders.buyer_purchases_refund?
25
+ scope :refunds if EffectiveOrders.refund
25
26
 
26
- scope :not_purchased
27
+ scope :not_purchased
28
+ end
27
29
  end
28
- end
29
30
 
30
- datatable do
31
- order :updated_at
31
+ datatable do
32
+ order :updated_at
32
33
 
33
- bulk_actions_col
34
+ bulk_actions_col
34
35
 
35
- col :created_at, visible: false
36
- col :updated_at, visible: false
36
+ col :created_at, visible: false
37
+ col :updated_at, visible: false
37
38
 
38
- col :id, label: 'Number' do |order|
39
- '#' + order.to_param
40
- end
39
+ col :id, label: 'Number' do |order|
40
+ '#' + order.to_param
41
+ end
41
42
 
42
- col :purchased_at do |order|
43
- order.purchased_at&.strftime('%F %H:%M') || ('pending refund' if order.pending_refund?) || ("pending #{order.payment_provider}" if order.deferred?) || 'not purchased'
44
- end
43
+ col :purchased_at do |order|
44
+ order.purchased_at&.strftime('%F %H:%M') || ('pending refund' if order.pending_refund?) || ("pending #{order.payment_provider}" if order.deferred?) || 'not purchased'
45
+ end
45
46
 
46
- if attributes[:user_id].blank?
47
- col :user, search: :string
48
- col :billing_name, visible: false
49
- col :email, visible: false
50
- end
47
+ if attributes[:user_id].blank?
48
+ col :user, search: :string
49
+ col :billing_name, visible: false
50
+ col :email, visible: false
51
+ end
51
52
 
52
- col :parent, visible: false, search: :string
53
+ col :parent, visible: false, search: :string
53
54
 
54
- col :cc, visible: false
55
+ col :cc, visible: false
55
56
 
56
- if EffectiveOrders.billing_address
57
- col :billing_address, visible: false
58
- end
57
+ if EffectiveOrders.billing_address
58
+ col :billing_address, visible: false
59
+ end
59
60
 
60
- if EffectiveOrders.shipping_address
61
- col :shipping_address, visible: false
62
- end
61
+ if EffectiveOrders.shipping_address
62
+ col :shipping_address, visible: false
63
+ end
63
64
 
64
- col(:order_items, search: :string).search do |collection, term|
65
- collection.where(id: Effective::OrderItem.where('name ILIKE ?', "%#{term}%").select('order_id'))
66
- end
65
+ col(:order_items, search: :string).search do |collection, term|
66
+ collection.where(id: Effective::OrderItem.where('name ILIKE ?', "%#{term}%").select('order_id'))
67
+ end
67
68
 
68
- col :payment_method
69
- col :payment_provider, label: 'Provider', visible: false, search: { collection: EffectiveOrders.admin_payment_providers }
70
- col :payment_card, label: 'Card', visible: false
69
+ col :payment_method
70
+ col :payment_provider, label: 'Provider', visible: false, search: { collection: EffectiveOrders.admin_payment_providers }
71
+ col :payment_card, label: 'Card', visible: false
71
72
 
72
- col :subtotal, as: :price, visible: false
73
+ col :subtotal, as: :price, visible: false
73
74
 
74
- col :tax, as: :price, visible: false
75
- col(:tax_rate, visible: false) { |order| rate_to_percentage(order.tax_rate) }
75
+ col :tax, as: :price, visible: false
76
+ col(:tax_rate, visible: false) { |order| rate_to_percentage(order.tax_rate) }
76
77
 
77
- col :surcharge, as: :price, visible: false
78
- col(:surcharge_percent, visible: false) { |order| rate_to_percentage(order.surcharge_percent) }
78
+ col :surcharge, as: :price, visible: false
79
+ col(:surcharge_percent, visible: false) { |order| rate_to_percentage(order.surcharge_percent) }
79
80
 
80
- col :total, as: :price
81
+ col :total, as: :price
81
82
 
82
- if EffectiveOrders.collect_note
83
- col :note, visible: false
84
- end
83
+ if EffectiveOrders.collect_note
84
+ col :note, visible: false
85
+ end
85
86
 
86
- col :note_to_buyer, visible: false
87
- col :note_internal, visible: false
87
+ col :note_to_buyer, visible: false
88
+ col :note_internal, visible: false
88
89
 
89
- actions_col partial: 'admin/orders/datatable_actions', partial_as: :order
90
+ actions_col partial: 'admin/orders/datatable_actions', partial_as: :order
91
+
92
+ unless attributes[:total] == false
93
+ aggregate :total
94
+ end
90
95
 
91
- unless attributes[:total] == false
92
- aggregate :total
93
96
  end
94
97
 
95
- end
98
+ collection do
99
+ scope = Effective::Order.all.deep
96
100
 
97
- collection do
98
- scope = Effective::Order.all.deep
101
+ if EffectiveOrders.orders_collection_scope.respond_to?(:call)
102
+ scope = EffectiveOrders.orders_collection_scope.call(scope)
103
+ end
99
104
 
100
- if EffectiveOrders.orders_collection_scope.respond_to?(:call)
101
- scope = EffectiveOrders.orders_collection_scope.call(scope)
102
- end
105
+ if attributes[:user_id].present?
106
+ user_klass = (attributes[:user_type].constantize if attributes[:user_type].present?)
107
+ user_klass ||= current_user.class
103
108
 
104
- if attributes[:user_id].present?
105
- user_klass = (attributes[:user_type].constantize if attributes[:user_type].present?)
106
- user_klass ||= current_user.class
109
+ user = user_klass.find(attributes[:user_id])
110
+ scope = scope.where(user: user)
111
+ end
107
112
 
108
- user = user_klass.find(attributes[:user_id])
109
- scope = scope.where(user: user)
110
- end
113
+ if attributes[:parent_id].present? && attributes[:parent_type].present?
114
+ scope = scope.where(parent_id: attributes[:parent_id], parent_type: attributes[:parent_type])
115
+ end
111
116
 
112
- if attributes[:parent_id].present? && attributes[:parent_type].present?
113
- scope = scope.where(parent_id: attributes[:parent_id], parent_type: attributes[:parent_type])
117
+ scope
114
118
  end
115
119
 
116
- scope
117
120
  end
118
-
119
121
  end
@@ -0,0 +1,78 @@
1
+ # Revenue: Grouped Transactions
2
+
3
+ module Admin
4
+ class ReportGroupedTransactionsDatatable < Effective::Datatable
5
+ filters do
6
+ filter :start_date, nil, as: :date
7
+ filter :end_date, nil, as: :date
8
+ end
9
+
10
+ datatable do
11
+ length 250
12
+
13
+ col :item
14
+ col :subtotal, as: :price
15
+ col :tax, as: :price
16
+ col :total, as: :price
17
+
18
+ payment_providers.each do |provider|
19
+ col(provider, as: :price)
20
+ end
21
+
22
+ col :orders_count
23
+
24
+ col :orders
25
+ col :users
26
+
27
+ col :start_date, as: :date, search: false, sort: false, visible: false do
28
+ date_range.begin&.strftime('%F')
29
+ end
30
+
31
+ col :end_date, as: :date, search: false, sort: false, visible: false do
32
+ date_range.end&.strftime('%F')
33
+ end
34
+
35
+ aggregate :total
36
+ end
37
+
38
+ collection do
39
+ start_date = date_range.begin&.strftime('%F')
40
+ end_date = date_range.end&.strftime('%F')
41
+
42
+ orders = Effective::Order.purchased.where(purchased_at: date_range).where('total != 0')
43
+ order_items = Effective::OrderItem.where(order_id: orders).includes(:purchasable, order: :user)
44
+
45
+ items = order_items.group_by(&:to_s).map do |name, items|
46
+ row = [
47
+ name,
48
+ items.sum { |item| item.subtotal }.to_i,
49
+ items.sum { |item| item.tax }.to_i,
50
+ items.sum { |item| item.total }.to_i,
51
+ ]
52
+
53
+ row += payment_providers.map do |payment_provider|
54
+ items.sum { |item| (item.order.payment_provider == payment_provider) ? item.total : 0 }.to_i
55
+ end
56
+
57
+ row += [
58
+ items.map(&:order_id).uniq.length,
59
+ items.map { |item| item.order },
60
+ items.map { |item| item.order.user },
61
+ start_date,
62
+ end_date
63
+ ]
64
+
65
+ row
66
+ end
67
+ end
68
+
69
+ def payment_providers
70
+ @payment_providers ||= EffectiveOrders.payment_providers - ['free', 'pretend']
71
+ end
72
+
73
+ def date_range
74
+ @date_range ||= (filters[:start_date].presence)..(filters[:end_date].presence)
75
+ end
76
+
77
+ end
78
+ end
@@ -0,0 +1,60 @@
1
+ # Revenue: Payment Providers
2
+
3
+ module Admin
4
+ class ReportPaymentProvidersDatatable < Effective::Datatable
5
+ filters do
6
+ filter :start_date, nil, as: :date
7
+ filter :end_date, nil, as: :date
8
+ end
9
+
10
+ datatable do
11
+ length 250
12
+
13
+ col :payment_provider
14
+
15
+ col :sales, as: :price
16
+ col :returns, as: :price
17
+ col :total, as: :price
18
+
19
+ col :start_date, as: :date, search: false, sort: false, visible: false do
20
+ date_range.begin&.strftime('%F')
21
+ end
22
+
23
+ col :end_date, as: :date, search: false, sort: false, visible: false do
24
+ date_range.end&.strftime('%F')
25
+ end
26
+
27
+ aggregate :total
28
+ end
29
+
30
+ collection do
31
+ start_date = date_range.begin&.strftime('%F')
32
+ end_date = date_range.end&.strftime('%F')
33
+
34
+ orders = Effective::Order.purchased.where(purchased_at: date_range).where('total != 0')
35
+ order_items = Effective::OrderItem.where(order_id: orders).includes(:purchasable, order: :user)
36
+
37
+ payment_providers.map do |provider|
38
+ items = order_items.select { |item| item.order.payment_provider == provider }
39
+
40
+ [
41
+ provider,
42
+ items.sum { |item| (item.total > 0 ? item.total : 0) }.to_i,
43
+ items.sum { |item| (item.total < 0 ? item.total : 0) }.to_i,
44
+ items.sum { |item| item.total }.to_i,
45
+ start_date,
46
+ end_date
47
+ ]
48
+ end
49
+ end
50
+
51
+ def payment_providers
52
+ @payment_providers ||= EffectiveOrders.payment_providers - ['free', 'pretend']
53
+ end
54
+
55
+ def date_range
56
+ @date_range ||= (filters[:start_date].presence)..(filters[:end_date].presence)
57
+ end
58
+
59
+ end
60
+ end
@@ -0,0 +1,63 @@
1
+ # Revenue: Individual Transactions
2
+
3
+ module Admin
4
+ class ReportTransactionsDatatable < Effective::Datatable
5
+
6
+ filters do
7
+ filter :start_date, nil, as: :date
8
+ filter :end_date, nil, as: :date
9
+ end
10
+
11
+ datatable do
12
+ order :id, :desc
13
+ length 250
14
+
15
+ col :created_at, visible: false
16
+
17
+ col :id, label: 'Order' do |order|
18
+ link_to(order.to_param, effective_orders.admin_order_path(order))
19
+ end
20
+
21
+ col :purchased_at
22
+ col :user
23
+ col :order_items
24
+
25
+ col :subtotal, as: :price
26
+ col :tax, as: :price
27
+ col(:tax_rate) { |order| rate_to_percentage(order.tax_rate) }.aggregate { nil }
28
+
29
+ col :amount_owing, as: :price
30
+
31
+ if EffectiveOrders.surcharge?
32
+ col :surcharge, as: :price
33
+ col(:surcharge_percent) { |order| rate_to_percentage(order.surcharge_percent) }.aggregate { nil }
34
+ end
35
+
36
+ col :total, as: :price
37
+
38
+ col :start_date, as: :date, search: false, sort: false, visible: false do
39
+ date_range.begin&.strftime('%F')
40
+ end
41
+
42
+ col :end_date, as: :date, search: false, sort: false, visible: false do
43
+ date_range.end&.strftime('%F')
44
+ end
45
+
46
+ aggregate :total
47
+
48
+ actions_col
49
+ end
50
+
51
+ collection do
52
+ Effective::Order.purchased
53
+ .where(purchased_at: date_range)
54
+ .where('total != 0')
55
+ .includes(:user, [order_items: :purchasable])
56
+ end
57
+
58
+ def date_range
59
+ @date_range ||= (filters[:start_date].presence)..(filters[:end_date].presence)
60
+ end
61
+
62
+ end
63
+ end
@@ -59,6 +59,10 @@ module Effective
59
59
  (subtotal * order.tax_rate / 100.0).round(0).to_i
60
60
  end
61
61
 
62
+ def amount_owing
63
+ total
64
+ end
65
+
62
66
  def total
63
67
  return subtotal if tax_exempt?
64
68
  raise 'parent Effective::Order must have a tax_rate to compute order item total' unless order.try(:tax_rate).present?
@@ -0,0 +1,3 @@
1
+ %h1.effective-admin-heading= @page_title
2
+
3
+ = render_datatable(@datatable)
data/config/routes.rb CHANGED
@@ -63,6 +63,15 @@ EffectiveOrders::Engine.routes.draw do
63
63
  post 'orders/:id', to: 'orders#update'
64
64
 
65
65
  resources :order_items, only: [:index]
66
+
67
+ resources :order_reports, only: [] do
68
+ collection do
69
+ get :transactions
70
+ get :grouped_transactions
71
+ get :payment_providers
72
+ end
73
+ end
74
+
66
75
  end
67
76
  end
68
77
 
@@ -1,3 +1,3 @@
1
1
  module EffectiveOrders
2
- VERSION = '6.0.1'.freeze
2
+ VERSION = '6.1.0'.freeze
3
3
  end
@@ -188,6 +188,10 @@ module EffectiveOrders
188
188
  use_effective_qb_online && defined?(EffectiveQbOnline)
189
189
  end
190
190
 
191
+ def self.surcharge?
192
+ credit_card_surcharge_percent.to_f > 0.0
193
+ end
194
+
191
195
  def self.mailer_class
192
196
  mailer&.constantize || Effective::OrdersMailer
193
197
  end
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: effective_orders
3
3
  version: !ruby/object:Gem::Version
4
- version: 6.0.1
4
+ version: 6.1.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Code and Effect
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2022-12-05 00:00:00.000000000 Z
11
+ date: 2022-12-07 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: rails
@@ -187,6 +187,7 @@ files:
187
187
  - app/assets/stylesheets/effective_orders/_order.scss
188
188
  - app/controllers/admin/customers_controller.rb
189
189
  - app/controllers/admin/order_items_controller.rb
190
+ - app/controllers/admin/order_reports_controller.rb
190
191
  - app/controllers/admin/orders_controller.rb
191
192
  - app/controllers/effective/carts_controller.rb
192
193
  - app/controllers/effective/concerns/purchase.rb
@@ -207,6 +208,9 @@ files:
207
208
  - app/controllers/effective/webhooks_controller.rb
208
209
  - app/datatables/admin/effective_customers_datatable.rb
209
210
  - app/datatables/admin/effective_orders_datatable.rb
211
+ - app/datatables/admin/report_grouped_transactions_datatable.rb
212
+ - app/datatables/admin/report_payment_providers_datatable.rb
213
+ - app/datatables/admin/report_transactions_datatable.rb
210
214
  - app/datatables/effective_orders_datatable.rb
211
215
  - app/helpers/effective_carts_helper.rb
212
216
  - app/helpers/effective_moneris_checkout_helper.rb
@@ -233,6 +237,7 @@ files:
233
237
  - app/views/admin/customers/index.html.haml
234
238
  - app/views/admin/customers/show.html.haml
235
239
  - app/views/admin/order_items/index.html.haml
240
+ - app/views/admin/order_reports/index.html.haml
236
241
  - app/views/admin/orders/_datatable_actions.html.haml
237
242
  - app/views/admin/orders/_form.html.haml
238
243
  - app/views/admin/orders/_form_note_internal.html.haml