stall 0.1.1 → 0.1.2

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 (120) hide show
  1. checksums.yaml +4 -4
  2. data/README.md +45 -0
  3. data/app/assets/javascripts/stall.coffee +2 -0
  4. data/app/assets/javascripts/stall/cart-form.coffee +23 -0
  5. data/app/controllers/stall/application_controller.rb +10 -2
  6. data/app/controllers/stall/carts_controller.rb +31 -10
  7. data/app/controllers/stall/checkout/steps_controller.rb +36 -4
  8. data/app/controllers/stall/checkouts_controller.rb +12 -3
  9. data/app/controllers/stall/line_items_controller.rb +3 -3
  10. data/app/controllers/stall/payments_controller.rb +5 -3
  11. data/app/helpers/stall/add_to_cart_helper.rb +1 -1
  12. data/app/helpers/stall/checkout_helper.rb +22 -2
  13. data/app/helpers/stall/payments_helper.rb +8 -0
  14. data/app/mailers/stall/admin_mailer.rb +11 -0
  15. data/app/mailers/stall/base_mailer.rb +17 -0
  16. data/app/mailers/stall/customer_mailer.rb +13 -0
  17. data/app/models/address.rb +3 -0
  18. data/app/models/address_ownership.rb +3 -0
  19. data/app/models/adjustment.rb +3 -0
  20. data/app/models/cart.rb +3 -0
  21. data/app/models/customer.rb +3 -0
  22. data/app/models/line_item.rb +3 -0
  23. data/app/models/payment.rb +3 -0
  24. data/app/models/payment_method.rb +3 -0
  25. data/app/models/product_list.rb +3 -0
  26. data/app/models/shipment.rb +3 -0
  27. data/app/models/shipping_method.rb +3 -0
  28. data/app/models/stall/models.rb +4 -0
  29. data/app/models/stall/models/address.rb +45 -0
  30. data/app/models/stall/models/address_ownership.rb +26 -0
  31. data/app/models/stall/models/adjustment.rb +49 -0
  32. data/app/models/stall/models/cart.rb +37 -0
  33. data/app/models/stall/models/customer.rb +18 -0
  34. data/app/models/stall/models/line_item.rb +57 -0
  35. data/app/models/stall/models/payment.rb +33 -0
  36. data/app/models/stall/models/payment_method.rb +18 -0
  37. data/app/models/stall/models/product_list.rb +147 -0
  38. data/app/models/stall/models/shipment.rb +29 -0
  39. data/app/models/stall/models/shipping_method.rb +16 -0
  40. data/app/services/stall/add_to_cart_service.rb +11 -1
  41. data/app/services/stall/cart_update_service.rb +26 -0
  42. data/app/services/stall/payment_notification_service.rb +23 -9
  43. data/app/services/stall/shipping_fee_calculator_service.rb +13 -2
  44. data/app/views/checkout/steps/_informations.html.haml +3 -3
  45. data/app/views/checkout/steps/_payment.html.haml +25 -4
  46. data/app/views/checkout/steps/_payment_method.html.haml +1 -3
  47. data/app/views/checkout/steps/_payment_return.html.haml +6 -0
  48. data/app/views/checkout/steps/_shipping_method.html.haml +1 -1
  49. data/app/views/stall/admin_mailer/order_paid_email.html.haml +4 -0
  50. data/app/views/stall/carts/show.html.haml +36 -8
  51. data/app/views/stall/customer_mailer/order_paid_email.html.haml +8 -0
  52. data/app/views/stall/line_items/_added.html.haml +1 -1
  53. data/app/views/stall/shared/mailers/_address.html.haml +18 -0
  54. data/app/views/stall/shared/mailers/_cart.html.haml +114 -0
  55. data/config/locales/stall.fr.yml +90 -8
  56. data/db/migrate/20160304134849_change_all_json_columns_to_jsonb.rb +18 -0
  57. data/db/migrate/20160307142924_add_state_to_stall_addresses.rb +5 -0
  58. data/db/migrate/20160308142713_create_adjustments.rb +16 -0
  59. data/db/migrate/20160309165136_add_identifier_to_stall_product_lists.rb +5 -0
  60. data/db/migrate/20160316114649_add_data_to_stall_shipments.rb +5 -0
  61. data/db/migrate/20160317141632_add_state_to_stall_shipments.rb +5 -0
  62. data/db/migrate/20160629102943_add_active_to_stall_shipping_methods.rb +11 -0
  63. data/db/migrate/20160629104617_add_active_to_stall_payment_methods.rb +11 -0
  64. data/db/migrate/20160705110151_add_locale_to_stall_customers.rb +5 -0
  65. data/lib/generators/stall/checkout/step/templates/step.html.haml.erb +1 -1
  66. data/lib/generators/stall/checkout/step/templates/step.rb.erb +10 -2
  67. data/lib/generators/stall/checkout/wizard/templates/wizard.rb.erb +1 -1
  68. data/lib/generators/stall/install/templates/initializer.rb +85 -1
  69. data/lib/generators/stall/model/model_generator.rb +27 -0
  70. data/lib/generators/stall/service/service_generator.rb +39 -0
  71. data/lib/generators/stall/service/templates/service.rb.erb +16 -0
  72. data/lib/generators/stall/shipping/calculator/calculator_generator.rb +17 -0
  73. data/lib/generators/stall/shipping/calculator/templates/calculator.rb.erb +29 -0
  74. data/lib/stall.rb +4 -0
  75. data/lib/stall/addressable.rb +28 -2
  76. data/lib/stall/cart_helper.rb +84 -0
  77. data/lib/stall/carts_cleaner.rb +46 -0
  78. data/lib/stall/checkout.rb +2 -0
  79. data/lib/stall/checkout/informations_checkout_step.rb +3 -5
  80. data/lib/stall/checkout/payment_checkout_step.rb +3 -0
  81. data/lib/stall/checkout/payment_return_checkout_step.rb +11 -0
  82. data/lib/stall/checkout/shipping_method_checkout_step.rb +2 -1
  83. data/lib/stall/checkout/step.rb +47 -11
  84. data/lib/stall/checkout/step_form.rb +71 -0
  85. data/lib/stall/checkout/wizard.rb +15 -5
  86. data/lib/stall/config.rb +51 -0
  87. data/lib/stall/engine.rb +24 -2
  88. data/lib/stall/payable.rb +26 -0
  89. data/lib/stall/payments.rb +7 -3
  90. data/lib/stall/payments/config.rb +37 -0
  91. data/lib/stall/payments/fake_gateway_payment_notification.rb +34 -0
  92. data/lib/stall/payments/gateway.rb +19 -12
  93. data/lib/stall/payments/urls_config.rb +40 -0
  94. data/lib/stall/priceable.rb +7 -0
  95. data/lib/stall/rails/currency_helper.rb +1 -1
  96. data/lib/stall/routes.rb +17 -4
  97. data/lib/stall/sellable.rb +1 -2
  98. data/lib/stall/shipping.rb +3 -1
  99. data/lib/stall/shipping/calculator.rb +36 -3
  100. data/lib/stall/shipping/config.rb +17 -3
  101. data/lib/stall/shipping/country_weight_table_calculator.rb +1 -1
  102. data/lib/stall/shipping/free_shipping_calculator.rb +1 -1
  103. data/lib/stall/utils.rb +2 -2
  104. data/lib/stall/utils/config_dsl.rb +5 -1
  105. data/lib/stall/version.rb +1 -1
  106. data/lib/tasks/stall_tasks.rake +11 -0
  107. metadata +73 -15
  108. data/app/assets/javascripts/stall/application.js +0 -13
  109. data/app/assets/javascripts/stall/carts.js +0 -2
  110. data/app/helpers/stall/cart_helper.rb +0 -28
  111. data/app/models/stall/address.rb +0 -5
  112. data/app/models/stall/address_ownership.rb +0 -8
  113. data/app/models/stall/cart.rb +0 -31
  114. data/app/models/stall/customer.rb +0 -8
  115. data/app/models/stall/line_item.rb +0 -49
  116. data/app/models/stall/payment.rb +0 -14
  117. data/app/models/stall/payment_method.rb +0 -7
  118. data/app/models/stall/product_list.rb +0 -68
  119. data/app/models/stall/shipment.rb +0 -15
  120. data/app/models/stall/shipping_method.rb +0 -5
@@ -0,0 +1,29 @@
1
+ module Stall
2
+ module Models
3
+ module Shipment
4
+ extend ActiveSupport::Concern
5
+
6
+ included do
7
+ self.table_name = 'stall_shipments'
8
+
9
+ include Stall::Priceable
10
+
11
+ belongs_to :cart
12
+ belongs_to :shipping_method
13
+
14
+ store_accessor :data, :tracking_code
15
+
16
+ monetize :eot_price_cents, :price_cents,
17
+ with_model_currency: :currency, allow_nil: true
18
+
19
+ enum state: { pending: 0, shipped: 1 }
20
+
21
+ validates :cart, :shipping_method, presence: true
22
+ end
23
+
24
+ def currency
25
+ cart.try(:currency) || Money.default_currency
26
+ end
27
+ end
28
+ end
29
+ end
@@ -0,0 +1,16 @@
1
+ module Stall
2
+ module Models
3
+ module ShippingMethod
4
+ extend ActiveSupport::Concern
5
+
6
+ included do
7
+ self.table_name = 'stall_shipping_methods'
8
+
9
+ has_many :shipments, dependent: :nullify
10
+
11
+ scope :ordered, -> { order('stall_shipping_methods.name ASC') }
12
+ scope :active, -> { where(active: true) }
13
+ end
14
+ end
15
+ end
16
+ end
@@ -14,7 +14,13 @@ module Stall
14
14
  cart.line_items << line_item
15
15
  end
16
16
 
17
- cart.save
17
+ cart.save.tap do |saved|
18
+ return false unless saved
19
+
20
+ # Recalculate shipping fee if available for calculation to ensure
21
+ # that the fee us always up to date when displayed to the customer
22
+ shipping_fee_service.call if shipping_fee_service.available?
23
+ end
18
24
  end
19
25
 
20
26
  def line_item
@@ -48,5 +54,9 @@ module Stall
48
54
  def sellable_class
49
55
  @sellable_class ||= params[:sellable_type].camelize.constantize
50
56
  end
57
+
58
+ def shipping_fee_service
59
+ @shipping_fee_service ||= Stall::ShippingFeeCalculatorService.new(cart)
60
+ end
51
61
  end
52
62
  end
@@ -0,0 +1,26 @@
1
+ module Stall
2
+ class CartUpdateService < Stall::BaseService
3
+ attr_reader :cart, :params
4
+
5
+ def initialize(cart, params)
6
+ @cart = cart
7
+ @params = params
8
+ end
9
+
10
+ def call
11
+ cart.update(params).tap do |saved|
12
+ return false unless saved
13
+
14
+ # Recalculate shipping fee if available for calculation to ensure
15
+ # that the fee us always up to date when displayed to the customer
16
+ shipping_fee_service.call if shipping_fee_service.available?
17
+ end
18
+ end
19
+
20
+ private
21
+
22
+ def shipping_fee_service
23
+ @shipping_fee_service ||= Stall::ShippingFeeCalculatorService.new(cart)
24
+ end
25
+ end
26
+ end
@@ -1,31 +1,45 @@
1
1
  module Stall
2
2
  class PaymentNotificationService < Stall::BaseService
3
- attr_reader :request
3
+ class UnknownNotificationError < StandardError; end
4
4
 
5
- def initialize(request)
5
+ attr_reader :gateway_identifier, :request
6
+
7
+ def initialize(gateway_identifier, request)
8
+ @gateway_identifier = gateway_identifier
6
9
  @request = request
7
10
  end
8
11
 
9
12
  def call
10
- gateway.process_payment_for(request)
13
+ if gateway_response.valid?
14
+ send_payment_notification_emails! if gateway_response.notify
15
+ else
16
+ raise UnknownNotificationError,
17
+ "The payment notification request does not seem to come from " +
18
+ "the \"#{ gateway_identifier }\" gateway."
19
+ end
11
20
  end
12
21
 
13
22
  def rendering_options
14
- gateway.rendering_options
23
+ gateway_response.rendering_options
15
24
  end
16
25
 
17
26
  private
18
27
 
19
- def gateway
20
- @gateway ||= gateway_class.new(cart)
28
+ def cart
29
+ gateway_response.cart
21
30
  end
22
31
 
23
32
  def gateway_class
24
- @gateway_class ||= Stall::Payments.gateways[request.params[:gateway]]
33
+ @gateway_class ||= Stall::Payments.gateways[gateway_identifier]
25
34
  end
26
35
 
27
- def cart
28
- @cart ||= Stall::Cart.find(gateway_class.cart_id_from(request))
36
+ def gateway_response
37
+ @gateway_response ||= gateway_class.response(request)
38
+ end
39
+
40
+ def send_payment_notification_emails!
41
+ Stall::CustomerMailer.order_paid_email(gateway_response.cart).deliver
42
+ Stall::AdminMailer.order_paid_email(gateway_response.cart).deliver
29
43
  end
30
44
  end
31
45
  end
@@ -10,12 +10,23 @@ module Stall
10
10
  return unless cart.shipment && cart.shipment.shipping_method
11
11
 
12
12
  calculator_identifier = cart.shipment.shipping_method.identifier
13
- calculator_class = Stall::Shipping.calculators[calculator_identifier]
13
+ calculator_class = Stall::Shipping::Calculator.for(calculator_identifier)
14
14
 
15
15
  if calculator_class
16
16
  calculator = calculator_class.new(cart, cart.shipment.shipping_method)
17
- cart.shipment.update_attributes(price: calculator.price)
17
+
18
+ cart.shipment.update_attributes(
19
+ price: calculator.price,
20
+ eot_price: calculator.eot_price,
21
+ vat_rate: calculator.vat_rate
22
+ )
18
23
  end
19
24
  end
25
+
26
+ def available?
27
+ cart.line_items.length > 0 &&
28
+ cart.try(:shipping_address) &&
29
+ cart.try(:shipment).try(:shipping_method)
30
+ end
20
31
  end
21
32
  end
@@ -1,6 +1,6 @@
1
1
  %h1= t('stall.checkout.informations.title')
2
2
 
3
- = simple_form_for cart, as: :cart, url: step_path(cart) do |form|
3
+ = simple_form_for cart, as: :cart, url: step_path do |form|
4
4
  = form.fields_for :customer do |customer_form|
5
5
  = customer_form.input :email
6
6
 
@@ -9,7 +9,7 @@
9
9
  = ownership_form.hidden_field :shipping
10
10
 
11
11
  = ownership_form.fields_for :address do |address_form|
12
- = address_form.input :civility
12
+ = address_form.input :civility, collection: Address.civility_enum
13
13
  = address_form.input :first_name
14
14
  = address_form.input :last_name
15
15
  = address_form.input :address
@@ -27,7 +27,7 @@
27
27
  = ownership_form.hidden_field :billing
28
28
 
29
29
  = ownership_form.fields_for :address do |address_form|
30
- = address_form.input :civility
30
+ = address_form.input :civility, collection: Address.civility_enum
31
31
  = address_form.input :first_name
32
32
  = address_form.input :last_name
33
33
  = address_form.input :address
@@ -3,10 +3,10 @@
3
3
  %table.table.table-striped
4
4
  %thead
5
5
  %tr
6
- %th= Stall::LineItem.human_attribute_name(:name)
7
- %th= Stall::LineItem.human_attribute_name(:unit_price)
8
- %th= Stall::LineItem.human_attribute_name(:quantity)
9
- %th= Stall::LineItem.human_attribute_name(:price)
6
+ %th= LineItem.human_attribute_name(:name)
7
+ %th= LineItem.human_attribute_name(:unit_price)
8
+ %th= LineItem.human_attribute_name(:quantity)
9
+ %th= LineItem.human_attribute_name(:price)
10
10
  %tbody
11
11
  - cart.line_items.each do |line_item|
12
12
  %tr{ data: { :'line-item-id' => line_item.id } }
@@ -15,6 +15,25 @@
15
15
  %td= line_item.quantity
16
16
  %td= number_to_currency(line_item.price)
17
17
 
18
+ - if cart.subtotal != cart.total_price
19
+ %tr
20
+ %td{ colspan: 3 }= t('stall.carts.recap.subtotal')
21
+ %td= number_to_currency(cart.subtotal)
22
+
23
+ - if cart.shipment && cart.shipment
24
+ %tr
25
+ %td{ colspan: 3 }
26
+ = t('stall.carts.recap.total_shipment_price')
27
+ \:
28
+ = cart.shipment.shipping_method.name
29
+
30
+ %td= number_to_currency(cart.shipment.price)
31
+
32
+ - cart.adjustments.each do |adjustment|
33
+ %tr
34
+ %td{ colspan: 3 }= adjustment.name
35
+ %td= number_to_currency(adjustment.price)
36
+
18
37
  %tr
19
38
  %td{ colspan: 3 }= t('stall.carts.recap.total_eot_price')
20
39
  %td= number_to_currency(cart.total_eot_price)
@@ -26,3 +45,5 @@
26
45
  %tr
27
46
  %td{ colspan: 3 }= t('stall.carts.recap.total_price')
28
47
  %td= number_to_currency(cart.total_price)
48
+
49
+ = payment_button_for(cart)
@@ -2,10 +2,8 @@
2
2
 
3
3
  = simple_form_for cart, as: :cart, url: step_path(cart) do |form|
4
4
  = form.fields_for :payment do |payment_fields|
5
- = payment_fields.association :payment_method, as: :radio_buttons
5
+ = payment_fields.association :payment_method, as: :radio_buttons, collection: PaymentMethod.active.ordered
6
6
 
7
7
  .form-actions
8
8
  %button.btn.btn-primary{ type: 'submit' }
9
9
  = t('stall.checkout.payment_method.validate')
10
-
11
-
@@ -0,0 +1,6 @@
1
+ %h1= t('stall.checkout.payment_return.title')
2
+
3
+ %p.help-block= t('stall.checkout.payment_return.help').html_safe
4
+
5
+ = link_to root_path, class: 'btn btn-primary' do
6
+ = t('stall.checkout.payment_return.back_to_shop')
@@ -1,6 +1,6 @@
1
1
  %h1= t('stall.checkout.shipping_method.title')
2
2
 
3
- = simple_form_for cart, as: :cart, url: step_path(cart) do |form|
3
+ = simple_form_for cart, as: :cart, url: step_path do |form|
4
4
  = form.fields_for :shipment do |shipment_fields|
5
5
  = shipment_fields.association :shipping_method, as: :radio_buttons
6
6
 
@@ -0,0 +1,4 @@
1
+ %table
2
+ %tr
3
+ %td
4
+ = render partial: 'stall/shared/mailers/cart', locals: { cart: @cart }
@@ -1,35 +1,63 @@
1
1
  .cart-recap{ data: { :'cart-recap' => true } }
2
- = simple_form_for @cart, url: cart_path(@cart), as: :cart do |form|
2
+ = simple_form_for @cart, url: cart_path(@cart), as: :cart, remote: true, data: { :'cart-form' => true } do |form|
3
3
  %table.table.table-striped
4
4
  %thead
5
5
  %tr
6
- %th= Stall::LineItem.human_attribute_name(:name)
7
- %th= Stall::LineItem.human_attribute_name(:unit_price)
8
- %th= Stall::LineItem.human_attribute_name(:quantity)
9
- %th= Stall::LineItem.human_attribute_name(:price)
6
+ %th= LineItem.human_attribute_name(:name)
7
+ %th= LineItem.human_attribute_name(:unit_price)
8
+ %th= LineItem.human_attribute_name(:quantity)
9
+ %th= LineItem.human_attribute_name(:price)
10
+ %th
11
+
10
12
  %tbody
11
13
  = form.fields_for :line_items do |line_item_fields|
12
14
  %tr{ data: { :'line-item-id' => line_item_fields.object.id } }
13
15
  %td= line_item_fields.object.name
14
16
  %td= line_item_fields.object.unit_price
15
- %td= line_item_fields.input_field :quantity, class: 'form-control', data: { :'quantity-field' => true }
17
+ %td= line_item_fields.input_field :quantity, spinner: false, class: 'form-control', data: { :'quantity-field' => true }
16
18
  %td= line_item_fields.object.price
19
+ %td= link_to_remove_association '&times;'.html_safe, line_item_fields
20
+
21
+ - if @cart.subtotal != @cart.total_price
22
+ %tr
23
+ %td{ colspan: 3 }= t('stall.carts.recap.subtotal')
24
+ %td= number_to_currency(@cart.subtotal)
25
+ %td
26
+
27
+ - if @cart.shipment && @cart.shipment.shipping_method
28
+ %tr
29
+ %td{ colspan: 3 }
30
+ = t('stall.carts.recap.total_shipment_price')
31
+ \:
32
+ = @cart.shipment.shipping_method.name
33
+
34
+ %td= number_to_currency(@cart.shipment.price)
35
+ %td
36
+
37
+ - @cart.adjustments.each do |adjustment|
38
+ %tr
39
+ %td{ colspan: 3 }= adjustment.name
40
+ %td= number_to_currency(adjustment.price)
41
+ %td
17
42
 
18
43
  %tr
19
44
  %td{ colspan: 3 }= t('stall.carts.recap.total_eot_price')
20
45
  %td= number_to_currency(@cart.total_eot_price)
46
+ %td
21
47
 
22
48
  %tr
23
49
  %td{ colspan: 3 }= t('stall.carts.recap.total_vat')
24
50
  %td= number_to_currency(@cart.total_vat)
51
+ %td
25
52
 
26
53
  %tr
27
54
  %td{ colspan: 3 }= t('stall.carts.recap.total_price')
28
55
  %td= number_to_currency(@cart.total_price)
56
+ %td
29
57
 
30
58
  .form-actions
31
- %button.btn.btn-default{ type: 'submit' }
59
+ %button.btn.btn-default{ type: 'submit', data: { :'cart-update-button' => true } }
32
60
  = t('stall.carts.recap.update')
33
61
 
34
- = link_to checkout_path(@cart), class: 'btn btn-primary' do
62
+ = link_to checkout_path(current_cart_key), class: 'btn btn-primary' do
35
63
  = t('stall.carts.recap.validate')
@@ -0,0 +1,8 @@
1
+ %table
2
+ %tr
3
+ %td
4
+ = t('stall.mailers.customer.order_paid_email.intro')
5
+
6
+ %tr
7
+ %td
8
+ = render partial: 'stall/shared/mailers/cart', locals: { cart: @cart }
@@ -1,4 +1,4 @@
1
- .modal.fade{ role: 'dialog', tabindex: '-1', data: { :'cart' => { :'total-quantity' => current_cart.total_quantity } } }
1
+ .modal.fade{ role: 'dialog', tabindex: '-1', data: { :'cart' => { token: current_cart.token, :'total-quantity' => current_cart.total_quantity } } }
2
2
  .modal-dialog
3
3
  .modal-content
4
4
  .modal-header
@@ -0,0 +1,18 @@
1
+ = address.civility_name
2
+ = address.first_name
3
+ = address.last_name
4
+ %br
5
+
6
+ = address.address
7
+ %br
8
+
9
+ - if address.address_details.present?
10
+ = address.address_details
11
+ %br
12
+
13
+ = [:zip, :city, :state, :country_name].map { |prop| address.send(prop).presence }.compact.join(', ')
14
+
15
+ %br
16
+
17
+ - if address.phone.present?
18
+ = address.phone
@@ -0,0 +1,114 @@
1
+ %table
2
+ %tbody
3
+ %tr
4
+ %td
5
+ %table
6
+ %tbody
7
+ %tr
8
+ %td
9
+ = t('stall.carts.recap.order_ref', ref: cart.reference)
10
+ %tr
11
+ %td
12
+ = t('stall.carts.recap.ordered_at', at: l(cart.created_at))
13
+
14
+ %tr
15
+ %td
16
+ %table
17
+ %tbody
18
+ %tr
19
+ %td
20
+ %h2= Cart.human_attribute_name(:billing_address)
21
+ = render partial: 'stall/shared/mailers/address', locals: { address: cart.billing_address }
22
+
23
+ %td
24
+ %h2= Cart.human_attribute_name(:shipping_address)
25
+ = render partial: 'stall/shared/mailers/address', locals: { address: cart.shipping_address }
26
+
27
+ %tr
28
+ %td
29
+ %table
30
+ %thead
31
+ %tr
32
+ %th= LineItem.human_attribute_name(:name)
33
+ %th= LineItem.human_attribute_name(:unit_price)
34
+ %th= LineItem.human_attribute_name(:quantity)
35
+ %th= LineItem.human_attribute_name(:price)
36
+
37
+ %tbody
38
+ - cart.line_items.each do |line_item|
39
+ %tr
40
+ %td= line_item.name
41
+ %td= number_to_currency(line_item.unit_price)
42
+ %td= line_item.quantity
43
+ %td= number_to_currency(line_item.price)
44
+
45
+ %tfoot
46
+ - if cart.subtotal != cart.total_price
47
+ %tr
48
+ %td{ colspan: 3 }= t('stall.carts.recap.subtotal')
49
+ %td= number_to_currency(cart.subtotal)
50
+
51
+ - if cart.shipment && cart.shipment.shipping_method
52
+ %tr
53
+ %td{ colspan: 3 }
54
+ = t('stall.carts.recap.total_shipment_price')
55
+ \:
56
+ = cart.shipment.shipping_method.name
57
+
58
+ %td= number_to_currency(cart.shipment.price)
59
+
60
+ - cart.adjustments.each do |adjustment|
61
+ %tr
62
+ %td{ colspan: 3 }= adjustment.name
63
+ %td= number_to_currency(adjustment.price)
64
+
65
+ %tr
66
+ %td{ colspan: 3 }= t('stall.carts.recap.total_eot_price')
67
+ %td= number_to_currency(cart.total_eot_price)
68
+
69
+ %tr
70
+ %td{ colspan: 3 }= t('stall.carts.recap.total_vat')
71
+ %td= number_to_currency(cart.total_vat)
72
+
73
+ %tr
74
+ %td{ colspan: 3 }= t('stall.carts.recap.total_price')
75
+ %td= number_to_currency(cart.total_price)
76
+
77
+ %tr
78
+ %td
79
+ %table
80
+ %tbody
81
+ %tr
82
+ %td{ colspan: 2 }
83
+ %strong= Cart.human_attribute_name(:payment)
84
+
85
+ %tr
86
+ %td
87
+ = Payment.human_attribute_name(:payment_method)
88
+ %td
89
+ = cart.payment.payment_method.name
90
+
91
+ %tr
92
+ %td
93
+ = Payment.human_attribute_name(:state)
94
+ %td
95
+ - if cart.payment.paid?
96
+ = t("stall.carts.recap.paid_at", at: cart.payment.paid_at)
97
+ - else
98
+ = t("activerecord.enums.payment.state.#{ cart.payment.state }")
99
+
100
+ %tr
101
+ %td{ colspan: 2 }
102
+ %strong= Cart.human_attribute_name(:shipment)
103
+
104
+ %tr
105
+ %td
106
+ = Shipment.human_attribute_name(:shipping_method)
107
+ %td
108
+ = cart.shipment.shipping_method.name
109
+
110
+ %tr
111
+ %td
112
+ = Shipment.human_attribute_name(:state)
113
+ %td
114
+ = t("activerecord.enums.payment.state.#{ cart.shipment.state }")