piggybak 0.5.5 → 0.6.0

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 (47) hide show
  1. data/README.md +32 -25
  2. data/VERSION +1 -1
  3. data/app/assets/javascripts/piggybak.js +11 -1
  4. data/app/assets/javascripts/piggybak.states.js +6 -5
  5. data/app/controllers/piggybak/orders_controller.rb +14 -22
  6. data/app/models/piggybak/address.rb +4 -1
  7. data/app/models/piggybak/adjustment.rb +1 -25
  8. data/app/models/piggybak/cart.rb +18 -17
  9. data/app/models/piggybak/line_item.rb +106 -19
  10. data/app/models/piggybak/order.rb +94 -108
  11. data/app/models/piggybak/payment.rb +25 -27
  12. data/app/models/piggybak/payment_method.rb +3 -1
  13. data/app/models/piggybak/payment_method_value.rb +3 -1
  14. data/app/models/piggybak/{variant.rb → sellable.rb} +6 -4
  15. data/app/models/piggybak/shipment.rb +4 -10
  16. data/app/models/piggybak/shipping_calculator/flat_rate.rb +4 -0
  17. data/app/models/piggybak/shipping_calculator/free.rb +4 -0
  18. data/app/models/piggybak/shipping_calculator/range.rb +4 -0
  19. data/app/models/piggybak/shipping_method.rb +1 -1
  20. data/app/models/piggybak/tax_method.rb +1 -1
  21. data/app/views/piggybak/cart/_form.html.erb +7 -7
  22. data/app/views/piggybak/cart/_items.html.erb +14 -5
  23. data/app/views/piggybak/notifier/order_notification.text.erb +10 -2
  24. data/app/views/piggybak/orders/_details.html.erb +14 -5
  25. data/app/views/piggybak/orders/_google_analytics.html.erb +3 -3
  26. data/app/views/piggybak/orders/download.text.erb +6 -6
  27. data/app/views/piggybak/orders/submit.html.erb +55 -49
  28. data/app/views/rails_admin/main/_location_select.html.haml +3 -3
  29. data/app/views/rails_admin/main/_order_details.html.erb +12 -24
  30. data/app/views/rails_admin/main/_polymorphic_nested.html.haml +29 -0
  31. data/bin/piggybak +12 -0
  32. data/config/routes.rb +0 -2
  33. data/db/migrate/20121008160425_rename_variants_to_sellables.rb +11 -0
  34. data/db/migrate/20121008175144_line_item_rearchitecture.rb +96 -0
  35. data/lib/acts_as_sellable.rb +21 -0
  36. data/lib/formatted_changes.rb +2 -2
  37. data/lib/piggybak.rb +80 -126
  38. data/lib/piggybak/cli.rb +81 -0
  39. data/lib/piggybak/config.rb +21 -0
  40. data/piggybak.gemspec +10 -7
  41. data/spec/dummy_app/app/models/image.rb +1 -1
  42. data/spec/factories.rb +1 -1
  43. metadata +52 -49
  44. data/app/controllers/piggybak/payments_controller.rb +0 -14
  45. data/app/views/rails_admin/main/_order_notes.html.erb +0 -1
  46. data/app/views/rails_admin/main/_payment_refund.html.haml +0 -6
  47. data/lib/acts_as_variant.rb +0 -15
@@ -2,6 +2,10 @@ module Piggybak
2
2
  class ShippingCalculator::FlatRate
3
3
  KEYS = ["rate"]
4
4
 
5
+ def self.description
6
+ "Flat Rate"
7
+ end
8
+
5
9
  def self.available?(*args)
6
10
  true
7
11
  end
@@ -2,6 +2,10 @@ module Piggybak
2
2
  class ShippingCalculator::Free
3
3
  KEYS = []
4
4
 
5
+ def self.description
6
+ "Free Shipping"
7
+ end
8
+
5
9
  def self.available?(method, object)
6
10
  true
7
11
  end
@@ -2,6 +2,10 @@ module Piggybak
2
2
  class ShippingCalculator::Range
3
3
  KEYS = ["cost", "upper", "lower"]
4
4
 
5
+ def self.description
6
+ "Cost per Range"
7
+ end
8
+
5
9
  def self.available?(method, object)
6
10
  low_end = method.metadata.detect { |m| m.key == "lower" }.value
7
11
  high_end = method.metadata.detect { |m| m.key == "upper" }.value
@@ -23,7 +23,7 @@ module Piggybak
23
23
  end
24
24
 
25
25
  def klass_enum
26
- Piggybak.config.shipping_calculators
26
+ Piggybak.config.shipping_calculators.collect { |b| [ b.constantize.description, b ] }
27
27
  end
28
28
 
29
29
  def self.available_methods(cart)
@@ -35,7 +35,7 @@ module Piggybak
35
35
  total_tax += calculator.rate(tax_method, object)
36
36
  end
37
37
  end
38
-
38
+
39
39
  total_tax
40
40
  end
41
41
 
@@ -1,14 +1,14 @@
1
- <% if object.reflections.keys.include?(:piggybak_variant) -%>
2
- <% if object.piggybak_variant && object.piggybak_variant.active -%>
3
- <% if object.piggybak_variant.quantity > 0 || object.piggybak_variant.unlimited_inventory -%>
1
+ <% if object.reflections.keys.include?(:piggybak_sellable) -%>
2
+ <% if object.piggybak_sellable && object.piggybak_sellable.active -%>
3
+ <% if object.piggybak_sellable.quantity > 0 || object.piggybak_sellable.unlimited_inventory -%>
4
4
  <%= form_tag piggybak.cart_add_url do -%>
5
- <div id="variant_details">
6
- <span id="title"><%= object.piggybak_variant.description %></span>
7
- <span id="price"><%= number_to_currency object.piggybak_variant.price %></span>
5
+ <div id="sellable_details">
6
+ <span id="title"><%= object.piggybak_sellable.description %></span>
7
+ <span id="price"><%= number_to_currency object.piggybak_sellable.price %></span>
8
8
  </div>
9
9
  <label>Quantity</label>
10
10
  <%= text_field_tag :quantity, "1" %>
11
- <%= hidden_field_tag :variant_id, object.piggybak_variant.id %>
11
+ <%= hidden_field_tag :sellable_id, object.piggybak_sellable.id %>
12
12
  <%= submit_tag "Add to Cart", :id => "submit" %>
13
13
  <% end -%>
14
14
  <% else -%>
@@ -12,19 +12,19 @@
12
12
  </tr>
13
13
  <% @cart.items.each do |item| %>
14
14
  <tr>
15
- <td><%= item[:variant].description %></td>
16
- <td><%= number_to_currency item[:variant].price %></td>
15
+ <td><%= item[:sellable].description %></td>
16
+ <td><%= number_to_currency item[:sellable].price %></td>
17
17
  <td>
18
18
  <% if page == "cart" -%>
19
- <%= text_field_tag "quantity[#{item[:variant].id}]", item[:quantity] %>
19
+ <%= text_field_tag "quantity[#{item[:sellable].id}]", item[:quantity] %>
20
20
  <% else -%>
21
21
  <%= item[:quantity] %>
22
22
  <% end -%>
23
23
  </td>
24
- <td><%= number_to_currency item[:quantity]*item[:variant].price %></td>
24
+ <td><%= number_to_currency item[:quantity]*item[:sellable].price %></td>
25
25
  <% if page == "cart" -%>
26
26
  <td>
27
- <%= link_to "Remove", piggybak.remove_item_url(item[:variant].id), :method => :delete %>
27
+ <%= link_to "Remove", piggybak.remove_item_url(item[:sellable].id), :method => :delete %>
28
28
  </td>
29
29
  <% end -%>
30
30
  </tr>
@@ -48,6 +48,15 @@
48
48
  <td>Shipping</td>
49
49
  <td id="shipping_total"></td>
50
50
  </tr>
51
+ <% Piggybak.config.line_item_types.each do |k, v| -%>
52
+ <% if v.has_key?(:display_in_cart) -%>
53
+ <tr id="<%= "#{k}_row" %>" style="display:none;">
54
+ <td colspan="<%= page == "cart" ? "3" : "2" %>"></td>
55
+ <td><%= v[:display_in_cart] %></td>
56
+ <td class="extra_totals" id="<%= k %>_total">$0.00</td>
57
+ </tr>
58
+ <% end -%>
59
+ <% end -%>
51
60
  <tr>
52
61
  <td colspan="<%= page == "cart" ? "3" : "2" %>"></td>
53
62
  <td>Total</td>
@@ -2,8 +2,16 @@ Thanks for your order!
2
2
 
3
3
  Items
4
4
 
5
- <% @order.line_items.each do |line_item| %>
6
- <%= line_item.variant.description %> x <%= line_item.quantity %> = <%= number_to_currency line_item.total %>
5
+ <% @order.line_items.sellables.each do |line_item| %>
6
+ <%= line_item.description %> x <%= line_item.quantity %> = <%= number_to_currency line_item.price %>
7
+ <% end -%>
8
+
9
+ <% @order.line_items.shipments.each do |line_item| %>
10
+ <%= line_item.description %> = <%= number_to_currency line_item.price %>
11
+ <% end -%>
12
+
13
+ <% @order.line_items.payments.each do |line_item| %>
14
+ <%= line_item.description %> = <%= number_to_currency line_item.price %>
7
15
  <% end -%>
8
16
 
9
17
  Total
@@ -5,12 +5,12 @@
5
5
  <th>Quantity</th>
6
6
  <th>Subtotal</th>
7
7
  </tr>
8
- <% order.line_items.each do |line_item| %>
8
+ <% order.line_items.sellables.each do |line_item| %>
9
9
  <tr>
10
10
  <td><%= line_item.description %></td>
11
- <td><%= number_to_currency line_item.price %></td>
11
+ <td><%= number_to_currency line_item.unit_price %></td>
12
12
  <td><%= line_item.quantity %></td>
13
- <td><%= number_to_currency line_item.total %></td>
13
+ <td><%= number_to_currency line_item.price %></td>
14
14
  </tr>
15
15
  <% end -%>
16
16
  <tr>
@@ -19,7 +19,7 @@
19
19
  <tr>
20
20
  <td colspan="2"></td>
21
21
  <td>Subtotal</td>
22
- <td><%= number_to_currency order.line_items.inject(0) { |subtotal, li| subtotal + li.total } %></td>
22
+ <td><%= number_to_currency order.line_items.sellables.inject(0) { |subtotal, li| subtotal + li.price } %></td>
23
23
  </tr>
24
24
  <tr>
25
25
  <td colspan="2"></td>
@@ -29,8 +29,17 @@
29
29
  <tr>
30
30
  <td colspan="2"></td>
31
31
  <td>Shipping</td>
32
- <td><%= number_to_currency order.shipments.inject(0) { |shipping, shipment| shipping + shipment.total } %></td>
32
+ <td><%= number_to_currency order.shipment_charge %></td>
33
+ </tr>
34
+ <% Piggybak.config.line_item_types.each do |k, v| -%>
35
+ <% if v.has_key?(:display_in_cart) && order.line_items.detect { |li| li.line_item_type == k.to_s } -%>
36
+ <tr>
37
+ <td colspan="2"></td>
38
+ <td><%= v[:display_in_cart] %></td>
39
+ <td class="extra_totals" id="<%= k %>_total"><%= number_to_currency order.line_items.detect { |li| li.line_item_type == k.to_s }.price %></td>
33
40
  </tr>
41
+ <% end -%>
42
+ <% end -%>
34
43
  <tr>
35
44
  <td colspan="2"></td>
36
45
  <td>Total</td>
@@ -4,16 +4,16 @@ _gaq.push(['_addTrans',
4
4
  '<%= store_name %>',
5
5
  '<%= @order.total %>',
6
6
  '<%= @order.tax_charge %>',
7
- '<%= @order.shipments.first.total %>',
7
+ '<%= @order.shipment_charge %>',
8
8
  '<%= @order.billing_address.city %>',
9
9
  '<%= @order.billing_address.state_display %>',
10
10
  '<%= @order.billing_address.country.name %>'
11
11
  ]);
12
12
 
13
- <% @order.line_items.each do |line_item| -%>
13
+ <% @order.line_items.sellables.each do |line_item| -%>
14
14
  _gaq.push(['_addItem',
15
15
  '<%= @order.id %>',
16
- '<%= line_item.variant.try(:sku) %>',
16
+ '<%= line_item.sellable.try(:sku) %>',
17
17
  '<%= line_item.description %>',
18
18
  '', // category or variation
19
19
  '<%= line_item.price %>', //unit price
@@ -3,16 +3,16 @@ Order: #<%= @order.id %>
3
3
  Email: <%= @order.email %>
4
4
  Phone: <%= @order.phone %>
5
5
 
6
- <% @order.line_items.each do |line_item| %>
7
- <%= line_item.quantity %> x <%= raw line_item.description %> (<%= number_to_currency line_item.total %>)
6
+ <% @order.line_items.sellables.each do |line_item| %>
7
+ <%= line_item.quantity %> x <%= raw line_item.description %> (<%= number_to_currency line_item.price %>)
8
8
  <% end -%>
9
9
 
10
- Subtotal: <%= number_to_currency @order.line_items.inject(0) { |subtotal, li| subtotal + li.total } %>
11
- Shipping & Handling: <%= number_to_currency @order.shipments.inject(0) { |shipping, shipment| shipping + shipment.total } %>
10
+ Subtotal: <%= number_to_currency @order.line_items.sellables.inject(0) { |subtotal, li| subtotal + li.price } %>
11
+ Shipping & Handling: <%= number_to_currency @order.line_items.shipments.inject(0) { |shipping, shipment| shipping + shipment.price } %>
12
12
  Tax: <%= number_to_currency @order.tax_charge %>
13
13
  Total: <%= number_to_currency @order.total %>
14
- Less Payment: <%= number_to_currency(@order.payments.inject(0) { |total, p| total + p.total if p.status == "paid" }) %>
15
- Adjustments: <%= number_to_currency(@order.adjustments.inject(0) { |total, adj| total + adj.total }) %>
14
+ Less Payment: <%= number_to_currency(@order.line_items.payments.inject(0) { |total, p| total + p.price if p.payment.status == "paid" }) %>
15
+ Adjustments: <%= number_to_currency(@order.line_items.adjustments.inject(0) { |total, adj| total + adj.price }) %>
16
16
  Balance Due: <%= number_to_currency @order.total_due %>
17
17
 
18
18
  Billing Information
@@ -6,7 +6,7 @@
6
6
  <% if @order.errors.any? -%>
7
7
  <div id="checkout_error">
8
8
  <b>You have errors with your submission:</b><br />
9
- <%= raw @order.errors.full_messages.join("<br />") %>
9
+ <%= raw @order.errors.full_messages.collect { |b| b.gsub(/^Line items payment/, 'Payment').gsub(/^Line items shipment shipping/, 'Shipping') }.join("<br />") %>
10
10
  </div>
11
11
  <% end -%>
12
12
  <div class="clear"></div>
@@ -50,59 +50,65 @@
50
50
  <div id="add_details">
51
51
  <div id="shipping">
52
52
  <h3>Shipping Option</h3>
53
- <%= f.fields_for :shipments, f.object.shipments.build do |shipment| %>
54
- <div class="item">
55
- <%= shipment.label :shipping_method_id %>
56
- <%= shipment.select :shipping_method_id, [] %>
57
- <div id="shipping_spinner" style="display:none;">
58
- <%= image_tag "ajax-loader.gif" %>
59
- </div>
60
- <div id="shipping_default" style="display:none;">
61
- Please enter a shipping address.
62
- </div>
63
- <div id="shipping_empty" style="display:none;">
64
- No shipping methods found.
65
- </div>
66
- </div>
53
+ <%= f.fields_for :line_items, @order.line_items.detect { |li| li.line_item_type == "shipment" } do |line_item_f| %>
54
+ <%= line_item_f.hidden_field :line_item_type, { :value => "shipment" } %>
55
+ <%= line_item_f.fields_for :shipment do |shipment| %>
56
+ <div class="item">
57
+ <%= shipment.label :shipping_method_id %>
58
+ <%= shipment.select :shipping_method_id, [] %>
59
+ <div id="shipping_spinner" style="display:none;">
60
+ <%= image_tag "ajax-loader.gif" %>
61
+ </div>
62
+ <div id="shipping_default" style="display:none;">
63
+ Please enter a shipping address.
64
+ </div>
65
+ <div id="shipping_empty" style="display:none;">
66
+ No shipping methods found.
67
+ </div>
68
+ </div>
69
+ <% end -%>
67
70
  <% end -%>
68
71
  </div>
69
72
  <div id="payment">
70
73
  <h3>Payment</h3>
71
- <%= f.fields_for :payments, f.object.payments.build do |payment| %>
72
- <div class="item">
73
- <%= payment.label :number %>
74
- <% if @order.errors.keys.include?("payments.number".to_sym) %>
75
- <span class="field_with_errors">
76
- <%= payment.text_field :number %>
77
- </span>
78
- <% else -%>
79
- <%= payment.text_field :number %>
80
- <% end -%>
81
- </div>
82
-
83
- <div class="item">
84
- <%= payment.label :verification_value %>
85
- <% if @order.errors.keys.include?("payments.verification_value".to_sym) %>
86
- <span class="field_with_errors">
87
- <%= payment.text_field :verification_value %>
88
- </span>
89
- <% else -%>
90
- <%= payment.text_field :verification_value %>
91
- <% end -%>
92
- </div>
93
-
94
- <div class="item">
95
- <%= payment.label :month %>
96
- <% if @order.errors.keys.include?("payments.verification_value".to_sym) %>
97
- <span class="field_with_errors">
98
- <%= payment.select :month, 1.upto(12).to_a %> /
99
- <%= payment.select :year, Time.now.year.upto(Time.now.year + 10).to_a %>
100
- </span>
101
- <% else -%>
102
- <%= payment.select :month, 1.upto(12).to_a %> /
103
- <%= payment.select :year, Time.now.year.upto(Time.now.year + 10).to_a %>
74
+ <%= f.fields_for :line_items, @order.line_items.detect { |li| li.line_item_type == "payment" } do |line_item_f| %>
75
+ <%= line_item_f.hidden_field :line_item_type, { :value => "payment" } %>
76
+ <%= line_item_f.fields_for :payment do |payment| %>
77
+ <div class="item">
78
+ <%= payment.label :number %>
79
+ <% if @order.errors.keys.include?("payments.number".to_sym) %>
80
+ <span class="field_with_errors">
81
+ <%= payment.text_field :number %>
82
+ </span>
83
+ <% else -%>
84
+ <%= payment.text_field :number %>
85
+ <% end -%>
86
+ </div>
87
+
88
+ <div class="item">
89
+ <%= payment.label :verification_value %>
90
+ <% if @order.errors.keys.include?("payments.verification_value".to_sym) %>
91
+ <span class="field_with_errors">
92
+ <%= payment.text_field :verification_value %>
93
+ </span>
94
+ <% else -%>
95
+ <%= payment.text_field :verification_value %>
96
+ <% end -%>
97
+ </div>
98
+
99
+ <div class="item">
100
+ <%= payment.label :month %>
101
+ <% if @order.errors.keys.include?("payments.verification_value".to_sym) %>
102
+ <span class="field_with_errors">
103
+ <%= payment.select :month, 1.upto(12).to_a %> /
104
+ <%= payment.select :year, Time.now.year.upto(Time.now.year + 10).to_a %>
105
+ </span>
106
+ <% else -%>
107
+ <%= payment.select :month, 1.upto(12).to_a %> /
108
+ <%= payment.select :year, Time.now.year.upto(Time.now.year + 10).to_a %>
109
+ <% end -%>
110
+ </div>
104
111
  <% end -%>
105
- </div>
106
112
  <% end -%>
107
113
  </div>
108
114
  <div id="submit">
@@ -8,8 +8,8 @@
8
8
  - else
9
9
  = form.text_field "state_id"
10
10
 
11
- - if type == "billing"
12
- = javascript_include_tag "piggybak.states"
13
-
14
11
  :javascript
15
12
  var geodata_lookup = "#{piggybak.orders_geodata_url}";
13
+
14
+ - if type == "billing"
15
+ = javascript_include_tag "piggybak.states"
@@ -3,32 +3,32 @@ N/A
3
3
  <% else -%>
4
4
  <table cellpadding="5" cellspacing="0">
5
5
  <tr>
6
- <td width="150">Subtotal</td>
7
- <td>$<%= "%.2f" % form.object.line_items.inject(0) { |subtotal, li| subtotal + li.total } %></td>
6
+ <td width="150">Subtotal (Sellables)</td>
7
+ <td><%= number_to_currency form.object.subtotal %></td>
8
8
  </tr>
9
9
  <tr>
10
10
  <td>Shipping</td>
11
- <td>$<%= "%.2f" % form.object.shipments.inject(0) { |shipping, shipment| shipping + shipment.total } %></td>
11
+ <td><%= number_to_currency form.object.shipment_charge %></td>
12
12
  </tr>
13
13
  <tr>
14
14
  <td>Tax</td>
15
- <td>$<%= "%.2f" % form.object.tax_charge %></td>
15
+ <td><%= number_to_currency form.object.tax_charge %></td>
16
16
  </tr>
17
17
  <tr>
18
- <td>Total</td>
19
- <td>$<%= "%.2f" % form.object.total %></td>
18
+ <td>Adjustments</td>
19
+ <td><%= number_to_currency form.object.adjustment_charge %></td>
20
20
  </tr>
21
21
  <tr>
22
- <td>Payments</td>
23
- <td>$<%= "%.2f" % form.object.payments.inject(0) { |total, payment| total + payment.total } %></td>
22
+ <td>Total</td>
23
+ <td><%= number_to_currency form.object.total %></td>
24
24
  </tr>
25
25
  <tr>
26
- <td>Adjustments</td>
27
- <td>$<%= "%.2f" % form.object.adjustments.inject(0) { |total, adj| total + adj.total.to_f } %></td>
26
+ <td>Payments</td>
27
+ <td><%= number_to_currency form.object.payment_charge %></td>
28
28
  </tr>
29
29
  <tr>
30
30
  <td>Balance Due</td>
31
- <td>$<%= "%.2f" % form.object.total_due %></td>
31
+ <td><%= number_to_currency form.object.total_due %></td>
32
32
  </tr>
33
33
  <tr>
34
34
  <td>Created at</td>
@@ -42,23 +42,11 @@ N/A
42
42
  <li><%= link_to "Send or Resend Email Confirmation", piggybak.email_order_url(form.object.id) %></li>
43
43
  <li><%= link_to "View as Text", piggybak.download_order_url(form.object.id) %></li>
44
44
  <% if form.object.total_due == 0.00 -%>
45
- <li><%= link_to "Cancel Order", piggybak.cancel_order_url(form.object.id) %> (This does not mark the payment gateway payments. This marks payments tied to ths order in this database as refunded, and marks the order as cancelled.)</li>
45
+ <li><%= link_to "Cancel Order", piggybak.cancel_order_url(form.object.id) %> (This does not refund payments.)</li>
46
46
  <% end -%>
47
47
  </ul>
48
48
  </td>
49
49
  </tr>
50
- <% else -%>
51
- <tr>
52
- <td valign="top">Actions</td>
53
- <td>
54
- <ul>
55
- <li>
56
- <%= link_to "Restore Cancel Order", piggybak.restore_order_url(form.object.id) %>
57
- (This marks order as un-cancelled.)
58
- </li>
59
- </ul>
60
- </td>
61
- </tr>
62
50
  <% end -%>
63
51
  </table>
64
52
  <% end -%>
@@ -0,0 +1,29 @@
1
+ - if form.object.new_record?
2
+ = form.select "line_item_type", Piggybak::LineItem.line_item_type_select, {}, :onchange => "toggle_line_item($(this));"
3
+ - else
4
+ = form.hidden_field "line_item_type"
5
+ = form.object.line_item_type
6
+
7
+ %script
8
+ var line_item_types=#{raw Piggybak.config.line_item_types.to_json};
9
+ var toggle_line_item = function(el) {
10
+ el.parent().parent().siblings('div').hide();
11
+ if(line_item_types[el.val()].fields === undefined) {
12
+ line_item_types[el.val()].fields = new Array();
13
+ }
14
+ $.each(line_item_types[el.val()].fields, function(a, b) {
15
+ el.parent().parent().siblings('.' + b + '_field').show();
16
+ if(line_item_types[el.val()].nested_attrs !== undefined) {
17
+ el.parent().parent().siblings('.' + b + '_field').find('> .controls,> .control-label').hide();
18
+ }
19
+ });
20
+ };
21
+ $.each($('.line_item_type_field select,.line_item_type_field input'), function(i, el) {
22
+ toggle_line_item($(el));
23
+ });
24
+ //Removing delete-ability of line_item_types that can't be destroyed
25
+ $.each($('.line_item_type_field input'), function(i, el) {
26
+ if(!line_item_types[$(el).val()].allow_destroy) {
27
+ $(el).parentsUntil('fieldset').parent().parent().find('.remove_nested_fields').remove();
28
+ }
29
+ });