spree_multi_currency 1.0.4
Sign up to get free protection for your applications and to get access to all the features.
- data.tar.gz.sig +3 -0
- data/.gitignore +5 -0
- data/Gemfile +11 -0
- data/LICENSE +0 -0
- data/README.markdown +196 -0
- data/Rakefile +28 -0
- data/Versionfile +9 -0
- data/app/controllers/spree/admin/currencies_controller.rb +11 -0
- data/app/controllers/spree/admin/currency_converters_controller.rb +4 -0
- data/app/controllers/spree/base_controller_decorator.rb +12 -0
- data/app/controllers/spree/currency_controller.rb +16 -0
- data/app/helpers/number_helper_decorator.rb +40 -0
- data/app/models/spree/adjustment_decorator.rb +4 -0
- data/app/models/spree/currency.rb +119 -0
- data/app/models/spree/currency_converter.rb +14 -0
- data/app/models/spree/line_item_decorator.rb +13 -0
- data/app/models/spree/order_decorator.rb +83 -0
- data/app/models/spree/variant_decorator.rb +22 -0
- data/app/overrides/add_currencies_admin_configurations_menu.rb +10 -0
- data/app/views/spree/admin/currencies/_form.html.erb +40 -0
- data/app/views/spree/admin/currencies/edit.html.erb +16 -0
- data/app/views/spree/admin/currencies/index.html.erb +44 -0
- data/app/views/spree/admin/currencies/new.html.erb +16 -0
- data/app/views/spree/admin/currency_converters/_form.html.erb +35 -0
- data/app/views/spree/admin/currency_converters/edit.html.erb +16 -0
- data/app/views/spree/admin/currency_converters/index.html.erb +42 -0
- data/app/views/spree/admin/currency_converters/new.html.erb +16 -0
- data/config/cucumber.yml +10 -0
- data/config/locales/currencies.yml +51 -0
- data/config/locales/en_multi_currency.yml +28 -0
- data/config/locales/ru_multi_currency.yml +26 -0
- data/config/routes.rb +8 -0
- data/db/migrate/20101109134351_create_currencies.rb +25 -0
- data/db/migrate/20101109134453_create_currency_converters.rb +15 -0
- data/db/sample/currencies.yml +1603 -0
- data/db/sample/currency_converters.yml +689 -0
- data/db/seeds.rb +2 -0
- data/features/products.feature +32 -0
- data/features/step_definitions/product.rb +124 -0
- data/features/step_definitions/ror_ringer.jpeg +0 -0
- data/features/support/env.rb +16 -0
- data/features/support/paths.rb +42 -0
- data/lib/generators/spree_multi_currency/install/install_generator.rb +29 -0
- data/lib/spree_multi_currency.rb +40 -0
- data/lib/spree_multi_currency/engine.rb +34 -0
- data/lib/tasks/spree_multi_currency.rake +99 -0
- data/script/rails +5 -0
- data/spec/changing_currency_spec.rb +18 -0
- data/spec/spec_helper.rb +17 -0
- data/spree_multi_currency.gemspec +32 -0
- metadata +226 -0
- metadata.gz.sig +1 -0
@@ -0,0 +1,14 @@
|
|
1
|
+
module Spree
|
2
|
+
class CurrencyConverter < ActiveRecord::Base
|
3
|
+
belongs_to :currency
|
4
|
+
default_scope :order => "spree_currency_converters.date_req ASC"
|
5
|
+
|
6
|
+
attr_accessible :currency_id, :nominal, :value, :date_req, :currency
|
7
|
+
|
8
|
+
class << self
|
9
|
+
def add(currency, date, value, nominal)
|
10
|
+
create({ :nominal => nominal, :value => value, :date_req => date, :currency => currency})
|
11
|
+
end
|
12
|
+
end
|
13
|
+
end
|
14
|
+
end
|
@@ -0,0 +1,13 @@
|
|
1
|
+
Spree::LineItem.class_eval do
|
2
|
+
extend Spree::MultiCurrency
|
3
|
+
multi_currency :price
|
4
|
+
|
5
|
+
def copy_price
|
6
|
+
self.price = variant.reade_attribute(:price) if variant && price.nil?
|
7
|
+
end
|
8
|
+
|
9
|
+
def raw_amount
|
10
|
+
read_attribute(:price) * self.quantity
|
11
|
+
end
|
12
|
+
|
13
|
+
end
|
@@ -0,0 +1,83 @@
|
|
1
|
+
Spree::Order.class_eval do
|
2
|
+
extend Spree::MultiCurrency
|
3
|
+
multi_currency :item_total, :total,
|
4
|
+
:rate_at_date => lambda{ |t| t.created_at },
|
5
|
+
:only_read => true
|
6
|
+
|
7
|
+
|
8
|
+
def update_totals
|
9
|
+
# update_adjustments
|
10
|
+
self.payment_total = payments.completed.map(&:amount).sum
|
11
|
+
self.item_total = line_items.map(&:raw_amount).sum
|
12
|
+
self.adjustment_total = adjustments.map(&:amount).sum
|
13
|
+
self.total = read_attribute(:item_total) + adjustment_total
|
14
|
+
end
|
15
|
+
|
16
|
+
def rate_hash
|
17
|
+
@rate_hash ||= available_shipping_methods(:front_end).collect do |ship_method|
|
18
|
+
next unless cost = ship_method.calculator.compute(self)
|
19
|
+
{ :id => ship_method.id,
|
20
|
+
:shipping_method => ship_method,
|
21
|
+
:name => ship_method.name,
|
22
|
+
:cost => Spree::Currency.conversion_to_current(cost)
|
23
|
+
}
|
24
|
+
end.compact.sort_by{|r| r[:cost]}
|
25
|
+
end
|
26
|
+
|
27
|
+
def update!
|
28
|
+
update_totals
|
29
|
+
update_payment_state
|
30
|
+
|
31
|
+
# give each of the shipments a chance to update themselves
|
32
|
+
shipments.each { |shipment| shipment.update!(self) }#(&:update!)
|
33
|
+
update_shipment_state
|
34
|
+
update_adjustments
|
35
|
+
# update totals a second time in case updated adjustments have an effect on the total
|
36
|
+
update_totals
|
37
|
+
update_attributes_without_callbacks({
|
38
|
+
:payment_state => payment_state,
|
39
|
+
:shipment_state => shipment_state,
|
40
|
+
:item_total => read_attribute(:item_total),
|
41
|
+
:adjustment_total => adjustment_total,
|
42
|
+
:payment_total => payment_total,
|
43
|
+
:total => read_attribute(:total)
|
44
|
+
})
|
45
|
+
|
46
|
+
#ensure checkout payment always matches order total
|
47
|
+
if payment and payment.checkout? and payment.amount != total
|
48
|
+
payment.update_attributes_without_callbacks(:amount => total)
|
49
|
+
end
|
50
|
+
|
51
|
+
update_hooks.each { |hook| self.send hook }
|
52
|
+
end
|
53
|
+
|
54
|
+
def add_variant(variant, quantity = 1)
|
55
|
+
current_item = contains?(variant)
|
56
|
+
if current_item
|
57
|
+
current_item.quantity += quantity
|
58
|
+
current_item.save
|
59
|
+
else
|
60
|
+
current_item = Spree::LineItem.new(:quantity => quantity)
|
61
|
+
current_item.variant = variant
|
62
|
+
current_item.price = variant.read_attribute(:price)
|
63
|
+
self.line_items << current_item
|
64
|
+
end
|
65
|
+
|
66
|
+
# populate line_items attributes for additional_fields entries
|
67
|
+
# that have populate => [:line_item]
|
68
|
+
Spree::Variant.additional_fields.select { |f| !f[:populate].nil? && f[:populate].include?(:line_item) }.each do |field|
|
69
|
+
value = ''
|
70
|
+
|
71
|
+
if field[:only].nil? || field[:only].include?(:variant)
|
72
|
+
value = variant.send(field[:name].gsub(' ', '_').downcase)
|
73
|
+
elsif field[:only].include?(:product)
|
74
|
+
value = variant.product.send(field[:name].gsub(' ', '_').downcase)
|
75
|
+
end
|
76
|
+
current_item.update_attribute(field[:name].gsub(' ', '_').downcase, value)
|
77
|
+
end
|
78
|
+
|
79
|
+
self.reload
|
80
|
+
current_item
|
81
|
+
end
|
82
|
+
|
83
|
+
end
|
@@ -0,0 +1,22 @@
|
|
1
|
+
Spree::Variant.class_eval do
|
2
|
+
extend Spree::MultiCurrency
|
3
|
+
multi_currency :price, :cost_price
|
4
|
+
def price_in(currency)
|
5
|
+
# will use internal currency, parametr will ignored
|
6
|
+
currency = Spree::Currency.current
|
7
|
+
prices.select{ |price| price.currency == currency }.first || Spree::Price.new(:variant_id => self.id, :currency => currency, :amount => self.cost_price)
|
8
|
+
end
|
9
|
+
end
|
10
|
+
|
11
|
+
Spree::Money.class_eval do
|
12
|
+
def initialize(amount, options={})
|
13
|
+
@money = ::Money.parse([amount, (Spree::Currency.current.char_code)].join)
|
14
|
+
@options = {}
|
15
|
+
@options[:with_currency] = true if Spree::Config[:display_currency]
|
16
|
+
@options[:symbol_position] = Spree::Config[:currency_symbol_position].to_sym
|
17
|
+
@options[:no_cents] = true if Spree::Config[:hide_cents]
|
18
|
+
@options.merge!(options)
|
19
|
+
# Must be a symbol because the Money gem doesn't do the conversion
|
20
|
+
@options[:symbol_position] = @options[:symbol_position].to_sym
|
21
|
+
end
|
22
|
+
end
|
@@ -0,0 +1,10 @@
|
|
1
|
+
Deface::Override.new(:virtual_path => "spree/admin/shared/_configuration_menu",
|
2
|
+
:name => "currencies_admin_configurations_menu",
|
3
|
+
:insert_bottom => "ul[data-hook='admin_configurations_sidebar_menu']",
|
4
|
+
:disabled => false,
|
5
|
+
:text => "
|
6
|
+
<% if current_user.has_spree_role?(:admin) %>
|
7
|
+
<%= configurations_sidebar_menu_item t(:currency_settings), admin_currencies_path %>
|
8
|
+
<%= configurations_sidebar_menu_item t(:currency_converters_settings), admin_currency_converters_path %>
|
9
|
+
<% end %>
|
10
|
+
")
|
@@ -0,0 +1,40 @@
|
|
1
|
+
<table>
|
2
|
+
<tr>
|
3
|
+
<td><%= t("currency_name") %>: </td>
|
4
|
+
<td>
|
5
|
+
<%= error_message_on :currency, :name %>
|
6
|
+
<%= f.text_field :name %>
|
7
|
+
</td>
|
8
|
+
</tr>
|
9
|
+
<tr>
|
10
|
+
<td><%= t("currency_num_code") %>: </td>
|
11
|
+
<td>
|
12
|
+
<%= error_message_on :currency, :num_code %>
|
13
|
+
<%= f.text_field :num_code %>
|
14
|
+
</td>
|
15
|
+
</tr>
|
16
|
+
<tr>
|
17
|
+
<td><%= t("currency_char_code") %>: </td>
|
18
|
+
<td>
|
19
|
+
<%= error_message_on :currency, :char_code %>
|
20
|
+
<%= f.text_field :char_code %>
|
21
|
+
</td>
|
22
|
+
</tr>
|
23
|
+
|
24
|
+
<tr>
|
25
|
+
<td><%= t("currency_basic") %>: </td>
|
26
|
+
<td>
|
27
|
+
<%= error_message_on :currency, :basic %>
|
28
|
+
<%= f.check_box :basic %>
|
29
|
+
</td>
|
30
|
+
</tr>
|
31
|
+
<tr>
|
32
|
+
<td><%= t("currency_locale") %>: </td>
|
33
|
+
<td>
|
34
|
+
<%= error_message_on :currency, :locale %>
|
35
|
+
<%= f.select :locale, I18n.available_locales.map{|x| [x,x] }, {}, { :multiple => true, :size => 10 } %>
|
36
|
+
</td>
|
37
|
+
</tr>
|
38
|
+
|
39
|
+
</table>
|
40
|
+
|
@@ -0,0 +1,16 @@
|
|
1
|
+
<% content_for :page_title do %>
|
2
|
+
<%= t(:editing_currency) %>
|
3
|
+
<% end %>
|
4
|
+
|
5
|
+
<% content_for :page_actions do %>
|
6
|
+
<li>
|
7
|
+
<%= button_link_to t("back_to_currencies"), collection_url, :icon => 'icon-arrow-left' %>
|
8
|
+
</li>
|
9
|
+
<% end %>
|
10
|
+
|
11
|
+
<%= form_for(@currency, :url => object_url, :html => { :method => :put }) do |f| %>
|
12
|
+
<fieldset class="no-border-top">
|
13
|
+
<%= render "form", :f => f %>
|
14
|
+
<%= render :partial => 'spree/admin/shared/edit_resource_links' %>
|
15
|
+
</fieldset>
|
16
|
+
<% end %>
|
@@ -0,0 +1,44 @@
|
|
1
|
+
<%= render(:partial => "/spree/admin/shared/configuration_menu") %>
|
2
|
+
<% content_for :page_title do %>
|
3
|
+
<%= t(:list_currency) %>
|
4
|
+
<% end %>
|
5
|
+
|
6
|
+
<% content_for :page_actions do %>
|
7
|
+
<li>
|
8
|
+
<%= button_link_to t("add_currency"), new_object_url, :icon => 'icon-plus' %>
|
9
|
+
</li>
|
10
|
+
<% end %>
|
11
|
+
|
12
|
+
<table class="index">
|
13
|
+
<colgroup>
|
14
|
+
<col style="width: 20%">
|
15
|
+
<col style="width: 20%">
|
16
|
+
<col style="width: 20%">
|
17
|
+
<col style="width: 20%">
|
18
|
+
<col style="width: 20%">
|
19
|
+
</colgroup>
|
20
|
+
<thead>
|
21
|
+
<tr>
|
22
|
+
<th><%= t("currency_name")%></th>
|
23
|
+
<th><%= t("currency_code")%></th>
|
24
|
+
<th><%= t("currency_locale")%></th>
|
25
|
+
<th><%= t("currency_basic")%></th>
|
26
|
+
</tr>
|
27
|
+
</thead>
|
28
|
+
<tbody>
|
29
|
+
<% @currencies.each do |currency|%>
|
30
|
+
<tr id="<%= dom_id currency %>">
|
31
|
+
<td width="350px"><%= currency.name %></td>
|
32
|
+
<td>
|
33
|
+
<%= currency.num_code %> - <%= currency.char_code %>
|
34
|
+
</td>
|
35
|
+
<td> <%= currency.locale(false) %></td>
|
36
|
+
<td> <%= currency.basic %></td>
|
37
|
+
<td class='actions'>
|
38
|
+
<%= link_to_edit currency, :no_text => true %>
|
39
|
+
<%= link_to_delete currency, :no_text => true %>
|
40
|
+
</td>
|
41
|
+
</tr>
|
42
|
+
<% end %>
|
43
|
+
</tbody>
|
44
|
+
</table>
|
@@ -0,0 +1,16 @@
|
|
1
|
+
<% content_for :page_title do %>
|
2
|
+
<%= t(:new_currency) %>
|
3
|
+
<% end %>
|
4
|
+
|
5
|
+
<% content_for :page_actions do %>
|
6
|
+
<li>
|
7
|
+
<%= button_link_to t("back_to_currencies"), collection_url, :icon => 'icon-arrow-left' %>
|
8
|
+
</li>
|
9
|
+
<% end %>
|
10
|
+
|
11
|
+
<%= form_for(:currency, :url => collection_url) do |f| %>
|
12
|
+
<fieldset class="no-border-top">
|
13
|
+
<%= render :partial => "form", :locals => { :f => f } %>
|
14
|
+
<%= render :partial => 'spree/admin/shared/new_resource_links' %>
|
15
|
+
</fieldset>
|
16
|
+
<% end %>
|
@@ -0,0 +1,35 @@
|
|
1
|
+
<table>
|
2
|
+
<tr>
|
3
|
+
<td><%= t("currency_converter_currency") %>: </td>
|
4
|
+
<td>
|
5
|
+
<%= error_message_on :currency_converter, :currency_id %>
|
6
|
+
<%= f.select :currency_id, Spree::Currency.all.map{|x| [x.name, x.id]} %>
|
7
|
+
</td>
|
8
|
+
</tr>
|
9
|
+
|
10
|
+
<tr>
|
11
|
+
<td><%= t("currency_converter_date_req") %>: </td>
|
12
|
+
<td>
|
13
|
+
<%= error_message_on :currency_converter, :date_req %>
|
14
|
+
<%= f.text_field :date_req, :class => 'datepicker' %>
|
15
|
+
</td>
|
16
|
+
</tr>
|
17
|
+
|
18
|
+
<tr>
|
19
|
+
<td><%= t("currency_converter_nominal") %>: </td>
|
20
|
+
<td>
|
21
|
+
<%= error_message_on :currency_converter, :nominal %>
|
22
|
+
<%= f.text_field :nominal %>
|
23
|
+
</td>
|
24
|
+
</tr>
|
25
|
+
|
26
|
+
<tr>
|
27
|
+
<td><%= t("currency_converter_value") %>: </td>
|
28
|
+
<td>
|
29
|
+
<%= error_message_on :currency_converter, :value %>
|
30
|
+
<%= f.text_field :value %>
|
31
|
+
</td>
|
32
|
+
</tr>
|
33
|
+
|
34
|
+
</table>
|
35
|
+
|
@@ -0,0 +1,16 @@
|
|
1
|
+
<% content_for :page_title do %>
|
2
|
+
<%= t(:editing_currency_converter) %>
|
3
|
+
<% end %>
|
4
|
+
|
5
|
+
<% content_for :page_actions do %>
|
6
|
+
<li>
|
7
|
+
<%= button_link_to t("back_to_currency_converters"), collection_url, :icon => 'icon-arrow-left' %>
|
8
|
+
</li>
|
9
|
+
<% end %>
|
10
|
+
|
11
|
+
<%= form_for(:currency_converter, :url => object_url, :html => { :method => :put }) do |f| %>
|
12
|
+
<fieldset class="no-border-top">
|
13
|
+
<%= render :partial => "form", :locals => { :f => f } %>
|
14
|
+
<%= render :partial => 'spree/admin/shared/edit_resource_links' %>
|
15
|
+
</fieldset>
|
16
|
+
<% end %>
|
@@ -0,0 +1,42 @@
|
|
1
|
+
<%= render(:partial => "/spree/admin/shared/configuration_menu") %>
|
2
|
+
<% content_for :page_title do %>
|
3
|
+
<%= t(:currency_converter) %>
|
4
|
+
<% end %>
|
5
|
+
|
6
|
+
<% content_for :page_actions do %>
|
7
|
+
<li>
|
8
|
+
<%= button_link_to t("add_currency_converter"), new_object_url, :icon => 'icon-plus' %>
|
9
|
+
</li>
|
10
|
+
<% end %>
|
11
|
+
|
12
|
+
<table class="index">
|
13
|
+
<colgroup>
|
14
|
+
<col style="width: 20%">
|
15
|
+
<col style="width: 20%">
|
16
|
+
<col style="width: 20%">
|
17
|
+
<col style="width: 20%">
|
18
|
+
<col style="width: 20%">
|
19
|
+
</colgroup>
|
20
|
+
<thead>
|
21
|
+
<tr>
|
22
|
+
<th><%= t("currency_converter_date_req") %></th>
|
23
|
+
<th><%= t("currency_converter_currency") %></th>
|
24
|
+
<th><%= t("currency_converter_nominal") %></th>
|
25
|
+
<th><%= t("currency_converter_value") %></th>
|
26
|
+
</tr>
|
27
|
+
</thead>
|
28
|
+
<tbody>
|
29
|
+
<% @currency_converters.each do |currency_converter|%>
|
30
|
+
<tr id="<%= dom_id currency_converter %>">
|
31
|
+
<td><%= currency_converter.date_req %></td>
|
32
|
+
<td width="350px"><%= currency_converter.currency.try(:name) %></td>
|
33
|
+
<td><%= currency_converter.nominal %></td>
|
34
|
+
<td><%= currency_converter.value %></td>
|
35
|
+
<td>
|
36
|
+
<%= link_to_edit currency_converter %>
|
37
|
+
<%= link_to_delete currency_converter %>
|
38
|
+
</td>
|
39
|
+
</tr>
|
40
|
+
<% end %>
|
41
|
+
</tbody>
|
42
|
+
</table>
|
@@ -0,0 +1,16 @@
|
|
1
|
+
<% content_for :page_title do %>
|
2
|
+
<%= t(:new_currency_converter) %>
|
3
|
+
<% end %>
|
4
|
+
|
5
|
+
<% content_for :page_actions do %>
|
6
|
+
<li>
|
7
|
+
<%= button_link_to t("back_to_currency_converters"), collection_url, :icon => 'icon-arrow-left' %>
|
8
|
+
</li>
|
9
|
+
<% end %>
|
10
|
+
|
11
|
+
<%= form_for(:currency_converter, :url => collection_url) do |f| %>
|
12
|
+
<fieldset class="no-border-top">
|
13
|
+
<%= render :partial => "form", :locals => { :f => f } %>
|
14
|
+
<%= render :partial => 'spree/admin/shared/new_resource_links' %>
|
15
|
+
</fieldset>
|
16
|
+
<% end %>
|
data/config/cucumber.yml
ADDED
@@ -0,0 +1,10 @@
|
|
1
|
+
<%
|
2
|
+
rerun = File.file?('rerun.txt') ? IO.read('rerun.txt') : ""
|
3
|
+
rerun_opts = rerun.to_s.strip.empty? ? "--format #{ENV['CUCUMBER_FORMAT'] || 'progress'} features" : "--format #{ENV['CUCUMBER_FORMAT'] || 'pretty'} #{rerun}"
|
4
|
+
std_opts = "--format #{ENV['CUCUMBER_FORMAT'] || 'progress'} --strict --tags ~@wip"
|
5
|
+
ci_opts = "--format progress --strict"
|
6
|
+
%>
|
7
|
+
default: <%= std_opts %> features
|
8
|
+
wip: --tags @wip:3 --wip features
|
9
|
+
ci: <%= ci_opts %> features CI=true
|
10
|
+
rerun: <%= rerun_opts %> --format rerun --out rerun.txt --strict --tags ~@wip
|
@@ -0,0 +1,51 @@
|
|
1
|
+
currency_USD: &usd
|
2
|
+
number:
|
3
|
+
currency:
|
4
|
+
format:
|
5
|
+
format: "%u%n"
|
6
|
+
unit: "$"
|
7
|
+
separator: "."
|
8
|
+
delimiter: ","
|
9
|
+
precision: 2
|
10
|
+
significant: false
|
11
|
+
strip_insignificant_zeros: false
|
12
|
+
|
13
|
+
currency_RUB:
|
14
|
+
number:
|
15
|
+
currency:
|
16
|
+
format:
|
17
|
+
format: "%n %u"
|
18
|
+
unit: "руб."
|
19
|
+
separator: "."
|
20
|
+
delimiter: " "
|
21
|
+
precision: 2
|
22
|
+
|
23
|
+
currency_EUR:
|
24
|
+
<<: *usd
|
25
|
+
number:
|
26
|
+
currency:
|
27
|
+
format:
|
28
|
+
format: "%u%n"
|
29
|
+
unit: "€"
|
30
|
+
separator: ","
|
31
|
+
delimiter: "."
|
32
|
+
|
33
|
+
currency_DKK:
|
34
|
+
number:
|
35
|
+
currency:
|
36
|
+
format:
|
37
|
+
format: "%n %u"
|
38
|
+
unit: "kr."
|
39
|
+
separator: ","
|
40
|
+
delimiter: "."
|
41
|
+
precision: 2
|
42
|
+
|
43
|
+
currency_GBP:
|
44
|
+
number:
|
45
|
+
currency:
|
46
|
+
format:
|
47
|
+
format: "%u%n"
|
48
|
+
unit: "£"
|
49
|
+
separator: "."
|
50
|
+
delimiter: ","
|
51
|
+
precision: 2
|