Skip to content

Commit a63e07b

Browse files
committed
Fix Fee#presentation_breakdowns_displayed_in_invoice to match the key instead of the value
Also, sum the presentation_breakdowns when exist duplicated keys
1 parent c33265e commit a63e07b

2 files changed

Lines changed: 133 additions & 8 deletions

File tree

app/models/fee.rb

Lines changed: 15 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -179,7 +179,21 @@ def presentation_group_keys_values_displayed_in_invoice
179179
end
180180

181181
def presentation_breakdowns_displayed_in_invoice
182-
presentation_breakdowns.select { |b| presentation_group_keys_values_displayed_in_invoice.any? { |k| b.presentation_by[k].present? } }
182+
keys = presentation_group_keys_values_displayed_in_invoice
183+
184+
return [] if keys.blank?
185+
186+
rows = Hash.new(0)
187+
presentation_breakdowns.each do |breakdown|
188+
presentation_by = breakdown.presentation_by
189+
values = keys.filter_map { |key| [key, presentation_by[key]] if presentation_by.key?(key) }
190+
191+
next if values.empty?
192+
193+
rows[values] += breakdown.units
194+
end
195+
196+
rows.map { |values, units| PresentationBreakdown.new(fee: self, presentation_by: values.to_h, units:) }
183197
end
184198

185199
def basic_rate_percentage?

spec/views/app/views/templates/invoices/v4/_presentation_breakdowns.slim_spec.rb

Lines changed: 118 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -22,20 +22,23 @@
2222
let(:subscription) { create(:subscription, customer:, plan:) }
2323
let(:invoice) { create(:invoice, customer:, organization:) }
2424
let(:billable_metric) { create(:billable_metric, organization:) }
25+
let(:properties) {
26+
{
27+
"amount" => "100",
28+
"presentation_group_keys" => [
29+
{"value" => "region", "options" => {"display_in_invoice" => true}},
30+
{"value" => "department", "options" => {"display_in_invoice" => true}}
31+
]
32+
}
33+
}
2534

2635
let(:charge) do
2736
create(
2837
:standard_charge,
2938
plan:,
3039
billable_metric:,
3140
invoice_display_name: "compute",
32-
properties: {
33-
"amount" => "100",
34-
"presentation_group_keys" => [
35-
{"value" => "region", "options" => {"display_in_invoice" => true}},
36-
{"value" => "department", "options" => {"display_in_invoice" => true}}
37-
]
38-
}
41+
properties:
3942
)
4043
end
4144

@@ -86,6 +89,27 @@
8689
it "renders each breakdown row's units" do
8790
expect(rendered_template).to include("40").and include("35").and include("25").and include("10")
8891
end
92+
93+
context "when a presentation key is not displayed in the invoice" do
94+
let(:properties) do
95+
{
96+
"amount" => "100",
97+
"presentation_group_keys" => [
98+
{"value" => "region", "options" => {"display_in_invoice" => false}},
99+
{"value" => "department", "options" => {"display_in_invoice" => true}}
100+
]
101+
}
102+
end
103+
104+
it "renders breakdown labels joined by ', ' in lexicographic order with nil-value rows last" do
105+
label_order = rendered_template.scan(%r{<td[^>]*>\s*(engineering|sales)?\s*</td>\s*<td[^>]*>\s*(?:75|25|10)\s*</td>}).map(&:first)
106+
expect(label_order).to eq(["engineering", "sales", nil])
107+
end
108+
109+
it "renders each breakdown row's units" do
110+
expect(rendered_template).to include("75").and include("25").and include("10")
111+
end
112+
end
89113
end
90114

91115
# Scenario 2 — `fee.grouped_by` is present.
@@ -137,6 +161,27 @@
137161
eu_bare_idx = rendered_template =~ %r{<td[^>]*>\s*eu\s*</td>}
138162
expect(eu_engineering_idx).to be < eu_bare_idx
139163
end
164+
165+
context "when a presentation key is not displayed in the invoice" do
166+
let(:properties) do
167+
{
168+
"amount" => "100",
169+
"presentation_group_keys" => [
170+
{"value" => "region", "options" => {"display_in_invoice" => false}},
171+
{"value" => "department", "options" => {"display_in_invoice" => true}}
172+
]
173+
}
174+
end
175+
176+
it "renders breakdown labels joined by ', ' in lexicographic order with nil-value rows last" do
177+
label_order = rendered_template.scan(%r{<td[^>]*>\s*(engineering|sales)?\s*</td>\s*<td[^>]*>\s*(?:40|20|5)\s*</td>}).map(&:first)
178+
expect(label_order).to eq(["engineering", "sales", nil])
179+
end
180+
181+
it "renders each breakdown row's units" do
182+
expect(rendered_template).to include("40").and include("20").and include("5")
183+
end
184+
end
140185
end
141186

142187
# Scenario 3 — `fee.charge_filter_id` is present (with `fee.grouped_by` empty).
@@ -188,6 +233,27 @@
188233
it "renders each breakdown row's units" do
189234
expect(rendered_template).to include("30").and include("15").and include("5")
190235
end
236+
237+
context "when a presentation key is not displayed in the invoice" do
238+
let(:properties) do
239+
{
240+
"amount" => "100",
241+
"presentation_group_keys" => [
242+
{"value" => "region", "options" => {"display_in_invoice" => false}},
243+
{"value" => "department", "options" => {"display_in_invoice" => true}}
244+
]
245+
}
246+
end
247+
248+
it "renders breakdown labels joined by ', ' in lexicographic order with nil-value rows last" do
249+
label_order = rendered_template.scan(%r{<td[^>]*>\s*(engineering|sales)?\s*</td>\s*<td[^>]*>\s*(?:30|15|5)\s*</td>}).map(&:first)
250+
expect(label_order).to eq(["engineering", "sales", nil])
251+
end
252+
253+
it "renders each breakdown row's units" do
254+
expect(rendered_template).to include("30").and include("15").and include("5")
255+
end
256+
end
191257
end
192258

193259
# Scenario 5 — breakdowns only contain keys not in displayable_keys.
@@ -219,6 +285,30 @@
219285
it "does not render any breakdown values" do
220286
expect(rendered_template).not_to include("country")
221287
end
288+
289+
context "when a presentation key is not displayed in the invoice" do
290+
let(:properties) do
291+
{
292+
"amount" => "100",
293+
"presentation_group_keys" => [
294+
{"value" => "country", "options" => {"display_in_invoice" => false}}
295+
]
296+
}
297+
end
298+
299+
it "does not render anything" do
300+
expect(rendered_template).to be_blank
301+
end
302+
303+
it "does not render the fee title row" do
304+
expect(rendered_template).not_to match(%r{<td[^>]*>\s*compute\s*</td>})
305+
end
306+
307+
it "does not render any breakdown values" do
308+
expect(rendered_template).not_to include("us")
309+
expect(rendered_template).not_to include("eu")
310+
end
311+
end
222312
end
223313

224314
# Scenario 4 — `fee.charge_filter_id` is present together with a non-empty
@@ -270,5 +360,26 @@
270360
it "renders each breakdown row's units" do
271361
expect(rendered_template).to include("30").and include("15").and include("5")
272362
end
363+
364+
context "when a presentation key is not displayed in the invoice" do
365+
let(:properties) do
366+
{
367+
"amount" => "100",
368+
"presentation_group_keys" => [
369+
{"value" => "region", "options" => {"display_in_invoice" => false}},
370+
{"value" => "department", "options" => {"display_in_invoice" => true}}
371+
]
372+
}
373+
end
374+
375+
it "renders breakdown labels joined by ', ' in lexicographic order with nil-value rows last" do
376+
label_order = rendered_template.scan(%r{<td[^>]*>\s*(engineering|sales)?\s*</td>\s*<td[^>]*>\s*(?:30|15|5)\s*</td>}).map(&:first)
377+
expect(label_order).to eq(["engineering", "sales", nil])
378+
end
379+
380+
it "renders each breakdown row's units" do
381+
expect(rendered_template).to include("30").and include("15").and include("5")
382+
end
383+
end
273384
end
274385
end

0 commit comments

Comments
 (0)