-
Notifications
You must be signed in to change notification settings - Fork 1.7k
Fix: Auto-apply VAT ID to recurring subscription charges #2270
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
base: main
Are you sure you want to change the base?
Changes from all commits
2637e39
5190f15
8a2257d
bc1e2d6
cd5bc09
8032530
326e8e8
4e63458
b99361d
0d0c50b
8d43386
3e07567
df45e4a
363871d
3f62cfb
bcb19d6
be409d1
a7d7e1d
6235f25
acf7dad
0c94609
7862e8f
4041e45
7d4423f
c369cc0
9b19114
ec61798
a40e35a
File filter
Filter by extension
Conversations
Jump to
Diff view
Diff view
There are no files selected for viewing
| Original file line number | Diff line number | Diff line change |
|---|---|---|
|
|
@@ -263,7 +263,7 @@ def build_purchase(override_params: {}, from_failed_charge_email: false) | |
| end | ||
| purchase.affiliate = original_purchase.affiliate if original_purchase.affiliate.try(:eligible_for_credit?) | ||
| purchase.is_upgrade_purchase = is_upgrade_purchase if is_upgrade_purchase | ||
| get_vat_id_from_original_purchase(purchase) | ||
| set_vat_id_for_purchase(purchase) | ||
| purchase | ||
| end | ||
|
|
||
|
|
@@ -462,7 +462,7 @@ def update_current_plan!(new_variants:, new_price:, new_quantity: nil, perceived | |
| new_purchase.is_original_subscription_purchase = true | ||
| new_purchase.perceived_price_cents = perceived_price_cents | ||
| new_purchase.price_range = perceived_price_cents.present? ? perceived_price_cents / (link.single_unit_currency? ? 1 : 100.0) : nil | ||
| new_purchase.business_vat_id = original_purchase.purchase_sales_tax_info&.business_vat_id | ||
| new_purchase.business_vat_id = resolve_vat_id | ||
| new_purchase.quantity = new_quantity if new_quantity.present? | ||
| original_purchase.purchase_custom_fields.each { new_purchase.purchase_custom_fields << _1.dup } | ||
|
|
||
|
|
@@ -696,6 +696,29 @@ def resubscribe! | |
| end | ||
| end | ||
|
|
||
| def update_business_vat_id!(vat_id) | ||
| update!(business_vat_id: vat_id) if vat_id.present? && business_vat_id.blank? | ||
| end | ||
|
Comment on lines
+699
to
+701
Member
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. @michellelarney should we allow the buyer to use different VAT IDs in the course of a subscription? Or is it like, once they set a certain VAT in a subscription, we shouldn't allow to change that? There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Generally I don't think people would need to change it and would usually be using the same VAT ID for all charges. I would say it should just stay the same. |
||
|
|
||
|
Comment on lines
+699
to
+702
Contributor
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Stores VAT ID on subscription only if not already set. This prevents overwriting if customer provides a different VAT ID later. |
||
| # TODO: Remove fallback logic after running Onetime::BackfillSubscriptionVatIds | ||
| def resolve_vat_id | ||
yashranaway marked this conversation as resolved.
Show resolved
Hide resolved
|
||
| business_vat_id.presence || | ||
| original_purchase&.purchase_sales_tax_info&.business_vat_id.presence || | ||
| vat_id_from_original_purchase_refund || | ||
| vat_id_from_any_subscription_purchase_refund | ||
| end | ||
|
|
||
| def vat_id_from_any_subscription_purchase_refund | ||
| Refund.joins(:purchase) | ||
| .where(purchases: { subscription_id: id }) | ||
| .where("refunds.gumroad_tax_cents > 0") | ||
| .where("refunds.amount_cents = 0") | ||
| .order("refunds.created_at DESC") | ||
| .limit(10) | ||
| .find { |refund| refund.business_vat_id.present? } | ||
| &.business_vat_id | ||
| end | ||
|
|
||
| def last_resubscribed_at | ||
| if defined?(@_last_resubscribed_at) | ||
| @_last_resubscribed_at | ||
|
|
@@ -935,12 +958,18 @@ def fetch_last_payment_option | |
| payment_options.alive.last | ||
| end | ||
|
|
||
| def get_vat_id_from_original_purchase(purchase) | ||
| if original_purchase.purchase_sales_tax_info&.business_vat_id | ||
| purchase.business_vat_id = original_purchase.purchase_sales_tax_info.business_vat_id | ||
| elsif original_purchase.refunds.where("gumroad_tax_cents > 0").where("amount_cents = 0").exists? | ||
| purchase.business_vat_id = original_purchase.refunds.where("gumroad_tax_cents > 0").where("amount_cents = 0").first.business_vat_id | ||
| end | ||
| def set_vat_id_for_purchase(purchase) | ||
| vat_id = resolve_vat_id | ||
| purchase.business_vat_id = vat_id if vat_id.present? | ||
| end | ||
|
|
||
| def vat_id_from_original_purchase_refund | ||
| original_purchase.refunds | ||
| .where("gumroad_tax_cents > 0") | ||
| .where("amount_cents = 0") | ||
yashranaway marked this conversation as resolved.
Show resolved
Hide resolved
|
||
| .order(created_at: :desc) | ||
| .find { |refund| refund.business_vat_id.present? } | ||
| &.business_vat_id | ||
| end | ||
|
|
||
| def schedule_member_cancellation_workflow_jobs | ||
|
|
||
|
Contributor
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. One-time service to populate |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,29 @@ | ||
| # frozen_string_literal: true | ||
|
|
||
| module Onetime | ||
| class BackfillSubscriptionVatIds | ||
| def self.process | ||
| new.process | ||
| end | ||
|
|
||
| def process | ||
| count = 0 | ||
|
|
||
| Subscription.where(business_vat_id: nil).find_each do |subscription| | ||
| vat_id = subscription.resolve_vat_id | ||
| next if vat_id.blank? | ||
|
|
||
| subscription.update!(business_vat_id: vat_id) | ||
yashranaway marked this conversation as resolved.
Show resolved
Hide resolved
|
||
| count += 1 | ||
|
|
||
| Rails.logger.info("Backfilled VAT ID for subscription #{subscription.id}") | ||
| ReplicaLagWatcher.watch | ||
| rescue StandardError => e | ||
| Rails.logger.error("Failed to backfill VAT ID for subscription #{subscription.id}: #{e.message}") | ||
| end | ||
|
|
||
| Rails.logger.info("Backfilled VAT IDs for #{count} subscriptions") | ||
| count | ||
| end | ||
| end | ||
| end | ||
|
Contributor
Author
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. Adds |
| Original file line number | Diff line number | Diff line change |
|---|---|---|
| @@ -0,0 +1,7 @@ | ||
| # frozen_string_literal: true | ||
|
|
||
| class AddBusinessVatIdToSubscriptions < ActiveRecord::Migration[7.1] | ||
| def change | ||
| add_column :subscriptions, :business_vat_id, :string, limit: 191 | ||
| end | ||
| end |
Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
If VAT ID is validated during checkout, store it on subscription for future recurring charges.