tang 0.2.2 → 0.2.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.
- checksums.yaml +4 -4
- data/Rakefile +3 -3
- data/app/controllers/tang/account/application_controller.rb +2 -4
- data/app/controllers/tang/account/cards_controller.rb +11 -8
- data/app/controllers/tang/account/coupons_controller.rb +1 -1
- data/app/controllers/tang/account/receipts_controller.rb +10 -4
- data/app/controllers/tang/account/subscriptions_controller.rb +11 -8
- data/app/controllers/tang/admin/application_controller.rb +4 -4
- data/app/controllers/tang/admin/coupons_controller.rb +18 -14
- data/app/controllers/tang/admin/customers_controller.rb +16 -16
- data/app/controllers/tang/admin/dashboard_controller.rb +1 -1
- data/app/controllers/tang/admin/invoices_controller.rb +6 -6
- data/app/controllers/tang/admin/payments_controller.rb +9 -9
- data/app/controllers/tang/admin/plans_controller.rb +21 -19
- data/app/controllers/tang/admin/search_controller.rb +15 -14
- data/app/controllers/tang/admin/subscriptions_controller.rb +16 -17
- data/app/controllers/tang/plans_controller.rb +1 -1
- data/app/helpers/tang/application_helper.rb +22 -28
- data/app/jobs/tang/import_charges_job.rb +4 -8
- data/app/jobs/tang/import_coupons_job.rb +3 -3
- data/app/jobs/tang/import_customers_job.rb +15 -13
- data/app/jobs/tang/import_invoices_job.rb +7 -7
- data/app/jobs/tang/import_plans_job.rb +4 -6
- data/app/jobs/tang/import_subscriptions_job.rb +4 -4
- data/app/mailers/application_mailer.rb +1 -1
- data/app/mailers/tang/stripe_mailer.rb +8 -9
- data/app/mailers/tang/subscription_mailer.rb +4 -1
- data/app/models/concerns/tang/customer.rb +32 -32
- data/app/models/tang/card.rb +7 -8
- data/app/models/tang/charge.rb +28 -50
- data/app/models/tang/coupon.rb +27 -25
- data/app/models/tang/invoice.rb +16 -17
- data/app/models/tang/invoice_item.rb +16 -18
- data/app/models/tang/plan.rb +31 -16
- data/app/models/tang/subscription.rb +34 -42
- data/app/services/tang/apply_customer_discount.rb +2 -2
- data/app/services/tang/apply_subscription_discount.rb +2 -2
- data/app/services/tang/cancel_subscription.rb +2 -2
- data/app/services/tang/change_subscription.rb +4 -4
- data/app/services/tang/create_coupon.rb +3 -5
- data/app/services/tang/create_invoice.rb +2 -2
- data/app/services/tang/create_plan.rb +9 -8
- data/app/services/tang/create_subscription.rb +18 -15
- data/app/services/tang/delete_card.rb +3 -3
- data/app/services/tang/delete_coupon.rb +3 -3
- data/app/services/tang/delete_customer.rb +2 -2
- data/app/services/tang/delete_plan.rb +2 -2
- data/app/services/tang/fail_invoice.rb +5 -6
- data/app/services/tang/pay_invoice.rb +2 -3
- data/app/services/tang/refresh_invoice_pdf.rb +9 -0
- data/app/services/tang/remove_customer_discount.rb +2 -2
- data/app/services/tang/remove_subscription_discount.rb +3 -3
- data/app/services/tang/save_card.rb +8 -9
- data/app/services/tang/update_coupon.rb +3 -5
- data/app/services/tang/update_customer.rb +4 -4
- data/app/services/tang/update_plan.rb +3 -5
- data/app/services/tang/update_subscription.rb +3 -5
- data/app/validators/future_validator.rb +4 -4
- data/app/views/tang/account/cards/show.html.erb +1 -1
- data/app/views/tang/account/receipts/_receipt.html.erb +1 -1
- data/app/views/tang/account/subscriptions/show.html.erb +14 -3
- data/app/views/tang/admin/coupons/show.html.erb +1 -1
- data/app/views/tang/admin/customers/show.html.erb +2 -2
- data/app/views/tang/admin/plans/show.html.erb +1 -1
- data/app/views/tang/admin/subscriptions/show.html.erb +2 -2
- data/app/views/tang/plans/index.html.erb +1 -1
- data/config/initializers/stripe.rb +2 -2
- data/config/initializers/stripe_event.rb +38 -33
- data/config/routes.rb +3 -1
- data/db/migrate/20160928154410_create_versions.rb +4 -4
- data/db/migrate/20160928161623_create_tang_stripe_webhooks.rb +1 -1
- data/db/migrate/20160928173328_create_tang_plans.rb +1 -1
- data/db/migrate/20160929152510_create_tang_coupons.rb +1 -1
- data/db/migrate/20160929152541_add_customer_fields.rb +1 -1
- data/db/migrate/20160929171640_create_tang_subscriptions.rb +2 -2
- data/db/migrate/20160929174251_create_tang_cards.rb +1 -1
- data/db/migrate/20161003035434_create_tang_invoices.rb +1 -1
- data/db/migrate/20161114181651_create_tang_invoice_items.rb +1 -1
- data/db/migrate/20161115201106_create_tang_charges.rb +1 -1
- data/db/migrate/20170523122759_add_group_to_plans.rb +1 -1
- data/db/migrate/20170701162853_add_stripe_indexes.rb +1 -1
- data/db/migrate/20170731010913_add_subscription_indexes.rb +1 -1
- data/db/migrate/20200827001523_add_invoice_pdf_to_invoices.rb +1 -1
- data/db/migrate/20230530172604_add_enable_customer_emails.rb +6 -0
- data/lib/generators/tang/install_generator.rb +1 -1
- data/lib/generators/templates/create_tang.rb +2 -2
- data/lib/tang/engine.rb +1 -1
- data/lib/tang/version.rb +1 -1
- data/lib/tang.rb +6 -6
- data/lib/tasks/cucumber.rake +50 -51
- data/lib/tasks/tang_tasks.rake +3 -3
- metadata +42 -30
|
@@ -6,18 +6,14 @@ module Tang
|
|
|
6
6
|
# Do something later
|
|
7
7
|
stripe_charges = Stripe::Charge.list(limit: 100, starting_after: starting_after)
|
|
8
8
|
stripe_charges.each do |stripe_charge|
|
|
9
|
-
|
|
10
9
|
invoice = Invoice.find_by(stripe_id: stripe_charge.invoice)
|
|
11
10
|
|
|
12
|
-
if invoice.present?
|
|
13
|
-
Charge.from_stripe(stripe_charge, invoice)
|
|
14
|
-
end
|
|
15
|
-
|
|
11
|
+
Charge.from_stripe(stripe_charge, invoice) if invoice.present?
|
|
16
12
|
end
|
|
17
13
|
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
14
|
+
return unless stripe_charges.has_more
|
|
15
|
+
|
|
16
|
+
Tang::ImportChargesJob.perform_now(stripe_charges.data.last.id)
|
|
21
17
|
end
|
|
22
18
|
end
|
|
23
19
|
end
|
|
@@ -9,9 +9,9 @@ module Tang
|
|
|
9
9
|
Coupon.from_stripe(stripe_coupon)
|
|
10
10
|
end
|
|
11
11
|
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
12
|
+
return unless stripe_coupons.has_more
|
|
13
|
+
|
|
14
|
+
Tang::ImportCouponsJob.perform_now(stripe_coupons.data.last.id)
|
|
15
15
|
end
|
|
16
16
|
end
|
|
17
17
|
end
|
|
@@ -12,25 +12,27 @@ module Tang
|
|
|
12
12
|
|
|
13
13
|
def import_customer(stripe_customer)
|
|
14
14
|
customer = Tang.customer_class.find_by(email: stripe_customer.email)
|
|
15
|
-
|
|
16
|
-
customer = update_customer(customer, stripe_customer)
|
|
15
|
+
return unless customer.present?
|
|
17
16
|
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
17
|
+
customer = update_customer(customer, stripe_customer)
|
|
18
|
+
|
|
19
|
+
# import card
|
|
20
|
+
return unless stripe_customer.default_source.present?
|
|
21
|
+
|
|
22
|
+
stripe_card = Stripe::Customer.retrieve_source(
|
|
23
|
+
stripe_customer.id,
|
|
24
|
+
stripe_customer.default_source
|
|
25
|
+
)
|
|
26
|
+
Card.from_stripe(stripe_card, customer)
|
|
27
27
|
end
|
|
28
28
|
|
|
29
29
|
def update_customer(customer, stripe_customer)
|
|
30
30
|
customer.stripe_id = stripe_customer.id if customer.stripe_id.nil?
|
|
31
|
-
|
|
31
|
+
if stripe_customer.discount.present?
|
|
32
|
+
customer.coupon = Coupon.find_by(stripe_id: stripe_customer.discount.coupon.id)
|
|
33
|
+
end
|
|
32
34
|
customer.save
|
|
33
|
-
|
|
35
|
+
customer
|
|
34
36
|
end
|
|
35
37
|
end
|
|
36
38
|
end
|
|
@@ -7,16 +7,16 @@ module Tang
|
|
|
7
7
|
stripe_invoices = Stripe::Invoice.list(limit: 100, starting_after: starting_after)
|
|
8
8
|
stripe_invoices.each do |stripe_invoice|
|
|
9
9
|
invoice = Invoice.from_stripe(stripe_invoice)
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
10
|
+
next unless invoice.present?
|
|
11
|
+
|
|
12
|
+
stripe_invoice.lines.data.each do |stripe_invoice_item|
|
|
13
|
+
InvoiceItem.from_stripe(stripe_invoice_item, invoice)
|
|
14
14
|
end
|
|
15
15
|
end
|
|
16
16
|
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
17
|
+
return unless stripe_invoices.has_more
|
|
18
|
+
|
|
19
|
+
Tang::ImportInvoicesJob.perform_now(stripe_invoices.data.last.id)
|
|
20
20
|
end
|
|
21
21
|
end
|
|
22
22
|
end
|
|
@@ -4,22 +4,20 @@ module Tang
|
|
|
4
4
|
|
|
5
5
|
def perform(starting_after = nil)
|
|
6
6
|
# Do something later
|
|
7
|
-
stripe_plans = Stripe::Plan.list(limit: 100, starting_after: starting_after)
|
|
7
|
+
stripe_plans = Stripe::Plan.list(limit: 100, starting_after: starting_after, expand: ['data.product'])
|
|
8
8
|
stripe_plans.each do |stripe_plan|
|
|
9
9
|
Plan.find_or_create_by(stripe_id: stripe_plan.id) do |p|
|
|
10
10
|
p.amount = stripe_plan.amount
|
|
11
11
|
p.currency = stripe_plan.currency
|
|
12
12
|
p.interval = stripe_plan.interval
|
|
13
13
|
p.interval_count = stripe_plan.interval_count
|
|
14
|
-
p.name = stripe_plan.name
|
|
15
|
-
p.statement_descriptor = stripe_plan.statement_descriptor
|
|
14
|
+
p.name = stripe_plan.product.name
|
|
15
|
+
# p.statement_descriptor = stripe_plan.statement_descriptor
|
|
16
16
|
p.trial_period_days = stripe_plan.trial_period_days
|
|
17
17
|
end
|
|
18
18
|
end
|
|
19
19
|
|
|
20
|
-
if stripe_plans.has_more
|
|
21
|
-
Tang::ImportPlansJob.perform_now(stripe_plans.data.last.id)
|
|
22
|
-
end
|
|
20
|
+
Tang::ImportPlansJob.perform_now(stripe_plans.data.last.id) if stripe_plans.has_more
|
|
23
21
|
end
|
|
24
22
|
end
|
|
25
23
|
end
|
|
@@ -20,10 +20,10 @@ module Tang
|
|
|
20
20
|
|
|
21
21
|
def import_subscription(stripe_subscription)
|
|
22
22
|
subscription = Subscription.from_stripe(stripe_subscription)
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
23
|
+
return unless subscription.present?
|
|
24
|
+
|
|
25
|
+
# Handle removed discounts
|
|
26
|
+
subscription.update(coupon: nil, coupon_start: nil) if stripe_subscription.discount.nil?
|
|
27
27
|
end
|
|
28
28
|
end
|
|
29
29
|
end
|
|
@@ -10,27 +10,26 @@ module Tang
|
|
|
10
10
|
|
|
11
11
|
def admin_payment_succeeded(charge)
|
|
12
12
|
@charge = charge
|
|
13
|
-
mail(to: Tang.admin_email, subject:
|
|
13
|
+
mail(to: Tang.admin_email, subject: 'Woo! Charge succeeded!')
|
|
14
14
|
end
|
|
15
15
|
|
|
16
16
|
def admin_payment_failed(charge)
|
|
17
17
|
@charge = charge
|
|
18
|
-
mail(to: Tang.admin_email, subject:
|
|
18
|
+
mail(to: Tang.admin_email, subject: 'Oh no! Charge failed!')
|
|
19
19
|
end
|
|
20
20
|
|
|
21
21
|
def customer_payment_succeeded(charge)
|
|
22
22
|
@receipt = charge
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
23
|
+
return unless @receipt.customer.present?
|
|
24
|
+
|
|
25
|
+
mail(to: @receipt.customer.email, subject: 'Thank you!')
|
|
26
26
|
end
|
|
27
27
|
|
|
28
28
|
def customer_payment_failed(charge)
|
|
29
29
|
@charge = charge
|
|
30
|
-
|
|
31
|
-
mail(to: @charge.customer.email, subject: "Oops! Your payment could not be processed.")
|
|
32
|
-
end
|
|
33
|
-
end
|
|
30
|
+
return unless @charge.customer.present?
|
|
34
31
|
|
|
32
|
+
mail(to: @charge.customer.email, subject: 'Oops! Your payment could not be processed.')
|
|
33
|
+
end
|
|
35
34
|
end
|
|
36
35
|
end
|
|
@@ -5,7 +5,10 @@ module Tang
|
|
|
5
5
|
|
|
6
6
|
def upgraded(subscription)
|
|
7
7
|
@subscription = subscription
|
|
8
|
-
mail(
|
|
8
|
+
mail(
|
|
9
|
+
to: @subscription.customer.email,
|
|
10
|
+
subject: "Oh, wow! Excited to have you on our #{@subscription.plan.name} plan!"
|
|
11
|
+
)
|
|
9
12
|
end
|
|
10
13
|
end
|
|
11
14
|
end
|
|
@@ -20,7 +20,7 @@ module Tang
|
|
|
20
20
|
validates :account_balance, numericality: { only_integer: true }, allow_nil: true
|
|
21
21
|
|
|
22
22
|
define_method :admin? do
|
|
23
|
-
|
|
23
|
+
respond_to?(:role) && role == 'admin'
|
|
24
24
|
end
|
|
25
25
|
|
|
26
26
|
define_method :stripe_enabled? do
|
|
@@ -29,7 +29,7 @@ module Tang
|
|
|
29
29
|
end
|
|
30
30
|
|
|
31
31
|
def self.table_name
|
|
32
|
-
|
|
32
|
+
Tang.customer_class.to_s.downcase.pluralize
|
|
33
33
|
end
|
|
34
34
|
|
|
35
35
|
def self.search(query)
|
|
@@ -37,22 +37,27 @@ module Tang
|
|
|
37
37
|
if query.present?
|
|
38
38
|
q = "%#{query.downcase}%"
|
|
39
39
|
customer_table = ActiveRecord::Base.connection.quote_table_name(Customer.table_name)
|
|
40
|
-
customers = Tang.customer_class
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
40
|
+
customers = Tang.customer_class
|
|
41
|
+
.joins(:subscriptions, :coupon)
|
|
42
|
+
.where.not(stripe_id: nil)
|
|
43
|
+
.where(
|
|
44
|
+
"lower(#{customer_table}.stripe_id) like ? or lower(#{customer_table}.email) like ? or lower(tang_subscriptions.stripe_id) like ? or lower(tang_coupons.stripe_id) like ?",
|
|
45
|
+
q,
|
|
46
|
+
q,
|
|
47
|
+
q,
|
|
48
|
+
q
|
|
49
|
+
)
|
|
50
|
+
.distinct
|
|
46
51
|
end
|
|
47
|
-
|
|
52
|
+
customers
|
|
48
53
|
end
|
|
49
54
|
|
|
50
55
|
def card
|
|
51
|
-
|
|
56
|
+
cards.order(:created_at).last
|
|
52
57
|
end
|
|
53
58
|
|
|
54
59
|
def subscription
|
|
55
|
-
@subscription ||=
|
|
60
|
+
@subscription ||= subscriptions.where.not(status: :canceled).order(:created_at).last
|
|
56
61
|
end
|
|
57
62
|
|
|
58
63
|
def generate_password
|
|
@@ -60,62 +65,57 @@ module Tang
|
|
|
60
65
|
end
|
|
61
66
|
|
|
62
67
|
def update_card_from_stripe(stripe_card)
|
|
63
|
-
my_card =
|
|
68
|
+
my_card = card.present? ? card : Card.new(customer: self)
|
|
64
69
|
my_card.update_from_stripe(stripe_card)
|
|
65
70
|
end
|
|
66
71
|
|
|
67
72
|
def update_subscription_end(subscription)
|
|
68
73
|
self.active_until = subscription.period_end
|
|
69
|
-
|
|
74
|
+
save!
|
|
70
75
|
end
|
|
71
76
|
|
|
72
77
|
# NOTE: May be causing memory bloat
|
|
73
78
|
def subscribed_to?(stripe_id)
|
|
74
|
-
subscription_plan =
|
|
79
|
+
subscription_plan = subscription.plan if subscription.present?
|
|
75
80
|
if subscription_plan.present?
|
|
76
81
|
return true if subscription_plan.stripe_id == stripe_id
|
|
82
|
+
|
|
77
83
|
if Tang.plan_inheritance
|
|
78
84
|
other_plan = Plan.find_by(stripe_id: stripe_id)
|
|
79
85
|
return true if other_plan.present? && subscription_plan.order >= other_plan.order
|
|
80
86
|
end
|
|
81
87
|
end
|
|
82
|
-
|
|
88
|
+
false
|
|
83
89
|
end
|
|
84
90
|
|
|
85
91
|
def coupon_end
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
end
|
|
89
|
-
return nil
|
|
92
|
+
nil
|
|
90
93
|
end
|
|
91
94
|
|
|
92
95
|
def has_coupon?
|
|
93
|
-
if
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
end
|
|
97
|
-
end
|
|
98
|
-
return self.coupon.present?
|
|
96
|
+
return true if subscription.present? && subscription.coupon.present?
|
|
97
|
+
|
|
98
|
+
coupon.present?
|
|
99
99
|
end
|
|
100
100
|
|
|
101
101
|
def has_subscription_coupon?
|
|
102
|
-
|
|
102
|
+
subscription.present? && subscription.coupon.present?
|
|
103
103
|
end
|
|
104
104
|
|
|
105
105
|
def discount_for_plan(plan)
|
|
106
106
|
amount_off = 0
|
|
107
|
-
if
|
|
108
|
-
amount_off = (
|
|
109
|
-
elsif
|
|
110
|
-
amount_off =
|
|
107
|
+
if coupon.percent_off.present?
|
|
108
|
+
amount_off = (coupon.percent_off.to_f / 100.0) * plan.amount.to_f
|
|
109
|
+
elsif coupon.amount_off.present?
|
|
110
|
+
amount_off = coupon.amount_off
|
|
111
111
|
end
|
|
112
|
-
|
|
112
|
+
amount_off
|
|
113
113
|
end
|
|
114
114
|
|
|
115
115
|
private
|
|
116
116
|
|
|
117
117
|
def nil_if_blank
|
|
118
|
-
self.description = nil if
|
|
118
|
+
self.description = nil if description.blank?
|
|
119
119
|
end
|
|
120
120
|
|
|
121
121
|
def update_stripe_customer
|
data/app/models/tang/card.rb
CHANGED
|
@@ -8,8 +8,11 @@ module Tang
|
|
|
8
8
|
validates :last4, numericality: { only_integer: true, greater_than_or_equal_to: 0 },
|
|
9
9
|
length: { is: 4 }
|
|
10
10
|
validates :exp_month, numericality: { only_integer: true, greater_than_or_equal_to: 1, less_than_or_equal_to: 12 }
|
|
11
|
-
validates :exp_year, numericality: {
|
|
12
|
-
|
|
11
|
+
validates :exp_year, numericality: {
|
|
12
|
+
only_integer: true,
|
|
13
|
+
greater_than_or_equal_to: Date.today.year - 30.years,
|
|
14
|
+
less_than_or_equal_to: Date.today.year + 70.years
|
|
15
|
+
}
|
|
13
16
|
validates :address_zip, presence: true
|
|
14
17
|
|
|
15
18
|
before_destroy :delete_stripe_card
|
|
@@ -27,15 +30,13 @@ module Tang
|
|
|
27
30
|
self.brand = stripe_card.brand
|
|
28
31
|
self.country = stripe_card.country
|
|
29
32
|
self.cvc_check = stripe_card.cvc_check
|
|
30
|
-
# self.dynamic_last4 = stripe_card.dynamic_last4
|
|
31
33
|
self.exp_month = stripe_card.exp_month
|
|
32
34
|
self.exp_year = stripe_card.exp_year
|
|
33
35
|
self.fingerprint = stripe_card.fingerprint
|
|
34
36
|
self.funding = stripe_card.funding
|
|
35
37
|
self.last4 = stripe_card.last4
|
|
36
38
|
self.name = stripe_card.name
|
|
37
|
-
|
|
38
|
-
self.save(validate: false)
|
|
39
|
+
save(validate: false)
|
|
39
40
|
end
|
|
40
41
|
|
|
41
42
|
def self.from_stripe(stripe_card, customer)
|
|
@@ -52,16 +53,14 @@ module Tang
|
|
|
52
53
|
c.brand = stripe_card.brand
|
|
53
54
|
c.country = stripe_card.country
|
|
54
55
|
c.cvc_check = stripe_card.cvc_check
|
|
55
|
-
# c.dynamic_last4 = stripe_card.dynamic_last4
|
|
56
56
|
c.exp_month = stripe_card.exp_month
|
|
57
57
|
c.exp_year = stripe_card.exp_year
|
|
58
58
|
c.funding = stripe_card.funding
|
|
59
59
|
c.last4 = stripe_card.last4
|
|
60
60
|
c.name = stripe_card.name
|
|
61
|
-
# c.tokenization_method = stripe_card.tokenization_method
|
|
62
61
|
end
|
|
63
62
|
card.save(validate: false) if card.new_record?
|
|
64
|
-
|
|
63
|
+
card
|
|
65
64
|
end
|
|
66
65
|
|
|
67
66
|
private
|
data/app/models/tang/charge.rb
CHANGED
|
@@ -40,27 +40,6 @@ module Tang
|
|
|
40
40
|
# Save payment source directly to charge
|
|
41
41
|
c.set_source(stripe_charge.source)
|
|
42
42
|
|
|
43
|
-
# c.card_stripe_id = stripe_charge.source.id
|
|
44
|
-
# c.card_address_city = stripe_charge.source.address_city
|
|
45
|
-
# c.card_address_country = stripe_charge.source.address_country
|
|
46
|
-
# c.card_address_line1 = stripe_charge.source.address_line1
|
|
47
|
-
# c.card_address_line1_check = stripe_charge.source.address_line1_check
|
|
48
|
-
# c.card_address_line2 = stripe_charge.source.address_line2
|
|
49
|
-
# c.card_address_state = stripe_charge.source.address_state
|
|
50
|
-
# c.card_address_zip = stripe_charge.source.address_zip
|
|
51
|
-
# c.card_address_zip_check = stripe_charge.source.address_zip_check
|
|
52
|
-
# c.card_brand = stripe_charge.source.brand
|
|
53
|
-
# c.card_country = stripe_charge.source.country
|
|
54
|
-
# c.card_cvc_check = stripe_charge.source.cvc_check
|
|
55
|
-
# # c.card_dynamic_last4 = stripe_charge.source.dynamic_last4
|
|
56
|
-
# c.card_exp_month = stripe_charge.source.exp_month
|
|
57
|
-
# c.card_exp_year = stripe_charge.source.exp_year
|
|
58
|
-
# c.card_fingerprint = stripe_charge.source.fingerprint
|
|
59
|
-
# c.card_funding = stripe_charge.source.funding
|
|
60
|
-
# c.card_last4 = stripe_charge.source.last4
|
|
61
|
-
# c.card_name = stripe_charge.source.name
|
|
62
|
-
# # c.card_tokenization_method = stripe_charge.source.tokenization_method
|
|
63
|
-
|
|
64
43
|
c.created = DateTime.strptime(stripe_charge.created.to_s, '%s')
|
|
65
44
|
c.status = stripe_charge.status
|
|
66
45
|
end
|
|
@@ -71,39 +50,38 @@ module Tang
|
|
|
71
50
|
if query.present?
|
|
72
51
|
q = "%#{query.downcase}%"
|
|
73
52
|
customer_table = connection.quote_table_name(Customer.table_name)
|
|
74
|
-
charges = Charge.joins(:customer)
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
|
|
53
|
+
charges = Charge.joins(:customer)
|
|
54
|
+
.where(
|
|
55
|
+
"lower(tang_charges.stripe_id) like ? or lower(#{customer_table}.stripe_id) like ?",
|
|
56
|
+
q,
|
|
57
|
+
q
|
|
58
|
+
)
|
|
59
|
+
.distinct
|
|
78
60
|
end
|
|
79
|
-
|
|
61
|
+
charges
|
|
80
62
|
end
|
|
81
63
|
|
|
82
64
|
def set_source(source)
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
# self.card_tokenization_method = source.tokenization_method
|
|
104
|
-
rescue NoMethodError
|
|
105
|
-
logger.debug "could not save a valid source"
|
|
106
|
-
end
|
|
65
|
+
self.card_stripe_id = source.id
|
|
66
|
+
self.card_address_city = source.address_city if source.has_attribute?
|
|
67
|
+
self.card_address_country = source.address_country
|
|
68
|
+
self.card_address_line1 = source.address_line1
|
|
69
|
+
self.card_address_line1_check = source.address_line1_check
|
|
70
|
+
self.card_address_line2 = source.address_line2
|
|
71
|
+
self.card_address_state = source.address_state
|
|
72
|
+
self.card_address_zip = source.address_zip
|
|
73
|
+
self.card_address_zip_check = source.address_zip_check
|
|
74
|
+
self.card_brand = source.brand
|
|
75
|
+
self.card_country = source.country
|
|
76
|
+
self.card_cvc_check = source.cvc_check
|
|
77
|
+
self.card_exp_month = source.exp_month
|
|
78
|
+
self.card_exp_year = source.exp_year
|
|
79
|
+
self.card_fingerprint = source.fingerprint
|
|
80
|
+
self.card_funding = source.funding
|
|
81
|
+
self.card_last4 = source.last4
|
|
82
|
+
self.card_name = source.name
|
|
83
|
+
rescue NoMethodError
|
|
84
|
+
logger.debug 'could not save a valid source'
|
|
107
85
|
end
|
|
108
86
|
end
|
|
109
87
|
end
|
data/app/models/tang/coupon.rb
CHANGED
|
@@ -9,32 +9,36 @@ module Tang
|
|
|
9
9
|
|
|
10
10
|
validates :stripe_id, presence: true
|
|
11
11
|
validates :stripe_id, uniqueness: true # , if: "deleted_at.nil?"
|
|
12
|
-
validates :duration, inclusion: { in: %w
|
|
12
|
+
validates :duration, inclusion: { in: %w[once repeating forever] }
|
|
13
13
|
validates :amount_off, numericality: { only_integer: true, greater_than: 0 }, allow_nil: true
|
|
14
14
|
validates :currency, presence: true, if: -> { amount_off.present? }
|
|
15
|
-
validates :duration_in_months, presence: true, numericality: {
|
|
15
|
+
validates :duration_in_months, presence: true, numericality: {
|
|
16
|
+
only_integer: true,
|
|
17
|
+
greater_than: 0
|
|
18
|
+
}, if: :repeating?
|
|
16
19
|
validates :max_redemptions, numericality: { only_integer: true, greater_than: 0 }, allow_nil: true
|
|
17
|
-
validates :percent_off, numericality: {
|
|
18
|
-
|
|
20
|
+
validates :percent_off, numericality: {
|
|
21
|
+
only_integer: true,
|
|
22
|
+
greater_than_or_equal_to: 1,
|
|
23
|
+
less_than_or_equal_to: 100
|
|
24
|
+
}, presence: true, if: -> { amount_off.nil? }
|
|
19
25
|
validates :redeem_by, future: true, if: -> { redeem_by.present? }
|
|
20
26
|
|
|
21
27
|
before_create :create_stripe_coupon
|
|
22
28
|
before_update :update_stripe_coupon
|
|
23
29
|
before_destroy :delete_stripe_coupon # should be soft delete
|
|
24
30
|
|
|
25
|
-
DURATIONS = [
|
|
31
|
+
DURATIONS = %w[once repeating forever].freeze
|
|
26
32
|
|
|
27
33
|
def coupon_valid?
|
|
28
34
|
# check if expired
|
|
29
|
-
if
|
|
30
|
-
return false if Time.now > self.redeem_by
|
|
31
|
-
end
|
|
35
|
+
return false if redeem_by.present? && Time.now > redeem_by
|
|
32
36
|
|
|
33
|
-
if
|
|
37
|
+
if max_redemptions.present?
|
|
34
38
|
# check if any discounts created
|
|
35
39
|
end
|
|
36
40
|
|
|
37
|
-
|
|
41
|
+
true
|
|
38
42
|
end
|
|
39
43
|
|
|
40
44
|
def formatted_duration
|
|
@@ -47,29 +51,29 @@ module Tang
|
|
|
47
51
|
|
|
48
52
|
def active_redemptions
|
|
49
53
|
customer_table = ActiveRecord::Base.connection.quote_table_name(Customer.table_name)
|
|
50
|
-
Tang.customer_class
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
54
|
+
Tang.customer_class
|
|
55
|
+
.joins(:subscriptions)
|
|
56
|
+
.where("#{customer_table}.coupon_id = ? OR tang_subscriptions.coupon_id = ?", id, id)
|
|
57
|
+
.where.not(tang_subscriptions: { status: :canceled })
|
|
58
|
+
.uniq
|
|
55
59
|
end
|
|
56
60
|
|
|
57
61
|
def repeating?
|
|
58
|
-
duration ==
|
|
62
|
+
duration == 'repeating'
|
|
59
63
|
end
|
|
60
64
|
|
|
61
65
|
def discount(amount)
|
|
62
66
|
subtotal = amount
|
|
63
|
-
if
|
|
64
|
-
subtotal = amount.to_f * (
|
|
65
|
-
elsif
|
|
66
|
-
subtotal =
|
|
67
|
+
if percent_off.present?
|
|
68
|
+
subtotal = amount.to_f * (percent_off.to_f / 100.0)
|
|
69
|
+
elsif amount_off.present?
|
|
70
|
+
subtotal = amount_off
|
|
67
71
|
end
|
|
68
|
-
|
|
72
|
+
-subtotal.to_f
|
|
69
73
|
end
|
|
70
74
|
|
|
71
|
-
def self.from_stripe(stripe_coupon)
|
|
72
|
-
|
|
75
|
+
def self.from_stripe(stripe_coupon)
|
|
76
|
+
Coupon.find_or_create_by(stripe_id: stripe_coupon.id) do |c|
|
|
73
77
|
c.percent_off = stripe_coupon.percent_off
|
|
74
78
|
c.currency = stripe_coupon.currency
|
|
75
79
|
c.amount_off = stripe_coupon.amount_off
|
|
@@ -78,8 +82,6 @@ module Tang
|
|
|
78
82
|
c.max_redemptions = stripe_coupon.max_redemptions
|
|
79
83
|
c.redeem_by = DateTime.strptime(stripe_coupon.redeem_by.to_s, '%s') if stripe_coupon.redeem_by.present?
|
|
80
84
|
end
|
|
81
|
-
|
|
82
|
-
return coupon
|
|
83
85
|
end
|
|
84
86
|
|
|
85
87
|
private
|
data/app/models/tang/invoice.rb
CHANGED
|
@@ -12,7 +12,7 @@ module Tang
|
|
|
12
12
|
# scope :paid, -> { joins(:charge) }
|
|
13
13
|
|
|
14
14
|
def charge
|
|
15
|
-
|
|
15
|
+
charges.order(:created_at).last
|
|
16
16
|
end
|
|
17
17
|
|
|
18
18
|
def period_start
|
|
@@ -27,7 +27,7 @@ module Tang
|
|
|
27
27
|
if subscription.present?
|
|
28
28
|
self[:period_end] || subscription.plan.period_days_from(period_start)
|
|
29
29
|
else
|
|
30
|
-
|
|
30
|
+
period_start
|
|
31
31
|
end
|
|
32
32
|
end
|
|
33
33
|
|
|
@@ -67,11 +67,8 @@ module Tang
|
|
|
67
67
|
end
|
|
68
68
|
end
|
|
69
69
|
|
|
70
|
-
if invoice.update_from_stripe(stripe_invoice)
|
|
71
|
-
|
|
72
|
-
end
|
|
73
|
-
|
|
74
|
-
return invoice
|
|
70
|
+
invoice.save if invoice.update_from_stripe(stripe_invoice)
|
|
71
|
+
invoice
|
|
75
72
|
end
|
|
76
73
|
|
|
77
74
|
def update_from_stripe(stripe_invoice)
|
|
@@ -90,17 +87,17 @@ module Tang
|
|
|
90
87
|
end
|
|
91
88
|
|
|
92
89
|
stripe_created = DateTime.strptime(stripe_invoice.created.to_s, '%s')
|
|
93
|
-
if
|
|
90
|
+
if date != stripe_created
|
|
94
91
|
self.date = stripe_created
|
|
95
92
|
changed = true
|
|
96
93
|
end
|
|
97
94
|
|
|
98
|
-
if
|
|
95
|
+
if invoice_pdf != stripe_invoice.invoice_pdf
|
|
99
96
|
self.invoice_pdf = stripe_invoice.invoice_pdf
|
|
100
97
|
changed = true
|
|
101
98
|
end
|
|
102
99
|
|
|
103
|
-
|
|
100
|
+
changed
|
|
104
101
|
end
|
|
105
102
|
|
|
106
103
|
def self.search(query)
|
|
@@ -108,14 +105,16 @@ module Tang
|
|
|
108
105
|
if query.present?
|
|
109
106
|
q = "%#{query.downcase}%"
|
|
110
107
|
customer_table = connection.quote_table_name(Customer.table_name)
|
|
111
|
-
invoices = Invoice.joins(
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
108
|
+
invoices = Invoice.joins('left join tang_charges on tang_invoices.id = tang_charges.invoice_id')
|
|
109
|
+
.joins('left join tang_subscriptions on tang_subscriptions.id = tang_invoices.subscription_id')
|
|
110
|
+
.joins("left join #{customer_table} on #{customer_table}.id = tang_invoices.customer_id")
|
|
111
|
+
.where(
|
|
112
|
+
"lower(tang_charges.stripe_id) like ? or lower(tang_subscriptions.stripe_id) like ? or lower(#{customer_table}.stripe_id) like ?",
|
|
113
|
+
q, q, q
|
|
114
|
+
)
|
|
115
|
+
.distinct
|
|
117
116
|
end
|
|
118
|
-
|
|
117
|
+
invoices
|
|
119
118
|
end
|
|
120
119
|
end
|
|
121
120
|
end
|