Skip to content

Commit

Permalink
fix (invoice-numbering): revert moving invoice numbering outside DB t…
Browse files Browse the repository at this point in the history
…ransaction (#2684)

## Description

This PR reverts #2621
  • Loading branch information
lovrocolic authored Oct 14, 2024
1 parent 096f5e3 commit 265d8ad
Show file tree
Hide file tree
Showing 16 changed files with 27 additions and 249 deletions.
2 changes: 1 addition & 1 deletion app/models/concerns/sequenced.rb
Original file line number Diff line number Diff line change
Expand Up @@ -27,7 +27,7 @@ def generate_sequential_id
transaction: true,
timeout_seconds: 10.seconds
) do
sequential_id = sequence_scope.with_sequential_id.where.not(id:).order(sequential_id: :desc).limit(1).pick(:sequential_id)
sequential_id = sequence_scope.with_sequential_id.order(sequential_id: :desc).limit(1).pick(:sequential_id)
sequential_id ||= 0

loop do
Expand Down
44 changes: 23 additions & 21 deletions app/models/invoice.rb
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,9 @@ class Invoice < ApplicationRecord
CREDIT_NOTES_MIN_VERSION = 2
COUPON_BEFORE_VAT_VERSION = 3

before_save :ensure_organization_sequential_id, if: -> { organization.per_organization? }
before_save :ensure_number

belongs_to :customer, -> { with_discarded }
belongs_to :organization

Expand Down Expand Up @@ -333,23 +336,20 @@ def document_invoice_name
I18n.t('invoice.document_name')
end

def ensure_organization_sequential_id
return if organization_sequential_id.present? && organization_sequential_id.positive?
return unless finalized?
private

self.organization_sequential_id = generate_organization_sequential_id
def should_assign_sequential_id?
status_changed_to_finalized?
end

def ensure_invoice_sequential_id
return if sequential_id.present?

self.sequential_id = generate_sequential_id
def void_invoice!
update!(ready_for_payment_processing: false)
end

def ensure_number
self.number = "#{organization.document_number_prefix}-DRAFT" if number.blank? && !finalized?
self.number = "#{organization.document_number_prefix}-DRAFT" if number.blank? && !status_changed_to_finalized?

return unless finalized?
return unless status_changed_to_finalized?

if organization.per_customer?
# NOTE: Example of expected customer slug format is ORG_PREFIX-005
Expand All @@ -365,15 +365,11 @@ def ensure_number
end
end

private

# For invoices we want to skip callback and set sequential_id from the dedicated service
def should_assign_sequential_id?
false
end
def ensure_organization_sequential_id
return if organization_sequential_id.present? && organization_sequential_id.positive?
return unless status_changed_to_finalized?

def void_invoice!
update!(ready_for_payment_processing: false)
self.organization_sequential_id = generate_organization_sequential_id
end

def generate_organization_sequential_id
Expand All @@ -391,12 +387,11 @@ def generate_organization_sequential_id
) do
# If previous invoice had different numbering, base sequential id is the total number of invoices
organization_sequential_id = if switched_from_customer_numbering?
organization.invoices.with_generated_number.where.not(id:).count
organization.invoices.with_generated_number.count
else
organization
.invoices
.where.not(organization_sequential_id: 0)
.where.not(id:)
.order(organization_sequential_id: :desc)
.limit(1)
.pick(:organization_sequential_id) || 0
Expand All @@ -417,12 +412,19 @@ def generate_organization_sequential_id
end

def switched_from_customer_numbering?
last_invoice = organization.invoices.where.not(id:).order(created_at: :desc).with_generated_number.first
last_invoice = organization.invoices.order(created_at: :desc).with_generated_number.first

return false unless last_invoice

last_invoice&.organization_sequential_id&.zero?
end

def status_changed_to_finalized?
status_changed?(from: 'draft', to: 'finalized') ||
status_changed?(from: 'generating', to: 'finalized') ||
status_changed?(from: 'open', to: 'finalized') ||
status_changed?(from: 'failed', to: 'finalized')
end
end

# == Schema Information
Expand Down
1 change: 0 additions & 1 deletion app/services/invoices/add_on_service.rb
Original file line number Diff line number Diff line change
Expand Up @@ -32,7 +32,6 @@ def create
result.invoice = invoice
end

Invoices::NumberGenerationService.call(invoice: result.invoice)
Utils::SegmentTrack.invoice_created(result.invoice)
SendWebhookJob.perform_later('invoice.add_on_added', result.invoice)
GeneratePdfAndNotifyJob.perform_later(invoice: result.invoice, email: should_deliver_email?)
Expand Down
2 changes: 0 additions & 2 deletions app/services/invoices/advance_charges_service.rb
Original file line number Diff line number Diff line change
Expand Up @@ -20,8 +20,6 @@ def call

invoice = create_group_invoice

Invoices::NumberGenerationService.call(invoice:) if invoice

if invoice && !invoice.closed?
SendWebhookJob.perform_later('invoice.created', invoice)
Invoices::GeneratePdfAndNotifyJob.perform_later(invoice:, email: false)
Expand Down
2 changes: 0 additions & 2 deletions app/services/invoices/create_one_off_service.rb
Original file line number Diff line number Diff line change
Expand Up @@ -40,8 +40,6 @@ def call
invoice.save!
end

Invoices::NumberGenerationService.call(invoice:)

unless invoice.closed?
Utils::SegmentTrack.invoice_created(invoice)
SendWebhookJob.perform_later('invoice.one_off_created', invoice)
Expand Down
2 changes: 0 additions & 2 deletions app/services/invoices/create_pay_in_advance_charge_service.rb
Original file line number Diff line number Diff line change
Expand Up @@ -47,8 +47,6 @@ def call
invoice.save!
end

Invoices::NumberGenerationService.call(invoice:)

unless invoice.closed?
Utils::SegmentTrack.invoice_created(invoice)
deliver_webhooks
Expand Down
2 changes: 0 additions & 2 deletions app/services/invoices/finalize_open_credit_service.rb
Original file line number Diff line number Diff line change
Expand Up @@ -20,8 +20,6 @@ def call
invoice.save!
end

Invoices::NumberGenerationService.call(invoice:)

SendWebhookJob.perform_later('invoice.paid_credit_added', result.invoice)
GeneratePdfAndNotifyJob.perform_later(invoice:, email: should_deliver_email?)
Integrations::Aggregator::Invoices::CreateJob.perform_later(invoice:) if invoice.should_sync_invoice?
Expand Down
37 changes: 0 additions & 37 deletions app/services/invoices/number_generation_service.rb

This file was deleted.

2 changes: 0 additions & 2 deletions app/services/invoices/paid_credit_service.rb
Original file line number Diff line number Diff line change
Expand Up @@ -30,8 +30,6 @@ def call
end
end

Invoices::NumberGenerationService.call(invoice:)

if invoice.finalized?
Utils::SegmentTrack.invoice_created(result.invoice)
SendWebhookJob.perform_later('invoice.paid_credit_added', result.invoice)
Expand Down
1 change: 0 additions & 1 deletion app/services/invoices/progressive_billing_service.rb
Original file line number Diff line number Diff line change
Expand Up @@ -45,7 +45,6 @@ def call

# TODO: deduct previous progressive billing invoices

Invoices::NumberGenerationService.call(invoice:)
Utils::SegmentTrack.invoice_created(invoice)
SendWebhookJob.perform_later('invoice.created', invoice)
Invoices::GeneratePdfAndNotifyJob.perform_later(invoice:, email: should_deliver_email?)
Expand Down
2 changes: 0 additions & 2 deletions app/services/invoices/refresh_draft_and_finalize_service.rb
Original file line number Diff line number Diff line change
Expand Up @@ -29,8 +29,6 @@ def call
end

result.invoice = invoice.reload
Invoices::NumberGenerationService.call(invoice:)

unless invoice.closed?
SendWebhookJob.perform_later('invoice.created', invoice)
GeneratePdfAndNotifyJob.perform_later(invoice:, email: should_deliver_email?)
Expand Down
1 change: 0 additions & 1 deletion app/services/invoices/retry_service.rb
Original file line number Diff line number Diff line change
Expand Up @@ -40,7 +40,6 @@ def call
result.invoice = invoice
end

Invoices::NumberGenerationService.call(invoice:)
SendWebhookJob.perform_later('invoice.created', invoice)
GeneratePdfAndNotifyJob.perform_later(invoice:, email: should_deliver_email?)
Integrations::Aggregator::Invoices::CreateJob.perform_later(invoice:) if invoice.should_sync_invoice?
Expand Down
3 changes: 0 additions & 3 deletions app/services/invoices/subscription_service.rb
Original file line number Diff line number Diff line change
Expand Up @@ -46,9 +46,6 @@ def call
flag_lifetime_usage_for_refresh
fee_result
end

Invoices::NumberGenerationService.call(invoice:)

result.non_invoiceable_fees = fee_result.non_invoiceable_fees

# non-invoiceable fees are created the first time, regardless of grace period.
Expand Down
31 changes: 3 additions & 28 deletions spec/models/invoice_spec.rb
Original file line number Diff line number Diff line change
Expand Up @@ -54,7 +54,6 @@
it 'assigns a sequential id and organization sequential id to a new invoice' do
invoice.save!
invoice.finalized!
invoice.ensure_invoice_sequential_id

aggregate_failures do
expect(invoice).to be_valid
Expand All @@ -72,7 +71,6 @@
it 'does not replace the sequential_id and organization_sequential_id' do
invoice.save!
invoice.finalized!
invoice.ensure_invoice_sequential_id

aggregate_failures do
expect(invoice).to be_valid
Expand All @@ -91,7 +89,6 @@
it 'takes the next available id' do
invoice.save!
invoice.finalized!
invoice.ensure_invoice_sequential_id

aggregate_failures do
expect(invoice).to be_valid
Expand All @@ -109,7 +106,6 @@
it 'scopes the sequence to the organization' do
invoice.save!
invoice.finalized!
invoice.ensure_invoice_sequential_id

aggregate_failures do
expect(invoice).to be_valid
Expand All @@ -131,8 +127,6 @@
it 'scopes the organization_sequential_id to the organization and month' do
invoice.save!
invoice.finalized!
invoice.ensure_invoice_sequential_id
invoice.ensure_organization_sequential_id

aggregate_failures do
expect(invoice).to be_valid
Expand Down Expand Up @@ -319,7 +313,7 @@
end
end

describe 'ensure_number' do
describe 'number' do
let(:organization) { create(:organization, name: 'LAGO') }
let(:customer) { create(:customer, organization:) }
let(:subscription) { create(:subscription, organization:, customer:) }
Expand All @@ -328,8 +322,6 @@
it 'generates the invoice number' do
invoice.save!
invoice.finalized!
invoice.ensure_invoice_sequential_id
invoice.ensure_number
organization_id_substring = organization.id.last(4).upcase

expect(invoice.number).to eq("LAG-#{organization_id_substring}-001-001")
Expand All @@ -341,9 +333,6 @@
it 'scopes the organization_sequential_id to the organization and month' do
invoice.save!
invoice.finalized!
invoice.ensure_invoice_sequential_id
invoice.ensure_organization_sequential_id
invoice.ensure_number
organization_id_substring = organization.id.last(4).upcase

expect(invoice.number).to eq("LAG-#{organization_id_substring}-#{Time.now.utc.strftime("%Y%m")}-001")
Expand All @@ -360,9 +349,6 @@
it 'scopes the organization_sequential_id to the organization and month' do
invoice.save!
invoice.finalized!
invoice.ensure_invoice_sequential_id
invoice.ensure_organization_sequential_id
invoice.ensure_number

organization_id_substring = organization.id.last(4).upcase

Expand All @@ -381,9 +367,6 @@
it 'scopes the organization_sequential_id to the organization and month' do
invoice.save!
invoice.finalized!
invoice.ensure_invoice_sequential_id
invoice.ensure_organization_sequential_id
invoice.ensure_number

organization_id_substring = organization.id.last(4).upcase

Expand Down Expand Up @@ -426,9 +409,6 @@
it 'scopes the organization_sequential_id to the organization and month' do
invoice.save!
invoice.finalized!
invoice.ensure_invoice_sequential_id
invoice.ensure_organization_sequential_id
invoice.ensure_number

organization_id_substring = organization.id.last(4).upcase

Expand All @@ -440,8 +420,7 @@
expect(invoice1.reload.number).to eq("LAG-#{organization_id_substring}-#{Time.now.utc.strftime("%Y%m")}-014")
expect(invoice2.reload.number).to eq("LAG-#{organization_id_substring}-#{Time.now.utc.strftime("%Y%m")}-015")

invoice.finalized!
Invoices::RefreshDraftAndFinalizeService.call(invoice: invoice1)
invoice1.finalized!

expect(invoice1.reload.number).to eq("LAG-#{organization_id_substring}-#{Time.now.utc.strftime("%Y%m")}-014")
end
Expand Down Expand Up @@ -482,9 +461,6 @@
it 'scopes the organization_sequential_id to the organization and month' do
invoice.save!
invoice.finalized!
invoice.ensure_invoice_sequential_id
invoice.ensure_organization_sequential_id
invoice.ensure_number

organization_id_substring = organization.id.last(4).upcase

Expand All @@ -496,8 +472,7 @@
expect(invoice1.reload.number).to eq("LAG-#{organization_id_substring}-DRAFT")
expect(invoice2.reload.number).to eq("LAG-#{organization_id_substring}-#{Time.now.utc.strftime("%Y%m")}-014")

invoice.finalized!
Invoices::RefreshDraftAndFinalizeService.call(invoice: invoice1)
invoice1.finalized!

expect(invoice1.reload.number).to eq("LAG-#{organization_id_substring}-#{Time.now.utc.strftime("%Y%m")}-016")
end
Expand Down
Loading

0 comments on commit 265d8ad

Please sign in to comment.