op_cart 0.4.0 → 0.4.1
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/app/controllers/op_cart/orders_controller.rb +1 -1
- data/app/models/op_cart/order.rb +16 -2
- data/app/models/op_cart/subscription.rb +66 -0
- data/db/migrate/20150205220423_create_op_cart_subscriptions.rb +19 -0
- data/db/seeds.rb +19 -7
- data/lib/op_cart/version.rb +1 -1
- data/test/dummy/log/development.log +59 -0
- metadata +6 -2
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 695ceaa47d75df3df79ef2d8049909b2cd605662
|
4
|
+
data.tar.gz: edfc90597c37f748372219b032568a26d17012c0
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: b9f7d545228109490cb3a503023943b4ae6a5dcf196eca748609af70a633fb4c229251570e7b723a9fea78f1eb369c713ac0c31cdf51b98f78eb89e094bba267
|
7
|
+
data.tar.gz: 88aa09d43bea2327481b99d933ac087a8093c2e857a22e0b0bf2bb6a253df0208565d43ac1958a6c556e320212230df1e35856c22f7a2383d343a824293a9a6a
|
data/app/models/op_cart/order.rb
CHANGED
@@ -1,6 +1,7 @@
|
|
1
1
|
module OpCart
|
2
2
|
class Order < ActiveRecord::Base
|
3
3
|
has_many :line_items
|
4
|
+
has_many :subscriptions
|
4
5
|
belongs_to :shipping_address
|
5
6
|
belongs_to :user
|
6
7
|
|
@@ -19,6 +20,7 @@ module OpCart
|
|
19
20
|
before_validation :set_total
|
20
21
|
before_validation -> { self.status = :pending }, unless: :status?
|
21
22
|
before_save :charge_customer, if: -> { self.status == 'pending' }
|
23
|
+
before_create :create_subscriptions
|
22
24
|
|
23
25
|
private
|
24
26
|
|
@@ -40,10 +42,9 @@ module OpCart
|
|
40
42
|
end
|
41
43
|
|
42
44
|
def charge_customer
|
43
|
-
customer = Customer.find_or_create_by user: user
|
44
45
|
if processor_token.present?
|
45
46
|
customer.update_card processor_token
|
46
|
-
processor_token = nil
|
47
|
+
self.processor_token = nil
|
47
48
|
end
|
48
49
|
|
49
50
|
self.processor_response = Stripe::Charge.create(
|
@@ -53,6 +54,7 @@ module OpCart
|
|
53
54
|
).to_hash
|
54
55
|
self.status = :paid if processor_response['captured']
|
55
56
|
rescue Stripe::InvalidRequestError, Stripe::CardError => e
|
57
|
+
self.processor_token = nil
|
56
58
|
if e.try(:code) == 'card_declined'
|
57
59
|
self.status = :payment_declined
|
58
60
|
end
|
@@ -68,5 +70,17 @@ module OpCart
|
|
68
70
|
self.errors.add :card_error, (message || e.message)
|
69
71
|
false
|
70
72
|
end
|
73
|
+
|
74
|
+
def create_subscriptions
|
75
|
+
line_items.each do |li|
|
76
|
+
if li.sellable.is_a? Plan
|
77
|
+
subscriptions.new customer: customer, plan: li.sellable, quantity: li.quantity
|
78
|
+
end
|
79
|
+
end
|
80
|
+
end
|
81
|
+
|
82
|
+
def customer
|
83
|
+
@customer ||= Customer.find_or_create_by user: user
|
84
|
+
end
|
71
85
|
end
|
72
86
|
end
|
@@ -0,0 +1,66 @@
|
|
1
|
+
module OpCart
|
2
|
+
class Subscription < ActiveRecord::Base
|
3
|
+
belongs_to :plan
|
4
|
+
belongs_to :order
|
5
|
+
belongs_to :customer
|
6
|
+
|
7
|
+
before_validation -> { self.status = :pending }, unless: :status?
|
8
|
+
before_validation -> { self.quantity = 1 }, unless: :quantity?
|
9
|
+
before_validation :create_subscription, on: :create
|
10
|
+
before_validation :update_subscription, on: :update
|
11
|
+
|
12
|
+
validates :processor_token, uniqueness: true, presence: true
|
13
|
+
validates :status, presence: true
|
14
|
+
validates :quantity, numericality: { only_integer: true, greater_than: 0 }
|
15
|
+
validates :started_at, presence: true
|
16
|
+
validates :plan, :order, :customer, presence: true
|
17
|
+
|
18
|
+
def processor_object
|
19
|
+
@processor_object ||= customer.processor_object.subscriptions.retrieve processor_token
|
20
|
+
rescue Stripe::InvalidRequestError => e
|
21
|
+
raise e unless e.message.include? 'does not have subscription'
|
22
|
+
end
|
23
|
+
|
24
|
+
private
|
25
|
+
|
26
|
+
def create_subscription
|
27
|
+
subscriptions_attributes = { plan: plan.processor_token, quantity: quantity }
|
28
|
+
subscriptions_attributes[:trial_end] = trial_ended_at.to_i if trial_ended_at
|
29
|
+
update_local_object customer.processor_object.subscriptions.create(subscriptions_attributes)
|
30
|
+
rescue Stripe::InvalidRequestError => e
|
31
|
+
if e.param
|
32
|
+
self.errors.add e.param, e.message
|
33
|
+
else
|
34
|
+
self.errors.add :base, e.message
|
35
|
+
end
|
36
|
+
false
|
37
|
+
end
|
38
|
+
|
39
|
+
def update_subscription
|
40
|
+
subscriptions_attributes = {}
|
41
|
+
subscriptions_attributes[:quantity] = quantity if quantity_changed?
|
42
|
+
subscriptions_attributes[:trial_end] = trial_ended_at.to_i if trial_ended_at_changed?
|
43
|
+
subscriptions_attributes[:plan] = plan.processor_token if plan_id_changed?
|
44
|
+
update_local_object customer.processor_object.subscriptions.create(subscriptions_attributes)
|
45
|
+
rescue Stripe::InvalidRequestError => e
|
46
|
+
if e.param
|
47
|
+
self.errors.add e.param, e.message
|
48
|
+
else
|
49
|
+
self.errors.add :base, e.message
|
50
|
+
end
|
51
|
+
false
|
52
|
+
end
|
53
|
+
|
54
|
+
def update_local_object subscription=processor_object
|
55
|
+
self.processor_token = subscription.id
|
56
|
+
self.status = subscription.status
|
57
|
+
self.quantity = subscription.quantity
|
58
|
+
self.started_at = Time.at subscription.start
|
59
|
+
self.canceled_at = Time.at subscription.canceled_at if subscription.canceled_at
|
60
|
+
self.ended_at = Time.at subscription.ended_at if subscription.ended_at
|
61
|
+
self.trial_started_at = Time.at subscription.trial_start if subscription.trial_start
|
62
|
+
self.trial_ended_at = Time.at subscription.trial_end if subscription.trial_end
|
63
|
+
self.plan = Plan.find_by! processor_token: subscription.plan.id
|
64
|
+
end
|
65
|
+
end
|
66
|
+
end
|
@@ -0,0 +1,19 @@
|
|
1
|
+
class CreateOpCartSubscriptions < ActiveRecord::Migration
|
2
|
+
def change
|
3
|
+
create_table :op_cart_subscriptions do |t|
|
4
|
+
t.string :processor_token
|
5
|
+
t.string :status
|
6
|
+
t.integer :quantity
|
7
|
+
t.datetime :started_at
|
8
|
+
t.datetime :canceled_at
|
9
|
+
t.datetime :ended_at
|
10
|
+
t.datetime :trial_started_at
|
11
|
+
t.datetime :trial_ended_at
|
12
|
+
t.references :plan, index: true
|
13
|
+
t.references :order, index: true
|
14
|
+
t.references :customer, index: true
|
15
|
+
|
16
|
+
t.timestamps null: false
|
17
|
+
end
|
18
|
+
end
|
19
|
+
end
|
data/db/seeds.rb
CHANGED
@@ -1,3 +1,13 @@
|
|
1
|
+
shipping_address1_attrs = {
|
2
|
+
full_name: User.first.name,
|
3
|
+
street: '123 N 4th',
|
4
|
+
locality: 'New York',
|
5
|
+
region: 'New York',
|
6
|
+
postal_code: '12345',
|
7
|
+
user: User.first,
|
8
|
+
}
|
9
|
+
shipping_address1 = OpCart::ShippingAddress.where(street: shipping_address1_attrs[:street]).first_or_create! shipping_address1_attrs
|
10
|
+
|
1
11
|
product1_attrs = {
|
2
12
|
name: 'Device 3000',
|
3
13
|
description: 'The original Device 3000',
|
@@ -7,8 +17,7 @@ product1_attrs = {
|
|
7
17
|
charge_taxes: true,
|
8
18
|
user: User.first,
|
9
19
|
}
|
10
|
-
|
11
|
-
product1 = OpCart::Product.where(sku: product1_attrs[:sku]).first_or_create product1_attrs
|
20
|
+
product1 = OpCart::Product.where(sku: product1_attrs[:sku]).first_or_create! product1_attrs
|
12
21
|
|
13
22
|
product2_attrs = {
|
14
23
|
name: 'Device 9000',
|
@@ -19,8 +28,7 @@ product2_attrs = {
|
|
19
28
|
charge_taxes: true,
|
20
29
|
user: User.first,
|
21
30
|
}
|
22
|
-
|
23
|
-
product2 = OpCart::Product.where(sku: product2_attrs[:sku]).first_or_create product2_attrs
|
31
|
+
product2 = OpCart::Product.where(sku: product2_attrs[:sku]).first_or_create! product2_attrs
|
24
32
|
|
25
33
|
rand_plan_no = rand 10**9
|
26
34
|
plan1_attrs = {
|
@@ -35,8 +43,7 @@ plan1_attrs = {
|
|
35
43
|
allow_purchases: true,
|
36
44
|
user: User.first,
|
37
45
|
}
|
38
|
-
|
39
|
-
plan1 = OpCart::Plan.where(name: plan1_attrs[:name]).first_or_create plan1_attrs
|
46
|
+
plan1 = OpCart::Plan.where(name: plan1_attrs[:name]).first_or_create! plan1_attrs
|
40
47
|
|
41
48
|
plan_addon1_attrs = {
|
42
49
|
recurring: false,
|
@@ -44,5 +51,10 @@ plan_addon1_attrs = {
|
|
44
51
|
plan: plan1,
|
45
52
|
user: User.first,
|
46
53
|
}
|
54
|
+
plan_addon1 = OpCart::PlanAddon.first_or_create! plan_addon1_attrs
|
47
55
|
|
48
|
-
|
56
|
+
token1 = Stripe::Token.create card: { number: '4'+'1'*15, exp_month: 1, exp_year: 2031, cvc: 123 }
|
57
|
+
order1 = OpCart::Order.first || OpCart::Order.new(user: User.first, shipping_address: shipping_address1, processor_token: token1.id)
|
58
|
+
order1.line_items << OpCart::LineItem.new(sellable: plan1, quantity: 1)
|
59
|
+
order1.line_items << OpCart::LineItem.new(sellable: plan_addon1.product, quantity: 1)
|
60
|
+
order1.save!
|
data/lib/op_cart/version.rb
CHANGED
@@ -0,0 +1,59 @@
|
|
1
|
+
[1m[36m (22.3ms)[0m [1mCREATE TABLE "schema_migrations" ("version" character varying NOT NULL) [0m
|
2
|
+
[1m[35m (2.1ms)[0m CREATE UNIQUE INDEX "unique_schema_migrations" ON "schema_migrations" ("version")
|
3
|
+
[1m[36mActiveRecord::SchemaMigration Load (0.4ms)[0m [1mSELECT "schema_migrations".* FROM "schema_migrations"[0m
|
4
|
+
Migrating to CreateOpCartProducts (20140829191646)
|
5
|
+
[1m[35m (0.3ms)[0m BEGIN
|
6
|
+
[1m[36m (30.8ms)[0m [1mCREATE TABLE "op_cart_products" ("id" serial primary key, "name" character varying NOT NULL, "description" text NOT NULL, "sku" character varying, "image_url" character varying, "price" integer NOT NULL, "allow_purchases" boolean DEFAULT 'f', "charge_taxes" boolean DEFAULT 'f', "user_id" integer, "created_at" timestamp NOT NULL, "updated_at" timestamp NOT NULL) [0m
|
7
|
+
[1m[35m (1.4ms)[0m CREATE INDEX "index_op_cart_products_on_user_id" ON "op_cart_products" ("user_id")
|
8
|
+
[1m[36mSQL (0.3ms)[0m [1mINSERT INTO "schema_migrations" ("version") VALUES ($1)[0m [["version", "20140829191646"]]
|
9
|
+
[1m[35m (7.3ms)[0m COMMIT
|
10
|
+
Migrating to CreateOpCartOrders (20140829200318)
|
11
|
+
[1m[36m (10.9ms)[0m [1mBEGIN[0m
|
12
|
+
[1m[35m (5.5ms)[0m CREATE TABLE "op_cart_orders" ("id" serial primary key, "total" integer NOT NULL, "tax_amount" integer DEFAULT 0, "status" character varying NOT NULL, "processor_response" json NOT NULL, "shipping_address_id" integer NOT NULL, "user_id" integer NOT NULL, "created_at" timestamp NOT NULL, "updated_at" timestamp NOT NULL)
|
13
|
+
[1m[36m (1.5ms)[0m [1mCREATE INDEX "index_op_cart_orders_on_shipping_address_id" ON "op_cart_orders" ("shipping_address_id")[0m
|
14
|
+
[1m[35m (1.4ms)[0m CREATE INDEX "index_op_cart_orders_on_user_id" ON "op_cart_orders" ("user_id")
|
15
|
+
[1m[36mSQL (0.3ms)[0m [1mINSERT INTO "schema_migrations" ("version") VALUES ($1)[0m [["version", "20140829200318"]]
|
16
|
+
[1m[35m (0.5ms)[0m COMMIT
|
17
|
+
Migrating to CreateOpCartLineItems (20140829201756)
|
18
|
+
[1m[36m (0.3ms)[0m [1mBEGIN[0m
|
19
|
+
[1m[35mSQL (26.9ms)[0m CREATE EXTENSION IF NOT EXISTS "hstore"
|
20
|
+
[1m[36m (4.8ms)[0m [1mCREATE TABLE "op_cart_line_items" ("id" serial primary key, "unit_price" integer NOT NULL, "quantity" integer NOT NULL, "sellable_snapshot" hstore NOT NULL, "sellable_id" integer NOT NULL, "sellable_type" character varying NOT NULL, "order_id" integer NOT NULL, "created_at" timestamp NOT NULL, "updated_at" timestamp NOT NULL) [0m
|
21
|
+
[1m[35m (1.4ms)[0m CREATE INDEX "index_op_cart_line_items_on_sellable_type_and_sellable_id" ON "op_cart_line_items" ("sellable_type", "sellable_id")
|
22
|
+
[1m[36m (1.1ms)[0m [1mCREATE INDEX "index_op_cart_line_items_on_order_id" ON "op_cart_line_items" ("order_id")[0m
|
23
|
+
[1m[35mSQL (0.3ms)[0m INSERT INTO "schema_migrations" ("version") VALUES ($1) [["version", "20140829201756"]]
|
24
|
+
[1m[36m (1.7ms)[0m [1mCOMMIT[0m
|
25
|
+
Migrating to CreateOpCartShippingAddresses (20150125000000)
|
26
|
+
[1m[35m (0.4ms)[0m BEGIN
|
27
|
+
[1m[36m (4.2ms)[0m [1mCREATE TABLE "op_cart_shipping_addresses" ("id" serial primary key, "full_name" character varying NOT NULL, "street" character varying NOT NULL, "street_2" character varying, "locality" character varying NOT NULL, "region" character varying NOT NULL, "postal_code" character varying NOT NULL, "user_id" integer, "created_at" timestamp NOT NULL, "updated_at" timestamp NOT NULL) [0m
|
28
|
+
[1m[35m (1.2ms)[0m CREATE INDEX "index_op_cart_shipping_addresses_on_user_id" ON "op_cart_shipping_addresses" ("user_id")
|
29
|
+
[1m[36mSQL (0.2ms)[0m [1mINSERT INTO "schema_migrations" ("version") VALUES ($1)[0m [["version", "20150125000000"]]
|
30
|
+
[1m[35m (0.4ms)[0m COMMIT
|
31
|
+
Migrating to CreateOpCartCustomers (20150131000000)
|
32
|
+
[1m[36m (0.3ms)[0m [1mBEGIN[0m
|
33
|
+
[1m[35m (5.3ms)[0m CREATE TABLE "op_cart_customers" ("id" serial primary key, "processor_token" character varying, "delinquent" boolean DEFAULT 'f', "default_card_id" integer, "user_id" integer, "created_at" timestamp NOT NULL, "updated_at" timestamp NOT NULL)
|
34
|
+
[1m[36m (0.8ms)[0m [1mCREATE INDEX "index_op_cart_customers_on_default_card_id" ON "op_cart_customers" ("default_card_id")[0m
|
35
|
+
[1m[35m (1.1ms)[0m CREATE INDEX "index_op_cart_customers_on_user_id" ON "op_cart_customers" ("user_id")
|
36
|
+
[1m[36mSQL (0.2ms)[0m [1mINSERT INTO "schema_migrations" ("version") VALUES ($1)[0m [["version", "20150131000000"]]
|
37
|
+
[1m[35m (0.3ms)[0m COMMIT
|
38
|
+
Migrating to CreateOpCartCards (20150131000001)
|
39
|
+
[1m[36m (0.3ms)[0m [1mBEGIN[0m
|
40
|
+
[1m[35m (5.1ms)[0m CREATE TABLE "op_cart_cards" ("id" serial primary key, "processor_token" character varying, "fingerprint" character varying, "last4" character varying, "brand" character varying, "exp_month" character varying, "exp_year" character varying, "customer_id" integer, "created_at" timestamp NOT NULL, "updated_at" timestamp NOT NULL)
|
41
|
+
[1m[36m (1.0ms)[0m [1mCREATE INDEX "index_op_cart_cards_on_processor_token" ON "op_cart_cards" ("processor_token")[0m
|
42
|
+
[1m[35m (1.2ms)[0m CREATE INDEX "index_op_cart_cards_on_fingerprint" ON "op_cart_cards" ("fingerprint")
|
43
|
+
[1m[36m (1.5ms)[0m [1mCREATE INDEX "index_op_cart_cards_on_customer_id" ON "op_cart_cards" ("customer_id")[0m
|
44
|
+
[1m[35mSQL (0.2ms)[0m INSERT INTO "schema_migrations" ("version") VALUES ($1) [["version", "20150131000001"]]
|
45
|
+
[1m[36m (0.5ms)[0m [1mCOMMIT[0m
|
46
|
+
Migrating to CreateOpCartPlans (20150201033629)
|
47
|
+
[1m[35m (0.4ms)[0m BEGIN
|
48
|
+
[1m[36m (6.2ms)[0m [1mCREATE TABLE "op_cart_plans" ("id" serial primary key, "processor_token" character varying, "name" character varying NOT NULL, "description" character varying, "image_url" character varying, "price" integer, "interval_count" integer, "interval" character varying, "trial_period_days" integer, "allow_purchases" boolean DEFAULT 'f', "user_id" integer, "created_at" timestamp NOT NULL, "updated_at" timestamp NOT NULL) [0m
|
49
|
+
[1m[35m (1.3ms)[0m CREATE INDEX "index_op_cart_plans_on_user_id" ON "op_cart_plans" ("user_id")
|
50
|
+
[1m[36m (7.5ms)[0m [1mALTER TABLE "op_cart_plans" ADD CONSTRAINT "fk_rails_f7712cb323"
|
51
|
+
FOREIGN KEY ("user_id")
|
52
|
+
REFERENCES "users" ("id")
|
53
|
+
[0m
|
54
|
+
PG::UndefinedTable: ERROR: relation "users" does not exist
|
55
|
+
: ALTER TABLE "op_cart_plans" ADD CONSTRAINT "fk_rails_f7712cb323"
|
56
|
+
FOREIGN KEY ("user_id")
|
57
|
+
REFERENCES "users" ("id")
|
58
|
+
|
59
|
+
[1m[35m (0.2ms)[0m ROLLBACK
|
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: op_cart
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.4.
|
4
|
+
version: 0.4.1
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Eric Boehs
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date: 2015-02-
|
11
|
+
date: 2015-02-12 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: rails
|
@@ -87,6 +87,7 @@ files:
|
|
87
87
|
- app/models/op_cart/plan_addon.rb
|
88
88
|
- app/models/op_cart/product.rb
|
89
89
|
- app/models/op_cart/shipping_address.rb
|
90
|
+
- app/models/op_cart/subscription.rb
|
90
91
|
- config/initializers/stripe.rb
|
91
92
|
- config/locales/op_cart.en.yml
|
92
93
|
- config/routes.rb
|
@@ -98,6 +99,7 @@ files:
|
|
98
99
|
- db/migrate/20150131000001_create_op_cart_cards.rb
|
99
100
|
- db/migrate/20150201033629_create_op_cart_plans.rb
|
100
101
|
- db/migrate/20150203043805_create_op_cart_plan_addons.rb
|
102
|
+
- db/migrate/20150205220423_create_op_cart_subscriptions.rb
|
101
103
|
- db/seeds.rb
|
102
104
|
- lib/op_cart.rb
|
103
105
|
- lib/op_cart/engine.rb
|
@@ -133,6 +135,7 @@ files:
|
|
133
135
|
- test/dummy/config/locales/en.yml
|
134
136
|
- test/dummy/config/routes.rb
|
135
137
|
- test/dummy/config/secrets.yml
|
138
|
+
- test/dummy/log/development.log
|
136
139
|
- test/dummy/log/test.log
|
137
140
|
- test/dummy/public/404.html
|
138
141
|
- test/dummy/public/422.html
|
@@ -199,6 +202,7 @@ test_files:
|
|
199
202
|
- test/dummy/config/routes.rb
|
200
203
|
- test/dummy/config/secrets.yml
|
201
204
|
- test/dummy/config.ru
|
205
|
+
- test/dummy/log/development.log
|
202
206
|
- test/dummy/log/test.log
|
203
207
|
- test/dummy/public/404.html
|
204
208
|
- test/dummy/public/422.html
|