spree_cm_commissioner 2.0.0.pre.pre1 → 2.0.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +4 -4
- data/Gemfile.lock +1 -1
- data/app/factory/spree_cm_commissioner/invite_guest_claimed_telegram_message_factory.rb +1 -2
- data/app/models/concerns/spree_cm_commissioner/line_item_durationable.rb +0 -18
- data/app/models/concerns/spree_cm_commissioner/variant_options_concern.rb +2 -4
- data/app/models/spree_cm_commissioner/user_decorator.rb +0 -6
- data/config/routes.rb +0 -1
- data/lib/spree_cm_commissioner/version.rb +1 -1
- metadata +4 -10
- data/app/controllers/spree/api/v2/operator/pie_chart_events_controller.rb +0 -46
- data/app/interactors/spree_cm_commissioner/create_vendor.rb +0 -44
- data/app/models/spree_cm_commissioner/chart_type.rb +0 -10
- data/app/queries/spree_cm_commissioner/pie_chart_event_queries.rb +0 -179
- data/app/serializables/spree_cm_commissioner/pie_chart_event.rb +0 -11
- data/app/serializers/spree_cm_commissioner/v2/operator/chart_type_serializer.rb +0 -10
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: f153e6dedc0923e77cd5fb9e53f99fb8b5f18f1289acc2961df248054621bbc8
|
4
|
+
data.tar.gz: efc85b32c83368f26e02db04b67c14e71c430baafcedcf997ee5961a6217d7d4
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 9f13f470efb8892b55fac8bdbb0e6f180dd08ebc12a3d6639ded76855526849890cc02f17d7bcdc592e4528eaad619da94f82b403084a1e697afd7e2fd0100b2
|
7
|
+
data.tar.gz: a6646ac4739b414ffab2890f2230f0e07c6401d78ed77482e394303234a6d67e102132ca0ad589a879c6370eac0d1efc947f0fba4a115ebc10622950c09ecbfe
|
data/Gemfile.lock
CHANGED
@@ -38,10 +38,9 @@ module SpreeCmCommissioner
|
|
38
38
|
text << "Tel: #{inline_code(guest.phone_number)}"
|
39
39
|
text << ''
|
40
40
|
|
41
|
-
# Each invitation_link leads to one order with one line_item, claimed by one guest so quantity is always 1.
|
42
41
|
selected_line_items.each do |item|
|
43
42
|
text << bold(item.product.name.to_s)
|
44
|
-
text <<
|
43
|
+
text << "🎟️ Quantity: #{item.quantity}"
|
45
44
|
text << italic("👉 #{item.options_text}") if item.options_text.present?
|
46
45
|
text << italic(pretty_date_for(item)) if item.date_present?
|
47
46
|
text << ''
|
@@ -55,24 +55,6 @@ module SpreeCmCommissioner
|
|
55
55
|
def set_duration
|
56
56
|
self.from_date ||= variant.start_date_time || event&.from_date
|
57
57
|
self.to_date ||= variant.end_date_time || event&.to_date
|
58
|
-
|
59
|
-
return if persisted?
|
60
|
-
|
61
|
-
apply_variant_time(:from_date, variant.start_date_time)
|
62
|
-
apply_variant_time(:to_date, variant.end_date_time)
|
63
|
-
end
|
64
|
-
|
65
|
-
def apply_variant_time(field, variant_time)
|
66
|
-
field_value = send(field)
|
67
|
-
|
68
|
-
return unless field_value.present? && field_value.hour.zero? && variant_time.present?
|
69
|
-
|
70
|
-
send("#{field}=", field_value.change(
|
71
|
-
hour: variant_time.hour,
|
72
|
-
min: variant_time.min,
|
73
|
-
sec: variant_time.sec
|
74
|
-
)
|
75
|
-
)
|
76
58
|
end
|
77
59
|
end
|
78
60
|
end
|
@@ -53,9 +53,8 @@ module SpreeCmCommissioner
|
|
53
53
|
# No need to fallback to event start date to avoid n+1.
|
54
54
|
# To get end_time duration of event, include event when needed instead.
|
55
55
|
def start_date_time
|
56
|
-
return nil if start_date.blank?
|
56
|
+
return nil if start_date.blank?
|
57
57
|
return start_date if start_time.blank?
|
58
|
-
return start_time if start_date.blank?
|
59
58
|
|
60
59
|
start_date.change(hour: start_time.hour, min: start_time.min, sec: start_time.sec)
|
61
60
|
end
|
@@ -63,9 +62,8 @@ module SpreeCmCommissioner
|
|
63
62
|
# No need to fallback to event end date to avoid n+1.
|
64
63
|
# To get end_time duration of event, include event when needed instead.
|
65
64
|
def end_date_time
|
66
|
-
return nil if end_date.blank?
|
65
|
+
return nil if end_date.blank?
|
67
66
|
return end_date if end_time.blank?
|
68
|
-
return end_time if end_date.blank?
|
69
67
|
|
70
68
|
end_date.change(hour: end_time.hour, min: end_time.min, sec: end_time.sec)
|
71
69
|
end
|
@@ -88,12 +88,6 @@ module SpreeCmCommissioner
|
|
88
88
|
has_spree_role?('operator')
|
89
89
|
end
|
90
90
|
|
91
|
-
def vendor_organizer?(vendor)
|
92
|
-
spree_roles.any? do |role|
|
93
|
-
role.name == "#{vendor.name.downcase.parameterize(separator: '-')}-organizer"
|
94
|
-
end
|
95
|
-
end
|
96
|
-
|
97
91
|
def full_name
|
98
92
|
[first_name, last_name].compact_blank.join(' ')
|
99
93
|
end
|
data/config/routes.rb
CHANGED
@@ -644,7 +644,6 @@ Spree::Core::Engine.add_routes do
|
|
644
644
|
resources :taxons, only: %i[show] do
|
645
645
|
resource :event_ticket_aggregators, only: %i[show]
|
646
646
|
resource :pie_chart_event_aggregators, only: %i[show]
|
647
|
-
resources :pie_chart_events, only: %i[index show]
|
648
647
|
end
|
649
648
|
end
|
650
649
|
end
|
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: spree_cm_commissioner
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 2.0.0
|
4
|
+
version: 2.0.0
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- You
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date: 2025-07-
|
11
|
+
date: 2025-07-28 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: spree
|
@@ -819,7 +819,6 @@ files:
|
|
819
819
|
- app/controllers/spree/api/v2/operator/guests_controller.rb
|
820
820
|
- app/controllers/spree/api/v2/operator/line_items_controller.rb
|
821
821
|
- app/controllers/spree/api/v2/operator/pie_chart_event_aggregators_controller.rb
|
822
|
-
- app/controllers/spree/api/v2/operator/pie_chart_events_controller.rb
|
823
822
|
- app/controllers/spree/api/v2/operator/recalculate_tickets_controller.rb
|
824
823
|
- app/controllers/spree/api/v2/operator/taxons_controller.rb
|
825
824
|
- app/controllers/spree/api/v2/organizer/base_controller.rb
|
@@ -1056,7 +1055,6 @@ files:
|
|
1056
1055
|
- app/interactors/spree_cm_commissioner/conversion_pre_calculator.rb
|
1057
1056
|
- app/interactors/spree_cm_commissioner/create_event.rb
|
1058
1057
|
- app/interactors/spree_cm_commissioner/create_ticket.rb
|
1059
|
-
- app/interactors/spree_cm_commissioner/create_vendor.rb
|
1060
1058
|
- app/interactors/spree_cm_commissioner/crew_invite_link_handler.rb
|
1061
1059
|
- app/interactors/spree_cm_commissioner/crew_inviter.rb
|
1062
1060
|
- app/interactors/spree_cm_commissioner/customer_content_notification_creator.rb
|
@@ -1235,7 +1233,6 @@ files:
|
|
1235
1233
|
- app/models/spree_cm_commissioner/base.rb
|
1236
1234
|
- app/models/spree_cm_commissioner/blazer_queryable.rb
|
1237
1235
|
- app/models/spree_cm_commissioner/branch.rb
|
1238
|
-
- app/models/spree_cm_commissioner/chart_type.rb
|
1239
1236
|
- app/models/spree_cm_commissioner/check_in.rb
|
1240
1237
|
- app/models/spree_cm_commissioner/check_in_ability.rb
|
1241
1238
|
- app/models/spree_cm_commissioner/check_in_record.rb
|
@@ -1557,7 +1554,6 @@ files:
|
|
1557
1554
|
- app/queries/spree_cm_commissioner/line_item_searcher_query.rb
|
1558
1555
|
- app/queries/spree_cm_commissioner/organizer_profile_event_query.rb
|
1559
1556
|
- app/queries/spree_cm_commissioner/pie_chart_event_aggregator_queries.rb
|
1560
|
-
- app/queries/spree_cm_commissioner/pie_chart_event_queries.rb
|
1561
1557
|
- app/queries/spree_cm_commissioner/reservation_query.rb
|
1562
1558
|
- app/queries/spree_cm_commissioner/subscription_orders_query.rb
|
1563
1559
|
- app/queries/spree_cm_commissioner/subscription_revenue_overview_query.rb
|
@@ -1575,7 +1571,6 @@ files:
|
|
1575
1571
|
- app/request_schemas/spree_cm_commissioner/user_account_linkage_request_schema.rb
|
1576
1572
|
- app/request_schemas/spree_cm_commissioner/user_profile_request_schema.rb
|
1577
1573
|
- app/serializables/spree_cm_commissioner/event_ticket_aggregator.rb
|
1578
|
-
- app/serializables/spree_cm_commissioner/pie_chart_event.rb
|
1579
1574
|
- app/serializables/spree_cm_commissioner/pie_chart_event_aggregator.rb
|
1580
1575
|
- app/serializables/spree_cm_commissioner/queue_item.rb
|
1581
1576
|
- app/serializers/.gitkeep
|
@@ -1665,7 +1660,6 @@ files:
|
|
1665
1660
|
- app/serializers/spree_cm_commissioner/json_ld/vendor_image_serializer.rb
|
1666
1661
|
- app/serializers/spree_cm_commissioner/json_ld/vendor_serializer.rb
|
1667
1662
|
- app/serializers/spree_cm_commissioner/v2/operator/base_serializer.rb
|
1668
|
-
- app/serializers/spree_cm_commissioner/v2/operator/chart_type_serializer.rb
|
1669
1663
|
- app/serializers/spree_cm_commissioner/v2/operator/check_in_serializer.rb
|
1670
1664
|
- app/serializers/spree_cm_commissioner/v2/operator/classification_serializer.rb
|
1671
1665
|
- app/serializers/spree_cm_commissioner/v2/operator/dashboard_crew_event_serializer.rb
|
@@ -2705,9 +2699,9 @@ required_ruby_version: !ruby/object:Gem::Requirement
|
|
2705
2699
|
version: '2.7'
|
2706
2700
|
required_rubygems_version: !ruby/object:Gem::Requirement
|
2707
2701
|
requirements:
|
2708
|
-
- - "
|
2702
|
+
- - ">="
|
2709
2703
|
- !ruby/object:Gem::Version
|
2710
|
-
version:
|
2704
|
+
version: '0'
|
2711
2705
|
requirements:
|
2712
2706
|
- none
|
2713
2707
|
rubygems_version: 3.4.1
|
@@ -1,46 +0,0 @@
|
|
1
|
-
module Spree
|
2
|
-
module Api
|
3
|
-
module V2
|
4
|
-
module Operator
|
5
|
-
class PieChartEventsController < ::Spree::Api::V2::ResourceController
|
6
|
-
ACCEPTED_KYC_FIELDS = %i[guest_gender guest_occupation guest_nationality].freeze
|
7
|
-
ADDITIONAL_FIELDS = %i[participation entry_type].freeze
|
8
|
-
|
9
|
-
def index
|
10
|
-
kyc_fields = fetch_filtered_kyc_fields
|
11
|
-
types = ADDITIONAL_FIELDS + kyc_fields
|
12
|
-
|
13
|
-
resources = types.map { |type| SpreeCmCommissioner::ChartType.new(type) }
|
14
|
-
|
15
|
-
render json: SpreeCmCommissioner::V2::Operator::ChartTypeSerializer.new(resources).serializable_hash
|
16
|
-
end
|
17
|
-
|
18
|
-
def resource
|
19
|
-
@resource = pie_chart_event_aggregator_queries.call
|
20
|
-
end
|
21
|
-
|
22
|
-
def resource_serializer
|
23
|
-
SpreeCmCommissioner::V2::Operator::PieChartEventAggregatorSerializer
|
24
|
-
end
|
25
|
-
|
26
|
-
private
|
27
|
-
|
28
|
-
def pie_chart_event_aggregator_queries
|
29
|
-
SpreeCmCommissioner::PieChartEventQueries.new(
|
30
|
-
taxon_id: params[:taxon_id],
|
31
|
-
chart_type: params[:id] || 'participation',
|
32
|
-
refreshed: params[:refreshed] || false
|
33
|
-
)
|
34
|
-
end
|
35
|
-
|
36
|
-
def fetch_filtered_kyc_fields
|
37
|
-
Spree::Product
|
38
|
-
.where(event_id: params[:taxon_id])
|
39
|
-
.flat_map(&:kyc_fields)
|
40
|
-
.uniq & ACCEPTED_KYC_FIELDS
|
41
|
-
end
|
42
|
-
end
|
43
|
-
end
|
44
|
-
end
|
45
|
-
end
|
46
|
-
end
|
@@ -1,44 +0,0 @@
|
|
1
|
-
module SpreeCmCommissioner
|
2
|
-
class CreateVendor
|
3
|
-
include Interactor
|
4
|
-
|
5
|
-
def call
|
6
|
-
validate_context!
|
7
|
-
|
8
|
-
ActiveRecord::Base.transaction do
|
9
|
-
create_vendor
|
10
|
-
assign_vendor_to_user
|
11
|
-
create_role
|
12
|
-
end
|
13
|
-
end
|
14
|
-
|
15
|
-
private
|
16
|
-
|
17
|
-
def validate_context!
|
18
|
-
context.fail!(message: 'User is missing') unless context.user
|
19
|
-
context.fail!(message: 'Vendor parameters are missing') unless context.vendor_params
|
20
|
-
end
|
21
|
-
|
22
|
-
def create_vendor
|
23
|
-
@vendor = Spree::Vendor.new(context.vendor_params)
|
24
|
-
return if @vendor.save
|
25
|
-
|
26
|
-
context.fail!(message: @vendor.errors.full_messages.join(', '))
|
27
|
-
end
|
28
|
-
|
29
|
-
def assign_vendor_to_user
|
30
|
-
context.user.vendors << @vendor
|
31
|
-
end
|
32
|
-
|
33
|
-
def create_role
|
34
|
-
role = context.user.spree_roles.create(
|
35
|
-
name: "#{@vendor.name.downcase.parameterize(separator: '-')}-organizer",
|
36
|
-
vendor_id: @vendor.id,
|
37
|
-
presentation: 'Organizer'
|
38
|
-
)
|
39
|
-
return if role.persisted?
|
40
|
-
|
41
|
-
context.fail!(message: role.errors.full_messages.to_sentence)
|
42
|
-
end
|
43
|
-
end
|
44
|
-
end
|
@@ -1,179 +0,0 @@
|
|
1
|
-
module SpreeCmCommissioner
|
2
|
-
class PieChartEventQueries
|
3
|
-
attr_reader :taxon_id, :chart_type, :refreshed
|
4
|
-
|
5
|
-
# chart_type: 'participation | gender | entry_type' taxon_id: taxon_id, refreshed: false
|
6
|
-
def initialize(taxon_id:, chart_type:, refreshed: false)
|
7
|
-
@taxon_id = taxon_id
|
8
|
-
@chart_type = chart_type || 'participation'
|
9
|
-
@refreshed = refreshed
|
10
|
-
end
|
11
|
-
|
12
|
-
def call
|
13
|
-
cache_key = "#{chart_type}-#{taxon_id}"
|
14
|
-
Rails.cache.delete(cache_key) if refreshed
|
15
|
-
|
16
|
-
product_charts = Rails.cache.fetch(cache_key, expires_in: 30.minutes) do
|
17
|
-
pie_chart || []
|
18
|
-
end
|
19
|
-
|
20
|
-
SpreeCmCommissioner::PieChartEvent.new(
|
21
|
-
id: taxon_id,
|
22
|
-
chart_type: chart_type,
|
23
|
-
product_charts: product_charts
|
24
|
-
)
|
25
|
-
end
|
26
|
-
|
27
|
-
def pie_chart
|
28
|
-
case chart_type
|
29
|
-
when 'participation' then participation_pie_chart
|
30
|
-
when 'entry_type' then entry_type_pie_chart
|
31
|
-
when 'guest_gender' then gender_pie_chart
|
32
|
-
when 'guest_occupation' then occupation_pie_chart
|
33
|
-
when 'guest_nationality' then nationality_pie_chart
|
34
|
-
end
|
35
|
-
end
|
36
|
-
|
37
|
-
private
|
38
|
-
|
39
|
-
def base_joins
|
40
|
-
query = SpreeCmCommissioner::Guest
|
41
|
-
join_type = chart_type.in?(%w[participation occupation nationality]) ? 'LEFT' : 'INNER'
|
42
|
-
|
43
|
-
query
|
44
|
-
.joins("#{join_type} JOIN cm_check_ins ON cm_check_ins.guest_id = cm_guests.id")
|
45
|
-
.joins('INNER JOIN spree_line_items ON spree_line_items.id = cm_guests.line_item_id')
|
46
|
-
.joins('INNER JOIN spree_variants ON spree_variants.id = spree_line_items.variant_id')
|
47
|
-
.joins('INNER JOIN spree_orders ON spree_orders.id = spree_line_items.order_id')
|
48
|
-
.joins('INNER JOIN spree_products ON spree_products.id = spree_variants.product_id')
|
49
|
-
.joins('INNER JOIN spree_products_taxons ON spree_products.id = spree_products_taxons.product_id')
|
50
|
-
.joins('INNER JOIN spree_taxons ON spree_taxons.id = spree_products_taxons.taxon_id')
|
51
|
-
.where(spree_orders: { state: 'complete' }, spree_taxons: { parent_id: taxon_id })
|
52
|
-
end
|
53
|
-
|
54
|
-
def participation_pie_chart
|
55
|
-
grouped_data = base_joins
|
56
|
-
.select("spree_products.id AS product_id,
|
57
|
-
spree_products.name AS product_name,
|
58
|
-
CASE
|
59
|
-
WHEN cm_check_ins.id IS NOT NULL THEN 'show'
|
60
|
-
ELSE 'no_show'
|
61
|
-
END AS name,
|
62
|
-
COUNT(*) AS total"
|
63
|
-
)
|
64
|
-
.group('spree_products.id, CASE WHEN cm_check_ins.id IS NOT NULL THEN \'show\' ELSE \'no_show\' END')
|
65
|
-
.group_by(&:product_id)
|
66
|
-
|
67
|
-
product_charts = build_product_charts(grouped_data)
|
68
|
-
|
69
|
-
add_overall_summary(product_charts)
|
70
|
-
end
|
71
|
-
|
72
|
-
def gender_pie_chart
|
73
|
-
data = base_joins.select(
|
74
|
-
"spree_products.id AS product_id,
|
75
|
-
spree_products.name AS product_name,
|
76
|
-
CASE
|
77
|
-
WHEN cm_guests.gender = 0 THEN 'other'
|
78
|
-
WHEN cm_guests.gender = 1 THEN 'male'
|
79
|
-
WHEN cm_guests.gender = 2 THEN 'female'
|
80
|
-
END AS name,
|
81
|
-
COUNT(DISTINCT cm_guests.id) AS total"
|
82
|
-
)
|
83
|
-
.group('spree_products.id, cm_guests.gender')
|
84
|
-
.group_by(&:product_id)
|
85
|
-
|
86
|
-
product_charts = build_product_charts(data)
|
87
|
-
|
88
|
-
add_overall_summary(product_charts)
|
89
|
-
end
|
90
|
-
|
91
|
-
def entry_type_pie_chart
|
92
|
-
data = base_joins
|
93
|
-
.where.not(cm_check_ins: { id: nil })
|
94
|
-
.select(
|
95
|
-
"spree_products.id AS product_id,
|
96
|
-
spree_products.name AS product_name,
|
97
|
-
CASE
|
98
|
-
WHEN cm_check_ins.entry_type = 0 THEN 'normal'
|
99
|
-
WHEN cm_check_ins.entry_type = 1 THEN 'VIP'
|
100
|
-
END AS name,
|
101
|
-
COUNT(cm_check_ins.id) AS total"
|
102
|
-
)
|
103
|
-
.group('spree_products.id, cm_check_ins.entry_type')
|
104
|
-
.group_by(&:product_id)
|
105
|
-
|
106
|
-
product_charts = build_product_charts(data)
|
107
|
-
|
108
|
-
add_overall_summary(product_charts)
|
109
|
-
end
|
110
|
-
|
111
|
-
def occupation_pie_chart
|
112
|
-
data = base_joins
|
113
|
-
.joins('LEFT JOIN spree_taxons AS occupation_taxons ON occupation_taxons.id = cm_guests.occupation_id')
|
114
|
-
.where.not(cm_guests: { occupation_id: nil })
|
115
|
-
.select(
|
116
|
-
'spree_products.id AS product_id,
|
117
|
-
spree_products.name AS product_name,
|
118
|
-
occupation_taxons.name AS name,
|
119
|
-
COUNT(DISTINCT cm_guests.id) AS total,
|
120
|
-
COUNT(DISTINCT cm_check_ins.id) AS show'
|
121
|
-
)
|
122
|
-
.group('spree_products.id, spree_products.name, occupation_taxons.name')
|
123
|
-
.group_by(&:product_id)
|
124
|
-
|
125
|
-
product_charts = build_product_charts(data, keys: %i[name total show])
|
126
|
-
|
127
|
-
add_overall_summary(product_charts, keys: %i[total show])
|
128
|
-
end
|
129
|
-
|
130
|
-
def nationality_pie_chart
|
131
|
-
data = base_joins
|
132
|
-
.joins('LEFT JOIN spree_taxons AS nationality_taxons ON nationality_taxons.id = cm_guests.nationality_id')
|
133
|
-
.where.not(cm_guests: { nationality_id: nil })
|
134
|
-
.select(
|
135
|
-
'spree_products.id AS product_id,
|
136
|
-
spree_products.name AS product_name,
|
137
|
-
nationality_taxons.name AS name,
|
138
|
-
COUNT(DISTINCT cm_guests.id) AS total,
|
139
|
-
COUNT(DISTINCT cm_check_ins.id) AS show'
|
140
|
-
)
|
141
|
-
.group('spree_products.id, spree_products.name, nationality_taxons.name')
|
142
|
-
.group_by(&:product_id)
|
143
|
-
|
144
|
-
product_charts = build_product_charts(data, keys: %i[name total show])
|
145
|
-
|
146
|
-
add_overall_summary(product_charts, keys: %i[total show])
|
147
|
-
end
|
148
|
-
|
149
|
-
def build_product_charts(grouped_data, keys: %i[name total])
|
150
|
-
grouped_data.map do |product_id, records|
|
151
|
-
{
|
152
|
-
product_id: product_id,
|
153
|
-
product_name: records.first.product_name,
|
154
|
-
pies: records.map { |r| r.slice(*keys) }
|
155
|
-
}
|
156
|
-
end
|
157
|
-
end
|
158
|
-
|
159
|
-
def add_overall_summary(product_charts, keys: %i[total])
|
160
|
-
totals = Hash.new { |hash, key| hash[key] = keys.index_with { |_k| 0 } }
|
161
|
-
|
162
|
-
product_charts.each do |chart|
|
163
|
-
chart[:pies].each do |pie|
|
164
|
-
keys.each { |k| totals[pie[:name]][k] += pie[k] }
|
165
|
-
end
|
166
|
-
end
|
167
|
-
|
168
|
-
overall = {
|
169
|
-
product_id: 'all',
|
170
|
-
product_name: 'Overall',
|
171
|
-
pies: totals.map do |name, values|
|
172
|
-
{ name: name }.merge(values)
|
173
|
-
end
|
174
|
-
}
|
175
|
-
|
176
|
-
[overall] + product_charts
|
177
|
-
end
|
178
|
-
end
|
179
|
-
end
|