mirror of
https://github.com/openfoodfoundation/openfoodnetwork
synced 2026-01-17 19:26:48 +00:00
Compare commits
185 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
12fde5b9fc | ||
|
|
0da6275d41 | ||
|
|
52d2d1d23c | ||
|
|
4dfc020eaa | ||
|
|
8ef52f97e5 | ||
|
|
68a7f547b1 | ||
|
|
7a0f2d47a3 | ||
|
|
4affd01b7b | ||
|
|
0432c73f19 | ||
|
|
103902c006 | ||
|
|
d2933e35f1 | ||
|
|
0b5e341ae7 | ||
|
|
7d36c3b5aa | ||
|
|
d511763733 | ||
|
|
a059c11d0f | ||
|
|
cecc19ae1d | ||
|
|
d4311a848e | ||
|
|
d64573f7fd | ||
|
|
a9fe6ec1b5 | ||
|
|
f14bbc5ed9 | ||
|
|
5ba8efec2c | ||
|
|
3bf38b7c08 | ||
|
|
a591e0736f | ||
|
|
3080eb9dfd | ||
|
|
ed98a16eec | ||
|
|
7a924bd9ca | ||
|
|
7639e19184 | ||
|
|
71aff7e1d2 | ||
|
|
2506667bca | ||
|
|
f87a553230 | ||
|
|
3171b60d6f | ||
|
|
516398fbd6 | ||
|
|
4a1b74c136 | ||
|
|
b9edea7c0e | ||
|
|
b9053f9fd2 | ||
|
|
f297cff8c7 | ||
|
|
7563d38b4b | ||
|
|
83523a676f | ||
|
|
abcfb5ce8d | ||
|
|
8ee6d1c320 | ||
|
|
1bc19ad6a4 | ||
|
|
191b8064ed | ||
|
|
e28274db14 | ||
|
|
02dec1d6cd | ||
|
|
df04c837a5 | ||
|
|
7a6c085b63 | ||
|
|
a4317b70f4 | ||
|
|
cb90fb052d | ||
|
|
18e5f9ba64 | ||
|
|
e9a5b889de | ||
|
|
cc57b0c200 | ||
|
|
a8040e986d | ||
|
|
2269f824c0 | ||
|
|
c45a3c2303 | ||
|
|
1327d80446 | ||
|
|
43a3ac0a7b | ||
|
|
b948312de7 | ||
|
|
7063de4734 | ||
|
|
56c1a9cca2 | ||
|
|
9555bfcc93 | ||
|
|
e455a47135 | ||
|
|
e15e71a3a7 | ||
|
|
91d959b7d6 | ||
|
|
108f57a705 | ||
|
|
af42159e09 | ||
|
|
8e55c39ca0 | ||
|
|
6cfb060184 | ||
|
|
0cfb7269c8 | ||
|
|
cbec495620 | ||
|
|
55eea21bb0 | ||
|
|
f63c7cf54f | ||
|
|
13633e8bea | ||
|
|
093edb66d3 | ||
|
|
fb25ddd219 | ||
|
|
d54850f097 | ||
|
|
f8451a2511 | ||
|
|
1a88549954 | ||
|
|
f79182253a | ||
|
|
8cfd7c610b | ||
|
|
486b5e9edc | ||
|
|
8fe3abfd45 | ||
|
|
0e7dafea46 | ||
|
|
4c9cc7460a | ||
|
|
c9e3f58aed | ||
|
|
4136306abf | ||
|
|
9f1eaf0b66 | ||
|
|
4771612adb | ||
|
|
7ce3dfe365 | ||
|
|
6f13707b9d | ||
|
|
64cb104434 | ||
|
|
1606f9900f | ||
|
|
9f0e8b0b2e | ||
|
|
d796e96470 | ||
|
|
ba7f78ef60 | ||
|
|
988e146240 | ||
|
|
e6d9ec7bd7 | ||
|
|
3acc53a389 | ||
|
|
9c9fc999de | ||
|
|
d824c84ce6 | ||
|
|
1a301f3dbb | ||
|
|
fad4f3b22a | ||
|
|
6080c99850 | ||
|
|
2944acff8a | ||
|
|
2068a59b72 | ||
|
|
3063439ed1 | ||
|
|
6bed05c721 | ||
|
|
a3ee6674ea | ||
|
|
e59077e63e | ||
|
|
f9f8d85841 | ||
|
|
0042690e18 | ||
|
|
5f1111b52b | ||
|
|
25ded0d23c | ||
|
|
a5458150ca | ||
|
|
96eebbabf3 | ||
|
|
c58e6fa964 | ||
|
|
fbe8f5195c | ||
|
|
f587bbb7d5 | ||
|
|
2793693a7c | ||
|
|
07e2317369 | ||
|
|
042162eda8 | ||
|
|
795f13d73a | ||
|
|
f1814f1b67 | ||
|
|
4ab7b78cb8 | ||
|
|
11631c3a33 | ||
|
|
0212381362 | ||
|
|
e6ca6bacac | ||
|
|
59df45b8cf | ||
|
|
5892e85869 | ||
|
|
c59326743b | ||
|
|
cb3397fd1a | ||
|
|
2bd4de3e29 | ||
|
|
b2c5be775e | ||
|
|
d22212ccfa | ||
|
|
dd600cd163 | ||
|
|
f189ca8004 | ||
|
|
db7146014c | ||
|
|
c6af55d9ae | ||
|
|
0f588dbe0b | ||
|
|
9c14d8ff36 | ||
|
|
a104bf8efd | ||
|
|
a039ef13f4 | ||
|
|
7ad8951375 | ||
|
|
99e59595b4 | ||
|
|
3264355f12 | ||
|
|
7e3b6e2b5d | ||
|
|
a9598c5d97 | ||
|
|
3e5b7ebbf1 | ||
|
|
1a9c3007b0 | ||
|
|
2f7fd1482a | ||
|
|
0416521772 | ||
|
|
cfe3f72d0e | ||
|
|
00478cc57c | ||
|
|
d5e42ee1e5 | ||
|
|
9451f1b66d | ||
|
|
ff584f9be9 | ||
|
|
a589ba38da | ||
|
|
a4a2f98b6e | ||
|
|
f5ddbfbac3 | ||
|
|
a66a4c3edb | ||
|
|
8179252924 | ||
|
|
0bec492208 | ||
|
|
5cf50f0adf | ||
|
|
197fb36524 | ||
|
|
62e6f09d94 | ||
|
|
79b2460664 | ||
|
|
66f3656bb5 | ||
|
|
6b087adab8 | ||
|
|
3653b88da6 | ||
|
|
3223bf930d | ||
|
|
2b3bc6d1ff | ||
|
|
24d7672abb | ||
|
|
89628c27f3 | ||
|
|
9adbdc377d | ||
|
|
883cd81058 | ||
|
|
0d7d029255 | ||
|
|
c5229dd763 | ||
|
|
99d4190814 | ||
|
|
f086c02e13 | ||
|
|
b726f961fc | ||
|
|
29e30c388e | ||
|
|
54a40fe79c | ||
|
|
4e7b397c5a | ||
|
|
842e191c5f | ||
|
|
68bf599a1a | ||
|
|
a10966b66b |
@@ -4,6 +4,7 @@
|
||||
#
|
||||
# The configuration is split into three files. Look into those files for more details.
|
||||
#
|
||||
require: rubocop-rails
|
||||
inherit_from:
|
||||
|
||||
# The automatically generated todo list to ignore all current violations.
|
||||
|
||||
@@ -18,7 +18,7 @@
|
||||
#
|
||||
# This process probably doesn't need repeating. Otherwise there is plenty
|
||||
# of room for improvements and automation.
|
||||
Metrics/LineLength:
|
||||
Layout/LineLength:
|
||||
Max: 100
|
||||
Exclude:
|
||||
- Gemfile
|
||||
@@ -42,7 +42,6 @@ Metrics/LineLength:
|
||||
- app/controllers/application_controller.rb
|
||||
- app/controllers/checkout_controller.rb
|
||||
- app/controllers/spree/admin/adjustments_controller_decorator.rb
|
||||
- app/controllers/spree/admin/base_controller_decorator.rb
|
||||
- app/controllers/spree/admin/orders_controller_decorator.rb
|
||||
- app/controllers/spree/admin/payments_controller_decorator.rb
|
||||
- app/controllers/spree/credit_cards_controller.rb
|
||||
@@ -115,7 +114,6 @@ Metrics/LineLength:
|
||||
- lib/open_food_network/enterprise_issue_validator.rb
|
||||
- lib/open_food_network/group_buy_report.rb
|
||||
- lib/open_food_network/lettuce_share_report.rb
|
||||
- lib/open_food_network/order_and_distributor_report.rb
|
||||
- lib/open_food_network/order_cycle_form_applicator.rb
|
||||
- lib/open_food_network/order_cycle_management_report.rb
|
||||
- lib/open_food_network/payments_report.rb
|
||||
@@ -144,6 +142,7 @@ Metrics/LineLength:
|
||||
- spec/controllers/admin/subscriptions_controller_spec.rb
|
||||
- spec/controllers/admin/variant_overrides_controller_spec.rb
|
||||
- spec/controllers/api/base_controller_spec.rb
|
||||
- spec/controllers/api/exchange_products_controller_spec.rb
|
||||
- spec/controllers/api/logos_controller_spec.rb
|
||||
- spec/controllers/api/order_cycles_controller_spec.rb
|
||||
- spec/controllers/api/orders_controller_spec.rb
|
||||
@@ -305,6 +304,7 @@ Metrics/LineLength:
|
||||
- spec/serializers/api/admin/exchange_serializer_spec.rb
|
||||
- spec/serializers/api/admin/for_order_cycle/enterprise_serializer_spec.rb
|
||||
- spec/serializers/api/admin/for_order_cycle/supplied_product_serializer_spec.rb
|
||||
- spec/serializers/api/admin/order_cycle_serializer_spec.rb
|
||||
- spec/serializers/api/admin/subscription_customer_serializer_spec.rb
|
||||
- spec/serializers/api/admin/variant_override_serializer_spec.rb
|
||||
- spec/serializers/api/current_order_serializer_spec.rb
|
||||
@@ -312,11 +312,13 @@ Metrics/LineLength:
|
||||
- spec/serializers/api/order_serializer_spec.rb
|
||||
- spec/services/cart_service_spec.rb
|
||||
- spec/services/embedded_page_service_spec.rb
|
||||
- spec/services/exchange_products_renderer_spec.rb
|
||||
- spec/services/order_cycle_distributed_products_spec.rb
|
||||
- spec/services/order_cycle_distributed_variants_spec.rb
|
||||
- spec/services/order_cycle_form_spec.rb
|
||||
- spec/services/order_factory_spec.rb
|
||||
- spec/services/order_syncer_spec.rb
|
||||
- spec/services/permissions/order_spec.rb
|
||||
- spec/services/product_tag_rules_filterer_spec.rb
|
||||
- spec/services/products_renderer_spec.rb
|
||||
- spec/services/subscription_estimator_spec.rb
|
||||
@@ -366,7 +368,8 @@ Metrics/AbcSize:
|
||||
- app/controllers/spree/admin/payment_methods_controller.rb
|
||||
- app/controllers/spree/admin/payments_controller_decorator.rb
|
||||
- app/controllers/spree/admin/products_controller_decorator.rb
|
||||
- app/controllers/spree/admin/reports_controller_decorator.rb
|
||||
- app/controllers/spree/admin/reports_controller.rb
|
||||
- app/controllers/spree/admin/resource_controller.rb
|
||||
- app/controllers/spree/admin/search_controller_decorator.rb
|
||||
- app/controllers/spree/admin/taxons_controller.rb
|
||||
- app/controllers/spree/admin/users_controller.rb
|
||||
@@ -565,7 +568,8 @@ Metrics/MethodLength:
|
||||
- app/controllers/spree/admin/payment_methods_controller.rb
|
||||
- app/controllers/spree/admin/payments_controller_decorator.rb
|
||||
- app/controllers/spree/admin/products_controller_decorator.rb
|
||||
- app/controllers/spree/admin/reports_controller_decorator.rb
|
||||
- app/controllers/spree/admin/reports_controller.rb
|
||||
- app/controllers/spree/admin/resource_controller.rb
|
||||
- app/controllers/spree/admin/search_controller_decorator.rb
|
||||
- app/controllers/spree/admin/tax_categories_controller.rb
|
||||
- app/controllers/spree/admin/taxons_controller.rb
|
||||
@@ -644,7 +648,10 @@ Metrics/ClassLength:
|
||||
- app/controllers/admin/subscriptions_controller.rb
|
||||
- app/controllers/api/products_controller.rb
|
||||
- app/controllers/checkout_controller.rb
|
||||
- app/controllers/spree/admin/base_controller.rb
|
||||
- app/controllers/spree/admin/payment_methods_controller.rb
|
||||
- app/controllers/spree/admin/reports_controller.rb
|
||||
- app/controllers/spree/admin/resource_controller.rb
|
||||
- app/controllers/spree/admin/users_controller.rb
|
||||
- app/controllers/spree/orders_controller.rb
|
||||
- app/models/enterprise.rb
|
||||
@@ -700,6 +707,7 @@ Metrics/ModuleLength:
|
||||
- spec/models/spree/payment_spec.rb
|
||||
- spec/models/spree/product_spec.rb
|
||||
- spec/models/spree/variant_spec.rb
|
||||
- spec/services/permissions/order_spec.rb
|
||||
- spec/support/request/web_helper.rb
|
||||
|
||||
Metrics/ParameterLists:
|
||||
|
||||
@@ -5,7 +5,6 @@
|
||||
# rubocop locally, the default configuration file `.rubocop.yml` loads
|
||||
# our "todo lists" to ignore all current violations.
|
||||
AllCops:
|
||||
TargetRubyVersion: 2.2
|
||||
TargetRailsVersion: 3.2
|
||||
Exclude:
|
||||
- 'bin/**/*'
|
||||
@@ -41,7 +40,7 @@ Layout/MultilineMethodCallIndentation:
|
||||
Enabled: true
|
||||
EnforcedStyle: indented
|
||||
|
||||
Metrics/LineLength:
|
||||
Layout/LineLength:
|
||||
Max: 100
|
||||
|
||||
## TEMPORARY/CONTESTED SETTINGS
|
||||
|
||||
1201
.rubocop_todo.yml
1201
.rubocop_todo.yml
File diff suppressed because it is too large
Load Diff
16
Gemfile
16
Gemfile
@@ -3,7 +3,7 @@ ruby "2.3.7"
|
||||
git_source(:github) { |repo_name| "https://github.com/#{repo_name}.git" }
|
||||
|
||||
gem 'i18n', '~> 0.6.11'
|
||||
gem 'i18n-js', '~> 3.5.0'
|
||||
gem 'i18n-js', '~> 3.5.1'
|
||||
gem 'rails', '~> 3.2.22'
|
||||
gem 'rails-i18n', '~> 3.0.0'
|
||||
gem 'rails_safe_tasks', '~> 1.0'
|
||||
@@ -93,7 +93,7 @@ gem 'wkhtmltopdf-binary'
|
||||
|
||||
gem 'foreigner'
|
||||
gem 'immigrant'
|
||||
gem 'roo', '~> 2.7.0'
|
||||
gem 'roo', '~> 2.8.2'
|
||||
gem 'roo-xls', '~> 1.1.0'
|
||||
|
||||
gem 'whenever', require: false
|
||||
@@ -106,10 +106,7 @@ group :assets do
|
||||
gem 'coffee-rails', '~> 3.2.1'
|
||||
gem 'compass-rails'
|
||||
|
||||
gem 'mini_racer', '0.1.15'
|
||||
# Previously we found that libv8 6.7.288.46.1 breakis the compilation of mini_racer.
|
||||
# Now we see that we need to set the version explicitly. Nothing else depends on libv8.
|
||||
gem 'libv8', '6.3.292.48.1'
|
||||
gem 'mini_racer', '0.2.4'
|
||||
|
||||
gem 'uglifier', '>= 1.0.3'
|
||||
|
||||
@@ -135,7 +132,7 @@ group :test, :development do
|
||||
# Pretty printed test output
|
||||
gem 'atomic'
|
||||
gem 'awesome_print'
|
||||
gem 'capybara', '>= 2.15.4'
|
||||
gem 'capybara', '>= 2.18.0' # 3.0 requires nokogiri 1.8
|
||||
gem 'database_cleaner', '0.7.1', require: false
|
||||
gem "factory_bot_rails", require: false
|
||||
gem 'fuubar', '~> 2.5.0'
|
||||
@@ -148,7 +145,7 @@ group :test, :development do
|
||||
gem 'shoulda-matchers'
|
||||
gem 'timecop'
|
||||
gem 'unicorn-rails'
|
||||
gem 'webdrivers', '3.8.1'
|
||||
gem 'webdrivers'
|
||||
end
|
||||
|
||||
group :test do
|
||||
@@ -163,7 +160,8 @@ group :development do
|
||||
gem 'debugger-linecache'
|
||||
gem "newrelic_rpm", "~> 3.0"
|
||||
gem 'pry-byebug', '>= 3.4.3'
|
||||
gem 'rubocop', '>= 0.49.1'
|
||||
gem 'rubocop'
|
||||
gem 'rubocop-rails'
|
||||
gem 'spring', '1.7.2'
|
||||
gem 'spring-commands-rspec'
|
||||
|
||||
|
||||
83
Gemfile.lock
83
Gemfile.lock
@@ -129,7 +129,7 @@ GEM
|
||||
activesupport (= 3.2.22.5)
|
||||
arel (~> 3.0.2)
|
||||
tzinfo (~> 0.3.29)
|
||||
activerecord-import (1.0.3)
|
||||
activerecord-import (1.0.4)
|
||||
activerecord (>= 3.2)
|
||||
activerecord-postgresql-adapter (0.0.1)
|
||||
pg
|
||||
@@ -178,8 +178,7 @@ GEM
|
||||
rack (>= 1.0.0)
|
||||
rack-test (>= 0.5.4)
|
||||
xpath (>= 2.0, < 4.0)
|
||||
childprocess (0.9.0)
|
||||
ffi (~> 1.0, >= 1.0.11)
|
||||
childprocess (3.0.0)
|
||||
chronic (0.10.2)
|
||||
chunky_png (1.3.10)
|
||||
climate_control (0.2.0)
|
||||
@@ -213,7 +212,6 @@ GEM
|
||||
sass-rails (< 5.1)
|
||||
sprockets (< 4.0)
|
||||
concurrent-ruby (1.1.5)
|
||||
connection_pool (2.2.2)
|
||||
crack (0.4.3)
|
||||
safe_yaml (~> 1.0.0)
|
||||
css_parser (1.7.0)
|
||||
@@ -225,7 +223,7 @@ GEM
|
||||
activerecord (>= 3.2.0, < 5.0)
|
||||
fog (~> 1.0)
|
||||
rails (>= 3.2.0, < 5.0)
|
||||
ddtrace (0.30.0)
|
||||
ddtrace (0.31.0)
|
||||
msgpack
|
||||
debugger-linecache (1.2.0)
|
||||
deface (1.0.2)
|
||||
@@ -256,17 +254,17 @@ GEM
|
||||
dry-inflector (0.1.2)
|
||||
erubis (2.7.0)
|
||||
eventmachine (1.2.7)
|
||||
excon (0.62.0)
|
||||
excon (0.71.1)
|
||||
execjs (2.7.0)
|
||||
factory_bot (4.10.0)
|
||||
activesupport (>= 3.0.0)
|
||||
factory_bot_rails (4.10.0)
|
||||
factory_bot (~> 4.10.0)
|
||||
railties (>= 3.0.0)
|
||||
faraday (0.15.4)
|
||||
faraday (0.17.1)
|
||||
multipart-post (>= 1.2, < 3)
|
||||
ffaker (1.22.1)
|
||||
ffi (1.10.0)
|
||||
ffi (1.11.3)
|
||||
figaro (1.1.1)
|
||||
thor (~> 0.14)
|
||||
fission (0.5.0)
|
||||
@@ -439,7 +437,7 @@ GEM
|
||||
httparty (0.16.2)
|
||||
multi_xml (>= 0.5.2)
|
||||
i18n (0.6.11)
|
||||
i18n-js (3.5.0)
|
||||
i18n-js (3.5.1)
|
||||
i18n (>= 0.6.6)
|
||||
immigrant (0.3.6)
|
||||
activerecord (>= 3.0)
|
||||
@@ -467,7 +465,7 @@ GEM
|
||||
addressable (~> 2.3)
|
||||
letter_opener (1.7.0)
|
||||
launchy (~> 2.2)
|
||||
libv8 (6.3.292.48.1)
|
||||
libv8 (7.3.492.27.1)
|
||||
mail (2.5.5)
|
||||
mime-types (~> 1.16)
|
||||
treetop (~> 1.4.8)
|
||||
@@ -475,8 +473,8 @@ GEM
|
||||
mime-types (1.25.1)
|
||||
mini_mime (1.0.1)
|
||||
mini_portile2 (2.1.0)
|
||||
mini_racer (0.1.15)
|
||||
libv8 (~> 6.3)
|
||||
mini_racer (0.2.4)
|
||||
libv8 (>= 6.3)
|
||||
momentjs-rails (2.20.1)
|
||||
railties (>= 3.1)
|
||||
money (5.1.1)
|
||||
@@ -485,8 +483,6 @@ GEM
|
||||
multi_json (1.14.1)
|
||||
multi_xml (0.6.0)
|
||||
multipart-post (2.1.1)
|
||||
net-http-persistent (3.1.0)
|
||||
connection_pool (~> 2.2)
|
||||
newrelic_rpm (3.18.1.330)
|
||||
nokogiri (1.6.8.1)
|
||||
mini_portile2 (~> 2.1.0)
|
||||
@@ -496,7 +492,7 @@ GEM
|
||||
multi_json (~> 1.3)
|
||||
multi_xml (~> 0.5)
|
||||
rack (>= 1.2, < 3)
|
||||
oj (3.7.12)
|
||||
oj (3.10.0)
|
||||
orm_adapter (0.5.0)
|
||||
paper_trail (5.2.3)
|
||||
activerecord (>= 3.0, < 6.0)
|
||||
@@ -507,10 +503,10 @@ GEM
|
||||
activesupport (>= 3.0.0)
|
||||
cocaine (~> 0.5.0)
|
||||
mime-types
|
||||
parallel (1.18.0)
|
||||
parallel (1.19.1)
|
||||
paranoia (1.3.4)
|
||||
activerecord (~> 3.1)
|
||||
parser (2.6.5.0)
|
||||
parser (2.7.0.2)
|
||||
ast (~> 2.4.0)
|
||||
paypal-sdk-core (0.2.10)
|
||||
multi_json (~> 1.0)
|
||||
@@ -534,7 +530,7 @@ GEM
|
||||
rack (1.4.7)
|
||||
rack-cache (1.9.0)
|
||||
rack (>= 0.4)
|
||||
rack-mini-profiler (1.0.0)
|
||||
rack-mini-profiler (1.1.4)
|
||||
rack (>= 1.2.0)
|
||||
rack-protection (1.5.5)
|
||||
rack
|
||||
@@ -588,9 +584,9 @@ GEM
|
||||
roadie-rails (1.3.0)
|
||||
railties (>= 3.0, < 5.3)
|
||||
roadie (~> 3.1)
|
||||
roo (2.7.1)
|
||||
roo (2.8.2)
|
||||
nokogiri (~> 1)
|
||||
rubyzip (~> 1.1, < 2.0.0)
|
||||
rubyzip (>= 1.2.1, < 2.0.0)
|
||||
roo-xls (1.1.0)
|
||||
nokogiri
|
||||
roo (>= 2.0.0beta1, < 3)
|
||||
@@ -618,13 +614,16 @@ GEM
|
||||
rspec-retry (0.6.2)
|
||||
rspec-core (> 3.3)
|
||||
rspec-support (3.9.0)
|
||||
rubocop (0.68.1)
|
||||
rubocop (0.79.0)
|
||||
jaro_winkler (~> 1.5.1)
|
||||
parallel (~> 1.10)
|
||||
parser (>= 2.5, != 2.5.1.1)
|
||||
parser (>= 2.7.0.1)
|
||||
rainbow (>= 2.2.2, < 4.0)
|
||||
ruby-progressbar (~> 1.7)
|
||||
unicode-display_width (>= 1.4.0, < 1.6)
|
||||
unicode-display_width (>= 1.4.0, < 1.7)
|
||||
rubocop-rails (2.4.1)
|
||||
rack (>= 1.1)
|
||||
rubocop (>= 0.72.0)
|
||||
ruby-ole (1.2.12.1)
|
||||
ruby-progressbar (1.10.1)
|
||||
ruby-rc4 (0.1.5)
|
||||
@@ -638,9 +637,9 @@ GEM
|
||||
select2-rails (3.4.9)
|
||||
sass-rails
|
||||
thor (~> 0.14)
|
||||
selenium-webdriver (3.141.0)
|
||||
childprocess (~> 0.5)
|
||||
rubyzip (~> 1.2, >= 1.2.2)
|
||||
selenium-webdriver (3.142.7)
|
||||
childprocess (>= 0.5, < 4.0)
|
||||
rubyzip (>= 1.2.2)
|
||||
shoulda-matchers (2.8.0)
|
||||
activesupport (>= 3.0.0)
|
||||
simplecov (0.17.1)
|
||||
@@ -666,10 +665,8 @@ GEM
|
||||
tilt (~> 1.1, != 1.3.0)
|
||||
state_machine (1.2.0)
|
||||
stringex (1.5.1)
|
||||
stripe (4.24.0)
|
||||
faraday (~> 0.13)
|
||||
net-http-persistent (~> 3.0)
|
||||
test-unit (3.3.4)
|
||||
stripe (5.11.0)
|
||||
test-unit (3.3.5)
|
||||
power_assert
|
||||
thor (0.20.3)
|
||||
tilt (1.4.1)
|
||||
@@ -682,11 +679,11 @@ GEM
|
||||
turbo-sprockets-rails3 (0.3.14)
|
||||
railties (> 3.2.8, < 4.0.0)
|
||||
sprockets (>= 2.2.0)
|
||||
tzinfo (0.3.55)
|
||||
tzinfo (0.3.56)
|
||||
uglifier (4.2.0)
|
||||
execjs (>= 0.3.0, < 3)
|
||||
unicode-display_width (1.5.0)
|
||||
unicorn (5.5.1)
|
||||
unicode-display_width (1.6.0)
|
||||
unicorn (5.5.2)
|
||||
kgio (~> 2.6)
|
||||
raindrops (~> 0.7)
|
||||
unicorn-rails (2.2.1)
|
||||
@@ -699,10 +696,10 @@ GEM
|
||||
railties (>= 3.0)
|
||||
warden (1.2.7)
|
||||
rack (>= 1.0)
|
||||
webdrivers (3.8.1)
|
||||
webdrivers (4.2.0)
|
||||
nokogiri (~> 1.6)
|
||||
rubyzip (~> 1.0)
|
||||
selenium-webdriver (~> 3.0)
|
||||
rubyzip (>= 1.3.0)
|
||||
selenium-webdriver (>= 3.0, < 4.0)
|
||||
webmock (3.7.6)
|
||||
addressable (>= 2.3.6)
|
||||
crack (>= 0.3.2)
|
||||
@@ -734,7 +731,7 @@ DEPENDENCIES
|
||||
blockenspiel
|
||||
bugsnag
|
||||
byebug (~> 9.0.0)
|
||||
capybara (>= 2.15.4)
|
||||
capybara (>= 2.18.0)
|
||||
coffee-rails (~> 3.2.1)
|
||||
combine_pdf
|
||||
compass-rails
|
||||
@@ -763,7 +760,7 @@ DEPENDENCIES
|
||||
gmaps4rails
|
||||
haml
|
||||
i18n (~> 0.6.11)
|
||||
i18n-js (~> 3.5.0)
|
||||
i18n-js (~> 3.5.1)
|
||||
immigrant
|
||||
jquery-migrate-rails
|
||||
jquery-rails (= 3.0.4)
|
||||
@@ -772,8 +769,7 @@ DEPENDENCIES
|
||||
kaminari (~> 0.14.1)
|
||||
knapsack
|
||||
letter_opener (>= 1.4.1)
|
||||
libv8 (= 6.3.292.48.1)
|
||||
mini_racer (= 0.1.15)
|
||||
mini_racer (= 0.2.4)
|
||||
momentjs-rails
|
||||
newrelic_rpm (~> 3.0)
|
||||
nokogiri (>= 1.6.7.1)
|
||||
@@ -794,11 +790,12 @@ DEPENDENCIES
|
||||
rails_safe_tasks (~> 1.0)
|
||||
redcarpet
|
||||
roadie-rails (~> 1.3.0)
|
||||
roo (~> 2.7.0)
|
||||
roo (~> 2.8.2)
|
||||
roo-xls (~> 1.1.0)
|
||||
rspec-rails (>= 3.5.2)
|
||||
rspec-retry
|
||||
rubocop (>= 0.49.1)
|
||||
rubocop
|
||||
rubocop-rails
|
||||
sass (~> 3.3)
|
||||
sass-rails (~> 3.2.3)
|
||||
selenium-webdriver
|
||||
@@ -821,7 +818,7 @@ DEPENDENCIES
|
||||
unicorn
|
||||
unicorn-rails
|
||||
web!
|
||||
webdrivers (= 3.8.1)
|
||||
webdrivers
|
||||
webmock
|
||||
whenever
|
||||
wicked_pdf
|
||||
|
||||
@@ -142,7 +142,7 @@ angular.module("ofn.admin").controller "AdminProductEditCtrl", ($scope, $timeout
|
||||
if confirm("Are you sure?")
|
||||
$http(
|
||||
method: "DELETE"
|
||||
url: "/api/products/" + product.id + "/soft_delete"
|
||||
url: "/api/products/" + product.id
|
||||
).success (data) ->
|
||||
$scope.products.splice $scope.products.indexOf(product), 1
|
||||
DirtyProducts.deleteProduct product.id
|
||||
@@ -157,7 +157,7 @@ angular.module("ofn.admin").controller "AdminProductEditCtrl", ($scope, $timeout
|
||||
if confirm(t("are_you_sure"))
|
||||
$http(
|
||||
method: "DELETE"
|
||||
url: "/api/products/" + product.permalink_live + "/variants/" + variant.id + "/soft_delete"
|
||||
url: "/api/products/" + product.permalink_live + "/variants/" + variant.id
|
||||
).success (data) ->
|
||||
$scope.removeVariant(product, variant)
|
||||
else
|
||||
|
||||
@@ -1,5 +1,31 @@
|
||||
angular.module('admin.orderCycles').controller 'AdminOrderCycleIncomingCtrl', ($scope, $controller, $location, Enterprise, ocInstance) ->
|
||||
angular.module('admin.orderCycles').controller 'AdminOrderCycleIncomingCtrl', ($scope, $controller, $location, Enterprise, OrderCycle, ExchangeProduct, ocInstance) ->
|
||||
$controller('AdminOrderCycleExchangesCtrl', {$scope: $scope, ocInstance: ocInstance, $location: $location})
|
||||
|
||||
$scope.enterpriseTotalVariants = (enterprise) ->
|
||||
Enterprise.totalVariants(enterprise)
|
||||
$scope.view = 'incoming'
|
||||
|
||||
$scope.exchangeTotalVariants = (exchange) ->
|
||||
return unless $scope.enterprises? && $scope.enterprises[exchange.enterprise_id]?
|
||||
|
||||
enterprise = $scope.enterprises[exchange.enterprise_id]
|
||||
return enterprise.numVariants if enterprise.numVariants?
|
||||
|
||||
enterprise.numVariants = 0
|
||||
params = { exchange_id: exchange.id, enterprise_id: exchange.enterprise_id, order_cycle_id: $scope.order_cycle.id, incoming: true}
|
||||
ExchangeProduct.countVariants params, (variants_count) ->
|
||||
enterprise.numVariants = variants_count
|
||||
$scope.setSelectAllVariantsCheckboxValue(exchange, enterprise.numVariants)
|
||||
|
||||
return enterprise.numVariants
|
||||
|
||||
$scope.addSupplier = ($event) ->
|
||||
$event.preventDefault()
|
||||
OrderCycle.addSupplier $scope.new_supplier_id
|
||||
|
||||
# To select all variants we first need to load them all from the server
|
||||
#
|
||||
# This is only needed in Incoming exchanges as here we use supplied_products,
|
||||
# in Outgoing Exchanges the variants are loaded as part of the Exchange payload
|
||||
$scope.selectAllVariants = (exchange, selected) ->
|
||||
$scope.loadAllExchangeProducts(exchange).then ->
|
||||
$scope.setExchangeVariants(exchange, $scope.suppliedVariants(exchange.enterprise_id), selected)
|
||||
$scope.$apply()
|
||||
|
||||
@@ -18,11 +18,11 @@ angular.module('admin.orderCycles')
|
||||
$scope.cancel = (destination) ->
|
||||
$window.location = destination
|
||||
|
||||
# Used in panels/exchange_supplied_products.html
|
||||
# Used in panels/exchange_products_supplied.html
|
||||
$scope.suppliedVariants = (enterprise_id) ->
|
||||
Enterprise.suppliedVariants(enterprise_id)
|
||||
|
||||
# Used in panels/exchange_supplied_products.html and panels/exchange_distributed_products.html
|
||||
# Used in panels/exchange_products_supplied.html and panels/exchange_products_distributed.html
|
||||
$scope.setExchangeVariants = (exchange, variants, selected) ->
|
||||
OrderCycle.setExchangeVariants(exchange, variants, selected)
|
||||
|
||||
|
||||
@@ -1,10 +1,15 @@
|
||||
angular.module('admin.orderCycles')
|
||||
.controller 'AdminOrderCycleExchangesCtrl', ($scope, $controller, $filter, $window, $location, $timeout, OrderCycle, Enterprise, EnterpriseFee, Schedules, RequestMonitor, ocInstance, StatusMessage) ->
|
||||
.controller 'AdminOrderCycleExchangesCtrl', ($scope, $controller, $filter, $window, $location, $timeout, OrderCycle, ExchangeProduct, Enterprise, EnterpriseFee, Schedules, RequestMonitor, ocInstance, StatusMessage) ->
|
||||
$controller('AdminEditOrderCycleCtrl', {$scope: $scope, ocInstance: ocInstance, $location: $location})
|
||||
|
||||
$scope.supplier_enterprises = Enterprise.producer_enterprises
|
||||
$scope.distributor_enterprises = Enterprise.hub_enterprises
|
||||
$scope.supplied_products = Enterprise.supplied_products
|
||||
|
||||
$scope.productsLoading = ->
|
||||
RequestMonitor.loading
|
||||
|
||||
$scope.setSelectAllVariantsCheckboxValue = (exchange, totalNumberOfVariants) ->
|
||||
exchange.select_all_variants = $scope.exchangeSelectedVariants(exchange) >= totalNumberOfVariants
|
||||
|
||||
$scope.exchangeSelectedVariants = (exchange) ->
|
||||
OrderCycle.exchangeSelectedVariants(exchange)
|
||||
@@ -29,14 +34,6 @@ angular.module('admin.orderCycles')
|
||||
OrderCycle.removeExchangeFee(exchange, index)
|
||||
$scope.order_cycle_form.$dirty = true
|
||||
|
||||
$scope.addSupplier = ($event) ->
|
||||
$event.preventDefault()
|
||||
OrderCycle.addSupplier($scope.new_supplier_id)
|
||||
|
||||
$scope.addDistributor = ($event) ->
|
||||
$event.preventDefault()
|
||||
OrderCycle.addDistributor($scope.new_distributor_id)
|
||||
|
||||
$scope.setPickupTimeFieldDirty = (index) ->
|
||||
$timeout ->
|
||||
pickup_time_field_name = "order_cycle_outgoing_exchange_" + index + "_pickup_time"
|
||||
@@ -44,3 +41,36 @@ angular.module('admin.orderCycles')
|
||||
|
||||
$scope.removeDistributionOfVariant = (variant_id) ->
|
||||
OrderCycle.removeDistributionOfVariant(variant_id)
|
||||
|
||||
$scope.loadExchangeProducts = (exchange, page = 1) ->
|
||||
enterprise = $scope.enterprises[exchange.enterprise_id]
|
||||
enterprise.supplied_products ?= []
|
||||
|
||||
return if enterprise.last_page_loaded? && enterprise.last_page_loaded >= page
|
||||
enterprise.last_page_loaded = page
|
||||
|
||||
incoming = true if $scope.view == 'incoming'
|
||||
params = { exchange_id: exchange.id, enterprise_id: exchange.enterprise_id, order_cycle_id: $scope.order_cycle.id, incoming: incoming, page: page}
|
||||
ExchangeProduct.index params, (products, num_of_pages, num_of_products) ->
|
||||
enterprise.num_of_pages = num_of_pages
|
||||
enterprise.num_of_products = num_of_products
|
||||
enterprise.supplied_products.push products...
|
||||
|
||||
$scope.loadMoreExchangeProducts = (exchange) ->
|
||||
$scope.loadExchangeProducts(exchange, $scope.enterprises[exchange.enterprise_id].last_page_loaded + 1)
|
||||
|
||||
$scope.loadAllExchangeProducts = (exchange) ->
|
||||
enterprise = $scope.enterprises[exchange.enterprise_id]
|
||||
|
||||
if enterprise.last_page_loaded < enterprise.num_of_pages
|
||||
for page_to_load in [(enterprise.last_page_loaded + 1)..enterprise.num_of_pages]
|
||||
RequestMonitor.load $scope.loadExchangeProducts(exchange, page_to_load).$promise
|
||||
|
||||
RequestMonitor.loadQueue
|
||||
|
||||
# initialize exchange products panel if not yet done
|
||||
$scope.exchangeProdutsPanelInitialized = []
|
||||
$scope.initializeExchangeProductsPanel = (exchange) ->
|
||||
return if $scope.exchangeProdutsPanelInitialized[exchange.enterprise_id]
|
||||
RequestMonitor.load $scope.loadExchangeProducts(exchange).$promise
|
||||
$scope.exchangeProdutsPanelInitialized[exchange.enterprise_id] = true
|
||||
|
||||
@@ -1,8 +1,7 @@
|
||||
angular.module('admin.orderCycles').controller 'AdminOrderCycleOutgoingCtrl', ($scope, $controller, $filter, $location, OrderCycle, ocInstance, StatusMessage) ->
|
||||
$controller('AdminOrderCycleExchangesCtrl', {$scope: $scope, ocInstance: ocInstance, $location: $location})
|
||||
|
||||
$scope.productSuppliedToOrderCycle = (product) ->
|
||||
OrderCycle.productSuppliedToOrderCycle(product)
|
||||
$scope.view = 'outgoing'
|
||||
|
||||
$scope.variantSuppliedToOrderCycle = (variant) ->
|
||||
OrderCycle.variantSuppliedToOrderCycle(variant)
|
||||
@@ -10,6 +9,15 @@ angular.module('admin.orderCycles').controller 'AdminOrderCycleOutgoingCtrl', ($
|
||||
$scope.incomingExchangeVariantsFor = (enterprise_id) ->
|
||||
$filter('filterExchangeVariants')(OrderCycle.incomingExchangesVariants(), $scope.order_cycle.visible_variants_for_outgoing_exchanges[enterprise_id])
|
||||
|
||||
$scope.exchangeTotalVariants = (exchange) ->
|
||||
totalNumberOfVariants = $scope.incomingExchangeVariantsFor(exchange.enterprise_id).length
|
||||
$scope.setSelectAllVariantsCheckboxValue(exchange, totalNumberOfVariants)
|
||||
totalNumberOfVariants
|
||||
|
||||
$scope.addDistributor = ($event) ->
|
||||
$event.preventDefault()
|
||||
OrderCycle.addDistributor $scope.new_distributor_id
|
||||
|
||||
$scope.submit = ($event, destination) ->
|
||||
$event.preventDefault()
|
||||
StatusMessage.display 'progress', t('js.saving')
|
||||
|
||||
@@ -1,23 +1,33 @@
|
||||
angular.module('admin.orderCycles').controller "AdminSimpleCreateOrderCycleCtrl", ($scope, $controller, $window, OrderCycle, Enterprise, EnterpriseFee, StatusMessage, Schedules, RequestMonitor, ocInstance) ->
|
||||
angular.module('admin.orderCycles').controller "AdminSimpleCreateOrderCycleCtrl", ($scope, $controller, $window, OrderCycle, Enterprise, EnterpriseFee, ExchangeProduct, StatusMessage, Schedules, RequestMonitor, ocInstance) ->
|
||||
$controller('AdminOrderCycleBasicCtrl', {$scope: $scope, ocInstance: ocInstance})
|
||||
|
||||
$scope.order_cycle = OrderCycle.new {coordinator_id: ocInstance.coordinator_id}, =>
|
||||
# TODO: make this a get method, which only fetches one enterprise
|
||||
$scope.enterprises = Enterprise.index {coordinator_id: ocInstance.coordinator_id}, (enterprises) =>
|
||||
$scope.init(enterprises)
|
||||
$scope.enterprise_fees = EnterpriseFee.index(coordinator_id: ocInstance.coordinator_id)
|
||||
|
||||
$scope.init = (enterprises) ->
|
||||
enterprise = enterprises[Object.keys(enterprises)[0]]
|
||||
OrderCycle.addSupplier enterprise.id
|
||||
OrderCycle.addDistributor enterprise.id
|
||||
OrderCycle.order_cycle.coordinator_id = enterprise.id
|
||||
|
||||
OrderCycle.addDistributor enterprise.id, $scope.setOutgoingExchange
|
||||
OrderCycle.addSupplier enterprise.id, $scope.loadExchangeProducts
|
||||
|
||||
$scope.setOutgoingExchange = ->
|
||||
$scope.outgoing_exchange = OrderCycle.order_cycle.outgoing_exchanges[0]
|
||||
|
||||
# All variants start as checked
|
||||
OrderCycle.setExchangeVariants(OrderCycle.order_cycle.incoming_exchanges[0],
|
||||
Enterprise.suppliedVariants(enterprise.id), true)
|
||||
$scope.loadExchangeProducts = ->
|
||||
$scope.incoming_exchange = OrderCycle.order_cycle.incoming_exchanges[0]
|
||||
|
||||
OrderCycle.order_cycle.coordinator_id = enterprise.id
|
||||
params = { enterprise_id: $scope.incoming_exchange.enterprise_id, incoming: true }
|
||||
ExchangeProduct.index params, $scope.storeProductsAndSelectAllVariants
|
||||
|
||||
$scope.storeProductsAndSelectAllVariants = (products) ->
|
||||
$scope.enterprises[$scope.incoming_exchange.enterprise_id].supplied_products = products
|
||||
|
||||
# All variants start as checked
|
||||
OrderCycle.setExchangeVariants($scope.incoming_exchange,
|
||||
Enterprise.suppliedVariants($scope.incoming_exchange.enterprise_id), true)
|
||||
|
||||
$scope.removeDistributionOfVariant = angular.noop
|
||||
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
angular.module('admin.orderCycles').controller "AdminSimpleEditOrderCycleCtrl", ($scope, $controller, $location, $window, OrderCycle, Enterprise, EnterpriseFee, Schedules, RequestMonitor, StatusMessage, ocInstance) ->
|
||||
angular.module('admin.orderCycles').controller "AdminSimpleEditOrderCycleCtrl", ($scope, $controller, $location, $window, OrderCycle, Enterprise, EnterpriseFee, ExchangeProduct, Schedules, RequestMonitor, StatusMessage, ocInstance) ->
|
||||
$controller('AdminOrderCycleBasicCtrl', {$scope: $scope, ocInstance: ocInstance})
|
||||
|
||||
$scope.orderCycleId = ->
|
||||
@@ -11,6 +11,12 @@ angular.module('admin.orderCycles').controller "AdminSimpleEditOrderCycleCtrl",
|
||||
|
||||
$scope.init = ->
|
||||
$scope.outgoing_exchange = OrderCycle.order_cycle.outgoing_exchanges[0]
|
||||
$scope.loadExchangeProducts()
|
||||
|
||||
$scope.loadExchangeProducts = ->
|
||||
exchange = OrderCycle.order_cycle.incoming_exchanges[0]
|
||||
ExchangeProduct.index { exchange_id: exchange.id }, (products) ->
|
||||
$scope.enterprises[exchange.enterprise_id].supplied_products = products
|
||||
|
||||
$scope.removeDistributionOfVariant = angular.noop
|
||||
|
||||
|
||||
@@ -12,7 +12,6 @@ angular.module('admin.orderCycles').factory('Enterprise', ($resource) ->
|
||||
enterprises: {}
|
||||
producer_enterprises: []
|
||||
hub_enterprises: []
|
||||
supplied_products: []
|
||||
loaded: false
|
||||
|
||||
index: (params={}, callback=null) ->
|
||||
@@ -22,9 +21,6 @@ angular.module('admin.orderCycles').factory('Enterprise', ($resource) ->
|
||||
@producer_enterprises.push(enterprise) if enterprise.is_primary_producer
|
||||
@hub_enterprises.push(enterprise) if enterprise.sells == 'any'
|
||||
|
||||
for product in enterprise.supplied_products
|
||||
@supplied_products.push(product)
|
||||
|
||||
@loaded = true
|
||||
(callback || angular.noop)(@enterprises)
|
||||
|
||||
@@ -39,13 +35,4 @@ angular.module('admin.orderCycles').factory('Enterprise', ($resource) ->
|
||||
variant.id for variant in product.variants
|
||||
else
|
||||
[product.master_id]
|
||||
|
||||
totalVariants: (enterprise) ->
|
||||
numVariants = 0
|
||||
|
||||
if enterprise
|
||||
counts = for product in enterprise.supplied_products
|
||||
numVariants += if product.variants.length == 0 then 1 else product.variants.length
|
||||
|
||||
numVariants
|
||||
})
|
||||
|
||||
@@ -0,0 +1,16 @@
|
||||
angular.module('admin.orderCycles').factory('ExchangeProduct', ($resource) ->
|
||||
ExchangeProductResource = $resource('/api/exchanges/:exchange_id/products.json', {}, {
|
||||
'index': { method: 'GET' }
|
||||
'variant_count': { method: 'GET', params: { action_name: "variant_count" }}
|
||||
})
|
||||
{
|
||||
ExchangeProductResource: ExchangeProductResource
|
||||
|
||||
index: (params={}, callback=null) ->
|
||||
ExchangeProductResource.index params, (data) =>
|
||||
(callback || angular.noop)(data.products, data.pagination.pages, data.pagination.results)
|
||||
|
||||
countVariants: (params={}, callback=null) ->
|
||||
ExchangeProductResource.variant_count params, (data) =>
|
||||
(callback || angular.noop)(data.count)
|
||||
})
|
||||
@@ -1,4 +1,4 @@
|
||||
angular.module('admin.orderCycles').factory 'OrderCycle', ($resource, $window, StatusMessage, Panels) ->
|
||||
angular.module('admin.orderCycles').factory 'OrderCycle', ($resource, $window, $timeout, StatusMessage, Panels) ->
|
||||
OrderCycleResource = $resource '/admin/order_cycles/:action_name/:order_cycle_id.json', {}, {
|
||||
'index': { method: 'GET', isArray: true}
|
||||
'new' : { method: 'GET', params: { action_name: "new" } }
|
||||
@@ -44,11 +44,15 @@ angular.module('admin.orderCycles').factory 'OrderCycle', ($resource, $window, S
|
||||
@removeDistributionOfVariant(variant.id) if exchange.incoming
|
||||
|
||||
|
||||
addSupplier: (new_supplier_id) ->
|
||||
this.order_cycle.incoming_exchanges.push({enterprise_id: new_supplier_id, incoming: true, active: true, variants: {}, enterprise_fees: []})
|
||||
addSupplier: (new_supplier_id, callback) ->
|
||||
this.order_cycle.incoming_exchanges.push({enterprise_id: new_supplier_id, incoming: true, active: true, variants: {}, enterprise_fees: []})
|
||||
$timeout ->
|
||||
(callback || angular.noop)()
|
||||
|
||||
addDistributor: (new_distributor_id) ->
|
||||
this.order_cycle.outgoing_exchanges.push({enterprise_id: new_distributor_id, incoming: false, active: true, variants: {}, enterprise_fees: []})
|
||||
addDistributor: (new_distributor_id, callback) ->
|
||||
this.order_cycle.outgoing_exchanges.push({ enterprise_id: new_distributor_id, incoming: false, active: true, variants: {}, enterprise_fees: [] })
|
||||
$timeout ->
|
||||
(callback || angular.noop)()
|
||||
|
||||
removeExchange: (exchange) ->
|
||||
if exchange.incoming
|
||||
@@ -71,18 +75,6 @@ angular.module('admin.orderCycles').factory 'OrderCycle', ($resource, $window, S
|
||||
removeExchangeFee: (exchange, index) ->
|
||||
exchange.enterprise_fees.splice(index, 1)
|
||||
|
||||
productSuppliedToOrderCycle: (product) ->
|
||||
product_variant_ids = (variant.id for variant in product.variants)
|
||||
variant_ids = [product.master_id].concat(product_variant_ids)
|
||||
incomingExchangesVariants = this.incomingExchangesVariants()
|
||||
|
||||
# TODO: This is an O(n^2) implementation of set intersection and thus is slooow.
|
||||
# Use a better algorithm if needed.
|
||||
# Also, incomingExchangesVariants is called every time, when it only needs to be
|
||||
# called once per change to incoming variants. Some sort of caching?
|
||||
ids = (variant_id for variant_id in variant_ids when incomingExchangesVariants.indexOf(variant_id) != -1)
|
||||
ids.length > 0
|
||||
|
||||
variantSuppliedToOrderCycle: (variant) ->
|
||||
this.incomingExchangesVariants().indexOf(variant.id) != -1
|
||||
|
||||
@@ -143,7 +135,8 @@ angular.module('admin.orderCycles').factory 'OrderCycle', ($resource, $window, S
|
||||
delete(service.order_cycle.exchanges)
|
||||
service.loaded = true
|
||||
|
||||
(callback || angular.noop)(service.order_cycle)
|
||||
$timeout ->
|
||||
(callback || angular.noop)(service.order_cycle)
|
||||
|
||||
this.order_cycle
|
||||
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
angular.module("admin.orders").controller "ordersCtrl", ($scope, RequestMonitor, Orders, SortOptions, $window, $filter) ->
|
||||
angular.module("admin.orders").controller "ordersCtrl", ($scope, $timeout, RequestMonitor, Orders, SortOptions, $window, $filter) ->
|
||||
$scope.RequestMonitor = RequestMonitor
|
||||
$scope.pagination = Orders.pagination
|
||||
$scope.orders = Orders.all
|
||||
@@ -13,6 +13,7 @@ angular.module("admin.orders").controller "ordersCtrl", ($scope, RequestMonitor,
|
||||
$scope.selected = false
|
||||
$scope.select_all = false
|
||||
$scope.poll = 0
|
||||
$scope.rowStatus = {}
|
||||
|
||||
$scope.initialise = ->
|
||||
$scope.per_page = 15
|
||||
@@ -69,6 +70,23 @@ angular.module("admin.orders").controller "ordersCtrl", ($scope, RequestMonitor,
|
||||
$scope.fetchResults()
|
||||
, true
|
||||
|
||||
$scope.capturePayment = (order) ->
|
||||
$scope.rowAction('capture', order)
|
||||
|
||||
$scope.shipOrder = (order) ->
|
||||
$scope.rowAction('ship', order)
|
||||
|
||||
$scope.rowAction = (action, order) ->
|
||||
$scope.rowStatus[order.id] = "loading"
|
||||
|
||||
Orders[action](order).$promise.then (data) ->
|
||||
$scope.rowStatus[order.id] = "success"
|
||||
$timeout(->
|
||||
$scope.rowStatus[order.id] = null
|
||||
, 1500)
|
||||
, (error) ->
|
||||
$scope.rowStatus[order.id] = "error"
|
||||
|
||||
$scope.changePage = (newPage) ->
|
||||
$scope.page = newPage
|
||||
$scope.fetchResults(newPage)
|
||||
|
||||
@@ -5,4 +5,14 @@ angular.module("admin.resources").factory 'OrderResource', ($resource) ->
|
||||
method: 'GET'
|
||||
'update':
|
||||
method: 'PUT'
|
||||
'capture':
|
||||
url: '/api/orders/:id/capture.json'
|
||||
method: 'PUT'
|
||||
params:
|
||||
id: '@id'
|
||||
'ship':
|
||||
url: '/api/orders/:id/ship.json'
|
||||
method: 'PUT'
|
||||
params:
|
||||
id: '@id'
|
||||
})
|
||||
|
||||
@@ -44,5 +44,19 @@ angular.module("admin.resources").factory 'Orders', ($q, OrderResource, RequestM
|
||||
changed.push attr unless attr is "$$hashKey"
|
||||
changed
|
||||
|
||||
capture: (order) ->
|
||||
@processAction('capture', order)
|
||||
|
||||
ship: (order) ->
|
||||
@processAction('ship', order)
|
||||
|
||||
processAction: (action, order) ->
|
||||
OrderResource[action] {id: order.number}, (data) =>
|
||||
if data.id
|
||||
angular.merge(order, data)
|
||||
data
|
||||
, (response) =>
|
||||
response.data
|
||||
|
||||
resetAttribute: (order, attribute) ->
|
||||
order[attribute] = @pristineByID[order.id][attribute]
|
||||
|
||||
@@ -1,5 +1,7 @@
|
||||
.row.exchange-distributed-products
|
||||
.sixteen.columns.alpha.omega
|
||||
.row.exchange-distributed-products{'ng-init' => 'initializeExchangeProductsPanel(exchange)'}
|
||||
.sixteen.columns.alpha.omega{ 'ng-show' => 'enterprises[exchange.enterprise_id].supplied_products.length != 0' }
|
||||
%div{ 'ng-include' => "'admin/panels/exchange_products_panel_header.html'" }
|
||||
|
||||
.exchange-select-all-variants
|
||||
%label
|
||||
%input{ type: 'checkbox', name: 'order_cycle_outgoing_exchange_{{ $parent.$index }}_select_all_variants',
|
||||
@@ -7,11 +9,10 @@
|
||||
'ng-model' => 'exchange.select_all_variants',
|
||||
'ng-change' => 'setExchangeVariants(exchange, incomingExchangeVariantsFor(exchange.enterprise_id), exchange.select_all_variants)',
|
||||
'id' => 'order_cycle_outgoing_exchange_{{ $parent.$index }}_select_all_variants' }
|
||||
{{ 'admin.select_all' | t }}
|
||||
{{ 'js.admin.panels.exchange_products.select_all_products' | t:{ total_number_of_products: enterprises[exchange.enterprise_id].num_of_products } }}
|
||||
|
||||
.exchange-products
|
||||
-# Scope product list based on permissions the current user has to view variants in this exchange
|
||||
.exchange-product{'ng-repeat' => 'product in supplied_products | filter:productSuppliedToOrderCycle | visibleProducts:exchange:order_cycle.visible_variants_for_outgoing_exchanges' }
|
||||
.exchange-products{ 'ng-hide' => 'productsLoading()' }
|
||||
.exchange-product{'ng-repeat' => 'product in enterprises[exchange.enterprise_id].supplied_products | filter:visibleProducts:exchange:order_cycle.visible_variants_for_outgoing_exchanges' }
|
||||
.exchange-product-details
|
||||
%label
|
||||
%img{'ng-src' => '{{ product.image_url }}'}
|
||||
@@ -26,3 +27,5 @@
|
||||
'id' => 'order_cycle_outgoing_exchange_{{ $parent.$parent.$index }}_variants_{{ variant.id }}',
|
||||
'ng-disabled' => '!order_cycle.editable_variants_for_outgoing_exchanges.hasOwnProperty(exchange.enterprise_id) || order_cycle.editable_variants_for_outgoing_exchanges[exchange.enterprise_id].indexOf(variant.id) < 0' }
|
||||
{{ variant.label }}
|
||||
|
||||
%div{ 'ng-include' => "'admin/panels/exchange_products_panel_footer.html'" }
|
||||
@@ -0,0 +1,11 @@
|
||||
.pagination{ 'ng-show' => 'enterprises[exchange.enterprise_id].last_page_loaded < enterprises[exchange.enterprise_id].num_of_pages && !productsLoading()'}
|
||||
.button{ 'ng-click' => 'loadMoreExchangeProducts(exchange)' }
|
||||
{{ 'js.admin.panels.exchange_products.load_more_products' | t }}
|
||||
.button{ 'ng-click' => 'loadAllExchangeProducts(exchange)' }
|
||||
{{ 'js.admin.panels.exchange_products.load_all_products' | t }}
|
||||
|
||||
.sixteen.columns.alpha#loading{ 'ng-show' => 'productsLoading()' }
|
||||
%br
|
||||
%img.spinner{ src: "/assets/spinning-circles.svg" }
|
||||
%h1
|
||||
{{ 'js.admin.panels.exchange_products.loading_products' | t }}
|
||||
@@ -0,0 +1,5 @@
|
||||
.exchange-load-all-variants
|
||||
%div
|
||||
{{ 'js.admin.panels.exchange_products.products_loaded' | t:{ num_of_products_loaded: enterprises[exchange.enterprise_id].supplied_products.length, total_number_of_products: enterprises[exchange.enterprise_id].num_of_products } }}
|
||||
%a{ 'ng-click' => 'loadAllExchangeProducts(exchange)', 'ng-show' => 'enterprises[exchange.enterprise_id].last_page_loaded < enterprises[exchange.enterprise_id].num_of_pages' }
|
||||
{{ 'js.admin.panels.exchange_products.load_all_products' | t }}
|
||||
@@ -0,0 +1,12 @@
|
||||
.row.exchange-supplied-products
|
||||
.sixteen.columns.alpha.omega
|
||||
.exchange-select-all-variants
|
||||
%label
|
||||
%input{ type: 'checkbox', name: 'order_cycle_incoming_exchange_{{ $index }}_select_all_variants',
|
||||
value: 1,
|
||||
'ng-model' => 'exchange.select_all_variants',
|
||||
'ng-change' => 'setExchangeVariants(exchange, suppliedVariants(exchange.enterprise_id), exchange.select_all_variants)',
|
||||
'id' => 'order_cycle_incoming_exchange_{{ $index }}_select_all_variants' }
|
||||
{{ 'admin.select_all' | t }}
|
||||
|
||||
%div{ 'ng-include' => "'admin/panels/exchange_products_supplied_list.html'" }
|
||||
@@ -0,0 +1,16 @@
|
||||
.row.exchange-supplied-products{'ng-init' => 'initializeExchangeProductsPanel(exchange)'}
|
||||
.sixteen.columns.alpha.omega{ 'ng-show' => 'enterprises[exchange.enterprise_id].supplied_products.length != 0' }
|
||||
%div{ 'ng-include' => "'admin/panels/exchange_products_panel_header.html'" }
|
||||
|
||||
.exchange-select-all-variants
|
||||
%label
|
||||
%input{ type: 'checkbox', name: 'order_cycle_incoming_exchange_{{ $index }}_select_all_variants',
|
||||
value: 1,
|
||||
'ng-model' => 'exchange.select_all_variants',
|
||||
'ng-change' => 'selectAllVariants(exchange, exchange.select_all_variants)',
|
||||
'id' => 'order_cycle_incoming_exchange_{{ $index }}_select_all_variants' }
|
||||
{{ 'js.admin.panels.exchange_products.select_all_products' | t:{ total_number_of_products: enterprises[exchange.enterprise_id].num_of_products } }}
|
||||
|
||||
%div{ 'ng-include' => "'admin/panels/exchange_products_supplied_list.html'" }
|
||||
|
||||
%div{ 'ng-include' => "'admin/panels/exchange_products_panel_footer.html'" }
|
||||
@@ -0,0 +1,16 @@
|
||||
.exchange-products{ 'ng-hide' => 'productsLoading()' }
|
||||
.exchange-product{'ng-repeat' => 'product in enterprises[exchange.enterprise_id].supplied_products'}
|
||||
.exchange-product-details
|
||||
%label
|
||||
%img{'ng-src' => '{{ product.image_url }}'}
|
||||
{{ product.name }}
|
||||
|
||||
.exchange-product-variant{'ng-repeat' => 'variant in product.variants'}
|
||||
%label
|
||||
%input{ type: 'checkbox', name: 'order_cycle_incoming_exchange_{{ $parent.$parent.$index }}_variants_{{ variant.id }}',
|
||||
value: 1,
|
||||
'ng-model' => 'exchange.variants[variant.id]',
|
||||
'ofn-sync-distributions' => '{{ variant.id }}',
|
||||
'id' => 'order_cycle_incoming_exchange_{{ $parent.$parent.$index }}_variants_{{ variant.id }}',
|
||||
'ng-disabled' => '!order_cycle.editable_variants_for_incoming_exchanges.hasOwnProperty(exchange.enterprise_id) || order_cycle.editable_variants_for_incoming_exchanges[exchange.enterprise_id].indexOf(variant.id) < 0' }
|
||||
{{ variant.label }}
|
||||
@@ -1,29 +0,0 @@
|
||||
.row.exchange-supplied-products
|
||||
.sixteen.columns.alpha.omega
|
||||
.exchange-select-all-variants
|
||||
%label
|
||||
%input{ type: 'checkbox', name: 'order_cycle_incoming_exchange_{{ $index }}_select_all_variants',
|
||||
value: 1,
|
||||
'ng-model' => 'exchange.select_all_variants',
|
||||
'ng-change' => 'setExchangeVariants(exchange, suppliedVariants(exchange.enterprise_id), exchange.select_all_variants)',
|
||||
'id' => 'order_cycle_incoming_exchange_{{ $index }}_select_all_variants' }
|
||||
{{ 'admin.select_all' | t }}
|
||||
|
||||
.exchange-products
|
||||
-# No need to scope product list based on permissions, because if an incoming exchange is visible,
|
||||
-# then all of the variants within it should be visible. May change in the future?
|
||||
.exchange-product{'ng-repeat' => 'product in enterprises[exchange.enterprise_id].supplied_products'}
|
||||
.exchange-product-details
|
||||
%label
|
||||
%img{'ng-src' => '{{ product.image_url }}'}
|
||||
{{ product.name }}
|
||||
|
||||
.exchange-product-variant{'ng-repeat' => 'variant in product.variants'}
|
||||
%label
|
||||
%input{ type: 'checkbox', name: 'order_cycle_incoming_exchange_{{ $parent.$parent.$index }}_variants_{{ variant.id }}',
|
||||
value: 1,
|
||||
'ng-model' => 'exchange.variants[variant.id]',
|
||||
'ofn-sync-distributions' => '{{ variant.id }}',
|
||||
'id' => 'order_cycle_incoming_exchange_{{ $parent.$parent.$index }}_variants_{{ variant.id }}',
|
||||
'ng-disabled' => '!order_cycle.editable_variants_for_incoming_exchanges.hasOwnProperty(exchange.enterprise_id) || order_cycle.editable_variants_for_incoming_exchanges[exchange.enterprise_id].indexOf(variant.id) < 0' }
|
||||
{{ variant.label }}
|
||||
@@ -1,9 +1,9 @@
|
||||
#save-bar.animate-show{ ng: { show: 'dirty || persist || StatusMessage.active()' } }
|
||||
.container
|
||||
.eight.columns.alpha
|
||||
.seven.columns.alpha
|
||||
%h5#status-message{ ng: { show: "StatusMessage.invalidMessage == ''", style: 'StatusMessage.statusMessage.style' } }
|
||||
{{ StatusMessage.statusMessage.text || " " }}
|
||||
%h5#status-message{ ng: { show: "StatusMessage.invalidMessage !== ''" }, style: 'color: #da5354' }
|
||||
{{ StatusMessage.invalidMessage || " " }}
|
||||
.eight.columns.omega.text-right{ ng: { transclude: true } }
|
||||
.nine.columns.omega.text-right{ ng: { transclude: true } }
|
||||
|
||||
|
||||
@@ -0,0 +1,32 @@
|
||||
@import '../variables';
|
||||
|
||||
.row-loading {
|
||||
opacity: .5;
|
||||
}
|
||||
|
||||
.row-loading-icons {
|
||||
margin-left: 3em;
|
||||
position: absolute;
|
||||
|
||||
.spinner {
|
||||
border: 0;
|
||||
width: 2.3em;
|
||||
}
|
||||
|
||||
i {
|
||||
font-size: 2.3em;
|
||||
opacity: .75;
|
||||
|
||||
&::before {
|
||||
vertical-align: top;
|
||||
}
|
||||
|
||||
&.success {
|
||||
color: $spree-green;
|
||||
}
|
||||
|
||||
&.error {
|
||||
color: $warning-red;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -104,9 +104,13 @@ form.order_cycle {
|
||||
width: 20px;
|
||||
}
|
||||
|
||||
.exchange-load-all-variants {
|
||||
margin: 0px 5px 20px 5px;
|
||||
}
|
||||
|
||||
.exchange-select-all-variants {
|
||||
clear: both;
|
||||
margin: 5px;
|
||||
margin: 15px 5px 25px 5px;
|
||||
}
|
||||
|
||||
.exchange-products {
|
||||
@@ -209,6 +213,7 @@ table#listing_enterprise_groups {
|
||||
#loading {
|
||||
text-align: center;
|
||||
img.spinner {
|
||||
border: 0px;
|
||||
width: 100px;
|
||||
height: 100px;
|
||||
}
|
||||
|
||||
@@ -28,15 +28,12 @@ module Admin
|
||||
|
||||
def bulk_update
|
||||
@enterprise_fee_set = EnterpriseFeeSet.new(params[:enterprise_fee_set])
|
||||
if @enterprise_fee_set.save
|
||||
redirect_path = main_app.admin_enterprise_fees_path
|
||||
if params.key? :enterprise_id
|
||||
redirect_path = main_app.admin_enterprise_fees_path(enterprise_id: params[:enterprise_id])
|
||||
end
|
||||
redirect_to redirect_path, notice: I18n.t(:enterprise_fees_update_notice)
|
||||
|
||||
if @enterprise_fee_set.save
|
||||
redirect_to redirect_path, notice: I18n.t(:enterprise_fees_update_notice)
|
||||
else
|
||||
render :index
|
||||
redirect_to redirect_path,
|
||||
flash: { error: @enterprise_fee_set.errors.full_messages.to_sentence }
|
||||
end
|
||||
end
|
||||
|
||||
@@ -73,5 +70,13 @@ module Admin
|
||||
def current_enterprise
|
||||
Enterprise.find params[:enterprise_id] if params.key? :enterprise_id
|
||||
end
|
||||
|
||||
def redirect_path
|
||||
if params.key? :enterprise_id
|
||||
return main_app.admin_enterprise_fees_path(enterprise_id: params[:enterprise_id])
|
||||
end
|
||||
|
||||
main_app.admin_enterprise_fees_path
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
@@ -66,7 +66,7 @@ module Admin
|
||||
|
||||
if @enterprise.update_attributes(attributes)
|
||||
flash[:success] = I18n.t(:enterprise_register_success_notice, enterprise: @enterprise.name)
|
||||
redirect_to admin_path
|
||||
redirect_to admin_dashboard_path
|
||||
else
|
||||
flash[:error] = I18n.t(:enterprise_register_error, enterprise: @enterprise.name)
|
||||
render :welcome, layout: "spree/layouts/bare_admin"
|
||||
|
||||
@@ -22,7 +22,7 @@ module Admin
|
||||
redirect_to main_app.edit_admin_enterprise_path(stripe_account.enterprise)
|
||||
rescue ActiveRecord::RecordNotFound
|
||||
flash[:error] = "Failed to disconnect Stripe."
|
||||
redirect_to spree.admin_path
|
||||
redirect_to spree.admin_dashboard_path
|
||||
end
|
||||
|
||||
def status
|
||||
|
||||
92
app/controllers/api/exchange_products_controller.rb
Normal file
92
app/controllers/api/exchange_products_controller.rb
Normal file
@@ -0,0 +1,92 @@
|
||||
# This controller lists products that can be added to an exchange
|
||||
module Api
|
||||
class ExchangeProductsController < Api::BaseController
|
||||
DEFAULT_PAGE = 1
|
||||
DEFAULT_PER_PAGE = 100
|
||||
|
||||
skip_authorization_check only: [:index]
|
||||
|
||||
# If exchange_id is present in the URL:
|
||||
# Lists Products that can be added to that Exchange
|
||||
#
|
||||
# If exchange_id is not present in the URL:
|
||||
# Lists Products of the Enterprise given that can be added to the given Order Cycle
|
||||
# In this case parameters are: enterprise_id, order_cycle_id and incoming
|
||||
# (order_cycle_id is not necessary for incoming exchanges)
|
||||
def index
|
||||
if params[:exchange_id].present?
|
||||
load_data_from_exchange
|
||||
else
|
||||
load_data_from_other_params
|
||||
end
|
||||
|
||||
render_variant_count && return if params[:action_name] == "variant_count"
|
||||
|
||||
render_paginated_products paginated_products
|
||||
end
|
||||
|
||||
private
|
||||
|
||||
def render_variant_count
|
||||
render text: {
|
||||
count: Spree::Variant.
|
||||
not_master.
|
||||
where(product_id: products).
|
||||
count
|
||||
}.to_json
|
||||
end
|
||||
|
||||
def products
|
||||
ExchangeProductsRenderer.
|
||||
new(@order_cycle, spree_current_user).
|
||||
exchange_products(@incoming, @enterprise)
|
||||
end
|
||||
|
||||
def paginated_products
|
||||
products.
|
||||
page(params[:page] || DEFAULT_PAGE).
|
||||
per(params[:per_page] || DEFAULT_PER_PAGE)
|
||||
end
|
||||
|
||||
def load_data_from_exchange
|
||||
exchange = Exchange.find_by_id(params[:exchange_id])
|
||||
|
||||
@order_cycle = exchange.order_cycle
|
||||
@incoming = exchange.incoming
|
||||
@enterprise = exchange.sender
|
||||
end
|
||||
|
||||
def load_data_from_other_params
|
||||
@enterprise = Enterprise.find_by_id(params[:enterprise_id])
|
||||
|
||||
if params[:order_cycle_id]
|
||||
@order_cycle = OrderCycle.find_by_id(params[:order_cycle_id])
|
||||
elsif !params[:incoming]
|
||||
raise "order_cycle_id is required to list products for new outgoing exchange"
|
||||
end
|
||||
@incoming = params[:incoming]
|
||||
end
|
||||
|
||||
def render_paginated_products(paginated_products)
|
||||
serializer = ActiveModel::ArraySerializer.new(
|
||||
paginated_products,
|
||||
each_serializer: Api::Admin::ForOrderCycle::SuppliedProductSerializer,
|
||||
order_cycle: @order_cycle
|
||||
)
|
||||
|
||||
render text: {
|
||||
products: serializer,
|
||||
pagination: pagination_data(paginated_products)
|
||||
}.to_json
|
||||
end
|
||||
|
||||
def pagination_data(paginated_products)
|
||||
{
|
||||
results: paginated_products.total_count,
|
||||
pages: paginated_products.num_pages,
|
||||
page: (params[:page] || DEFAULT_PAGE).to_i,
|
||||
per_page: (params[:per_page] || DEFAULT_PER_PAGE).to_i
|
||||
}
|
||||
end
|
||||
end
|
||||
end
|
||||
@@ -16,8 +16,38 @@ module Api
|
||||
}
|
||||
end
|
||||
|
||||
def ship
|
||||
authorize! :admin, order
|
||||
|
||||
if order.ship
|
||||
render json: order.reload, serializer: Api::Admin::OrderSerializer, status: :ok
|
||||
else
|
||||
render json: { error: I18n.t('api.orders.failed_to_update') }, status: :unprocessable_entity
|
||||
end
|
||||
end
|
||||
|
||||
def capture
|
||||
authorize! :admin, order
|
||||
|
||||
pending_payment = order.pending_payments.first
|
||||
|
||||
return payment_capture_failed unless order.payment_required? && pending_payment
|
||||
|
||||
if pending_payment.capture!
|
||||
render json: order.reload, serializer: Api::Admin::OrderSerializer, status: :ok
|
||||
else
|
||||
payment_capture_failed
|
||||
end
|
||||
rescue Spree::Core::GatewayError => e
|
||||
error_during_processing(e)
|
||||
end
|
||||
|
||||
private
|
||||
|
||||
def payment_capture_failed
|
||||
render json: { error: t(:payment_processing_failed) }, status: :unprocessable_entity
|
||||
end
|
||||
|
||||
def serialized_orders(orders)
|
||||
ActiveModel::ArraySerializer.new(
|
||||
orders,
|
||||
|
||||
@@ -42,8 +42,8 @@ module Api
|
||||
def destroy
|
||||
authorize! :delete, Spree::Product
|
||||
@product = find_product(params[:id])
|
||||
@product.update_attribute(:deleted_at, Time.zone.now)
|
||||
@product.variants_including_master.update_all(deleted_at: Time.zone.now)
|
||||
authorize! :delete, @product
|
||||
@product.destroy
|
||||
render json: @product, serializer: Api::Admin::ProductSerializer, status: :no_content
|
||||
end
|
||||
|
||||
@@ -71,14 +71,6 @@ module Api
|
||||
render_paged_products @products
|
||||
end
|
||||
|
||||
def soft_delete
|
||||
authorize! :delete, Spree::Product
|
||||
@product = find_product(params[:product_id])
|
||||
authorize! :delete, @product
|
||||
@product.destroy
|
||||
render json: @product, serializer: Api::Admin::ProductSerializer, status: :no_content
|
||||
end
|
||||
|
||||
# POST /api/products/:product_id/clone
|
||||
#
|
||||
def clone
|
||||
|
||||
@@ -35,18 +35,12 @@ module Api
|
||||
end
|
||||
end
|
||||
|
||||
def soft_delete
|
||||
@variant = scope.find(params[:variant_id])
|
||||
authorize! :delete, @variant
|
||||
|
||||
VariantDeleter.new.delete(@variant)
|
||||
render json: @variant, serializer: Api::VariantSerializer, status: :no_content
|
||||
end
|
||||
|
||||
def destroy
|
||||
authorize! :delete, Spree::Variant
|
||||
@variant = scope.find(params[:id])
|
||||
@variant.destroy
|
||||
authorize! :delete, @variant
|
||||
|
||||
VariantDeleter.new.delete(@variant)
|
||||
render json: @variant, serializer: Api::VariantSerializer, status: :no_content
|
||||
end
|
||||
|
||||
|
||||
@@ -1,12 +1,23 @@
|
||||
module Spree
|
||||
module Admin
|
||||
AdjustmentsController.class_eval do
|
||||
class AdjustmentsController < ResourceController
|
||||
belongs_to 'spree/order', find_by: :number
|
||||
destroy.after :reload_order
|
||||
|
||||
prepend_before_filter :set_included_tax, only: [:create, :update]
|
||||
before_filter :set_default_tax_rate, only: :edit
|
||||
before_filter :enable_updates, only: :update
|
||||
|
||||
private
|
||||
|
||||
def reload_order
|
||||
@order.reload
|
||||
end
|
||||
|
||||
def collection
|
||||
parent.adjustments.eligible
|
||||
end
|
||||
|
||||
# Choose a default tax rate to show on the edit form. The adjustment stores its included
|
||||
# tax in dollars, but doesn't store the source of the tax (ie. TaxRate that generated it).
|
||||
# We guess which tax rate here, choosing:
|
||||
@@ -15,28 +26,34 @@ module Spree
|
||||
# When we have to go with 2, we show an error message to ask the admin to check that the
|
||||
# correct tax is being applied.
|
||||
def set_default_tax_rate
|
||||
if @adjustment.included_tax > 0
|
||||
trs = TaxRate.match(@order)
|
||||
tr_yielding_matching_tax = trs.select { |tr| tr.compute_tax(@adjustment.amount) == @adjustment.included_tax }.first.andand.id
|
||||
tr_valid_for_order = TaxRate.match(@order).first.andand.id
|
||||
return if @adjustment.included_tax <= 0
|
||||
|
||||
@tax_rate_id = tr_yielding_matching_tax || tr_valid_for_order
|
||||
tax_rates = TaxRate.match(@order)
|
||||
tax_rate_with_matching_tax = find_tax_rate_with_matching_tax(tax_rates)
|
||||
tax_rate_valid_for_order = tax_rates.first.andand.id
|
||||
|
||||
if tr_yielding_matching_tax.nil?
|
||||
@adjustment.errors.add :tax_rate_id, I18n.t(:adjustments_tax_rate_error)
|
||||
end
|
||||
@tax_rate_id = tax_rate_with_matching_tax || tax_rate_valid_for_order
|
||||
|
||||
return unless tax_rate_with_matching_tax.nil?
|
||||
|
||||
@adjustment.errors.add :tax_rate_id, I18n.t(:adjustments_tax_rate_error)
|
||||
end
|
||||
|
||||
def find_tax_rate_with_matching_tax(tax_rates)
|
||||
tax_rates_yielding_matching_tax = tax_rates.select do |tr|
|
||||
tr.compute_tax(@adjustment.amount) == @adjustment.included_tax
|
||||
end
|
||||
tax_rates_yielding_matching_tax.first.andand.id
|
||||
end
|
||||
|
||||
def set_included_tax
|
||||
included_tax = 0
|
||||
if params[:tax_rate_id].present?
|
||||
tax_rate = TaxRate.find params[:tax_rate_id]
|
||||
amount = params[:adjustment][:amount].to_f
|
||||
params[:adjustment][:included_tax] = tax_rate.compute_tax amount
|
||||
|
||||
else
|
||||
params[:adjustment][:included_tax] = 0
|
||||
included_tax = tax_rate.compute_tax amount
|
||||
end
|
||||
params[:adjustment][:included_tax] = included_tax
|
||||
end
|
||||
|
||||
# Spree 2.0 keeps shipping fee adjustments open unless they are manually
|
||||
142
app/controllers/spree/admin/base_controller.rb
Normal file
142
app/controllers/spree/admin/base_controller.rb
Normal file
@@ -0,0 +1,142 @@
|
||||
module Spree
|
||||
module Admin
|
||||
class BaseController < Spree::BaseController
|
||||
ssl_required
|
||||
|
||||
helper 'spree/admin/navigation'
|
||||
layout '/spree/layouts/admin'
|
||||
|
||||
include I18nHelper
|
||||
|
||||
before_filter :authorize_admin
|
||||
before_filter :set_locale
|
||||
before_filter :warn_invalid_order_cycles, if: :html_request?
|
||||
|
||||
# Warn the user when they have an active order cycle with hubs that are not ready
|
||||
# for checkout (ie. does not have valid shipping and payment methods).
|
||||
def warn_invalid_order_cycles
|
||||
distributors = active_distributors_not_ready_for_checkout
|
||||
|
||||
return if distributors.empty? || flash[:notice].present?
|
||||
|
||||
flash[:notice] = active_distributors_not_ready_for_checkout_message(distributors)
|
||||
end
|
||||
|
||||
# This is in Spree::Core::ControllerHelpers::Auth
|
||||
# But you can't easily reopen modules in Ruby
|
||||
def unauthorized
|
||||
if try_spree_current_user
|
||||
flash[:error] = t(:authorization_failure)
|
||||
redirect_to '/unauthorized'
|
||||
else
|
||||
store_location
|
||||
redirect_to root_path(anchor: "login?after_login=#{request.env['PATH_INFO']}")
|
||||
end
|
||||
end
|
||||
|
||||
protected
|
||||
|
||||
def model_class
|
||||
const_name = controller_name.classify
|
||||
return "Spree::#{const_name}".constantize if Spree.const_defined?(const_name)
|
||||
|
||||
nil
|
||||
end
|
||||
|
||||
def action
|
||||
params[:action].to_sym
|
||||
end
|
||||
|
||||
def authorize_admin
|
||||
if respond_to?(:model_class, true) && model_class
|
||||
record = model_class
|
||||
else
|
||||
# This allows specificity for each non-resource controller
|
||||
# (to be consistent with "authorize_resource :class => false", see https://github.com/ryanb/cancan/blob/60cf6a67ef59c0c9b63bc27ea0101125c4193ea6/lib/cancan/controller_resource.rb#L146)
|
||||
record = self.class.to_s.
|
||||
sub("Controller", "").
|
||||
underscore.split('/').last.singularize.to_sym
|
||||
end
|
||||
authorize! :admin, record
|
||||
authorize! resource_authorize_action, record
|
||||
end
|
||||
|
||||
def resource_authorize_action
|
||||
action
|
||||
end
|
||||
|
||||
def flash_message_for(object, event_sym)
|
||||
resource_desc = object.class.model_name.human
|
||||
resource_desc += " \"#{object.name}\"" if object.respond_to?(:name) && object.name.present?
|
||||
Spree.t(event_sym, resource: resource_desc)
|
||||
end
|
||||
|
||||
def render_js_for_destroy
|
||||
render partial: '/spree/admin/shared/destroy'
|
||||
end
|
||||
|
||||
# Index request for JSON needs to pass a CSRF token in order to prevent JSON Hijacking
|
||||
def check_json_authenticity
|
||||
return unless request.format.js? || request.format.json?
|
||||
|
||||
return unless protect_against_forgery?
|
||||
|
||||
auth_token = params[request_forgery_protection_token]
|
||||
return if auth_token && form_authenticity_token == CGI.unescape(auth_token)
|
||||
|
||||
raise(ActionController::InvalidAuthenticityToken)
|
||||
end
|
||||
|
||||
def config_locale
|
||||
Spree::Backend::Config[:locale]
|
||||
end
|
||||
|
||||
private
|
||||
|
||||
def active_distributors_not_ready_for_checkout
|
||||
ocs = OrderCycle.managed_by(spree_current_user).active
|
||||
distributors = ocs.includes(:distributors).map(&:distributors).flatten.uniq
|
||||
Enterprise.where('enterprises.id IN (?)', distributors).not_ready_for_checkout
|
||||
end
|
||||
|
||||
def active_distributors_not_ready_for_checkout_message(distributors)
|
||||
distributor_names = distributors.map(&:name).join ', '
|
||||
|
||||
if distributors.count > 1
|
||||
I18n.t(:active_distributors_not_ready_for_checkout_message_plural,
|
||||
distributor_names: distributor_names)
|
||||
else
|
||||
I18n.t(:active_distributors_not_ready_for_checkout_message_singular,
|
||||
distributor_names: distributor_names)
|
||||
end
|
||||
end
|
||||
|
||||
def html_request?
|
||||
request.format.html?
|
||||
end
|
||||
|
||||
def json_request?
|
||||
request.format.json?
|
||||
end
|
||||
|
||||
def render_as_json(data, options = {})
|
||||
ams_prefix = options.delete :ams_prefix
|
||||
if [Array, ActiveRecord::Relation].include? data.class
|
||||
render options.merge(json: data, each_serializer: serializer(ams_prefix))
|
||||
else
|
||||
render options.merge(json: data, serializer: serializer(ams_prefix))
|
||||
end
|
||||
end
|
||||
|
||||
def serializer(ams_prefix)
|
||||
unless ams_prefix.nil? || ams_prefix_whitelist.include?(ams_prefix.to_sym)
|
||||
raise "Suffix '#{ams_prefix}' not found in ams_prefix_whitelist for #{self.class.name}."
|
||||
end
|
||||
|
||||
prefix = ams_prefix.andand.classify || ""
|
||||
name = controller_name.classify
|
||||
"::Api::Admin::#{prefix}#{name}Serializer".constantize
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
@@ -1,105 +0,0 @@
|
||||
require 'spree/core/controller_helpers/respond_with_decorator'
|
||||
|
||||
Spree::Admin::BaseController.class_eval do
|
||||
include I18nHelper
|
||||
|
||||
layout 'spree/layouts/admin'
|
||||
|
||||
before_filter :set_locale
|
||||
before_filter :warn_invalid_order_cycles, if: :html_request?
|
||||
|
||||
# Warn the user when they have an active order cycle with hubs that are not ready
|
||||
# for checkout (ie. does not have valid shipping and payment methods).
|
||||
def warn_invalid_order_cycles
|
||||
distributors = active_distributors_not_ready_for_checkout
|
||||
|
||||
if distributors.any? && flash[:notice].nil?
|
||||
flash[:notice] = active_distributors_not_ready_for_checkout_message(distributors)
|
||||
end
|
||||
end
|
||||
|
||||
# Override Spree method
|
||||
# It's a shame Spree doesn't just let CanCan handle this in it's own way
|
||||
def authorize_admin
|
||||
if respond_to?(:model_class, true) && model_class
|
||||
record = model_class
|
||||
else
|
||||
# this line changed to allow specificity for each non-resource controller (to be consistent with "authorize_resource :class => false", see https://github.com/ryanb/cancan/blob/60cf6a67ef59c0c9b63bc27ea0101125c4193ea6/lib/cancan/controller_resource.rb#L146)
|
||||
record = self.class.to_s.sub("Controller", "").underscore.split('/').last.singularize.to_sym
|
||||
end
|
||||
authorize! :admin, record
|
||||
authorize! resource_authorize_action, record
|
||||
end
|
||||
|
||||
def resource_authorize_action
|
||||
action
|
||||
end
|
||||
|
||||
# This is in Spree::Core::ControllerHelpers::Auth
|
||||
# But you can't easily reopen modules in Ruby
|
||||
def unauthorized
|
||||
if try_spree_current_user
|
||||
flash[:error] = t(:authorization_failure)
|
||||
redirect_to '/unauthorized'
|
||||
else
|
||||
store_location
|
||||
redirect_to root_path(anchor: "login?after_login=#{request.env['PATH_INFO']}")
|
||||
end
|
||||
end
|
||||
|
||||
protected
|
||||
|
||||
def model_class
|
||||
const_name = controller_name.classify
|
||||
if Spree.const_defined?(const_name)
|
||||
return "Spree::#{const_name}".constantize
|
||||
end
|
||||
|
||||
nil
|
||||
end
|
||||
|
||||
private
|
||||
|
||||
def active_distributors_not_ready_for_checkout
|
||||
ocs = OrderCycle.managed_by(spree_current_user).active
|
||||
distributors = ocs.includes(:distributors).map(&:distributors).flatten.uniq
|
||||
Enterprise.where('enterprises.id IN (?)', distributors).not_ready_for_checkout
|
||||
end
|
||||
|
||||
def active_distributors_not_ready_for_checkout_message(distributors)
|
||||
distributor_names = distributors.map(&:name).join ', '
|
||||
|
||||
if distributors.count > 1
|
||||
I18n.t(:active_distributors_not_ready_for_checkout_message_plural, distributor_names: distributor_names)
|
||||
else
|
||||
I18n.t(:active_distributors_not_ready_for_checkout_message_singular, distributor_names: distributor_names)
|
||||
end
|
||||
end
|
||||
|
||||
def html_request?
|
||||
request.format.html?
|
||||
end
|
||||
|
||||
def json_request?
|
||||
request.format.json?
|
||||
end
|
||||
|
||||
def render_as_json(data, options = {})
|
||||
ams_prefix = options.delete :ams_prefix
|
||||
if [Array, ActiveRecord::Relation].include? data.class
|
||||
render options.merge(json: data, each_serializer: serializer(ams_prefix))
|
||||
else
|
||||
render options.merge(json: data, serializer: serializer(ams_prefix))
|
||||
end
|
||||
end
|
||||
|
||||
def serializer(ams_prefix)
|
||||
if ams_prefix.nil? || ams_prefix_whitelist.include?(ams_prefix.to_sym)
|
||||
prefix = ams_prefix.andand.classify || ""
|
||||
name = controller_name.classify
|
||||
"Api::Admin::#{prefix}#{name}Serializer".constantize
|
||||
else
|
||||
raise "Suffix '#{ams_prefix}' not found in ams_prefix_whitelist for #{self.class.name}."
|
||||
end
|
||||
end
|
||||
end
|
||||
@@ -5,8 +5,7 @@ module Spree
|
||||
@preferences_general = [:site_name, :default_seo_title, :default_meta_keywords,
|
||||
:default_meta_description, :site_url, :bugherd_api_key]
|
||||
@preferences_security = [:allow_ssl_in_production,
|
||||
:allow_ssl_in_staging, :allow_ssl_in_development_and_test,
|
||||
:check_for_spree_alerts]
|
||||
:allow_ssl_in_staging, :allow_ssl_in_development_and_test]
|
||||
@preferences_currency = [:display_currency, :hide_cents]
|
||||
end
|
||||
|
||||
@@ -20,18 +19,6 @@ module Spree
|
||||
|
||||
redirect_to edit_admin_general_settings_path
|
||||
end
|
||||
|
||||
def dismiss_alert
|
||||
return unless request.xhr? && params[:alert_id]
|
||||
|
||||
dismissed = Spree::Config[:dismissed_spree_alerts] || ''
|
||||
Spree::Config.set(dismissed_spree_alerts: dismissed.
|
||||
split(',').
|
||||
push(params[:alert_id]).
|
||||
join(','))
|
||||
filter_dismissed_alerts
|
||||
render nothing: true
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
317
app/controllers/spree/admin/reports_controller.rb
Normal file
317
app/controllers/spree/admin/reports_controller.rb
Normal file
@@ -0,0 +1,317 @@
|
||||
require 'csv'
|
||||
|
||||
require 'open_food_network/reports/list'
|
||||
require 'open_food_network/order_and_distributor_report'
|
||||
require 'open_food_network/products_and_inventory_report'
|
||||
require 'open_food_network/lettuce_share_report'
|
||||
require 'open_food_network/group_buy_report'
|
||||
require 'open_food_network/order_grouper'
|
||||
require 'open_food_network/customers_report'
|
||||
require 'open_food_network/users_and_enterprises_report'
|
||||
require 'open_food_network/order_cycle_management_report'
|
||||
require 'open_food_network/packing_report'
|
||||
require 'open_food_network/sales_tax_report'
|
||||
require 'open_food_network/xero_invoices_report'
|
||||
require 'open_food_network/bulk_coop_report'
|
||||
require 'open_food_network/payments_report'
|
||||
require 'open_food_network/orders_and_fulfillments_report'
|
||||
|
||||
module Spree
|
||||
module Admin
|
||||
class ReportsController < Spree::Admin::BaseController
|
||||
include Spree::ReportsHelper
|
||||
|
||||
helper_method :render_content?
|
||||
|
||||
before_filter :cache_search_state
|
||||
# Fetches user's distributors, suppliers and order_cycles
|
||||
before_filter :load_data,
|
||||
only: [:customers, :products_and_inventory, :order_cycle_management, :packing]
|
||||
|
||||
respond_to :html
|
||||
|
||||
def report_types
|
||||
OpenFoodNetwork::Reports::List.all
|
||||
end
|
||||
|
||||
def index
|
||||
@reports = authorized_reports
|
||||
respond_with(@reports)
|
||||
end
|
||||
|
||||
def customers
|
||||
@report_types = report_types[:customers]
|
||||
@report_type = params[:report_type]
|
||||
@report = OpenFoodNetwork::CustomersReport.new spree_current_user, params, render_content?
|
||||
render_report(@report.header, @report.table, params[:csv], "customers_#{timestamp}.csv")
|
||||
end
|
||||
|
||||
def order_cycle_management
|
||||
params[:q] ||= {}
|
||||
|
||||
@report_types = report_types[:order_cycle_management]
|
||||
@report_type = params[:report_type]
|
||||
|
||||
# -- Build Report with Order Grouper
|
||||
@report = OpenFoodNetwork::OrderCycleManagementReport.new spree_current_user,
|
||||
params,
|
||||
render_content?
|
||||
@table = @report.table_items
|
||||
|
||||
render_report(@report.header, @table, params[:csv],
|
||||
"order_cycle_management_#{timestamp}.csv")
|
||||
end
|
||||
|
||||
def packing
|
||||
params[:q] ||= {}
|
||||
|
||||
@report_types = report_types[:packing]
|
||||
@report_type = params[:report_type]
|
||||
|
||||
# -- Build Report with Order Grouper
|
||||
@report = OpenFoodNetwork::PackingReport.new spree_current_user, params, render_content?
|
||||
@table = order_grouper_table
|
||||
|
||||
render_report(@report.header, @table, params[:csv], "packing_#{timestamp}.csv")
|
||||
end
|
||||
|
||||
def orders_and_distributors
|
||||
@report = OpenFoodNetwork::OrderAndDistributorReport.new spree_current_user,
|
||||
params,
|
||||
render_content?
|
||||
@search = @report.search
|
||||
csv_file_name = "orders_and_distributors_#{timestamp}.csv"
|
||||
render_report(@report.header, @report.table, params[:csv], csv_file_name)
|
||||
end
|
||||
|
||||
def sales_tax
|
||||
@distributors = my_distributors
|
||||
@report_type = params[:report_type]
|
||||
@report = OpenFoodNetwork::SalesTaxReport.new spree_current_user, params, render_content?
|
||||
render_report(@report.header, @report.table, params[:csv], "sales_tax.csv")
|
||||
end
|
||||
|
||||
def bulk_coop
|
||||
# -- Prepare form options
|
||||
@distributors = my_distributors
|
||||
@report_type = params[:report_type]
|
||||
|
||||
# -- Build Report with Order Grouper
|
||||
@report = OpenFoodNetwork::BulkCoopReport.new spree_current_user, params, render_content?
|
||||
@table = order_grouper_table
|
||||
csv_file_name = "bulk_coop_#{params[:report_type]}_#{timestamp}.csv"
|
||||
|
||||
render_report(@report.header, @table, params[:csv], csv_file_name)
|
||||
end
|
||||
|
||||
def payments
|
||||
# -- Prepare Form Options
|
||||
@distributors = my_distributors
|
||||
@report_type = params[:report_type]
|
||||
|
||||
# -- Build Report with Order Grouper
|
||||
@report = OpenFoodNetwork::PaymentsReport.new spree_current_user, params, render_content?
|
||||
@table = order_grouper_table
|
||||
csv_file_name = "payments_#{timestamp}.csv"
|
||||
|
||||
render_report(@report.header, @table, params[:csv], csv_file_name)
|
||||
end
|
||||
|
||||
def orders_and_fulfillment
|
||||
params[:q] ||= orders_and_fulfillment_default_filters
|
||||
|
||||
# -- Prepare Form Options
|
||||
permissions = OpenFoodNetwork::Permissions.new(spree_current_user)
|
||||
# My distributors and any distributors distributing products I supply
|
||||
@distributors = permissions.visible_enterprises_for_order_reports.is_distributor
|
||||
# My suppliers and any suppliers supplying products I distribute
|
||||
@suppliers = permissions.visible_enterprises_for_order_reports.is_primary_producer
|
||||
|
||||
@order_cycles = my_order_cycles
|
||||
|
||||
@report_types = report_types[:orders_and_fulfillment]
|
||||
@report_type = params[:report_type]
|
||||
|
||||
@include_blank = I18n.t(:all)
|
||||
|
||||
# -- Build Report with Order Grouper
|
||||
@report = OpenFoodNetwork::OrdersAndFulfillmentsReport.new spree_current_user,
|
||||
params,
|
||||
render_content?
|
||||
@table = order_grouper_table
|
||||
csv_file_name = "#{params[:report_type]}_#{timestamp}.csv"
|
||||
|
||||
render_report(@report.header, @table, params[:csv], csv_file_name)
|
||||
end
|
||||
|
||||
def products_and_inventory
|
||||
@report_types = report_types[:products_and_inventory]
|
||||
@report = if params[:report_type] != 'lettuce_share'
|
||||
OpenFoodNetwork::ProductsAndInventoryReport.new spree_current_user,
|
||||
params,
|
||||
render_content?
|
||||
else
|
||||
OpenFoodNetwork::LettuceShareReport.new spree_current_user,
|
||||
params,
|
||||
render_content?
|
||||
end
|
||||
|
||||
render_report @report.header,
|
||||
@report.table,
|
||||
params[:csv],
|
||||
"products_and_inventory_#{timestamp}.csv"
|
||||
end
|
||||
|
||||
def users_and_enterprises
|
||||
@report = OpenFoodNetwork::UsersAndEnterprisesReport.new params, render_content?
|
||||
render_report(@report.header, @report.table, params[:csv],
|
||||
"users_and_enterprises_#{timestamp}.csv")
|
||||
end
|
||||
|
||||
def xero_invoices
|
||||
params[:q] ||= {}
|
||||
|
||||
@distributors = my_distributors
|
||||
@order_cycles = my_order_cycles
|
||||
|
||||
@report = OpenFoodNetwork::XeroInvoicesReport.new(spree_current_user,
|
||||
params,
|
||||
render_content?)
|
||||
render_report(@report.header, @report.table, params[:csv], "xero_invoices_#{timestamp}.csv")
|
||||
end
|
||||
|
||||
private
|
||||
|
||||
def model_class
|
||||
Spree::Admin::ReportsController
|
||||
end
|
||||
|
||||
# Some actions are changing the `params` object. That is unfortunate Spree
|
||||
# behavior and we are building on it. So we have to look at `params` early
|
||||
# to check if we are searching or just displaying a report search form.
|
||||
def cache_search_state
|
||||
search_keys = [
|
||||
# search parameter for ransack
|
||||
:q,
|
||||
# common in all reports, only set for CSV rendering
|
||||
:csv,
|
||||
# `button` is included in all forms. It's not important for searching,
|
||||
# but the Users & Enterprises report doesn't have any other parameter
|
||||
# for an empty search. So we use this one to display data.
|
||||
:button,
|
||||
# Some reports use filtering by enterprise or order cycle
|
||||
:distributor_id,
|
||||
:supplier_id,
|
||||
:order_cycle_id,
|
||||
# Xero Invoices can be filtered by date
|
||||
:invoice_date,
|
||||
:due_date
|
||||
]
|
||||
@searching = search_keys.any? { |key| params.key? key }
|
||||
end
|
||||
|
||||
# We don't want to render data unless search params are supplied.
|
||||
# Compiling data can take a long time.
|
||||
def render_content?
|
||||
@searching
|
||||
end
|
||||
|
||||
def render_report(header, table, create_csv, csv_file_name)
|
||||
send_data csv_report(header, table), filename: csv_file_name if create_csv
|
||||
@header = header
|
||||
@table = table
|
||||
# Rendering HTML is the default.
|
||||
end
|
||||
|
||||
def csv_report(header, table)
|
||||
CSV.generate do |csv|
|
||||
csv << header
|
||||
table.each { |row| csv << row }
|
||||
end
|
||||
end
|
||||
|
||||
def load_data
|
||||
@distributors = my_distributors
|
||||
@suppliers = my_suppliers | suppliers_of_products_distributed_by(@distributors)
|
||||
@order_cycles = my_order_cycles
|
||||
end
|
||||
|
||||
# Load managed distributor enterprises of current user
|
||||
def my_distributors
|
||||
Enterprise.is_distributor.managed_by(spree_current_user)
|
||||
end
|
||||
|
||||
# Load managed producer enterprises of current user
|
||||
def my_suppliers
|
||||
Enterprise.is_primary_producer.managed_by(spree_current_user)
|
||||
end
|
||||
|
||||
def suppliers_of_products_distributed_by(distributors)
|
||||
distributors.map { |d| Spree::Product.in_distributor(d).includes(:supplier).all }.
|
||||
flatten.map(&:supplier).uniq
|
||||
end
|
||||
|
||||
# Load order cycles the current user has access to
|
||||
def my_order_cycles
|
||||
OrderCycle.
|
||||
active_or_complete.
|
||||
accessible_by(spree_current_user).
|
||||
order('orders_close_at DESC')
|
||||
end
|
||||
|
||||
def order_grouper_table
|
||||
order_grouper = OpenFoodNetwork::OrderGrouper.new @report.rules, @report.columns
|
||||
order_grouper.table(@report.table_items)
|
||||
end
|
||||
|
||||
def authorized_reports
|
||||
all_reports = [
|
||||
:orders_and_distributors,
|
||||
:bulk_coop,
|
||||
:payments,
|
||||
:orders_and_fulfillment,
|
||||
:customers,
|
||||
:products_and_inventory,
|
||||
:users_and_enterprises,
|
||||
:enterprise_fee_summary,
|
||||
:order_cycle_management,
|
||||
:sales_tax,
|
||||
:xero_invoices,
|
||||
:packing
|
||||
]
|
||||
reports = all_reports.select { |action| can? action, Spree::Admin::ReportsController }
|
||||
reports.map { |report| [report, describe_report(report)] }.to_h
|
||||
end
|
||||
|
||||
def describe_report(report)
|
||||
name = I18n.t(:name, scope: [:admin, :reports, report])
|
||||
description = begin
|
||||
I18n.t!(:description, scope: [:admin, :reports, report])
|
||||
rescue I18n::MissingTranslationData
|
||||
render_to_string(
|
||||
partial: "#{report}_description",
|
||||
layout: false,
|
||||
locals: { report_types: report_types[report] }
|
||||
).html_safe
|
||||
end
|
||||
{ name: name, url: url_for_report(report), description: description }
|
||||
end
|
||||
|
||||
def url_for_report(report)
|
||||
public_send("#{report}_admin_reports_url".to_sym)
|
||||
rescue NoMethodError
|
||||
url_for([:new, :admin, :reports, report.to_s.singularize])
|
||||
end
|
||||
|
||||
def timestamp
|
||||
Time.zone.now.strftime("%Y%m%d")
|
||||
end
|
||||
|
||||
def orders_and_fulfillment_default_filters
|
||||
now = Time.zone.now
|
||||
{ completed_at_gt: (now - 1.month).beginning_of_day,
|
||||
completed_at_lt: (now + 1.day).beginning_of_day }
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
@@ -1,302 +0,0 @@
|
||||
require 'csv'
|
||||
|
||||
require 'open_food_network/reports/list'
|
||||
require 'open_food_network/order_and_distributor_report'
|
||||
require 'open_food_network/products_and_inventory_report'
|
||||
require 'open_food_network/lettuce_share_report'
|
||||
require 'open_food_network/group_buy_report'
|
||||
require 'open_food_network/order_grouper'
|
||||
require 'open_food_network/customers_report'
|
||||
require 'open_food_network/users_and_enterprises_report'
|
||||
require 'open_food_network/order_cycle_management_report'
|
||||
require 'open_food_network/packing_report'
|
||||
require 'open_food_network/sales_tax_report'
|
||||
require 'open_food_network/xero_invoices_report'
|
||||
require 'open_food_network/bulk_coop_report'
|
||||
require 'open_food_network/payments_report'
|
||||
require 'open_food_network/orders_and_fulfillments_report'
|
||||
|
||||
Spree::Admin::ReportsController.class_eval do
|
||||
include Spree::ReportsHelper
|
||||
|
||||
helper_method :render_content?
|
||||
|
||||
before_filter :cache_search_state
|
||||
# Fetches user's distributors, suppliers and order_cycles
|
||||
before_filter :load_data,
|
||||
only: [:customers, :products_and_inventory, :order_cycle_management, :packing]
|
||||
|
||||
def report_types
|
||||
OpenFoodNetwork::Reports::List.all
|
||||
end
|
||||
|
||||
# Override spree reports list.
|
||||
def index
|
||||
@reports = authorized_reports
|
||||
respond_with(@reports)
|
||||
end
|
||||
|
||||
def customers
|
||||
@report_types = report_types[:customers]
|
||||
@report_type = params[:report_type]
|
||||
@report = OpenFoodNetwork::CustomersReport.new spree_current_user, params, render_content?
|
||||
render_report(@report.header, @report.table, params[:csv], "customers_#{timestamp}.csv")
|
||||
end
|
||||
|
||||
def order_cycle_management
|
||||
params[:q] ||= {}
|
||||
|
||||
@report_types = report_types[:order_cycle_management]
|
||||
@report_type = params[:report_type]
|
||||
|
||||
# -- Build Report with Order Grouper
|
||||
@report = OpenFoodNetwork::OrderCycleManagementReport.new spree_current_user,
|
||||
params,
|
||||
render_content?
|
||||
@table = @report.table_items
|
||||
|
||||
render_report(@report.header, @table, params[:csv], "order_cycle_management_#{timestamp}.csv")
|
||||
end
|
||||
|
||||
def packing
|
||||
params[:q] ||= {}
|
||||
|
||||
@report_types = report_types[:packing]
|
||||
@report_type = params[:report_type]
|
||||
|
||||
# -- Build Report with Order Grouper
|
||||
@report = OpenFoodNetwork::PackingReport.new spree_current_user, params, render_content?
|
||||
@table = order_grouper_table
|
||||
|
||||
render_report(@report.header, @table, params[:csv], "packing_#{timestamp}.csv")
|
||||
end
|
||||
|
||||
def orders_and_distributors
|
||||
@report = OpenFoodNetwork::OrderAndDistributorReport.new spree_current_user,
|
||||
params,
|
||||
render_content?
|
||||
@search = @report.search
|
||||
csv_file_name = "orders_and_distributors_#{timestamp}.csv"
|
||||
render_report(@report.header, @report.table, params[:csv], csv_file_name)
|
||||
end
|
||||
|
||||
def sales_tax
|
||||
@distributors = my_distributors
|
||||
@report_type = params[:report_type]
|
||||
@report = OpenFoodNetwork::SalesTaxReport.new spree_current_user, params, render_content?
|
||||
render_report(@report.header, @report.table, params[:csv], "sales_tax.csv")
|
||||
end
|
||||
|
||||
def bulk_coop
|
||||
# -- Prepare form options
|
||||
@distributors = my_distributors
|
||||
@report_type = params[:report_type]
|
||||
|
||||
# -- Build Report with Order Grouper
|
||||
@report = OpenFoodNetwork::BulkCoopReport.new spree_current_user, params, render_content?
|
||||
@table = order_grouper_table
|
||||
csv_file_name = "bulk_coop_#{params[:report_type]}_#{timestamp}.csv"
|
||||
|
||||
render_report(@report.header, @table, params[:csv], csv_file_name)
|
||||
end
|
||||
|
||||
def payments
|
||||
# -- Prepare Form Options
|
||||
@distributors = my_distributors
|
||||
@report_type = params[:report_type]
|
||||
|
||||
# -- Build Report with Order Grouper
|
||||
@report = OpenFoodNetwork::PaymentsReport.new spree_current_user, params, render_content?
|
||||
@table = order_grouper_table
|
||||
csv_file_name = "payments_#{timestamp}.csv"
|
||||
|
||||
render_report(@report.header, @table, params[:csv], csv_file_name)
|
||||
end
|
||||
|
||||
def orders_and_fulfillment
|
||||
params[:q] ||= orders_and_fulfillment_default_filters
|
||||
|
||||
# -- Prepare Form Options
|
||||
permissions = OpenFoodNetwork::Permissions.new(spree_current_user)
|
||||
# My distributors and any distributors distributing products I supply
|
||||
@distributors = permissions.visible_enterprises_for_order_reports.is_distributor
|
||||
# My suppliers and any suppliers supplying products I distribute
|
||||
@suppliers = permissions.visible_enterprises_for_order_reports.is_primary_producer
|
||||
|
||||
@order_cycles = my_order_cycles
|
||||
|
||||
@report_types = report_types[:orders_and_fulfillment]
|
||||
@report_type = params[:report_type]
|
||||
|
||||
@include_blank = I18n.t(:all)
|
||||
|
||||
# -- Build Report with Order Grouper
|
||||
@report = OpenFoodNetwork::OrdersAndFulfillmentsReport.new spree_current_user,
|
||||
params,
|
||||
render_content?
|
||||
@table = order_grouper_table
|
||||
csv_file_name = "#{params[:report_type]}_#{timestamp}.csv"
|
||||
|
||||
render_report(@report.header, @table, params[:csv], csv_file_name)
|
||||
end
|
||||
|
||||
def products_and_inventory
|
||||
@report_types = report_types[:products_and_inventory]
|
||||
@report = if params[:report_type] != 'lettuce_share'
|
||||
OpenFoodNetwork::ProductsAndInventoryReport.new spree_current_user,
|
||||
params,
|
||||
render_content?
|
||||
else
|
||||
OpenFoodNetwork::LettuceShareReport.new spree_current_user, params, render_content?
|
||||
end
|
||||
render_report(@report.header,
|
||||
@report.table,
|
||||
params[:csv],
|
||||
"products_and_inventory_#{timestamp}.csv")
|
||||
end
|
||||
|
||||
def users_and_enterprises
|
||||
@report = OpenFoodNetwork::UsersAndEnterprisesReport.new params, render_content?
|
||||
render_report(@report.header,
|
||||
@report.table,
|
||||
params[:csv],
|
||||
"users_and_enterprises_#{timestamp}.csv")
|
||||
end
|
||||
|
||||
def xero_invoices
|
||||
params[:q] ||= {}
|
||||
|
||||
@distributors = my_distributors
|
||||
@order_cycles = my_order_cycles
|
||||
|
||||
@report = OpenFoodNetwork::XeroInvoicesReport.new spree_current_user, params, render_content?
|
||||
render_report(@report.header, @report.table, params[:csv], "xero_invoices_#{timestamp}.csv")
|
||||
end
|
||||
|
||||
private
|
||||
|
||||
# Some actions are changing the `params` object. That is unfortunate Spree
|
||||
# behavior and we are building on it. So we have to look at `params` early
|
||||
# to check if we are searching or just displaying a report search form.
|
||||
def cache_search_state
|
||||
search_keys = [
|
||||
# search parameter for ransack
|
||||
:q,
|
||||
# common in all reports, only set for CSV rendering
|
||||
:csv,
|
||||
# `button` is included in all forms. It's not important for searching,
|
||||
# but the Users & Enterprises report doesn't have any other parameter
|
||||
# for an empty search. So we use this one to display data.
|
||||
:button,
|
||||
# Some reports use filtering by enterprise or order cycle
|
||||
:distributor_id,
|
||||
:supplier_id,
|
||||
:order_cycle_id,
|
||||
# Xero Invoices can be filtered by date
|
||||
:invoice_date,
|
||||
:due_date
|
||||
]
|
||||
@searching = search_keys.any? { |key| params.key? key }
|
||||
end
|
||||
|
||||
# We don't want to render data unless search params are supplied.
|
||||
# Compiling data can take a long time.
|
||||
def render_content?
|
||||
@searching
|
||||
end
|
||||
|
||||
def render_report(header, table, create_csv, csv_file_name)
|
||||
send_data csv_report(header, table), filename: csv_file_name if create_csv
|
||||
@header = header
|
||||
@table = table
|
||||
# Rendering HTML is the default.
|
||||
end
|
||||
|
||||
def csv_report(header, table)
|
||||
CSV.generate do |csv|
|
||||
csv << header
|
||||
table.each { |row| csv << row }
|
||||
end
|
||||
end
|
||||
|
||||
def load_data
|
||||
@distributors = my_distributors
|
||||
@suppliers = my_suppliers | suppliers_of_products_distributed_by(@distributors)
|
||||
@order_cycles = my_order_cycles
|
||||
end
|
||||
|
||||
# Load managed distributor enterprises of current user
|
||||
def my_distributors
|
||||
Enterprise.is_distributor.managed_by(spree_current_user)
|
||||
end
|
||||
|
||||
# Load managed producer enterprises of current user
|
||||
def my_suppliers
|
||||
Enterprise.is_primary_producer.managed_by(spree_current_user)
|
||||
end
|
||||
|
||||
def suppliers_of_products_distributed_by(distributors)
|
||||
distributors.map { |d| Spree::Product.in_distributor(d).includes(:supplier).all }.
|
||||
flatten.map(&:supplier).uniq
|
||||
end
|
||||
|
||||
# Load order cycles the current user has access to
|
||||
def my_order_cycles
|
||||
OrderCycle.active_or_complete.accessible_by(spree_current_user).order('orders_close_at DESC')
|
||||
end
|
||||
|
||||
def order_grouper_table
|
||||
order_grouper = OpenFoodNetwork::OrderGrouper.new @report.rules, @report.columns
|
||||
order_grouper.table(@report.table_items)
|
||||
end
|
||||
|
||||
def authorized_reports
|
||||
all_reports = [
|
||||
:orders_and_distributors,
|
||||
:bulk_coop,
|
||||
:payments,
|
||||
:orders_and_fulfillment,
|
||||
:customers,
|
||||
:products_and_inventory,
|
||||
:sales_total,
|
||||
:users_and_enterprises,
|
||||
:enterprise_fee_summary,
|
||||
:order_cycle_management,
|
||||
:sales_tax,
|
||||
:xero_invoices,
|
||||
:packing
|
||||
]
|
||||
reports = all_reports.select { |action| can? action, Spree::Admin::ReportsController }
|
||||
reports.map { |report| [report, describe_report(report)] }.to_h
|
||||
end
|
||||
|
||||
def describe_report(report)
|
||||
name = I18n.t(:name, scope: [:admin, :reports, report])
|
||||
description = begin
|
||||
I18n.t!(:description, scope: [:admin, :reports, report])
|
||||
rescue I18n::MissingTranslationData
|
||||
render_to_string(
|
||||
partial: "#{report}_description",
|
||||
layout: false,
|
||||
locals: { report_types: report_types[report] }
|
||||
).html_safe
|
||||
end
|
||||
{ name: name, url: url_for_report(report), description: description }
|
||||
end
|
||||
|
||||
def url_for_report(report)
|
||||
public_send("#{report}_admin_reports_url".to_sym)
|
||||
rescue NoMethodError
|
||||
url_for([:new, :admin, :reports, report.to_s.singularize])
|
||||
end
|
||||
|
||||
def timestamp
|
||||
Time.zone.now.strftime("%Y%m%d")
|
||||
end
|
||||
|
||||
def orders_and_fulfillment_default_filters
|
||||
now = Time.zone.now
|
||||
{ completed_at_gt: (now - 1.month).beginning_of_day,
|
||||
completed_at_lt: (now + 1.day).beginning_of_day }
|
||||
end
|
||||
end
|
||||
275
app/controllers/spree/admin/resource_controller.rb
Normal file
275
app/controllers/spree/admin/resource_controller.rb
Normal file
@@ -0,0 +1,275 @@
|
||||
require 'action_callbacks'
|
||||
|
||||
module Spree
|
||||
module Admin
|
||||
class ResourceController < Spree::Admin::BaseController
|
||||
helper_method :new_object_url, :edit_object_url, :object_url, :collection_url
|
||||
before_filter :load_resource, except: [:update_positions]
|
||||
rescue_from ActiveRecord::RecordNotFound, with: :resource_not_found
|
||||
rescue_from CanCan::AccessDenied, with: :unauthorized
|
||||
|
||||
respond_to :html
|
||||
respond_to :js, except: [:show, :index]
|
||||
|
||||
def new
|
||||
invoke_callbacks(:new_action, :before)
|
||||
respond_with(@object) do |format|
|
||||
format.html { render layout: !request.xhr? }
|
||||
format.js { render layout: false }
|
||||
end
|
||||
end
|
||||
|
||||
def edit
|
||||
respond_with(@object) do |format|
|
||||
format.html { render layout: !request.xhr? }
|
||||
format.js { render layout: false }
|
||||
end
|
||||
end
|
||||
|
||||
def update
|
||||
invoke_callbacks(:update, :before)
|
||||
if @object.update_attributes(params[object_name])
|
||||
invoke_callbacks(:update, :after)
|
||||
flash[:success] = flash_message_for(@object, :successfully_updated)
|
||||
respond_with(@object) do |format|
|
||||
format.html { redirect_to location_after_save }
|
||||
format.js { render layout: false }
|
||||
end
|
||||
else
|
||||
invoke_callbacks(:update, :fails)
|
||||
respond_with(@object)
|
||||
end
|
||||
end
|
||||
|
||||
def create
|
||||
invoke_callbacks(:create, :before)
|
||||
@object.attributes = params[object_name]
|
||||
if @object.save
|
||||
invoke_callbacks(:create, :after)
|
||||
flash[:success] = flash_message_for(@object, :successfully_created)
|
||||
respond_with(@object) do |format|
|
||||
format.html { redirect_to location_after_save }
|
||||
format.js { render layout: false }
|
||||
end
|
||||
else
|
||||
invoke_callbacks(:create, :fails)
|
||||
respond_with(@object)
|
||||
end
|
||||
end
|
||||
|
||||
def update_positions
|
||||
params[:positions].each do |id, index|
|
||||
model_class.where(id: id).update_all(position: index)
|
||||
end
|
||||
|
||||
respond_to do |format|
|
||||
format.js { render text: 'Ok' }
|
||||
end
|
||||
end
|
||||
|
||||
def destroy
|
||||
invoke_callbacks(:destroy, :before)
|
||||
if @object.destroy
|
||||
invoke_callbacks(:destroy, :after)
|
||||
flash[:success] = flash_message_for(@object, :successfully_removed)
|
||||
respond_with(@object) do |format|
|
||||
format.html { redirect_to collection_url }
|
||||
format.js { render partial: "spree/admin/shared/destroy" }
|
||||
end
|
||||
else
|
||||
invoke_callbacks(:destroy, :fails)
|
||||
respond_with(@object) do |format|
|
||||
format.html { redirect_to collection_url }
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
protected
|
||||
|
||||
def resource_not_found
|
||||
flash[:error] = flash_message_for(model_class.new, :not_found)
|
||||
redirect_to collection_url
|
||||
end
|
||||
|
||||
class << self
|
||||
attr_accessor :parent_data
|
||||
attr_accessor :callbacks
|
||||
|
||||
def belongs_to(model_name, options = {})
|
||||
@parent_data ||= {}
|
||||
@parent_data[:model_name] = model_name
|
||||
@parent_data[:model_class] = model_name.to_s.classify.constantize
|
||||
@parent_data[:find_by] = options[:find_by] || :id
|
||||
end
|
||||
|
||||
def new_action
|
||||
@callbacks ||= {}
|
||||
@callbacks[:new_action] ||= ActionCallbacks.new
|
||||
end
|
||||
|
||||
def create
|
||||
@callbacks ||= {}
|
||||
@callbacks[:create] ||= ActionCallbacks.new
|
||||
end
|
||||
|
||||
def update
|
||||
@callbacks ||= {}
|
||||
@callbacks[:update] ||= ActionCallbacks.new
|
||||
end
|
||||
|
||||
def destroy
|
||||
@callbacks ||= {}
|
||||
@callbacks[:destroy] ||= ActionCallbacks.new
|
||||
end
|
||||
end
|
||||
|
||||
def model_class
|
||||
"Spree::#{controller_name.classify}".constantize
|
||||
end
|
||||
|
||||
def model_name
|
||||
parent_data[:model_name].gsub('spree/', '')
|
||||
end
|
||||
|
||||
def object_name
|
||||
controller_name.singularize
|
||||
end
|
||||
|
||||
def load_resource
|
||||
if member_action?
|
||||
@object ||= load_resource_instance
|
||||
|
||||
# call authorize! a third time (called twice already in Admin::BaseController)
|
||||
# this time we pass the actual instance so fine-grained abilities can control
|
||||
# access to individual records, not just entire models.
|
||||
authorize! action, @object
|
||||
|
||||
instance_variable_set("@#{object_name}", @object)
|
||||
|
||||
# If we don't have access, clear the object
|
||||
unless can? action, @object
|
||||
instance_variable_set("@#{object_name}", nil)
|
||||
end
|
||||
|
||||
authorize! action, @object
|
||||
else
|
||||
@collection ||= collection
|
||||
|
||||
# note: we don't call authorize here as the collection method should use
|
||||
# CanCan's accessible_by method to restrict the actual records returned
|
||||
|
||||
instance_variable_set("@#{controller_name}", @collection)
|
||||
end
|
||||
end
|
||||
|
||||
def load_resource_instance
|
||||
if new_actions.include?(action)
|
||||
build_resource
|
||||
elsif params[:id]
|
||||
find_resource
|
||||
end
|
||||
end
|
||||
|
||||
def parent_data
|
||||
self.class.parent_data
|
||||
end
|
||||
|
||||
def parent
|
||||
return nil if parent_data.blank?
|
||||
|
||||
@parent ||= parent_data[:model_class].
|
||||
public_send("find_by_#{parent_data[:find_by]}", params["#{model_name}_id"])
|
||||
instance_variable_set("@#{model_name}", @parent)
|
||||
end
|
||||
|
||||
def find_resource
|
||||
if parent_data.present?
|
||||
parent.public_send(controller_name).find(params[:id])
|
||||
else
|
||||
model_class.find(params[:id])
|
||||
end
|
||||
end
|
||||
|
||||
def build_resource
|
||||
if parent_data.present?
|
||||
parent.public_send(controller_name).build
|
||||
else
|
||||
model_class.new
|
||||
end
|
||||
end
|
||||
|
||||
def collection
|
||||
return parent.public_send(controller_name) if parent_data.present?
|
||||
|
||||
if model_class.respond_to?(:accessible_by) &&
|
||||
!current_ability.has_block?(params[:action], model_class)
|
||||
model_class.accessible_by(current_ability, action)
|
||||
else
|
||||
model_class.scoped
|
||||
end
|
||||
end
|
||||
|
||||
def location_after_save
|
||||
collection_url
|
||||
end
|
||||
|
||||
def invoke_callbacks(action, callback_type)
|
||||
callbacks = self.class.callbacks || {}
|
||||
return if callbacks[action].nil?
|
||||
|
||||
case callback_type.to_sym
|
||||
when :before then callbacks[action].before_methods.each { |method| __send__ method }
|
||||
when :after then callbacks[action].after_methods.each { |method| __send__ method }
|
||||
when :fails then callbacks[action].fails_methods.each { |method| __send__ method }
|
||||
end
|
||||
end
|
||||
|
||||
# URL helpers
|
||||
|
||||
def new_object_url(options = {})
|
||||
if parent_data.present?
|
||||
spree.new_polymorphic_url([:admin, parent, model_class], options)
|
||||
else
|
||||
spree.new_polymorphic_url([:admin, model_class], options)
|
||||
end
|
||||
end
|
||||
|
||||
def edit_object_url(object, options = {})
|
||||
if parent_data.present?
|
||||
spree.public_send "edit_admin_#{model_name}_#{object_name}_url", parent, object, options
|
||||
else
|
||||
spree.public_send "edit_admin_#{object_name}_url", object, options
|
||||
end
|
||||
end
|
||||
|
||||
def object_url(object = nil, options = {})
|
||||
target = object || @object
|
||||
if parent_data.present?
|
||||
spree.public_send "admin_#{model_name}_#{object_name}_url", parent, target, options
|
||||
else
|
||||
spree.public_send "admin_#{object_name}_url", target, options
|
||||
end
|
||||
end
|
||||
|
||||
def collection_url(options = {})
|
||||
if parent_data.present?
|
||||
spree.polymorphic_url([:admin, parent, model_class], options)
|
||||
else
|
||||
spree.polymorphic_url([:admin, model_class], options)
|
||||
end
|
||||
end
|
||||
|
||||
def collection_actions
|
||||
[:index]
|
||||
end
|
||||
|
||||
def member_action?
|
||||
!collection_actions.include? action
|
||||
end
|
||||
|
||||
def new_actions
|
||||
[:new, :create]
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
@@ -1,20 +0,0 @@
|
||||
module AuthorizeOnLoadResource
|
||||
def load_resource
|
||||
super
|
||||
|
||||
if member_action?
|
||||
# If we don't have access, clear the object
|
||||
unless can? action, @object
|
||||
instance_variable_set("@#{object_name}", nil)
|
||||
end
|
||||
|
||||
authorize! action, @object
|
||||
end
|
||||
end
|
||||
end
|
||||
|
||||
Spree::Admin::ResourceController.prepend(AuthorizeOnLoadResource)
|
||||
|
||||
Spree::Admin::ResourceController.class_eval do
|
||||
rescue_from CanCan::AccessDenied, with: :unauthorized
|
||||
end
|
||||
@@ -176,7 +176,7 @@ module Spree
|
||||
previous_states = @order.adjustments.each_with_object({}) do |adjustment, hash|
|
||||
hash[adjustment.id] = adjustment.state
|
||||
end
|
||||
@order.adjustments.each(&:open)
|
||||
@order.adjustments.each { |adjustment| adjustment.fire_events(:open) }
|
||||
|
||||
yield
|
||||
|
||||
|
||||
11
app/helpers/admin/enterprises_helper.rb
Normal file
11
app/helpers/admin/enterprises_helper.rb
Normal file
@@ -0,0 +1,11 @@
|
||||
module Admin
|
||||
module EnterprisesHelper
|
||||
def add_check_if_single(count)
|
||||
if count == 1
|
||||
{ checked: true }
|
||||
else
|
||||
{}
|
||||
end
|
||||
end
|
||||
end
|
||||
end
|
||||
@@ -20,12 +20,27 @@ module ShopHelper
|
||||
)
|
||||
end
|
||||
|
||||
def shop_tabs
|
||||
def base_shop_tabs(column_sizes)
|
||||
[
|
||||
{ name: 'about', title: t(:shopping_tabs_about, distributor: current_distributor.name), cols: 6 },
|
||||
{ name: 'producers', title: t(:label_producers), cols: 2 },
|
||||
{ name: 'contact', title: t(:shopping_tabs_contact), cols: 2 },
|
||||
{ name: 'groups', title: t(:label_groups), cols: 2 },
|
||||
{ name: 'about', cols: column_sizes[0],
|
||||
title: t(:shopping_tabs_about, distributor: current_distributor.name) },
|
||||
{ name: 'producers', cols: column_sizes[1],
|
||||
title: t(:label_producers) },
|
||||
{ name: 'contact', cols: column_sizes[2],
|
||||
title: t(:shopping_tabs_contact) }
|
||||
]
|
||||
end
|
||||
|
||||
def tabs_with_groups
|
||||
tabs = base_shop_tabs([6, 2, 2])
|
||||
tabs << { name: 'groups', title: t(:label_groups), cols: 2 }
|
||||
end
|
||||
|
||||
def tabs_without_groups
|
||||
base_shop_tabs([4, 4, 4])
|
||||
end
|
||||
|
||||
def shop_tabs
|
||||
current_distributor.groups.present? ? tabs_with_groups : tabs_without_groups
|
||||
end
|
||||
end
|
||||
|
||||
@@ -1,3 +1,5 @@
|
||||
require 'spree/admin/base_helper'
|
||||
|
||||
module Spree
|
||||
module Admin
|
||||
module BaseHelper
|
||||
|
||||
@@ -1,3 +1,5 @@
|
||||
require 'spree/admin/navigation_helper'
|
||||
|
||||
module Spree
|
||||
module Admin
|
||||
module NavigationHelper
|
||||
|
||||
@@ -1,3 +1,3 @@
|
||||
class EnterpriseRelationshipPermission < ActiveRecord::Base
|
||||
default_scope order('name')
|
||||
default_scope { order('name') }
|
||||
end
|
||||
|
||||
@@ -142,9 +142,9 @@ class OrderCycle < ActiveRecord::Base
|
||||
oc.name = I18n.t("models.order_cycle.cloned_order_cycle_name", order_cycle: oc.name)
|
||||
oc.orders_open_at = oc.orders_close_at = nil
|
||||
oc.coordinator_fee_ids = coordinator_fee_ids
|
||||
# rubocop:disable Metrics/LineLength
|
||||
# rubocop:disable Layout/LineLength
|
||||
oc.preferred_product_selection_from_coordinator_inventory_only = preferred_product_selection_from_coordinator_inventory_only
|
||||
# rubocop:enable Metrics/LineLength
|
||||
# rubocop:enable Layout/LineLength
|
||||
oc.save!
|
||||
exchanges.each { |e| e.clone!(oc) }
|
||||
oc.reload
|
||||
|
||||
@@ -2,7 +2,7 @@ class ProducerProperty < ActiveRecord::Base
|
||||
belongs_to :producer, class_name: 'Enterprise', touch: true
|
||||
belongs_to :property, class_name: 'Spree::Property'
|
||||
|
||||
default_scope order("#{table_name}.position")
|
||||
default_scope { order("#{table_name}.position") }
|
||||
|
||||
scope :ever_sold_by, ->(shop) {
|
||||
joins(producer: { supplied_products: { variants: { exchanges: :order_cycle } } }).
|
||||
|
||||
@@ -214,7 +214,9 @@ module ProductImport
|
||||
end
|
||||
|
||||
def accepted_mimetype
|
||||
File.extname(@file.path).in?('.csv', '.xls', '.xlsx', '.ods') ? @file.path.split('.').last.to_sym : false
|
||||
return false unless ['.csv'].include? File.extname(@file.path)
|
||||
|
||||
@file.path.split('.').last.to_sym
|
||||
end
|
||||
|
||||
def headers
|
||||
|
||||
@@ -45,11 +45,11 @@ module ProductImport
|
||||
|
||||
next if @enterprises_index.key? enterprise_name
|
||||
|
||||
enterprise = Enterprise.find_by_name(enterprise_name, select: 'id, is_primary_producer')
|
||||
enterprise = Enterprise.select([:id, :is_primary_producer]).
|
||||
where(name: enterprise_name).first
|
||||
|
||||
@enterprises_index[enterprise_name] =
|
||||
{ id: enterprise.try(:id),
|
||||
is_primary_producer: enterprise.try(:is_primary_producer) }
|
||||
{ id: enterprise.try(:id), is_primary_producer: enterprise.try(:is_primary_producer) }
|
||||
end
|
||||
@enterprises_index
|
||||
end
|
||||
@@ -60,7 +60,8 @@ module ProductImport
|
||||
next unless entry.producer
|
||||
|
||||
producer_name = entry.producer
|
||||
producer_id = @producers_index[producer_name] || Enterprise.find_by_name(producer_name, select: 'id, name').try(:id)
|
||||
producer_id = @producers_index[producer_name] ||
|
||||
Enterprise.select([:id, :name]).where(name: producer_name).first.try(:id)
|
||||
@producers_index[producer_name] = producer_id
|
||||
end
|
||||
@producers_index
|
||||
@@ -70,7 +71,8 @@ module ProductImport
|
||||
@categories_index = {}
|
||||
@entries.each do |entry|
|
||||
category_name = entry.category
|
||||
category_id = @categories_index[category_name] || Spree::Taxon.find_by_name(category_name, select: 'id, name').try(:id)
|
||||
category_id = @categories_index[category_name] ||
|
||||
Spree::Taxon.select([:id, :name]).where(name: category_name).first.try(:id)
|
||||
@categories_index[category_name] = category_id
|
||||
end
|
||||
@categories_index
|
||||
|
||||
@@ -1,7 +1,5 @@
|
||||
module Spree
|
||||
class User < ActiveRecord::Base
|
||||
include Core::UserBanners
|
||||
|
||||
devise :database_authenticatable, :token_authenticatable, :registerable, :recoverable,
|
||||
:rememberable, :trackable, :validatable, :encryptable, encryptor: 'authlogic_sha512'
|
||||
|
||||
|
||||
@@ -6,6 +6,8 @@ class SubscriptionLineItem < ActiveRecord::Base
|
||||
validates :variant, presence: true
|
||||
validates :quantity, presence: true, numericality: { only_integer: true }
|
||||
|
||||
default_scope { order('id ASC') }
|
||||
|
||||
def total_estimate
|
||||
(price_estimate || 0) * (quantity || 0)
|
||||
end
|
||||
@@ -22,6 +24,4 @@ class SubscriptionLineItem < ActiveRecord::Base
|
||||
def price
|
||||
price_estimate
|
||||
end
|
||||
|
||||
default_scope order('id ASC')
|
||||
end
|
||||
|
||||
@@ -12,7 +12,7 @@ class VariantOverride < ActiveRecord::Base
|
||||
# Default stock can be nil, indicating stock should not be reset or zero, meaning reset to zero. Need to ensure this can be set by the user.
|
||||
validates :default_stock, numericality: { greater_than_or_equal_to: 0 }, allow_nil: true
|
||||
|
||||
default_scope where(permission_revoked_at: nil)
|
||||
default_scope { where(permission_revoked_at: nil) }
|
||||
|
||||
scope :for_hubs, lambda { |hubs|
|
||||
where(hub_id: hubs)
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
require 'open_food_network/enterprise_issue_validator'
|
||||
|
||||
class Api::Admin::ForOrderCycle::EnterpriseSerializer < ActiveModel::Serializer
|
||||
attributes :id, :name, :managed, :supplied_products,
|
||||
attributes :id, :name, :managed,
|
||||
:issues_summary_supplier, :issues_summary_distributor,
|
||||
:is_primary_producer, :is_distributor, :sells
|
||||
|
||||
@@ -25,12 +25,6 @@ class Api::Admin::ForOrderCycle::EnterpriseSerializer < ActiveModel::Serializer
|
||||
Enterprise.managed_by(options[:spree_current_user]).include? object
|
||||
end
|
||||
|
||||
def supplied_products
|
||||
serializer = Api::Admin::ForOrderCycle::SuppliedProductSerializer
|
||||
ActiveModel::ArraySerializer.new(products, each_serializer: serializer,
|
||||
order_cycle: order_cycle)
|
||||
end
|
||||
|
||||
private
|
||||
|
||||
def products_scope
|
||||
|
||||
@@ -14,7 +14,8 @@ class Api::Admin::ForOrderCycle::SuppliedProductSerializer < ActiveModel::Serial
|
||||
end
|
||||
|
||||
def variants
|
||||
variants = if order_cycle.prefers_product_selection_from_coordinator_inventory_only?
|
||||
variants = if order_cycle.present? &&
|
||||
order_cycle.prefers_product_selection_from_coordinator_inventory_only?
|
||||
object.variants.visible_for(order_cycle.coordinator)
|
||||
else
|
||||
object.variants
|
||||
|
||||
@@ -1,8 +1,8 @@
|
||||
class Api::Admin::OrderSerializer < ActiveModel::Serializer
|
||||
attributes :id, :number, :user_id, :full_name, :email, :phone, :completed_at, :display_total,
|
||||
:edit_path, :state, :payment_state, :shipment_state,
|
||||
:payments_path, :ship_path, :ready_to_ship, :created_at,
|
||||
:distributor_name, :special_instructions, :payment_capture_path,
|
||||
:payments_path, :ready_to_ship, :ready_to_capture, :created_at,
|
||||
:distributor_name, :special_instructions,
|
||||
:item_total, :adjustment_total, :payment_total, :total
|
||||
|
||||
has_one :distributor, serializer: Api::Admin::IdSerializer
|
||||
@@ -28,15 +28,9 @@ class Api::Admin::OrderSerializer < ActiveModel::Serializer
|
||||
spree_routes_helper.admin_order_payments_path(object)
|
||||
end
|
||||
|
||||
def ship_path
|
||||
spree_routes_helper.fire_admin_order_path(object, e: 'ship')
|
||||
end
|
||||
|
||||
def payment_capture_path
|
||||
def ready_to_capture
|
||||
pending_payment = object.pending_payments.first
|
||||
return '' unless object.payment_required? && pending_payment
|
||||
|
||||
spree_routes_helper.fire_admin_order_payment_path(object, pending_payment.id, e: 'capture')
|
||||
object.payment_required? && pending_payment
|
||||
end
|
||||
|
||||
def ready_to_ship
|
||||
|
||||
23
app/services/action_callbacks.rb
Normal file
23
app/services/action_callbacks.rb
Normal file
@@ -0,0 +1,23 @@
|
||||
class ActionCallbacks
|
||||
attr_reader :before_methods
|
||||
attr_reader :after_methods
|
||||
attr_reader :fails_methods
|
||||
|
||||
def initialize
|
||||
@before_methods = []
|
||||
@after_methods = []
|
||||
@fails_methods = []
|
||||
end
|
||||
|
||||
def before(method)
|
||||
@before_methods << method
|
||||
end
|
||||
|
||||
def after(method)
|
||||
@after_methods << method
|
||||
end
|
||||
|
||||
def fails(method)
|
||||
@fails_methods << method
|
||||
end
|
||||
end
|
||||
86
app/services/exchange_products_renderer.rb
Normal file
86
app/services/exchange_products_renderer.rb
Normal file
@@ -0,0 +1,86 @@
|
||||
class ExchangeProductsRenderer
|
||||
def initialize(order_cycle, user)
|
||||
@order_cycle = order_cycle
|
||||
@user = user
|
||||
end
|
||||
|
||||
def exchange_products(incoming, enterprise)
|
||||
if incoming
|
||||
products_for_incoming_exchange(enterprise)
|
||||
else
|
||||
products_for_outgoing_exchange
|
||||
end
|
||||
end
|
||||
|
||||
private
|
||||
|
||||
def products_for_incoming_exchange(enterprise)
|
||||
supplied_products(enterprise.id)
|
||||
end
|
||||
|
||||
def supplied_products(enterprises_query_matcher)
|
||||
products_relation = Spree::Product.where(supplier_id: enterprises_query_matcher)
|
||||
|
||||
if @order_cycle.present? &&
|
||||
@order_cycle.prefers_product_selection_from_coordinator_inventory_only?
|
||||
products_relation = products_relation.visible_for(@order_cycle.coordinator)
|
||||
end
|
||||
|
||||
products_relation
|
||||
end
|
||||
|
||||
def products_for_outgoing_exchange
|
||||
supplied_products(enterprises_for_outgoing_exchange.select(:id)).
|
||||
includes(:variants).
|
||||
where("spree_variants.id": incoming_exchanges_variants)
|
||||
end
|
||||
|
||||
def incoming_exchanges_variants
|
||||
return @incoming_exchanges_variants if @incoming_exchanges_variants.present?
|
||||
|
||||
@incoming_exchanges_variants = []
|
||||
visible_incoming_exchanges.each do |incoming_exchange|
|
||||
@incoming_exchanges_variants.push(
|
||||
*incoming_exchange.variants.merge(
|
||||
visible_incoming_variants(incoming_exchange.sender)
|
||||
).map(&:id).to_a
|
||||
)
|
||||
end
|
||||
@incoming_exchanges_variants
|
||||
end
|
||||
|
||||
def visible_incoming_exchanges
|
||||
OpenFoodNetwork::OrderCyclePermissions.
|
||||
new(@user, @order_cycle).
|
||||
visible_exchanges.
|
||||
by_enterprise_name.
|
||||
incoming
|
||||
end
|
||||
|
||||
def visible_incoming_variants(incoming_exchange_sender)
|
||||
variants_relation = permitted_incoming_variants(incoming_exchange_sender)
|
||||
|
||||
if @order_cycle.prefers_product_selection_from_coordinator_inventory_only?
|
||||
variants_relation = variants_relation.visible_for(@order_cycle.coordinator)
|
||||
end
|
||||
|
||||
variants_relation
|
||||
end
|
||||
|
||||
def permitted_incoming_variants(incoming_exchange_sender)
|
||||
OpenFoodNetwork::OrderCyclePermissions.
|
||||
new(@user, @order_cycle).
|
||||
visible_variants_for_incoming_exchanges_from(incoming_exchange_sender)
|
||||
end
|
||||
|
||||
def enterprises_for_outgoing_exchange
|
||||
enterprises = OpenFoodNetwork::OrderCyclePermissions.
|
||||
new(@user, @order_cycle)
|
||||
.visible_enterprises
|
||||
return enterprises if enterprises.empty?
|
||||
|
||||
enterprises.includes(
|
||||
supplied_products: [:supplier, :variants, master: [:images]]
|
||||
)
|
||||
end
|
||||
end
|
||||
@@ -7,17 +7,17 @@ module Permissions
|
||||
|
||||
# Find orders that the user can see
|
||||
def visible_orders
|
||||
Spree::Order.where(id:
|
||||
managed_orders.select(:id) |
|
||||
coordinated_orders.select(:id) |
|
||||
produced_orders.select("spree_orders.id"))
|
||||
Spree::Order.
|
||||
with_line_items_variants_and_products_outer.
|
||||
where(visible_orders_where_values)
|
||||
end
|
||||
|
||||
# Any orders that the user can edit
|
||||
def editable_orders
|
||||
Spree::Order.where(id:
|
||||
managed_orders.select(:id) |
|
||||
coordinated_orders.select(:id) )
|
||||
Spree::Order.where(
|
||||
managed_orders_where_values.
|
||||
or(coordinated_orders_where_values)
|
||||
)
|
||||
end
|
||||
|
||||
def visible_line_items
|
||||
@@ -28,27 +28,45 @@ module Permissions
|
||||
|
||||
# Any line items that I can edit
|
||||
def editable_line_items
|
||||
Spree::LineItem.where(order_id: editable_orders)
|
||||
Spree::LineItem.where(order_id: editable_orders.select(:id))
|
||||
end
|
||||
|
||||
private
|
||||
|
||||
def visible_orders_where_values
|
||||
# Grouping keeps the 2 where clauses from produced_orders_where_values inside parentheses
|
||||
# This way it makes the OR work between the 3 types of orders:
|
||||
# produced, managed and coordinated
|
||||
Spree::Order.arel_table.
|
||||
grouping(produced_orders_where_values).
|
||||
or(managed_orders_where_values).
|
||||
or(coordinated_orders_where_values)
|
||||
end
|
||||
|
||||
# Any orders placed through any hub that I manage
|
||||
def managed_orders
|
||||
Spree::Order.where(distributor_id: @permissions.managed_enterprises.select("enterprises.id"))
|
||||
def managed_orders_where_values
|
||||
Spree::Order.
|
||||
where(distributor_id: @permissions.managed_enterprises.select("enterprises.id")).
|
||||
where_values.
|
||||
reduce(:and)
|
||||
end
|
||||
|
||||
# Any order that is placed through an order cycle one of my managed enterprises coordinates
|
||||
def coordinated_orders
|
||||
Spree::Order.where(order_cycle_id: @permissions.coordinated_order_cycles.select(:id))
|
||||
def coordinated_orders_where_values
|
||||
Spree::Order.
|
||||
where(order_cycle_id: @permissions.coordinated_order_cycles.select(:id)).
|
||||
where_values.
|
||||
reduce(:and)
|
||||
end
|
||||
|
||||
def produced_orders
|
||||
def produced_orders_where_values
|
||||
Spree::Order.with_line_items_variants_and_products_outer.
|
||||
where(
|
||||
distributor_id: granted_distributor_ids,
|
||||
spree_products: { supplier_id: enterprises_with_associated_orders }
|
||||
)
|
||||
).
|
||||
where_values.
|
||||
reduce(:and)
|
||||
end
|
||||
|
||||
def enterprises_with_associated_orders
|
||||
@@ -69,7 +87,7 @@ module Permissions
|
||||
|
||||
# Any from visible orders, where the product is produced by one of my managed producers
|
||||
def produced_line_items
|
||||
Spree::LineItem.where(order_id: visible_orders.select(:id)).
|
||||
Spree::LineItem.where(order_id: visible_orders.select("DISTINCT spree_orders.id")).
|
||||
joins(:product).
|
||||
where(spree_products:
|
||||
{
|
||||
|
||||
@@ -1,11 +1,7 @@
|
||||
%tr{ ng: { class: "'#{type} #{type}-{{ exchange.enterprise_id }}'" } }
|
||||
%td{:class => "#{type}_name"} {{ enterprises[exchange.enterprise_id].name }}
|
||||
%td.products.panel-toggle.text-center{ name: "products" }
|
||||
{{ exchangeSelectedVariants(exchange) }} /
|
||||
- if type == 'supplier'
|
||||
{{ enterpriseTotalVariants(enterprises[exchange.enterprise_id]) }}
|
||||
- else
|
||||
{{ (incomingExchangeVariantsFor(exchange.enterprise_id)).length }}
|
||||
{{ exchangeSelectedVariants(exchange) }} / {{ exchangeTotalVariants(exchange) }}
|
||||
= t('.selected')
|
||||
- if type == 'supplier'
|
||||
%td.receival-details
|
||||
@@ -34,11 +30,11 @@
|
||||
|
||||
- if type == 'supplier'
|
||||
%tr.panel-row{ object: "exchange",
|
||||
panels: "{products: 'exchange_supplied_products'}",
|
||||
locals: "$index,order_cycle,exchange,enterprises,setExchangeVariants,suppliedVariants,removeDistributionOfVariant",
|
||||
panels: "{products: 'exchange_products_supplied'}",
|
||||
locals: "$index,order_cycle,exchange,enterprises,setExchangeVariants,selectAllVariants,suppliedVariants,removeDistributionOfVariant,initializeExchangeProductsPanel,loadMoreExchangeProducts,loadAllExchangeProducts,productsLoading",
|
||||
colspan: 4 }
|
||||
- if type == 'distributor'
|
||||
%tr.panel-row{ object: "exchange",
|
||||
panels: "{products: 'exchange_distributed_products', tags: 'exchange_tags'}",
|
||||
locals: "$index,order_cycle,exchange,supplied_products,setExchangeVariants,incomingExchangeVariantsFor,productSuppliedToOrderCycle,variantSuppliedToOrderCycle",
|
||||
panels: "{products: 'exchange_products_distributed', tags: 'exchange_tags'}",
|
||||
locals: "$index,order_cycle,exchange,enterprises,setExchangeVariants,incomingExchangeVariantsFor,variantSuppliedToOrderCycle,initializeExchangeProductsPanel,loadMoreExchangeProducts,loadAllExchangeProducts,productsLoading",
|
||||
colspan: 5 }
|
||||
|
||||
@@ -17,7 +17,7 @@
|
||||
%table.exchanges
|
||||
%tbody{ng: {repeat: "exchange in order_cycle.incoming_exchanges"}}
|
||||
%tr.products
|
||||
%td{ ng: { include: "'admin/panels/exchange_supplied_products.html'" } }
|
||||
%td{ ng: { include: "'admin/panels/exchange_products_simple.html'" } }
|
||||
|
||||
%br/
|
||||
= label_tag t('.fees')
|
||||
|
||||
@@ -7,7 +7,6 @@
|
||||
= render 'wizard_progress'
|
||||
|
||||
%save-bar{ dirty: "order_cycle_form.$dirty", persist: "true" }
|
||||
%input{ type: "button", value: t('.previous'), ng: { click: "cancel('#{main_app.edit_admin_order_cycle_path(@order_cycle)}')", disabled: "order_cycle_form.$dirty" } }
|
||||
%input.red{ type: "button", value: t('.save'), ng: { click: "submit($event, null)", disabled: "!order_cycle_form.$dirty || order_cycle_form.$invalid" } }
|
||||
%input.red{ type: "button", value: t('.save_and_next'), ng: { click: "submit($event, '#{main_app.admin_order_cycle_outgoing_path(@order_cycle)}')", disabled: "!order_cycle_form.$dirty || order_cycle_form.$invalid" } }
|
||||
%input{ type: "button", value: t('.next'), ng: { click: "cancel('#{main_app.admin_order_cycle_outgoing_path(@order_cycle)}')", disabled: "order_cycle_form.$dirty" } }
|
||||
|
||||
@@ -7,7 +7,6 @@
|
||||
= render 'wizard_progress'
|
||||
|
||||
%save-bar{ dirty: "order_cycle_form.$dirty", persist: "true" }
|
||||
%input{ type: "button", value: t('.previous'), ng: { click: "cancel('#{main_app.admin_order_cycle_incoming_path(@order_cycle)}')", disabled: "order_cycle_form.$dirty" } }
|
||||
%input.red{ type: "button", value: t('.save'), ng: { click: "submit($event, null)", disabled: "!order_cycle_form.$dirty || order_cycle_form.$invalid" } }
|
||||
%input.red{ type: "button", value: t('.save_and_back_to_list'), ng: { click: "submit($event, '#{main_app.admin_order_cycles_path}')", disabled: "!order_cycle_form.$dirty || order_cycle_form.$invalid" } }
|
||||
%input{ type: "button", ng: { value: "order_cycle_form.$dirty ? '#{t('.cancel')}' : '#{t('.back_to_list')}'", click: "cancel('#{main_app.admin_order_cycles_path}')" } }
|
||||
|
||||
@@ -8,7 +8,7 @@
|
||||
%p
|
||||
= t(".email_userguide_html", link: link_to(t(".userguide"), ContentConfig.user_guide_link))
|
||||
%p
|
||||
= t(".email_admin_html", link: link_to(t(".admin_panel"), spree.admin_url))
|
||||
= t(".email_admin_html", link: link_to(t(".admin_panel"), spree.admin_dashboard_url))
|
||||
|
||||
%p
|
||||
= t(".email_community_html", link: link_to(t(".join_community"), ContentConfig.community_forum_url))
|
||||
|
||||
@@ -8,38 +8,6 @@
|
||||
.small-12.medium-8.medium-offset-2.columns.text-center
|
||||
.alert-box
|
||||
= render 'shared/register_call'
|
||||
.row
|
||||
.small-12.medium-4.medium-offset-2.columns.text-center
|
||||
%h6
|
||||
= t '.footer_global_headline'
|
||||
%p
|
||||
%a{href: "http://www.openfoodnetwork.org", target: "_blank"}
|
||||
= t '.footer_global_home'
|
||||
%span |
|
||||
%a{href: "http://www.openfoodnetwork.org/news/", target: "_blank"}
|
||||
= t '.footer_global_news'
|
||||
%span |
|
||||
%a{href: "http://www.openfoodnetwork.org/about/history-team/", target: "_blank"}
|
||||
= t '.footer_global_about'
|
||||
%span |
|
||||
%a{href: "http://www.openfoodnetwork.org/contact/", target: "_blank"}
|
||||
= t '.footer_global_contact'
|
||||
|
||||
.small-12.medium-4.columns.text-center
|
||||
%h6
|
||||
= t '.footer_sites_headline'
|
||||
%p
|
||||
%a{href: "http://dev.openfoodnetwork.org", target: "_blank"}
|
||||
= t '.footer_sites_developer'
|
||||
%span |
|
||||
%a{href: "http://community.openfoodnetwork.org", target: "_blank"}
|
||||
= t '.footer_sites_community'
|
||||
%span |
|
||||
%a{href: "http://www.openfoodnetwork.org/platform/user-guide/", target: "_blank"}
|
||||
= t '.footer_sites_userguide'
|
||||
|
||||
.medium-2.columns.text-center
|
||||
/ Placeholder
|
||||
|
||||
.footer-local
|
||||
.row
|
||||
|
||||
@@ -15,7 +15,7 @@
|
||||
|
||||
- if admin_user? or enterprise_user?
|
||||
%li
|
||||
%a{href: spree.admin_path, target:'_blank'}
|
||||
%a{href: spree.admin_dashboard_path, target:'_blank'}
|
||||
%i.ofn-i_021-tools
|
||||
= t 'label_administration'
|
||||
|
||||
|
||||
@@ -7,7 +7,7 @@
|
||||
|
||||
- if admin_user? or enterprise_user?
|
||||
%li
|
||||
%a{href: spree.admin_path, target:'_blank'}
|
||||
%a{href: spree.admin_dashboard_path, target:'_blank'}
|
||||
%i.ofn-i_021-tools
|
||||
= t 'label_admin'
|
||||
|
||||
|
||||
@@ -10,4 +10,4 @@
|
||||
|
||||
= render :partial => 'adjustments_table'
|
||||
|
||||
= button_link_to t(:continue), @order.cart? ? new_admin_order_payment_url(@order) : admin_orders_url, :icon => 'icon-arrow-right'
|
||||
= button_link_to t(:continue), admin_order_payments_url(@order), :icon => 'icon-arrow-right'
|
||||
|
||||
@@ -47,7 +47,7 @@
|
||||
|
||||
%th.actions
|
||||
%tbody
|
||||
%tr{ng: {repeat: 'order in orders track by order.id', class: {even: "'even'", odd: "'odd'"}}, 'ng-class' => "'state-{{order.state}}'"}
|
||||
%tr{ng: {repeat: 'order in orders track by order.id', class: {even: "'even'", odd: "'odd'"}}, 'ng-class' => "{'state-{{order.state}}': true, 'row-loading': rowStatus[order.id] == 'loading'}"}
|
||||
%td.align-center
|
||||
%input{type: 'checkbox', 'ng-model' => 'checkboxes[order.id]', 'ng-change' => 'toggleSelection(order.id)'}
|
||||
%td.align-center
|
||||
@@ -78,11 +78,15 @@
|
||||
%td.align-center
|
||||
%span{'ng-bind-html' => 'order.display_total'}
|
||||
%td.actions
|
||||
%div.row-loading-icons
|
||||
%img.spinner{src: "/assets/spinning-circles.svg", ng: {show: 'rowStatus[order.id] == "loading"'} }
|
||||
%i.success.icon-ok-sign{ng: {show: 'rowStatus[order.id] == "success"'} }
|
||||
%i.error.icon-remove-sign.with-tip{ng: {show: 'rowStatus[order.id] == "error"'}, 'ofn-with-tip' => t('.order_not_updated')}
|
||||
%a.icon_link.with-tip.icon-edit.no-text{'ng-href' => '{{order.edit_path}}', 'data-action' => 'edit', 'ofn-with-tip' => t('.edit')}
|
||||
%div{'ng-if' => 'order.ready_to_ship'}
|
||||
%a.icon-road.icon_link.with-tip.no-text{'ng-href' => '{{order.ship_path}}', 'data-action' => 'ship', 'data-confirm' => t(:are_you_sure), 'data-method' => 'put', rel: 'nofollow', 'ofn-with-tip' => t('.ship')}
|
||||
%div{'ng-if' => 'order.payment_capture_path'}
|
||||
%a.icon-capture.icon_link.no-text{'ng-href' => '{{order.payment_capture_path}}', 'data-action' => 'capture', 'data-method' => 'put', rel: 'nofollow', 'ofn-with-tip' => t('.capture')}
|
||||
%button.icon-road.icon_link.with-tip.no-text{'ng-click' => 'shipOrder(order)', 'data-confirm' => t(:are_you_sure), rel: 'nofollow', 'ofn-with-tip' => t('.ship')}
|
||||
%div{'ng-if' => 'order.ready_to_capture'}
|
||||
%button.icon-capture.icon_link.no-text{'ng-click' => 'capturePayment(order)', rel: 'nofollow', 'ofn-with-tip' => t('.capture')}
|
||||
|
||||
.orders-loading{'ng-show' => 'RequestMonitor.loading'}
|
||||
.row
|
||||
|
||||
@@ -44,14 +44,14 @@
|
||||
%td{ :align => "right" }
|
||||
= t :invoice_billing_address
|
||||
%br
|
||||
%strong= @order.ship_address.full_name
|
||||
%strong= @order.bill_address.full_name
|
||||
- if @order.andand.customer.andand.code.present?
|
||||
%br
|
||||
= "Code: #{@order.customer.code}"
|
||||
%br
|
||||
= @order.ship_address.address_part1
|
||||
= @order.bill_address.address_part1
|
||||
%br
|
||||
= @order.ship_address.address_part2
|
||||
= @order.bill_address.address_part2
|
||||
|
||||
= render 'spree/admin/orders/invoice_table2'
|
||||
|
||||
|
||||
@@ -1,21 +0,0 @@
|
||||
<% content_for :page_title do %>
|
||||
<%= t(:listing_reports) %>
|
||||
<% end %>
|
||||
|
||||
<table class="index">
|
||||
<thead>
|
||||
<tr data-hook="reports_header">
|
||||
<th><%= t(:name) %></th>
|
||||
<th><%= t(:description) %></th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
<% @reports.each do |key, value| %>
|
||||
<tr data-hook="reports_row">
|
||||
<td><%= link_to value[:name], value[:url] %></td>
|
||||
<td><%= value[:description] %></td>
|
||||
</tr>
|
||||
<% end %>
|
||||
</tbody>
|
||||
</table>
|
||||
|
||||
13
app/views/spree/admin/reports/index.html.haml
Normal file
13
app/views/spree/admin/reports/index.html.haml
Normal file
@@ -0,0 +1,13 @@
|
||||
- content_for :page_title do
|
||||
= t(:listing_reports)
|
||||
|
||||
%table.index
|
||||
%thead
|
||||
%tr
|
||||
%th= t(:name)
|
||||
%th= t(:description)
|
||||
%tbody
|
||||
- @reports.each do |key, value|
|
||||
%tr
|
||||
%td= link_to value[:name], value[:url]
|
||||
%td= value[:description]
|
||||
@@ -1,24 +0,0 @@
|
||||
%tr{"data-hook" => "address1"}
|
||||
%td
|
||||
= t(:admin_shared_address_1):
|
||||
%td= f.text_field :address1
|
||||
%tr{"data-hook" => "address2" }
|
||||
%td
|
||||
= t(:admin_shared_address_2):
|
||||
%td= f.text_field :address2
|
||||
%tr{"data-hook" => "city" }
|
||||
%td
|
||||
= t(:admin_share_city):
|
||||
%td= f.text_field :city
|
||||
%tr{"data-hook" => "zipcode" }
|
||||
%td
|
||||
= t(:admin_share_zipcode):
|
||||
%td= f.text_field :zipcode
|
||||
%tr{"data-hook" => "country" }
|
||||
%td
|
||||
= t(:admin_share_country):
|
||||
%td= f.collection_select(:country_id, available_countries, :id, :name)
|
||||
%tr{"data-hook" => "state" }
|
||||
%td
|
||||
= t(:admin_share_state):
|
||||
%td= f.collection_select(:state_id, f.object.country.states, :id, :name)
|
||||
@@ -12,7 +12,7 @@
|
||||
%span.four.columns
|
||||
%span.three.columns.alpha
|
||||
%label
|
||||
= check_box klass, :distributor_ids, { multiple: true }, hub.id, nil
|
||||
= check_box klass, :distributor_ids, { multiple: true }.merge(add_check_if_single(@hubs.count)), hub.id, nil
|
||||
= hub.name
|
||||
%a.one.column.omega{ href: "#{main_app.edit_admin_enterprise_path(hub)}" }
|
||||
%span.icon-arrow-right
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
= tab :dashboard, :route => :admin, :icon => 'icon-dashboard'
|
||||
= tab :overview, label: 'dashboard', url: spree.admin_dashboard_path, icon: 'icon-dashboard'
|
||||
= tab :products, :option_types, :properties, :variants, :product_properties, :taxons, :url => admin_products_path, :icon => 'icon-th-large'
|
||||
= tab :order_cycles, :url => main_app.admin_order_cycles_path, :icon => 'icon-refresh'
|
||||
= tab :orders, :payments, :creditcard_payments, :shipments, :credit_cards, :return_authorizations, :url => admin_orders_path('q[s]' => 'completed_at desc'), :icon => 'icon-shopping-cart'
|
||||
|
||||
@@ -16,12 +16,10 @@
|
||||
= Spree.t(:loading)
|
||||
\...
|
||||
|
||||
= render :partial => 'spree/admin/shared/alert', :collection => session[:alerts]
|
||||
|
||||
%header#header{"data-hook" => ""}
|
||||
.container
|
||||
%figure.columns.five{"data-hook" => "logo-wrapper"}
|
||||
= link_to image_tag(Spree::Config[:admin_interface_logo], :id => 'logo'), spree.admin_path
|
||||
= link_to image_tag(Spree::Config[:admin_interface_logo], :id => 'logo'), spree.admin_dashboard_path
|
||||
%nav.columns.eleven{"data-hook" => "admin_login_navigation_bar"}
|
||||
= render :partial => 'spree/layouts/admin/login_nav'
|
||||
|
||||
|
||||
@@ -14,11 +14,10 @@
|
||||
.progress-message
|
||||
= t(:loading)
|
||||
\...
|
||||
= render :partial => 'spree/admin/shared/alert', :collection => session[:alerts]
|
||||
|
||||
%header#header{"data-hook" => ""}
|
||||
.container
|
||||
%figure.columns.five{"data-hook" => "logo-wrapper"}= link_to image_tag(Spree::Config[:admin_interface_logo], :id => 'logo'), spree.admin_path
|
||||
%figure.columns.five{"data-hook" => "logo-wrapper"}= link_to image_tag(Spree::Config[:admin_interface_logo], :id => 'logo'), spree.admin_dashboard_path
|
||||
%nav.columns.eleven{"data-hook" => "admin_login_navigation_bar"}
|
||||
= render partial: "spree/layouts/admin/login_nav"
|
||||
|
||||
|
||||
1
config/initializers/paper_trail.rb
Normal file
1
config/initializers/paper_trail.rb
Normal file
@@ -0,0 +1 @@
|
||||
PaperTrail.config.track_associations = false
|
||||
@@ -2,6 +2,8 @@ ar:
|
||||
language_name: "الانجيلزي"
|
||||
activerecord:
|
||||
attributes:
|
||||
enterprise_fee:
|
||||
fee_type: نوع الرسوم
|
||||
spree/order:
|
||||
payment_state: حالة الدفعة
|
||||
shipment_state: حالة الشحن
|
||||
@@ -48,6 +50,8 @@ ar:
|
||||
shipping_method_ids: "طرق الشحن"
|
||||
payment_method_ids: "طريقة الدفع"
|
||||
errors:
|
||||
messages:
|
||||
inclusion: "غير مدرجة في القائمة"
|
||||
models:
|
||||
subscription_validator:
|
||||
attributes:
|
||||
@@ -847,7 +851,6 @@ ar:
|
||||
save_and_back_to_list: "حفظ والعودة إلى القائمة"
|
||||
choose_products_from: "اختر المنتجات من:"
|
||||
incoming:
|
||||
previous: "السابق"
|
||||
save: "حفظ"
|
||||
save_and_next: "حفظ والتالي"
|
||||
next: "التالى"
|
||||
@@ -986,9 +989,6 @@ ar:
|
||||
name: العملاء
|
||||
products_and_inventory:
|
||||
name: المنتجات والمخزون
|
||||
sales_total:
|
||||
name: إجمالي المبيعات
|
||||
description: إجمالي المبيعات لجميع الطلبات
|
||||
users_and_enterprises:
|
||||
name: المستخدمين والمؤسسات
|
||||
description: ملكية الشركات وحالتها
|
||||
@@ -1127,15 +1127,6 @@ ar:
|
||||
selling_on_ofn: "هل أنت مهتم بالحصول على شبكة الغذاء المفتوح؟"
|
||||
register: "سجل هنا"
|
||||
footer:
|
||||
footer_global_headline: "شبكة الغذاء المفتوحة العالمية"
|
||||
footer_global_home: "الصفحة الرئيسية"
|
||||
footer_global_news: "أخبار"
|
||||
footer_global_about: "حول"
|
||||
footer_global_contact: "اتصل"
|
||||
footer_sites_headline: "مواقع شبكة الغذاء المفتوحة"
|
||||
footer_sites_developer: "مطور"
|
||||
footer_sites_community: "تواصل اجتماعي"
|
||||
footer_sites_userguide: "دليل المستخدم"
|
||||
footer_secure: "آمن وموثوق به."
|
||||
footer_secure_text: "تستخدم شبكة الغذاء المفتوح تشفير( SSL 2048 بت RSA) في كل مكان للحفاظ على خصوصية معلومات التسوق والدفع. لا تقوم خوادمنا بتخزين تفاصيل بطاقة الائتمان الخاصة بك ، وتتم معالجة المدفوعات بواسطة خدمات متوافقة مع PCI."
|
||||
footer_contact_headline: "أبق على اتصال"
|
||||
@@ -2426,6 +2417,12 @@ ar:
|
||||
severity: خطورة
|
||||
description: وصف
|
||||
resolve: حل
|
||||
exchange_products:
|
||||
load_more_products: "تحميل المزيد من المنتجات"
|
||||
load_all_products: "تحميل جميع المنتجات"
|
||||
select_all_products: "حدد جميع المنتجات %{total_number_of_products}"
|
||||
products_loaded: "%{num_of_products_loaded} من %{total_number_of_products} المنتجات المحملة"
|
||||
loading_products: "تحميل المنتجات"
|
||||
tag_rules:
|
||||
shipping_method_tagged_top: "طرق الشحن الموسومة"
|
||||
shipping_method_tagged_bottom: "هي:"
|
||||
@@ -2709,7 +2706,6 @@ ar:
|
||||
allow_ssl_in_development_and_test: "السماح باستخدام طبقة المقابس الآمنة SSL عندما تكون في أوضاع التطوير والاختبار"
|
||||
allow_ssl_in_production: "السماح باستخدام طبقة المقابس الآمنة في وضع الإنتاج"
|
||||
allow_ssl_in_staging: "اسمح باستخدام طبقة المقابس الآمنة في وضع التدريج"
|
||||
check_for_spree_alerts: "تحقق من وجود تنبيهات Spree"
|
||||
currency_decimal_mark: "العملة العشرية"
|
||||
currency_settings: "إعدادات العملة"
|
||||
currency_symbol_position: ضع "رمز العملة قبل أو بعد مبلغ الدولار؟"
|
||||
|
||||
@@ -2,6 +2,8 @@ ca:
|
||||
language_name: "Català"
|
||||
activerecord:
|
||||
attributes:
|
||||
enterprise_fee:
|
||||
fee_type: Tipus de comissió
|
||||
spree/order:
|
||||
payment_state: Estat del Pagament
|
||||
shipment_state: Estat de la Tramesa
|
||||
@@ -850,7 +852,6 @@ ca:
|
||||
save_and_back_to_list: "Desa i torna a la llista"
|
||||
choose_products_from: "Trieu Productes des de:"
|
||||
incoming:
|
||||
previous: "Anterior"
|
||||
save: "Desa"
|
||||
save_and_next: "Desa i següent"
|
||||
next: "Següent"
|
||||
@@ -989,9 +990,6 @@ ca:
|
||||
name: Consumidores
|
||||
products_and_inventory:
|
||||
name: Productes & Inventari
|
||||
sales_total:
|
||||
name: Total de vendes
|
||||
description: Total de vendes per a totes les comandes
|
||||
users_and_enterprises:
|
||||
name: Usuaris & Organitzacions
|
||||
description: Propietat i estatus de l'organització
|
||||
@@ -1130,15 +1128,6 @@ ca:
|
||||
selling_on_ofn: "Estàs interessat en formar part d'Open Food Network?"
|
||||
register: "Registra't aquí"
|
||||
footer:
|
||||
footer_global_headline: "OFN Global"
|
||||
footer_global_home: "Inici"
|
||||
footer_global_news: "Notícies"
|
||||
footer_global_about: "Sobre"
|
||||
footer_global_contact: "Contacte"
|
||||
footer_sites_headline: "Pàgines d'OFN"
|
||||
footer_sites_developer: "Desenvolupador"
|
||||
footer_sites_community: "Comunitat"
|
||||
footer_sites_userguide: "Guia de l'usuari"
|
||||
footer_secure: "Segur i de confiança."
|
||||
footer_secure_text: "Open Food Network utilitza el xifrat SSL (RSA de 2048 bits) a tot arreu per mantenir les vostres dades comercials i de pagament privades. Els nostres servidors no emmagatzemen els detalls de la targeta de crèdit i els pagaments es processen mitjançant serveis compatibles amb PCI."
|
||||
footer_contact_headline: "Mantén el contacte"
|
||||
@@ -2713,7 +2702,6 @@ ca:
|
||||
allow_ssl_in_development_and_test: "Permet que s'utilitzi SSL quan s'utilitzi el desenvolupament i els modes de prova"
|
||||
allow_ssl_in_production: "Permet que SSL s'utilitzi en mode de producció"
|
||||
allow_ssl_in_staging: "Permet que SSL s'utilitzi en mode de staging"
|
||||
check_for_spree_alerts: "Comproveu si hi ha alertes Spree"
|
||||
currency_decimal_mark: "Separador decimal de moneda"
|
||||
currency_settings: "Configuració de moneda"
|
||||
currency_symbol_position: Posa "símbol de moneda abans o després d'una quantitat"?
|
||||
|
||||
@@ -2,6 +2,8 @@ de_DE:
|
||||
language_name: "Deutsch"
|
||||
activerecord:
|
||||
attributes:
|
||||
enterprise_fee:
|
||||
fee_type: Art der Gebühr
|
||||
spree/order:
|
||||
payment_state: Zahlungsstatus
|
||||
shipment_state: Lieferstatus
|
||||
@@ -850,7 +852,6 @@ de_DE:
|
||||
save_and_back_to_list: "Speichern und zurück zur Liste"
|
||||
choose_products_from: "Wählen Sie Produkte von:"
|
||||
incoming:
|
||||
previous: "Bisherige"
|
||||
save: "Speichern"
|
||||
save_and_next: "Speichern und weiter"
|
||||
next: "Weiter"
|
||||
@@ -989,9 +990,6 @@ de_DE:
|
||||
name: Kunden
|
||||
products_and_inventory:
|
||||
name: Produkte und Katalog
|
||||
sales_total:
|
||||
name: Gesamtumsatz
|
||||
description: Gesamtumsatz für alle Bestellungen
|
||||
users_and_enterprises:
|
||||
name: Benutzer und Unternehmen
|
||||
description: Unternehmenseigentum & Status
|
||||
@@ -1130,15 +1128,6 @@ de_DE:
|
||||
selling_on_ofn: "Interesse am Open Food Network?"
|
||||
register: "Hier anmelden"
|
||||
footer:
|
||||
footer_global_headline: "OFN Global"
|
||||
footer_global_home: "Startseite"
|
||||
footer_global_news: "Aktuelles"
|
||||
footer_global_about: "Über Uns"
|
||||
footer_global_contact: "Kontakt"
|
||||
footer_sites_headline: "OFN Webseiten"
|
||||
footer_sites_developer: "Entwickler"
|
||||
footer_sites_community: "Community"
|
||||
footer_sites_userguide: "Benutzerhandbuch"
|
||||
footer_secure: "Sicher und vertrauenswürdig."
|
||||
footer_secure_text: "Open Food Network verwendet überall SSL-Verschlüsselung (2048 Bit RSA), um Ihre Einkaufs- und Zahlungsinformationen geheim zu halten. Unsere Server speichern Ihre Kreditkartendetails nicht und Zahlungen werden von PCI-konformen Dienstleistern verarbeitet."
|
||||
footer_contact_headline: "In Verbindung bleiben"
|
||||
@@ -2713,7 +2702,6 @@ de_DE:
|
||||
allow_ssl_in_development_and_test: "Erlauben Sie SSL in Entwicklungs- und Testmodi"
|
||||
allow_ssl_in_production: "Zulassen, dass SSL im Produktionsmodus verwendet wird"
|
||||
allow_ssl_in_staging: "Zulassen, dass SSL im Staging-Modus verwendet wird"
|
||||
check_for_spree_alerts: "Suchen Sie nach Spree-Benachrichtigungen"
|
||||
currency_decimal_mark: "Dezimalzeichen der Währung"
|
||||
currency_settings: "Währungseinstellungen"
|
||||
currency_symbol_position: Setzen Sie "Währungssymbol vor oder nach dem Dollarbetrag?"
|
||||
|
||||
@@ -23,6 +23,8 @@ en:
|
||||
language_name: "English" # Localised name of this language
|
||||
activerecord:
|
||||
attributes:
|
||||
enterprise_fee:
|
||||
fee_type: Fee Type
|
||||
spree/order:
|
||||
payment_state: Payment State
|
||||
shipment_state: Shipment State
|
||||
@@ -69,6 +71,8 @@ en:
|
||||
shipping_method_ids: "Shipping Methods"
|
||||
payment_method_ids: "Payment Methods"
|
||||
errors:
|
||||
messages:
|
||||
inclusion: "is not included in the list"
|
||||
models:
|
||||
subscription_validator:
|
||||
attributes:
|
||||
@@ -903,7 +907,6 @@ en:
|
||||
save_and_back_to_list: "Save and Back to List"
|
||||
choose_products_from: "Choose Products From:"
|
||||
incoming:
|
||||
previous: "Previous"
|
||||
save: "Save"
|
||||
save_and_next: "Save and Next"
|
||||
next: "Next"
|
||||
@@ -1046,9 +1049,6 @@ en:
|
||||
products_and_inventory:
|
||||
name: Products & Inventory
|
||||
description:
|
||||
sales_total:
|
||||
name: Sales Total
|
||||
description: Sales Total For All Orders
|
||||
users_and_enterprises:
|
||||
name: Users & Enterprises
|
||||
description: Enterprise Ownership & Status
|
||||
@@ -1169,6 +1169,8 @@ en:
|
||||
destroy_attachment_does_not_exist: "Logo does not exist"
|
||||
enterprise_promo_image:
|
||||
destroy_attachment_does_not_exist: "Promo image does not exist"
|
||||
orders:
|
||||
failed_to_update: "Failed to update order"
|
||||
|
||||
# Frontend views
|
||||
#
|
||||
@@ -1199,15 +1201,6 @@ en:
|
||||
selling_on_ofn: "Interested in getting on the Open Food Network?"
|
||||
register: "Register here"
|
||||
footer:
|
||||
footer_global_headline: "OFN Global"
|
||||
footer_global_home: "Home"
|
||||
footer_global_news: "News"
|
||||
footer_global_about: "About"
|
||||
footer_global_contact: "Contact"
|
||||
footer_sites_headline: "OFN Sites"
|
||||
footer_sites_developer: "Developer"
|
||||
footer_sites_community: "Community"
|
||||
footer_sites_userguide: "User Guide"
|
||||
footer_secure: "Secure and trusted."
|
||||
footer_secure_text: "Open Food Network uses SSL encryption (2048 bit RSA) everywhere to keep your shopping and payment information private. Our servers do not store your credit card details and payments are processed by PCI-compliant services."
|
||||
footer_contact_headline: "Keep in touch"
|
||||
@@ -2560,6 +2553,12 @@ See the %{link} to find out more about %{sitename}'s features and to start using
|
||||
severity: Severity
|
||||
description: Description
|
||||
resolve: Resolve
|
||||
exchange_products:
|
||||
load_more_products: "Load More Products"
|
||||
load_all_products: "Load All Products"
|
||||
select_all_products: "Select All %{total_number_of_products} Products"
|
||||
products_loaded: "%{num_of_products_loaded} of %{total_number_of_products} Products Loaded"
|
||||
loading_products: "Loading Products"
|
||||
tag_rules:
|
||||
shipping_method_tagged_top: "Shipping methods tagged"
|
||||
shipping_method_tagged_bottom: "are:"
|
||||
@@ -2851,7 +2850,6 @@ See the %{link} to find out more about %{sitename}'s features and to start using
|
||||
allow_ssl_in_development_and_test: "Allow SSL to be used when in development and test modes"
|
||||
allow_ssl_in_production: "Allow SSL to be used in production mode"
|
||||
allow_ssl_in_staging: "Allow SSL to be used in staging mode"
|
||||
check_for_spree_alerts: "Check for Spree alerts"
|
||||
currency_decimal_mark: "Currency decimal mark"
|
||||
currency_settings: "Currency Settings"
|
||||
currency_symbol_position: Put "currency symbol before or after dollar amount?"
|
||||
@@ -3073,6 +3071,7 @@ See the %{link} to find out more about %{sitename}'s features and to start using
|
||||
capture: "Capture"
|
||||
ship: "Ship"
|
||||
edit: "Edit"
|
||||
order_not_updated: "The order could not be updated"
|
||||
note: "Note"
|
||||
first: "First"
|
||||
last: "Last"
|
||||
|
||||
@@ -2,6 +2,8 @@ en_AU:
|
||||
language_name: "English"
|
||||
activerecord:
|
||||
attributes:
|
||||
enterprise_fee:
|
||||
fee_type: Fee Type
|
||||
spree/order:
|
||||
payment_state: Payment State
|
||||
shipment_state: Shipment State
|
||||
@@ -848,7 +850,6 @@ en_AU:
|
||||
save_and_back_to_list: "Save and Back to List"
|
||||
choose_products_from: "Choose Products From:"
|
||||
incoming:
|
||||
previous: "Previous"
|
||||
save: "Save"
|
||||
save_and_next: "Save and Next"
|
||||
next: "Next"
|
||||
@@ -987,9 +988,6 @@ en_AU:
|
||||
name: Customers
|
||||
products_and_inventory:
|
||||
name: Products & Inventory
|
||||
sales_total:
|
||||
name: Sales Total
|
||||
description: Sales Total For All Orders
|
||||
users_and_enterprises:
|
||||
name: Users & Enterprises
|
||||
description: Enterprise Ownership & Status
|
||||
@@ -1128,15 +1126,6 @@ en_AU:
|
||||
selling_on_ofn: "Interested in getting on the Open Food Network?"
|
||||
register: "Register here"
|
||||
footer:
|
||||
footer_global_headline: "OFN Global"
|
||||
footer_global_home: "Home"
|
||||
footer_global_news: "News"
|
||||
footer_global_about: "About"
|
||||
footer_global_contact: "Contact"
|
||||
footer_sites_headline: "OFN Sites"
|
||||
footer_sites_developer: "Developer"
|
||||
footer_sites_community: "Community"
|
||||
footer_sites_userguide: "User Guide"
|
||||
footer_secure: "Secure and trusted."
|
||||
footer_secure_text: "Open Food Network uses SSL encryption (2048 bit RSA) everywhere to keep your shopping and payment information private. Our servers do not store your credit card details and payments are processed by PCI-compliant services."
|
||||
footer_contact_headline: "Keep in touch"
|
||||
@@ -1603,11 +1592,11 @@ en_AU:
|
||||
producers_signup_title: Sign up as a producer
|
||||
producers_signup_headline: Food producers, empowered.
|
||||
producers_signup_motivation: Sell your food and tell your stories to diverse new markets. Save time and money on every overhead. We support innovation without the risk. We've levelled the playing field.
|
||||
producers_signup_send: Join now
|
||||
producers_signup_send: Register
|
||||
producers_signup_enterprise: Enterprise Accounts
|
||||
producers_signup_studies: Stories from our producers.
|
||||
producers_signup_cta_headline: Join now!
|
||||
producers_signup_cta_action: Join now
|
||||
producers_signup_cta_action: Register
|
||||
producers_signup_detail: Here's the detail.
|
||||
products_item: Item
|
||||
products_description: Description
|
||||
@@ -1637,7 +1626,7 @@ en_AU:
|
||||
shops_signup_title: Sign up as a hub
|
||||
shops_signup_headline: Food hubs, unlimited.
|
||||
shops_signup_motivation: Whatever your model, we support you. However you change, we're with you. We're non-profit, independent, and open-sourced. We're the software partners you've dreamed of.
|
||||
shops_signup_action: Join now
|
||||
shops_signup_action: Register
|
||||
shops_signup_pricing: Enterprise Accounts
|
||||
shops_signup_stories: Stories from our hubs.
|
||||
shops_signup_help: We're ready to help.
|
||||
@@ -1858,7 +1847,7 @@ en_AU:
|
||||
finished:
|
||||
headline: "Finished!"
|
||||
thanks: "Thanks for filling out the details for %{enterprise}."
|
||||
login: "You can change or update your enterprise at any stage by logging into Open Food Network and going to Admin."
|
||||
login: "To manage your new Enterprise, go to openfoodnetwork.org.au/admin"
|
||||
action: "Open Food Network home"
|
||||
back: "Back"
|
||||
continue: "Continue"
|
||||
@@ -2708,7 +2697,6 @@ en_AU:
|
||||
allow_ssl_in_development_and_test: "Allow SSL to be used when in development and test modes"
|
||||
allow_ssl_in_production: "Allow SSL to be used in production mode"
|
||||
allow_ssl_in_staging: "Allow SSL to be used in staging mode"
|
||||
check_for_spree_alerts: "Check for Spree alerts"
|
||||
currency_decimal_mark: "Currency decimal mark"
|
||||
currency_settings: "Currency Settings"
|
||||
currency_symbol_position: Put "currency symbol before or after dollar amount?"
|
||||
|
||||
@@ -2,6 +2,8 @@ en_BE:
|
||||
language_name: "English"
|
||||
activerecord:
|
||||
attributes:
|
||||
enterprise_fee:
|
||||
fee_type: Fee Type
|
||||
spree/order:
|
||||
payment_state: Payment State
|
||||
shipment_state: Shipment State
|
||||
@@ -833,7 +835,6 @@ en_BE:
|
||||
cancel: "Cancel"
|
||||
choose_products_from: "Choose Products From:"
|
||||
incoming:
|
||||
previous: "Previous"
|
||||
save: "Save"
|
||||
next: "Next"
|
||||
cancel: "Cancel"
|
||||
@@ -964,9 +965,6 @@ en_BE:
|
||||
name: Customers
|
||||
products_and_inventory:
|
||||
name: Products & Inventory
|
||||
sales_total:
|
||||
name: Sales Total
|
||||
description: Sales Total For All Orders
|
||||
users_and_enterprises:
|
||||
name: Users & Enterprises
|
||||
description: Enterprise Ownership & Status
|
||||
@@ -1103,15 +1101,6 @@ en_BE:
|
||||
selling_on_ofn: "Interested in getting on the Open Food Network?"
|
||||
register: "Register here"
|
||||
footer:
|
||||
footer_global_headline: "OFN Global"
|
||||
footer_global_home: "Home"
|
||||
footer_global_news: "News"
|
||||
footer_global_about: "About"
|
||||
footer_global_contact: "Contact"
|
||||
footer_sites_headline: "OFN Sites"
|
||||
footer_sites_developer: "Developer"
|
||||
footer_sites_community: "Community"
|
||||
footer_sites_userguide: "User Guide"
|
||||
footer_secure: "Secure and trusted."
|
||||
footer_secure_text: "Open Food Network uses SSL encryption (2048 bit RSA) everywhere to keep your shopping and payment information private. Our servers do not store your credit card details and payments are processed by PCI-compliant services."
|
||||
footer_contact_headline: "Keep in touch"
|
||||
@@ -2681,7 +2670,6 @@ en_BE:
|
||||
allow_ssl_in_development_and_test: "Allow SSL to be used when in development and test modes"
|
||||
allow_ssl_in_production: "Allow SSL to be used in production mode"
|
||||
allow_ssl_in_staging: "Allow SSL to be used in staging mode"
|
||||
check_for_spree_alerts: "Check for Spree alerts"
|
||||
currency_decimal_mark: "Currency decimal mark"
|
||||
currency_settings: "Currency Settings"
|
||||
currency_symbol_position: Put "currency symbol before or after euros amount?"
|
||||
|
||||
@@ -2,6 +2,8 @@ en_CA:
|
||||
language_name: "English"
|
||||
activerecord:
|
||||
attributes:
|
||||
enterprise_fee:
|
||||
fee_type: Fee Type
|
||||
spree/order:
|
||||
payment_state: Payment State
|
||||
shipment_state: Shipment State
|
||||
@@ -48,6 +50,8 @@ en_CA:
|
||||
shipping_method_ids: "Shipping Methods"
|
||||
payment_method_ids: "Payment Methods"
|
||||
errors:
|
||||
messages:
|
||||
inclusion: "is not included in the list"
|
||||
models:
|
||||
subscription_validator:
|
||||
attributes:
|
||||
@@ -117,7 +121,7 @@ en_CA:
|
||||
userguide: "Open Food Network User Guide"
|
||||
email_admin_html: "You can manage your account by logging into the %{link} or by clicking on the cog in the top right hand side of the homepage, and selecting Administration."
|
||||
admin_panel: "Admin Panel"
|
||||
email_community_html: "We also have an online forum for community discussion related to OFN software and the unique challenges of running a food enterprise. You are encouraged to join in. We are constantly evolving and your input into this forum will shape what happens next. %{link}"
|
||||
email_community_html: "We also have an online forum for community discussion related to OFN software and the unique challenges of tech-enabling local enterprises. You are encouraged to join in. We are constantly evolving and your input into this forum will shape what happens next. %{link}"
|
||||
join_community: "Join the community"
|
||||
invite_manager:
|
||||
subject: "%{enterprise} has invited you to be a manager"
|
||||
@@ -612,7 +616,7 @@ en_CA:
|
||||
name: Name
|
||||
name_placeholder: eg. Gustav Plum
|
||||
email_address: Public Email Address
|
||||
email_address_placeholder: eg. inquiries@fresh-food.com
|
||||
email_address_placeholder: eg. inquiries@localproducts.com
|
||||
email_address_tip: "This email address will be displayed in your public profile"
|
||||
phone: Phone
|
||||
phone_placeholder: eg. 519 885 8888
|
||||
@@ -654,7 +658,7 @@ en_CA:
|
||||
groups_tip: Select any groups or regions that you are a member of. This will help customers find your enterprise.
|
||||
groups_placeholder: Start typing to search available groups...
|
||||
primary_producer: Primary Producer?
|
||||
primary_producer_tip: Select 'Producer' if you are a primary producer of food.
|
||||
primary_producer_tip: Select 'Producer' if you are a primary producer, grower, maker or designer
|
||||
producer: Producer
|
||||
any: Any
|
||||
none: None
|
||||
@@ -778,18 +782,18 @@ en_CA:
|
||||
always_free: ALWAYS FREE
|
||||
producer_description_text: Add your products to Open Food Network, allowing hubs to stock your products in their stores.
|
||||
producer_shop: Producer Shop
|
||||
sell_your_produce: Sell your own produce
|
||||
sell_your_produce: Sell your own products
|
||||
producer_shop_description_text: Sell your products directly to customers through your very own Open Food Network shopfront.
|
||||
producer_shop_description_text2: A Producer Shop is for your produce only, if you want to sell produce grown/produced off site, select 'Producer Hub'.
|
||||
producer_shop_description_text2: A Producer Shop is for your products only, if you want to sell producyd grown/produced off site, select 'Producer Hub'.
|
||||
producer_hub: Producer Hub
|
||||
producer_hub_text: Sell produce from self and others
|
||||
producer_hub_description_text: Your enterprise is the backbone of your local food system. You can sell your own produce as well as produce aggregated from other enterprises through your shopfront on the Open Food Network.
|
||||
producer_hub_text: Sell products from self and others
|
||||
producer_hub_description_text: Your enterprise is the backbone of your local food system. You can sell your own products as well as products aggregated from other enterprises through your shopfront on the Open Food Network.
|
||||
profile: Profile Only
|
||||
get_listing: Get a listing
|
||||
profile_description_text: People can find and contact you on the Open Food Network. Your enterprise will be visible on the map, and will be searchable in listings.
|
||||
hub_shop: Hub Shop
|
||||
hub_shop_text: Sell produce from others
|
||||
hub_shop_description_text: Your enterprise is the backbone of your local food system. You aggregate produce from other enterprises and can sell it through your shop on the Open Food Network.
|
||||
hub_shop_text: Sell products from others
|
||||
hub_shop_description_text: Your enterprise is the backbone of your local community. You aggregate products from other enterprises and can sell them through your shop on the Open Food Network.
|
||||
choose_option: Please choose one of the options above.
|
||||
change_now: Change now
|
||||
enterprise_user_index:
|
||||
@@ -848,7 +852,6 @@ en_CA:
|
||||
save_and_back_to_list: "Save and Back to List"
|
||||
choose_products_from: "Choose Products From:"
|
||||
incoming:
|
||||
previous: "Previous"
|
||||
save: "Save"
|
||||
save_and_next: "Save and Next"
|
||||
next: "Next"
|
||||
@@ -987,9 +990,6 @@ en_CA:
|
||||
name: Customers
|
||||
products_and_inventory:
|
||||
name: Products & Inventory
|
||||
sales_total:
|
||||
name: Sales Total
|
||||
description: Sales Total For All Orders
|
||||
users_and_enterprises:
|
||||
name: Users & Enterprises
|
||||
description: Enterprise Ownership & Status
|
||||
@@ -1104,6 +1104,8 @@ en_CA:
|
||||
destroy_attachment_does_not_exist: "Logo does not exist"
|
||||
enterprise_promo_image:
|
||||
destroy_attachment_does_not_exist: "Promo image does not exist"
|
||||
orders:
|
||||
failed_to_update: "Failed to update order"
|
||||
checkout:
|
||||
already_ordered:
|
||||
cart: "cart"
|
||||
@@ -1128,15 +1130,6 @@ en_CA:
|
||||
selling_on_ofn: "Interested in getting on the Open Food Network?"
|
||||
register: "Register here"
|
||||
footer:
|
||||
footer_global_headline: "OFN Global"
|
||||
footer_global_home: "Home"
|
||||
footer_global_news: "News"
|
||||
footer_global_about: "About"
|
||||
footer_global_contact: "Contact"
|
||||
footer_sites_headline: "OFN Sites"
|
||||
footer_sites_developer: "Developer"
|
||||
footer_sites_community: "Community"
|
||||
footer_sites_userguide: "User Guide"
|
||||
footer_secure: "Secure and trusted."
|
||||
footer_secure_text: "Open Food Network uses SSL encryption (2048 bit RSA) everywhere to keep your shopping and payment information private. Our servers do not store your credit card details and payments are processed by PCI-compliant services."
|
||||
footer_contact_headline: "Keep in touch"
|
||||
@@ -1297,7 +1290,7 @@ en_CA:
|
||||
cookies_policy:
|
||||
header: "How We Use Cookies"
|
||||
desc_part_1: "Cookies are very small text files that are stored on your computer when you visit some websites."
|
||||
desc_part_2: "In OFN we are fully respectful of your privacy. We use only the cookies that are necessary for delivering you the service of selling/buying food online. We don’t sell any of your data. We might in the future propose you to share some of your data to build new commons services that could be useful for the ecosystem (like logistics services for short food systems) but we are not yet there, and we won’t do it without your authorization :-)"
|
||||
desc_part_2: "In OFN we are fully respectful of your privacy. We use only the cookies that are necessary for delivering you the service of selling/buying products online. We don’t sell any of your data. We might in the future propose you to share some of your data to build new commons services that could be useful for the ecosystem (like logistics or local delivery services) but we are not yet there, and we won’t do it without your authorization :-)"
|
||||
desc_part_3: "We use cookies mainly to remember who you are if you 'log in' to the service, or to be able to remember the items you put in your cart even if you are not logged in. If you keep navigating on the website without clicking on “Accept cookies”, we assume you are giving us consent to store the cookies that are essential for the functioning of the website. Here is the list of cookies we use!"
|
||||
essential_cookies: "Essential Cookies"
|
||||
essential_cookies_desc: "The following cookies are strictly necessary for the operation of our website."
|
||||
@@ -1331,7 +1324,7 @@ en_CA:
|
||||
cookies_banner:
|
||||
cookies_usage: "This site uses cookies in order to make your navigation frictionless and secure, and to help us understand how you use it in order to improve the features we offer."
|
||||
cookies_definition: "Cookies are very small text files that are stored on your computer when you visit some websites."
|
||||
cookies_desc: "We use only the cookies that are necessary for delivering you the service of selling/buying food online. We don’t sell any of your data. We use cookies mainly to remember who you are if you ‘log in’ to the service, or to be able to remember the items you put in your cart even if you are not logged in. If you keep navigating on the website without clicking on “Accept cookies”, we assume you are giving us consent to store the cookies that are essential for the functioning of the website."
|
||||
cookies_desc: "We use only the cookies that are necessary for delivering you the service of selling/buying products online. We don’t sell any of your data. We use cookies mainly to remember who you are if you ‘log in’ to the service, or to be able to remember the items you put in your cart even if you are not logged in. If you keep navigating on the website without clicking on “Accept cookies”, we assume you are giving us consent to store the cookies that are essential for the functioning of the website."
|
||||
cookies_policy_link_desc: "If you want to learn more, check our"
|
||||
cookies_policy_link: "cookies policy"
|
||||
cookies_accept_button: "Accept Cookies"
|
||||
@@ -1339,29 +1332,29 @@ en_CA:
|
||||
brandstory_headline: "Food, unincorporated."
|
||||
brandstory_intro: "Sometimes the best way to fix the system is to start a new one…"
|
||||
brandstory_part1: "We begin from the ground up. With farmers and growers ready to tell their stories proudly and truly. With distributors ready to connect people with products fairly and honestly. With buyers who believe that better weekly shopping decisions can seriously change the world."
|
||||
brandstory_part2: "Then we need a way to make it real. A way to empower everyone who grows, sells and buys food. A way to tell all the stories, to handle all the logistics. A way to turn transaction into transformation every day."
|
||||
brandstory_part2: "Then we need a way to make it real. A way to empower everyone who makes, grows, sells and buys local sustainable products. A way to tell all the stories, to handle all the logistics. A way to turn transaction into transformation every day."
|
||||
brandstory_part3: "So we build an online marketplace that levels the playing field. It’s transparent, so it creates real relationships. It’s open source, so it’s owned by everyone. It scales to regions and nations, so people start versions across the world."
|
||||
brandstory_part4: "It works everywhere. It changes everything."
|
||||
brandstory_part5_strong: "We call it Open Food Network."
|
||||
brandstory_part6: "We all love food. Now we can love our food system too."
|
||||
learn_body: "Explore models, stories and resources to support you to develop your fair food business or organisation. Find training, events and other opportunities to learn from peers."
|
||||
learn_body: "Explore models, stories and resources to support you to develop your local business or organisation. Find training, events and other opportunities to learn from peers."
|
||||
learn_cta: "Get Inspired"
|
||||
connect_body: "Search our full directories of producers, hubs and groups to find fair food traders near you. List your business or organisation on the OFN so buyers can find you. Join the community to get advice and solve problems together."
|
||||
connect_body: "Search our full directories of producers, hubs and groups to find fair and sustainably produced products near you. List your business or organisation on the OFN so buyers can find you. Join the community to get advice and solve problems together."
|
||||
connect_cta: "Go Exploring"
|
||||
system_headline: "Shopping - here's how it works."
|
||||
system_step1: "1. Search"
|
||||
system_step1_text: "Search our diverse, independent shops for seasonal local food. Search by neighbourhood and food category, or whether you prefer delivery or pickup."
|
||||
system_step1_text: "Search our diverse, independent shops for seasonal, sustainably produced products locally. Search by neighbourhood and food category, or whether you prefer delivery or pickup."
|
||||
system_step2: "2. Shop"
|
||||
system_step2_text: "Transform your transactions with affordable local food from diverse producers and hubs. Know the stories behind your food and the people who make it!"
|
||||
system_step2_text: "Transform your transactions with affordable local products from diverse producers, makers and hubs. Know the stories behind their products and the people who make them!"
|
||||
system_step3: "3. Pick-up / Delivery"
|
||||
system_step3_text: "Hang on for your delivery, or visit your producer or hub for a more personal connection with your food. Food shopping as diverse as nature intended it."
|
||||
system_step3_text: "Hang on for your delivery, or connect with the producer, maker or artisan directly. Shopping as diverse as nature intended it."
|
||||
cta_headline: "Shopping that makes the world a better place."
|
||||
cta_label: "I'm Ready"
|
||||
stats_headline: "We're creating a new food system."
|
||||
stats_producers: "food producers"
|
||||
stats_shops: "food shops"
|
||||
stats_shoppers: "food shoppers"
|
||||
stats_orders: "food orders"
|
||||
stats_producers: "producers"
|
||||
stats_shops: "shops"
|
||||
stats_shoppers: "shoppers"
|
||||
stats_orders: "orders"
|
||||
checkout_title: Checkout
|
||||
checkout_now: Checkout now
|
||||
checkout_order_ready: Order ready for
|
||||
@@ -1397,7 +1390,7 @@ en_CA:
|
||||
order_special_instructions: "Your notes:"
|
||||
order_pickup_time: Ready for collection
|
||||
order_pickup_instructions: Collection Instructions
|
||||
order_produce: Produce
|
||||
order_produce: Subtotal
|
||||
order_total_price: Total
|
||||
order_includes_tax: (includes tax)
|
||||
order_payment_paypal_successful: Your payment via PayPal has been processed successfully.
|
||||
@@ -1471,7 +1464,7 @@ en_CA:
|
||||
email_signup_welcome: "Welcome to %{sitename}!"
|
||||
email_signup_confirmed_email: "Thanks for confirming your email."
|
||||
email_signup_shop_html: "You can now log in at %{link}."
|
||||
email_signup_text: "Thanks for joining the network. If you are a customer, we look forward to introducing you to many fantastic farmers, wonderful food hubs and delicious food! If you are a producer or food enterprise, we are excited to have you as a part of the network."
|
||||
email_signup_text: "Thanks for joining the network. If you are a customer, we look forward to introducing you to many fantastic growers, artisans and makers, and wonderful hubs and marketplaces. If you are a grower, artisan or maker we are excited to have you as a part of the network."
|
||||
email_signup_help_html: "We welcome all your questions and feedback; you can use the <em>Send Feedback</em> button on the site or email us at %{email}"
|
||||
invite_email:
|
||||
greeting: "Hello!"
|
||||
@@ -1562,9 +1555,9 @@ en_CA:
|
||||
groups_signup_motivation2: It's why we get out of bed every day. We're a global non-profit, based on open source code. We play fair. You can always trust us.
|
||||
groups_signup_motivation3: We know you have big ideas, and we want to help. We'll share our knowledge, networks and resources. We know that isolation doesn't create change, so we'll partner with you.
|
||||
groups_signup_motivation4: We meet you where you are.
|
||||
groups_signup_motivation5: You might be an alliance of food hubs, producers, or distributors, and an industry body, or a local government.
|
||||
groups_signup_motivation6: Whatever your role in your local food movement, we're ready to help. However you come to wonder what Open Food Network would look like or is doing in your part of the world, let's start the conversation.
|
||||
groups_signup_motivation7: We make food movements make more sense.
|
||||
groups_signup_motivation5: You might be an alliance of food hubs or initiatives, a local flower marketplace, a network of makers or crafters, a food re-distribution network, an industry body, or a local government.
|
||||
groups_signup_motivation6: Whatever your role in supporting sustainable production and fair distribution we're ready to help. However you come to wonder what Open Food Network would look like or is doing in your part of the world, let's start the conversation.
|
||||
groups_signup_motivation7: We make local food and artisanal food movements make more sense.
|
||||
groups_signup_motivation8: You need to activate and enable your networks, we offer a platform for conversation and action. You need real engagement. We’ll help reach all the players, all the stakeholders, all the sectors.
|
||||
groups_signup_motivation9: You need resourcing. We’ll bring all our experience to bear. You need cooperation. We’ll better connect you to a global network of peers.
|
||||
groups_signup_pricing: Group Account
|
||||
@@ -1573,22 +1566,22 @@ en_CA:
|
||||
groups_signup_contact_text: "Get in touch to discover what OFN can do for you:"
|
||||
groups_signup_detail: "Here's the detail."
|
||||
login_invalid: "Invalid email or password"
|
||||
modal_hubs: "Food Hubs"
|
||||
modal_hubs_abstract: Our food hubs are the point of contact between you and the people who make your food!
|
||||
modal_hubs_content1: You can search for a convenient hub by location or name. Some hubs have multiple points where you can pick-up your purchases, and some will also provide delivery options. Each food hub is a sales point with independent business operations and logistics - so variations between hubs are to be expected.
|
||||
modal_hubs_content2: You can only shop at one food hub at a time.
|
||||
modal_hubs: "Hubs"
|
||||
modal_hubs_abstract: Our hubs are the point of contact between you and the people who grow & make local sustainable things!
|
||||
modal_hubs_content1: You can search for a convenient hub by location or name. Some hubs have multiple points where you can pick-up your purchases, and some will also provide delivery options. Each fhub is a sales/distribution point with independent operations and logistics - so variations between hubs are to be expected.
|
||||
modal_hubs_content2: You can only shop at one hub at a time.
|
||||
modal_groups: "Groups / Regions"
|
||||
modal_groups_content1: These are the organisations and relationships between hubs which make up the Open Food Network.
|
||||
modal_groups_content2: Some groups are clustered by location or council, others by non-geographic similarities.
|
||||
modal_how: "How it works"
|
||||
modal_how_shop: Shop the Open Food Network
|
||||
modal_how_shop_explained: Search for a food hub near you to start shopping! You can expand each food hub to see what kinds of goodies are available, and click through to start shopping. (You can only shop one food hub at a time.)
|
||||
modal_how_shop_explained: Search for a hub near you to start shopping! You can expand each hub to see what kinds of products are available, and click through to start. (You can only shop one hub at a time.)
|
||||
modal_how_pickup: Pick-ups, delivery and shipping costs
|
||||
modal_how_pickup_explained: Some food hubs deliver to your door, while others require you to pick-up your purchases. You can see which options are available on the homepage, and select which you'd like at the shopping and check-out pages. Delivery will cost more, and pricing differs from hub-to-hub. Each food hub is a sales point with independent business operations and logisitics - so variations between hubs are to be expected.
|
||||
modal_how_pickup_explained: Some hubs deliver to your door, while others require you to pick-up your purchases. You can see which options are available on the homepage, and select which you'd like at the shopping and check-out pages. Delivery will cost more, and pricing differs from hub-to-hub. Each hub is a sales point with independent operations and logisitics - so variations between hubs are to be expected.
|
||||
modal_how_more: Learn more
|
||||
modal_how_more_explained: "If you want to learn more about the Open Food Network, how it works, and get involved, check out:"
|
||||
modal_producers: "Producers"
|
||||
modal_producers_explained: "Our producers make all the delicious food you can shop for on the Open Food Network."
|
||||
modal_producers_explained: "Our producers make things you can shop for on the Open Food Network."
|
||||
producers_about: About us
|
||||
producers_buy: Shop for
|
||||
producers_contact: Contact
|
||||
@@ -1601,8 +1594,8 @@ en_CA:
|
||||
producers_title: Producers
|
||||
producers_headline: Find local producers
|
||||
producers_signup_title: Sign up as a producer
|
||||
producers_signup_headline: Food producers, empowered.
|
||||
producers_signup_motivation: Sell your food and tell your stories to diverse new markets. Save time and money on every overhead. We support innovation without the risk. We've levelled the playing field.
|
||||
producers_signup_headline: Producers & makers, empowered.
|
||||
producers_signup_motivation: Sell your products and tell your stories to diverse new markets. Save time and money on every overhead. We support innovation without the risk. We've levelled the playing field.
|
||||
producers_signup_send: Join now
|
||||
producers_signup_enterprise: Enterprise Accounts
|
||||
producers_signup_studies: Stories from our producers.
|
||||
@@ -1620,22 +1613,22 @@ en_CA:
|
||||
register_title: Register
|
||||
sell_title: "Register"
|
||||
sell_headline: "Get on the Open Food Network!"
|
||||
sell_motivation: "Showcase your beautiful food."
|
||||
sell_motivation: "Showcase your beautiful products."
|
||||
sell_producers: "Producers"
|
||||
sell_hubs: "Hubs"
|
||||
sell_groups: "Groups"
|
||||
sell_producers_detail: "Set up a profile for your business on the OFN in just minutes. At any time you can upgrade your profile to an online store and sell your products direct to customers."
|
||||
sell_hubs_detail: "Set up a profile for your food enterprise or organisation on the OFN. At any time you can upgrade your profile to a multi-producer shop."
|
||||
sell_groups_detail: "Set up a tailored directory of enterprises (producers and other food enterprises) for your region or for your organisation."
|
||||
sell_hubs_detail: "Set up a profile for your enterprise or organisation on the OFN. At any time you can upgrade your profile to a multi-producer shop."
|
||||
sell_groups_detail: "Set up a tailored directory of enterprises (producers and other local enterprises) for your region or for your organisation."
|
||||
sell_user_guide: "Find out more in our user guide."
|
||||
sell_listing_price: "Listing on the OFN is free. Opening and running a shop on OFN is free up to $500 of monthly sales. If you sell more we will invoice you for 2% of sales to a maximum of $150/month. For more detail on pricing visit the Software Platform section via the About link in the top menu."
|
||||
sell_embed: "We can also embed an OFN shop in your own customised website or build a customised local food network website for your region."
|
||||
sell_ask_services: "Ask us about OFN services."
|
||||
shops_title: Shops
|
||||
shops_headline: Shopping, transformed.
|
||||
shops_text: Food grows in cycles, farmers harvest in cycles, and we order food in cycles. If you find an order cycle closed, check back soon.
|
||||
shops_text: Products grow and are made in cycles so we order these products in cycles. If you find an order cycle closed, check back soon.
|
||||
shops_signup_title: Sign up as a hub
|
||||
shops_signup_headline: Food hubs, unlimited.
|
||||
shops_signup_headline: Hubs & Markeplaces, unlimited.
|
||||
shops_signup_motivation: Whatever your model, we support you. However you change, we're with you. We're non-profit, independent, and open-sourced. We're the software partners you've dreamed of.
|
||||
shops_signup_action: Join now
|
||||
shops_signup_pricing: Enterprise Accounts
|
||||
@@ -1651,7 +1644,7 @@ en_CA:
|
||||
orders_edit_continue: Continue shopping
|
||||
orders_edit_checkout: Checkout
|
||||
orders_form_empty_cart: "Empty cart"
|
||||
orders_form_subtotal: Produce subtotal
|
||||
orders_form_subtotal: Subtotal
|
||||
orders_form_admin: Admin & Handling
|
||||
orders_form_total: Total
|
||||
orders_oc_expired_headline: Orders have closed for this order cycle
|
||||
@@ -1794,8 +1787,8 @@ en_CA:
|
||||
yes_producer: "Yes, I'm a producer"
|
||||
no_producer: "No, I'm not a producer"
|
||||
producer_field_error: "Please choose one. Are you are producer?"
|
||||
yes_producer_help: "Producers make yummy things to eat and/or drink. You're a producer if you grow it, raise it, brew it, bake it, ferment it, milk it or mould it."
|
||||
no_producer_help: "If you’re not a producer, you’re probably someone who sells and distributes food. You might be a hub, coop, buying group, retailer, wholesaler or other."
|
||||
yes_producer_help: "Producers make things. You're a producer if you make it, grow it, raise it, brew it, bake it, ferment it, milk it, mould it or design it."
|
||||
no_producer_help: "If you’re not a producer, you’re probably someone who sells and distributes the things they produce or make. You might be a hub, coop, buying group, retailer, wholesaler or other."
|
||||
create_profile: "Create Profile"
|
||||
about:
|
||||
title: "About"
|
||||
@@ -2092,14 +2085,14 @@ en_CA:
|
||||
report_header_ship_street_2: Ship Street 2
|
||||
report_header_ship_city: Ship City
|
||||
report_header_ship_postcode: Ship Postal Code
|
||||
report_header_ship_state: Ship State
|
||||
report_header_ship_state: Ship Province
|
||||
report_header_billing_street: Billing Street
|
||||
report_header_billing_street_2: Billing Street 2
|
||||
report_header_billing_street_3: Billing Street 3
|
||||
report_header_billing_street_4: Billing Street 4
|
||||
report_header_billing_city: Billing City
|
||||
report_header_billing_postcode: Billing Postal Code
|
||||
report_header_billing_state: Billing State
|
||||
report_header_billing_state: Billing Province
|
||||
report_header_incoming_transport: Incoming Transport
|
||||
report_header_special_instructions: Special Instructions
|
||||
report_header_order_number: Order number
|
||||
@@ -2192,7 +2185,7 @@ en_CA:
|
||||
report_header_not_confirmed: Not Confirmed
|
||||
report_header_gst_on_income: Sales Tax on Income
|
||||
report_header_gst_free_income: Tax Free Income
|
||||
report_header_total_untaxable_produce: Total untaxable produce (no tax)
|
||||
report_header_total_untaxable_produce: Total untaxable products (no tax)
|
||||
report_header_total_taxable_produce: Total taxable produce (tax inclusive)
|
||||
report_header_total_untaxable_fees: Total untaxable fees (no tax)
|
||||
report_header_total_taxable_fees: Total taxable fees (tax inclusive)
|
||||
@@ -2344,16 +2337,16 @@ en_CA:
|
||||
People can find and contact you on the Open Food Network. Your enterprise
|
||||
will be visible on the map, and will be searchable in listings.
|
||||
hub_profile_text2: >
|
||||
Having a profile, and making connections within your local food system
|
||||
through the Open Food Network will always be free.
|
||||
Having a profile, and making connections within your local networks
|
||||
and communities through the Open Food Network will always be free.
|
||||
hub_shop: Hub Shop
|
||||
hub_shop_text1: >
|
||||
Your enterprise is the backbone of your local food system. You aggregate
|
||||
produce from other enterprises and can sell it through your shop on
|
||||
Your enterprise is the backbone of your local community. You aggregate
|
||||
products from other enterprises and sell them through your shop on
|
||||
the Open Food Network.
|
||||
hub_shop_text2: >
|
||||
Hubs can take many forms, whether they be a food co-op, a buying group,
|
||||
a veggie-box program, or a local grocery store.
|
||||
Hubs can take many forms - a local co-op, a buying group, a food-box
|
||||
program, or an on-line markeplace for crafts or flowers....
|
||||
hub_shop_text3: >
|
||||
If you also want to sell your own products, you will need to switch
|
||||
this enterprise to be a producer.
|
||||
@@ -2370,9 +2363,9 @@ en_CA:
|
||||
A profile makes you visible and contactable to others and is a way to
|
||||
share your story.
|
||||
profile_only_text2: >
|
||||
If you prefer to focus on producing food, and want to leave the work
|
||||
of selling it to someone else, you won't require a shop on the Open
|
||||
Food Network.
|
||||
If you prefer to focus on producing, designing and making, and want
|
||||
to leave the work of selling it to someone else, you won't require a
|
||||
shop on the Open Food Network.
|
||||
profile_only_text3: >
|
||||
Add your products to Open Food Network, allowing hubs to stock your
|
||||
products in their stores.
|
||||
@@ -2381,51 +2374,56 @@ en_CA:
|
||||
Sell your products directly to customers through your very own Open
|
||||
Food Network shopfront.
|
||||
producer_shop_text2: >
|
||||
A Producer Shop is for your produce only, if you want to sell produce
|
||||
grown/produced off site, please select 'Producer Hub'.
|
||||
A Producer Shop is for your products only, if you want to sell products
|
||||
grown/made/created off site, please select 'Producer Hub'.
|
||||
producer_hub: Producer Hub
|
||||
producer_hub_text1: >
|
||||
Your enterprise is the backbone of your local food system. You can sell
|
||||
your own produce as well as produce aggregated from other enterprises
|
||||
Your enterprise is the backbone of your local community. You can sell
|
||||
your own products as well as products aggregated from other enterprises
|
||||
through your shopfront on the Open Food Network.
|
||||
producer_hub_text2: >
|
||||
Producer Hubs can take many forms, whether they be a CSA, a veggie-box
|
||||
program, or a food co-op with a rooftop garden.
|
||||
Producer Hubs can take many forms, whether they be a CSA, a food box
|
||||
program, a co-op, cut flower marketplace.....
|
||||
producer_hub_text3: >
|
||||
The Open Food Network aims to support as many hub models as possible,
|
||||
so no matter your situation, we want to provide the tools you need to
|
||||
run your organisation or local food business.
|
||||
get_listing: Get a listing
|
||||
always_free: ALWAYS FREE
|
||||
sell_produce_others: Sell produce from others
|
||||
sell_own_produce: Sell your own produce
|
||||
sell_both: Sell produce from self and others
|
||||
sell_produce_others: Sell products from others
|
||||
sell_own_produce: Sell your own products
|
||||
sell_both: Sell products from self and others
|
||||
enterprise_producer:
|
||||
producer: Producer
|
||||
producer_text1: >
|
||||
Producers make yummy things to eat or drink. You're a producer if you
|
||||
grow it, raise it, brew it, bake it, ferment it, milk it or mould it.
|
||||
Producers make things. You're a producer if you make it, grow it, raise
|
||||
it, brew it, bake it, ferment it, milk it, mould it, design it.....
|
||||
producer_text2: >
|
||||
Producers can also perform other functions, such as aggregating food
|
||||
from other enterprises and selling it through a shop on the Open Food
|
||||
Producers can also perform other functions, such as aggregating products
|
||||
from other enterprises and selling them through a shop on the Open Food
|
||||
Network.
|
||||
non_producer: Non-producer
|
||||
non_producer_text1: >
|
||||
Non-producers do not produce any food themselves, meaning that they
|
||||
Non-producers do not produce any products themselves, meaning that they
|
||||
cannot create their own products for sale through the Open Food Network.
|
||||
non_producer_text2: >
|
||||
Instead, non-producers specialise in linking producers to the end eater,
|
||||
whether it be by aggregating, grading, packing, selling or delivering
|
||||
food.
|
||||
producer_desc: Producers of food
|
||||
Instead, non-producers specialise in linking producers and their products
|
||||
to the end buyer/user, by aggregating, packing, selling or distributing.
|
||||
producer_desc: 'Producers '
|
||||
producer_example: eg. GROWERS, BAKERS, BREWERS, MAKERS
|
||||
non_producer_desc: All other food enterprises
|
||||
non_producer_example: eg. Grocery stores, Food co-ops, Buying groups
|
||||
non_producer_desc: All other enterprises
|
||||
non_producer_example: eg. Grocery stores, Co-ops, Buying groups, Markets
|
||||
enterprise_status:
|
||||
status_title: "%{name} is set up and ready to go!"
|
||||
severity: Severity
|
||||
description: Description
|
||||
resolve: Resolve
|
||||
exchange_products:
|
||||
load_more_products: "Load More Products"
|
||||
load_all_products: "Load All Products"
|
||||
select_all_products: "Select All %{total_number_of_products}Products"
|
||||
products_loaded: "%{num_of_products_loaded}of %{total_number_of_products} Products Loaded"
|
||||
loading_products: "Loading Products"
|
||||
tag_rules:
|
||||
shipping_method_tagged_top: "Shipping methods tagged"
|
||||
shipping_method_tagged_bottom: "are:"
|
||||
@@ -2688,7 +2686,7 @@ en_CA:
|
||||
city: "City"
|
||||
zip: "Postal Code"
|
||||
country: "Country"
|
||||
state: "State"
|
||||
state: "Province"
|
||||
phone: "Phone"
|
||||
update: "Update"
|
||||
use_billing_address: "Use Billing Address"
|
||||
@@ -2709,7 +2707,6 @@ en_CA:
|
||||
allow_ssl_in_development_and_test: "Allow SSL to be used when in development and test modes"
|
||||
allow_ssl_in_production: "Allow SSL to be used in production mode"
|
||||
allow_ssl_in_staging: "Allow SSL to be used in staging mode"
|
||||
check_for_spree_alerts: "Check for Spree alerts"
|
||||
currency_decimal_mark: "Currency decimal mark"
|
||||
currency_settings: "Currency Settings"
|
||||
currency_symbol_position: Put "currency symbol before or after dollar amount?"
|
||||
@@ -2912,6 +2909,7 @@ en_CA:
|
||||
capture: "Capture"
|
||||
ship: "Ship"
|
||||
edit: "Edit"
|
||||
order_not_updated: "The order could not be updated"
|
||||
note: "Note"
|
||||
first: "First"
|
||||
last: "Last"
|
||||
|
||||
@@ -2,6 +2,8 @@ en_DE:
|
||||
language_name: "English"
|
||||
activerecord:
|
||||
attributes:
|
||||
enterprise_fee:
|
||||
fee_type: Fee Type
|
||||
spree/order:
|
||||
payment_state: Payment State
|
||||
shipment_state: Shipment State
|
||||
@@ -841,7 +843,6 @@ en_DE:
|
||||
cancel: "Cancel"
|
||||
choose_products_from: "Choose Products From:"
|
||||
incoming:
|
||||
previous: "Previous"
|
||||
save: "Save"
|
||||
next: "Next"
|
||||
cancel: "Cancel"
|
||||
@@ -972,9 +973,6 @@ en_DE:
|
||||
name: Customers
|
||||
products_and_inventory:
|
||||
name: Products & Inventory
|
||||
sales_total:
|
||||
name: Sales Total
|
||||
description: Sales Total For All Orders
|
||||
users_and_enterprises:
|
||||
name: Users & Enterprises
|
||||
description: Enterprise Ownership & Status
|
||||
@@ -1113,15 +1111,6 @@ en_DE:
|
||||
selling_on_ofn: "Interested in getting on the Open Food Network?"
|
||||
register: "Register here"
|
||||
footer:
|
||||
footer_global_headline: "OFN Global"
|
||||
footer_global_home: "Home"
|
||||
footer_global_news: "News"
|
||||
footer_global_about: "About"
|
||||
footer_global_contact: "Contact"
|
||||
footer_sites_headline: "OFN Sites"
|
||||
footer_sites_developer: "Developer"
|
||||
footer_sites_community: "Community"
|
||||
footer_sites_userguide: "User Guide"
|
||||
footer_secure: "Secure and trusted."
|
||||
footer_secure_text: "Open Food Network uses SSL encryption (2048 bit RSA) everywhere to keep your shopping and payment information private. Our servers do not store your credit card details and payments are processed by PCI-compliant services."
|
||||
footer_contact_headline: "Keep in touch"
|
||||
@@ -2693,7 +2682,6 @@ en_DE:
|
||||
allow_ssl_in_development_and_test: "Allow SSL to be used when in development and test modes"
|
||||
allow_ssl_in_production: "Allow SSL to be used in production mode"
|
||||
allow_ssl_in_staging: "Allow SSL to be used in staging mode"
|
||||
check_for_spree_alerts: "Check for Spree alerts"
|
||||
currency_decimal_mark: "Currency decimal mark"
|
||||
currency_settings: "Currency Settings"
|
||||
currency_symbol_position: Put "currency symbol before or after dollar amount?"
|
||||
|
||||
@@ -2,6 +2,8 @@ en_FR:
|
||||
language_name: "English"
|
||||
activerecord:
|
||||
attributes:
|
||||
enterprise_fee:
|
||||
fee_type: Fee Type
|
||||
spree/order:
|
||||
payment_state: Payment State
|
||||
shipment_state: Shipment State
|
||||
@@ -48,6 +50,8 @@ en_FR:
|
||||
shipping_method_ids: "Shipping Methods"
|
||||
payment_method_ids: "Payment Methods"
|
||||
errors:
|
||||
messages:
|
||||
inclusion: "is not included in the list"
|
||||
models:
|
||||
subscription_validator:
|
||||
attributes:
|
||||
@@ -848,7 +852,6 @@ en_FR:
|
||||
save_and_back_to_list: "Save and Back to List"
|
||||
choose_products_from: "Choose Products From:"
|
||||
incoming:
|
||||
previous: "Previous"
|
||||
save: "Save"
|
||||
save_and_next: "Save and Next"
|
||||
next: "Next"
|
||||
@@ -987,9 +990,6 @@ en_FR:
|
||||
name: Customers
|
||||
products_and_inventory:
|
||||
name: Products & Inventory
|
||||
sales_total:
|
||||
name: Sales Total
|
||||
description: Sales Total For All Orders
|
||||
users_and_enterprises:
|
||||
name: Users & Enterprises
|
||||
description: Enterprise Ownership & Status
|
||||
@@ -1104,6 +1104,8 @@ en_FR:
|
||||
destroy_attachment_does_not_exist: "Logo does not exist"
|
||||
enterprise_promo_image:
|
||||
destroy_attachment_does_not_exist: "Promo image does not exist"
|
||||
orders:
|
||||
failed_to_update: "Failed to update order"
|
||||
checkout:
|
||||
already_ordered:
|
||||
cart: "cart"
|
||||
@@ -1128,15 +1130,6 @@ en_FR:
|
||||
selling_on_ofn: "Interested in getting on the Open Food Network?"
|
||||
register: "Register here"
|
||||
footer:
|
||||
footer_global_headline: "OFN Global"
|
||||
footer_global_home: "Home"
|
||||
footer_global_news: "News"
|
||||
footer_global_about: "About"
|
||||
footer_global_contact: "Contact"
|
||||
footer_sites_headline: "OFN Sites"
|
||||
footer_sites_developer: "Developer"
|
||||
footer_sites_community: "Community"
|
||||
footer_sites_userguide: "User Guide"
|
||||
footer_secure: "Secure and trusted."
|
||||
footer_secure_text: "Open Food Network uses SSL encryption (2048 bit RSA) everywhere to keep your shopping and payment information private. Our servers do not store your credit card details and payments are processed by PCI-compliant services."
|
||||
footer_contact_headline: "Keep in touch"
|
||||
@@ -2426,6 +2419,12 @@ en_FR:
|
||||
severity: Severity
|
||||
description: Description
|
||||
resolve: Resolve
|
||||
exchange_products:
|
||||
load_more_products: "Load More Products"
|
||||
load_all_products: "Load All Products"
|
||||
select_all_products: "Select All %{total_number_of_products} Products"
|
||||
products_loaded: "%{num_of_products_loaded}of %{total_number_of_products} Products Loaded"
|
||||
loading_products: "Loading Products"
|
||||
tag_rules:
|
||||
shipping_method_tagged_top: "Shipping methods tagged"
|
||||
shipping_method_tagged_bottom: "are:"
|
||||
@@ -2709,7 +2708,6 @@ en_FR:
|
||||
allow_ssl_in_development_and_test: "Allow SSL to be used when in development and test modes"
|
||||
allow_ssl_in_production: "Allow SSL to be used in production mode"
|
||||
allow_ssl_in_staging: "Allow SSL to be used in staging mode"
|
||||
check_for_spree_alerts: "Check for Spree alerts"
|
||||
currency_decimal_mark: "Currency decimal mark"
|
||||
currency_settings: "Currency Settings"
|
||||
currency_symbol_position: Put "currency symbol before or after dollar amount?"
|
||||
@@ -2912,6 +2910,7 @@ en_FR:
|
||||
capture: "Capture"
|
||||
ship: "Ship"
|
||||
edit: "Edit"
|
||||
order_not_updated: "The order could not be updated"
|
||||
note: "Note"
|
||||
first: "First"
|
||||
last: "Last"
|
||||
|
||||
@@ -2,6 +2,8 @@ en_GB:
|
||||
language_name: "English"
|
||||
activerecord:
|
||||
attributes:
|
||||
enterprise_fee:
|
||||
fee_type: Fee Type
|
||||
spree/order:
|
||||
payment_state: Payment State
|
||||
shipment_state: Shipment State
|
||||
@@ -48,6 +50,8 @@ en_GB:
|
||||
shipping_method_ids: "Shipping Methods"
|
||||
payment_method_ids: "Payment Methods"
|
||||
errors:
|
||||
messages:
|
||||
inclusion: "is not included in the list"
|
||||
models:
|
||||
subscription_validator:
|
||||
attributes:
|
||||
@@ -848,7 +852,6 @@ en_GB:
|
||||
save_and_back_to_list: "Save and Back to List"
|
||||
choose_products_from: "Choose Products From:"
|
||||
incoming:
|
||||
previous: "Previous"
|
||||
save: "Save"
|
||||
save_and_next: "Save and Next"
|
||||
next: "Next"
|
||||
@@ -987,9 +990,6 @@ en_GB:
|
||||
name: Customers
|
||||
products_and_inventory:
|
||||
name: Products & Inventory
|
||||
sales_total:
|
||||
name: Sales Total
|
||||
description: Sales Total For All Orders
|
||||
users_and_enterprises:
|
||||
name: Users & Enterprises
|
||||
description: Enterprise Ownership & Status
|
||||
@@ -1128,15 +1128,6 @@ en_GB:
|
||||
selling_on_ofn: "Interested in selling through the Open Food Network?"
|
||||
register: "Register here"
|
||||
footer:
|
||||
footer_global_headline: "OFN Global"
|
||||
footer_global_home: "Home"
|
||||
footer_global_news: "News"
|
||||
footer_global_about: "About"
|
||||
footer_global_contact: "Contact"
|
||||
footer_sites_headline: "OFN Sites"
|
||||
footer_sites_developer: "Developer"
|
||||
footer_sites_community: "Community"
|
||||
footer_sites_userguide: "User Guide"
|
||||
footer_secure: "Secure and trusted."
|
||||
footer_secure_text: "Open Food Network uses SSL encryption (2048 bit RSA) everywhere to keep your shopping and payment information private. Our servers do not store your credit card details and payments are processed by PCI-compliant services."
|
||||
footer_contact_headline: "Keep in touch"
|
||||
@@ -1512,7 +1503,7 @@ en_GB:
|
||||
hubs_filter_type: "Type"
|
||||
hubs_filter_delivery: "Delivery"
|
||||
hubs_filter_property: "Property"
|
||||
hubs_matches: "Did you mean?"
|
||||
hubs_matches: "Showing results for"
|
||||
hubs_intro: Shop in your local area
|
||||
hubs_distance: Closest to
|
||||
hubs_distance_filter: "Show me shops near %{location}"
|
||||
@@ -2432,6 +2423,12 @@ en_GB:
|
||||
severity: Severity
|
||||
description: Description
|
||||
resolve: Resolve
|
||||
exchange_products:
|
||||
load_more_products: "Load More Products"
|
||||
load_all_products: "Load All Products"
|
||||
select_all_products: "Select All %{total_number_of_products} Products"
|
||||
products_loaded: "%{num_of_products_loaded} of %{total_number_of_products} Products Loaded"
|
||||
loading_products: "Loading Products"
|
||||
tag_rules:
|
||||
shipping_method_tagged_top: "Shipping methods tagged"
|
||||
shipping_method_tagged_bottom: "are:"
|
||||
@@ -2514,6 +2511,7 @@ en_GB:
|
||||
customer_placeholder: "customer@example.org"
|
||||
valid_email_error: "Please enter a valid email address"
|
||||
subscriptions:
|
||||
error_saving: "Error saving subscription"
|
||||
new:
|
||||
please_select_a_shop: "Please select a shop"
|
||||
insufficient_stock: "Insufficient stock available, only %{on_hand} remaining"
|
||||
@@ -2714,7 +2712,6 @@ en_GB:
|
||||
allow_ssl_in_development_and_test: "Allow SSL to be used when in development and test modes"
|
||||
allow_ssl_in_production: "Allow SSL to be used in production mode"
|
||||
allow_ssl_in_staging: "Allow SSL to be used in staging mode"
|
||||
check_for_spree_alerts: "Check for Spree alerts"
|
||||
currency_decimal_mark: "Currency decimal mark"
|
||||
currency_settings: "Currency Settings"
|
||||
currency_symbol_position: Put "currency symbol before or after pound amount?"
|
||||
|
||||
@@ -2,6 +2,8 @@ en_NZ:
|
||||
language_name: "English"
|
||||
activerecord:
|
||||
attributes:
|
||||
enterprise_fee:
|
||||
fee_type: Fee Type
|
||||
spree/order:
|
||||
payment_state: Payment State
|
||||
shipment_state: Shipment State
|
||||
@@ -48,6 +50,8 @@ en_NZ:
|
||||
shipping_method_ids: "Shipping Methods"
|
||||
payment_method_ids: "Payment Methods"
|
||||
errors:
|
||||
messages:
|
||||
inclusion: "is not included in the list"
|
||||
models:
|
||||
subscription_validator:
|
||||
attributes:
|
||||
@@ -848,7 +852,6 @@ en_NZ:
|
||||
save_and_back_to_list: "Save and Back to List"
|
||||
choose_products_from: "Choose Products From:"
|
||||
incoming:
|
||||
previous: "Previous"
|
||||
save: "Save"
|
||||
save_and_next: "Save and Next"
|
||||
next: "Next"
|
||||
@@ -987,9 +990,6 @@ en_NZ:
|
||||
name: Customers
|
||||
products_and_inventory:
|
||||
name: Products & Inventory
|
||||
sales_total:
|
||||
name: Sales Total
|
||||
description: Sales Total For All Orders
|
||||
users_and_enterprises:
|
||||
name: Users & Enterprises
|
||||
description: Enterprise Ownership & Status
|
||||
@@ -1128,15 +1128,6 @@ en_NZ:
|
||||
selling_on_ofn: "Interested in getting on the Open Food Network?"
|
||||
register: "Register here"
|
||||
footer:
|
||||
footer_global_headline: "OFN Global"
|
||||
footer_global_home: "Home"
|
||||
footer_global_news: "News"
|
||||
footer_global_about: "About"
|
||||
footer_global_contact: "Contact"
|
||||
footer_sites_headline: "OFN Sites"
|
||||
footer_sites_developer: "Developer"
|
||||
footer_sites_community: "Community"
|
||||
footer_sites_userguide: "User Guide"
|
||||
footer_secure: "Secure and trusted."
|
||||
footer_secure_text: "Open Food Network uses SSL encryption (2048 bit RSA) everywhere to keep your shopping and payment information private. Our servers do not store your credit card details and payments are processed by PCI-compliant services."
|
||||
footer_contact_headline: "Keep in touch"
|
||||
@@ -2426,6 +2417,12 @@ en_NZ:
|
||||
severity: Severity
|
||||
description: Description
|
||||
resolve: Resolve
|
||||
exchange_products:
|
||||
load_more_products: "Load More Products"
|
||||
load_all_products: "Load All Products"
|
||||
select_all_products: "Select All %{total_number_of_products} Products"
|
||||
products_loaded: "%{num_of_products_loaded} of %{total_number_of_products} Products Loaded"
|
||||
loading_products: "Loading Products"
|
||||
tag_rules:
|
||||
shipping_method_tagged_top: "Shipping methods tagged"
|
||||
shipping_method_tagged_bottom: "are:"
|
||||
@@ -2508,6 +2505,7 @@ en_NZ:
|
||||
customer_placeholder: "customer@example.org"
|
||||
valid_email_error: "Please enter a valid email address"
|
||||
subscriptions:
|
||||
error_saving: "Error saving subscription"
|
||||
new:
|
||||
please_select_a_shop: "Please select a shop"
|
||||
insufficient_stock: "Insufficient stock available, only %{on_hand} remaining"
|
||||
@@ -2708,7 +2706,6 @@ en_NZ:
|
||||
allow_ssl_in_development_and_test: "Allow SSL to be used when in development and test modes"
|
||||
allow_ssl_in_production: "Allow SSL to be used in production mode"
|
||||
allow_ssl_in_staging: "Allow SSL to be used in staging mode"
|
||||
check_for_spree_alerts: "Check for Spree alerts"
|
||||
currency_decimal_mark: "Currency decimal mark"
|
||||
currency_settings: "Currency Settings"
|
||||
currency_symbol_position: Put "currency symbol before or after dollar amount?"
|
||||
|
||||
@@ -2,6 +2,8 @@ en_US:
|
||||
language_name: "English"
|
||||
activerecord:
|
||||
attributes:
|
||||
enterprise_fee:
|
||||
fee_type: Fee Type
|
||||
spree/order:
|
||||
payment_state: Payment State
|
||||
shipment_state: Shipment State
|
||||
@@ -838,7 +840,6 @@ en_US:
|
||||
cancel: "Cancel"
|
||||
choose_products_from: "Choose Products From:"
|
||||
incoming:
|
||||
previous: "Previous"
|
||||
save: "Save"
|
||||
next: "Next"
|
||||
cancel: "Cancel"
|
||||
@@ -969,9 +970,6 @@ en_US:
|
||||
name: Customers
|
||||
products_and_inventory:
|
||||
name: Products & Inventory
|
||||
sales_total:
|
||||
name: Sales Total
|
||||
description: Sales Total For All Orders
|
||||
users_and_enterprises:
|
||||
name: Users & Enterprises
|
||||
description: Enterprise Ownership & Status
|
||||
@@ -1110,15 +1108,6 @@ en_US:
|
||||
selling_on_ofn: "Interested in selling through the Open Food Network?"
|
||||
register: "Register here"
|
||||
footer:
|
||||
footer_global_headline: "OFN Global"
|
||||
footer_global_home: "Home"
|
||||
footer_global_news: "News"
|
||||
footer_global_about: "About"
|
||||
footer_global_contact: "Contact"
|
||||
footer_sites_headline: "OFN Sites"
|
||||
footer_sites_developer: "Developer"
|
||||
footer_sites_community: "Community"
|
||||
footer_sites_userguide: "User Guide"
|
||||
footer_secure: "Secure and trusted."
|
||||
footer_secure_text: "Open Food Network uses SSL encryption (2048 bit RSA) everywhere to keep your shopping and payment information private. Our servers do not store your credit card details and payments are processed by PCI-compliant services."
|
||||
footer_contact_headline: "Keep in touch"
|
||||
@@ -2690,7 +2679,6 @@ en_US:
|
||||
allow_ssl_in_development_and_test: "Allow SSL to be used when in development and test modes"
|
||||
allow_ssl_in_production: "Allow SSL to be used in production mode"
|
||||
allow_ssl_in_staging: "Allow SSL to be used in staging mode"
|
||||
check_for_spree_alerts: "Check for Spree alerts"
|
||||
currency_decimal_mark: "Currency decimal mark"
|
||||
currency_settings: "Currency Settings"
|
||||
currency_symbol_position: Put "currency symbol before or after dollar amount?"
|
||||
|
||||
@@ -2,6 +2,8 @@ en_ZA:
|
||||
language_name: "English"
|
||||
activerecord:
|
||||
attributes:
|
||||
enterprise_fee:
|
||||
fee_type: Fee Type
|
||||
spree/order:
|
||||
payment_state: Payment State
|
||||
shipment_state: Shipment State
|
||||
@@ -837,7 +839,6 @@ en_ZA:
|
||||
cancel: "Cancel"
|
||||
choose_products_from: "Choose Products From:"
|
||||
incoming:
|
||||
previous: "Previous"
|
||||
save: "Save"
|
||||
next: "Next"
|
||||
cancel: "Cancel"
|
||||
@@ -968,9 +969,6 @@ en_ZA:
|
||||
name: Customers
|
||||
products_and_inventory:
|
||||
name: Products & Inventory
|
||||
sales_total:
|
||||
name: Sales Total
|
||||
description: Sales Total For All Orders
|
||||
users_and_enterprises:
|
||||
name: Users & Enterprises
|
||||
description: Enterprise Ownership & Status
|
||||
@@ -1109,15 +1107,6 @@ en_ZA:
|
||||
selling_on_ofn: "Interested in selling through the Open Food Network?"
|
||||
register: "Register here"
|
||||
footer:
|
||||
footer_global_headline: "OFN Global"
|
||||
footer_global_home: "Home"
|
||||
footer_global_news: "News"
|
||||
footer_global_about: "About"
|
||||
footer_global_contact: "Contact"
|
||||
footer_sites_headline: "OFN Sites"
|
||||
footer_sites_developer: "Developer"
|
||||
footer_sites_community: "Community"
|
||||
footer_sites_userguide: "User Guide"
|
||||
footer_secure: "Secure and trusted."
|
||||
footer_secure_text: "Open Food Network uses SSL encryption (2048 bit RSA) everywhere to keep your shopping and payment information private. Our servers do not store your credit card details and payments are processed by PCI-compliant services."
|
||||
footer_contact_headline: "Keep in touch"
|
||||
@@ -2694,7 +2683,6 @@ en_ZA:
|
||||
allow_ssl_in_development_and_test: "Allow SSL to be used when in development and test modes"
|
||||
allow_ssl_in_production: "Allow SSL to be used in production mode"
|
||||
allow_ssl_in_staging: "Allow SSL to be used in staging mode"
|
||||
check_for_spree_alerts: "Check for Spree alerts"
|
||||
currency_decimal_mark: "Currency decimal mark"
|
||||
currency_settings: "Currency Settings"
|
||||
currency_symbol_position: Put "currency symbol before or after Rand amount?"
|
||||
|
||||
@@ -2,6 +2,8 @@ es:
|
||||
language_name: "Castellano"
|
||||
activerecord:
|
||||
attributes:
|
||||
enterprise_fee:
|
||||
fee_type: Tipo de Comisión
|
||||
spree/order:
|
||||
payment_state: Estado del pago
|
||||
shipment_state: Estado del envío
|
||||
@@ -843,7 +845,6 @@ es:
|
||||
cancel: "Cancelar"
|
||||
choose_products_from: "Escoger Productos desde:"
|
||||
incoming:
|
||||
previous: "Anterior"
|
||||
save: "Guardar"
|
||||
next: "Siguiente"
|
||||
cancel: "Cancelar"
|
||||
@@ -974,9 +975,6 @@ es:
|
||||
name: Consumidoras
|
||||
products_and_inventory:
|
||||
name: Productos & Inventario
|
||||
sales_total:
|
||||
name: Total Ventas
|
||||
description: Total de ventas para todas los pedidos
|
||||
users_and_enterprises:
|
||||
name: Usuarias y Organizaciones
|
||||
description: Propiedad y Estado de la Organización
|
||||
@@ -1115,15 +1113,6 @@ es:
|
||||
selling_on_ofn: "¿Estás interesada en entrar en Open Food Network?"
|
||||
register: "Regístrate aquí"
|
||||
footer:
|
||||
footer_global_headline: "OFN Global"
|
||||
footer_global_home: "Inicio"
|
||||
footer_global_news: "Noticas"
|
||||
footer_global_about: "Acerca de"
|
||||
footer_global_contact: "Contacto"
|
||||
footer_sites_headline: "Sitios OFN"
|
||||
footer_sites_developer: "Desarrollador"
|
||||
footer_sites_community: "Comunidad"
|
||||
footer_sites_userguide: "Manual de Usuario"
|
||||
footer_secure: "Seguro y de confianza."
|
||||
footer_secure_text: "Open Food Network usa cifrado SSL (RSA de 2048 bit) en toda su plataforma para mantener privada la información de compras y pagos. Nuestros servidores no almacenan los detalles de tarjetas de créditos y los pagos son procesados por servicios que cumplen con PCI."
|
||||
footer_contact_headline: "Mantenerse en contacto"
|
||||
@@ -2699,7 +2688,6 @@ es:
|
||||
allow_ssl_in_development_and_test: "Permitir el uso de SSL en los modos de desarrollo y prueba"
|
||||
allow_ssl_in_production: "Permitir que SSL se utilice en modo de producción"
|
||||
allow_ssl_in_staging: "Permitir que SSL se utilice en modo de staging"
|
||||
check_for_spree_alerts: "Compruebe si hay alertas de Spree"
|
||||
currency_decimal_mark: "Marca decimal de la moneda"
|
||||
currency_settings: "Ajustes de moneda"
|
||||
currency_symbol_position: ¿Poner "símbolo de moneda antes o después de la cantidad?"
|
||||
|
||||
@@ -2,6 +2,8 @@ fr:
|
||||
language_name: "Français"
|
||||
activerecord:
|
||||
attributes:
|
||||
enterprise_fee:
|
||||
fee_type: Type de marge
|
||||
spree/order:
|
||||
payment_state: Statut du paiement
|
||||
shipment_state: Statut livraison
|
||||
@@ -48,6 +50,8 @@ fr:
|
||||
shipping_method_ids: "Méthodes de livraison"
|
||||
payment_method_ids: "Méthodes de paiement"
|
||||
errors:
|
||||
messages:
|
||||
inclusion: "n'est pas inclus dans la liste"
|
||||
models:
|
||||
subscription_validator:
|
||||
attributes:
|
||||
@@ -849,7 +853,6 @@ fr:
|
||||
save_and_back_to_list: "Sauvegarder et revenir à la liste"
|
||||
choose_products_from: "Choisir produits depuis :"
|
||||
incoming:
|
||||
previous: "Précédent"
|
||||
save: "Sauvegarder"
|
||||
save_and_next: "Sauvegarder et suivant"
|
||||
next: "Suivant"
|
||||
@@ -988,9 +991,6 @@ fr:
|
||||
name: Acheteurs
|
||||
products_and_inventory:
|
||||
name: Listings produits
|
||||
sales_total:
|
||||
name: Total des Ventes
|
||||
description: Total des Ventes pour toutes les Commandes
|
||||
users_and_enterprises:
|
||||
name: Gestionnaires & Entreprises
|
||||
description: Gestionnaires de l'Entreprise & Droits
|
||||
@@ -1105,6 +1105,8 @@ fr:
|
||||
destroy_attachment_does_not_exist: "Aucun logo trouvé :-("
|
||||
enterprise_promo_image:
|
||||
destroy_attachment_does_not_exist: "Aucune bannière trouvée :-("
|
||||
orders:
|
||||
failed_to_update: "La mise à jour de la commande échoué"
|
||||
checkout:
|
||||
already_ordered:
|
||||
cart: "panier"
|
||||
@@ -1129,15 +1131,6 @@ fr:
|
||||
selling_on_ofn: "Vous souhaitez proposer vos produits sur Open Food France?"
|
||||
register: "Démarrez ici"
|
||||
footer:
|
||||
footer_global_headline: "OFN Global"
|
||||
footer_global_home: "Accueil"
|
||||
footer_global_news: "News"
|
||||
footer_global_about: "A propos"
|
||||
footer_global_contact: "Contact"
|
||||
footer_sites_headline: "Sites OFN"
|
||||
footer_sites_developer: "Developpeur"
|
||||
footer_sites_community: "Communauté"
|
||||
footer_sites_userguide: "Guide utilisateur"
|
||||
footer_secure: "Fiable et sécurisé."
|
||||
footer_secure_text: "Open Food France utilise un certificat type SSL (2048 bit RSA) pour garantir la confidentialité de votre commandes et données bancaires. Nos serveurs ne conservent pas vos données bancaires et les paiements sont effectués conformément aux normes de sécurité PCI."
|
||||
footer_contact_headline: "Restez en contact"
|
||||
@@ -2454,6 +2447,12 @@ fr:
|
||||
severity: Rigueur
|
||||
description: Description
|
||||
resolve: Résoudre
|
||||
exchange_products:
|
||||
load_more_products: "Voir plus de produits"
|
||||
load_all_products: "Voir tous les produits"
|
||||
select_all_products: "Sélectionner tous les %{total_number_of_products}produits"
|
||||
products_loaded: "%{num_of_products_loaded}sur %{total_number_of_products}produits affichés"
|
||||
loading_products: "Produits en cours de chargement"
|
||||
tag_rules:
|
||||
shipping_method_tagged_top: "Les méthodes de livraison taguées"
|
||||
shipping_method_tagged_bottom: "sont:"
|
||||
@@ -2738,7 +2737,6 @@ fr:
|
||||
allow_ssl_in_development_and_test: "Autoriser l'utilisation SSL dans les environnements de développement et de test"
|
||||
allow_ssl_in_production: "Autoriser l'utilisation SSL dans l'environnement de production"
|
||||
allow_ssl_in_staging: "Autoriser l'utilisation SSL dans l'environnement de staging"
|
||||
check_for_spree_alerts: "Vérifier les alertes Spree"
|
||||
currency_decimal_mark: "Symbole du séparateur de décimales"
|
||||
currency_settings: "Paramètres devise"
|
||||
currency_symbol_position: Mettre le symbole de la devise avant ou après le montant ?
|
||||
@@ -2941,6 +2939,7 @@ fr:
|
||||
capture: "Payée"
|
||||
ship: "Expédier"
|
||||
edit: "Modifier"
|
||||
order_not_updated: "La commande n'a pas pu être mise à jour"
|
||||
note: "Note"
|
||||
first: "Début"
|
||||
last: "Fin"
|
||||
|
||||
@@ -2,6 +2,8 @@ fr_BE:
|
||||
language_name: "Français"
|
||||
activerecord:
|
||||
attributes:
|
||||
enterprise_fee:
|
||||
fee_type: Type de marge
|
||||
spree/order:
|
||||
payment_state: Statut du paiement
|
||||
shipment_state: Statut livraison
|
||||
@@ -12,9 +14,9 @@ fr_BE:
|
||||
spree/payment:
|
||||
amount: Montant
|
||||
spree/product:
|
||||
primary_taxon: "Catégorie Produit"
|
||||
primary_taxon: "Catégorie de Produit"
|
||||
supplier: "Fournisseur"
|
||||
shipping_category_id: "Catégorie d'expédition"
|
||||
shipping_category_id: "Catégorie de livraison"
|
||||
variant_unit: "Unité"
|
||||
variant_unit_name: "Nom de la variante"
|
||||
order_cycle:
|
||||
@@ -90,10 +92,11 @@ fr_BE:
|
||||
unconfirmed: "Veuillez valider le lien envoyé par email pour pouvoir continuer."
|
||||
already_registered: "Cet email est déjà associé à un utilisateur et a déjà été validé. Veuillez vous connecter pour continuer, ou utiliser un autre email."
|
||||
success:
|
||||
logged_in_succesfully: "Connecté avec succès"
|
||||
logged_in_succesfully: "Connecté(e) avec succès"
|
||||
user_passwords:
|
||||
spree_user:
|
||||
updated_not_active: "Votre mot de passe a bien été réinitialisé, mais votre email n'a pas encore été confirmé."
|
||||
updated: "Votre mot de passe a été changé avec succès. Vous êtes à présent connecté."
|
||||
send_instructions: "Un email a été envoyé avec des instructions pour confirmer votre adresse email. Vérifiez votre boite mail!"
|
||||
models:
|
||||
order_cycle:
|
||||
@@ -113,7 +116,9 @@ fr_BE:
|
||||
email_welcome: "Bienvenue"
|
||||
email_registered: "fait maintenant partie de"
|
||||
email_userguide_html: "Le Guide Utilisateur expliquant comment mettre en place son profil producteur ou son comptoir est accessible ici: %{link}"
|
||||
userguide: "Guide de l'utilisateur Open Food Network"
|
||||
email_admin_html: "Vous pouvez gérer votre compte en vous connectant ici %{link} ou en cliquant sur la roue en haut à droite de la page d'accueil et en sélectionnant Administration."
|
||||
admin_panel: "Panneau de l'administrateur"
|
||||
email_community_html: "Nous avons aussi un forum de discussion en ligne (en anglais) pour échanger avec la communauté sur des questions liées au logiciel OFN et aux défis de la gestion d'un food hub. Nous vous invitons à y participer. Nous sommes en constante évolution et vos contributions à ce forum vont façonner les prochaines étapes. %{link}"
|
||||
join_community: "Rejoindre la communauté"
|
||||
invite_manager:
|
||||
@@ -246,9 +251,10 @@ fr_BE:
|
||||
change_my_password: "Changer mon mot de passe"
|
||||
update_password: "Mise à jour du mot de passe"
|
||||
password_confirmation: confirmation du mot de passe
|
||||
reset_password_token: réinitialisation du mot de passe
|
||||
reset_password_token: Réinitialisation du mot de passe
|
||||
expired: a expiré, veuillez en demander un nouveau
|
||||
back_to_payments_list: "Retour à la liste des paiements"
|
||||
maestro_or_solo_cards: "Cartes Maestro / Solo"
|
||||
on hand: "En stock"
|
||||
ship: "Expédier"
|
||||
actions:
|
||||
@@ -270,7 +276,7 @@ fr_BE:
|
||||
name: Nom
|
||||
on_hand: En stock
|
||||
on_demand: A volonté
|
||||
on_demand?: A volonté?
|
||||
on_demand?: A volonté ?
|
||||
order_cycle: Cycle de vente
|
||||
payment: Paiement
|
||||
payment_method: Méthode de paiement
|
||||
@@ -313,7 +319,7 @@ fr_BE:
|
||||
whats_this: Qu'est-ce que c'est?
|
||||
tag_has_rules: "Règles existantes pour ce tag: %{num}"
|
||||
has_one_rule: "a une règle"
|
||||
has_n_rules: "a %{num} règles"
|
||||
has_n_rules: "a %{num} règle(s)"
|
||||
unsaved_confirm_leave: "Des modifications n'ont pas été sauvegardées et seront perdues si vous quittez la page. Souhaitez-vous quitter la page?"
|
||||
unsaved_changes: "Des modifications n'ont pas été sauvegardées."
|
||||
shopfront_settings:
|
||||
@@ -326,7 +332,7 @@ fr_BE:
|
||||
invoice_settings:
|
||||
edit:
|
||||
title: "Paramètres de facturation"
|
||||
enable_invoices?: "Activer les factures?"
|
||||
enable_invoices?: "Permettre les factures ?"
|
||||
invoice_style2?: "Utiliser le modèle de facture alternatif qui détaille le montant de TVA agrégé par taux et l'information du taux de TVA par produit (pas adapté pour les instances affichant les prix HT)"
|
||||
enable_receipt_printing?: "Afficher les options d'impression de tickets de caisse dans le menu déroulant des commandes?"
|
||||
stripe_connect_settings:
|
||||
@@ -430,8 +436,10 @@ fr_BE:
|
||||
to_order_tip: "Les articles fabriqués sur commande n'ont pas un niveau de stock défini, comme des pains faits à la main."
|
||||
back_to_products_list: "Retour à la liste produits"
|
||||
tabs:
|
||||
product_details: "Détails du produit"
|
||||
group_buy_options: "Options d'achat par lot"
|
||||
images: "Images"
|
||||
variants: "Variantes"
|
||||
product_properties: "Propriétés / labels Produits"
|
||||
product_import:
|
||||
title: Import liste produits
|
||||
@@ -454,6 +462,8 @@ fr_BE:
|
||||
encoding_error: "Veuillez vérifier la langage de votre fichier source et l'enregistrer avec un encodage UTF-8"
|
||||
unexpected_error: "L'import du produit à provoqué une erreur à l'ouverture du fichier: %{error_message}"
|
||||
index:
|
||||
notice: "Remarque"
|
||||
beta_notice: "Cette fonction est encore en phase Beta: vous pouvez rencontrer quelques erreurs pendant que vous l'utilisez. N'hésitez donc pas à contacter notre support."
|
||||
select_file: Sélectionner le fichier (tableur sous format csv) à importer
|
||||
spreadsheet: Tableur csv
|
||||
choose_import_type: Choisir le type d'import
|
||||
@@ -532,6 +542,7 @@ fr_BE:
|
||||
title: Catalogue du magasin
|
||||
description: Utilisez cette page pour gérer le catalogue de votre entreprise. Les détails produits saisis ici remplaceront ceux de la page "Produit" pour votre entreprise uniquement.
|
||||
enable_reset?: Autoriser réinitialisation du stock (retour configurations par défaut)?
|
||||
default_stock: "Stock par défaut"
|
||||
inherit?: Hériter?
|
||||
add: Ajouter
|
||||
hide: Masquer
|
||||
@@ -827,21 +838,32 @@ fr_BE:
|
||||
new:
|
||||
create: "Créer"
|
||||
cancel: "Annuler"
|
||||
back_to_list: "Retour à la liste"
|
||||
edit:
|
||||
advanced_settings: "Paramétrages avancés"
|
||||
save: "Sauvergarder"
|
||||
save_and_next: "Sauver et suivant"
|
||||
next: "Suivant"
|
||||
cancel: "Annuler"
|
||||
back_to_list: "Retour à la liste"
|
||||
save_and_back_to_list: "Sauver et retour à la liste"
|
||||
choose_products_from: "Choisir produits depuis :"
|
||||
incoming:
|
||||
previous: "Précédent"
|
||||
save: "Sauvergarder"
|
||||
save_and_next: "Sauver et suivant"
|
||||
next: "Suivant"
|
||||
cancel: "Annuler"
|
||||
back_to_list: "Retour à la liste."
|
||||
outgoing:
|
||||
previous: "Précédent"
|
||||
save: "Sauvergarder"
|
||||
save_and_back_to_list: "Sauver et retour à la liste"
|
||||
cancel: "Annuler"
|
||||
back_to_list: "Retour à la liste."
|
||||
wizard_progress:
|
||||
edit: "1. Paramètres généraux"
|
||||
incoming: "2. Produits entrants"
|
||||
outgoing: "3. Produits sortants"
|
||||
exchange_form:
|
||||
pickup_time_tip: Quand des commandes liées à ce cycle de vente seront prêtes à être soumises à l'acheteur
|
||||
pickup_instructions_placeholder: "Modalités de retrait/livraison"
|
||||
@@ -965,9 +987,6 @@ fr_BE:
|
||||
name: Acheteurs
|
||||
products_and_inventory:
|
||||
name: Produits et Catalogues
|
||||
sales_total:
|
||||
name: Total des Ventes
|
||||
description: Total des Ventes pour toutes les Commandes
|
||||
users_and_enterprises:
|
||||
name: Managers & Entreprises
|
||||
description: Managers de l'Entreprise & Droits
|
||||
@@ -1046,6 +1065,7 @@ fr_BE:
|
||||
saved: "Enregistré"
|
||||
product_already_in_order: Ce produit a déjà été ajouté à la commande. Veuillez directement modifier la quantité.
|
||||
stock:
|
||||
insufficient_stock: "Stock insuffisant"
|
||||
out_of_stock: "Pas en stock"
|
||||
orders:
|
||||
number: Nombre
|
||||
@@ -1104,15 +1124,6 @@ fr_BE:
|
||||
selling_on_ofn: "Intéressé à participer à Open Food Network?"
|
||||
register: "Démarrez ici"
|
||||
footer:
|
||||
footer_global_headline: "OFN Global"
|
||||
footer_global_home: "Accueil"
|
||||
footer_global_news: "News"
|
||||
footer_global_about: "A propos"
|
||||
footer_global_contact: "Contact"
|
||||
footer_sites_headline: "Sites OFN"
|
||||
footer_sites_developer: "Developpeur"
|
||||
footer_sites_community: "Communauté"
|
||||
footer_sites_userguide: "Guide utilisateur"
|
||||
footer_secure: "Fiable et sécurisé."
|
||||
footer_secure_text: "Open Food Network utilise un certificat type SSL (2048 bit RSA) pour garantir la confidentialité de votre commandes et données bancaires. Nos serveurs ne conservent pas vos données bancaires et les paiements sont effectués conformément aux normes de sécurité PCI."
|
||||
footer_contact_headline: "Restons en contact"
|
||||
@@ -2496,6 +2507,7 @@ fr_BE:
|
||||
customer_placeholder: "acheteur@exemple.org"
|
||||
valid_email_error: "Veuillez entrer un email valide"
|
||||
subscriptions:
|
||||
error_saving: "Erreur pendant la sauvegarde de l'abonnement"
|
||||
new:
|
||||
please_select_a_shop: "Veuillez choisir un comptoir"
|
||||
insufficient_stock: "Stock disponible insuffisant , il ne reste que %{on_hand}"
|
||||
@@ -2695,7 +2707,6 @@ fr_BE:
|
||||
allow_ssl_in_development_and_test: "Autoriser l’utilisation de SSL pendant le développement et les modes test"
|
||||
allow_ssl_in_production: "Autoriser SSL en mode production "
|
||||
allow_ssl_in_staging: "Autoriser SSL quand est employé en mode visible "
|
||||
check_for_spree_alerts: "Attention aux alertes en série "
|
||||
currency_decimal_mark: "Devise à la décimale "
|
||||
currency_settings: "Devise "
|
||||
currency_symbol_position: Mettez "symbole monétaire avant ou après le montant en euros?"
|
||||
@@ -2795,8 +2806,15 @@ fr_BE:
|
||||
minimal_amount: "Montant minimal"
|
||||
normal_amount: "Montant normal"
|
||||
discount_amount: "Montant de la remise"
|
||||
no_images_found: "Pas d'image trouvée"
|
||||
new_image: "Nouvelle image"
|
||||
filename: "Nom de fichier"
|
||||
alt_text: "Texte alternatif"
|
||||
thumbnail: "Miniature"
|
||||
back_to_images_list: "Retour à la liste d'images"
|
||||
email: Email
|
||||
account_updated: "Compte mis à jour!"
|
||||
email_updated: "Le compte sera mis à jour une fois la nouvelle adresse-mail confirmée"
|
||||
my_account: "Mon compte"
|
||||
date: "Date"
|
||||
time: "Heure"
|
||||
@@ -2804,6 +2822,8 @@ fr_BE:
|
||||
inventory: Catalogue boutique
|
||||
zipcode: Code postal
|
||||
weight: Poids (au kg)
|
||||
error_user_destroy_with_orders: "Les utilisateurs avec une commande finalisée ne peuvent pas être supprimés"
|
||||
options: "Options"
|
||||
actions:
|
||||
update: "Mettre à jour"
|
||||
errors:
|
||||
@@ -2835,24 +2855,37 @@ fr_BE:
|
||||
product_properties:
|
||||
index:
|
||||
inherits_properties_checkbox_hint: "Hériter des propriétés de %{supplier} ? (non applicable si information de remplacement déjà saisie)"
|
||||
add_product_properties: "Ajouter des caractéristiques au produit"
|
||||
properties:
|
||||
index:
|
||||
properties: "Labels / propriétés"
|
||||
new_property: "Nouvelle caractéristique"
|
||||
name: "Nom"
|
||||
new:
|
||||
new_property: "Nouvelle caractéristique"
|
||||
edit:
|
||||
editing_property: "Editer la caractéristique"
|
||||
back_to_properties_list: "Retour à la liste des caractéristiques"
|
||||
form:
|
||||
name: "Nom"
|
||||
return_authorizations:
|
||||
index:
|
||||
new_return_authorization: "Nouvelle autorisation de retour"
|
||||
back_to_orders_list: "Retour vers la liste des commandes "
|
||||
rma_number: "Numéro d' Autorisation de Retour de Marchandise"
|
||||
status: "Statut"
|
||||
amount: "Quantité"
|
||||
continue: "Suivant"
|
||||
new:
|
||||
new_return_authorization: "Nouvelle autorisation de retour"
|
||||
back_to_return_authorizations_list: "Retour vers la liste d'autorisation de retour"
|
||||
continue: "Suivant"
|
||||
edit:
|
||||
are_you_sure: "Confirmer?"
|
||||
return_authorization: "Autorisation de retour"
|
||||
form:
|
||||
product: "Produit"
|
||||
quantity_shipped: "Quantité livrée"
|
||||
amount: "Quantité"
|
||||
orders:
|
||||
index:
|
||||
@@ -3044,8 +3077,10 @@ fr_BE:
|
||||
index:
|
||||
sku: "Référence produit"
|
||||
price: "Prix"
|
||||
options: "Options"
|
||||
no_results: "Aucun résultat"
|
||||
option_types: "Option Types "
|
||||
and: "et"
|
||||
form:
|
||||
sku: "Référence produit"
|
||||
price: "Prix"
|
||||
|
||||
@@ -2,6 +2,8 @@ fr_CA:
|
||||
language_name: "Français"
|
||||
activerecord:
|
||||
attributes:
|
||||
enterprise_fee:
|
||||
fee_type: Type de commissions
|
||||
spree/order:
|
||||
payment_state: Statut du paiement
|
||||
shipment_state: Statut de la livraison
|
||||
@@ -48,6 +50,8 @@ fr_CA:
|
||||
shipping_method_ids: "Méthodes de livraison"
|
||||
payment_method_ids: "Méthodes de paiement"
|
||||
errors:
|
||||
messages:
|
||||
inclusion: "n'est pas inclus dans la liste"
|
||||
models:
|
||||
subscription_validator:
|
||||
attributes:
|
||||
@@ -850,7 +854,6 @@ fr_CA:
|
||||
save_and_back_to_list: "Sauvegarder et suivant"
|
||||
choose_products_from: "Choisir produits depuis :"
|
||||
incoming:
|
||||
previous: "Précédent"
|
||||
save: "Enregistrer"
|
||||
save_and_next: "Sauvegarder et suivant"
|
||||
next: "Suivant"
|
||||
@@ -989,9 +992,6 @@ fr_CA:
|
||||
name: Acheteurs
|
||||
products_and_inventory:
|
||||
name: Produits et Catalogues
|
||||
sales_total:
|
||||
name: Total des Ventes
|
||||
description: Total des Ventes pour toutes les Commandes
|
||||
users_and_enterprises:
|
||||
name: Utilisateurs & Entreprises
|
||||
description: Gérance de l'Entreprise & Droits
|
||||
@@ -1129,15 +1129,6 @@ fr_CA:
|
||||
selling_on_ofn: "Vous souhaitez proposer vos produits sur Open Food Network?"
|
||||
register: "Démarrez ici"
|
||||
footer:
|
||||
footer_global_headline: "OFN Global"
|
||||
footer_global_home: "Accueil"
|
||||
footer_global_news: "News"
|
||||
footer_global_about: "A propos"
|
||||
footer_global_contact: "Contact"
|
||||
footer_sites_headline: "Sites OFN"
|
||||
footer_sites_developer: "Developpeur"
|
||||
footer_sites_community: "Communauté"
|
||||
footer_sites_userguide: "Guide utilisateur"
|
||||
footer_secure: "Fiable et sécurisé."
|
||||
footer_secure_text: "Open Food Network utilise un certificat type SSL (2048 bit RSA) pour garantir la confidentialité de votre commandes et données bancaires. Nos serveurs ne conservent pas vos données bancaires et les paiements sont effectués conformément aux normes de sécurité PCI."
|
||||
footer_contact_headline: "Restez en contact"
|
||||
@@ -1198,7 +1189,7 @@ fr_CA:
|
||||
menu_4_title: "Groupes"
|
||||
menu_4_url: "/groups"
|
||||
menu_5_title: "A propos"
|
||||
menu_5_url: "https://about.openfoodnetwork.org.au/"
|
||||
menu_5_url: "https://about.openfoodnetwork.ca"
|
||||
menu_6_title: "Se connecter"
|
||||
menu_6_url: "https://openfoodnetwork.org/au/connect/"
|
||||
menu_7_title: "Apprendre"
|
||||
@@ -2437,6 +2428,12 @@ fr_CA:
|
||||
severity: Gravité
|
||||
description: Description
|
||||
resolve: Résoudre
|
||||
exchange_products:
|
||||
load_more_products: "Voir plus de produits"
|
||||
load_all_products: "Voir tous les produits"
|
||||
select_all_products: "Sélectionner tous les %{total_number_of_products} produits"
|
||||
products_loaded: "%{num_of_products_loaded}sur %{total_number_of_products}produits affichés"
|
||||
loading_products: "Produits en cours de chargement..."
|
||||
tag_rules:
|
||||
shipping_method_tagged_top: "Les méthodes de livraison taggées"
|
||||
shipping_method_tagged_bottom: "sont:"
|
||||
@@ -2721,7 +2718,6 @@ fr_CA:
|
||||
allow_ssl_in_development_and_test: "Autoriser l'utilisation SSL dans les environnements de développement et de test"
|
||||
allow_ssl_in_production: "Autoriser l'utilisation SSL dans l'environnement de production"
|
||||
allow_ssl_in_staging: "Autoriser l'utilisation SSL dans l'environnement de staging"
|
||||
check_for_spree_alerts: "Vérifier les alertes Spree"
|
||||
currency_decimal_mark: "Symbole du séparateur de décimales"
|
||||
currency_settings: "Paramètres devise"
|
||||
currency_symbol_position: Mettre le symbole de la devise avant ou après le montant ?
|
||||
|
||||
@@ -2,6 +2,8 @@ it:
|
||||
language_name: "Italiano"
|
||||
activerecord:
|
||||
attributes:
|
||||
enterprise_fee:
|
||||
fee_type: Tipo di tariffa
|
||||
spree/order:
|
||||
payment_state: Stato del pagamento
|
||||
shipment_state: Stato della spedizione
|
||||
@@ -850,7 +852,6 @@ it:
|
||||
save_and_back_to_list: "Salva e torna alla lista"
|
||||
choose_products_from: "Scegli i prodotti da:"
|
||||
incoming:
|
||||
previous: "Precedente"
|
||||
save: "Salva"
|
||||
save_and_next: "Salva e continua"
|
||||
next: "Prossimo"
|
||||
@@ -989,9 +990,6 @@ it:
|
||||
name: Consumatori
|
||||
products_and_inventory:
|
||||
name: Prodotti e inventario
|
||||
sales_total:
|
||||
name: Totale vendite
|
||||
description: Totale vendite per tutti gli ordini
|
||||
users_and_enterprises:
|
||||
name: Utenti e aziende
|
||||
description: Proprietà e status aziende
|
||||
@@ -1130,15 +1128,6 @@ it:
|
||||
selling_on_ofn: "Interessato ad entrare in Open Food Network?"
|
||||
register: "Registrati qui"
|
||||
footer:
|
||||
footer_global_headline: "OFN Globale"
|
||||
footer_global_home: "Home"
|
||||
footer_global_news: "News"
|
||||
footer_global_about: "About"
|
||||
footer_global_contact: "Contatto"
|
||||
footer_sites_headline: "Siti OFN"
|
||||
footer_sites_developer: "Sviluppatore"
|
||||
footer_sites_community: "Community"
|
||||
footer_sites_userguide: "Guida utente"
|
||||
footer_secure: "Sicuro e affidabile."
|
||||
footer_secure_text: "Open Food Network usa la codifica SSL (2048 bit RSA) ovunque per mantenere private le tue informazioni sulla spesa e i pagamenti. I nostri server non memorizzano i dettagli della tua carta di credito e i pagamenti sono processati da servizi PCI-conformi."
|
||||
footer_contact_headline: "Tieniti in contatto"
|
||||
@@ -2713,7 +2702,6 @@ it:
|
||||
allow_ssl_in_development_and_test: "Consentire l'utilizzo di SSL nelle modalità di sviluppo e test"
|
||||
allow_ssl_in_production: "Consentire l'utilizzo di SSL in modalità produzione"
|
||||
allow_ssl_in_staging: "Consentire l'utilizzo di SSL nella modalità di gestione temporanea"
|
||||
check_for_spree_alerts: "Controlla gli avvisi Spree"
|
||||
currency_decimal_mark: "Valuta decimale"
|
||||
currency_settings: "Impostazioni valuta"
|
||||
currency_symbol_position: Metti "simbolo di valuta prima o dopo l'importo?"
|
||||
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user