Skip to content

Commit

Permalink
Fix invoice dates for backend prorated initial orders (#991)
Browse files Browse the repository at this point in the history
  • Loading branch information
nadaismail-stripe authored Feb 6, 2023
1 parent f0b38fd commit 6789b41
Show file tree
Hide file tree
Showing 3 changed files with 48 additions and 13 deletions.
1 change: 1 addition & 0 deletions lib/stripe-force/translate/order.rb
Original file line number Diff line number Diff line change
Expand Up @@ -244,6 +244,7 @@ def generate_phases_for_initial_order(sf_order:, invoice_items:, subscription_it
# add special metadata to line items as well
invoice_items_for_prorations.each do |invoice_item|
invoice_item[:metadata][StripeForce::Translate::Metadata.metadata_key(@user, MetadataKeys::BACKEND_PRORATION)] = true
invoice_item[:period][:end][:type] = 'phase_end'
end

backend_proration_term = subscription_term_from_sales_force % billing_frequency
Expand Down
40 changes: 36 additions & 4 deletions test/integration/amendments/test_backend_prorated_amendments.rb
Original file line number Diff line number Diff line change
Expand Up @@ -9,10 +9,13 @@ class Critic::BackendProratedAmendmentTranslation < Critic::OrderAmendmentFuncti
end

it 'handles an initial order with a backend proration' do
@user.enable_feature FeatureFlags::TEST_CLOCKS, update: true

backend_prorated_term = 6
contract_term = TEST_DEFAULT_CONTRACT_TERM + backend_prorated_term
initial_start_date = now_time
end_date = initial_start_date + contract_term.months
initial_end_date = initial_start_date + contract_term.months
backend_proration_start = initial_start_date + TEST_DEFAULT_CONTRACT_TERM.months

sf_product_id, sf_pricebook_entry_id = salesforce_recurring_product_with_price(
additional_product_fields: {
Expand Down Expand Up @@ -46,11 +49,11 @@ class Critic::BackendProratedAmendmentTranslation < Critic::OrderAmendmentFuncti

# first phase should start now and end at the end of the billing cycle
assert_equal(0, first_phase.start_date - initial_start_date.to_i)
assert_equal(0, first_phase.end_date - (initial_start_date + TEST_DEFAULT_CONTRACT_TERM.months).to_i)
assert_equal(0, first_phase.end_date - backend_proration_start.to_i)

# second phase should start at the end of the billing cycle and end at the contract term
assert_equal(0, second_phase.start_date - (initial_start_date + TEST_DEFAULT_CONTRACT_TERM.months).to_i)
assert_equal(0, second_phase.end_date - end_date.to_i)
assert_equal(0, second_phase.start_date - backend_proration_start.to_i)
assert_equal(0, second_phase.end_date - initial_end_date.to_i)

# first phase should have one item with no quantity, since it is a metered product
assert_equal(1, first_phase.items.count)
Expand All @@ -74,6 +77,35 @@ class Critic::BackendProratedAmendmentTranslation < Critic::OrderAmendmentFuncti
assert_equal(TEST_DEFAULT_PRICE / 2, prorated_price.unit_amount_decimal.to_i)
assert_equal("one_time", prorated_price.type)
assert_equal("true", prorated_price.metadata[StripeForce::Translate::Metadata.metadata_key(@user, MetadataKeys::PRORATION)])

# now, let's advance the clock
sf_account = sf_get(sf_order['AccountId'])
stripe_customer_id = sf_account[prefixed_stripe_field(GENERIC_STRIPE_ID)]
stripe_customer = stripe_get(stripe_customer_id)
refute_nil(stripe_customer.test_clock)

test_clock = advance_test_clock(stripe_customer, (backend_proration_start + 1.day).to_i)

# simulate sending the webhook
events = Stripe::Event.list({
type: 'invoiceitem.created',
}, @user.stripe_credentials)

invoice_events = events.data.select do |event|
event_object = event.data.object
event_object.test_clock == test_clock.id && event.request.id.nil?
end

assert_equal(1, invoice_events.count)
invoice_event = invoice_events.first

invoice_period_start = invoice_event.data.object.period.start
invoice_period_end = invoice_event.data.object.period.end

# sanity check the usage period of this proration invoice
# should be from the first phase end to contract end
assert_equal(backend_proration_start.to_i, invoice_period_start)
assert_equal(initial_end_date.to_i, invoice_period_end)
end

describe 'amendments' do
Expand Down
20 changes: 11 additions & 9 deletions test/integration/amendments/test_proration_amendments.rb
Original file line number Diff line number Diff line change
Expand Up @@ -20,7 +20,7 @@ class Critic::ProratedAmendmentTranslation < Critic::OrderAmendmentFunctionalTes
initial_order_end_date = initial_order_start_date + contract_term

amendment_term = 18
amendment_start_date = now_time + (contract_term - amendment_term).months
amendment_start_date = initial_order_start_date + (contract_term - amendment_term).months
amendment_end_date = amendment_start_date + amendment_term.months

# normalize the amendment_end_date so test doesn't fail EOM
Expand Down Expand Up @@ -60,7 +60,6 @@ class Critic::ProratedAmendmentTranslation < Critic::OrderAmendmentFunctionalTes
subscription_schedule = Stripe::SubscriptionSchedule.retrieve(stripe_id, @user.stripe_credentials)

assert_equal(2, subscription_schedule.phases.count)

first_phase = T.must(subscription_schedule.phases.first)
second_phase = T.must(subscription_schedule.phases[1])

Expand Down Expand Up @@ -146,20 +145,23 @@ class Critic::ProratedAmendmentTranslation < Critic::OrderAmendmentFunctionalTes
assert_equal(1, invoice_events.count)
invoice_event = invoice_events.first

invoice_period_start = invoice_event.data.object.period.start
invoice_period_end = invoice_event.data.object.period.end

# sanity check the usage period of this proration invoice
# should be from the amendment start to the next billing cycle date
assert_equal(amendment_start_date.to_i, invoice_period_start)
# the proration period end should align with the next billing cycle
# since this is billed 'Annually', add a year to the initial order start date to get the start of the next billing cycle
assert_equal((initial_order_start_date + 1.year).to_i, invoice_period_end)

invoice = T.must(StripeForce::ProrationAutoBill.create_invoice_from_invoice_item_event(@user, invoice_event))

assert_equal(1, invoice.lines.count)
invoice_line = invoice.lines.first
assert_equal(2, invoice_line.quantity)
assert_equal(60_00 * 2, invoice.total)
assert_equal("true", invoice.metadata[StripeForce::Translate::Metadata.metadata_key(@user, MetadataKeys::PRORATION_INVOICE)])

# sanity check the usage period of this proration invoice
# should be from the amendment start to the next billing cycle date
assert_equal(amendment_start_date.to_i, invoice.period_start)
# the proration period end should align with the next billing cycle
# since this is billed 'Annually', add a year to the initial order start date to get the start of the next billing cycle
assert_equal((initial_order_start_date + 1.year).to_i, invoice.period_end.to_i)
end

# NOTE this was the first test written and has more extensive edge cases than other amendment tests
Expand Down

0 comments on commit 6789b41

Please sign in to comment.