piggybak 0.3.0 → 0.3.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.
data/README.md CHANGED
@@ -11,28 +11,6 @@ Modular / mountable ecommerce gem. Features:
11
11
 
12
12
  * Fully defined backend RailsAdmin interface for adding orders on the backend
13
13
 
14
- This engine explicitly excludes:
15
-
16
- * SSL configuration (to be handled in your parent application)
17
-
18
- * Redirects on login / logout (see recipe below)
19
-
20
- * Coupons and Gift cerficates (May be added later)
21
-
22
- * Per unit inventory tracking
23
-
24
- * Downloadable products
25
-
26
- This engine is highly dependent on:
27
-
28
- * Rails 3.1 (Assets, Engines)
29
-
30
- * RailsAdmin (Admin UI)
31
-
32
- * Devise (User Authentication)
33
-
34
- * CanCan (User Authorization)
35
-
36
14
  Installation
37
15
  ========
38
16
 
@@ -52,62 +30,14 @@ Installation
52
30
 
53
31
  mount Piggybak::Engine => '/checkout', :as => 'piggybak'" to config/routes
54
32
 
55
- Integration Components
33
+ More Details
56
34
  ========
57
35
 
58
- * Add acts_as_variant to models that will be sellable
59
- * Add acts_as_orderer to user model (or model that devise hooks into as authenticated user)
60
- * Add <%= cart_form(@some_item) %> to view to display cart form
61
- * Add <%= cart_link %> to display link to cart
62
- * Add <%= orders_link %> to display link to user orders
63
-
64
- Recipes
65
- ========
66
-
67
- * Redirect after login / logout
68
-
69
- before_filter :set_last_page
70
- def set_last_page
71
- if !request.xhr? && !request.url.match(/users\/sign_in/) && !request.url.match(/users\/sign_out/)
72
- session[:return_to] = request.url
73
- end
74
- end
75
- def after_sign_in_path_for(resource_or_scope)
76
- session[:return_to] || root_url
77
- end
78
- def after_sign_out_path_for(resource_or_scope)
79
- session[:return_to] || root_url
80
- end
81
-
82
- * Cancan access control
83
-
84
- class Ability
85
- include CanCan::Ability
86
- def initialize(user)
87
- if user && user.roles.include?(Role.find_by_name("admin"))
88
- can :access, :rails_admin
89
- can :manage, [ #Insert your app models here
90
- ::Piggybak::Variant,
91
- ::Piggybak::ShippingMethod,
92
- ::Piggybak::PaymentMethod,
93
- ::Piggybak::TaxMethod,
94
- ::Piggybak::State,
95
- ::Piggybak::Country]
96
- can [:download, :email, :read, :create, :update, :history, :export], ::Piggybak::Order
97
- end
98
- end
99
- end
100
-
101
-
102
- TODOs
103
- ========
36
+ Visit the project website [here][project-website] to see more documentation and view a demo.
104
37
 
105
- * Test: Test email send functionality
106
- * Test: Add unit testing
107
- * Feature: Add API to call Refund if profiles only
108
- * Feature: Add helper for Google Analytics order tagging
38
+ [project-website]: http://www.piggybak.org/
109
39
 
110
40
  Copyright
111
41
  ========
112
42
 
113
- Copyright (c) 2011 Steph Skardal. See LICENSE.txt for further details.
43
+ Copyright (c) 2011 End Point & Steph Skardal. See LICENSE.txt for further details.
data/VERSION CHANGED
@@ -1 +1 @@
1
- 0.3.0
1
+ 0.3.1
@@ -2,7 +2,9 @@ var tax_total = 0;
2
2
 
3
3
  $(function() {
4
4
  piggybak.initialize_listeners();
5
- piggybak.update_shipping_options($('#piggybak_order_shipping_address_attributes_state_id'));
5
+ piggybak.update_shipping_options($('#piggybak_order_shipping_address_attributes_state_id'), function() {
6
+ $('#piggybak_order_shipments_attributes_0_shipping_method_id').val(previous_shipping);
7
+ });
6
8
  piggybak.update_tax();
7
9
  });
8
10
 
@@ -35,7 +37,7 @@ var piggybak = {
35
37
  $('#piggybak_order_shipping_address_attributes_state_id').val(state);
36
38
  });
37
39
  },
38
- update_shipping_options: function(field) {
40
+ update_shipping_options: function(field, block) {
39
41
  var shipping_field = $('#piggybak_order_shipments_attributes_0_shipping_method_id');
40
42
  shipping_field.hide();
41
43
  var shipping_data = {};
@@ -56,6 +58,9 @@ var piggybak = {
56
58
  });
57
59
  shipping_field.show();
58
60
  piggybak.update_totals();
61
+ if(block) {
62
+ block();
63
+ }
59
64
  }
60
65
  });
61
66
  },
@@ -41,7 +41,10 @@ var piggybak_states = {
41
41
  new_field = $('<input>');
42
42
  }
43
43
  var old_field = $('#piggybak_order_' + type + '_address_attributes_state_id');
44
- new_field.attr('name', old_field.attr('name')).attr('id', old_field.attr('id')).val(old_field.val());
44
+ new_field.attr('name', old_field.attr('name')).attr('id', old_field.attr('id'));
45
+ if(old_field.prop('tagName') == new_field.prop('tagName')) {
46
+ new_field.val(old_field.val());
47
+ }
45
48
  old_field.replaceWith(new_field);
46
49
 
47
50
  if(block) {
@@ -6,30 +6,19 @@ module Piggybak
6
6
  @cart = Piggybak::Cart.new(request.cookies["cart"])
7
7
  @order = Piggybak::Order.new
8
8
 
9
- if current_user
10
- @order.user = current_user
11
- @order.email = current_user.email
12
- end
13
-
14
- @order.billing_address ||= Piggybak::Address.new
15
- @order.shipping_address ||= Piggybak::Address.new
16
-
17
- @order.shipments ||= [Piggybak::Shipment.new]
18
-
19
- @order.payments ||= [Piggybak::Payment.new]
9
+ @order.initialize_user(current_user)
20
10
  end
21
11
 
22
12
  def submit
23
13
  response.headers['Cache-Control'] = 'no-cache'
14
+ @cart = Piggybak::Cart.new(request.cookies["cart"])
24
15
 
25
16
  begin
26
17
  ActiveRecord::Base.transaction do
27
18
  @order = Piggybak::Order.new(params[:piggybak_order])
28
- @order.user = current_user if current_user
29
- @order.payments.first.payment_method_id = Piggybak::PaymentMethod.find_by_active(true).id
19
+ @order.initialize_user(current_user)
30
20
 
31
- cart = Piggybak::Cart.new(request.cookies["cart"])
32
- @order.add_line_items(cart)
21
+ @order.add_line_items(@cart)
33
22
 
34
23
  if @order.save
35
24
  Piggybak::Notifier.order_notification(@order)
@@ -42,15 +31,10 @@ module Piggybak
42
31
  end
43
32
  end
44
33
  rescue Exception => e
45
- @cart = Piggybak::Cart.new(request.cookies["cart"])
46
-
47
- if current_user
48
- @order.user = current_user
49
- @order.email = current_user.email
34
+ if @order.errors.empty?
35
+ @order.errors.add "", "Your order could not go through. Please try again."
50
36
  end
51
37
 
52
- @user = current_user
53
-
54
38
  render "piggybak/orders/show"
55
39
  end
56
40
  end
@@ -58,6 +42,11 @@ module Piggybak
58
42
  def receipt
59
43
  response.headers['Cache-Control'] = 'no-cache'
60
44
 
45
+ if !session.has_key?(:last_order)
46
+ redirect_to root_url
47
+ return
48
+ end
49
+
61
50
  @order = Piggybak::Order.find(session[:last_order])
62
51
  end
63
52
 
@@ -14,4 +14,9 @@ module PiggybakHelper
14
14
  link_to text, piggybak.orders_list_url
15
15
  end
16
16
  end
17
+ def piggybak_track_order(store_name)
18
+ if params[:controller] == "piggybak/orders" && params[:action] == "receipt" && session.has_key?(:last_order)
19
+ render "piggybak/orders/google_analytics", :order => @order, :store_name => store_name
20
+ end
21
+ end
17
22
  end
@@ -23,10 +23,14 @@ module Piggybak
23
23
  if self.address2 && self.address2 != ''
24
24
  address += "#{self.address2}<br />"
25
25
  end
26
- address += "#{self.city}, #{self.state ? self.state.name : self.state_id} #{self.zip}<br />"
26
+ address += "#{self.city}, #{self.state_display} #{self.zip}<br />"
27
27
  address += "#{self.country.name}"
28
28
  address
29
29
  end
30
30
  alias :display :admin_label
31
+
32
+ def state_display
33
+ self.state ? self.state.name : self.state_id
34
+ end
31
35
  end
32
36
  end
@@ -23,10 +23,28 @@ module Piggybak
23
23
  validates_presence_of :tax_charge
24
24
  validates_presence_of :created_at
25
25
 
26
+ after_initialize :initialize_nested
26
27
  before_validation :set_defaults
27
28
  after_validation :update_totals
28
29
  before_save :process_payments, :update_status
29
30
 
31
+ def initialize_nested
32
+ self.billing_address ||= Piggybak::Address.new
33
+ self.shipping_address ||= Piggybak::Address.new
34
+ self.shipments ||= [Piggybak::Shipment.new]
35
+ self.payments ||= [Piggybak::Payment.new]
36
+ if self.payments.any?
37
+ self.payments.first.payment_method_id = Piggybak::PaymentMethod.find_by_active(true).id
38
+ end
39
+ end
40
+
41
+ def initialize_user(user)
42
+ if user
43
+ self.user = user
44
+ self.email = user.email
45
+ end
46
+ end
47
+
30
48
  def process_payments
31
49
  has_errors = false
32
50
  self.payments.each do |payment|
@@ -63,7 +81,11 @@ module Piggybak
63
81
  self.tax_charge = 0
64
82
 
65
83
  self.line_items.each do |line_item|
66
- line_item.total = line_item.variant.price * line_item.quantity
84
+ if line_item.variant
85
+ line_item.total = line_item.variant.price * line_item.quantity
86
+ else
87
+ line_item.total = 0
88
+ end
67
89
  end
68
90
  end
69
91
 
@@ -71,14 +93,14 @@ module Piggybak
71
93
  self.total = 0
72
94
 
73
95
  self.line_items.each do |line_item|
74
- self.total += line_item.total
96
+ self.total += line_item.total
75
97
  end
76
98
 
77
99
  self.tax_charge = TaxMethod.calculate_tax(self)
78
100
  self.total += self.tax_charge
79
101
 
80
102
  shipments.each do |shipment|
81
- if shipment.new_record?
103
+ if shipment.new_record? && shipment.shipping_method
82
104
  calculator = shipment.shipping_method.klass.constantize
83
105
  shipment.total = calculator.rate(shipment.shipping_method, self)
84
106
  end
@@ -90,8 +112,6 @@ module Piggybak
90
112
  self.total -= credit.total
91
113
  end
92
114
 
93
- self.total = self.total.to_c
94
-
95
115
  self.total_due = self.total
96
116
  payments.each do |payment|
97
117
  if payment.status == "paid"
@@ -110,7 +130,7 @@ module Piggybak
110
130
  else
111
131
  if self.total == 0.00
112
132
  self.status = "new"
113
- elsif self.shipments.all? { |s| s.status == "shipped" }
133
+ elsif self.shipments.any? && self.shipments.all? { |s| s.status == "shipped" }
114
134
  self.status = "shipped"
115
135
  else
116
136
  self.status = "paid"
@@ -126,7 +146,7 @@ module Piggybak
126
146
  {
127
147
  :address1 => self.billing_address.address1,
128
148
  :city => self.billing_address.city,
129
- :state => self.billing_address.state,
149
+ :state => self.billing_address.state_display,
130
150
  :zip => self.billing_address.zip,
131
151
  :country => "US"
132
152
  }
@@ -9,6 +9,9 @@ module Piggybak
9
9
  validates_presence_of :month
10
10
  validates_presence_of :year
11
11
 
12
+ attr_accessor :number
13
+ attr_accessor :verification_value
14
+
12
15
  def status_enum
13
16
  ["paid", "refunded"]
14
17
  end
@@ -40,8 +43,6 @@ module Piggybak
40
43
  gateway_response = gateway.authorize(self.order.total_due*100, credit_card, :address => self.order.avs_address)
41
44
  if gateway_response.success?
42
45
  self.attributes = { :total => self.order.total_due,
43
- :number => 'hidden',
44
- :verification_value => 'hidden',
45
46
  :transaction_id => payment_gateway.transaction_id(gateway_response) }
46
47
  gateway.capture(1000, gateway_response.authorization)
47
48
  return true
@@ -0,0 +1,23 @@
1
+ var _gaq = _gaq || [];
2
+ _gaq.push(['_addTrans',
3
+ '<%= @order.id %>',
4
+ '<%= store_name %>',
5
+ '<%= @order.total %>',
6
+ '<%= @order.tax_charge %>',
7
+ '<%= @order.shipments.first.total %>',
8
+ '<%= @order.billing_address.city %>',
9
+ '<%= @order.billing_address.state_display %>',
10
+ '<%= @order.billing_address.country.name %>'
11
+ ]);
12
+
13
+ <% @order.line_items.each do |line_item| -%>
14
+ _gaq.push(['_addItem',
15
+ '<%= @order.id %>',
16
+ '<%= line_item.variant.sku %>',
17
+ '<%= line_item.variant.description %>',
18
+ '', // category or variation
19
+ '<%= line_item.variant.price %>', //unit price
20
+ '<%= line_item.quantity %>'
21
+ ]);
22
+ <% end -%>
23
+ _gaq.push(['_trackTrans']); //submits transaction to the Analytics servers
@@ -114,4 +114,9 @@
114
114
  var shipping_lookup = "<%= piggybak.orders_shipping_url %>";
115
115
  var tax_lookup = "<%= piggybak.orders_tax_url %>";
116
116
  var geodata_lookup = "<%= piggybak.orders_geodata_url %>";
117
+ <% if params.has_key?(:piggybak_order) && params[:piggybak_order].has_key?(:shipments_attributes) -%>
118
+ var previous_shipping = <%= params[:piggybak_order][:shipments_attributes]["0"][:shipping_method_id] %>;
119
+ <% else -%>
120
+ var previous_shipping = "";
121
+ <% end -%>
117
122
  </script>
@@ -1,7 +1,15 @@
1
1
  = form.fields_for field.name do |nested_form|
2
2
  %blockquote
3
3
  - if nested_form.object.new_record?
4
- = nested_form.link_to_remove "cancel", :class => 'label notice'
4
+ = nested_form.link_to_remove "cancel", :class => 'label notice', :id => "payments_cancel"
5
5
  = nested_form.generate({:action => :create, :model_config => field.associated_model_config, :nested_in => field.name })
6
6
  %hr
7
- = form.link_to_add t("admin.index.add_new"), field.name, :class => 'label notice'
7
+ = form.link_to_add t("admin.index.add_new"), field.name, :class => 'label notice', :id => "payments_add"
8
+
9
+ :javascript
10
+ $('#payments_add').live('click', function() {
11
+ $(this).hide();
12
+ });
13
+ $('#payments_cancel').live('click', function() {
14
+ $('#payments_add').show();
15
+ });
@@ -0,0 +1,11 @@
1
+ class DropCcFields < ActiveRecord::Migration
2
+ def up
3
+ remove_column :payments, :number
4
+ remove_column :payments, :verification_value
5
+ end
6
+
7
+ def down
8
+ add_column :payments, :number, :string
9
+ add_column :payments, :verification_value, :string
10
+ end
11
+ end
data/piggybak.gemspec CHANGED
@@ -5,11 +5,11 @@
5
5
 
6
6
  Gem::Specification.new do |s|
7
7
  s.name = "piggybak"
8
- s.version = "0.3.0"
8
+ s.version = "0.3.1"
9
9
 
10
10
  s.required_rubygems_version = Gem::Requirement.new(">= 0") if s.respond_to? :required_rubygems_version=
11
11
  s.authors = ["Steph Skardal", "Brian Buchalter"]
12
- s.date = "2012-01-09"
12
+ s.date = "2012-01-11"
13
13
  s.description = "Mountable ecommerce"
14
14
  s.email = "steph@endpoint.com"
15
15
  s.extra_rdoc_files = [
@@ -59,6 +59,7 @@ Gem::Specification.new do |s|
59
59
  "app/views/piggybak/notifier/order_notification.text.erb",
60
60
  "app/views/piggybak/orders/_address_form.html.erb",
61
61
  "app/views/piggybak/orders/_details.html.erb",
62
+ "app/views/piggybak/orders/_google_analytics.html.erb",
62
63
  "app/views/piggybak/orders/download.text.erb",
63
64
  "app/views/piggybak/orders/list.html.erb",
64
65
  "app/views/piggybak/orders/no_access.text.erb",
@@ -87,6 +88,7 @@ Gem::Specification.new do |s|
87
88
  "db/migrate/20120104020930_populate_countries_and_states.rb",
88
89
  "db/migrate/20120106010412_create_credits.rb",
89
90
  "db/migrate/20120107135459_add_active_to_countries.rb",
91
+ "db/migrate/20120111195534_drop_cc_fields.rb",
90
92
  "lib/acts_as_orderer/base.rb",
91
93
  "lib/acts_as_variant/base.rb",
92
94
  "lib/currency.rb",
metadata CHANGED
@@ -2,7 +2,7 @@
2
2
  name: piggybak
3
3
  version: !ruby/object:Gem::Version
4
4
  prerelease:
5
- version: 0.3.0
5
+ version: 0.3.1
6
6
  platform: ruby
7
7
  authors:
8
8
  - Steph Skardal
@@ -11,7 +11,7 @@ autorequire:
11
11
  bindir: bin
12
12
  cert_chain: []
13
13
 
14
- date: 2012-01-09 00:00:00 Z
14
+ date: 2012-01-11 00:00:00 Z
15
15
  dependencies:
16
16
  - !ruby/object:Gem::Dependency
17
17
  name: countries
@@ -153,6 +153,7 @@ files:
153
153
  - app/views/piggybak/notifier/order_notification.text.erb
154
154
  - app/views/piggybak/orders/_address_form.html.erb
155
155
  - app/views/piggybak/orders/_details.html.erb
156
+ - app/views/piggybak/orders/_google_analytics.html.erb
156
157
  - app/views/piggybak/orders/download.text.erb
157
158
  - app/views/piggybak/orders/list.html.erb
158
159
  - app/views/piggybak/orders/no_access.text.erb
@@ -181,6 +182,7 @@ files:
181
182
  - db/migrate/20120104020930_populate_countries_and_states.rb
182
183
  - db/migrate/20120106010412_create_credits.rb
183
184
  - db/migrate/20120107135459_add_active_to_countries.rb
185
+ - db/migrate/20120111195534_drop_cc_fields.rb
184
186
  - lib/acts_as_orderer/base.rb
185
187
  - lib/acts_as_variant/base.rb
186
188
  - lib/currency.rb
@@ -200,7 +202,7 @@ required_ruby_version: !ruby/object:Gem::Requirement
200
202
  requirements:
201
203
  - - ">="
202
204
  - !ruby/object:Gem::Version
203
- hash: -3349211022741350095
205
+ hash: 379901271419735142
204
206
  segments:
205
207
  - 0
206
208
  version: "0"