op_cart 0.4.0 → 0.4.1

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 CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: a055877b518c695c504b0910b9ee3b53d7dee695
4
- data.tar.gz: b09e9b447b40d0185ef69a7f108a2807798ae29e
3
+ metadata.gz: 695ceaa47d75df3df79ef2d8049909b2cd605662
4
+ data.tar.gz: edfc90597c37f748372219b032568a26d17012c0
5
5
  SHA512:
6
- metadata.gz: de05c032008bf45018a3e243bfa6dea54f4dae090fcce0213625b60c8bcffa1f661af8a1a983674cd41373c00e7ba7a43930db10dad57d5cb01b7a733164a7da
7
- data.tar.gz: 8fe5ab19e078945cfe0b34b1ddbd062a26718a9390f3b71058ef4489fcfd4005e1e41ed7e4f2b324b4c7b5ff8469e39688c76c4d79d6f23ed27c00d6f705f486
6
+ metadata.gz: b9f7d545228109490cb3a503023943b4ae6a5dcf196eca748609af70a633fb4c229251570e7b723a9fea78f1eb369c713ac0c31cdf51b98f78eb89e094bba267
7
+ data.tar.gz: 88aa09d43bea2327481b99d933ac087a8093c2e857a22e0b0bf2bb6a253df0208565d43ac1958a6c556e320212230df1e35856c22f7a2383d343a824293a9a6a
@@ -105,7 +105,7 @@ module OpCart
105
105
 
106
106
  def add_shipping_address
107
107
  @order.shipping_address = @shipping_address = ShippingAddress.new(
108
- shipping_address_params.merge user_id: @user.try(:id)
108
+ shipping_address_params.merge user: @user
109
109
  )
110
110
  end
111
111
  end
@@ -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
- plan_addon1 = OpCart::PlanAddon.first_or_create plan_addon1_attrs
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!
@@ -1,3 +1,3 @@
1
1
  module OpCart
2
- VERSION = "0.4.0"
2
+ VERSION = "0.4.1"
3
3
  end
@@ -0,0 +1,59 @@
1
+  (22.3ms) CREATE TABLE "schema_migrations" ("version" character varying NOT NULL) 
2
+  (2.1ms) CREATE UNIQUE INDEX "unique_schema_migrations" ON "schema_migrations" ("version")
3
+ ActiveRecord::SchemaMigration Load (0.4ms) SELECT "schema_migrations".* FROM "schema_migrations"
4
+ Migrating to CreateOpCartProducts (20140829191646)
5
+  (0.3ms) BEGIN
6
+  (30.8ms) CREATE 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) 
7
+  (1.4ms) CREATE INDEX "index_op_cart_products_on_user_id" ON "op_cart_products" ("user_id")
8
+ SQL (0.3ms) INSERT INTO "schema_migrations" ("version") VALUES ($1) [["version", "20140829191646"]]
9
+  (7.3ms) COMMIT
10
+ Migrating to CreateOpCartOrders (20140829200318)
11
+  (10.9ms) BEGIN
12
+  (5.5ms) 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
+  (1.5ms) CREATE INDEX "index_op_cart_orders_on_shipping_address_id" ON "op_cart_orders" ("shipping_address_id")
14
+  (1.4ms) CREATE INDEX "index_op_cart_orders_on_user_id" ON "op_cart_orders" ("user_id")
15
+ SQL (0.3ms) INSERT INTO "schema_migrations" ("version") VALUES ($1) [["version", "20140829200318"]]
16
+  (0.5ms) COMMIT
17
+ Migrating to CreateOpCartLineItems (20140829201756)
18
+  (0.3ms) BEGIN
19
+ SQL (26.9ms) CREATE EXTENSION IF NOT EXISTS "hstore"
20
+  (4.8ms) CREATE 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) 
21
+  (1.4ms) CREATE INDEX "index_op_cart_line_items_on_sellable_type_and_sellable_id" ON "op_cart_line_items" ("sellable_type", "sellable_id")
22
+  (1.1ms) CREATE INDEX "index_op_cart_line_items_on_order_id" ON "op_cart_line_items" ("order_id")
23
+ SQL (0.3ms) INSERT INTO "schema_migrations" ("version") VALUES ($1) [["version", "20140829201756"]]
24
+  (1.7ms) COMMIT
25
+ Migrating to CreateOpCartShippingAddresses (20150125000000)
26
+  (0.4ms) BEGIN
27
+  (4.2ms) CREATE 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) 
28
+  (1.2ms) CREATE INDEX "index_op_cart_shipping_addresses_on_user_id" ON "op_cart_shipping_addresses" ("user_id")
29
+ SQL (0.2ms) INSERT INTO "schema_migrations" ("version") VALUES ($1) [["version", "20150125000000"]]
30
+  (0.4ms) COMMIT
31
+ Migrating to CreateOpCartCustomers (20150131000000)
32
+  (0.3ms) BEGIN
33
+  (5.3ms) 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
+  (0.8ms) CREATE INDEX "index_op_cart_customers_on_default_card_id" ON "op_cart_customers" ("default_card_id")
35
+  (1.1ms) CREATE INDEX "index_op_cart_customers_on_user_id" ON "op_cart_customers" ("user_id")
36
+ SQL (0.2ms) INSERT INTO "schema_migrations" ("version") VALUES ($1) [["version", "20150131000000"]]
37
+  (0.3ms) COMMIT
38
+ Migrating to CreateOpCartCards (20150131000001)
39
+  (0.3ms) BEGIN
40
+  (5.1ms) 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
+  (1.0ms) CREATE INDEX "index_op_cart_cards_on_processor_token" ON "op_cart_cards" ("processor_token")
42
+  (1.2ms) CREATE INDEX "index_op_cart_cards_on_fingerprint" ON "op_cart_cards" ("fingerprint")
43
+  (1.5ms) CREATE INDEX "index_op_cart_cards_on_customer_id" ON "op_cart_cards" ("customer_id")
44
+ SQL (0.2ms) INSERT INTO "schema_migrations" ("version") VALUES ($1) [["version", "20150131000001"]]
45
+  (0.5ms) COMMIT
46
+ Migrating to CreateOpCartPlans (20150201033629)
47
+  (0.4ms) BEGIN
48
+  (6.2ms) CREATE 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) 
49
+  (1.3ms) CREATE INDEX "index_op_cart_plans_on_user_id" ON "op_cart_plans" ("user_id")
50
+  (7.5ms) ALTER TABLE "op_cart_plans" ADD CONSTRAINT "fk_rails_f7712cb323"
51
+ FOREIGN KEY ("user_id")
52
+ REFERENCES "users" ("id")
53
+ 
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
+  (0.2ms) 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.0
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-04 00:00:00.000000000 Z
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