stripe_model_callbacks 0.1.0 → 0.1.4

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (196) hide show
  1. checksums.yaml +4 -4
  2. data/README.md +22 -1
  3. data/app/models/stripe_model_callbacks/application_record.rb +17 -0
  4. data/app/services/stripe_model_callbacks/account/external_account/updated_service.rb +1 -1
  5. data/app/services/stripe_model_callbacks/attributes_assigner_service.rb +1 -1
  6. data/app/services/stripe_model_callbacks/base_service.rb +35 -3
  7. data/app/services/stripe_model_callbacks/charge/dispute_updated_service.rb +1 -1
  8. data/app/services/stripe_model_callbacks/charge/updated_service.rb +1 -1
  9. data/app/services/stripe_model_callbacks/configure_service.rb +52 -24
  10. data/app/services/stripe_model_callbacks/coupon/sync_all.rb +9 -0
  11. data/app/services/stripe_model_callbacks/coupon/updated_service.rb +1 -1
  12. data/app/services/stripe_model_callbacks/customer/bank_account/deleted_service.rb +1 -1
  13. data/app/services/stripe_model_callbacks/customer/deleted_service.rb +1 -1
  14. data/app/services/stripe_model_callbacks/customer/discount_updated_service.rb +1 -1
  15. data/app/services/stripe_model_callbacks/customer/source_updated_service.rb +1 -1
  16. data/app/services/stripe_model_callbacks/customer/subscription/updated_service.rb +1 -1
  17. data/app/services/stripe_model_callbacks/customer/updated_service.rb +1 -1
  18. data/app/services/stripe_model_callbacks/event_mocker_service.rb +1 -1
  19. data/app/services/stripe_model_callbacks/invoice/updated_service.rb +1 -1
  20. data/app/services/stripe_model_callbacks/invoice_item/updated_service.rb +1 -1
  21. data/app/services/stripe_model_callbacks/notifier_service.rb +1 -1
  22. data/app/services/stripe_model_callbacks/order/updated_service.rb +1 -1
  23. data/app/services/stripe_model_callbacks/payout/updated_service.rb +1 -1
  24. data/app/services/stripe_model_callbacks/plan/sync_all.rb +9 -0
  25. data/app/services/stripe_model_callbacks/plan/updated_service.rb +1 -1
  26. data/app/services/stripe_model_callbacks/price/updated_service.rb +14 -0
  27. data/app/services/stripe_model_callbacks/product/updated_service.rb +1 -1
  28. data/app/services/stripe_model_callbacks/recipient/updated_service.rb +1 -1
  29. data/app/services/stripe_model_callbacks/refund/updated_service.rb +1 -1
  30. data/app/services/stripe_model_callbacks/review/updated_service.rb +1 -1
  31. data/app/services/stripe_model_callbacks/sku/updated_service.rb +1 -1
  32. data/app/services/stripe_model_callbacks/source/updated_service.rb +1 -1
  33. data/app/services/stripe_model_callbacks/subscription/state_checker_service.rb +2 -2
  34. data/app/services/stripe_model_callbacks/subscription_schedule/updated_service.rb +46 -0
  35. data/app/services/stripe_model_callbacks/sync_everything.rb +8 -0
  36. data/app/services/stripe_model_callbacks/sync_from_stripe.rb +29 -0
  37. data/app/services/stripe_model_callbacks/tax_rate/updated_service.rb +27 -0
  38. data/app/services/stripe_model_callbacks/transfer/updated_service.rb +1 -1
  39. data/db/migrate/20200317160513_add_auto_advance_and_billing_reason_to_stripe_invoices.rb +6 -0
  40. data/db/migrate/20200317160602_add_status_and_status_transitions_to_stripe_invoices.rb +10 -0
  41. data/db/migrate/20200317180115_add_product_type_to_products.rb +5 -0
  42. data/db/migrate/20200317181224_rename_stripe_invoices_application_fee_to_application_fee_amount.rb +6 -0
  43. data/db/migrate/20200320105158_make_stripe_invoices_forgive_optional.rb +5 -0
  44. data/db/migrate/20200320114859_make_stripe_invoice_closed_optional.rb +5 -0
  45. data/db/migrate/20200323143634_add_amount_paid_and_remaining_and_invoice_url_and_pdf.rb +11 -0
  46. data/db/migrate/20200331074940_add_unit_label_to_stripe_products.rb +5 -0
  47. data/db/migrate/20200331075241_add_metered_info_to_stripe_plans.rb +9 -0
  48. data/db/migrate/20200513131105_create_stripe_subscription_schedules.rb +31 -0
  49. data/db/migrate/20200513131120_create_stripe_subscription_schedule_phases.rb +21 -0
  50. data/db/migrate/20200513131640_create_stripe_subscription_schedule_phase_plans.rb +13 -0
  51. data/db/migrate/20200514132247_add_stripe_id_uniq_to_stripe_invoices.rb +8 -0
  52. data/db/migrate/20200520152604_change_stripe_subscription_schedule_phase_id_to_bigint.rb +27 -0
  53. data/db/migrate/20200529144649_add_latest_invoice_id_to_stripe_subscription.rb +5 -0
  54. data/db/migrate/20201223173035_rename_stripe_subscriptions_start_to_start_date.rb +5 -0
  55. data/db/migrate/20201223202117_create_stripe_tax_rates.rb +15 -0
  56. data/db/migrate/20201224120534_create_stripe_subscription_default_tax_rates.rb +9 -0
  57. data/db/migrate/20201224122058_create_stripe_prices.rb +26 -0
  58. data/db/migrate/20201224123838_add_stripe_price_to_stripe_subscription_items.rb +6 -0
  59. data/db/migrate/20211121155313_change_invoice_billing_to_nullable.rb +5 -0
  60. data/db/migrate/20211121155732_rename_invoices_billing_to_deprecated_billing.rb +5 -0
  61. data/lib/stripe_model_callbacks/configuration.rb +1 -1
  62. data/lib/stripe_model_callbacks/factories/stripe_bank_accounts.rb +5 -0
  63. data/lib/stripe_model_callbacks/factories/stripe_cards.rb +7 -0
  64. data/lib/stripe_model_callbacks/factories/stripe_charges.rb +11 -0
  65. data/lib/stripe_model_callbacks/factories/stripe_coupons.rb +21 -0
  66. data/lib/stripe_model_callbacks/factories/stripe_customers.rb +17 -0
  67. data/lib/stripe_model_callbacks/factories/stripe_discounts.rb +6 -0
  68. data/lib/stripe_model_callbacks/factories/stripe_disputes.rb +7 -0
  69. data/lib/stripe_model_callbacks/factories/stripe_invoice_items.rb +11 -0
  70. data/lib/stripe_model_callbacks/factories/stripe_invoices.rb +16 -0
  71. data/lib/stripe_model_callbacks/factories/stripe_order_items.rb +8 -0
  72. data/lib/stripe_model_callbacks/factories/stripe_orders.rb +9 -0
  73. data/lib/stripe_model_callbacks/factories/stripe_payouts.rb +5 -0
  74. data/lib/stripe_model_callbacks/factories/stripe_plans.rb +30 -0
  75. data/lib/stripe_model_callbacks/factories/stripe_prices.rb +3 -0
  76. data/lib/stripe_model_callbacks/factories/stripe_products.rb +18 -0
  77. data/lib/stripe_model_callbacks/factories/stripe_recipients.rb +5 -0
  78. data/lib/stripe_model_callbacks/factories/stripe_refunds.rb +9 -0
  79. data/lib/stripe_model_callbacks/factories/stripe_reviews.rb +6 -0
  80. data/lib/stripe_model_callbacks/factories/stripe_skus.rb +7 -0
  81. data/lib/stripe_model_callbacks/factories/stripe_sources.rb +8 -0
  82. data/lib/stripe_model_callbacks/factories/stripe_subscription_default_tax_rates.rb +6 -0
  83. data/lib/stripe_model_callbacks/factories/stripe_subscription_items.rb +19 -0
  84. data/lib/stripe_model_callbacks/factories/stripe_subscription_schedule.rb.rb +5 -0
  85. data/lib/stripe_model_callbacks/factories/stripe_subscription_schedule_phase_plan.rb +5 -0
  86. data/lib/stripe_model_callbacks/factories/stripe_subscription_schedule_phases.rb +5 -0
  87. data/lib/stripe_model_callbacks/factories/stripe_subscriptions.rb +40 -0
  88. data/lib/stripe_model_callbacks/factories/stripe_tax_rates.rb +5 -0
  89. data/lib/stripe_model_callbacks/factories/stripe_transfers.rb +8 -0
  90. data/lib/stripe_model_callbacks/factory_bot_definitions.rb +1 -1
  91. data/lib/stripe_model_callbacks/fixtures/stripe_events/account/account.external_account.created.json +29 -0
  92. data/lib/stripe_model_callbacks/fixtures/stripe_events/account/account.external_account.deleted.json +29 -0
  93. data/lib/stripe_model_callbacks/fixtures/stripe_events/account/account.external_account.updated.json +31 -0
  94. data/lib/stripe_model_callbacks/fixtures/stripe_events/charge/charge.dispute.closed.json +65 -0
  95. data/lib/stripe_model_callbacks/fixtures/stripe_events/charge/charge.dispute.created.json +65 -0
  96. data/lib/stripe_model_callbacks/fixtures/stripe_events/charge/charge.dispute.funds_reinstated.json +65 -0
  97. data/lib/stripe_model_callbacks/fixtures/stripe_events/charge/charge.dispute.funds_withdrawn.json +65 -0
  98. data/lib/stripe_model_callbacks/fixtures/stripe_events/charge/charge.dispute.updated.json +96 -0
  99. data/lib/stripe_model_callbacks/fixtures/stripe_events/charge/charge.refund.updated.json +28 -0
  100. data/lib/stripe_model_callbacks/fixtures/stripe_events/charge/charge.refunded.json +98 -0
  101. data/lib/stripe_model_callbacks/fixtures/stripe_events/coupon/coupon.created.json +29 -0
  102. data/lib/stripe_model_callbacks/fixtures/stripe_events/coupon/coupon.deleted.json +29 -0
  103. data/lib/stripe_model_callbacks/fixtures/stripe_events/coupon/coupon.updated.json +31 -0
  104. data/lib/stripe_model_callbacks/fixtures/stripe_events/customer/customer.bank_account.deleted.json +29 -0
  105. data/lib/stripe_model_callbacks/fixtures/stripe_events/customer/customer.created.json +36 -0
  106. data/lib/stripe_model_callbacks/fixtures/stripe_events/customer/customer.deleted.json +47 -0
  107. data/lib/stripe_model_callbacks/fixtures/stripe_events/customer/customer.discount.created.json +36 -0
  108. data/lib/stripe_model_callbacks/fixtures/stripe_events/customer/customer.discount.deleted.json +36 -0
  109. data/lib/stripe_model_callbacks/fixtures/stripe_events/customer/customer.discount.updated.json +55 -0
  110. data/lib/stripe_model_callbacks/fixtures/stripe_events/customer/customer.source.created.card.json +80 -0
  111. data/lib/stripe_model_callbacks/fixtures/stripe_events/customer/customer.source.created.json +53 -0
  112. data/lib/stripe_model_callbacks/fixtures/stripe_events/customer/customer.source.deleted.json +53 -0
  113. data/lib/stripe_model_callbacks/fixtures/stripe_events/customer/customer.source.expiring.json +53 -0
  114. data/lib/stripe_model_callbacks/fixtures/stripe_events/customer/customer.source.updated.json +56 -0
  115. data/lib/stripe_model_callbacks/fixtures/stripe_events/customer/customer.subscription.created.2020-12-24.json +112 -0
  116. data/lib/stripe_model_callbacks/fixtures/stripe_events/customer/customer.subscription.created.json +84 -0
  117. data/lib/stripe_model_callbacks/fixtures/stripe_events/customer/customer.subscription.deleted.json +83 -0
  118. data/lib/stripe_model_callbacks/fixtures/stripe_events/customer/customer.subscription.trial_will_end.json +88 -0
  119. data/lib/stripe_model_callbacks/fixtures/stripe_events/customer/customer.subscription.updated.json +100 -0
  120. data/lib/stripe_model_callbacks/fixtures/stripe_events/customer/customer.updated.json +50 -0
  121. data/lib/stripe_model_callbacks/fixtures/stripe_events/invoice/invoice.created.json +135 -0
  122. data/lib/stripe_model_callbacks/fixtures/stripe_events/invoice/invoice.payment_failed.json +100 -0
  123. data/lib/stripe_model_callbacks/fixtures/stripe_events/invoice/invoice.payment_succeeded.json +207 -0
  124. data/lib/stripe_model_callbacks/fixtures/stripe_events/invoice/invoice.sent.json +100 -0
  125. data/lib/stripe_model_callbacks/fixtures/stripe_events/invoice/invoice.upcoming.json +100 -0
  126. data/lib/stripe_model_callbacks/fixtures/stripe_events/invoice/invoice.updated.json +105 -0
  127. data/lib/stripe_model_callbacks/fixtures/stripe_events/invoice/invoice.voided.json +152 -0
  128. data/lib/stripe_model_callbacks/fixtures/stripe_events/invoiceitem/invoiceitem.created.json +34 -0
  129. data/lib/stripe_model_callbacks/fixtures/stripe_events/order/order.created.json +72 -0
  130. data/lib/stripe_model_callbacks/fixtures/stripe_events/order/order.updated.json +74 -0
  131. data/lib/stripe_model_callbacks/fixtures/stripe_events/payout/payout.canceled.json +35 -0
  132. data/lib/stripe_model_callbacks/fixtures/stripe_events/payout/payout.created.json +35 -0
  133. data/lib/stripe_model_callbacks/fixtures/stripe_events/payout/payout.failed.json +35 -0
  134. data/lib/stripe_model_callbacks/fixtures/stripe_events/payout/payout.paid.json +35 -0
  135. data/lib/stripe_model_callbacks/fixtures/stripe_events/payout/payout.updated.json +37 -0
  136. data/lib/stripe_model_callbacks/fixtures/stripe_events/plan/plan.created.json +32 -0
  137. data/lib/stripe_model_callbacks/fixtures/stripe_events/plan/plan.deleted.json +27 -0
  138. data/lib/stripe_model_callbacks/fixtures/stripe_events/plan/plan.updated.json +30 -0
  139. data/lib/stripe_model_callbacks/fixtures/stripe_events/price/price.created.json +37 -0
  140. data/lib/stripe_model_callbacks/fixtures/stripe_events/price/price.deleted.json +37 -0
  141. data/lib/stripe_model_callbacks/fixtures/stripe_events/price/price.updated.json +40 -0
  142. data/lib/stripe_model_callbacks/fixtures/stripe_events/product/product.created.json +49 -0
  143. data/lib/stripe_model_callbacks/fixtures/stripe_events/product/product.deleted.json +48 -0
  144. data/lib/stripe_model_callbacks/fixtures/stripe_events/product/product.updated.json +50 -0
  145. data/lib/stripe_model_callbacks/fixtures/stripe_events/recipient/recipient.created.json +37 -0
  146. data/lib/stripe_model_callbacks/fixtures/stripe_events/recipient/recipient.deleted.json +37 -0
  147. data/lib/stripe_model_callbacks/fixtures/stripe_events/recipient/recipient.updated.json +39 -0
  148. data/lib/stripe_model_callbacks/fixtures/stripe_events/review/review.closed.json +21 -0
  149. data/lib/stripe_model_callbacks/fixtures/stripe_events/review/review.opened.json +21 -0
  150. data/lib/stripe_model_callbacks/fixtures/stripe_events/sku/sku.created.json +36 -0
  151. data/lib/stripe_model_callbacks/fixtures/stripe_events/sku/sku.deleted.json +36 -0
  152. data/lib/stripe_model_callbacks/fixtures/stripe_events/sku/sku.updated.json +38 -0
  153. data/lib/stripe_model_callbacks/fixtures/stripe_events/source/source.canceled.json +53 -0
  154. data/lib/stripe_model_callbacks/fixtures/stripe_events/source/source.chargeable.json +53 -0
  155. data/lib/stripe_model_callbacks/fixtures/stripe_events/source/source.failed.json +53 -0
  156. data/lib/stripe_model_callbacks/fixtures/stripe_events/source/source.mandate_notification.json +53 -0
  157. data/lib/stripe_model_callbacks/fixtures/stripe_events/source/source.transaction_created.json +21 -0
  158. data/lib/stripe_model_callbacks/fixtures/stripe_events/subscription_schedule/subscription_schedule.canceled.json +81 -0
  159. data/lib/stripe_model_callbacks/fixtures/stripe_events/subscription_schedule/subscription_schedule.created.json +77 -0
  160. data/lib/stripe_model_callbacks/fixtures/stripe_events/subscription_schedule/subscription_schedule.updated.json +87 -0
  161. data/lib/stripe_model_callbacks/fixtures/stripe_events/tax_rate/tax_rate.created.json +26 -0
  162. data/lib/stripe_model_callbacks/fixtures/stripe_events/tax_rate/tax_rate.updated.json +29 -0
  163. data/lib/stripe_model_callbacks/fixtures/stripe_events/transfer/transfer.created.json +41 -0
  164. data/lib/stripe_model_callbacks/fixtures/stripe_events/transfer/transfer.reversed.json +40 -0
  165. data/lib/stripe_model_callbacks/fixtures/stripe_events/transfer/transfer.updated.json +44 -0
  166. data/lib/stripe_model_callbacks/models/stripe_bank_account.rb +1 -0
  167. data/lib/stripe_model_callbacks/models/stripe_card.rb +2 -1
  168. data/lib/stripe_model_callbacks/models/stripe_charge.rb +3 -0
  169. data/lib/stripe_model_callbacks/models/stripe_coupon.rb +1 -0
  170. data/lib/stripe_model_callbacks/models/stripe_customer.rb +4 -2
  171. data/lib/stripe_model_callbacks/models/stripe_discount.rb +10 -3
  172. data/lib/stripe_model_callbacks/models/stripe_dispute.rb +1 -0
  173. data/lib/stripe_model_callbacks/models/stripe_invoice.rb +62 -7
  174. data/lib/stripe_model_callbacks/models/stripe_invoice_item.rb +2 -0
  175. data/lib/stripe_model_callbacks/models/stripe_order.rb +1 -0
  176. data/lib/stripe_model_callbacks/models/stripe_order_item.rb +1 -0
  177. data/lib/stripe_model_callbacks/models/stripe_payout.rb +2 -1
  178. data/lib/stripe_model_callbacks/models/stripe_plan.rb +4 -1
  179. data/lib/stripe_model_callbacks/models/stripe_price.rb +27 -0
  180. data/lib/stripe_model_callbacks/models/stripe_product.rb +17 -7
  181. data/lib/stripe_model_callbacks/models/stripe_recipient.rb +1 -0
  182. data/lib/stripe_model_callbacks/models/stripe_refund.rb +1 -0
  183. data/lib/stripe_model_callbacks/models/stripe_review.rb +1 -0
  184. data/lib/stripe_model_callbacks/models/stripe_sku.rb +13 -6
  185. data/lib/stripe_model_callbacks/models/stripe_source.rb +4 -2
  186. data/lib/stripe_model_callbacks/models/stripe_subscription.rb +56 -6
  187. data/lib/stripe_model_callbacks/models/stripe_subscription_default_tax_rate.rb +4 -0
  188. data/lib/stripe_model_callbacks/models/stripe_subscription_item.rb +19 -1
  189. data/lib/stripe_model_callbacks/models/stripe_subscription_schedule.rb +94 -0
  190. data/lib/stripe_model_callbacks/models/stripe_subscription_schedule_phase.rb +67 -0
  191. data/lib/stripe_model_callbacks/models/stripe_subscription_schedule_phase_plan.rb +37 -0
  192. data/lib/stripe_model_callbacks/models/stripe_tax_rate.rb +22 -0
  193. data/lib/stripe_model_callbacks/models/stripe_transfer.rb +1 -0
  194. data/lib/stripe_model_callbacks/version.rb +1 -1
  195. data/lib/stripe_model_callbacks.rb +1 -0
  196. metadata +163 -11
@@ -1,12 +1,17 @@
1
1
  class StripeInvoice < StripeModelCallbacks::ApplicationRecord
2
+ belongs_to :stripe_charge, optional: true, primary_key: "stripe_id"
2
3
  belongs_to :stripe_customer, optional: true, primary_key: "stripe_id"
3
4
  belongs_to :stripe_discount, optional: true
4
5
  belongs_to :stripe_subscription, optional: true, primary_key: "stripe_id"
5
6
 
6
7
  has_many :stripe_invoice_items, autosave: true, primary_key: "stripe_id"
7
8
 
9
+ validates :stripe_id, uniqueness: true
10
+
8
11
  monetize :amount_due_cents, allow_nil: true
9
- monetize :application_fee_cents, allow_nil: true
12
+ monetize :amount_paid_cents, allow_nil: true
13
+ monetize :amount_remaining_cents, allow_nil: true
14
+ monetize :application_fee_amount_cents, allow_nil: true
10
15
  monetize :subtotal_cents, allow_nil: true
11
16
  monetize :tax_cents, allow_nil: true
12
17
  monetize :total_cents, allow_nil: true
@@ -16,6 +21,7 @@ class StripeInvoice < StripeModelCallbacks::ApplicationRecord
16
21
  end
17
22
 
18
23
  def assign_from_stripe(object)
24
+ check_object_is_stripe_class(object)
19
25
  assign_attributes(
20
26
  stripe_charge_id: object.charge,
21
27
  stripe_customer_id: object.customer,
@@ -25,15 +31,24 @@ class StripeInvoice < StripeModelCallbacks::ApplicationRecord
25
31
  period_end: Time.zone.at(object.period_end)
26
32
  )
27
33
 
34
+ assign_closed(object)
28
35
  assign_created(object)
36
+
29
37
  assign_amounts(object)
38
+ assign_discount_item(object)
39
+ assign_tax(object)
40
+
41
+ assign_forgiven(object)
42
+ assign_status_transitions(object)
30
43
 
31
44
  StripeModelCallbacks::AttributesAssignerService.execute!(
32
45
  model: self, stripe_model: object,
33
46
  attributes: %w[
34
- attempted attempt_count billing closed currency description forgiven id livemode
35
- ending_balance forgiven next_payment_attempt number paid receipt_number
36
- starting_balance statement_descriptor tax_percent
47
+ attempted attempt_count auto_advance billing_reason
48
+ collection_method currency description ending_balance hosted_invoice_url
49
+ id invoice_pdf livemode next_payment_attempt number
50
+ paid receipt_number starting_balance statement_descriptor
51
+ status tax_percent
37
52
  ]
38
53
  )
39
54
 
@@ -45,14 +60,23 @@ private
45
60
  def assign_amounts(object)
46
61
  assign_attributes(
47
62
  amount_due: Money.new(object.amount_due, object.currency),
48
- application_fee: object.application_fee ? Money.new(object.application_fee, object.currency) : nil,
49
- stripe_discount_id: stripe_discount_id_from_object(object),
63
+ amount_paid: Money.new(object.amount_paid, object.currency),
64
+ amount_remaining: Money.new(object.amount_remaining, object.currency),
65
+ application_fee_amount: object.application_fee_amount ? Money.new(object.application_fee_amount, object.currency) : nil,
50
66
  subtotal: Money.new(object.subtotal, object.currency),
51
- tax: object.tax ? Money.new(object.tax, object.currency) : nil,
52
67
  total: object.total ? Money.new(object.total, object.currency) : nil
53
68
  )
54
69
  end
55
70
 
71
+ def assign_closed(object)
72
+ # The date-field was changed to auto_advance on 2018-11-08
73
+ if object.respond_to?(:closed)
74
+ self.closed = object.closed
75
+ else
76
+ self.closed = object.auto_advance == false
77
+ end
78
+ end
79
+
56
80
  def assign_created(object)
57
81
  # The date-field was renamed to created on 2019-03-14
58
82
  if object.respond_to?(:date)
@@ -62,6 +86,19 @@ private
62
86
  end
63
87
  end
64
88
 
89
+ def assign_discount_item(object)
90
+ self.stripe_discount_id = stripe_discount_id_from_object(object)
91
+ end
92
+
93
+ def assign_forgiven(object)
94
+ # The date-field was changed 2018-11-08
95
+ if object.respond_to?(:forgiven)
96
+ self.forgiven = object.forgiven
97
+ else
98
+ self.forgiven = object.status == "uncollectible"
99
+ end
100
+ end
101
+
65
102
  def assign_invoice_items(object)
66
103
  object.lines.each do |item|
67
104
  # Has to be found this way to actually update the values
@@ -77,6 +114,24 @@ private
77
114
  end
78
115
  end
79
116
 
117
+ def assign_status_transitions(object)
118
+ return unless object.respond_to?(:status_transitions)
119
+
120
+ transition_dates = {}
121
+ %i[finalized_at marked_uncollectible_at paid_at voided_at].each do |date_attribute|
122
+ date_value = object.status_transitions.__send__(date_attribute)
123
+ transition_dates[date_attribute] = Time.zone.at(date_value) if date_value.present?
124
+ end
125
+
126
+ assign_attributes(transition_dates) if transition_dates.any?
127
+ end
128
+
129
+ def assign_tax(object)
130
+ return unless object.tax
131
+
132
+ self.tax = Money.new(object.tax, object.currency)
133
+ end
134
+
80
135
  def stripe_discount_id_from_object(object)
81
136
  return nil unless object.discount
82
137
 
@@ -1,6 +1,7 @@
1
1
  class StripeInvoiceItem < StripeModelCallbacks::ApplicationRecord
2
2
  belongs_to :stripe_customer, optional: true, primary_key: "stripe_id"
3
3
  belongs_to :stripe_invoice, optional: true, primary_key: "stripe_id"
4
+ belongs_to :stripe_subscription, optional: true, primary_key: "stripe_id"
4
5
  belongs_to :stripe_subscription_item, optional: true, primary_key: "stripe_id"
5
6
  belongs_to :stripe_plan, optional: true, primary_key: "stripe_id"
6
7
 
@@ -11,6 +12,7 @@ class StripeInvoiceItem < StripeModelCallbacks::ApplicationRecord
11
12
  end
12
13
 
13
14
  def assign_from_stripe(object)
15
+ check_object_is_stripe_class(object, [Stripe::InvoiceItem, Stripe::InvoiceLineItem])
14
16
  assign_attributes(
15
17
  amount: Money.new(object.amount, object.currency),
16
18
  stripe_customer_id: object.try(:customer),
@@ -12,6 +12,7 @@ class StripeOrder < StripeModelCallbacks::ApplicationRecord
12
12
  end
13
13
 
14
14
  def assign_from_stripe(object)
15
+ check_object_is_stripe_class(object)
15
16
  assign_attributes(
16
17
  stripe_charge_id: object.charge,
17
18
  created: Time.zone.at(object.created),
@@ -8,6 +8,7 @@ class StripeOrderItem < StripeModelCallbacks::ApplicationRecord
8
8
  end
9
9
 
10
10
  def assign_from_stripe(object)
11
+ check_object_is_stripe_class(object)
11
12
  assign_attributes(
12
13
  amount: Money.new(object.amount, object.currency),
13
14
  currency: object.currency,
@@ -2,10 +2,11 @@ class StripePayout < StripeModelCallbacks::ApplicationRecord
2
2
  monetize :amount_cents, allow_nil: true
3
3
 
4
4
  def self.stripe_class
5
- Stripe::Subscription
5
+ Stripe::Payout
6
6
  end
7
7
 
8
8
  def assign_from_stripe(object)
9
+ check_object_is_stripe_class(object)
9
10
  assign_attributes(
10
11
  amount: Money.new(object.amount, object.currency),
11
12
  arrival_date: Time.zone.at(object.arrival_date),
@@ -14,14 +14,17 @@ class StripePlan < StripeModelCallbacks::ApplicationRecord
14
14
  end
15
15
 
16
16
  def assign_from_stripe(object)
17
+ check_object_is_stripe_class(object)
18
+ self.active = object.active == true if object.respond_to?(:active)
17
19
  assign_attributes(amount: Money.new(object.amount, object.currency))
18
20
  self.stripe_product_id = object.product if object.respond_to?(:product)
19
21
 
20
22
  StripeModelCallbacks::AttributesAssignerService.execute!(
21
23
  model: self, stripe_model: object,
22
24
  attributes: %w[
25
+ aggregate_usage amount_decimal billing_scheme
23
26
  created currency id interval interval_count livemode metadata nickname statement_descriptor
24
- trial_period_days
27
+ trial_period_days usage_type
25
28
  ]
26
29
  )
27
30
  end
@@ -0,0 +1,27 @@
1
+ class StripePrice < StripeModelCallbacks::ApplicationRecord
2
+ def self.stripe_class
3
+ Stripe::Price
4
+ end
5
+
6
+ def assign_from_stripe(object)
7
+ check_object_is_stripe_class(object)
8
+
9
+ assign_attributes(
10
+ stripe_id: object.id,
11
+ stripe_product_id: object.product,
12
+ recurring_aggregate_usage: object.recurring&.aggregate_usage,
13
+ recurring_interval: object.recurring&.interval,
14
+ recurring_interval_count: object.recurring&.interval_count,
15
+ recurring_usage_type: object.recurring&.usage_type,
16
+ transform_quantity_divide_by: object.transform_quantity&.divide_by,
17
+ transform_quantity_round: object.transform_quantity&.round
18
+ )
19
+
20
+ StripeModelCallbacks::AttributesAssignerService.execute!(
21
+ model: self, stripe_model: object,
22
+ attributes: %w[
23
+ active billing_scheme created currency lookup_key metadata nickname tiers_mode unit_amount
24
+ ]
25
+ )
26
+ end
27
+ end
@@ -1,26 +1,36 @@
1
1
  class StripeProduct < StripeModelCallbacks::ApplicationRecord
2
2
  has_many :stripe_plans, primary_key: "stripe_id"
3
+ has_many :stripe_subscriptions, through: :stripe_plans
3
4
 
4
5
  def self.stripe_class
5
6
  Stripe::Subscription
6
7
  end
7
8
 
8
9
  def assign_from_stripe(object)
10
+ check_object_is_stripe_class(object, [Stripe::Product, Stripe::Subscription])
9
11
  assign_attributes(
10
12
  active: object.active == true,
11
- updated: Time.zone.at(object.updated),
13
+ product_type: object.type,
12
14
  stripe_attributes: JSON.generate(object.attributes),
13
- package_dimensions_height: object.package_dimensions&.height,
14
- package_dimensions_length: object.package_dimensions&.length,
15
- package_dimensions_weight: object.package_dimensions&.weight,
16
- package_dimensions_width: object.package_dimensions&.width,
17
- shippable: object.shippable == true
15
+ updated: Time.zone.at(object.updated)
18
16
  )
19
17
 
18
+ if object.respond_to?(:package_dimensions)
19
+ assign_attributes(
20
+ package_dimensions_height: object.package_dimensions&.height,
21
+ package_dimensions_length: object.package_dimensions&.length,
22
+ package_dimensions_weight: object.package_dimensions&.weight,
23
+ package_dimensions_width: object.package_dimensions&.width
24
+ )
25
+ end
26
+
27
+ assign_attributes(shippable: object.shippable == true) if object.respond_to?(:shippable)
28
+
20
29
  StripeModelCallbacks::AttributesAssignerService.execute!(
21
30
  model: self, stripe_model: object,
22
31
  attributes: %w[
23
- caption created description id livemode name metadata statement_descriptor
32
+ caption created description id livemode
33
+ name metadata statement_descriptor unit_label
24
34
  ]
25
35
  )
26
36
  end
@@ -4,6 +4,7 @@ class StripeRecipient < StripeModelCallbacks::ApplicationRecord
4
4
  end
5
5
 
6
6
  def assign_from_stripe(object)
7
+ check_object_is_stripe_class(object)
7
8
  assign_attributes(
8
9
  stripe_type: object.type
9
10
  )
@@ -8,6 +8,7 @@ class StripeRefund < StripeModelCallbacks::ApplicationRecord
8
8
  end
9
9
 
10
10
  def assign_from_stripe(object)
11
+ check_object_is_stripe_class(object)
11
12
  assign_attributes(
12
13
  amount: Money.new(object.amount, object.currency),
13
14
  stripe_charge_id: object.charge,
@@ -6,6 +6,7 @@ class StripeReview < StripeModelCallbacks::ApplicationRecord
6
6
  end
7
7
 
8
8
  def assign_from_stripe(object)
9
+ check_object_is_stripe_class(object)
9
10
  assign_attributes(
10
11
  stripe_charge_id: object.charge
11
12
  )
@@ -2,10 +2,22 @@ class StripeSku < StripeModelCallbacks::ApplicationRecord
2
2
  monetize :price_cents
3
3
 
4
4
  def self.stripe_class
5
- Stripe::Sku
5
+ Stripe::SKU
6
6
  end
7
7
 
8
8
  def assign_from_stripe(object)
9
+ check_object_is_stripe_class(object)
10
+ assign_base_attributes(object)
11
+
12
+ StripeModelCallbacks::AttributesAssignerService.execute!(
13
+ model: self, stripe_model: object,
14
+ attributes: %w[currency]
15
+ )
16
+ end
17
+
18
+ private
19
+
20
+ def assign_base_attributes(object)
9
21
  assign_attributes(
10
22
  active: object.active == true,
11
23
  created: Time.zone.at(object.created),
@@ -19,10 +31,5 @@ class StripeSku < StripeModelCallbacks::ApplicationRecord
19
31
  price: Money.new(object.price, object.currency),
20
32
  stripe_product_id: object.product
21
33
  )
22
-
23
- StripeModelCallbacks::AttributesAssignerService.execute!(
24
- model: self, stripe_model: object,
25
- attributes: %w[currency]
26
- )
27
34
  end
28
35
  end
@@ -9,6 +9,8 @@ class StripeSource < StripeModelCallbacks::ApplicationRecord
9
9
  end
10
10
 
11
11
  def assign_from_stripe(object)
12
+ check_object_is_stripe_class(object)
13
+
12
14
  self.stripe_type = object.type
13
15
  self.amount = Money.new(object.amount, object.currency) if object.respond_to?(:amount)
14
16
 
@@ -28,7 +30,7 @@ class StripeSource < StripeModelCallbacks::ApplicationRecord
28
30
 
29
31
  private
30
32
 
31
- def assign_owner(object)
33
+ def assign_owner(object) # rubocop:disable Metrics/AbcSize
32
34
  assign_attributes(
33
35
  owner_address_city: object.owner.address&.city,
34
36
  owner_address_country: object.owner.address&.country,
@@ -42,7 +44,7 @@ private
42
44
  )
43
45
  end
44
46
 
45
- def assign_owner_verified(object)
47
+ def assign_owner_verified(object) # rubocop:disable Metrics/AbcSize
46
48
  assign_attributes(
47
49
  owner_verified_address_city: object.owner.verified_address&.city,
48
50
  owner_verified_address_country: object.owner.verified_address&.country,
@@ -4,7 +4,11 @@ class StripeSubscription < StripeModelCallbacks::ApplicationRecord
4
4
  belongs_to :stripe_plan, optional: true, primary_key: "stripe_id"
5
5
  has_many :stripe_invoices, primary_key: "stripe_id"
6
6
  has_many :stripe_discounts, primary_key: "stripe_id"
7
+ has_many :stripe_subscription_default_tax_rates, autosave: true, dependent: :destroy
7
8
  has_many :stripe_subscription_items, autosave: true, primary_key: "stripe_id"
9
+ has_many :stripe_subscription_schedules, primary_key: "stripe_id"
10
+ has_many :stripe_plans, through: :stripe_subscription_items
11
+ has_many :default_tax_rates, source: :stripe_tax_rate, through: :stripe_subscription_default_tax_rates
8
12
 
9
13
  STATES = %w[trialing active past_due canceled unpaid].freeze
10
14
 
@@ -18,13 +22,16 @@ class StripeSubscription < StripeModelCallbacks::ApplicationRecord
18
22
  end
19
23
 
20
24
  def assign_from_stripe(object)
25
+ check_object_is_stripe_class(object)
21
26
  assign_attributes(
22
27
  canceled_at: object.canceled_at ? Time.zone.at(object.canceled_at) : nil,
23
- stripe_customer_id: object.customer,
24
28
  ended_at: object.ended_at ? Time.zone.at(object.ended_at) : nil,
25
- stripe_plan_id: object.plan&.id
29
+ latest_stripe_invoice_id: latest_invoice_id(object),
30
+ stripe_customer_id: object.customer,
31
+ stripe_plan_id: object.respond_to?(:plan) ? object.plan&.id : nil
26
32
  )
27
33
 
34
+ assign_default_tax_rates(object)
28
35
  assign_discount(object)
29
36
  assign_items(object)
30
37
  assign_periods(object)
@@ -63,6 +70,32 @@ class StripeSubscription < StripeModelCallbacks::ApplicationRecord
63
70
 
64
71
  private
65
72
 
73
+ def assign_default_tax_rates(object)
74
+ return unless object.try(:default_tax_rates)
75
+
76
+ found_ids = []
77
+
78
+ object.default_tax_rates.each do |default_tax_rate|
79
+ tax_rate = StripeModelCallbacks::TaxRate::UpdatedService.execute!(object: default_tax_rate)
80
+
81
+ if new_record?
82
+ stripe_subscription_default_tax_rates.build(stripe_subscription_id: object.id, stripe_tax_rate_id: tax_rate.id)
83
+ else
84
+ default_tax_rate = StripeSubscriptionDefaultTaxRate.find_by(stripe_subscription_id: object.id, stripe_tax_rate_id: tax_rate.id)
85
+ stripe_subscription_default_tax_rates.build(stripe_subscription_id: object.id, stripe_tax_rate_id: tax_rate.id) unless default_tax_rate
86
+ found_ids << default_tax_rate.id if default_tax_rate
87
+ end
88
+ end
89
+
90
+ clean_up_default_tax_rates_not_found(found_ids) if persisted?
91
+ end
92
+
93
+ def clean_up_default_tax_rates_not_found(found_ids)
94
+ stripe_subscription_default_tax_rates.select(&:persisted?).each do |subscription_default_tax_rate|
95
+ subscription_default_tax_rate.mark_for_destruction if found_ids.exclude?(subscription_default_tax_rate.stripe_tax_rate_id)
96
+ end
97
+ end
98
+
66
99
  def assign_discount(object)
67
100
  return if object.discount.blank?
68
101
 
@@ -80,10 +113,16 @@ private
80
113
  end
81
114
 
82
115
  def assign_periods(object)
116
+ start_date = if object.respond_to?(:start_date)
117
+ object.start_date
118
+ else
119
+ object.start
120
+ end
121
+
83
122
  assign_attributes(
84
123
  current_period_start: Time.zone.at(object.current_period_start),
85
124
  current_period_end: Time.zone.at(object.current_period_end),
86
- start: Time.zone.at(object.start),
125
+ start_date: Time.zone.at(start_date),
87
126
  trial_start: object.trial_start ? Time.zone.at(object.trial_start) : nil,
88
127
  trial_end: object.trial_end ? Time.zone.at(object.trial_end) : nil
89
128
  )
@@ -91,11 +130,22 @@ private
91
130
 
92
131
  def find_item_by_stripe_item(item)
93
132
  stripe_subscription_items.find do |sub_item|
94
- if item.plan.is_a?(String)
95
- sub_item.stripe_plan_id == item.plan
133
+ if item.try(:plan)
134
+ if item.plan.is_a?(String)
135
+ sub_item.stripe_plan_id == item.plan
136
+ else
137
+ sub_item.stripe_plan_id == item.plan.id
138
+ end
96
139
  else
97
- sub_item.stripe_plan_id == item.plan.id
140
+ sub_item.stripe_price_id == item.price.id
98
141
  end
99
142
  end
100
143
  end
144
+
145
+ def latest_invoice_id(object)
146
+ return unless object.respond_to?(:latest_invoice)
147
+ return object.latest_invoice if object.latest_invoice.is_a?(String)
148
+
149
+ object.latest_invoice&.id
150
+ end
101
151
  end
@@ -0,0 +1,4 @@
1
+ class StripeSubscriptionDefaultTaxRate < StripeModelCallbacks::ApplicationRecord
2
+ belongs_to :stripe_subscription
3
+ belongs_to :stripe_tax_rate
4
+ end
@@ -1,5 +1,6 @@
1
1
  class StripeSubscriptionItem < StripeModelCallbacks::ApplicationRecord
2
2
  belongs_to :stripe_plan, optional: true, primary_key: "stripe_id"
3
+ belongs_to :stripe_price, optional: true, primary_key: "stripe_id"
3
4
  belongs_to :stripe_subscription, optional: true, primary_key: "stripe_id"
4
5
 
5
6
  has_many :stripe_invoice_items, primary_key: "stripe_id"
@@ -9,8 +10,11 @@ class StripeSubscriptionItem < StripeModelCallbacks::ApplicationRecord
9
10
  end
10
11
 
11
12
  def assign_from_stripe(object)
13
+ check_object_is_stripe_class(object)
12
14
  self.stripe_subscription_id = object.subscription if object.respond_to?(:subscription)
13
- self.stripe_plan_id = object.plan.id if object.plan.respond_to?(:id)
15
+ self.stripe_plan_id = object.plan.id if object.try(:plan).respond_to?(:id)
16
+
17
+ assign_price_from_stripe(object)
14
18
 
15
19
  StripeModelCallbacks::AttributesAssignerService.execute!(
16
20
  model: self, stripe_model: object,
@@ -33,4 +37,18 @@ class StripeSubscriptionItem < StripeModelCallbacks::ApplicationRecord
33
37
  stripe_subscription.reload_from_stripe!
34
38
  nil
35
39
  end
40
+
41
+ private
42
+
43
+ def assign_price_from_stripe(object)
44
+ # Older versions doesn't support price
45
+ return unless object.try(:price).respond_to?(:id)
46
+
47
+ # Make sure price is created
48
+ price = StripePrice.find_by(stripe_id: object.price.id)
49
+ StripePrice.create_from_stripe!(object.price) unless price
50
+
51
+ # Set stripe ID on the subscription item
52
+ self.stripe_price_id = object.price.id
53
+ end
36
54
  end
@@ -0,0 +1,94 @@
1
+ class StripeSubscriptionSchedule < StripeModelCallbacks::ApplicationRecord
2
+ MATCHING_STRIPE_ATTRIBUTES = %w[
3
+ billing created collection_method
4
+ default_payment_method default_source
5
+ end_behavior id metadata livemode
6
+ renewal_behavior renewal_interval
7
+ status
8
+ ].freeze
9
+ private_constant :MATCHING_STRIPE_ATTRIBUTES
10
+
11
+ belongs_to :stripe_customer, optional: true, primary_key: "stripe_id"
12
+ belongs_to :stripe_subscription, optional: true, primary_key: "stripe_id"
13
+
14
+ has_many :stripe_subscription_schedule_phases, primary_key: "stripe_id", dependent: :destroy
15
+
16
+ def self.stripe_class
17
+ Stripe::SubscriptionSchedule
18
+ end
19
+
20
+ def assign_from_stripe(object)
21
+ check_object_is_stripe_class(object)
22
+ assign_attributes(
23
+ released_stripe_subscription_id: object.released_subscription,
24
+ stripe_customer_id: object.customer,
25
+ stripe_subscription_id: object.subscription
26
+ )
27
+
28
+ assign_billing_thresholds(object)
29
+ assign_current_phase(object)
30
+ assign_invoice_settings(object)
31
+ assign_timestamps(object)
32
+
33
+ StripeModelCallbacks::AttributesAssignerService.execute!(
34
+ model: self,
35
+ stripe_model: object,
36
+ attributes: MATCHING_STRIPE_ATTRIBUTES
37
+ )
38
+
39
+ assign_subscription_schedule_phases(object)
40
+ end
41
+
42
+ def cancel_on_stripe
43
+ to_stripe.cancel
44
+ update!(canceled_at: Time.zone.now) if respond_to?(:canceled_at)
45
+ reload_from_stripe!
46
+ true
47
+ end
48
+
49
+ def cancel_on_stripe!
50
+ raise ActiveRecord::RecordInvalid, self unless cancel_on_stripe
51
+ end
52
+
53
+ private
54
+
55
+ def assign_billing_thresholds(object)
56
+ billing_thresholds = object.billing_thresholds
57
+
58
+ self.billing_thresholds_amount_gte = billing_thresholds&.amount_gte
59
+ self.billing_thresholds_reset_billing_cycle_anchor = billing_thresholds&.reset_billing_cycle_anchor
60
+ end
61
+
62
+ def assign_current_phase(object)
63
+ current_phase = object.current_phase
64
+
65
+ start_date = current_phase&.start_date
66
+ self.current_phase_start_date = Time.zone.at(start_date) if start_date
67
+
68
+ end_date = current_phase&.end_date
69
+ self.current_phase_end_date = Time.zone.at(end_date) if end_date
70
+ end
71
+
72
+ def assign_invoice_settings(object)
73
+ self.invoice_settings_days_until_due = object.invoice_settings&.days_until_due
74
+ end
75
+
76
+ def assign_timestamps(object)
77
+ %i[canceled_at completed_at released_at].each do |timestamp|
78
+ object_timestamp = object.__send__(timestamp)
79
+ __send__("#{timestamp}=", Time.zone.at(object_timestamp)) if object_timestamp
80
+ end
81
+ end
82
+
83
+ def assign_subscription_schedule_phases(object)
84
+ self.stripe_subscription_schedule_phases = new_stripe_subscription_schedule_phases(object)
85
+ end
86
+
87
+ def new_stripe_subscription_schedule_phases(object)
88
+ @new_stripe_subscription_schedule_phases ||= object.phases.collect do |phase|
89
+ subscription_schedule_phase = StripeSubscriptionSchedulePhase.new(stripe_subscription_schedule: self)
90
+ subscription_schedule_phase.assign_from_stripe(phase)
91
+ subscription_schedule_phase
92
+ end
93
+ end
94
+ end
@@ -0,0 +1,67 @@
1
+ class StripeSubscriptionSchedulePhase < StripeModelCallbacks::ApplicationRecord
2
+ MATCHING_STRIPE_ATTRIBUTES = %w[
3
+ application_fee_percent
4
+ collection_method
5
+ default_payment_method
6
+ prorate
7
+ proration_behavior
8
+ ].freeze
9
+ private_constant :MATCHING_STRIPE_ATTRIBUTES
10
+
11
+ belongs_to :stripe_subscription_schedule, primary_key: "stripe_id"
12
+
13
+ has_many :stripe_subscription_schedule_phase_plans, dependent: :destroy
14
+
15
+ def self.stripe_class
16
+ Stripe::SubscriptionSchedulePhase
17
+ end
18
+
19
+ def assign_from_stripe(object)
20
+ check_object_is_stripe_class(object)
21
+ StripeModelCallbacks::AttributesAssignerService.execute!(
22
+ model: self,
23
+ stripe_model: object,
24
+ attributes: MATCHING_STRIPE_ATTRIBUTES
25
+ )
26
+
27
+ assign_billing_thresholds(object)
28
+ assign_invoice_settings(object)
29
+ assign_timestamps(object)
30
+
31
+ assign_subscription_schedule_phase_plans(object)
32
+ end
33
+
34
+ private
35
+
36
+ def assign_billing_thresholds(object)
37
+ billing_thresholds = object.billing_thresholds
38
+
39
+ self.billing_thresholds_amount_gte = billing_thresholds&.amount_gte
40
+ self.billing_thresholds_reset_billing_cycle_anchor = billing_thresholds&.reset_billing_cycle_anchor
41
+ end
42
+
43
+ def assign_invoice_settings(object)
44
+ invoice_settings = object.invoice_settings
45
+
46
+ self.invoice_settings_days_until_due = invoice_settings&.days_until_due
47
+ end
48
+
49
+ def assign_timestamps(object)
50
+ %i[end_date start_date trial_end].each do |timestamp|
51
+ object_timestamp = object.__send__(timestamp)
52
+ __send__("#{timestamp}=", Time.zone.at(object_timestamp)) if object_timestamp
53
+ end
54
+ end
55
+
56
+ def assign_subscription_schedule_phase_plans(object)
57
+ self.stripe_subscription_schedule_phase_plans = new_stripe_subscription_schedule_phase_plans(object)
58
+ end
59
+
60
+ def new_stripe_subscription_schedule_phase_plans(object)
61
+ @new_stripe_subscription_schedule_phase_plans ||= object.plans.collect do |plan|
62
+ subscription_schedule_phase_plan = StripeSubscriptionSchedulePhasePlan.new(stripe_subscription_schedule_phase: self)
63
+ subscription_schedule_phase_plan.assign_from_stripe(plan)
64
+ subscription_schedule_phase_plan
65
+ end
66
+ end
67
+ end