Skip to content

Commit

Permalink
Invoices paid in advance fees from subs with same external_id
Browse files Browse the repository at this point in the history
finds all terminated and active subscriptions with the same external_id
to invoice advance fees belonging to them.
  • Loading branch information
ancorcruz committed Jan 2, 2025
1 parent eb78b5a commit d9a9421
Show file tree
Hide file tree
Showing 3 changed files with 81 additions and 7 deletions.
2 changes: 1 addition & 1 deletion app/jobs/bill_non_invoiceable_fees_job.rb
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@ class BillNonInvoiceableFeesJob < ApplicationJob
retry_on Sequenced::SequenceError, ActiveJob::DeserializationError

def perform(subscriptions, billing_at)
result = Invoices::AdvanceChargesService.call(subscriptions:, billing_at:)
result = Invoices::AdvanceChargesService.call(initial_subscriptions: subscriptions, billing_at:)
result.raise_if_error!
end
end
19 changes: 14 additions & 5 deletions app/services/invoices/advance_charges_service.rb
Original file line number Diff line number Diff line change
Expand Up @@ -2,13 +2,13 @@

module Invoices
class AdvanceChargesService < BaseService
def initialize(subscriptions:, billing_at:)
@subscriptions = subscriptions
def initialize(initial_subscriptions:, billing_at:)
@initial_subscriptions = initial_subscriptions
@billing_at = billing_at

@customer = subscriptions&.first&.customer
@customer = initial_subscriptions&.first&.customer
@organization = customer&.organization
@currency = subscriptions&.first&.plan&.amount_currency
@currency = initial_subscriptions&.first&.plan&.amount_currency

super
end
Expand All @@ -35,7 +35,16 @@ def call

private

attr_accessor :subscriptions, :billing_at, :customer, :organization, :currency
attr_accessor :initial_subscriptions, :billing_at, :customer, :organization, :currency

def subscriptions
return [] unless organization

@subscriptions ||= organization.subscriptions.where(
external_id: initial_subscriptions.pluck(:external_id).uniq,
status: [:active, :terminated]
)
end

def has_charges_with_statement?
plan_ids = subscriptions.pluck(:plan_id)
Expand Down
67 changes: 66 additions & 1 deletion spec/services/invoices/advance_charges_service_spec.rb
Original file line number Diff line number Diff line change
Expand Up @@ -3,7 +3,9 @@
require 'rails_helper'

RSpec.describe Invoices::AdvanceChargesService, type: :service do
subject(:invoice_service) { described_class.new(subscriptions:, billing_at:) }
subject(:invoice_service) do
described_class.new(initial_subscriptions: subscriptions, billing_at:)
end

let(:organization) { create(:organization) }
let(:customer) { create(:customer, organization:) }
Expand Down Expand Up @@ -111,6 +113,69 @@ def fee_boundaries
end
end

context "when there is a successful non invoiceable paid in advance fees" do
let(:billable_metric) { create(:sum_billable_metric, :recurring, organization:) }

let(:charge) do
create(
:charge,
plan:,
billable_metric:,
prorated: true,
pay_in_advance: true,
invoiceable: false,
regroup_paid_fees: "invoice",
properties: {amount: "1"}
)
end

let(:subscription_2) do
create(:subscription, {
external_id: subscription.external_id,
customer: subscription.customer,
status: :terminated
})
end

let(:paid_in_advance_fee) do
create(
:fee,
:succeeded,
invoice_id: nil,
subscription: subscription_2,
amount_cents: 999,
properties: fee_boundaries,
charge:
)
end

before { paid_in_advance_fee }

it 'creates invoices' do
result = invoice_service.call

expect(result).to be_success
expect(result.invoice).to be_a Invoice
expect(result.invoice.fees.count).to eq 1
expect(result.invoice.total_amount_cents).to eq(paid_in_advance_fee.amount_cents)

expect(result.invoice)
.to be_finalized
.and have_attributes(
invoice_type: 'advance_charges',
currency: 'EUR',
issuing_date: billing_at.to_date,
skip_charges: true
)

expect(result.invoice.invoice_subscriptions.count).to eq(2)
sub = result.invoice.invoice_subscriptions.first
expect(sub.charges_to_datetime).to match_datetime fee_boundaries[:charges_to_datetime]
expect(sub.charges_from_datetime).to match_datetime fee_boundaries[:charges_from_datetime]
expect(sub.invoicing_reason).to eq 'in_advance_charge_periodic'
end
end

context 'with integration requiring sync' do
before do
tax
Expand Down

0 comments on commit d9a9421

Please sign in to comment.