From 7ba09c1952377934efe10dd5df51992e7b679e20 Mon Sep 17 00:00:00 2001 From: Vincent Pochet Date: Fri, 23 Aug 2024 11:52:26 +0200 Subject: [PATCH 1/4] feat(ProgressiveBilling): Add AppliedUsageThreshold --- app/models/applied_usage_threshold.rb | 31 +++++++++++++++++++ app/models/invoice.rb | 3 ++ app/models/usage_threshold.rb | 3 ++ ...3092643_create_applied_usage_thresholds.rb | 14 +++++++++ db/schema.rb | 15 ++++++++- spec/factories/applied_usage_thresholds.rb | 8 +++++ spec/models/applied_usage_threshold_spec.rb | 12 +++++++ spec/models/invoice_spec.rb | 3 ++ spec/models/usage_threshold_spec.rb | 3 ++ 9 files changed, 91 insertions(+), 1 deletion(-) create mode 100644 app/models/applied_usage_threshold.rb create mode 100644 db/migrate/20240823092643_create_applied_usage_thresholds.rb create mode 100644 spec/factories/applied_usage_thresholds.rb create mode 100644 spec/models/applied_usage_threshold_spec.rb diff --git a/app/models/applied_usage_threshold.rb b/app/models/applied_usage_threshold.rb new file mode 100644 index 00000000000..bbb17f87d77 --- /dev/null +++ b/app/models/applied_usage_threshold.rb @@ -0,0 +1,31 @@ +# frozen_string_literal: true + +class AppliedUsageThreshold < ApplicationRecord + belongs_to :usage_threshold + belongs_to :invoice + + validates :usage_threshold_id, uniqueness: {scope: :invoice_id} +end + +# == Schema Information +# +# Table name: applied_usage_thresholds +# +# id :uuid not null, primary key +# lifetime_usage_amount_cents :bigint default(0), not null +# created_at :datetime not null +# updated_at :datetime not null +# invoice_id :uuid not null +# usage_threshold_id :uuid not null +# +# Indexes +# +# idx_on_usage_threshold_id_invoice_id_cb82cdf163 (usage_threshold_id,invoice_id) UNIQUE +# index_applied_usage_thresholds_on_invoice_id (invoice_id) +# index_applied_usage_thresholds_on_usage_threshold_id (usage_threshold_id) +# +# Foreign Keys +# +# fk_rails_... (invoice_id => invoices.id) +# fk_rails_... (usage_threshold_id => usage_thresholds.id) +# diff --git a/app/models/invoice.rb b/app/models/invoice.rb index 2644aa6c8cd..a628a76803c 100644 --- a/app/models/invoice.rb +++ b/app/models/invoice.rb @@ -34,6 +34,9 @@ class Invoice < ApplicationRecord has_many :payment_requests, through: :applied_payment_requests has_many :payments, as: :payable + has_many :applied_usage_thresholds + has_many :usage_thresholds, through: :applied_usage_thresholds + has_one_attached :file monetize :coupons_amount_cents, diff --git a/app/models/usage_threshold.rb b/app/models/usage_threshold.rb index 0db739b7e01..165fad404cf 100644 --- a/app/models/usage_threshold.rb +++ b/app/models/usage_threshold.rb @@ -8,6 +8,9 @@ class UsageThreshold < ApplicationRecord belongs_to :plan + has_many :applied_usage_thresholds + has_many :invoices, through: :applied_usage_thresholds + monetize :amount_cents, with_currency: ->(threshold) { threshold.plan.amount_currency } validates :amount_cents, numericality: {greater_than: 0} diff --git a/db/migrate/20240823092643_create_applied_usage_thresholds.rb b/db/migrate/20240823092643_create_applied_usage_thresholds.rb new file mode 100644 index 00000000000..e3f45667fb2 --- /dev/null +++ b/db/migrate/20240823092643_create_applied_usage_thresholds.rb @@ -0,0 +1,14 @@ +# frozen_string_literal: true + +class CreateAppliedUsageThresholds < ActiveRecord::Migration[7.1] + def change + create_table :applied_usage_thresholds, id: :uuid do |t| + t.references :usage_threshold, null: false, foreign_key: true, type: :uuid + t.references :invoice, null: false, foreign_key: true, type: :uuid + + t.timestamps + + t.index %i[usage_threshold_id invoice_id], unique: true + end + end +end diff --git a/db/schema.rb b/db/schema.rb index 949755929da..33b5180436d 100644 --- a/db/schema.rb +++ b/db/schema.rb @@ -10,7 +10,7 @@ # # It's strongly recommended that you check this file into your version control system. -ActiveRecord::Schema[7.1].define(version: 2024_08_22_142524) do +ActiveRecord::Schema[7.1].define(version: 2024_08_23_092643) do # These are extensions that must be enabled in order to support this database enable_extension "pgcrypto" enable_extension "plpgsql" @@ -129,6 +129,17 @@ t.index ["customer_id"], name: "index_applied_coupons_on_customer_id" end + create_table "applied_usage_thresholds", id: :uuid, default: -> { "gen_random_uuid()" }, force: :cascade do |t| + t.uuid "usage_threshold_id", null: false + t.uuid "invoice_id", null: false + t.bigint "lifetime_usage_amount_cents", default: 0, null: false + t.datetime "created_at", null: false + t.datetime "updated_at", null: false + t.index ["invoice_id"], name: "index_applied_usage_thresholds_on_invoice_id" + t.index ["usage_threshold_id", "invoice_id"], name: "idx_on_usage_threshold_id_invoice_id_cb82cdf163", unique: true + t.index ["usage_threshold_id"], name: "index_applied_usage_thresholds_on_usage_threshold_id" + end + create_table "billable_metric_filters", id: :uuid, default: -> { "gen_random_uuid()" }, force: :cascade do |t| t.uuid "billable_metric_id", null: false t.string "key", null: false @@ -1175,6 +1186,8 @@ add_foreign_key "adjusted_fees", "subscriptions" add_foreign_key "applied_add_ons", "add_ons" add_foreign_key "applied_add_ons", "customers" + add_foreign_key "applied_usage_thresholds", "invoices" + add_foreign_key "applied_usage_thresholds", "usage_thresholds" add_foreign_key "billable_metric_filters", "billable_metrics" add_foreign_key "billable_metrics", "organizations" add_foreign_key "cached_aggregations", "groups" diff --git a/spec/factories/applied_usage_thresholds.rb b/spec/factories/applied_usage_thresholds.rb new file mode 100644 index 00000000000..3a0e92b4e99 --- /dev/null +++ b/spec/factories/applied_usage_thresholds.rb @@ -0,0 +1,8 @@ +# frozen_string_literal: true + +FactoryBot.define do + factory :applied_usage_threshold do + usage_threshold + invoice + end +end diff --git a/spec/models/applied_usage_threshold_spec.rb b/spec/models/applied_usage_threshold_spec.rb new file mode 100644 index 00000000000..e715f54f65b --- /dev/null +++ b/spec/models/applied_usage_threshold_spec.rb @@ -0,0 +1,12 @@ +# frozen_string_literal: true + +require 'rails_helper' + +RSpec.describe AppliedUsageThreshold, type: :model do + subject(:applied_usage_threshold) { build(:applied_usage_threshold) } + + it { is_expected.to belong_to(:usage_threshold) } + it { is_expected.to belong_to(:invoice) } + + it { is_expected.to validate_uniqueness_of(:usage_threshold_id).scoped_to(:invoice_id).case_insensitive } +end diff --git a/spec/models/invoice_spec.rb b/spec/models/invoice_spec.rb index a25260d0128..e3afa65b3b2 100644 --- a/spec/models/invoice_spec.rb +++ b/spec/models/invoice_spec.rb @@ -18,6 +18,9 @@ it { is_expected.to have_many(:payment_requests).through(:applied_payment_requests) } it { is_expected.to have_many(:payments) } + it { is_expected.to have_many(:applied_usage_thresholds) } + it { is_expected.to have_many(:usage_thresholds).through(:applied_usage_thresholds) } + it 'has fixed status mapping' do expect(described_class::VISIBLE_STATUS).to match(draft: 0, finalized: 1, voided: 2, failed: 4) expect(described_class::INVISIBLE_STATUS).to match(generating: 3, open: 5) diff --git a/spec/models/usage_threshold_spec.rb b/spec/models/usage_threshold_spec.rb index 1df267f3981..02736ec1624 100644 --- a/spec/models/usage_threshold_spec.rb +++ b/spec/models/usage_threshold_spec.rb @@ -5,6 +5,9 @@ RSpec.describe UsageThreshold, type: :model do subject(:usage_threshold) { build(:usage_threshold) } + it { is_expected.to have_many(:applied_usage_thresholds) } + it { is_expected.to have_many(:invoices).through(:applied_usage_thresholds) } + it { is_expected.to validate_numericality_of(:amount_cents).is_greater_than(0) } describe 'default scope' do From 5553ab7f5054cd5c4fa72e2e2dff4558140b5745 Mon Sep 17 00:00:00 2001 From: Vincent Pochet Date: Fri, 23 Aug 2024 12:09:01 +0200 Subject: [PATCH 2/4] feat(ProgressiveBilling): Attach usage threshold to invoices --- app/services/invoices/progressive_billing_service.rb | 5 +++++ spec/services/invoices/progressive_billing_service_spec.rb | 2 ++ 2 files changed, 7 insertions(+) diff --git a/app/services/invoices/progressive_billing_service.rb b/app/services/invoices/progressive_billing_service.rb index fd7b5fd17f2..9295b129e3d 100644 --- a/app/services/invoices/progressive_billing_service.rb +++ b/app/services/invoices/progressive_billing_service.rb @@ -14,6 +14,7 @@ def call ActiveRecord::Base.transaction do create_generating_invoice create_fees + create_applied_usage_thresholds invoice.fees_amount_cents = invoice.fees.sum(:amount_cents) invoice.sub_total_excluding_taxes_amount_cents = invoice.fees_amount_cents @@ -107,6 +108,10 @@ def boundaries } end + def create_applied_usage_thresholds + usage_thresholds.each { AppliedUsageThreshold.create!(invoice:, usage_threshold: _1) } + end + def should_deliver_email? License.premium? && subscription.organization.email_settings.include?('invoice.finalized') end diff --git a/spec/services/invoices/progressive_billing_service_spec.rb b/spec/services/invoices/progressive_billing_service_spec.rb index dd7babd731e..2404b2f9a8e 100644 --- a/spec/services/invoices/progressive_billing_service_spec.rb +++ b/spec/services/invoices/progressive_billing_service_spec.rb @@ -62,6 +62,7 @@ expect(invoice.invoice_subscriptions.count).to eq(1) expect(invoice.fees.count).to eq(1) + expect(invoice.applied_usage_thresholds.count).to eq(1) end context 'with multiple thresholds' do @@ -95,6 +96,7 @@ expect(invoice.invoice_subscriptions.count).to eq(1) expect(invoice.fees.count).to eq(1) + expect(invoice.applied_usage_thresholds.count).to eq(2) end end From e0b01b7934f742ac8d8820c32d88b8d44f506b9f Mon Sep 17 00:00:00 2001 From: Vincent Pochet Date: Fri, 23 Aug 2024 16:43:58 +0200 Subject: [PATCH 3/4] feat(ProgressiveBilling): Add label on invoice --- app/models/applied_usage_threshold.rb | 5 ++++- app/models/lifetime_usage.rb | 5 +++++ .../invoices/progressive_billing_service.rb | 15 +++++++-------- app/views/templates/invoices/v4.slim | 5 +++++ config/locales/en/invoice.yml | 1 + ...40823092643_create_applied_usage_thresholds.rb | 1 + spec/factories/applied_usage_thresholds.rb | 2 ++ spec/models/applied_usage_threshold_spec.rb | 7 +++---- spec/models/lifetime_usage_spec.rb | 10 ++++++++++ .../invoices/progressive_billing_service_spec.rb | 3 +++ 10 files changed, 41 insertions(+), 13 deletions(-) diff --git a/app/models/applied_usage_threshold.rb b/app/models/applied_usage_threshold.rb index bbb17f87d77..fecd2e1b827 100644 --- a/app/models/applied_usage_threshold.rb +++ b/app/models/applied_usage_threshold.rb @@ -1,10 +1,13 @@ # frozen_string_literal: true class AppliedUsageThreshold < ApplicationRecord - belongs_to :usage_threshold + belongs_to :usage_threshold, -> { with_discarded } belongs_to :invoice validates :usage_threshold_id, uniqueness: {scope: :invoice_id} + + monetize :lifetime_usage_amount_cents, + with_currency: ->(applied_usage_threshold) { applied_usage_threshold.invoice.currency } end # == Schema Information diff --git a/app/models/lifetime_usage.rb b/app/models/lifetime_usage.rb index bacb1b270d9..44dc38d3f05 100644 --- a/app/models/lifetime_usage.rb +++ b/app/models/lifetime_usage.rb @@ -14,11 +14,16 @@ class LifetimeUsage < ApplicationRecord monetize :current_usage_amount_cents, :invoiced_usage_amount_cents, + :historical_usage_amount_cents, with_currency: ->(lifetime_usage) { lifetime_usage.subscription.plan.amount_currency } default_scope -> { kept } scope :needs_recalculation, -> { where(recalculate_current_usage: true).or(where(recalculate_invoiced_usage: true)) } + + def total_amount_cents + historical_usage_amount_cents + invoiced_usage_amount_cents + current_usage_amount_cents + end end # == Schema Information diff --git a/app/services/invoices/progressive_billing_service.rb b/app/services/invoices/progressive_billing_service.rb index 9295b129e3d..c146f6e3475 100644 --- a/app/services/invoices/progressive_billing_service.rb +++ b/app/services/invoices/progressive_billing_service.rb @@ -23,7 +23,6 @@ def call Credits::AppliedCouponsService.call(invoice:) Invoices::ComputeAmountsFromFees.call(invoice:) - create_credit_note_credit create_applied_prepaid_credit invoice.payment_status = invoice.total_amount_cents.positive? ? :pending : :succeeded @@ -109,19 +108,19 @@ def boundaries end def create_applied_usage_thresholds - usage_thresholds.each { AppliedUsageThreshold.create!(invoice:, usage_threshold: _1) } + usage_thresholds.each do + AppliedUsageThreshold.create!( + invoice:, + usage_threshold: _1, + lifetime_usage_amount_cents: lifetime_usage.total_amount_cents + ) + end end def should_deliver_email? License.premium? && subscription.organization.email_settings.include?('invoice.finalized') end - def create_credit_note_credit - credit_result = Credits::CreditNoteService.call(invoice:).raise_if_error! - - invoice.total_amount_cents -= credit_result.credits.sum(&:amount_cents) if credit_result.credits - end - def create_applied_prepaid_credit wallet = subscription.customer.wallets.active.first return unless wallet&.active? diff --git a/app/views/templates/invoices/v4.slim b/app/views/templates/invoices/v4.slim index 55ef494e608..9671742e867 100644 --- a/app/views/templates/invoices/v4.slim +++ b/app/views/templates/invoices/v4.slim @@ -462,6 +462,11 @@ html == SlimHelper.render('templates/invoices/v4/_eu_tax_management', self) + - if progressive_billing? + p.body-3.mb-24 + - applied_usage_threshold = applied_usage_thresholds.order(created_at: :asc).last + = I18n.t('invoice.reached_usage_threshold', usage_amount: MoneyHelper. applied_usage_threshold.lifetime_usage_amount, threshold_amount: MoneyHelper.format(applied_usage_threshold.threshold.amount_cents) + p.body-3.mb-24 = LineBreakHelper.break_lines(organization.invoice_footer) .powered-by diff --git a/config/locales/en/invoice.yml b/config/locales/en/invoice.yml index 56b66c61f9b..cee74a3d9f0 100644 --- a/config/locales/en/invoice.yml +++ b/config/locales/en/invoice.yml @@ -55,6 +55,7 @@ en: progressive_billing_credit: Usage already billed quarter: quarter quarterly: Quarterly + reached_usage_threshold: This progressive billing invoice is generated because your lifetime usage has reached %{usage_amount}, exceeding the ${threshold_amount} threshold. see_breakdown: See breakdown for total unit sub_total: Subtotal sub_total_with_tax: Subtotal (incl. tax) diff --git a/db/migrate/20240823092643_create_applied_usage_thresholds.rb b/db/migrate/20240823092643_create_applied_usage_thresholds.rb index e3f45667fb2..e10c85e7aba 100644 --- a/db/migrate/20240823092643_create_applied_usage_thresholds.rb +++ b/db/migrate/20240823092643_create_applied_usage_thresholds.rb @@ -5,6 +5,7 @@ def change create_table :applied_usage_thresholds, id: :uuid do |t| t.references :usage_threshold, null: false, foreign_key: true, type: :uuid t.references :invoice, null: false, foreign_key: true, type: :uuid + t.bigint :lifetime_usage_amount_cents, null: false, default: 0 t.timestamps diff --git a/spec/factories/applied_usage_thresholds.rb b/spec/factories/applied_usage_thresholds.rb index 3a0e92b4e99..276e4c63108 100644 --- a/spec/factories/applied_usage_thresholds.rb +++ b/spec/factories/applied_usage_thresholds.rb @@ -4,5 +4,7 @@ factory :applied_usage_threshold do usage_threshold invoice + + lifetime_usage_amount_cents { 100 } end end diff --git a/spec/models/applied_usage_threshold_spec.rb b/spec/models/applied_usage_threshold_spec.rb index e715f54f65b..d00027cd699 100644 --- a/spec/models/applied_usage_threshold_spec.rb +++ b/spec/models/applied_usage_threshold_spec.rb @@ -3,10 +3,9 @@ require 'rails_helper' RSpec.describe AppliedUsageThreshold, type: :model do - subject(:applied_usage_threshold) { build(:applied_usage_threshold) } + subject(:applied_usage_threshold) { create(:applied_usage_threshold, invoice:) } - it { is_expected.to belong_to(:usage_threshold) } - it { is_expected.to belong_to(:invoice) } + let(:invoice) { create(:invoice) } - it { is_expected.to validate_uniqueness_of(:usage_threshold_id).scoped_to(:invoice_id).case_insensitive } + it { is_expected.to belong_to(:usage_threshold) } end diff --git a/spec/models/lifetime_usage_spec.rb b/spec/models/lifetime_usage_spec.rb index 73a15a3f9c3..97eae27700c 100644 --- a/spec/models/lifetime_usage_spec.rb +++ b/spec/models/lifetime_usage_spec.rb @@ -60,4 +60,14 @@ expect(described_class.needs_recalculation).to match_array([lifetime_usage1, lifetime_usage2]) end end + + describe '#total_amount_cents' do + it 'returns the sum of the historical, invoiced, and current usage' do + lifetime_usage.historical_usage_amount_cents = 100 + lifetime_usage.invoiced_usage_amount_cents = 200 + lifetime_usage.current_usage_amount_cents = 300 + + expect(lifetime_usage.total_amount_cents).to eq(600) + end + end end diff --git a/spec/services/invoices/progressive_billing_service_spec.rb b/spec/services/invoices/progressive_billing_service_spec.rb index 2404b2f9a8e..f3b4f724ee1 100644 --- a/spec/services/invoices/progressive_billing_service_spec.rb +++ b/spec/services/invoices/progressive_billing_service_spec.rb @@ -63,6 +63,9 @@ expect(invoice.invoice_subscriptions.count).to eq(1) expect(invoice.fees.count).to eq(1) expect(invoice.applied_usage_thresholds.count).to eq(1) + + expect(invoice.applied_usage_thresholds.first.lifetime_usage_amount_cents) + .to eq(lifetime_usage.total_amount_cents) end context 'with multiple thresholds' do From 44f84d053d27197c317bdf7175eae9559b8e7892 Mon Sep 17 00:00:00 2001 From: Vincent Pochet Date: Mon, 26 Aug 2024 09:27:47 +0200 Subject: [PATCH 4/4] feat(PrgoressiveBilling): Update locales --- app/services/invoices/progressive_billing_service.rb | 7 +++++++ app/views/templates/invoices/v4.slim | 2 +- config/locales/de/invoice.yml | 1 + config/locales/en/invoice.yml | 2 +- config/locales/es/invoice.yml | 1 + config/locales/fr/invoice.yml | 1 + config/locales/it/invoice.yml | 3 ++- config/locales/nb/invoice.yml | 1 + config/locales/sv/invoice.yml | 3 ++- 9 files changed, 17 insertions(+), 4 deletions(-) diff --git a/app/services/invoices/progressive_billing_service.rb b/app/services/invoices/progressive_billing_service.rb index c146f6e3475..16e59f08d1f 100644 --- a/app/services/invoices/progressive_billing_service.rb +++ b/app/services/invoices/progressive_billing_service.rb @@ -23,6 +23,7 @@ def call Credits::AppliedCouponsService.call(invoice:) Invoices::ComputeAmountsFromFees.call(invoice:) + create_credit_note_credit create_applied_prepaid_credit invoice.payment_status = invoice.total_amount_cents.positive? ? :pending : :succeeded @@ -121,6 +122,12 @@ def should_deliver_email? License.premium? && subscription.organization.email_settings.include?('invoice.finalized') end + def create_credit_note_credit + credit_result = Credits::CreditNoteService.call(invoice:).raise_if_error! + + invoice.total_amount_cents -= credit_result.credits.sum(&:amount_cents) if credit_result.credits + end + def create_applied_prepaid_credit wallet = subscription.customer.wallets.active.first return unless wallet&.active? diff --git a/app/views/templates/invoices/v4.slim b/app/views/templates/invoices/v4.slim index 9671742e867..f48a744716a 100644 --- a/app/views/templates/invoices/v4.slim +++ b/app/views/templates/invoices/v4.slim @@ -465,7 +465,7 @@ html - if progressive_billing? p.body-3.mb-24 - applied_usage_threshold = applied_usage_thresholds.order(created_at: :asc).last - = I18n.t('invoice.reached_usage_threshold', usage_amount: MoneyHelper. applied_usage_threshold.lifetime_usage_amount, threshold_amount: MoneyHelper.format(applied_usage_threshold.threshold.amount_cents) + = I18n.t('invoice.reached_usage_threshold', usage_amount: MoneyHelper. applied_usage_threshold.lifetime_usage_amount, threshold_amount: MoneyHelper.format(applied_usage_threshold.threshold.amount_cents)) p.body-3.mb-24 = LineBreakHelper.break_lines(organization.invoice_footer) diff --git a/config/locales/de/invoice.yml b/config/locales/de/invoice.yml index 1ca5db5ff7a..6f148e46c2e 100644 --- a/config/locales/de/invoice.yml +++ b/config/locales/de/invoice.yml @@ -55,6 +55,7 @@ de: progressive_billing_credit: Nutzung bereits abgerechnet quarter: quartal quarterly: Vierteljährlich + reached_usage_threshold: Diese progressive Rechnung wird erstellt, da Ihre kumulierte Nutzung %{usage_amount} erreicht hat und den Schwellenwert von %{threshold_amount} überschritten hat. see_breakdown: Siehe Aufschlüsselung für Gesamtübersicht sub_total: Zwischensumme sub_total_with_tax: Zwischensumme (inkl. Steuern) diff --git a/config/locales/en/invoice.yml b/config/locales/en/invoice.yml index cee74a3d9f0..a285c5840e4 100644 --- a/config/locales/en/invoice.yml +++ b/config/locales/en/invoice.yml @@ -55,7 +55,7 @@ en: progressive_billing_credit: Usage already billed quarter: quarter quarterly: Quarterly - reached_usage_threshold: This progressive billing invoice is generated because your lifetime usage has reached %{usage_amount}, exceeding the ${threshold_amount} threshold. + reached_usage_threshold: This progressive billing is generated because your cumulative usage has reached %{usage_amount}, exceeding the %{threshold_amount} threshold. see_breakdown: See breakdown for total unit sub_total: Subtotal sub_total_with_tax: Subtotal (incl. tax) diff --git a/config/locales/es/invoice.yml b/config/locales/es/invoice.yml index e8501f4542f..f744419031d 100644 --- a/config/locales/es/invoice.yml +++ b/config/locales/es/invoice.yml @@ -54,6 +54,7 @@ es: progressive_billing_credit: Uso ya facturado quarter: trimestre quarterly: Trimestral + reached_usage_threshold: Esta facturación progresiva se genera porque su uso acumulado ha alcanzado los %{usage_amount}, superando el umbral de %{threshold_amount}. see_breakdown: Consulte el desglose a continuación sub_total: Subtotal sub_total_with_tax: Subtotal (impuestos incl.) diff --git a/config/locales/fr/invoice.yml b/config/locales/fr/invoice.yml index 70862d7ea80..693a4dc0920 100644 --- a/config/locales/fr/invoice.yml +++ b/config/locales/fr/invoice.yml @@ -55,6 +55,7 @@ fr: progressive_billing_credit: Usage déjà facturé quarter: trimestre quarterly: trimestriellement + reached_usage_threshold: Cette facturation progressive est générée car votre usage cumulé a atteint %{usage_amount}, dépassant le seuil de %{threshold_amount}. see_breakdown: Consultez le détail ci-après sub_total: Sous total sub_total_with_tax: Sous total (TTC) diff --git a/config/locales/it/invoice.yml b/config/locales/it/invoice.yml index c637d25d2bf..3fa3fde2bd7 100644 --- a/config/locales/it/invoice.yml +++ b/config/locales/it/invoice.yml @@ -52,9 +52,10 @@ it: prepaid_credit_invoice: Fattura anticipata prepaid_credits: Crediti prepagati prepaid_credits_with_value: Crediti prepagati - %{wallet_name} - progressive_billing_credit: Utilizzo già fatturato + progressive_billing_credit: Uso già fatturato quarter: trimestre quarterly: Trimestrale + reached_usage_threshold: Questa fatturazione progressiva è generata poiché il tuo utilizzo cumulato ha raggiunto %{usage_amount}, superando la soglia di %{threshold_amount}. see_breakdown: Vedere la ripartizione per l'unità totale sub_total: Subtotale sub_total_with_tax: Subtotale (incl. tasse) diff --git a/config/locales/nb/invoice.yml b/config/locales/nb/invoice.yml index 2924c4a2626..04013023883 100644 --- a/config/locales/nb/invoice.yml +++ b/config/locales/nb/invoice.yml @@ -55,6 +55,7 @@ nb: progressive_billing_credit: Bruk allerede fakturert quarter: kvartal quarterly: Kvartalsvis + reached_usage_threshold: Denne progressive faktureringen er generert fordi din akkumulerte bruk har nådd %{usage_amount}, og overskredet terskelen på %{threshold_amount}. see_breakdown: Se oversikt for antall enheter sub_total: Sub total sub_total_with_tax: Sub total (inkl. MVA) diff --git a/config/locales/sv/invoice.yml b/config/locales/sv/invoice.yml index 894ac5742e9..f3972d05dca 100644 --- a/config/locales/sv/invoice.yml +++ b/config/locales/sv/invoice.yml @@ -51,9 +51,10 @@ sv: prepaid_credit_invoice: Förskottsfaktura prepaid_credits: Förbetald kontobalans prepaid_credits_with_value: Förbetald kontobalans - %{wallet_name} - progressive_billing_credit: Användning redan fakturerad + progressive_billing_credit: Redan fakturerad användning quarter: kvartal quarterly: Kvartalsvis + reached_usage_threshold: Denna progressiva fakturering skapas eftersom din ackumulerade användning har nått %{usage_amount} och överstiger %{threshold_amount} tröskeln. see_breakdown: Se uppdelning nedan sub_total: Delsumma sub_total_with_tax: Delsumma (inkl. moms)