diff --git a/app/models/fee.rb b/app/models/fee.rb index a26591c7b6c..06cf2919686 100644 --- a/app/models/fee.rb +++ b/app/models/fee.rb @@ -153,6 +153,7 @@ def item_description def invoice_name return invoice_display_name if invoice_display_name.present? return charge.invoice_display_name.presence || billable_metric.name if charge? + return invoiceable.invoice_name if product? return add_on.invoice_name if add_on? return invoiceable&.name.presence || fee_type if credit? return fixed_charge.invoice_display_name.presence || fixed_charge_add_on.invoice_name if fixed_charge? @@ -161,7 +162,11 @@ def invoice_name end def filter_display_name(separator: ", ") - charge_filter&.display_name(separator:) + if product? + product_filter&.invoice_name + else + charge_filter&.display_name(separator:) + end end def grouped_by_display @@ -173,7 +178,7 @@ def grouped_by_display def invoice_sorting_clause base_clause = "#{invoice_name} #{filter_display_name}".downcase - return base_clause unless charge? + return base_clause unless charge? || product? return base_clause if grouped_by.blank? "#{invoice_name} #{grouped_by.values.join} #{filter_display_name}".downcase @@ -184,11 +189,15 @@ def currency end def grouped_or_filtered? - grouped_by.present? || charge_filter_id.present? + grouped_by.present? || filtered? end def ungrouped_or_filtered? - grouped_by.blank? || charge_filter_id.present? + grouped_by.blank? || filtered? + end + + def filtered? + charge_filter_id.present? || product_filter_id.present? end def presentation_group_keys_values_displayed_in_invoice diff --git a/app/views/helpers/fee_display_helper.rb b/app/views/helpers/fee_display_helper.rb index 2a0e2a013c0..99a75599ece 100644 --- a/app/views/helpers/fee_display_helper.rb +++ b/app/views/helpers/fee_display_helper.rb @@ -6,7 +6,13 @@ def self.grouped_by_display(fee) end def self.fee_title(fee) - fee.invoice_name + grouped_by_display(fee) + (fee.charge_filter_id? ? " • #{fee.filter_display_name(separator: " • ")}" : "") + filter_display = if fee.filtered? + " • #{fee.filter_display_name(separator: " • ")}" + else + "" + end + + fee.invoice_name + grouped_by_display(fee) + filter_display end def self.should_display_subscription_fee?(invoice_subscription) diff --git a/spec/models/fee_spec.rb b/spec/models/fee_spec.rb index 5c3389401b6..d7cf48d01c4 100644 --- a/spec/models/fee_spec.rb +++ b/spec/models/fee_spec.rb @@ -600,6 +600,48 @@ end end + describe "#filter_display_name" do + let(:charge) { create(:standard_charge) } + let(:charge_filter) { create(:charge_filter, charge:, invoice_display_name: "EU Premium") } + let(:product) { create(:product) } + let(:product_filter) { create(:product_filter, product:, invoice_display_name: "EU Premium") } + + context "when the fee is charge-backed" do + let(:fee) { build(:charge_fee, charge:, charge_filter:) } + + it "uses the charge filter display name" do + expect(fee.filter_display_name).to eq("EU Premium") + end + end + + context "when the fee is product-backed" do + let(:fee) { build(:fee, fee_type: :product, product_filter:) } + + it "uses the product filter invoice name" do + expect(fee.filter_display_name).to eq("EU Premium") + end + + context "when sorting the invoice fees" do + let(:product) { create(:product, name: "Compute") } + let(:fee) do + build( + :fee, + fee_type: :product, + product_filter:, + invoiceable: product, + subscription: nil, + invoice_display_name: nil, + grouped_by: {} + ) + end + + it "includes the product filter" do + expect(fee.invoice_sorting_clause).to eq("compute eu premium") + end + end + end + end + describe "#grouped_by_display" do let(:charge) { create(:standard_charge, properties:) } let(:fee) { described_class.new(charge:, fee_type: "charge", grouped_by:) } @@ -977,6 +1019,11 @@ fee = build(:charge_fee, grouped_by: {}, charge_filter_id: SecureRandom.uuid) expect(fee).to be_grouped_or_filtered end + + it "returns true when product_filter_id is present" do + fee = build(:fee, fee_type: :product, grouped_by: {}, product_filter_id: SecureRandom.uuid) + expect(fee).to be_grouped_or_filtered + end end describe "#ungrouped_or_filtered?" do @@ -994,6 +1041,35 @@ fee = build(:charge_fee, grouped_by: {"cloud" => "aws"}, charge_filter_id: SecureRandom.uuid) expect(fee).to be_ungrouped_or_filtered end + + it "returns true when product_filter_id is present" do + fee = build(:fee, fee_type: :product, grouped_by: {"cloud" => "aws"}, product_filter_id: SecureRandom.uuid) + expect(fee).to be_ungrouped_or_filtered + end + end + + describe "#filtered?" do + let(:fee) { build(:fee) } + + it "returns false when neither filter is present" do + expect(fee).not_to be_filtered + end + + context "when the charge filter is present" do + let(:fee) { build(:charge_fee, charge_filter_id: SecureRandom.uuid) } + + it "returns true" do + expect(fee).to be_filtered + end + end + + context "when the product filter is present" do + let(:fee) { build(:fee, fee_type: :product, product_filter_id: SecureRandom.uuid) } + + it "returns true" do + expect(fee).to be_filtered + end + end end describe "#basic_rate_percentage?" do diff --git a/spec/views/helpers/fee_display_helper_spec.rb b/spec/views/helpers/fee_display_helper_spec.rb index de4016de313..17e127f1911 100644 --- a/spec/views/helpers/fee_display_helper_spec.rb +++ b/spec/views/helpers/fee_display_helper_spec.rb @@ -43,6 +43,27 @@ expect(subject).to eq("Compute • eu • EU Premium") end end + + context "when product filter is present" do + let(:product) { create(:product, organization: charge.organization, name: "Compute") } + let(:product_filter) { create(:product_filter, product:, invoice_display_name: "EU Premium") } + let(:fee) do + build( + :fee, + charge: nil, + fee_type: "product", + invoiceable: product, + subscription: nil, + product_filter:, + grouped_by: {}, + invoice_display_name: nil + ) + end + + it "returns invoice_name appended with the product filter display name" do + expect(subject).to eq("Compute • EU Premium") + end + end end describe ".should_display_subscription_fee?" do